feat(desktop): manage ACP adapters and connect local agents
This commit is contained in:
1 parent
ca5153041b
commit
4ed13eb0ad
16 files changed
+1541
-59
No files matched your search
@@ -22,6 +22,8 @@
|
||||
"@edgeever/public-network": "workspace:*",
|
||||
"croner": "^10.0.1",
|
||||
"electron-updater": "^6.6.2",
|
||||
"fflate": "0.8.3",
|
||||
"npm": "11.6.2",
|
||||
"zod": "^4.6.5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import { createHash } from "node:crypto";
|
||||
import { createReadStream, createWriteStream, existsSync, readFileSync } from "node:fs";
|
||||
import { chmod, mkdir, open, readdir, rename, rm } from "node:fs/promises";
|
||||
import { once } from "node:events";
|
||||
import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import { finished } from "node:stream/promises";
|
||||
import { Readable } from "node:stream";
|
||||
import { Unzip, UnzipInflate } from "fflate";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const npmCli = path.join(path.dirname(require.resolve("npm")), "bin", "npm-cli.js");
|
||||
const REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json";
|
||||
const MAX_ARCHIVE_BYTES = 300 * 1024 * 1024;
|
||||
const MAX_EXTRACTED_BYTES = 1024 * 1024 * 1024;
|
||||
const VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
||||
const SUPPORTED_MAJOR = { codex: 2, antigravity: 1 };
|
||||
|
||||
const platformTarget = (platform, arch) => {
|
||||
const system = { darwin: "darwin", linux: "linux", win32: "windows" }[platform];
|
||||
const cpu = { arm64: "aarch64", x64: "x86_64" }[arch];
|
||||
return system && cpu ? `${system}-${cpu}` : null;
|
||||
};
|
||||
|
||||
const compareVersions = (left, right) => {
|
||||
const a = left.split(".").map(Number);
|
||||
const b = right.split(".").map(Number);
|
||||
for (let i = 0; i < 3; i += 1) if (a[i] !== b[i]) return a[i] - b[i];
|
||||
return 0;
|
||||
};
|
||||
|
||||
const commandFile = (root, id, version, platform) => id === "codex"
|
||||
? path.join(root, id, version, "node_modules", "@agentclientprotocol", "codex-acp", "dist", "index.js")
|
||||
: path.join(root, id, version, platform === "win32" ? "agy_acp_server.exe" : "agy_acp_server.par");
|
||||
|
||||
const antigravityArgs = (platform) => platform === "linux" ? ["--uid="] : [];
|
||||
|
||||
export const managedAdapterCommand = (root, id, version, { platform = process.platform, executablePath = process.execPath } = {}) => {
|
||||
if (!VERSION_PATTERN.test(version) || (id !== "codex" && id !== "antigravity")) return null;
|
||||
const file = commandFile(root, id, version, platform);
|
||||
if (!existsSync(file)) return null;
|
||||
return id === "codex"
|
||||
? { command: executablePath, args: [file], env: { ELECTRON_RUN_AS_NODE: "1" } }
|
||||
: { command: file, args: antigravityArgs(platform) };
|
||||
};
|
||||
|
||||
const readRegistry = async (fetchImpl) => {
|
||||
const response = await fetchImpl(REGISTRY_URL, { signal: AbortSignal.timeout(15_000), redirect: "error" });
|
||||
if (!response.ok) throw new Error("registry_unavailable");
|
||||
const contentLength = Number(response.headers.get("content-length") || 0);
|
||||
if (contentLength > 1024 * 1024) throw new Error("registry_too_large");
|
||||
const raw = await response.text();
|
||||
if (raw.length > 1024 * 1024) throw new Error("registry_too_large");
|
||||
const agents = JSON.parse(raw).agents;
|
||||
if (!Array.isArray(agents)) throw new Error("invalid_registry");
|
||||
return agents;
|
||||
};
|
||||
|
||||
export const selectAdapterRelease = (agents, id, { platform = process.platform, arch = process.arch } = {}) => {
|
||||
const entry = agents.find((agent) => agent?.id === (id === "codex" ? "codex-acp" : "antigravity-acp"));
|
||||
if (!entry || !VERSION_PATTERN.test(entry.version)) throw new Error("unsupported_release");
|
||||
if (Number(entry.version.split(".")[0]) !== SUPPORTED_MAJOR[id]) throw new Error("unsupported_release");
|
||||
if (id === "codex") {
|
||||
const packageName = entry.distribution?.npx?.package;
|
||||
if (packageName !== `@agentclientprotocol/codex-acp@${entry.version}`) throw new Error("unsupported_release");
|
||||
return { id, version: entry.version, kind: "npm", packageName };
|
||||
}
|
||||
const target = platformTarget(platform, arch);
|
||||
const binary = target && entry.distribution?.binary?.[target];
|
||||
const archive = binary?.archive;
|
||||
if (!archive || !/^https:\/\/dl\.google\.com\/agy-extensions\/releases\/[^?#]+\.zip$/.test(archive)) {
|
||||
throw new Error("unsupported_release");
|
||||
}
|
||||
const expectedCommand = platform === "win32" ? "agy_acp_server.exe" : "agy_acp_server.par";
|
||||
if (binary.cmd !== `./${expectedCommand}`) throw new Error("unsupported_release");
|
||||
if (JSON.stringify(binary.args ?? []) !== JSON.stringify(antigravityArgs(platform))) throw new Error("unsupported_release");
|
||||
if (binary.sha256 != null && !/^[a-fA-F0-9]{64}$/.test(binary.sha256)) throw new Error("unsupported_release");
|
||||
return { id, version: entry.version, kind: "binary", archive, sha256: binary.sha256 ?? null };
|
||||
};
|
||||
|
||||
const runNpm = (args, cwd, { executablePath = process.execPath, spawnImpl = spawn, npmPath = npmCli } = {}) => new Promise((resolve, reject) => {
|
||||
const child = spawnImpl(executablePath, [npmPath, ...args], {
|
||||
cwd,
|
||||
env: { ...process.env, ELECTRON_RUN_AS_NODE: "1", npm_config_update_notifier: "false" },
|
||||
stdio: "ignore",
|
||||
windowsHide: true,
|
||||
shell: false,
|
||||
});
|
||||
const timer = setTimeout(() => child.kill(), 5 * 60 * 1000);
|
||||
timer.unref?.();
|
||||
child.once("error", (error) => { clearTimeout(timer); reject(error); });
|
||||
child.once("exit", (code) => {
|
||||
clearTimeout(timer);
|
||||
code === 0 ? resolve() : reject(new Error("adapter_install_failed"));
|
||||
});
|
||||
});
|
||||
|
||||
const downloadArchive = async (url, destination, expectedHash, fetchImpl) => {
|
||||
const response = await fetchImpl(url, { signal: AbortSignal.timeout(120_000), redirect: "error" });
|
||||
if (!response.ok || !response.body) throw new Error("adapter_download_failed");
|
||||
if (Number(response.headers.get("content-length") || 0) > MAX_ARCHIVE_BYTES) throw new Error("adapter_too_large");
|
||||
const handle = await open(destination, "wx", 0o600);
|
||||
const hash = createHash("sha256");
|
||||
let bytes = 0;
|
||||
try {
|
||||
for await (const chunk of Readable.fromWeb(response.body)) {
|
||||
bytes += chunk.length;
|
||||
if (bytes > MAX_ARCHIVE_BYTES) throw new Error("adapter_too_large");
|
||||
hash.update(chunk);
|
||||
let offset = 0;
|
||||
while (offset < chunk.length) {
|
||||
const { bytesWritten } = await handle.write(chunk, offset, chunk.length - offset);
|
||||
if (!bytesWritten) throw new Error("adapter_download_failed");
|
||||
offset += bytesWritten;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
await handle.close();
|
||||
}
|
||||
if (expectedHash && hash.digest("hex").toLowerCase() !== expectedHash.toLowerCase()) throw new Error("adapter_integrity_failed");
|
||||
};
|
||||
|
||||
const extractAntigravity = async (archive, destination, platform) => {
|
||||
const required = platform === "win32" ? "agy_acp_server.exe" : "agy_acp_server.par";
|
||||
const allowed = new Set([required, "localharness_external"]);
|
||||
const extracted = new Set();
|
||||
let total = 0;
|
||||
let failure = null;
|
||||
let drain = null;
|
||||
const writes = [];
|
||||
const unzip = new Unzip((file) => {
|
||||
if (!allowed.has(file.name) || extracted.has(file.name) || file.compression !== 8) {
|
||||
failure = new Error("invalid_adapter_archive");
|
||||
return;
|
||||
}
|
||||
extracted.add(file.name);
|
||||
const output = createWriteStream(path.join(destination, file.name), { flags: "wx", mode: 0o700 });
|
||||
const done = finished(output);
|
||||
void done.catch(() => {});
|
||||
writes.push(done);
|
||||
file.ondata = (error, chunk, final) => {
|
||||
if (error) { failure = error; output.destroy(error); return; }
|
||||
total += chunk.length;
|
||||
if (total > MAX_EXTRACTED_BYTES) {
|
||||
failure = new Error("adapter_too_large");
|
||||
output.destroy(failure);
|
||||
return;
|
||||
}
|
||||
if (chunk.length && !output.write(chunk) && !final) drain = once(output, "drain");
|
||||
if (final) output.end();
|
||||
};
|
||||
file.start();
|
||||
});
|
||||
unzip.register(UnzipInflate);
|
||||
try {
|
||||
for await (const chunk of createReadStream(archive, { highWaterMark: 64 * 1024 })) {
|
||||
if (failure) throw failure;
|
||||
unzip.push(chunk);
|
||||
if (drain) { await drain; drain = null; }
|
||||
}
|
||||
unzip.push(new Uint8Array(), true);
|
||||
if (failure) throw failure;
|
||||
await Promise.all(writes);
|
||||
if (!extracted.has(required)) throw new Error("invalid_adapter_archive");
|
||||
} catch (error) {
|
||||
for (const promise of writes) void promise.catch(() => {});
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export function createAcpAdapterManager({ root, fetchImpl = fetch, platform = process.platform, arch = process.arch, executablePath = process.execPath, spawnImpl = spawn, npmPath = npmCli, installNpmImpl = runNpm, downloadImpl = downloadArchive, extractImpl = extractAntigravity } = {}) {
|
||||
if (!root || !path.isAbsolute(root)) throw new Error("invalid_adapter_store");
|
||||
const manifestPath = path.join(root, "installed.json");
|
||||
const inFlight = new Map();
|
||||
let saveQueue = Promise.resolve();
|
||||
let state = {};
|
||||
try { state = JSON.parse(readFileSync(manifestPath, "utf8")); } catch { /* First run or damaged manifest. */ }
|
||||
if (!state || typeof state !== "object" || Array.isArray(state)) state = {};
|
||||
|
||||
const get = (id) => {
|
||||
const version = state[id]?.version;
|
||||
if (typeof version !== "string") return null;
|
||||
const command = managedAdapterCommand(root, id, version, { platform, executablePath });
|
||||
return command ? { id, version, command } : null;
|
||||
};
|
||||
|
||||
const save = (id, version) => {
|
||||
const write = saveQueue.then(async () => {
|
||||
const next = { ...state, [id]: { version } };
|
||||
await mkdir(root, { recursive: true, mode: 0o700 });
|
||||
const temporary = `${manifestPath}.${process.pid}.tmp`;
|
||||
const file = await open(temporary, "w", 0o600);
|
||||
try { await file.writeFile(JSON.stringify(next)); } finally { await file.close(); }
|
||||
await rename(temporary, manifestPath);
|
||||
state = next;
|
||||
});
|
||||
saveQueue = write.catch(() => {});
|
||||
return write;
|
||||
};
|
||||
|
||||
const install = (id, validate, { updateOnly = false } = {}) => {
|
||||
if (id !== "codex" && id !== "antigravity") return Promise.reject(new Error("unknown_adapter"));
|
||||
if (inFlight.has(id)) return inFlight.get(id);
|
||||
const task = (async () => {
|
||||
const previous = get(id);
|
||||
if (updateOnly && !previous) return { updated: false, reason: "not_managed" };
|
||||
const release = selectAdapterRelease(await readRegistry(fetchImpl), id, { platform, arch });
|
||||
if (previous && compareVersions(release.version, previous.version) <= 0) return { updated: false, version: previous.version };
|
||||
const versionRoot = path.join(root, id);
|
||||
const target = path.join(versionRoot, release.version);
|
||||
const stage = path.join(versionRoot, `.stage-${release.version}-${process.pid}-${Date.now()}`);
|
||||
await mkdir(stage, { recursive: true, mode: 0o700 });
|
||||
try {
|
||||
if (release.kind === "npm") {
|
||||
await installNpmImpl(["install", "--prefix", stage, "--ignore-scripts", "--no-audit", "--no-fund", "--package-lock=false", "--registry=https://registry.npmjs.org", release.packageName], stage, { executablePath, spawnImpl, npmPath });
|
||||
} else {
|
||||
const archive = path.join(stage, "adapter.zip");
|
||||
await downloadImpl(release.archive, archive, release.sha256, fetchImpl);
|
||||
await extractImpl(archive, stage, platform);
|
||||
await rm(archive);
|
||||
if (platform !== "win32") await chmod(path.join(stage, "agy_acp_server.par"), 0o700);
|
||||
}
|
||||
// Inspect the staged command before making it visible to future sessions.
|
||||
const stagedFile = release.kind === "npm"
|
||||
? path.join(stage, "node_modules", "@agentclientprotocol", "codex-acp", "dist", "index.js")
|
||||
: path.join(stage, platform === "win32" ? "agy_acp_server.exe" : "agy_acp_server.par");
|
||||
if (!existsSync(stagedFile)) throw new Error("adapter_install_failed");
|
||||
const stagedCommand = release.kind === "npm"
|
||||
? { command: executablePath, args: [stagedFile], env: { ELECTRON_RUN_AS_NODE: "1" } }
|
||||
: { command: stagedFile, args: antigravityArgs(platform) };
|
||||
const result = await validate(stagedCommand);
|
||||
if (result?.state === "needs_login" && previous) {
|
||||
const previousResult = await validate(previous.command);
|
||||
if (previousResult?.state !== "needs_login") throw new Error("adapter_probe_failed");
|
||||
} else if (result?.state !== "available" && !(result?.state === "needs_login" && !previous)) {
|
||||
throw new Error(result?.detail || result?.state || "adapter_probe_failed");
|
||||
}
|
||||
await rm(target, { recursive: true, force: true });
|
||||
await rename(stage, target);
|
||||
await save(id, release.version);
|
||||
return { updated: true, version: release.version, adapter: result };
|
||||
} catch (error) {
|
||||
await rm(stage, { recursive: true, force: true });
|
||||
throw error;
|
||||
}
|
||||
})();
|
||||
inFlight.set(id, task);
|
||||
void task.finally(() => inFlight.delete(id)).catch(() => {});
|
||||
return task;
|
||||
};
|
||||
|
||||
const prune = async () => {
|
||||
for (const id of ["codex", "antigravity"]) {
|
||||
const current = get(id)?.version;
|
||||
if (!current) continue;
|
||||
const folder = path.join(root, id);
|
||||
const names = await readdir(folder).catch(() => []);
|
||||
const versions = names.filter((name) => VERSION_PATTERN.test(name) && name !== current)
|
||||
.sort((a, b) => compareVersions(b, a));
|
||||
for (const name of names) {
|
||||
if (name.startsWith(".stage-") || (versions.includes(name) && name !== versions[0])) {
|
||||
await rm(path.join(folder, name), { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return { get, install, prune, installedIds: () => ["codex", "antigravity"].filter((id) => get(id)) };
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { existsSync } from "node:fs";
|
||||
import { mkdtemp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { zipSync } from "fflate";
|
||||
import { createAcpAdapterManager, managedAdapterCommand, selectAdapterRelease } from "./acp-adapter-manager.mjs";
|
||||
|
||||
const codexEntry = (version) => ({
|
||||
id: "codex-acp",
|
||||
version,
|
||||
distribution: { npx: { package: `@agentclientprotocol/codex-acp@${version}` } },
|
||||
});
|
||||
|
||||
describe("managed ACP adapters", () => {
|
||||
test("accepts only the supported official distribution and platform command", () => {
|
||||
expect(selectAdapterRelease([codexEntry("2.0.1")], "codex").version).toBe("2.0.1");
|
||||
expect(() => selectAdapterRelease([{ ...codexEntry("2.0.1"), distribution: { npx: { package: "evil@2.0.1" } } }], "codex")).toThrow("unsupported_release");
|
||||
const entry = {
|
||||
id: "antigravity-acp",
|
||||
version: "1.2.1",
|
||||
distribution: { binary: { "darwin-aarch64": {
|
||||
archive: "https://dl.google.com/agy-extensions/releases/macos/test.zip",
|
||||
cmd: "./agy_acp_server.par",
|
||||
} } },
|
||||
};
|
||||
expect(selectAdapterRelease([entry], "antigravity", { platform: "darwin", arch: "arm64" }).kind).toBe("binary");
|
||||
entry.distribution.binary["linux-x86_64"] = {
|
||||
archive: "https://dl.google.com/agy-extensions/releases/linux/test.zip",
|
||||
cmd: "./agy_acp_server.par",
|
||||
args: ["--uid="],
|
||||
};
|
||||
expect(selectAdapterRelease([entry], "antigravity", { platform: "linux", arch: "x64" }).kind).toBe("binary");
|
||||
entry.distribution.binary["linux-x86_64"].args = [];
|
||||
expect(() => selectAdapterRelease([entry], "antigravity", { platform: "linux", arch: "x64" })).toThrow("unsupported_release");
|
||||
entry.distribution.binary["darwin-aarch64"].archive = "https://example.com/test.zip";
|
||||
expect(() => selectAdapterRelease([entry], "antigravity", { platform: "darwin", arch: "arm64" })).toThrow("unsupported_release");
|
||||
});
|
||||
|
||||
test("keeps the previous version when a staged update fails the ACP handshake", async () => {
|
||||
const root = await mkdtemp(path.join(tmpdir(), "edgeever-managed-acp-"));
|
||||
let release = "2.0.1";
|
||||
const manager = createAcpAdapterManager({
|
||||
root,
|
||||
platform: "darwin",
|
||||
arch: "arm64",
|
||||
executablePath: "/usr/bin/node",
|
||||
fetchImpl: async () => new Response(JSON.stringify({ agents: [codexEntry(release)] }), { status: 200 }),
|
||||
installNpmImpl: async (_args, stage) => {
|
||||
const directory = path.join(stage, "node_modules", "@agentclientprotocol", "codex-acp", "dist");
|
||||
await mkdir(directory, { recursive: true });
|
||||
await writeFile(path.join(directory, "index.js"), "// fake agent");
|
||||
},
|
||||
});
|
||||
const valid = async () => ({ id: "codex", label: "Codex", state: "available" });
|
||||
try {
|
||||
expect((await manager.install("codex", valid)).updated).toBe(true);
|
||||
expect(manager.get("codex")?.version).toBe("2.0.1");
|
||||
expect(manager.installedIds()).toEqual(["codex"]);
|
||||
expect((await manager.install("codex", valid, { updateOnly: true })).updated).toBe(false);
|
||||
|
||||
release = "2.0.2";
|
||||
await expect(manager.install("codex", async () => ({ state: "failed", detail: "handshake_failed" }), { updateOnly: true })).rejects.toThrow("handshake_failed");
|
||||
expect(manager.get("codex")?.version).toBe("2.0.1");
|
||||
expect(JSON.parse(await readFile(path.join(root, "installed.json"), "utf8")).codex.version).toBe("2.0.1");
|
||||
|
||||
expect((await manager.install("codex", valid, { updateOnly: true })).updated).toBe(true);
|
||||
expect(manager.get("codex")?.version).toBe("2.0.2");
|
||||
expect(await readFile(path.join(root, "codex", "2.0.1", "node_modules", "@agentclientprotocol", "codex-acp", "dist", "index.js"), "utf8")).toBe("// fake agent");
|
||||
|
||||
release = "2.0.3";
|
||||
expect((await manager.install("codex", valid, { updateOnly: true })).updated).toBe(true);
|
||||
await manager.prune();
|
||||
expect(existsSync(path.join(root, "codex", "2.0.1"))).toBe(false);
|
||||
expect(existsSync(path.join(root, "codex", "2.0.2"))).toBe(true);
|
||||
expect(manager.get("codex")?.version).toBe("2.0.3");
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("extracts only expected Antigravity files and rejects archive traversal", async () => {
|
||||
const root = await mkdtemp(path.join(tmpdir(), "edgeever-managed-agy-"));
|
||||
let malicious = false;
|
||||
const entry = {
|
||||
id: "antigravity-acp",
|
||||
version: "1.2.1",
|
||||
distribution: { binary: { "darwin-aarch64": {
|
||||
archive: "https://dl.google.com/agy-extensions/releases/macos/test.zip",
|
||||
cmd: "./agy_acp_server.par",
|
||||
} } },
|
||||
};
|
||||
const manager = createAcpAdapterManager({
|
||||
root,
|
||||
platform: "darwin",
|
||||
arch: "arm64",
|
||||
fetchImpl: async () => new Response(JSON.stringify({ agents: [entry] }), { status: 200 }),
|
||||
downloadImpl: async (_url, destination) => {
|
||||
const files = malicious
|
||||
? { "../outside": [new Uint8Array([1]), { level: 1 }] }
|
||||
: { "agy_acp_server.par": [new Uint8Array([1]), { level: 1 }], localharness_external: [new Uint8Array([2]), { level: 1 }] };
|
||||
await writeFile(destination, zipSync(files));
|
||||
},
|
||||
});
|
||||
try {
|
||||
malicious = true;
|
||||
await expect(manager.install("antigravity", async () => ({ state: "available" }))).rejects.toThrow("invalid_adapter_archive");
|
||||
expect(existsSync(path.join(root, "outside"))).toBe(false);
|
||||
malicious = false;
|
||||
expect((await manager.install("antigravity", async () => ({ state: "available" }))).updated).toBe(true);
|
||||
expect(manager.get("antigravity")?.version).toBe("1.2.1");
|
||||
expect(managedAdapterCommand(root, "antigravity", "1.2.1", { platform: "linux" })?.args).toEqual(["--uid="]);
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("updates an unauthenticated connector only when the previous version also needs login", async () => {
|
||||
const root = await mkdtemp(path.join(tmpdir(), "edgeever-acp-login-update-"));
|
||||
let release = "2.0.1";
|
||||
const manager = createAcpAdapterManager({
|
||||
root,
|
||||
platform: "darwin",
|
||||
arch: "arm64",
|
||||
executablePath: "/usr/bin/node",
|
||||
fetchImpl: async () => new Response(JSON.stringify({ agents: [codexEntry(release)] }), { status: 200 }),
|
||||
installNpmImpl: async (_args, stage) => {
|
||||
const directory = path.join(stage, "node_modules", "@agentclientprotocol", "codex-acp", "dist");
|
||||
await mkdir(directory, { recursive: true });
|
||||
await writeFile(path.join(directory, "index.js"), "// fake agent");
|
||||
},
|
||||
});
|
||||
try {
|
||||
await manager.install("codex", async () => ({ state: "needs_login" }));
|
||||
release = "2.0.2";
|
||||
await expect(manager.install("codex", async (command) => ({
|
||||
state: command.args[0].includes(".stage-") ? "needs_login" : "available",
|
||||
}), { updateOnly: true })).rejects.toThrow("adapter_probe_failed");
|
||||
expect(manager.get("codex")?.version).toBe("2.0.1");
|
||||
expect((await manager.install("codex", async () => ({ state: "needs_login" }), { updateOnly: true })).updated).toBe(true);
|
||||
expect(manager.get("codex")?.version).toBe("2.0.2");
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,16 +1,20 @@
|
||||
import { spawn as nodeSpawn } from "node:child_process";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { accessSync, constants as fsConstants, readFileSync, realpathSync, statSync } from "node:fs";
|
||||
import { accessSync, constants as fsConstants, existsSync, readFileSync, realpathSync, statSync } from "node:fs";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
import { homedir, tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { Readable, Writable } from "node:stream";
|
||||
import { ClientSideConnection, ndJsonStream, PROTOCOL_VERSION, RequestError } from "@agentclientprotocol/sdk";
|
||||
import { waitForChildProcessSpawn } from "./child-process-start.mjs";
|
||||
import { createAcpAdapterManager } from "./acp-adapter-manager.mjs";
|
||||
|
||||
const ADAPTERS = {
|
||||
codex: { id: "codex", label: "Codex" },
|
||||
antigravity: { id: "antigravity", label: "Antigravity" },
|
||||
grokBuild: { id: "grokBuild", label: "Grok Build" },
|
||||
workbuddyCn: { id: "workbuddyCn", label: "WorkBuddy 中国版" },
|
||||
workbuddyIntl: { id: "workbuddyIntl", label: "WorkBuddy International" },
|
||||
};
|
||||
const AUTH_REQUIRED_CODE = -32000;
|
||||
const MAX_ATTACHMENTS = 8;
|
||||
@@ -68,8 +72,40 @@ const findOnPath = (names, { access, pathEnv, delimiter, sep }) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
export function detectInstalledAgentApps({
|
||||
platform = process.platform,
|
||||
pathEnv = process.env.PATH ?? "",
|
||||
home = homedir(),
|
||||
env = process.env,
|
||||
access = accessSync,
|
||||
exists = existsSync,
|
||||
} = {}) {
|
||||
const lookup = (names) => !!findOnPath(names, {
|
||||
access,
|
||||
pathEnv,
|
||||
delimiter: platform === "win32" ? ";" : ":",
|
||||
sep: platform === "win32" ? "\\" : "/",
|
||||
});
|
||||
const candidates = (id) => {
|
||||
if (platform === "darwin") return id === "codex"
|
||||
? ["/Applications/Codex.app", path.join(home, "Applications", "Codex.app"), "/Applications/ChatGPT.app/Contents/Resources/codex"]
|
||||
: ["/Applications/Antigravity.app", path.join(home, "Applications", "Antigravity.app")];
|
||||
if (platform === "win32") return id === "codex"
|
||||
? [env.LOCALAPPDATA && path.join(env.LOCALAPPDATA, "Programs", "Codex", "Codex.exe")]
|
||||
: [env.LOCALAPPDATA && path.join(env.LOCALAPPDATA, "Programs", "Antigravity", "Antigravity.exe"), env.PROGRAMFILES && path.join(env.PROGRAMFILES, "Antigravity", "Antigravity.exe")];
|
||||
return [];
|
||||
};
|
||||
return ["codex", "antigravity"].filter((id) => {
|
||||
const names = platform === "win32" ? [`${id}.exe`, id] : [id];
|
||||
return lookup(names) || candidates(id).some((candidate) => candidate && exists(candidate));
|
||||
});
|
||||
}
|
||||
|
||||
const resolutionDeps = (deps = {}) => ({
|
||||
platform: deps.platform ?? process.platform,
|
||||
home: deps.home ?? homedir(),
|
||||
env: deps.env ?? process.env,
|
||||
executablePath: deps.executablePath ?? process.execPath,
|
||||
access: deps.accessSync ?? accessSync,
|
||||
realpath: deps.realpathSync ?? realpathSync,
|
||||
stat: deps.statSync ?? statSync,
|
||||
@@ -81,9 +117,65 @@ const resolutionDeps = (deps = {}) => ({
|
||||
export function resolveAcpCommand(input, deps = {}) {
|
||||
const resolved = resolutionDeps(deps);
|
||||
const id = input?.id;
|
||||
if (id !== "codex" && id !== "antigravity") return { ok: false, state: "failed", detail: "unknown_adapter" };
|
||||
if (!Object.hasOwn(ADAPTERS, id)) return { ok: false, state: "failed", detail: "unknown_adapter" };
|
||||
if (id === "codex") return resolveCodex(input?.path, resolved);
|
||||
return resolveAntigravity(input?.path, resolved);
|
||||
if (id === "antigravity") return resolveAntigravity(input?.path, resolved);
|
||||
if (id === "grokBuild") return resolveGrok(input?.path, resolved);
|
||||
return resolveWorkBuddy(id, resolved);
|
||||
}
|
||||
|
||||
function resolveWorkBuddy(id, deps) {
|
||||
const homeApplications = path.join(deps.home, "Applications");
|
||||
const macApps = id === "workbuddyCn" ? ["WorkBuddy.app", "WorkBuddy AI.app"] : ["WorkBuddy AI.app", "WorkBuddy.app"];
|
||||
const candidates = deps.platform === "darwin"
|
||||
? macApps.flatMap((name) => [path.join("/Applications", name), path.join(homeApplications, name)])
|
||||
.map((app) => path.join(app, "Contents", "Resources", "app.asar.unpacked", "cli", "bin", "codebuddy"))
|
||||
: deps.platform === "win32"
|
||||
? [deps.env.LOCALAPPDATA && path.join(deps.env.LOCALAPPDATA, "Programs", "WorkBuddy"), deps.env.LOCALAPPDATA && path.join(deps.env.LOCALAPPDATA, "WorkBuddy"), deps.env.PROGRAMFILES && path.join(deps.env.PROGRAMFILES, "WorkBuddy")]
|
||||
.filter(Boolean).map((folder) => path.join(folder, "resources", "app.asar.unpacked", "cli", "bin", "codebuddy"))
|
||||
: [];
|
||||
for (const candidate of candidates) {
|
||||
try {
|
||||
const actual = deps.realpath(candidate);
|
||||
if (!deps.stat(actual).isFile()) continue;
|
||||
deps.access(actual, fsConstants.R_OK);
|
||||
return { ok: true, command: workBuddyCommand(deps.executablePath, actual, id) };
|
||||
} catch { /* Try another installed WorkBuddy application. */ }
|
||||
}
|
||||
const external = findOnPath(deps.platform === "win32" ? ["codebuddy.exe"] : ["codebuddy"], deps);
|
||||
return external
|
||||
? { ok: true, command: workBuddyCommand(external, null, id) }
|
||||
: { ok: false, state: "not_installed" };
|
||||
}
|
||||
|
||||
function workBuddyCommand(executablePath, bundledCli, id) {
|
||||
const edition = id === "workbuddyCn" ? { CODEBUDDY_INTERNET_ENVIRONMENT: "internal" } : {};
|
||||
return bundledCli
|
||||
? { command: executablePath, args: [bundledCli, "--acp"], env: { ...edition, ELECTRON_RUN_AS_NODE: "1" }, ...(id === "workbuddyIntl" ? { unsetEnv: ["CODEBUDDY_INTERNET_ENVIRONMENT"] } : {}) }
|
||||
: { command: executablePath, args: ["--acp"], env: edition, ...(id === "workbuddyIntl" ? { unsetEnv: ["CODEBUDDY_INTERNET_ENVIRONMENT"] } : {}) };
|
||||
}
|
||||
|
||||
function resolveGrok(configured, deps) {
|
||||
const executable = deps.platform === "win32" ? "grok.exe" : "grok";
|
||||
const explicit = typeof configured === "string" && configured.trim() ? configured.trim() : null;
|
||||
if (explicit && (explicit.includes("\0") || !path.isAbsolute(explicit) || explicit.split(/[/\\]/).includes(".."))) {
|
||||
return { ok: false, state: "failed", detail: "invalid_path" };
|
||||
}
|
||||
const candidates = explicit ? [explicit] : [
|
||||
findOnPath([executable], deps),
|
||||
path.join(deps.home, ".grok", "bin", executable),
|
||||
...(deps.platform === "darwin" ? [`/opt/homebrew/bin/${executable}`, `/usr/local/bin/${executable}`] : []),
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
if (!candidate) continue;
|
||||
try {
|
||||
const actual = deps.realpath(candidate);
|
||||
if (!deps.stat(actual).isFile()) continue;
|
||||
deps.access(actual, fsConstants.X_OK);
|
||||
return { ok: true, command: { command: actual, args: ["agent", "stdio"] } };
|
||||
} catch { /* Try another installed Grok binary. */ }
|
||||
}
|
||||
return { ok: false, state: explicit ? "failed" : "not_installed", ...(explicit ? { detail: "invalid_path" } : {}) };
|
||||
}
|
||||
|
||||
function resolveCodex(configured, deps) {
|
||||
@@ -291,19 +383,27 @@ export function acpInitializeParams(version = clientVersion()) {
|
||||
};
|
||||
}
|
||||
|
||||
export function createAcpSpawnPlan(command, cwd) {
|
||||
export function createAcpSpawnPlan(input, cwd) {
|
||||
const spec = typeof input === "string" ? { command: input, args: [] } : input;
|
||||
const command = spec?.command;
|
||||
if (typeof command !== "string" || !command.trim() || command.includes("\0")) throw new Error("invalid_command");
|
||||
if (!Array.isArray(spec.args) || spec.args.some((arg) => typeof arg !== "string" || arg.includes("\0"))) throw new Error("invalid_command");
|
||||
if (typeof cwd !== "string" || !cwd.trim()) throw new Error("invalid_workspace");
|
||||
const workspace = path.resolve(cwd);
|
||||
if (workspace === path.resolve(homedir())) throw new Error("invalid_workspace");
|
||||
return {
|
||||
command,
|
||||
args: [],
|
||||
args: spec.args,
|
||||
options: {
|
||||
cwd: workspace,
|
||||
stdio: ["pipe", "pipe", "ignore"],
|
||||
windowsHide: true,
|
||||
shell: false,
|
||||
...(spec.env || spec.unsetEnv ? { env: (() => {
|
||||
const env = { ...process.env, ...spec.env };
|
||||
for (const key of spec.unsetEnv ?? []) delete env[key];
|
||||
return env;
|
||||
})() } : {}),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -312,7 +412,7 @@ export function spawnAcpChild(spawnImpl, command, cwd) {
|
||||
const plan = createAcpSpawnPlan(command, cwd);
|
||||
const options = { ...plan.options, shell: false, stdio: ["pipe", "pipe", "ignore"] };
|
||||
if (options.shell !== false) throw new Error("ACP processes cannot use a shell");
|
||||
const child = spawnImpl(plan.command, [], options);
|
||||
const child = spawnImpl(plan.command, plan.args, options);
|
||||
trackChild(child);
|
||||
return waitForChildProcessSpawn(child);
|
||||
}
|
||||
@@ -403,6 +503,13 @@ const normalizePromptCapabilities = (initialized) => {
|
||||
};
|
||||
};
|
||||
|
||||
const publicAuthMethods = (initialized) => (
|
||||
Array.isArray(initialized?.authMethods)
|
||||
? initialized.authMethods.filter((method) => (method?.type == null || method.type === "agent") && typeof method.id === "string" && method.id.length <= 120)
|
||||
.map((method) => ({ id: method.id, name: typeof method.name === "string" ? method.name.slice(0, 120) : method.id }))
|
||||
: []
|
||||
);
|
||||
|
||||
const createEdgeEverAcpClient = (requestId, emit) => ({
|
||||
requestPermission() {
|
||||
return { outcome: { outcome: "cancelled" } };
|
||||
@@ -459,11 +566,23 @@ export function createAcpHostRuntime(options = {}) {
|
||||
const version = options.clientVersion ?? clientVersion();
|
||||
const handshakeTimeoutMs = options.handshakeTimeoutMs ?? HANDSHAKE_TIMEOUT_MS;
|
||||
const commandDeps = options;
|
||||
const manager = options.adapterManager ?? (options.adapterStore ? createAcpAdapterManager({ root: options.adapterStore, executablePath: options.executablePath }) : null);
|
||||
const active = new Map();
|
||||
const updateFailures = new Map();
|
||||
const installingIds = new Set();
|
||||
const latestStatus = new Map();
|
||||
|
||||
const connect = async (command, requestId, emit, signal) => {
|
||||
const resolveCommand = (input) => {
|
||||
if (input?.id === "antigravity" && typeof input.path === "string" && input.path.trim()) return resolveAcpCommand(input, commandDeps);
|
||||
const managed = manager?.get(input?.id);
|
||||
if (managed) return { ok: true, command: managed.command, version: managed.version, managed: true };
|
||||
return resolveAcpCommand(input, commandDeps);
|
||||
};
|
||||
|
||||
const connect = async (command, requestId, emit, signal, authMethodId) => {
|
||||
const cwd = await createAcpWorkspace(mkdtempImpl, options.tmpRoot);
|
||||
let child = null;
|
||||
let authMethods = [];
|
||||
const abort = () => stopChild(child);
|
||||
signal?.addEventListener("abort", abort, { once: true });
|
||||
try {
|
||||
@@ -474,6 +593,11 @@ export function createAcpHostRuntime(options = {}) {
|
||||
const connection = new ClientSideConnection(() => createEdgeEverAcpClient(requestId, emit), stream);
|
||||
void connection.closed?.catch(() => {});
|
||||
const initialized = await connection.initialize(acpInitializeParams(version));
|
||||
authMethods = publicAuthMethods(initialized);
|
||||
if (authMethodId) {
|
||||
if (!authMethods.some((method) => method.id === authMethodId)) throw new Error("invalid_auth_method");
|
||||
await connection.authenticate({ methodId: authMethodId });
|
||||
}
|
||||
const session = await connection.newSession({ cwd, mcpServers: [] });
|
||||
if (signal?.aborted) throw Object.assign(new Error("connection_timeout"), { code: "TIMEOUT" });
|
||||
return {
|
||||
@@ -485,6 +609,7 @@ export function createAcpHostRuntime(options = {}) {
|
||||
stop: abort,
|
||||
};
|
||||
} catch (error) {
|
||||
if (authMethods.length && error && typeof error === "object") error.authMethods = authMethods;
|
||||
abort();
|
||||
await removeAcpWorkspace(cwd, rmImpl);
|
||||
throw error;
|
||||
@@ -493,9 +618,9 @@ export function createAcpHostRuntime(options = {}) {
|
||||
}
|
||||
};
|
||||
|
||||
const withHandshakeTimeout = async (operation) => {
|
||||
const withHandshakeTimeout = async (operation, timeoutMs = handshakeTimeoutMs) => {
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(() => controller.abort(), handshakeTimeoutMs);
|
||||
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
||||
timer.unref?.();
|
||||
try {
|
||||
return await operation(controller.signal);
|
||||
@@ -511,44 +636,131 @@ export function createAcpHostRuntime(options = {}) {
|
||||
|
||||
return {
|
||||
listAdapters() {
|
||||
const codex = resolveAcpCommand({ id: "codex" }, commandDeps);
|
||||
const codexAdapter = codex.ok
|
||||
? { ...adapterShell("codex"), state: "failed", detail: "not_probed" }
|
||||
: adapterFromResolution("codex", codex);
|
||||
return [codexAdapter, { ...adapterShell("antigravity"), state: "not_installed" }];
|
||||
return ["codex", "antigravity", "grokBuild", "workbuddyCn", "workbuddyIntl"].map((id) => {
|
||||
if (installingIds.has(id)) return { ...adapterShell(id), state: "installing" };
|
||||
const resolved = resolveCommand({ id });
|
||||
return resolved.ok
|
||||
? { ...adapterShell(id), ...(latestStatus.get(id) ?? { state: "failed", detail: "not_probed" }), ...(resolved.version ? { version: resolved.version, managed: true } : {}), ...(updateFailures.has(id) ? { updateError: updateFailures.get(id) } : {}) }
|
||||
: adapterFromResolution(id, resolved);
|
||||
});
|
||||
},
|
||||
|
||||
async installAdapter(id, { updateOnly = false } = {}) {
|
||||
if (!manager) return { updated: false, reason: "adapter_store_unavailable" };
|
||||
installingIds.add(id);
|
||||
try {
|
||||
const result = await manager.install(id, async (command) => {
|
||||
let connected;
|
||||
try {
|
||||
connected = await withHandshakeTimeout((signal) => connect(command, `install-${id}`, () => {}, signal), 90_000);
|
||||
return { ...adapterShell(id), state: "available", promptCapabilities: connected.promptCapabilities };
|
||||
} catch (error) {
|
||||
return { ...adapterShell(id), ...failureFields(classifyAcpFailure(error)), ...(isAuthRequiredError(error) ? { authMethods: error.authMethods ?? [] } : {}) };
|
||||
} finally {
|
||||
if (connected) {
|
||||
connected.stop();
|
||||
await removeAcpWorkspace(connected.cwd, rmImpl);
|
||||
}
|
||||
}
|
||||
}, { updateOnly });
|
||||
if (result.adapter) latestStatus.set(id, result.adapter);
|
||||
return result;
|
||||
} finally {
|
||||
installingIds.delete(id);
|
||||
}
|
||||
},
|
||||
|
||||
async installDetected() {
|
||||
if (!manager) return [];
|
||||
const detected = options.detectInstalledAgentApps?.() ?? detectInstalledAgentApps();
|
||||
const results = [];
|
||||
for (const id of detected) {
|
||||
if (manager.get(id) || resolveAcpCommand({ id }, commandDeps).ok) continue;
|
||||
try {
|
||||
results.push({ id, ...await this.installAdapter(id) });
|
||||
} catch (error) {
|
||||
results.push({ id, updated: false, reason: sanitizeFailureDetail(error) });
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
||||
async updateInstalled() {
|
||||
if (!manager) return [];
|
||||
const results = [];
|
||||
for (const id of manager.installedIds()) {
|
||||
try {
|
||||
const result = await this.installAdapter(id, { updateOnly: true });
|
||||
updateFailures.delete(id);
|
||||
results.push({ id, ...result });
|
||||
} catch (error) {
|
||||
const reason = sanitizeFailureDetail(error);
|
||||
updateFailures.set(id, reason);
|
||||
results.push({ id, updated: false, reason });
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
||||
async pruneAdapters() {
|
||||
await manager?.prune();
|
||||
},
|
||||
|
||||
async probeAdapter(input) {
|
||||
const id = input?.id;
|
||||
if (id !== "codex" && id !== "antigravity") throw new Error("unknown_adapter");
|
||||
const resolved = resolveAcpCommand(input, commandDeps);
|
||||
if (!Object.hasOwn(ADAPTERS, id)) throw new Error("unknown_adapter");
|
||||
const resolved = resolveCommand(input);
|
||||
if (!resolved.ok) return adapterFromResolution(id, resolved);
|
||||
let connected;
|
||||
try {
|
||||
connected = await withHandshakeTimeout((signal) => connect(resolved.command, `probe-${id}`, () => {}, signal));
|
||||
} catch (error) {
|
||||
return { ...adapterShell(id), ...failureFields(classifyAcpFailure(error)) };
|
||||
const failure = { ...adapterShell(id), ...failureFields(classifyAcpFailure(error)), ...(isAuthRequiredError(error) ? { authMethods: error.authMethods ?? [] } : {}), ...(resolved.version ? { version: resolved.version, managed: true } : {}) };
|
||||
latestStatus.set(id, failure);
|
||||
return failure;
|
||||
}
|
||||
const adapter = {
|
||||
...adapterShell(id),
|
||||
state: "available",
|
||||
promptCapabilities: connected.promptCapabilities,
|
||||
...(resolved.version ? { version: resolved.version, managed: true } : {}),
|
||||
};
|
||||
latestStatus.set(id, adapter);
|
||||
connected.stop();
|
||||
await removeAcpWorkspace(connected.cwd, rmImpl);
|
||||
return adapter;
|
||||
},
|
||||
|
||||
async authenticateAdapter(input) {
|
||||
const id = input?.id;
|
||||
if (!Object.hasOwn(ADAPTERS, id)) throw new Error("unknown_adapter");
|
||||
if (typeof input.methodId !== "string" || !input.methodId || input.methodId.length > 120) throw new Error("invalid_auth_method");
|
||||
const resolved = resolveCommand(input);
|
||||
if (!resolved.ok) return adapterFromResolution(id, resolved);
|
||||
let connected;
|
||||
try {
|
||||
connected = await withHandshakeTimeout((signal) => connect(resolved.command, `auth-${id}`, () => {}, signal, input.methodId), 5 * 60_000);
|
||||
return { ...adapterShell(id), state: "available", promptCapabilities: connected.promptCapabilities, ...(resolved.version ? { version: resolved.version, managed: true } : {}) };
|
||||
} catch (error) {
|
||||
return { ...adapterShell(id), ...failureFields(classifyAcpFailure(error)), ...(isAuthRequiredError(error) ? { authMethods: error.authMethods ?? [] } : {}), ...(resolved.version ? { version: resolved.version, managed: true } : {}) };
|
||||
} finally {
|
||||
if (connected) {
|
||||
connected.stop();
|
||||
await removeAcpWorkspace(connected.cwd, rmImpl);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async prompt(input, emit = () => {}) {
|
||||
if (!input || typeof input !== "object" || typeof input.prompt !== "string") throw new Error("invalid_prompt");
|
||||
if (input.adapterId !== "codex" && input.adapterId !== "antigravity") throw new Error("unknown_adapter");
|
||||
if (!Object.hasOwn(ADAPTERS, input.adapterId)) throw new Error("unknown_adapter");
|
||||
const requestId = randomUUID();
|
||||
const notify = (event) => emit(event);
|
||||
const fail = (message) => {
|
||||
notify({ requestId, type: "error", message });
|
||||
return { requestId };
|
||||
};
|
||||
const resolved = resolveAcpCommand({ id: input.adapterId, path: input.path }, commandDeps);
|
||||
const resolved = resolveCommand({ id: input.adapterId, path: input.path });
|
||||
if (!resolved.ok) return fail(promptFailureMessage(resolved));
|
||||
|
||||
let connected;
|
||||
@@ -616,13 +828,21 @@ const failureFields = (failure) => (
|
||||
: { state: failure.state }
|
||||
);
|
||||
|
||||
export function registerAcpIpc(ipcMain, runtime = createAcpHostRuntime()) {
|
||||
export function registerAcpIpc(ipcMain, runtime = createAcpHostRuntime(), { allowInstall = () => false } = {}) {
|
||||
const send = (sender, event) => {
|
||||
if (!sender || sender.isDestroyed?.()) return;
|
||||
sender.send("desktop:acp-event", event);
|
||||
};
|
||||
ipcMain.handle("desktop:acp-list", () => runtime.listAdapters());
|
||||
ipcMain.handle("desktop:acp-probe", (_event, input) => runtime.probeAdapter(input));
|
||||
ipcMain.handle("desktop:acp-install", (event, id) => {
|
||||
if (!allowInstall(event.sender)) throw new Error("adapter_install_forbidden");
|
||||
return runtime.installAdapter(id);
|
||||
});
|
||||
ipcMain.handle("desktop:acp-authenticate", (event, input) => {
|
||||
if (!allowInstall(event.sender)) throw new Error("adapter_auth_forbidden");
|
||||
return runtime.authenticateAdapter(input);
|
||||
});
|
||||
ipcMain.handle("desktop:acp-prompt", (event, input) => runtime.prompt(input, (acpEvent) => send(event.sender, acpEvent)));
|
||||
ipcMain.handle("desktop:acp-cancel", (_event, requestId) => runtime.cancel(requestId));
|
||||
return runtime;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { EventEmitter } from "node:events";
|
||||
import { realpathSync } from "node:fs";
|
||||
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { createRequire } from "node:module";
|
||||
import { homedir, tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
classifyAcpFailure,
|
||||
createAcpHostRuntime,
|
||||
createAcpSpawnPlan,
|
||||
detectInstalledAgentApps,
|
||||
eventsFromSessionUpdate,
|
||||
isAuthRequiredError,
|
||||
registerAcpIpc,
|
||||
@@ -59,7 +60,7 @@ const collector = () => {
|
||||
};
|
||||
};
|
||||
|
||||
const fakeAgentSource = ({ reportPath, secretPath, allowImage, allowEmbedded, hold }) => `#!/usr/bin/env bun
|
||||
const fakeAgentSource = ({ reportPath, secretPath, allowImage, allowEmbedded, hold, requireAuth }) => `#!/usr/bin/env bun
|
||||
import * as acp from ${JSON.stringify(sdkHref)};
|
||||
import { writeFileSync } from "node:fs";
|
||||
|
||||
@@ -68,7 +69,9 @@ const secretPath = ${JSON.stringify(secretPath)};
|
||||
const allowImage = ${allowImage ? "true" : "false"};
|
||||
const allowEmbedded = ${allowEmbedded ? "true" : "false"};
|
||||
const hold = ${hold ? "true" : "false"};
|
||||
const report = { initialize: null, newSession: null, permission: null, readError: null, readResult: null, prompt: null };
|
||||
const requireAuth = ${requireAuth ? "true" : "false"};
|
||||
let authenticated = false;
|
||||
const report = { initialize: null, newSession: null, permission: null, readError: null, readResult: null, prompt: null, authMethod: null };
|
||||
const save = () => writeFileSync(reportPath, JSON.stringify(report));
|
||||
writeFileSync(reportPath + ".pid", String(process.pid));
|
||||
let releaseHold = () => {};
|
||||
@@ -107,9 +110,17 @@ acp.agent({ name: "edgeever-fake-agent" })
|
||||
return {
|
||||
protocolVersion: ctx.params.protocolVersion,
|
||||
agentCapabilities: { promptCapabilities: { image: allowImage, embeddedContext: allowEmbedded } },
|
||||
authMethods: requireAuth ? [{ id: "browser", name: "Browser" }] : [],
|
||||
};
|
||||
})
|
||||
.onRequest("authenticate", (ctx) => {
|
||||
report.authMethod = ctx.params.methodId;
|
||||
authenticated = true;
|
||||
save();
|
||||
return {};
|
||||
})
|
||||
.onRequest("session/new", (ctx) => {
|
||||
if (requireAuth && !authenticated) throw new acp.RequestError(-32000, "auth_required");
|
||||
report.newSession = { cwd: ctx.params.cwd, mcpServers: ctx.params.mcpServers };
|
||||
save();
|
||||
return { sessionId: "sess-1" };
|
||||
@@ -212,6 +223,39 @@ describe("ACP command allow-list", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("detects installed agent applications separately from ACP connectors", () => {
|
||||
const detected = detectInstalledAgentApps({
|
||||
platform: "darwin",
|
||||
home: "/Users/example",
|
||||
pathEnv: "",
|
||||
access() { throw new Error("not on PATH"); },
|
||||
exists(candidate) { return candidate === "/Applications/Antigravity.app" || candidate === "/Applications/ChatGPT.app/Contents/Resources/codex"; },
|
||||
});
|
||||
expect(detected).toEqual(["codex", "antigravity"]);
|
||||
});
|
||||
|
||||
test("automatically installs only a detected agent missing its ACP connector", async () => {
|
||||
let installed = false;
|
||||
let installs = 0;
|
||||
const runtime = createAcpHostRuntime({
|
||||
platform: "darwin",
|
||||
pathEnv: "",
|
||||
detectInstalledAgentApps: () => ["codex"],
|
||||
adapterManager: {
|
||||
get: () => installed ? { version: "2.0.1", command: { command: "/tmp/codex-acp", args: [] } } : null,
|
||||
install: async () => {
|
||||
installs += 1;
|
||||
installed = true;
|
||||
return { updated: true, version: "2.0.1", adapter: { id: "codex", label: "Codex", state: "available" } };
|
||||
},
|
||||
},
|
||||
});
|
||||
expect((await runtime.installDetected())[0]?.updated).toBe(true);
|
||||
expect(runtime.listAdapters()[0]?.state).toBe("available");
|
||||
expect(await runtime.installDetected()).toEqual([]);
|
||||
expect(installs).toBe(1);
|
||||
});
|
||||
|
||||
test("looks up codex-acp.exe only as a win32 basename", () => {
|
||||
const seen = [];
|
||||
resolveAcpCommand({ id: "codex" }, {
|
||||
@@ -229,6 +273,47 @@ describe("ACP command allow-list", () => {
|
||||
expect(seen).toEqual(["C:\\Tools\\codex-acp", "C:\\Tools\\codex-acp.exe"]);
|
||||
});
|
||||
|
||||
test("runs an installed Grok Build CLI through its built-in ACP mode", async () => {
|
||||
const directory = await mkdtemp(path.join(tmpdir(), "edgeever-grok-acp-"));
|
||||
try {
|
||||
const binary = path.join(directory, ".grok", "bin", "grok");
|
||||
await mkdir(path.dirname(binary), { recursive: true });
|
||||
await writeFile(binary, "#!/bin/sh\nexit 0\n", { mode: 0o755 });
|
||||
const resolved = resolveAcpCommand({ id: "grokBuild" }, { platform: "darwin", pathEnv: "", home: directory });
|
||||
expect(resolved).toEqual({ ok: true, command: { command: realpathSync(binary), args: ["agent", "stdio"] } });
|
||||
const runtime = createAcpHostRuntime({ platform: "darwin", pathEnv: "", home: directory });
|
||||
expect(runtime.listAdapters().find((adapter) => adapter.id === "grokBuild")?.state).toBe("failed");
|
||||
expect(resolveAcpCommand({ id: "grokBuild", path: "../grok" }, { platform: "darwin", home: directory }).detail).toBe("invalid_path");
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("keeps WorkBuddy domestic and international ACP authentication environments separate", async () => {
|
||||
const directory = await mkdtemp(path.join(tmpdir(), "edgeever-workbuddy-acp-"));
|
||||
try {
|
||||
const bundled = path.join(directory, "Applications", "WorkBuddy AI.app", "Contents", "Resources", "app.asar.unpacked", "cli", "bin", "codebuddy");
|
||||
await mkdir(path.dirname(bundled), { recursive: true });
|
||||
await writeFile(bundled, "// fake bundled CLI");
|
||||
const deps = {
|
||||
platform: "darwin", home: directory, pathEnv: "", executablePath: "/usr/bin/node",
|
||||
realpathSync(candidate) {
|
||||
if (!candidate.startsWith(directory)) throw new Error("not installed");
|
||||
return realpathSync(candidate);
|
||||
},
|
||||
};
|
||||
const domestic = resolveAcpCommand({ id: "workbuddyCn" }, deps);
|
||||
const international = resolveAcpCommand({ id: "workbuddyIntl" }, deps);
|
||||
expect(domestic.command.args).toEqual([realpathSync(bundled), "--acp"]);
|
||||
expect(domestic.command.env.CODEBUDDY_INTERNET_ENVIRONMENT).toBe("internal");
|
||||
expect(international.command.args).toEqual([realpathSync(bundled), "--acp"]);
|
||||
expect(international.command.unsetEnv).toEqual(["CODEBUDDY_INTERNET_ENVIRONMENT"]);
|
||||
expect(createAcpSpawnPlan(international.command, directory).options.env.CODEBUDDY_INTERNET_ENVIRONMENT).toBeUndefined();
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("requires an Antigravity absolute file and does not accept a directory", async () => {
|
||||
const directory = await mkdtemp(path.join(tmpdir(), "edgeever-acp-agy-"));
|
||||
try {
|
||||
@@ -424,6 +509,30 @@ describe("ACP stdio session", () => {
|
||||
}
|
||||
}, 15_000);
|
||||
|
||||
sessionTest("offers advertised agent login and verifies a session after authentication", async () => {
|
||||
const directory = await mkdtemp(path.join(tmpdir(), "edgeever-acp-auth-"));
|
||||
const reportPath = path.join(directory, "report.json");
|
||||
try {
|
||||
const scriptPath = await writeFakeAgent(directory, {
|
||||
reportPath,
|
||||
secretPath: path.join(directory, "secret.txt"),
|
||||
allowImage: false,
|
||||
allowEmbedded: false,
|
||||
hold: false,
|
||||
requireAuth: true,
|
||||
});
|
||||
const runtime = createAcpHostRuntime();
|
||||
const probed = await runtime.probeAdapter({ id: "antigravity", path: scriptPath });
|
||||
expect(probed.state).toBe("needs_login");
|
||||
expect(probed.authMethods).toEqual([{ id: "browser", name: "Browser" }]);
|
||||
const authenticated = await runtime.authenticateAdapter({ id: "antigravity", path: scriptPath, methodId: "browser" });
|
||||
expect(authenticated.state).toBe("available");
|
||||
expect((await readReport(reportPath)).authMethod).toBe("browser");
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
}, 15_000);
|
||||
|
||||
sessionTest("streams updates, cancels permission, and never reads a local file", async () => {
|
||||
const directory = await mkdtemp(path.join(tmpdir(), "edgeever-acp-prompt-"));
|
||||
const reportPath = path.join(directory, "report.json");
|
||||
@@ -541,7 +650,9 @@ test("desktop preload and main process expose the ACP host", async () => {
|
||||
Bun.file(new URL("../preload/index.cjs", import.meta.url)).text(),
|
||||
Bun.file(new URL("./acp-host.mjs", import.meta.url)).text(),
|
||||
]);
|
||||
expect(main).toContain("registerAcpIpc(ipcMain)");
|
||||
expect(main).toContain("registerAcpIpc(ipcMain, createAcpHostRuntime({");
|
||||
expect(preload).toContain('installAcpAdapter: (id) => ipcRenderer.invoke("desktop:acp-install", id)');
|
||||
expect(preload).toContain('authenticateAcpAdapter: (input) => ipcRenderer.invoke("desktop:acp-authenticate", input)');
|
||||
expect(host).toContain('ipcMain.handle("desktop:acp-prompt"');
|
||||
expect(preload).toContain('listAcpAdapters: () => ipcRenderer.invoke("desktop:acp-list")');
|
||||
expect(preload).toContain('probeAcpAdapter: (input) => ipcRenderer.invoke("desktop:acp-probe", input)');
|
||||
@@ -550,5 +661,5 @@ test("desktop preload and main process expose the ACP host", async () => {
|
||||
expect(preload).toContain('ipcRenderer.on("desktop:acp-event"');
|
||||
const handlers = new Map();
|
||||
registerAcpIpc({ handle: (channel, handler) => handlers.set(channel, handler) });
|
||||
expect([...handlers.keys()]).toEqual(["desktop:acp-list", "desktop:acp-probe", "desktop:acp-prompt", "desktop:acp-cancel"]);
|
||||
expect([...handlers.keys()]).toEqual(["desktop:acp-list", "desktop:acp-probe", "desktop:acp-install", "desktop:acp-authenticate", "desktop:acp-prompt", "desktop:acp-cancel"]);
|
||||
});
|
||||
@@ -48,7 +48,7 @@ import {
|
||||
import electronUpdater from "electron-updater";
|
||||
import { createPluginPublicNetworkRuntime } from "./plugin-public-network.mjs";
|
||||
import { createAiDirectRuntime } from "./ai-direct.mjs";
|
||||
import { registerAcpIpc } from "./acp-host.mjs";
|
||||
import { createAcpHostRuntime, registerAcpIpc } from "./acp-host.mjs";
|
||||
import { shouldQuitAfterAllWindowsClosed } from "./window-lifecycle.mjs";
|
||||
import {
|
||||
RENDERER_HIBERNATE_PREPARE_TIMEOUT_MS,
|
||||
@@ -1594,7 +1594,15 @@ const startApplication = async () => {
|
||||
ipcMain.on("desktop:ai-direct-cancel", (event, requestId) => {
|
||||
if (event.sender === mainWindow?.webContents && typeof requestId === "string") aiDirect.cancel(requestId);
|
||||
});
|
||||
registerAcpIpc(ipcMain);
|
||||
const acpRuntime = registerAcpIpc(ipcMain, createAcpHostRuntime({
|
||||
adapterStore: join(app.getPath("userData"), "acp-adapters"),
|
||||
}), { allowInstall: (sender) => sender === mainWindow?.webContents });
|
||||
await acpRuntime.pruneAdapters().catch(() => {});
|
||||
const refreshAdapters = () => { void acpRuntime.installDetected().catch(() => []).then(() => acpRuntime.updateInstalled()).catch(() => {}); };
|
||||
const firstAdapterRefresh = setTimeout(refreshAdapters, 10_000);
|
||||
firstAdapterRefresh.unref?.();
|
||||
const adapterRefreshInterval = setInterval(refreshAdapters, 24 * 60 * 60 * 1000);
|
||||
adapterRefreshInterval.unref?.();
|
||||
ipcMain.handle("desktop:sync-scheduled-tasks", async (event, tasks) => {
|
||||
if (event.sender !== mainWindow?.webContents) throw new Error("Scheduled tasks must come from the main window");
|
||||
if (!Array.isArray(tasks) || tasks.length > 1_000) throw new Error("Invalid scheduled task list");
|
||||
|
||||
@@ -50,6 +50,8 @@ contextBridge.exposeInMainWorld("edgeeverDesktop", Object.freeze({
|
||||
},
|
||||
listAcpAdapters: () => ipcRenderer.invoke("desktop:acp-list"),
|
||||
probeAcpAdapter: (input) => ipcRenderer.invoke("desktop:acp-probe", input),
|
||||
installAcpAdapter: (id) => ipcRenderer.invoke("desktop:acp-install", id),
|
||||
authenticateAcpAdapter: (input) => ipcRenderer.invoke("desktop:acp-authenticate", input),
|
||||
promptAcp: (input) => ipcRenderer.invoke("desktop:acp-prompt", input),
|
||||
cancelAcp: (requestId) => ipcRenderer.invoke("desktop:acp-cancel", requestId),
|
||||
onAcpEvent: (callback) => {
|
||||
|
||||
@@ -347,9 +347,9 @@ function AiSidebarThreadMenu({
|
||||
|
||||
const readLocalAdapter = (): { id: DesktopAcpAdapterId; path?: string } | null => {
|
||||
const id = readStorage(AI_SIDEBAR_ADAPTER_KEY);
|
||||
if (id !== "codex" && id !== "antigravity") return null;
|
||||
if (id !== "codex" && id !== "antigravity" && id !== "grokBuild" && id !== "workbuddyCn" && id !== "workbuddyIntl") return null;
|
||||
const path = readStorage(AI_SIDEBAR_ADAPTER_PATH_KEY)?.trim();
|
||||
return path ? { id, path } : { id };
|
||||
return id === "antigravity" && path ? { id, path } : { id };
|
||||
};
|
||||
|
||||
const attachmentServerCode = (code: string | undefined) => (
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
AI_SIDEBAR_ADAPTER_PATH_KEY,
|
||||
AI_SIDEBAR_SOURCE_KEY,
|
||||
listDesktopAcpAdapters,
|
||||
installDesktopAcpAdapter,
|
||||
authenticateDesktopAcpAdapter,
|
||||
probeDesktopAcpAdapter,
|
||||
type AiSidebarSource,
|
||||
type DesktopAcpAdapter,
|
||||
@@ -25,29 +27,33 @@ import {
|
||||
SETTINGS_ITEM_TITLE_CLASSNAME,
|
||||
} from "./settings-ui";
|
||||
|
||||
const adapterIds: DesktopAcpAdapterId[] = ["codex", "antigravity"];
|
||||
const adapterIds: DesktopAcpAdapterId[] = ["codex", "antigravity", "grokBuild", "workbuddyCn", "workbuddyIntl"];
|
||||
|
||||
const agentCatalog = [
|
||||
{ id: "codex", connectable: true },
|
||||
{ id: "antigravity", connectable: true },
|
||||
{ id: "claudeCode", connectable: false },
|
||||
{ id: "workbuddy", connectable: false },
|
||||
{ id: "grokBuild", connectable: false },
|
||||
{ id: "workbuddyCn", connectable: true },
|
||||
{ id: "workbuddyIntl", connectable: true },
|
||||
{ id: "grokBuild", connectable: true },
|
||||
] as const;
|
||||
|
||||
const readSource = (): AiSidebarSource => (
|
||||
localStorage.getItem(AI_SIDEBAR_SOURCE_KEY) === "local" ? "local" : "builtin"
|
||||
);
|
||||
|
||||
const readAdapterId = (): DesktopAcpAdapterId => (
|
||||
localStorage.getItem(AI_SIDEBAR_ADAPTER_KEY) === "antigravity" ? "antigravity" : "codex"
|
||||
);
|
||||
const readAdapterId = (): DesktopAcpAdapterId => {
|
||||
const stored = localStorage.getItem(AI_SIDEBAR_ADAPTER_KEY);
|
||||
return adapterIds.find((id) => id === stored) ?? "codex";
|
||||
};
|
||||
|
||||
const statusKey = (adapter: DesktopAcpAdapter | undefined, probing: boolean) => {
|
||||
if (probing) return "aiAssistant.agentSource.probing";
|
||||
if (!adapter || adapter.detail === "not_probed") return "aiAssistant.agentSource.notProbed";
|
||||
if (adapter.detail === "invalid_path") return "aiAssistant.agentSource.invalidPath";
|
||||
if (adapter.detail === "desktop_unavailable") return "aiAssistant.agentSource.localDisabled";
|
||||
if (adapter.id === "grokBuild" && adapter.state === "not_installed") return "aiAssistant.agentSource.grokBuildNotFound";
|
||||
if ((adapter.id === "workbuddyCn" || adapter.id === "workbuddyIntl") && adapter.state === "not_installed") return "aiAssistant.agentSource.workbuddyNotFound";
|
||||
return `aiAssistant.agentSource.states.${adapter.state}`;
|
||||
};
|
||||
|
||||
@@ -64,6 +70,9 @@ const DesktopAcpAgentCardBody = ({ bridge }: { bridge: boolean }) => {
|
||||
const [listed, setListed] = useState<DesktopAcpAdapter[]>([]);
|
||||
const [probed, setProbed] = useState<DesktopAcpAdapter | null>(null);
|
||||
const [probing, setProbing] = useState(false);
|
||||
const [installing, setInstalling] = useState(false);
|
||||
const [installError, setInstallError] = useState(false);
|
||||
const [authenticating, setAuthenticating] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const stored = readSource();
|
||||
@@ -82,24 +91,72 @@ const DesktopAcpAgentCardBody = ({ bridge }: { bridge: boolean }) => {
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
void listDesktopAcpAdapters().then((adapters) => {
|
||||
const refresh = () => void listDesktopAcpAdapters().then((adapters) => {
|
||||
if (!cancelled) setListed(adapters);
|
||||
}).catch(() => {});
|
||||
refresh();
|
||||
const interval = window.setInterval(refresh, 5_000);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
window.clearInterval(interval);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const shown = probed?.id === adapterId ? probed : listed.find((adapter) => adapter.id === adapterId);
|
||||
const listedCurrent = listed.find((adapter) => adapter.id === adapterId);
|
||||
const shown = listedCurrent?.state === "installing" || (listedCurrent?.managed && (!probed?.managed || listedCurrent.version !== probed.version))
|
||||
? listedCurrent
|
||||
: probed?.id === adapterId ? probed : listedCurrent;
|
||||
const status = t(statusKey(shown, probing));
|
||||
const authMethods = shown?.authMethods?.filter((method) => (
|
||||
adapterId === "workbuddyCn" ? method.id !== "external" : adapterId === "workbuddyIntl" ? method.id !== "internal" : true
|
||||
)) ?? [];
|
||||
|
||||
const selectAdapter = (id: DesktopAcpAdapterId) => {
|
||||
setAdapterId(id);
|
||||
setProbed(null);
|
||||
setInstallError(false);
|
||||
};
|
||||
|
||||
const install = async () => {
|
||||
if (adapterId !== "codex" && adapterId !== "antigravity") return;
|
||||
setInstalling(true);
|
||||
setInstallError(false);
|
||||
try {
|
||||
const result = await installDesktopAcpAdapter(adapterId);
|
||||
if (result.updated) {
|
||||
if (adapterId === "antigravity") setAdapterPath("");
|
||||
setListed(await listDesktopAcpAdapters());
|
||||
if (result.adapter) setProbed({ ...result.adapter, version: result.version, managed: true });
|
||||
} else {
|
||||
setInstallError(true);
|
||||
}
|
||||
} catch {
|
||||
setInstallError(true);
|
||||
} finally {
|
||||
setInstalling(false);
|
||||
}
|
||||
};
|
||||
|
||||
const authenticate = async (methodId: string) => {
|
||||
setAuthenticating(true);
|
||||
setInstallError(false);
|
||||
try {
|
||||
const result = await authenticateDesktopAcpAdapter({
|
||||
id: adapterId,
|
||||
methodId,
|
||||
...(adapterId === "antigravity" && adapterPath.trim() ? { path: adapterPath.trim() } : {}),
|
||||
});
|
||||
setProbed(result);
|
||||
} catch {
|
||||
setProbed({ id: adapterId, label: t(`aiAssistant.agentSource.${adapterId}`), state: "failed" });
|
||||
} finally {
|
||||
setAuthenticating(false);
|
||||
}
|
||||
};
|
||||
|
||||
const probe = async () => {
|
||||
setProbing(true);
|
||||
setInstallError(false);
|
||||
try {
|
||||
const result = await probeDesktopAcpAdapter({
|
||||
id: adapterId,
|
||||
@@ -107,7 +164,7 @@ const DesktopAcpAgentCardBody = ({ bridge }: { bridge: boolean }) => {
|
||||
});
|
||||
setProbed(result);
|
||||
} catch {
|
||||
setProbed({ id: adapterId, label: adapterId === "codex" ? "Codex" : "Antigravity", state: "failed" });
|
||||
setProbed({ id: adapterId, label: t(`aiAssistant.agentSource.${adapterId}`), state: "failed" });
|
||||
} finally {
|
||||
setProbing(false);
|
||||
}
|
||||
@@ -228,11 +285,45 @@ const DesktopAcpAgentCardBody = ({ bridge }: { bridge: boolean }) => {
|
||||
) : null}
|
||||
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<p className="text-xs leading-5 text-slate-600" role="status">{status}</p>
|
||||
<Button type="button" variant="outline" size="sm" className="h-8 bg-card text-xs font-normal" disabled={probing} title={t("aiAssistant.agentSource.probeHint")} onClick={() => void probe()}>
|
||||
{probing ? t("aiAssistant.agentSource.probing") : t("aiAssistant.agentSource.probe")}
|
||||
</Button>
|
||||
<p className="text-xs leading-5 text-slate-600" role="status">
|
||||
{installing ? t("aiAssistant.agentSource.installing") : installError ? t("aiAssistant.agentSource.installFailed") : status}
|
||||
{shown?.managed && shown.version ? ` · v${shown.version} · ${t("aiAssistant.agentSource.autoUpdated")}` : ""}
|
||||
</p>
|
||||
<div className="flex shrink-0 gap-2">
|
||||
{shown?.state === "not_installed" && (adapterId === "codex" || adapterId === "antigravity") ? (
|
||||
<Button type="button" variant="outline" size="sm" className="h-8 bg-card text-xs font-normal" disabled={installing || probing} onClick={() => void install()}>
|
||||
{installing ? t("aiAssistant.agentSource.installing") : t("aiAssistant.agentSource.install")}
|
||||
</Button>
|
||||
) : null}
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span><Button type="button" variant="outline" size="sm" className="h-8 bg-card text-xs font-normal" disabled={probing || installing} onClick={() => void probe()}>
|
||||
{probing ? t("aiAssistant.agentSource.probing") : t("aiAssistant.agentSource.probe")}
|
||||
</Button></span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t("aiAssistant.agentSource.probeHint")}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
</div>
|
||||
{shown?.state === "not_installed" ? <p className="text-xs text-slate-500">{t(adapterId === "grokBuild" ? "aiAssistant.agentSource.grokBuildMissingHint" : adapterId === "workbuddyCn" || adapterId === "workbuddyIntl" ? "aiAssistant.agentSource.workbuddyMissingHint" : "aiAssistant.agentSource.installHint")}</p> : null}
|
||||
{shown?.state === "needs_login" && (adapterId === "workbuddyCn" || adapterId === "workbuddyIntl") ? (
|
||||
<p className="text-xs text-slate-600">{t(adapterId === "workbuddyCn" ? "aiAssistant.agentSource.workbuddyCnLoginHint" : "aiAssistant.agentSource.workbuddyIntlLoginHint")}</p>
|
||||
) : null}
|
||||
{shown?.state === "needs_login" && authMethods.length ? (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{authMethods.map((method) => (
|
||||
<Button key={method.id} type="button" variant="outline" size="sm" className="h-8 bg-card text-xs font-normal" disabled={authenticating} onClick={() => void authenticate(method.id)}>
|
||||
{authenticating ? t("aiAssistant.agentSource.authenticating") : t("aiAssistant.agentSource.authenticateWith", { method: method.name })}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
{shown?.state === "needs_login" && !authMethods.length ? (
|
||||
<p className="text-xs text-amber-700" role="status">{t("aiAssistant.agentSource.loginUnavailable")}</p>
|
||||
) : null}
|
||||
{shown?.updateError ? <p className="text-xs text-amber-700" role="status">{t("aiAssistant.agentSource.updateFailed")}</p> : null}
|
||||
</div>
|
||||
) : null}
|
||||
</CardContent>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export type DesktopAcpAdapterId = "codex" | "antigravity";
|
||||
export type DesktopAcpAdapterState = "not_installed" | "needs_login" | "available" | "failed";
|
||||
export type DesktopAcpAdapterId = "codex" | "antigravity" | "grokBuild" | "workbuddyCn" | "workbuddyIntl";
|
||||
export type DesktopAcpAdapterState = "not_installed" | "installing" | "needs_login" | "available" | "failed";
|
||||
|
||||
export type DesktopAcpPromptCapabilities = {
|
||||
image?: boolean;
|
||||
@@ -12,6 +12,10 @@ export type DesktopAcpAdapter = {
|
||||
state: DesktopAcpAdapterState;
|
||||
detail?: string;
|
||||
promptCapabilities?: DesktopAcpPromptCapabilities;
|
||||
version?: string;
|
||||
managed?: boolean;
|
||||
updateError?: string;
|
||||
authMethods?: Array<{ id: string; name: string }>;
|
||||
};
|
||||
|
||||
export type DesktopAcpAttachment = {
|
||||
@@ -67,6 +71,18 @@ export const probeDesktopAcpAdapter = async (input: { id: DesktopAcpAdapterId; p
|
||||
return desktop.probeAcpAdapter(input);
|
||||
};
|
||||
|
||||
export const installDesktopAcpAdapter = async (id: Extract<DesktopAcpAdapterId, "codex" | "antigravity">) => {
|
||||
const desktop = bridge();
|
||||
if (!desktop?.installAcpAdapter) throw new Error("desktop_acp_unavailable");
|
||||
return desktop.installAcpAdapter(id);
|
||||
};
|
||||
|
||||
export const authenticateDesktopAcpAdapter = async (input: { id: DesktopAcpAdapterId; path?: string; methodId: string }): Promise<DesktopAcpAdapter> => {
|
||||
const desktop = bridge();
|
||||
if (!desktop?.authenticateAcpAdapter) throw new Error("desktop_acp_unavailable");
|
||||
return desktop.authenticateAcpAdapter(input);
|
||||
};
|
||||
|
||||
export const promptDesktopAcp = async (input: DesktopAcpPromptInput): Promise<DesktopAcpPromptResult> => {
|
||||
const desktop = bridge();
|
||||
if (!desktop?.promptAcp) throw new Error("desktop_acp_unavailable");
|
||||
|
||||
Vendored
+26
-4
@@ -92,21 +92,43 @@ interface EdgeEverDesktopBridge {
|
||||
finishWeChatImport?(importId: string, success: boolean): Promise<void>;
|
||||
retryWeChatImport?(importId: string): Promise<boolean>;
|
||||
listAcpAdapters?(): Promise<Array<{
|
||||
id: "codex" | "antigravity";
|
||||
id: "codex" | "antigravity" | "grokBuild" | "workbuddyCn" | "workbuddyIntl";
|
||||
label: string;
|
||||
state: "not_installed" | "needs_login" | "available" | "failed";
|
||||
state: "not_installed" | "installing" | "needs_login" | "available" | "failed";
|
||||
detail?: string;
|
||||
promptCapabilities?: { image?: boolean; embeddedContext?: boolean };
|
||||
version?: string;
|
||||
managed?: boolean;
|
||||
updateError?: string;
|
||||
authMethods?: Array<{ id: string; name: string }>;
|
||||
}>>;
|
||||
probeAcpAdapter?(input: { id: "codex" | "antigravity"; path?: string }): Promise<{
|
||||
probeAcpAdapter?(input: { id: "codex" | "antigravity" | "grokBuild" | "workbuddyCn" | "workbuddyIntl"; path?: string }): Promise<{
|
||||
id: "codex" | "antigravity" | "grokBuild" | "workbuddyCn" | "workbuddyIntl";
|
||||
label: string;
|
||||
state: "not_installed" | "needs_login" | "available" | "failed";
|
||||
detail?: string;
|
||||
promptCapabilities?: { image?: boolean; embeddedContext?: boolean };
|
||||
version?: string;
|
||||
managed?: boolean;
|
||||
authMethods?: Array<{ id: string; name: string }>;
|
||||
}>;
|
||||
installAcpAdapter?(id: "codex" | "antigravity"): Promise<{ updated: boolean; version?: string; adapter?: {
|
||||
id: "codex" | "antigravity";
|
||||
label: string;
|
||||
state: "not_installed" | "needs_login" | "available" | "failed";
|
||||
detail?: string;
|
||||
promptCapabilities?: { image?: boolean; embeddedContext?: boolean };
|
||||
authMethods?: Array<{ id: string; name: string }>;
|
||||
} }>;
|
||||
authenticateAcpAdapter?(input: { id: "codex" | "antigravity" | "grokBuild" | "workbuddyCn" | "workbuddyIntl"; path?: string; methodId: string }): Promise<{
|
||||
id: "codex" | "antigravity" | "grokBuild" | "workbuddyCn" | "workbuddyIntl";
|
||||
label: string;
|
||||
state: "not_installed" | "needs_login" | "available" | "failed";
|
||||
detail?: string;
|
||||
authMethods?: Array<{ id: string; name: string }>;
|
||||
}>;
|
||||
promptAcp?(input: {
|
||||
adapterId: "codex" | "antigravity";
|
||||
adapterId: "codex" | "antigravity" | "grokBuild" | "workbuddyCn" | "workbuddyIntl";
|
||||
path?: string;
|
||||
prompt: string;
|
||||
contextText?: string;
|
||||
|
||||
@@ -102,12 +102,14 @@
|
||||
},
|
||||
"apps/desktop": {
|
||||
"name": "@edgeever/desktop",
|
||||
"version": "1.90.0",
|
||||
"version": "1.92.1",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "^1.5.1",
|
||||
"@edgeever/public-network": "workspace:*",
|
||||
"croner": "^10.0.1",
|
||||
"electron-updater": "^6.6.2",
|
||||
"fflate": "0.8.3",
|
||||
"npm": "11.6.2",
|
||||
"zod": "^4.6.5",
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -3324,6 +3326,8 @@
|
||||
|
||||
"normalize-url": ["normalize-url@6.1.0", "", {}, "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="],
|
||||
|
||||
"npm": ["npm@11.6.2", "", { "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/arborist": "^9.1.6", "@npmcli/config": "^10.4.2", "@npmcli/fs": "^4.0.0", "@npmcli/map-workspaces": "^5.0.0", "@npmcli/package-json": "^7.0.1", "@npmcli/promise-spawn": "^8.0.3", "@npmcli/redact": "^3.2.2", "@npmcli/run-script": "^10.0.0", "@sigstore/tuf": "^4.0.0", "abbrev": "^3.0.1", "archy": "~1.0.0", "cacache": "^20.0.1", "chalk": "^5.6.2", "ci-info": "^4.3.1", "cli-columns": "^4.0.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", "glob": "^11.0.3", "graceful-fs": "^4.2.11", "hosted-git-info": "^9.0.2", "ini": "^5.0.0", "init-package-json": "^8.2.2", "is-cidr": "^6.0.1", "json-parse-even-better-errors": "^4.0.0", "libnpmaccess": "^10.0.3", "libnpmdiff": "^8.0.9", "libnpmexec": "^10.1.8", "libnpmfund": "^7.0.9", "libnpmorg": "^8.0.1", "libnpmpack": "^9.0.9", "libnpmpublish": "^11.1.2", "libnpmsearch": "^9.0.1", "libnpmteam": "^8.0.2", "libnpmversion": "^8.0.2", "make-fetch-happen": "^15.0.2", "minimatch": "^10.0.3", "minipass": "^7.1.1", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", "node-gyp": "^11.4.2", "nopt": "^8.1.0", "npm-audit-report": "^6.0.0", "npm-install-checks": "^7.1.2", "npm-package-arg": "^13.0.1", "npm-pick-manifest": "^11.0.1", "npm-profile": "^12.0.0", "npm-registry-fetch": "^19.0.0", "npm-user-validate": "^3.0.0", "p-map": "^7.0.3", "pacote": "^21.0.3", "parse-conflict-json": "^4.0.0", "proc-log": "^5.0.0", "qrcode-terminal": "^0.12.0", "read": "^4.1.0", "semver": "^7.7.3", "spdx-expression-parse": "^4.0.0", "ssri": "^12.0.0", "supports-color": "^10.2.2", "tar": "^7.5.1", "text-table": "~0.2.0", "tiny-relative-date": "^2.0.2", "treeverse": "^3.0.0", "validate-npm-package-name": "^6.0.2", "which": "^5.0.0" }, "bin": { "npm": "bin/npm-cli.js", "npx": "bin/npx-cli.js" } }, "sha512-7iKzNfy8lWYs3zq4oFPa8EXZz5xt9gQNKJZau3B1ErLBb6bF7sBJ00x09485DOvRT2l5Gerbl3VlZNT57MxJVA=="],
|
||||
|
||||
"npm-package-arg": ["npm-package-arg@11.0.3", "", { "dependencies": { "hosted-git-info": "^7.0.0", "proc-log": "^4.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^5.0.0" } }, "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw=="],
|
||||
|
||||
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
|
||||
@@ -4772,6 +4776,348 @@
|
||||
|
||||
"node-gyp/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
|
||||
|
||||
"npm/@gar/promise-retry": ["@gar/promise-retry@1.0.3", "", {}, "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA=="],
|
||||
|
||||
"npm/@isaacs/cliui": ["@isaacs/cliui@9.0.0", "", {}, "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg=="],
|
||||
|
||||
"npm/@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
|
||||
|
||||
"npm/@isaacs/string-locale-compare": ["@isaacs/string-locale-compare@1.1.0", "", { "bundled": true }, "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ=="],
|
||||
|
||||
"npm/@npmcli/agent": ["@npmcli/agent@4.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^11.2.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-EUEuWAxnL07Sp5/iC/1X6Xj+XThUvnbei9zfRWZdEXa7lss9RTHMhAHBeg+MZ5To9s/gGaSI+UwZTPdYMvKSeg=="],
|
||||
|
||||
"npm/@npmcli/arborist": ["@npmcli/arborist@9.9.2", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/fs": "^5.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/map-workspaces": "^5.0.0", "@npmcli/metavuln-calculator": "^9.0.2", "@npmcli/name-from-folder": "^4.0.0", "@npmcli/node-gyp": "^5.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/query": "^5.0.0", "@npmcli/redact": "^4.0.0", "@npmcli/run-script": "^10.0.0", "bin-links": "^6.0.0", "cacache": "^20.0.1", "common-ancestor-path": "^2.0.0", "hosted-git-info": "^9.0.0", "json-stringify-nice": "^1.1.4", "lru-cache": "^11.2.1", "minimatch": "^10.0.3", "nopt": "^9.0.0", "npm-install-checks": "^8.0.0", "npm-package-arg": "^13.0.0", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "pacote": "^21.0.2", "parse-conflict-json": "^5.0.1", "proc-log": "^6.0.0", "proggy": "^4.0.0", "promise-all-reject-late": "^1.0.0", "promise-call-limit": "^3.0.1", "semver": "^7.3.7", "ssri": "^13.0.0", "treeverse": "^3.0.0", "walk-up-path": "^4.0.0" }, "bundled": true, "bin": { "arborist": "bin/index.js" } }, "sha512-N8FWFgZPRtkBYUhrEXagY9ADlGylgQgWHw1ywlHRXE8IobqFH+RAK2KL2at5YM33XFFpIDeoDh6nJ+3ZqB/sQQ=="],
|
||||
|
||||
"npm/@npmcli/config": ["@npmcli/config@10.13.0", "", { "dependencies": { "@npmcli/map-workspaces": "^5.0.0", "@npmcli/package-json": "^7.0.0", "ci-info": "^4.0.0", "ini": "^6.0.0", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "walk-up-path": "^4.0.0" }, "bundled": true }, "sha512-FS1eopTDqQ7EgmkuyC7QrarKr7ZXx1aVrQerER+AT27fsqt4ZvyaH/LeVYUOa2V6UUtokQsPOTfsb+LoqYyphw=="],
|
||||
|
||||
"npm/@npmcli/fs": ["@npmcli/fs@4.0.0", "", { "dependencies": { "semver": "^7.3.5" }, "bundled": true }, "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q=="],
|
||||
|
||||
"npm/@npmcli/git": ["@npmcli/git@7.0.2", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/promise-spawn": "^9.0.0", "ini": "^6.0.0", "lru-cache": "^11.2.1", "npm-pick-manifest": "^11.0.1", "proc-log": "^6.0.0", "semver": "^7.3.5", "which": "^6.0.0" } }, "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg=="],
|
||||
|
||||
"npm/@npmcli/installed-package-contents": ["@npmcli/installed-package-contents@4.0.0", "", { "dependencies": { "npm-bundled": "^5.0.0", "npm-normalize-package-bin": "^5.0.0" }, "bin": { "installed-package-contents": "bin/index.js" } }, "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA=="],
|
||||
|
||||
"npm/@npmcli/map-workspaces": ["@npmcli/map-workspaces@5.0.3", "", { "dependencies": { "@npmcli/name-from-folder": "^4.0.0", "@npmcli/package-json": "^7.0.0", "glob": "^13.0.0", "minimatch": "^10.0.3" }, "bundled": true }, "sha512-o2grssXo1e774E5OtEwwrgoszYRh0lqkJH+Pb9r78UcqdGJRDRfhpM8DvZPjzNLLNYeD/rNbjOKM3Ss5UABROw=="],
|
||||
|
||||
"npm/@npmcli/metavuln-calculator": ["@npmcli/metavuln-calculator@9.0.3", "", { "dependencies": { "cacache": "^20.0.0", "json-parse-even-better-errors": "^5.0.0", "pacote": "^21.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5" } }, "sha512-94GLSYhLXF2t2LAC7pDwLaM4uCARzxShyAQKsirmlNcpidH89VA4/+K1LbJmRMgz5gy65E/QBBWQdUvGLe2Frg=="],
|
||||
|
||||
"npm/@npmcli/name-from-folder": ["@npmcli/name-from-folder@4.0.0", "", {}, "sha512-qfrhVlOSqmKM8i6rkNdZzABj8MKEITGFAY+4teqBziksCQAOLutiAxM1wY2BKEd8KjUSpWmWCYxvXr0y4VTlPg=="],
|
||||
|
||||
"npm/@npmcli/node-gyp": ["@npmcli/node-gyp@5.0.0", "", {}, "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ=="],
|
||||
|
||||
"npm/@npmcli/package-json": ["@npmcli/package-json@7.0.5", "", { "dependencies": { "@npmcli/git": "^7.0.0", "glob": "^13.0.0", "hosted-git-info": "^9.0.0", "json-parse-even-better-errors": "^5.0.0", "proc-log": "^6.0.0", "semver": "^7.5.3", "spdx-expression-parse": "^4.0.0" }, "bundled": true }, "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ=="],
|
||||
|
||||
"npm/@npmcli/promise-spawn": ["@npmcli/promise-spawn@8.0.3", "", { "dependencies": { "which": "^5.0.0" }, "bundled": true }, "sha512-Yb00SWaL4F8w+K8YGhQ55+xE4RUNdMHV43WZGsiTM92gS+lC0mGsn7I4hLug7pbao035S6bj3Y3w0cUNGLfmkg=="],
|
||||
|
||||
"npm/@npmcli/query": ["@npmcli/query@5.0.0", "", { "dependencies": { "postcss-selector-parser": "^7.0.0" } }, "sha512-8TZWfTQOsODpLqo9SVhVjHovmKXNpevHU0gO9e+y4V4fRIOneiXy0u0sMP9LmS71XivrEWfZWg50ReH4WRT4aQ=="],
|
||||
|
||||
"npm/@npmcli/redact": ["@npmcli/redact@3.2.2", "", { "bundled": true }, "sha512-7VmYAmk4csGv08QzrDKScdzn11jHPFGyqJW39FyPgPuAp3zIaUmuCo1yxw9aGs+NEJuTGQ9Gwqpt93vtJubucg=="],
|
||||
|
||||
"npm/@npmcli/run-script": ["@npmcli/run-script@10.0.4", "", { "dependencies": { "@npmcli/node-gyp": "^5.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "node-gyp": "^12.1.0", "proc-log": "^6.0.0" }, "bundled": true }, "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg=="],
|
||||
|
||||
"npm/@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||
|
||||
"npm/@sigstore/bundle": ["@sigstore/bundle@4.0.0", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.5.0" } }, "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A=="],
|
||||
|
||||
"npm/@sigstore/core": ["@sigstore/core@3.2.1", "", {}, "sha512-qRsxPnCrbC/puegGxKuynfnxgLiHqWStrSjxkoB4YKqq3Z3s4cyZyj42ZdWFAEblNP65C+rBH8EuREHIXoi83g=="],
|
||||
|
||||
"npm/@sigstore/protobuf-specs": ["@sigstore/protobuf-specs@0.5.2", "", {}, "sha512-SQqvFMt4V78fdjcDdYX6HbiVSOR4QK3ZgwCa2KOsopAgPIHy1rU5UDUmzLl02r5oyyaYcYHR1hpwDRk/yUe+Mw=="],
|
||||
|
||||
"npm/@sigstore/sign": ["@sigstore/sign@4.1.1", "", { "dependencies": { "@gar/promise-retry": "^1.0.2", "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.2.0", "@sigstore/protobuf-specs": "^0.5.0", "make-fetch-happen": "^15.0.4", "proc-log": "^6.1.0" } }, "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ=="],
|
||||
|
||||
"npm/@sigstore/tuf": ["@sigstore/tuf@4.0.2", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.5.0", "tuf-js": "^4.1.0" }, "bundled": true }, "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ=="],
|
||||
|
||||
"npm/@sigstore/verify": ["@sigstore/verify@3.1.1", "", { "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.2.1", "@sigstore/protobuf-specs": "^0.5.0" } }, "sha512-qv7+G3J2cc6wwFj3yKvXOamzqhMwSk1ogPGmhpS8iXllcPrJaIIBA+4HbttlHVu1pqWTdmaCH/WE7UOC51kdoA=="],
|
||||
|
||||
"npm/@tufjs/canonical-json": ["@tufjs/canonical-json@2.0.0", "", {}, "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA=="],
|
||||
|
||||
"npm/@tufjs/models": ["@tufjs/models@4.1.0", "", { "dependencies": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^10.1.1" } }, "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww=="],
|
||||
|
||||
"npm/abbrev": ["abbrev@3.0.1", "", { "bundled": true }, "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg=="],
|
||||
|
||||
"npm/agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
||||
|
||||
"npm/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"npm/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
||||
|
||||
"npm/aproba": ["aproba@2.1.0", "", {}, "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew=="],
|
||||
|
||||
"npm/archy": ["archy@1.0.0", "", { "bundled": true }, "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw=="],
|
||||
|
||||
"npm/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"npm/bin-links": ["bin-links@6.0.2", "", { "dependencies": { "cmd-shim": "^8.0.0", "npm-normalize-package-bin": "^5.0.0", "proc-log": "^6.0.0", "read-cmd-shim": "^6.0.0", "write-file-atomic": "^7.0.0" } }, "sha512-frE1t78WOwJ45PKV2cF2tNPjTcs9L1J9s6VkrV59wanRP4GlaomuxYPVma7BwthMg8WnfSory4w5PTE6FZZ81w=="],
|
||||
|
||||
"npm/binary-extensions": ["binary-extensions@3.2.0", "", {}, "sha512-DjR9rgAOMQn9TrUHzijJUtvoKviDRvFxuIyqZrubxHqRpQN9OzfXrrLivm7xb3q8oJSKsiuBor4bAS2wafLnVQ=="],
|
||||
|
||||
"npm/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
|
||||
|
||||
"npm/cacache": ["cacache@20.0.4", "", { "dependencies": { "@npmcli/fs": "^5.0.0", "fs-minipass": "^3.0.0", "glob": "^13.0.0", "lru-cache": "^11.1.0", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^13.0.0" }, "bundled": true }, "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA=="],
|
||||
|
||||
"npm/chalk": ["chalk@5.6.2", "", { "bundled": true }, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||
|
||||
"npm/chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||
|
||||
"npm/ci-info": ["ci-info@4.4.0", "", { "bundled": true }, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="],
|
||||
|
||||
"npm/cidr-regex": ["cidr-regex@5.0.5", "", {}, "sha512-59tdLZcC+BJXa4C5rOmVSuJTy/UneqfJJtCraqwdx5BDHTkGrBtKCUl3u2uiCFvXu+wk0kVuX8axX7yHCZOI9w=="],
|
||||
|
||||
"npm/cli-columns": ["cli-columns@4.0.0", "", { "dependencies": { "string-width": "^4.2.3", "strip-ansi": "^6.0.1" }, "bundled": true }, "sha512-XW2Vg+w+L9on9wtwKpyzluIPCWXjaBahI7mTcYjx+BVIYD9c3yqcv/yKC7CmdCZat4rq2yiE1UMSJC5ivKfMtQ=="],
|
||||
|
||||
"npm/cmd-shim": ["cmd-shim@8.0.0", "", {}, "sha512-Jk/BK6NCapZ58BKUxlSI+ouKRbjH1NLZCgJkYoab+vEHUY3f6OzpNBN9u7HFSv9J6TRDGs4PLOHezoKGaFRSCA=="],
|
||||
|
||||
"npm/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"npm/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"npm/common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="],
|
||||
|
||||
"npm/cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"npm/cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
||||
|
||||
"npm/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"npm/diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
|
||||
|
||||
"npm/eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
|
||||
|
||||
"npm/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"npm/encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="],
|
||||
|
||||
"npm/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
|
||||
|
||||
"npm/err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="],
|
||||
|
||||
"npm/exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="],
|
||||
|
||||
"npm/fastest-levenshtein": ["fastest-levenshtein@1.0.16", "", { "bundled": true }, "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="],
|
||||
|
||||
"npm/fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"npm/foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
||||
|
||||
"npm/fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" }, "bundled": true }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="],
|
||||
|
||||
"npm/glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bundled": true, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="],
|
||||
|
||||
"npm/graceful-fs": ["graceful-fs@4.2.11", "", { "bundled": true }, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"npm/hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" }, "bundled": true }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="],
|
||||
|
||||
"npm/http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="],
|
||||
|
||||
"npm/http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
|
||||
|
||||
"npm/https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
||||
|
||||
"npm/iconv-lite": ["iconv-lite@0.7.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ=="],
|
||||
|
||||
"npm/ignore-walk": ["ignore-walk@8.0.0", "", { "dependencies": { "minimatch": "^10.0.3" } }, "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A=="],
|
||||
|
||||
"npm/imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"npm/ini": ["ini@5.0.0", "", { "bundled": true }, "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw=="],
|
||||
|
||||
"npm/init-package-json": ["init-package-json@8.2.5", "", { "dependencies": { "@npmcli/package-json": "^7.0.0", "npm-package-arg": "^13.0.0", "promzard": "^3.0.1", "read": "^5.0.1", "semver": "^7.7.2", "validate-npm-package-name": "^7.0.0" }, "bundled": true }, "sha512-IknQ+upLuJU6t3p0uo9wS3GjFD/1GtxIwcIGYOWR8zL2HxQeJwvxYTgZr9brJ8pyZ4kvpkebM8ZKcyqOeLOHSg=="],
|
||||
|
||||
"npm/ip-address": ["ip-address@10.7.2", "", {}, "sha512-7H/2gFSIitxc0hG3nOI1glS8QLo/EHBFFLk8vEUjXY/xu0AdL8jZ9U1IzO2PUm0d2D/ofQcAifb0g6OBkt8U7w=="],
|
||||
|
||||
"npm/is-cidr": ["is-cidr@6.0.4", "", { "dependencies": { "cidr-regex": "^5.0.4" }, "bundled": true }, "sha512-tOIBU3QiXy0W4LvHbcKWAWSuQfGwDiEILphFCAZtDqj7C57uv3ClO6K8aNEGV4VTA7bWJlpQ0suKQkUe6Rd6ag=="],
|
||||
|
||||
"npm/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"npm/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
|
||||
|
||||
"npm/jackspeak": ["jackspeak@4.2.3", "", { "dependencies": { "@isaacs/cliui": "^9.0.0" } }, "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg=="],
|
||||
|
||||
"npm/json-parse-even-better-errors": ["json-parse-even-better-errors@4.0.0", "", { "bundled": true }, "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA=="],
|
||||
|
||||
"npm/json-stringify-nice": ["json-stringify-nice@1.1.4", "", {}, "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw=="],
|
||||
|
||||
"npm/jsonparse": ["jsonparse@1.3.1", "", {}, "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg=="],
|
||||
|
||||
"npm/just-diff": ["just-diff@6.0.2", "", {}, "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA=="],
|
||||
|
||||
"npm/just-diff-apply": ["just-diff-apply@5.5.0", "", {}, "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw=="],
|
||||
|
||||
"npm/libnpmaccess": ["libnpmaccess@10.0.3", "", { "dependencies": { "npm-package-arg": "^13.0.0", "npm-registry-fetch": "^19.0.0" }, "bundled": true }, "sha512-JPHTfWJxIK+NVPdNMNGnkz4XGX56iijPbe0qFWbdt68HL+kIvSzh+euBL8npLZvl2fpaxo+1eZSdoG15f5YdIQ=="],
|
||||
|
||||
"npm/libnpmdiff": ["libnpmdiff@8.1.13", "", { "dependencies": { "@npmcli/arborist": "^9.9.2", "@npmcli/installed-package-contents": "^4.0.0", "binary-extensions": "^3.0.0", "diff": "^8.0.2", "minimatch": "^10.0.3", "npm-package-arg": "^13.0.0", "pacote": "^21.0.2", "tar": "^7.5.1" }, "bundled": true }, "sha512-CllgpfURhglenD7OEhMx1oMk8Z0+IEkZ9+IQlxhbO6TA9I7rfQrLZf7M7EXRYI0mRQxQnn2NcOzYQRMOK77XgA=="],
|
||||
|
||||
"npm/libnpmexec": ["libnpmexec@10.3.3", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/arborist": "^9.9.2", "@npmcli/package-json": "^7.0.0", "@npmcli/run-script": "^10.0.0", "ci-info": "^4.0.0", "npm-package-arg": "^13.0.0", "pacote": "^21.0.2", "proc-log": "^6.0.0", "read": "^5.0.1", "semver": "^7.3.7", "signal-exit": "^4.1.0", "walk-up-path": "^4.0.0" }, "bundled": true }, "sha512-IqoZup+ubFEwv7mqGd4ztYQilq6NSOi/r+y0O9Kmio8+/DX5b1irE4VnyO5Qf4TjVygnAFL8I91/rVvEfr6K0w=="],
|
||||
|
||||
"npm/libnpmfund": ["libnpmfund@7.0.27", "", { "dependencies": { "@npmcli/arborist": "^9.9.2" }, "bundled": true }, "sha512-2eU661BS4TrnrfmLYQBTTKwkFuV8dLibxRkBhCUNRsJFY0wjcdTG4SR1X22H0iXTkiI++9wb3M+/r4gmwrO4HA=="],
|
||||
|
||||
"npm/libnpmorg": ["libnpmorg@8.0.1", "", { "dependencies": { "aproba": "^2.0.0", "npm-registry-fetch": "^19.0.0" }, "bundled": true }, "sha512-/QeyXXg4hqMw0ESM7pERjIT2wbR29qtFOWIOug/xO4fRjS3jJJhoAPQNsnHtdwnCqgBdFpGQ45aIdFFZx2YhTA=="],
|
||||
|
||||
"npm/libnpmpack": ["libnpmpack@9.1.14", "", { "dependencies": { "@npmcli/arborist": "^9.9.2", "@npmcli/run-script": "^10.0.0", "npm-package-arg": "^13.0.0", "pacote": "^21.0.2" }, "bundled": true }, "sha512-zSUaxpUc91dMyDgWmPlCqeW14FQdRvk3YHEwGAbfOTKaczD+gOr0cweXQ3bOkfLKXdnaOhvkqFZp0MvIfpkElQ=="],
|
||||
|
||||
"npm/libnpmpublish": ["libnpmpublish@11.2.1", "", { "dependencies": { "@npmcli/package-json": "^7.0.0", "ci-info": "^4.0.0", "npm-package-arg": "^13.0.0", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", "semver": "^7.3.7", "sigstore": "^4.0.0", "ssri": "^13.0.0" }, "bundled": true }, "sha512-eZTRbsvZnG7tV0b9Hxug9feQt9Z29GyijcWpEKpLrgaJjxuVCkUNPW+w6OcXmlvSaopkyrGN65hgtk+Z0YP3Hg=="],
|
||||
|
||||
"npm/libnpmsearch": ["libnpmsearch@9.0.1", "", { "dependencies": { "npm-registry-fetch": "^19.0.0" }, "bundled": true }, "sha512-oKw58X415ERY/BOGV3jQPVMcep8YeMRWMzuuqB0BAIM5VxicOU1tQt19ExCu4SV77SiTOEoziHxGEgJGw3FBYQ=="],
|
||||
|
||||
"npm/libnpmteam": ["libnpmteam@8.0.2", "", { "dependencies": { "aproba": "^2.0.0", "npm-registry-fetch": "^19.0.0" }, "bundled": true }, "sha512-ypLrDUQoi8EhG+gzx5ENMcYq23YjPV17Mfvx4nOnQiHOi8vp47+4GvZBrMsEM4yeHPwxguF/HZoXH4rJfHdH/w=="],
|
||||
|
||||
"npm/libnpmversion": ["libnpmversion@8.0.4", "", { "dependencies": { "@npmcli/git": "^7.0.0", "@npmcli/run-script": "^10.0.0", "json-parse-even-better-errors": "^5.0.0", "proc-log": "^6.0.0", "semver": "^7.3.7" }, "bundled": true }, "sha512-5NiNpLxXkNeLHCYVTLxX/qRgdAoRAjiR0arFdVpQ5kZOJ2b0pHdXS9G3qC7uiqVsLa/gfQQIbQIEPdmSMKXF2A=="],
|
||||
|
||||
"npm/lru-cache": ["lru-cache@11.5.1", "", {}, "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A=="],
|
||||
|
||||
"npm/make-fetch-happen": ["make-fetch-happen@15.0.6", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/agent": "^4.0.0", "@npmcli/redact": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^6.0.0", "ssri": "^13.0.0" }, "bundled": true }, "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw=="],
|
||||
|
||||
"npm/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" }, "bundled": true }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
||||
|
||||
"npm/minipass": ["minipass@7.1.3", "", { "bundled": true }, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"npm/minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="],
|
||||
|
||||
"npm/minipass-fetch": ["minipass-fetch@5.0.2", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^2.0.0", "minizlib": "^3.0.1" }, "optionalDependencies": { "iconv-lite": "^0.7.2" } }, "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ=="],
|
||||
|
||||
"npm/minipass-flush": ["minipass-flush@1.0.7", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA=="],
|
||||
|
||||
"npm/minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" }, "bundled": true }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="],
|
||||
|
||||
"npm/minipass-sized": ["minipass-sized@2.0.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA=="],
|
||||
|
||||
"npm/minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
||||
|
||||
"npm/ms": ["ms@2.1.3", "", { "bundled": true }, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"npm/mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="],
|
||||
|
||||
"npm/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||
|
||||
"npm/node-gyp": ["node-gyp@11.5.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "make-fetch-happen": "^14.0.3", "nopt": "^8.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5", "tar": "^7.4.3", "tinyglobby": "^0.2.12", "which": "^5.0.0" }, "bundled": true, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ=="],
|
||||
|
||||
"npm/nopt": ["nopt@8.1.0", "", { "dependencies": { "abbrev": "^3.0.0" }, "bundled": true, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A=="],
|
||||
|
||||
"npm/npm-audit-report": ["npm-audit-report@6.0.0", "", { "bundled": true }, "sha512-Ag6Y1irw/+CdSLqEEAn69T8JBgBThj5mw0vuFIKeP7hATYuQuS5jkMjK6xmVB8pr7U4g5Audbun0lHhBDMIBRA=="],
|
||||
|
||||
"npm/npm-bundled": ["npm-bundled@5.0.0", "", { "dependencies": { "npm-normalize-package-bin": "^5.0.0" } }, "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw=="],
|
||||
|
||||
"npm/npm-install-checks": ["npm-install-checks@7.1.2", "", { "dependencies": { "semver": "^7.1.1" }, "bundled": true }, "sha512-z9HJBCYw9Zr8BqXcllKIs5nI+QggAImbBdHphOzVYrz2CB4iQ6FzWyKmlqDZua+51nAu7FcemlbTc9VgQN5XDQ=="],
|
||||
|
||||
"npm/npm-normalize-package-bin": ["npm-normalize-package-bin@5.0.0", "", {}, "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag=="],
|
||||
|
||||
"npm/npm-package-arg": ["npm-package-arg@13.0.2", "", { "dependencies": { "hosted-git-info": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^7.0.0" }, "bundled": true }, "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA=="],
|
||||
|
||||
"npm/npm-packlist": ["npm-packlist@10.0.4", "", { "dependencies": { "ignore-walk": "^8.0.0", "proc-log": "^6.0.0" } }, "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng=="],
|
||||
|
||||
"npm/npm-pick-manifest": ["npm-pick-manifest@11.0.3", "", { "dependencies": { "npm-install-checks": "^8.0.0", "npm-normalize-package-bin": "^5.0.0", "npm-package-arg": "^13.0.0", "semver": "^7.3.5" }, "bundled": true }, "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ=="],
|
||||
|
||||
"npm/npm-profile": ["npm-profile@12.0.2", "", { "dependencies": { "npm-registry-fetch": "^19.0.0", "proc-log": "^6.1.0" }, "bundled": true }, "sha512-+OKkPvqvx83vRG8aIetzABI99e5uzZZ6HIS5zCr+oRPSuDL0Buk1KJh/LqyR0BuiWmLeDWGI77igNYipztLm1w=="],
|
||||
|
||||
"npm/npm-registry-fetch": ["npm-registry-fetch@19.1.1", "", { "dependencies": { "@npmcli/redact": "^4.0.0", "jsonparse": "^1.3.1", "make-fetch-happen": "^15.0.0", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minizlib": "^3.0.1", "npm-package-arg": "^13.0.0", "proc-log": "^6.0.0" }, "bundled": true }, "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw=="],
|
||||
|
||||
"npm/npm-user-validate": ["npm-user-validate@3.0.0", "", { "bundled": true }, "sha512-9xi0RdSmJ4mPYTC393VJPz1Sp8LyCx9cUnm/L9Qcb3cFO8gjT4mN20P9FAsea8qDHdQ7LtcN8VLh2UT47SdKCw=="],
|
||||
|
||||
"npm/p-map": ["p-map@7.0.8", "", { "bundled": true }, "sha512-MitaVsCuCFIvOLLPIU7NnfrZvS9H9h7kwMUkDo+T2pEISaJD48IV9S8iIdXB7PsvvdxyYcsSTTrr90XKsbulNw=="],
|
||||
|
||||
"npm/package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
|
||||
|
||||
"npm/pacote": ["pacote@21.5.1", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "@npmcli/run-script": "^10.0.0", "cacache": "^20.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^13.0.0", "npm-packlist": "^10.0.1", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", "sigstore": "^4.0.0", "ssri": "^13.0.0", "tar": "^7.4.3" }, "bundled": true, "bin": { "pacote": "bin/index.js" } }, "sha512-KvcJ9iy3crysCsgqc4+PknH/w6jkrp8JN36mpZBPwNaDRwTfMZD37YzRazNstiZUOhuF5pno9f78n9mEJBavwg=="],
|
||||
|
||||
"npm/parse-conflict-json": ["parse-conflict-json@4.0.0", "", { "dependencies": { "json-parse-even-better-errors": "^4.0.0", "just-diff": "^6.0.0", "just-diff-apply": "^5.2.0" }, "bundled": true }, "sha512-37CN2VtcuvKgHUs8+0b1uJeEsbGn61GRHz469C94P5xiOoqpDYJYwjg4RY9Vmz39WyZAVkR5++nbJwLMIgOCnQ=="],
|
||||
|
||||
"npm/path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"npm/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
||||
|
||||
"npm/picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
|
||||
|
||||
"npm/postcss-selector-parser": ["postcss-selector-parser@7.1.6", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-7qASPzhKF2l2KLboRZux8CCTRMdGiV08vWmyKzPz22qZ7ZjQBOeY7rNzNoCLSUiftJ7HUq0GERHmxw/t0dCdMw=="],
|
||||
|
||||
"npm/proc-log": ["proc-log@5.0.0", "", { "bundled": true }, "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ=="],
|
||||
|
||||
"npm/proggy": ["proggy@4.0.0", "", {}, "sha512-MbA4R+WQT76ZBm/5JUpV9yqcJt92175+Y0Bodg3HgiXzrmKu7Ggq+bpn6y6wHH+gN9NcyKn3yg1+d47VaKwNAQ=="],
|
||||
|
||||
"npm/promise-all-reject-late": ["promise-all-reject-late@1.0.1", "", {}, "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw=="],
|
||||
|
||||
"npm/promise-call-limit": ["promise-call-limit@3.0.2", "", {}, "sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw=="],
|
||||
|
||||
"npm/promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="],
|
||||
|
||||
"npm/promzard": ["promzard@3.0.1", "", { "dependencies": { "read": "^5.0.0" } }, "sha512-M5mHhWh+Adz0BIxgSrqcc6GTCSconR7zWQV9vnOSptNtr6cSFlApLc28GbQhuN6oOWBQeV2C0bNE47JCY/zu3Q=="],
|
||||
|
||||
"npm/qrcode-terminal": ["qrcode-terminal@0.12.0", "", { "bundled": true, "bin": { "qrcode-terminal": "./bin/qrcode-terminal.js" } }, "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ=="],
|
||||
|
||||
"npm/read": ["read@4.1.0", "", { "dependencies": { "mute-stream": "^2.0.0" }, "bundled": true }, "sha512-uRfX6K+f+R8OOrYScaM3ixPY4erg69f8DN6pgTvMcA9iRc8iDhwrA4m3Yu8YYKsXJgVvum+m8PkRboZwwuLzYA=="],
|
||||
|
||||
"npm/read-cmd-shim": ["read-cmd-shim@6.0.0", "", {}, "sha512-1zM5HuOfagXCBWMN83fuFI/x+T/UhZ7k+KIzhrHXcQoeX5+7gmaDYjELQHmmzIodumBHeByBJT4QYS7ufAgs7A=="],
|
||||
|
||||
"npm/retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="],
|
||||
|
||||
"npm/safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||
|
||||
"npm/semver": ["semver@7.8.5", "", { "bundled": true, "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||
|
||||
"npm/shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"npm/shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"npm/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
|
||||
"npm/sigstore": ["sigstore@4.1.1", "", { "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.2.1", "@sigstore/protobuf-specs": "^0.5.0", "@sigstore/sign": "^4.1.1", "@sigstore/tuf": "^4.0.2", "@sigstore/verify": "^3.1.1" } }, "sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w=="],
|
||||
|
||||
"npm/smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
|
||||
|
||||
"npm/socks": ["socks@2.8.10", "", { "dependencies": { "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" } }, "sha512-e0VyvkVTwVYViNovRkZ9aodhxVlyoMn7eJhVUPxZ+eK9P/7CBkxvvsBOHqFPEH416726W8tLXXXjKwqgTErrCQ=="],
|
||||
|
||||
"npm/socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
|
||||
|
||||
"npm/spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="],
|
||||
|
||||
"npm/spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" }, "bundled": true }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="],
|
||||
|
||||
"npm/spdx-license-ids": ["spdx-license-ids@3.0.24", "", {}, "sha512-cLS9TtWkIQFyLkJ3/5aFQAOHOSKTlOs/7WDut/XPSdjom1fJhUdkepeJAKXa9Y05+FabHd0sti+Et559vDtkpQ=="],
|
||||
|
||||
"npm/ssri": ["ssri@12.0.0", "", { "dependencies": { "minipass": "^7.0.3" }, "bundled": true }, "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ=="],
|
||||
|
||||
"npm/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"npm/string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"npm/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"npm/strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"npm/supports-color": ["supports-color@10.2.2", "", { "bundled": true }, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
|
||||
|
||||
"npm/tar": ["tar@7.5.19", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" }, "bundled": true }, "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw=="],
|
||||
|
||||
"npm/text-table": ["text-table@0.2.0", "", { "bundled": true }, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="],
|
||||
|
||||
"npm/tiny-relative-date": ["tiny-relative-date@2.0.2", "", { "bundled": true }, "sha512-rGxAbeL9z3J4pI2GtBEoFaavHdO4RKAU54hEuOef5kfx5aPqiQtbhYktMOTL5OA33db8BjsDcLXuNp+/v19PHw=="],
|
||||
|
||||
"npm/tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
|
||||
|
||||
"npm/treeverse": ["treeverse@3.0.0", "", { "bundled": true }, "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ=="],
|
||||
|
||||
"npm/tuf-js": ["tuf-js@4.1.0", "", { "dependencies": { "@tufjs/models": "4.1.0", "debug": "^4.4.3", "make-fetch-happen": "^15.0.1" } }, "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ=="],
|
||||
|
||||
"npm/undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="],
|
||||
|
||||
"npm/unique-filename": ["unique-filename@4.0.0", "", { "dependencies": { "unique-slug": "^5.0.0" } }, "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ=="],
|
||||
|
||||
"npm/unique-slug": ["unique-slug@5.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg=="],
|
||||
|
||||
"npm/util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"npm/validate-npm-package-name": ["validate-npm-package-name@6.0.2", "", { "bundled": true }, "sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ=="],
|
||||
|
||||
"npm/walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="],
|
||||
|
||||
"npm/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bundled": true, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="],
|
||||
|
||||
"npm/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||
|
||||
"npm/wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"npm/write-file-atomic": ["write-file-atomic@7.0.1", "", { "dependencies": { "signal-exit": "^4.0.1" } }, "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg=="],
|
||||
|
||||
"npm/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||
|
||||
"npm-package-arg/hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="],
|
||||
|
||||
"ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||
@@ -5392,6 +5738,122 @@
|
||||
|
||||
"npm-package-arg/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"npm/@npmcli/arborist/@npmcli/fs": ["@npmcli/fs@5.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og=="],
|
||||
|
||||
"npm/@npmcli/arborist/@npmcli/redact": ["@npmcli/redact@4.0.0", "", {}, "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q=="],
|
||||
|
||||
"npm/@npmcli/arborist/nopt": ["nopt@9.0.0", "", { "dependencies": { "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw=="],
|
||||
|
||||
"npm/@npmcli/arborist/npm-install-checks": ["npm-install-checks@8.0.0", "", { "dependencies": { "semver": "^7.1.1" } }, "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA=="],
|
||||
|
||||
"npm/@npmcli/arborist/parse-conflict-json": ["parse-conflict-json@5.0.1", "", { "dependencies": { "json-parse-even-better-errors": "^5.0.0", "just-diff": "^6.0.0", "just-diff-apply": "^5.2.0" } }, "sha512-ZHEmNKMq1wyJXNwLxyHnluPfRAFSIliBvbK/UiOceROt4Xh9Pz0fq49NytIaeaCUf5VR86hwQ/34FCcNU5/LKQ=="],
|
||||
|
||||
"npm/@npmcli/arborist/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/@npmcli/arborist/ssri": ["ssri@13.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ=="],
|
||||
|
||||
"npm/@npmcli/config/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="],
|
||||
|
||||
"npm/@npmcli/config/nopt": ["nopt@9.0.0", "", { "dependencies": { "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw=="],
|
||||
|
||||
"npm/@npmcli/config/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/@npmcli/git/@npmcli/promise-spawn": ["@npmcli/promise-spawn@9.0.1", "", { "dependencies": { "which": "^6.0.0" } }, "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q=="],
|
||||
|
||||
"npm/@npmcli/git/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="],
|
||||
|
||||
"npm/@npmcli/git/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/@npmcli/git/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
|
||||
|
||||
"npm/@npmcli/map-workspaces/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
|
||||
|
||||
"npm/@npmcli/metavuln-calculator/json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="],
|
||||
|
||||
"npm/@npmcli/metavuln-calculator/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/@npmcli/package-json/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
|
||||
|
||||
"npm/@npmcli/package-json/json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="],
|
||||
|
||||
"npm/@npmcli/package-json/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/@npmcli/run-script/@npmcli/promise-spawn": ["@npmcli/promise-spawn@9.0.1", "", { "dependencies": { "which": "^6.0.0" } }, "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q=="],
|
||||
|
||||
"npm/@npmcli/run-script/node-gyp": ["node-gyp@12.4.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "tar": "^7.5.4", "tinyglobby": "^0.2.12", "undici": "^6.25.0", "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw=="],
|
||||
|
||||
"npm/@npmcli/run-script/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/@sigstore/sign/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/bin-links/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/cacache/@npmcli/fs": ["@npmcli/fs@5.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og=="],
|
||||
|
||||
"npm/cacache/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
|
||||
|
||||
"npm/cacache/ssri": ["ssri@13.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ=="],
|
||||
|
||||
"npm/cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"npm/encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
||||
|
||||
"npm/init-package-json/read": ["read@5.0.1", "", { "dependencies": { "mute-stream": "^3.0.0" } }, "sha512-+nsqpqYkkpet2UVPG8ZiuE8d113DK4vHYEoEhcrXBAlPiq6di7QRTuNiKQAbaRYegobuX2BpZ6QjanKOXnJdTA=="],
|
||||
|
||||
"npm/init-package-json/validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="],
|
||||
|
||||
"npm/libnpmexec/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/libnpmexec/read": ["read@5.0.1", "", { "dependencies": { "mute-stream": "^3.0.0" } }, "sha512-+nsqpqYkkpet2UVPG8ZiuE8d113DK4vHYEoEhcrXBAlPiq6di7QRTuNiKQAbaRYegobuX2BpZ6QjanKOXnJdTA=="],
|
||||
|
||||
"npm/libnpmpublish/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/libnpmpublish/ssri": ["ssri@13.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ=="],
|
||||
|
||||
"npm/libnpmversion/json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="],
|
||||
|
||||
"npm/libnpmversion/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/make-fetch-happen/@npmcli/redact": ["@npmcli/redact@4.0.0", "", {}, "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q=="],
|
||||
|
||||
"npm/make-fetch-happen/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/make-fetch-happen/ssri": ["ssri@13.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ=="],
|
||||
|
||||
"npm/minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"npm/minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen": ["make-fetch-happen@14.0.3", "", { "dependencies": { "@npmcli/agent": "^3.0.0", "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", "ssri": "^12.0.0" } }, "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ=="],
|
||||
|
||||
"npm/npm-package-arg/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/npm-package-arg/validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="],
|
||||
|
||||
"npm/npm-packlist/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/npm-pick-manifest/npm-install-checks": ["npm-install-checks@8.0.0", "", { "dependencies": { "semver": "^7.1.1" } }, "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA=="],
|
||||
|
||||
"npm/npm-profile/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/npm-registry-fetch/@npmcli/redact": ["@npmcli/redact@4.0.0", "", {}, "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q=="],
|
||||
|
||||
"npm/npm-registry-fetch/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/pacote/@npmcli/promise-spawn": ["@npmcli/promise-spawn@9.0.1", "", { "dependencies": { "which": "^6.0.0" } }, "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q=="],
|
||||
|
||||
"npm/pacote/proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"npm/pacote/ssri": ["ssri@13.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ=="],
|
||||
|
||||
"npm/promzard/read": ["read@5.0.1", "", { "dependencies": { "mute-stream": "^3.0.0" } }, "sha512-+nsqpqYkkpet2UVPG8ZiuE8d113DK4vHYEoEhcrXBAlPiq6di7QRTuNiKQAbaRYegobuX2BpZ6QjanKOXnJdTA=="],
|
||||
|
||||
"npm/wrap-ansi/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
"npm/wrap-ansi/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
||||
|
||||
"npm/wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||
|
||||
"ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||
@@ -5640,6 +6102,44 @@
|
||||
|
||||
"metro/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"npm/@npmcli/arborist/nopt/abbrev": ["abbrev@4.0.0", "", {}, "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA=="],
|
||||
|
||||
"npm/@npmcli/arborist/parse-conflict-json/json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="],
|
||||
|
||||
"npm/@npmcli/config/nopt/abbrev": ["abbrev@4.0.0", "", {}, "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA=="],
|
||||
|
||||
"npm/@npmcli/git/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
|
||||
|
||||
"npm/@npmcli/run-script/@npmcli/promise-spawn/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
|
||||
|
||||
"npm/@npmcli/run-script/node-gyp/nopt": ["nopt@9.0.0", "", { "dependencies": { "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw=="],
|
||||
|
||||
"npm/@npmcli/run-script/node-gyp/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
|
||||
|
||||
"npm/cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"npm/init-package-json/read/mute-stream": ["mute-stream@3.0.0", "", {}, "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw=="],
|
||||
|
||||
"npm/libnpmexec/read/mute-stream": ["mute-stream@3.0.0", "", {}, "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw=="],
|
||||
|
||||
"npm/minipass-flush/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"npm/minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/@npmcli/agent": ["@npmcli/agent@3.0.0", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache": ["cacache@19.0.1", "", { "dependencies": { "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^12.0.0", "tar": "^7.4.3", "unique-filename": "^4.0.0" } }, "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/minipass-fetch": ["minipass-fetch@4.0.1", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^3.0.1" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ=="],
|
||||
|
||||
"npm/pacote/@npmcli/promise-spawn/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
|
||||
|
||||
"npm/promzard/read/mute-stream": ["mute-stream@3.0.0", "", {}, "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw=="],
|
||||
|
||||
"npm/wrap-ansi/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"npm/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"ora/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
@@ -5710,6 +6210,22 @@
|
||||
|
||||
"log-symbols/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
|
||||
"npm/@npmcli/run-script/@npmcli/promise-spawn/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
|
||||
|
||||
"npm/@npmcli/run-script/node-gyp/nopt/abbrev": ["abbrev@4.0.0", "", {}, "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA=="],
|
||||
|
||||
"npm/@npmcli/run-script/node-gyp/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/minipass-fetch/minipass-sized": ["minipass-sized@1.0.3", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="],
|
||||
|
||||
"npm/pacote/@npmcli/promise-spawn/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
|
||||
|
||||
"ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
|
||||
"workbox-build/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
@@ -5725,5 +6241,29 @@
|
||||
"@react-native/metro-config/metro-config/metro/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"@react-native/metro-config/metro-config/metro/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/minipass-fetch/minipass-sized/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/minipass-fetch/minipass-sized/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"npm/node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -63,7 +63,7 @@
|
||||
"release": "bun scripts/release.mjs",
|
||||
"publish:stores": "bun scripts/store-delivery.mjs",
|
||||
"test:desktop:sidecar": "bun scripts/test-desktop-sidecar.mjs",
|
||||
"test:desktop": "bun test apps/desktop/src/main/account-scope.test.mjs apps/desktop/src/main/app-protocol.test.mjs apps/desktop/src/main/child-process-start.test.mjs apps/desktop/src/main/clipboard-write.test.mjs apps/desktop/src/main/desktop-diagnostics.test.mjs apps/desktop/src/main/desktop-menu.test.mjs apps/desktop/src/main/desktop-update-flow.test.mjs apps/desktop/src/main/diagnostic-log.test.mjs apps/desktop/src/main/file-association.test.mjs apps/desktop/src/main/wechat-chat-archive.test.mjs apps/desktop/src/main/wechat-share-import.test.mjs apps/desktop/src/main/share-extension-registration.test.mjs apps/desktop/src/main/windows-share-menu.test.mjs apps/desktop/src/main/file-permissions.test.mjs apps/desktop/src/main/installation-location.test.mjs apps/desktop/src/main/local-data-reset.test.mjs apps/desktop/src/main/ai-direct.test.mjs apps/desktop/src/main/plugin-public-network.test.mjs apps/desktop/src/main/renderer-recovery.test.mjs apps/desktop/src/main/renderer-hibernate.test.mjs apps/desktop/src/main/renderer-startup-guard.test.mjs apps/desktop/src/main/renderer-storage-migration.test.mjs apps/desktop/src/main/resource-request.test.mjs apps/desktop/src/main/resource-url.test.mjs apps/desktop/src/main/scheduled-task-scheduler.test.mjs apps/desktop/src/main/screenshot-capture.test.mjs apps/desktop/src/main/staged-resource.test.mjs apps/desktop/src/main/staged-resource-alias.test.mjs apps/desktop/src/main/tray-icon.test.mjs apps/desktop/src/main/user-data-directory.test.mjs apps/desktop/src/main/window-open-policy.test.mjs apps/desktop/src/main/window-visibility.test.mjs apps/desktop/src/main/windows-update-trust.test.mjs apps/web/src/lib/api.test.mjs apps/web/src/lib/app-page-path.test.mjs apps/web/src/lib/clipboard.test.mjs apps/web/src/lib/desktop-renderer-ready.test.mjs apps/web/src/lib/desktop-workspace-restore.test.mjs apps/web/src/lib/desktop-repository.test.mjs apps/web/src/lib/desktop-resources.test.mjs apps/web/src/lib/desktop-sync.test.mjs apps/web/src/lib/local-mirror.test.mjs apps/web/src/lib/repository.test.mjs apps/web/src/lib/runtime.test.mjs apps/web/src/lib/screenshot-import.test.mjs apps/web/src/lib/wechat-chat-import.test.mjs apps/web/src/lib/shared-file-import.test.mjs apps/web/src/lib/sync-queue.test.mjs && bun test --cwd apps/desktop src/main/acp-host.test.mjs && bun run test:desktop:sidecar",
|
||||
"test:desktop": "bun test apps/desktop/src/main/account-scope.test.mjs apps/desktop/src/main/app-protocol.test.mjs apps/desktop/src/main/child-process-start.test.mjs apps/desktop/src/main/clipboard-write.test.mjs apps/desktop/src/main/desktop-diagnostics.test.mjs apps/desktop/src/main/desktop-menu.test.mjs apps/desktop/src/main/desktop-update-flow.test.mjs apps/desktop/src/main/diagnostic-log.test.mjs apps/desktop/src/main/file-association.test.mjs apps/desktop/src/main/wechat-chat-archive.test.mjs apps/desktop/src/main/wechat-share-import.test.mjs apps/desktop/src/main/share-extension-registration.test.mjs apps/desktop/src/main/windows-share-menu.test.mjs apps/desktop/src/main/file-permissions.test.mjs apps/desktop/src/main/installation-location.test.mjs apps/desktop/src/main/local-data-reset.test.mjs apps/desktop/src/main/ai-direct.test.mjs apps/desktop/src/main/plugin-public-network.test.mjs apps/desktop/src/main/renderer-recovery.test.mjs apps/desktop/src/main/renderer-hibernate.test.mjs apps/desktop/src/main/renderer-startup-guard.test.mjs apps/desktop/src/main/renderer-storage-migration.test.mjs apps/desktop/src/main/resource-request.test.mjs apps/desktop/src/main/resource-url.test.mjs apps/desktop/src/main/scheduled-task-scheduler.test.mjs apps/desktop/src/main/screenshot-capture.test.mjs apps/desktop/src/main/staged-resource.test.mjs apps/desktop/src/main/staged-resource-alias.test.mjs apps/desktop/src/main/tray-icon.test.mjs apps/desktop/src/main/user-data-directory.test.mjs apps/desktop/src/main/window-open-policy.test.mjs apps/desktop/src/main/window-visibility.test.mjs apps/desktop/src/main/windows-update-trust.test.mjs apps/web/src/lib/api.test.mjs apps/web/src/lib/app-page-path.test.mjs apps/web/src/lib/clipboard.test.mjs apps/web/src/lib/desktop-renderer-ready.test.mjs apps/web/src/lib/desktop-workspace-restore.test.mjs apps/web/src/lib/desktop-repository.test.mjs apps/web/src/lib/desktop-resources.test.mjs apps/web/src/lib/desktop-sync.test.mjs apps/web/src/lib/local-mirror.test.mjs apps/web/src/lib/repository.test.mjs apps/web/src/lib/runtime.test.mjs apps/web/src/lib/screenshot-import.test.mjs apps/web/src/lib/wechat-chat-import.test.mjs apps/web/src/lib/shared-file-import.test.mjs apps/web/src/lib/sync-queue.test.mjs && bun test --cwd apps/desktop src/main/acp-adapter-manager.test.mjs src/main/acp-host.test.mjs && bun run test:desktop:sidecar",
|
||||
"verify:desktop-renderer": "bun scripts/verify-desktop-renderer.mjs",
|
||||
"verify:renderer-origin-migration": "bun run --cwd apps/desktop verify-origin-migration",
|
||||
"verify:desktop-cross-version-startup": "bun scripts/verify-desktop-cross-version-startup.mjs",
|
||||
|
||||
@@ -1375,23 +1375,41 @@ export const enUS = {
|
||||
builtin: "Built-in companion",
|
||||
builtinHint: "Uses the AI model configured below.",
|
||||
local: "Local ACP agent",
|
||||
localHint: "Codex or Antigravity on this computer. EdgeEver does not grant the agent your notes folder or a terminal.",
|
||||
localHint: "Codex, Antigravity, Grok Build, or WorkBuddy on this computer. EdgeEver does not provide your notes folder or a terminal through ACP; the agent's own tool permissions follow its configuration.",
|
||||
adapter: "Agent",
|
||||
codex: "Codex",
|
||||
antigravity: "Antigravity",
|
||||
claudeCode: "Claude Code",
|
||||
workbuddy: "WorkBuddy",
|
||||
workbuddyCn: "WorkBuddy China",
|
||||
workbuddyIntl: "WorkBuddy International",
|
||||
grokBuild: "Grok Build",
|
||||
pathLabel: "Antigravity executable",
|
||||
pathPlaceholder: "/absolute/path/to/antigravity-acp",
|
||||
pathHint: "Absolute path to an executable file. EdgeEver does not download agents or search application folders.",
|
||||
pathHint: "Enter the absolute path of an existing Antigravity ACP executable, or let EdgeEver install one on demand.",
|
||||
install: "Install connector",
|
||||
installHint: "When a local agent is detected, its connector downloads from the official source. This may exceed 100 MiB; updates are checked automatically.",
|
||||
grokBuildMissingHint: "Grok Build includes ACP. Install the Grok CLI first; EdgeEver uses the local grok command without a separate connector download.",
|
||||
grokBuildNotFound: "Grok CLI not found",
|
||||
workbuddyNotFound: "WorkBuddy ACP program not found",
|
||||
workbuddyMissingHint: "Install the WorkBuddy desktop app or CodeBuddy CLI. EdgeEver uses its built-in ACP; China and International accounts sign in separately.",
|
||||
workbuddyCnLoginHint: "ACP sign-in is separate from the WorkBuddy desktop app. Use WeChat or your organization's sign-in method for China.",
|
||||
workbuddyIntlLoginHint: "ACP sign-in is separate from the WorkBuddy desktop app. Use Google/GitHub or your organization's sign-in method for International.",
|
||||
installing: "Installing and checking…",
|
||||
installFailed: "Installation or connection check failed. The previous version was kept.",
|
||||
updateFailed: "Automatic update failed. The previous version remains in use.",
|
||||
authenticating: "Signing in…",
|
||||
authenticateWith: "Sign in with {{method}}",
|
||||
loginUnavailable: "This ACP connector requires authentication but provides no ACP sign-in method. Authenticate in the agent, then check the connection again.",
|
||||
autoUpdated: "Auto-updated",
|
||||
probe: "Check connection",
|
||||
probing: "Checking…",
|
||||
probeHint: "Opens a temporary session and closes it. Your notes are not sent.",
|
||||
notProbed: "Not checked yet",
|
||||
invalidPath: "Enter an absolute path to an executable file.",
|
||||
states: {
|
||||
not_installed: "Not installed",
|
||||
not_installed: "ACP connector not found",
|
||||
installing: "Installing the ACP connector automatically…",
|
||||
needs_login: "Needs login",
|
||||
available: "Session available",
|
||||
failed: "Connection failed",
|
||||
|
||||
@@ -1375,23 +1375,41 @@ export const ja = {
|
||||
builtin: "内蔵コンパニオン",
|
||||
builtinHint: "下で設定した AI モデルを使います。",
|
||||
local: "ローカル ACP エージェント",
|
||||
localHint: "このコンピュータ上の Codex または Antigravity です。EdgeEver はノートのフォルダもターミナルも渡しません。",
|
||||
localHint: "このコンピュータ上の Codex、Antigravity、Grok Build、または WorkBuddy です。EdgeEver は ACP 経由でノートのフォルダやターミナルを提供しません。エージェント自身のツール権限はその設定に従います。",
|
||||
adapter: "エージェント",
|
||||
codex: "Codex",
|
||||
antigravity: "Antigravity",
|
||||
claudeCode: "Claude Code",
|
||||
workbuddy: "WorkBuddy",
|
||||
workbuddyCn: "WorkBuddy 中国版",
|
||||
workbuddyIntl: "WorkBuddy 国際版",
|
||||
grokBuild: "Grok Build",
|
||||
pathLabel: "Antigravity の実行ファイル",
|
||||
pathPlaceholder: "/absolute/path/to/antigravity-acp",
|
||||
pathHint: "実行ファイルの絶対パスを入力します。EdgeEver はエージェントをダウンロードせず、アプリケーションフォルダも検索しません。",
|
||||
pathHint: "既存の Antigravity ACP 実行ファイルの絶対パスを入力するか、EdgeEver で必要時にインストールします。",
|
||||
install: "接続コンポーネントをインストール",
|
||||
installHint: "ローカルのエージェントを検出すると、公式配布元からダウンロードします。100 MiB を超える場合があり、インストール後は更新を自動確認します。",
|
||||
grokBuildMissingHint: "Grok Build には ACP が内蔵されています。先に Grok CLI をインストールしてください。EdgeEver はローカルの grok コマンドを使用し、別の接続コンポーネントはダウンロードしません。",
|
||||
grokBuildNotFound: "Grok CLI が見つかりません",
|
||||
workbuddyNotFound: "WorkBuddy の ACP プログラムが見つかりません",
|
||||
workbuddyMissingHint: "WorkBuddy デスクトップアプリまたは CodeBuddy CLI をインストールしてください。内蔵 ACP を使用し、中国版と国際版は別々にログインします。",
|
||||
workbuddyCnLoginHint: "ACP ログインは WorkBuddy デスクトップアプリとは別です。中国版は WeChat または組織指定の方法を使用してください。",
|
||||
workbuddyIntlLoginHint: "ACP ログインは WorkBuddy デスクトップアプリとは別です。国際版は Google/GitHub または組織指定の方法を使用してください。",
|
||||
installing: "インストールして確認中…",
|
||||
installFailed: "インストールまたは接続確認に失敗しました。以前のバージョンは保持されています。",
|
||||
updateFailed: "自動更新に失敗しました。以前のバージョンを継続して使用します。",
|
||||
authenticating: "ログイン中…",
|
||||
authenticateWith: "{{method}} でログイン",
|
||||
loginUnavailable: "この ACP 接続コンポーネントは認証が必要ですが、ACP のログイン方法を提供していません。エージェント側で認証してから再確認してください。",
|
||||
autoUpdated: "自動更新",
|
||||
probe: "接続を確認",
|
||||
probing: "確認中…",
|
||||
probeHint: "一時的なセッションを開いてすぐ閉じます。ノートは送信しません。",
|
||||
notProbed: "未確認",
|
||||
invalidPath: "実行ファイルの絶対パスを入力してください。",
|
||||
states: {
|
||||
not_installed: "未インストール",
|
||||
not_installed: "ACP 接続コンポーネントが見つかりません",
|
||||
installing: "ACP 接続コンポーネントを自動インストール中…",
|
||||
needs_login: "ログインが必要",
|
||||
available: "セッションを利用できます",
|
||||
failed: "接続に失敗しました",
|
||||
|
||||
@@ -1375,23 +1375,41 @@ export const zhCN = {
|
||||
builtin: "内置助手",
|
||||
builtinHint: "使用下方配置的 AI 模型。",
|
||||
local: "本地 ACP 代理",
|
||||
localHint: "使用这台电脑上的 Codex 或 Antigravity。EdgeEver 不会把笔记目录或终端交给代理。",
|
||||
localHint: "使用这台电脑上的 Codex、Antigravity、Grok Build 或 WorkBuddy。EdgeEver 不通过 ACP 提供笔记目录或终端;代理自身的工具权限由其配置决定。",
|
||||
adapter: "代理",
|
||||
codex: "Codex",
|
||||
antigravity: "Antigravity",
|
||||
claudeCode: "Claude Code",
|
||||
workbuddy: "WorkBuddy",
|
||||
workbuddyCn: "WorkBuddy 国内版",
|
||||
workbuddyIntl: "WorkBuddy 国际版",
|
||||
grokBuild: "Grok Build",
|
||||
pathLabel: "Antigravity 可执行文件",
|
||||
pathPlaceholder: "/absolute/path/to/antigravity-acp",
|
||||
pathHint: "填写可执行文件的绝对路径。EdgeEver 不会下载代理,也不会搜索应用程序目录。",
|
||||
pathHint: "如需使用已有的 Antigravity ACP 程序,可填写其绝对路径;也可以让 EdgeEver 按需安装。",
|
||||
install: "安装连接组件",
|
||||
installHint: "检测到本机 Agent 后会从官方来源下载,可能超过 100 MiB;安装后会自动检查更新。",
|
||||
grokBuildMissingHint: "Grok Build 已内置 ACP。请先安装 Grok CLI;EdgeEver 会使用本机的 grok 命令,无需下载单独适配器。",
|
||||
grokBuildNotFound: "未找到 Grok CLI",
|
||||
workbuddyNotFound: "未找到 WorkBuddy 的 ACP 程序",
|
||||
workbuddyMissingHint: "请安装 WorkBuddy 桌面版或 CodeBuddy CLI。EdgeEver 使用其内置 ACP,国内版和国际版分别登录。",
|
||||
workbuddyCnLoginHint: "ACP 登录与 WorkBuddy 桌面 App 的登录分开。国内版请使用微信或组织指定的登录方式。",
|
||||
workbuddyIntlLoginHint: "ACP 登录与 WorkBuddy 桌面 App 的登录分开。国际版请使用 Google/GitHub 或组织指定的登录方式。",
|
||||
installing: "正在安装并检查…",
|
||||
installFailed: "安装或连接检查失败,原版本已保留。",
|
||||
updateFailed: "自动更新失败,正在继续使用原版本。",
|
||||
authenticating: "正在登录…",
|
||||
authenticateWith: "使用 {{method}} 登录",
|
||||
loginUnavailable: "这个 ACP 连接组件要求认证,但没有提供 ACP 登录入口。请在对应代理中完成认证后重试连接。",
|
||||
autoUpdated: "自动更新",
|
||||
probe: "检查连接",
|
||||
probing: "正在检查…",
|
||||
probeHint: "会临时建立会话并立即关闭,不会发送你的笔记。",
|
||||
notProbed: "尚未检查",
|
||||
invalidPath: "请填写可执行文件的绝对路径。",
|
||||
states: {
|
||||
not_installed: "未安装",
|
||||
not_installed: "未找到 ACP 连接组件",
|
||||
installing: "正在自动安装 ACP 连接组件…",
|
||||
needs_login: "需要登录",
|
||||
available: "会话可用",
|
||||
failed: "连接失败",
|
||||
|
||||
Reference in new issue
Block a user