@maintainer-pro/ai-bridge 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/daemon.mjs +11 -0
- package/src/share-rewrite.mjs +56 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maintainer-pro/ai-bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "Local bridge daemon that pairs a machine to Maintainer Pro and configures multiple client sandboxes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"maintainer-pro",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"node": ">=22"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@maintainer-pro/ai-cli": "^0.1.
|
|
32
|
-
"@maintainer-pro/ai-server": "^0.1.
|
|
31
|
+
"@maintainer-pro/ai-cli": "^0.1.8",
|
|
32
|
+
"@maintainer-pro/ai-server": "^0.1.7"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/daemon.mjs
CHANGED
|
@@ -5200,6 +5200,12 @@ async function main() {
|
|
|
5200
5200
|
|
|
5201
5201
|
if (args.pair || !cfg.token || !cfg.adminUrl) {
|
|
5202
5202
|
cfg = await pairFlow(args);
|
|
5203
|
+
} else if (typeof args.adminUrl === "string" && args.adminUrl.trim()) {
|
|
5204
|
+
const next = args.adminUrl.replace(/\/$/, "");
|
|
5205
|
+
if (cfg.adminUrl && cfg.adminUrl !== next) {
|
|
5206
|
+
log(`admin URL ${cfg.adminUrl} → ${next}`);
|
|
5207
|
+
}
|
|
5208
|
+
cfg.adminUrl = next;
|
|
5203
5209
|
}
|
|
5204
5210
|
|
|
5205
5211
|
cfg.noAiServer = Boolean(args.noAiServer);
|
|
@@ -5557,6 +5563,11 @@ async function main() {
|
|
|
5557
5563
|
clearHeartbeatTimer();
|
|
5558
5564
|
clearPingTimer();
|
|
5559
5565
|
if (socket === ws) socket = null;
|
|
5566
|
+
if (Number(code) === 1008) {
|
|
5567
|
+
warn(
|
|
5568
|
+
"Admin rejected this computer’s token. This admin is not the one in ~/.maintainer-pro/bridge.json. Generate a new pair code (Admin → Bridges → Add computer) and run the pair command."
|
|
5569
|
+
);
|
|
5570
|
+
}
|
|
5560
5571
|
scheduleReconnect(code, reason);
|
|
5561
5572
|
};
|
|
5562
5573
|
|
package/src/share-rewrite.mjs
CHANGED
|
@@ -237,17 +237,36 @@ function notModifiedResult(headers, etag) {
|
|
|
237
237
|
|
|
238
238
|
function rewriteLocation(value, publicBase, port) {
|
|
239
239
|
if (!publicBase) return value;
|
|
240
|
+
const base = String(publicBase).replace(/\/$/, "");
|
|
241
|
+
const prefix = proxyPathPrefix(publicBase);
|
|
240
242
|
try {
|
|
241
243
|
const u = new URL(value, `http://127.0.0.1:${Number(port) || 0}`);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
+
const host = String(u.hostname || "").toLowerCase();
|
|
245
|
+
const local =
|
|
246
|
+
host === "127.0.0.1" ||
|
|
247
|
+
host === "localhost" ||
|
|
248
|
+
host === "::1" ||
|
|
249
|
+
host === "0.0.0.0";
|
|
250
|
+
if (!local) return value;
|
|
251
|
+
let path = u.pathname || "/";
|
|
252
|
+
if (prefix && (path === prefix || path.startsWith(`${prefix}/`))) {
|
|
253
|
+
path = path.slice(prefix.length) || "/";
|
|
244
254
|
}
|
|
255
|
+
return `${base}${path}${u.search}${u.hash}`;
|
|
245
256
|
} catch {
|
|
246
257
|
/* keep */
|
|
247
258
|
}
|
|
248
259
|
return value;
|
|
249
260
|
}
|
|
250
261
|
|
|
262
|
+
function rewriteLinkHeader(value, publicBase) {
|
|
263
|
+
const prefix = proxyPathPrefix(publicBase);
|
|
264
|
+
if (!prefix || !value) return value;
|
|
265
|
+
return String(value).replace(/<(\/(?!\/)[^>\s]*)>/g, (full, path) =>
|
|
266
|
+
alreadyPrefixed(path, prefix) ? full : `<${prefix}${path}>`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
251
270
|
function gzipIfRequested(payload, headers, acceptEncoding) {
|
|
252
271
|
if (payload.length < 1024) return payload;
|
|
253
272
|
if (!/\bgzip\b/i.test(acceptEncoding || "")) return payload;
|
|
@@ -411,9 +430,38 @@ function alreadyPrefixed(path, pathPrefix) {
|
|
|
411
430
|
return path === pathPrefix || path.startsWith(`${pathPrefix}/`);
|
|
412
431
|
}
|
|
413
432
|
|
|
433
|
+
function rewriteNextFlightCanonical(body, pathPrefix) {
|
|
434
|
+
if (!pathPrefix || !body) return body;
|
|
435
|
+
const encoded = JSON.stringify(pathPrefix);
|
|
436
|
+
const escaped = pathPrefix.replaceAll("\\", "\\\\").replaceAll('"', '\\"');
|
|
437
|
+
let out = body;
|
|
438
|
+
if (out.includes(`"c":["",""]`)) {
|
|
439
|
+
out = out.split(`"c":["",""]`).join(`"c":[${encoded}]`);
|
|
440
|
+
}
|
|
441
|
+
if (out.includes('\\"c\\":[\\"\\",\\"\\"]')) {
|
|
442
|
+
out = out
|
|
443
|
+
.split('\\"c\\":[\\"\\",\\"\\"]')
|
|
444
|
+
.join(`\\"c\\":[\\"${escaped}\\"]`);
|
|
445
|
+
}
|
|
446
|
+
out = out.replace(/("b":"[^"]+","p":)""/g, `$1${encoded}`);
|
|
447
|
+
out = out.replace(
|
|
448
|
+
/(\\?"b\\":\\?"[^"]+\\?",\\?"p\\":)\\?"\\?"/g,
|
|
449
|
+
`$1\\"${escaped}\\"`
|
|
450
|
+
);
|
|
451
|
+
if (out.includes(`"assetPrefix":""`)) {
|
|
452
|
+
out = out.split(`"assetPrefix":""`).join(`"assetPrefix":${encoded}`);
|
|
453
|
+
}
|
|
454
|
+
if (out.includes('\\"assetPrefix\\":\\"\\"')) {
|
|
455
|
+
out = out
|
|
456
|
+
.split('\\"assetPrefix\\":\\"\\"')
|
|
457
|
+
.join(`\\"assetPrefix\\":\\"${escaped}\\"`);
|
|
458
|
+
}
|
|
459
|
+
return out;
|
|
460
|
+
}
|
|
461
|
+
|
|
414
462
|
function rewriteNextTurbopackBasePath(body, pathPrefix) {
|
|
415
463
|
if (!pathPrefix) return body;
|
|
416
|
-
let out = body;
|
|
464
|
+
let out = rewriteNextFlightCanonical(body, pathPrefix);
|
|
417
465
|
if (out.includes("TURBOPACK compile-time value")) {
|
|
418
466
|
const next = JSON.stringify(pathPrefix);
|
|
419
467
|
out = out
|
|
@@ -486,6 +534,7 @@ function prefixRootPaths(body, publicBase, contentType = "") {
|
|
|
486
534
|
out = out.replace(/\s+crossorigin(?:\s*=\s*(["']).*?\1)?/gi, "");
|
|
487
535
|
}
|
|
488
536
|
if (isNextDocument(out)) {
|
|
537
|
+
out = rewriteNextFlightCanonical(out, pathPrefix);
|
|
489
538
|
out = prefixQuotedRoots(out, pathPrefix, ["/_next/", "/__nextjs_"]);
|
|
490
539
|
out = out.replace(
|
|
491
540
|
/(url\(\s*['"]?)(\/(?!\/)[^)"']*)/gi,
|
|
@@ -610,7 +659,7 @@ function injectNextProxyShim(html, publicBase) {
|
|
|
610
659
|
return html;
|
|
611
660
|
}
|
|
612
661
|
const p = JSON.stringify(prefix);
|
|
613
|
-
const script = `<script data-mp-proxy-next>(function(p){if(!p)return;function add(v){if(typeof v!=="string"||!v)return v;if(v.charAt(0)==="/"&&v.charAt(1)!=="/"){if(v===p||v.indexOf(p+"/")===0)return v;var root=p.slice(0,p.lastIndexOf("/"));if(root&&(v===root||v.indexOf(root+"/")===0)return v;if(v==="/api/v1"||v.indexOf("/api/v1/")===0)return v;return p+v}try{var u=new URL(v,location.href);var host=String(u.hostname||"").toLowerCase();if(host.charAt(0)==="["&&host.charAt(host.length-1)==="]")host=host.slice(1,-1);var local=host==="localhost"||host==="127.0.0.1"||host==="::1"||host==="0.0.0.0";if(!local){if(u.pathname===p){u.pathname="/";return u.toString()}if(u.pathname.indexOf(p+"/")===0){u.pathname=u.pathname.slice(p.length)||"/";return u.toString()}return v}var samePort=String(u.port||"")===String(location.port||"");if(samePort){u.pathname=add(u.pathname);return u.toString()}if(u.pathname===p||u.pathname.indexOf(p+"/")===0){u.protocol=location.protocol;u.host=location.host;return u.toString()}}catch(e){}return v}function mapSel(sel){if(typeof sel!=="string")return sel;var pairs=[["src=\\"/_next/","src=\\""+p+"/_next/"],["href=\\"/_next/","href=\\""+p+"/_next/"]];for(var i=0;i<pairs.length;i++){if(sel.indexOf(pairs[i][0])!==-1)return sel.split(pairs[i][0]).join(pairs[i][1])}return sel}function patchQS(proto,name){var orig=proto[name];proto[name]=function(sel){var r=orig.call(this,sel);if(name==="querySelector"){if(r)return r}else if(r.length)return r;var s2=mapSel(sel);return s2===sel?r:orig.call(this,s2)}}patchQS(Document.prototype,"querySelector");patchQS(Document.prototype,"querySelectorAll");patchQS(Element.prototype,"querySelector");patchQS(Element.prototype,"querySelectorAll");var sa=Element.prototype.setAttribute;Element.prototype.setAttribute=function(n,v){if((n==="src"||n==="href")&&typeof v==="string")v=add(v);return sa.call(this,n,v)};function patchUrlProp(ctor,prop){try{var d=Object.getOwnPropertyDescriptor(ctor.prototype,prop);if(!d||!d.set)return;Object.defineProperty(ctor.prototype,prop,{configurable:true,enumerable:true,get:d.get,set:function(v){d.set.call(this,add(v))}})}catch(e){}}patchUrlProp(HTMLScriptElement,"src");patchUrlProp(HTMLLinkElement,"href");var f=window.fetch;window.fetch=function(input,init){if(typeof input==="string")input=add(input);else if(typeof Request!=="undefined"&&input instanceof Request)input=new Request(add(input.url),input);else if(typeof URL!=="undefined"&&input instanceof URL)input=new URL(add(input.href));return f.call(this,input,init)};var xo=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(m,u){if(typeof u==="string")arguments[1]=add(u);return xo.apply(this,arguments)};var ps=history.pushState.bind(history);history.pushState=function(s,t,u){if(typeof u==="string")u=add(u);return ps(s,t,u)};var rs=history.replaceState.bind(history);history.replaceState=function(s,t,u){if(typeof u==="string")u=add(u);return rs(s,t,u)};var WS=window.WebSocket;function WrappedWS(url,protocols){if(typeof url==="string")url=add(url);return protocols!==undefined?new WS(url,protocols):new WS(url)}WrappedWS.prototype=WS.prototype;WrappedWS.CONNECTING=WS.CONNECTING;WrappedWS.OPEN=WS.OPEN;WrappedWS.CLOSING=WS.CLOSING;WrappedWS.CLOSED=WS.CLOSED;window.WebSocket=WrappedWS})(${p})</script>`;
|
|
662
|
+
const script = `<script data-mp-proxy-next>(function(p){if(!p)return;function add(v){if(typeof v!=="string"||!v)return v;function collapse(path){var d=p+p;while(path.indexOf(d)===0)path=p+path.slice(d.length);return path}if(v.charAt(0)==="/"&&v.charAt(1)!=="/"){if(v===p||v.indexOf(p+"/")===0)return collapse(v);var root=p.slice(0,p.lastIndexOf("/"));if(root&&(v===root||v.indexOf(root+"/")===0))return v;if(v==="/api/v1"||v.indexOf("/api/v1/")===0)return v;return collapse(p+v)}try{var u=new URL(v,location.href);var host=String(u.hostname||"").toLowerCase();if(host.charAt(0)==="["&&host.charAt(host.length-1)==="]")host=host.slice(1,-1);var local=host==="localhost"||host==="127.0.0.1"||host==="::1"||host==="0.0.0.0";if(!local){if(u.pathname===p){u.pathname="/";return u.toString()}if(u.pathname.indexOf(p+"/")===0){u.pathname=u.pathname.slice(p.length)||"/";return u.toString()}return v}var samePort=String(u.port||"")===String(location.port||"");if(samePort){u.pathname=add(u.pathname);return u.toString()}if(u.pathname===p||u.pathname.indexOf(p+"/")===0){u.protocol=location.protocol;u.host=location.host;return u.toString()}u.pathname=add(u.pathname||"/");u.protocol=location.protocol;u.host=location.host;return u.toString()}catch(e){}return v}function mapSel(sel){if(typeof sel!=="string")return sel;var pairs=[["src=\\"/_next/","src=\\""+p+"/_next/"],["href=\\"/_next/","href=\\""+p+"/_next/"]];for(var i=0;i<pairs.length;i++){if(sel.indexOf(pairs[i][0])!==-1)return sel.split(pairs[i][0]).join(pairs[i][1])}return sel}function patchQS(proto,name){var orig=proto[name];proto[name]=function(sel){var r=orig.call(this,sel);if(name==="querySelector"){if(r)return r}else if(r.length)return r;var s2=mapSel(sel);return s2===sel?r:orig.call(this,s2)}}patchQS(Document.prototype,"querySelector");patchQS(Document.prototype,"querySelectorAll");patchQS(Element.prototype,"querySelector");patchQS(Element.prototype,"querySelectorAll");var sa=Element.prototype.setAttribute;Element.prototype.setAttribute=function(n,v){if((n==="src"||n==="href")&&typeof v==="string")v=add(v);return sa.call(this,n,v)};function patchUrlProp(ctor,prop){try{var d=Object.getOwnPropertyDescriptor(ctor.prototype,prop);if(!d||!d.set)return;Object.defineProperty(ctor.prototype,prop,{configurable:true,enumerable:true,get:d.get,set:function(v){d.set.call(this,add(v))}})}catch(e){}}patchUrlProp(HTMLScriptElement,"src");patchUrlProp(HTMLLinkElement,"href");var f=window.fetch;window.fetch=function(input,init){if(typeof input==="string")input=add(input);else if(typeof Request!=="undefined"&&input instanceof Request)input=new Request(add(input.url),input);else if(typeof URL!=="undefined"&&input instanceof URL)input=new URL(add(input.href));return f.call(this,input,init)};var xo=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(m,u){if(typeof u==="string")arguments[1]=add(u);return xo.apply(this,arguments)};var ps=history.pushState.bind(history);history.pushState=function(s,t,u){if(typeof u==="string")u=add(u);return ps(s,t,u)};var rs=history.replaceState.bind(history);history.replaceState=function(s,t,u){if(typeof u==="string")u=add(u);return rs(s,t,u)};var WS=window.WebSocket;function WrappedWS(url,protocols){if(typeof url==="string")url=add(url);return protocols!==undefined?new WS(url,protocols):new WS(url)}WrappedWS.prototype=WS.prototype;WrappedWS.CONNECTING=WS.CONNECTING;WrappedWS.OPEN=WS.OPEN;WrappedWS.CLOSING=WS.CLOSING;WrappedWS.CLOSED=WS.CLOSED;window.WebSocket=WrappedWS;try{var la=location.assign.bind(location);location.assign=function(u){return la(add(String(u)))};var lr=location.replace.bind(location);location.replace=function(u){return lr(add(String(u)))}}catch(e){}try{var hd=Object.getOwnPropertyDescriptor(Location.prototype,"href");if(hd&&hd.set){Object.defineProperty(location,"href",{configurable:true,enumerable:true,get:function(){return hd.get.call(location)},set:function(v){hd.set.call(location,add(String(v)))}})}}catch(e){}})(${p})</script>`;
|
|
614
663
|
return html.replace(/<head([^>]*)>/i, `<head$1>${script}`);
|
|
615
664
|
}
|
|
616
665
|
|
|
@@ -649,6 +698,9 @@ export function processShareHttpResponse(opts) {
|
|
|
649
698
|
if (headers.location) {
|
|
650
699
|
headers.location = rewriteLocation(headers.location, publicBase, port);
|
|
651
700
|
}
|
|
701
|
+
if (headers.link) {
|
|
702
|
+
headers.link = rewriteLinkHeader(headers.link, publicBase);
|
|
703
|
+
}
|
|
652
704
|
|
|
653
705
|
const cachedKey = rewriteCacheKey(publicBase, path);
|
|
654
706
|
const hit =
|