app
Adom Bridge
Public Made by Adomby adom
Adom Bridge unleashes your AI onto your full PC: full power, full safety. The AI breaks out of the container it runs in and onto your real machine, managing and running your entire laptop as you: launch apps, move files, drive any window, control KiCad, Fusion 360 or your real signed-in browser. Works with any AI, cloud or local (Claude Desktop, Claude Code, Codex), no Hydrogen required. Bridge and its bridges are an operating system for AI, with managed Node and Python runtimes, and a human-onl
← Commit history
demo: stage large part files through write_file_chunk (ab#90) - a 3.7 MB .step now transfers in ~1 MB chunks instead of 413ing
1 file changed
+52−7
web-control-demo.html+52−7@@ -1354,7 +1354,7 @@ for (const w of mine) { if (note) { note.innerHTML = esc(PART.kind) + " - .step is <strong>" + fmtKB(PART.stepBytes) + "</strong>" + (PART.stepBytes > 2000000- ? ' <span style="color:#d29922">- over the ~2.5 MB /command body cap, so staging the 3D model is expected to 413 (ab#90); the symbol and footprint still work</span>'+ ? ' <span style="color:#3fb950">- staged in ~1 MB chunks via write_file_chunk (ab#90), so the 3D model transfers fine</span>' : ""); } }@@ -1396,13 +1396,58 @@ for (const w of mine) { return btoa(out); } function stageFail(msg) { var e = new Error(msg); e.staged = true; return e; }- // Write one part file onto the PC via ab's write_file; resolves the ABSOLUTE path.+ // Write one part file onto the PC; resolves the ABSOLUTE path.+ //+ // Small files go through write_file in a single request. Anything big enough to+ // threaten the /command body cap goes through write_file_chunk instead+ // (ab 2.0.72, ab#90): base64 inflates ~33%, and a body over ~2.5 MB is refused+ // with 413 - which is why a real .step 3D model could not be staged at all+ // before. The chunked path sends ~1 MB of RAW bytes per request, so the request+ // size stops depending on the file size.+ var CHUNK_RAW = 1024 * 1024; // ~1.37 MB of base64 per request+ var SINGLE_SHOT_MAX = 1024 * 1024; // above this, chunk it+ function stageFile(c, name, b64) {- return postSelf("write_file", { path: PART.dir + name, content: b64, encoding: "base64" }).then(function (r) {- if (!(r.s === 200 && r.j && r.j.success)) throw stageFail("write_file " + name + ": " + ((r.j && (r.j.error || r.j.errorCode)) || r.s));- clog(c, " staged " + name + " -> " + r.j.path);- return r.j.path;- });+ var path = PART.dir + name;+ // b64 length -> raw bytes (4 base64 chars encode 3 bytes)+ var rawBytes = Math.floor(b64.length * 3 / 4);+ if (rawBytes <= SINGLE_SHOT_MAX) {+ return postSelf("write_file", { path: path, content: b64, encoding: "base64" }).then(function (r) {+ if (!(r.s === 200 && r.j && r.j.success)) throw stageFail("write_file " + name + ": " + ((r.j && (r.j.error || r.j.errorCode)) || r.s));+ clog(c, " staged " + name + " -> " + r.j.path);+ return r.j.path;+ });+ }+ return stageFileChunked(c, name, path, b64, rawBytes);+ }++ // Chunk on BASE64 boundaries: 4 base64 chars == 3 raw bytes, so slicing at a+ // multiple of 4 decodes to exactly the bytes we intend and every chunk's offset+ // is computable without decoding anything client-side.+ function stageFileChunked(c, name, path, b64, rawBytes) {+ var b64Step = Math.floor(CHUNK_RAW / 3) * 4;+ var total = Math.ceil(b64.length / b64Step);+ clog(c, " " + name + " is " + fmtKB(rawBytes) + " - too big for one /command body, sending " + total + " chunks via write_file_chunk");+ var i = 0, offset = 0, finalPath = path;+ function next() {+ if (i >= total) return finalPath;+ var slice = b64.substr(i * b64Step, b64Step);+ var isLast = (i === total - 1);+ return postSelf("write_file_chunk", {+ path: path, dataB64: slice, offset: offset, "final": isLast+ }).then(function (r) {+ if (!(r.s === 200 && r.j && r.j.success)) {+ throw stageFail("write_file_chunk " + name + " @" + offset + ": " + ((r.j && (r.j.error || r.j.errorCode)) || r.s));+ }+ finalPath = r.j.path || finalPath;+ offset = r.j.nextOffset;+ i++;+ if (isLast) clog(c, " staged " + name + " -> " + finalPath + " (" + fmtKB(r.j.size) + ", sha " + String(r.j.sha256 || "").slice(0, 12) + ")");+ else if (i % 2 === 0 || total <= 4) clog(c, " chunk " + i + "/" + total + " (" + fmtKB(offset) + " of " + fmtKB(rawBytes) + ")");+ return next();+ });+ }+ return Promise.resolve().then(next); } // KiCad component staging (the kicad-bridge's own recipe, adom-bridge-sdk#4