feat: Electrobun Svelte+WGPU prototype (Dawn GPU confirmed on Linux)
- Svelte 5 frontend with Catppuccin Mocha theme, 2 project cards - Electrobun v1.16.0 with bundleWGPU: true (Dawn on Linux x64) - WebKitGTK webview + WGPU surface coexistence confirmed - CPU: 6.5% idle (CSS animation + WebKitGTK overhead) - Port 9760 for dev server (project convention)
This commit is contained in:
parent
1f20fc460e
commit
cfc135ffaf
29 changed files with 1106 additions and 1020 deletions
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>launcher</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>dev.agor.orchestrator</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>AgentOrchestrator-dev</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.0.1</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>AppIcon</string>
|
||||
</dict>
|
||||
</plist>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Svelte App</title>
|
||||
<script type="module" crossorigin src="/assets/index-D-cE0ySN.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DpJ88YKe.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"defaultRenderer":"native","availableRenderers":["native"],"runtime":{},"bunVersion":"1.3.9"}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
// @bun
|
||||
var __require = import.meta.require;
|
||||
|
||||
// src/launcher/main.ts
|
||||
import { join, dirname, resolve } from "path";
|
||||
import { dlopen, suffix, ptr, toArrayBuffer } from "bun:ffi";
|
||||
import { existsSync, writeFileSync } from "fs";
|
||||
import { tmpdir } from "os";
|
||||
var pathToMacOS = dirname(process.argv0);
|
||||
var libPath = join(pathToMacOS, `libNativeWrapper.${suffix}`);
|
||||
var absoluteLibPath = resolve(libPath);
|
||||
function main() {
|
||||
let channel = "";
|
||||
let identifier = "";
|
||||
let name = "";
|
||||
try {
|
||||
const pathToLauncherBin2 = process.argv0;
|
||||
const pathToBinDir2 = dirname(pathToLauncherBin2);
|
||||
const versionJsonPath = join(pathToBinDir2, "..", "Resources", "version.json");
|
||||
if (existsSync(versionJsonPath)) {
|
||||
const versionInfo = __require(versionJsonPath);
|
||||
if (versionInfo.identifier) {
|
||||
identifier = versionInfo.identifier;
|
||||
}
|
||||
if (versionInfo.name) {
|
||||
name = versionInfo.name;
|
||||
}
|
||||
if (versionInfo.channel) {
|
||||
channel = versionInfo.channel;
|
||||
}
|
||||
console.log(`[LAUNCHER] Loaded identifier: ${identifier}, name: ${name}, channel: ${channel}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[LAUNCHER] Warning: Could not read version.json:`, error);
|
||||
}
|
||||
if (process.platform === "linux") {
|
||||
const cefLibs = [
|
||||
join(pathToMacOS, "libcef.so"),
|
||||
join(pathToMacOS, "libvk_swiftshader.so")
|
||||
];
|
||||
const existingCefLibs = cefLibs.filter((lib2) => existsSync(lib2));
|
||||
if (existingCefLibs.length > 0 && !process.env["LD_PRELOAD"]) {
|
||||
console.error(`[LAUNCHER] ERROR: CEF libraries found but LD_PRELOAD not set!`);
|
||||
console.error(`[LAUNCHER] Please run through the wrapper script: ./run.sh`);
|
||||
console.error(`[LAUNCHER] Or set: LD_PRELOAD="${existingCefLibs.join(":")}" before starting.`);
|
||||
const { spawn } = __require("child_process");
|
||||
const env = { ...process.env, LD_PRELOAD: existingCefLibs.join(":") };
|
||||
const child = spawn(process.argv[0], process.argv.slice(1), {
|
||||
env,
|
||||
stdio: "inherit"
|
||||
});
|
||||
child.on("exit", (code) => process.exit(code ?? 1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
let lib;
|
||||
try {
|
||||
if (!process.env["LD_LIBRARY_PATH"]?.includes(".")) {
|
||||
process.env["LD_LIBRARY_PATH"] = `.${process.env["LD_LIBRARY_PATH"] ? ":" + process.env["LD_LIBRARY_PATH"] : ""}`;
|
||||
}
|
||||
lib = dlopen(libPath, {
|
||||
startEventLoop: {
|
||||
args: ["cstring", "cstring", "cstring"],
|
||||
returns: "void"
|
||||
},
|
||||
forceExit: {
|
||||
args: ["i32"],
|
||||
returns: "void"
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[LAUNCHER] Failed to load library: ${error.message}`);
|
||||
try {
|
||||
lib = dlopen(absoluteLibPath, {
|
||||
startEventLoop: {
|
||||
args: ["cstring", "cstring", "cstring"],
|
||||
returns: "void"
|
||||
},
|
||||
forceExit: {
|
||||
args: ["i32"],
|
||||
returns: "void"
|
||||
}
|
||||
});
|
||||
} catch (absError) {
|
||||
console.error(`[LAUNCHER] Library loading failed. Try running: ldd ${libPath}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
const pathToLauncherBin = process.argv0;
|
||||
const pathToBinDir = dirname(pathToLauncherBin);
|
||||
const resourcesDir = join(pathToBinDir, "..", "Resources");
|
||||
const asarPath = join(resourcesDir, "app.asar");
|
||||
const appFolderPath = join(resourcesDir, "app");
|
||||
let appEntrypointPath;
|
||||
if (existsSync(asarPath)) {
|
||||
console.log(`[LAUNCHER] Loading app code from ASAR: ${asarPath}`);
|
||||
let asarLibPath;
|
||||
let asarLib;
|
||||
if (process.platform === "win32") {
|
||||
asarLibPath = libPath;
|
||||
console.log(`[LAUNCHER] Using native wrapper's ASAR reader: ${asarLibPath}`);
|
||||
} else {
|
||||
asarLibPath = join(pathToMacOS, `libasar.${suffix}`);
|
||||
}
|
||||
try {
|
||||
asarLib = dlopen(asarLibPath, {
|
||||
asar_open: { args: ["cstring"], returns: "ptr" },
|
||||
asar_read_file: { args: ["ptr", "cstring", "ptr"], returns: "ptr" },
|
||||
asar_free_buffer: { args: ["ptr", "u64"], returns: "void" },
|
||||
asar_close: { args: ["ptr"], returns: "void" }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`[LAUNCHER] Failed to load ASAR library: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
const asarArchive = asarLib.symbols.asar_open(ptr(new Uint8Array(Buffer.from(asarPath + "\x00", "utf8"))));
|
||||
if (!asarArchive || asarArchive === 0n) {
|
||||
console.error(`[LAUNCHER] Failed to open ASAR archive at: ${asarPath}`);
|
||||
throw new Error("Failed to open ASAR archive");
|
||||
}
|
||||
const filePath = "bun/index.js";
|
||||
const sizeBuffer = new BigUint64Array(1);
|
||||
const fileDataPtr = asarLib.symbols.asar_read_file(asarArchive, ptr(new Uint8Array(Buffer.from(filePath + "\x00", "utf8"))), ptr(sizeBuffer));
|
||||
if (!fileDataPtr || fileDataPtr === 0n) {
|
||||
console.error(`[LAUNCHER] Failed to read ${filePath} from ASAR`);
|
||||
asarLib.symbols.asar_close(asarArchive);
|
||||
throw new Error(`Failed to read ${filePath} from ASAR`);
|
||||
}
|
||||
const fileSize = Number(sizeBuffer[0]);
|
||||
console.log(`[LAUNCHER] Read ${fileSize} bytes from ASAR for ${filePath}`);
|
||||
const arrayBuffer = toArrayBuffer(fileDataPtr, 0, fileSize);
|
||||
const fileData = Buffer.from(arrayBuffer);
|
||||
const systemTmpDir = tmpdir();
|
||||
const randomFileName = `electrobun-${Date.now()}-${Math.random().toString(36).substring(7)}.js`;
|
||||
appEntrypointPath = join(systemTmpDir, randomFileName);
|
||||
const wrappedFileData = `
|
||||
// Auto-delete temp file after Worker loads it
|
||||
const __tempFilePath = "${appEntrypointPath}";
|
||||
setTimeout(() => {
|
||||
try {
|
||||
require("fs").unlinkSync(__tempFilePath);
|
||||
console.log("[LAUNCHER] Deleted temp file:", __tempFilePath);
|
||||
} catch (error) {
|
||||
console.warn("[LAUNCHER] Failed to delete temp file:", error.message);
|
||||
}
|
||||
}, 100);
|
||||
|
||||
${fileData.toString("utf8")}
|
||||
`;
|
||||
writeFileSync(appEntrypointPath, wrappedFileData);
|
||||
console.log(`[LAUNCHER] Wrote app entrypoint to: ${appEntrypointPath}`);
|
||||
asarLib.symbols.asar_free_buffer(fileDataPtr, BigInt(fileSize));
|
||||
asarLib.symbols.asar_close(asarArchive);
|
||||
} else {
|
||||
console.log(`[LAUNCHER] Loading app code from flat files`);
|
||||
appEntrypointPath = join(appFolderPath, "bun", "index.js");
|
||||
}
|
||||
process.on("SIGINT", () => {});
|
||||
process.on("SIGTERM", () => {});
|
||||
new Worker(appEntrypointPath, {});
|
||||
lib.symbols.startEventLoop(ptr(new Uint8Array(Buffer.from(identifier + "\x00", "utf8"))), ptr(new Uint8Array(Buffer.from(name + "\x00", "utf8"))), ptr(new Uint8Array(Buffer.from(channel + "\x00", "utf8"))));
|
||||
lib.symbols.forceExit(0);
|
||||
}
|
||||
main();
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"version":"0.0.1","hash":"dev","channel":"dev","baseUrl":"","name":"AgentOrchestrator-dev","identifier":"dev.agor.orchestrator"}
|
||||
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/bspatch
Executable file
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/bspatch
Executable file
Binary file not shown.
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/bun
Executable file
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/bun
Executable file
Binary file not shown.
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/launcher
Executable file
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/launcher
Executable file
Binary file not shown.
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/libNativeWrapper.so
Executable file
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/libNativeWrapper.so
Executable file
Binary file not shown.
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/libasar.so
Executable file
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/libasar.so
Executable file
Binary file not shown.
Binary file not shown.
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/zig-zstd
Executable file
BIN
ui-electrobun/build/dev-linux-x64/AgentOrchestrator-dev/bin/zig-zstd
Executable file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue