Files
Nivora/codex/patch-computer-use.js
T
Александр f405ae2bcf feat: create autonomous Nivora package repository
Maintain a validated cross-distribution package catalog.
Automate upstream updates, isolated builds, diagnostics, and direct publication.
Build the official GitHub Desktop sources for Linux with working OAuth.
2026-07-25 00:49:32 +10:00

140 lines
4.3 KiB
JavaScript
Executable File

#!/usr/bin/env node
"use strict";
// This file only adapts upstream patch discovery to the current hashed bundle
// name. Computer Use behavior remains sourced from codex-desktop-linux.
const fs = require("node:fs");
const path = require("node:path");
const linuxPortRoot = path.resolve(process.argv[2] ?? "");
const extractedApp = path.resolve(process.argv[3] ?? "");
if (!fs.existsSync(linuxPortRoot) || !fs.existsSync(extractedApp)) {
console.error("usage: patch-computer-use.js LINUX_PORT_ROOT EXTRACTED_APP");
process.exit(2);
}
process.env.CODEX_LINUX_ENABLE_COMPUTER_USE_UI = "1";
const { patchExtractedApp } = require(
path.join(linuxPortRoot, "scripts/patches/runner.js"),
);
const implementation = require(
path.join(linuxPortRoot, "scripts/patches/impl/computer-use.js"),
);
const coreRoot = path.join(
linuxPortRoot,
"scripts/patches/core/all-linux",
);
patchExtractedApp(extractedApp, {
corePatchRoot: path.join(coreRoot, "main-process/computer-use"),
});
patchExtractedApp(extractedApp, {
corePatchRoot: path.join(coreRoot, "webview/computer-use-ui"),
});
const assetsDirectory = path.join(extractedApp, "webview/assets");
const javaScriptAssets = fs.readdirSync(assetsDirectory)
.filter((name) => name.endsWith(".js"))
.map((name) => path.join(assetsDirectory, name));
function applyToUniqueAsset(label, patchFunction, alreadyPatched, isCandidate) {
const changed = [];
const existing = [];
for (const target of javaScriptAssets) {
const source = fs.readFileSync(target, "utf8");
if (alreadyPatched(source)) {
existing.push(target);
continue;
}
if (!isCandidate(source)) {
continue;
}
const patched = patchFunction(source);
if (patched !== source) {
changed.push({ target, patched });
}
}
if (existing.length === 1 && changed.length === 0) {
return;
}
if (existing.length !== 0 || changed.length !== 1) {
throw new Error(
`${label}: expected one target, found existing=${existing.length}, changed=${changed.length}`,
);
}
fs.writeFileSync(changed[0].target, changed[0].patched, "utf8");
console.log(`${label}: ${path.basename(changed[0].target)}`);
}
applyToUniqueAsset(
"Linux Computer Use host platform",
implementation.applyLinuxComputerUseHostPlatformPatch,
(source) =>
/featureName:`computer_use`[\s\S]{0,2200}?isHostCompatiblePlatform:[A-Za-z_$][\w$]*===`linux`\|\|/.test(
source,
),
(source) => source.includes("featureName:`computer_use`"),
);
applyToUniqueAsset(
"Linux Computer Use install flow",
implementation.applyLinuxComputerUseInstallFlowPatch,
(source) =>
source.includes("plugin detail query requires pluginName") &&
/let [A-Za-z_$][\w$]*=[A-Za-z_$][\w$]*&&[A-Za-z_$][\w$]*!==`computer-use`,/.test(
source,
),
(source) => source.includes("plugin detail query requires pluginName"),
);
const iconCandidates = fs.readdirSync(assetsDirectory)
.filter((name) => /^computer-use-plugin-icon-[^.]+\.png$/.test(name))
.filter((name) => name !== "computer-use-plugin-icon-linux.png");
if (iconCandidates.length !== 1) {
throw new Error(
`Computer Use icon: expected one source, found ${iconCandidates.length}`,
);
}
let iconReferences = 0;
for (const target of javaScriptAssets) {
const source = fs.readFileSync(target, "utf8");
if (!source.includes("computer-use-plugin-icon-linux.png")) {
continue;
}
fs.writeFileSync(
target,
source.replaceAll(
"computer-use-plugin-icon-linux.png",
iconCandidates[0],
),
"utf8",
);
iconReferences += 1;
}
if (iconReferences !== 1) {
throw new Error(
`Computer Use icon: expected one patched reference, found ${iconReferences}`,
);
}
const mainBundle = fs.readdirSync(path.join(extractedApp, ".vite/build"))
.filter((name) => /^main-[^.]+\.js$/.test(name));
if (mainBundle.length !== 1) {
throw new Error(`main bundle: expected one target, found ${mainBundle.length}`);
}
const mainSource = fs.readFileSync(
path.join(extractedApp, ".vite/build", mainBundle[0]),
"utf8",
);
for (const marker of [
"codexLinuxNativeDesktopApps(",
"codexLinuxRegisterComputerUseCursorHandler",
"platform!==`darwin`&&",
]) {
if (!mainSource.includes(marker)) {
throw new Error(`main bundle: missing upstream marker ${marker}`);
}
}
console.log("Linux Computer Use upstream patches applied");