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: dedupe repeated stepShot thumbnails (the same evidence rides every poll frame) and serve a favicon (pup flagged the page as an Adom app with none)
1 file changed
+15−3
web-control-demo.html+15−3@@ -3,7 +3,8 @@ <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" />-<title>Adom Bridge web control - local test harness</title>+<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath fill=%22%23fff%22 d=%22M12 2 3 21h4l5-11 5 11h4L12 2z%22/%3E%3C/svg%3E">+ <title>Adom Bridge web control - local test harness</title> <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEuklEQVR4nLWXT2xUVRTGf/e+13mddkrbaYf+AbRCBUGMogGMgDEGXBB1YVxoQlxgiBg34MaFCTHqVsW4EILGxIWy0kRNCAkRRFloNNUEW6UUWirt0HaY/pl2+mbee9fFmce00BkmtJzkzZ2Ze3PPd757znfuUxgDSsGpM+1EMvtwzSN4ns3dMNv2cNSf5GLH2PnUEMagABgb2E5f/9cQrCTrhouX1rnnyRh1wOj/WH//S9S3n1Nc+KONwcG/iDUmSCY9IhGNUmZpvRfMGEUuF9DSajORHuW+VQ/bXBx4neZEguEhD8e5O9SHphQ4juZa0qOtPUHflf0apTYxM21wHHVXnc81x1HMTBuU2iQR2/binBsjD0iUqoLtbFthjFo85caAZUGiGTSQnYX0RBHM7XAs2nlzE+RcOHlaMn3dati4AVIpmJq+LYg7B2AMNDbA0DAcPASzOaiywfdgw3o4dACa4jCWAq1LblN6phKLReHwUXHw0FroWAWrO+DyJdh7UJhZFivmx5IBCM99fBJG0tC6HLI5CAKZ6+gA34f3D0O8qexWi2NAa7CtWyOcnYUVbXC+B853Q2N9SRYWB6CcKQWWDRcuQbS6JIDKk9Dc+JBh7oZKIV2lkPHGQHUE8p70lKD0trcHEDqyrPn/RaOS9fk8ZLPye64Y9Q1AdTXs2AKjYyXLsTyAsNRiURifKhyYBYEPVVXChLIg60oChpEGvuTAm69BxIHJzB0ACEVmaBjeOgrX06ALLGjAzYvzLz4UIPl8Yd4XIA11kMmKDpQRo4UBhGWWc0VktAWtifkU66xErhARymbnO5rKFNeWsYWrwBjR9p9/k83X3FPIaqvw6EIOVEmiZbPgB1L7vi/fK2xKpY9AK/DykmizuSIwCWvhKijnMLz63exmwcVKSVTr1oi2l5HSsha2aaWgNirj3NZdFkB6Qrrag+vh6rCU1M1rPF+yv5Tz2lo5sogDmWkZHQtqaiRpSwIILZWCtw/IJv39heTTEI1AcgSWN0LDMjn3ufQaA4m4AO9YCclrsPtFkeXOTujrh7ZWMDkUJ779nrq6Z8lkfMCaByAIiv3+3cPQ3SPymveEkY/egZblkB4vAjBG6E6Owd4DsG0zTE7BTFYYSMTh5I8+Xx2zWNHyQ3kh0hpS16GuFj5+TyL495LI644tsuHNda4UzLqw9VF4+gno6RWQ9cskoMtX4PHN8ORW6P2nAilWSm42U9OwagWsXSNCMzq2sMIpBXYETp2F1Lg411qY0Rqa45DJwOlfoDleYTcMazo9AVeTMJy89dxD+p2I3Atf3S+OQufhvCqMe96Ant4CAM+rrM7CJNR64ZpXCtyctN/Pj0AsJrSHa5UqdFIFX35ieKDTaIzpoqZW4bpL8zZkDHg52LkdmhpgJFUEEQQwloaaqGH3LgV2l6bz3k+ZSo3S0mrjuh7GBIB/x48xPhHH5+yvPid/8mlL+LiuT3rCZ3omoCXu0T9oc/ybEZ7ZfUS4mRjaRnfvcfQiX049IALk8nJP7O2HxzZC19/w/Cvw2QfwwnPw3YlB9ux9GaXOqRtS+fuZdiYz+/CX4vVcQd5AfZWMJoDui7BhrYfjdLFj1zGUGsYY/geDsv+dOi74jwAAAABJRU5ErkJggg=="> <style> :root { color-scheme: dark; }@@ -989,6 +990,7 @@ for (const w of mine) { "on " + esc(who) + " - one slow verb, animated purely from its progress block"); var finished = false, frames = 0, sawMoving = false, lastLabel = null;+ c._lastShotKey = null; // fresh evidence stream per run // ---- the poll leg: this is what animates ------------------------------- function poll() {@@ -1008,9 +1010,19 @@ for (const w of mine) { (block.blockedBy ? " BLOCKED: " + block.blockedBy : "")); } // A frame can carry its own evidence screenshot - show it verbatim.+ // DEDUPE: the same stepShot rides EVERY poll frame until the bridge+ // moves to the next step, so appending on each poll stacks identical+ // thumbnails and makes one step look like several. Key on the step ++ // the image itself so a genuine re-capture of the same step still shows. var ss = readStepShot(block) || readStepShot(res.j);- if (ss && (ss.image || ss.base64)) addShot(c.card, ss.image || ss.base64,- "step: " + (ss.step || ss.title || label || "step"));+ var img = ss && (ss.image || ss.base64);+ if (img) {+ var key = (ss.step || "") + "|" + (ss.title || "") + "|" + String(img).length;+ if (key !== c._lastShotKey) {+ c._lastShotKey = key;+ addShot(c.card, img, "step: " + (ss.step || ss.title || label || "step"));+ }+ } } setTimeout(poll, 1000); }).catch(function () { if (!finished) setTimeout(poll, 1000); });