@melaya/runner 1.1.14 → 1.1.16
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/dist/browserBridge.js +44 -35
- package/package.json +44 -44
package/dist/browserBridge.js
CHANGED
|
@@ -59,51 +59,56 @@ const MELAYA_BRAND_SCRIPT = `(() => {
|
|
|
59
59
|
if (document.getElementById(ID + "_border")) return;
|
|
60
60
|
const style = document.createElement("style");
|
|
61
61
|
style.id = ID + "_style";
|
|
62
|
-
style.textContent = "@keyframes melBrandPulse{0%,100%{box-shadow:inset 0 0 9px 2px rgba(34,211,238,.5),inset 0 0 30px 7px rgba(124,111,240,.18)}50%{box-shadow:inset 0 0 16px 4px rgba(34,211,238,.8),inset 0 0 54px 13px rgba(124,111,240,.32)}}@keyframes melBrandGlow{0%,100%{opacity:.78}50%{opacity:1}}#" + ID + "_border{position:fixed;inset:0;pointer-events:none;z-index:2147483647;border-radius:7px;animation:melBrandPulse 2.6s ease-in-out infinite}#" + ID + "_badge{position:fixed;top:10px;left:50%;transform:translateX(-50%);pointer-events:none;z-index:2147483647;font-family:-apple-system,Segoe UI,Roboto,sans-serif;font-weight:600;font-size:12px;line-height:
|
|
62
|
+
style.textContent = "@keyframes melBrandPulse{0%,100%{box-shadow:inset 0 0 9px 2px rgba(34,211,238,.5),inset 0 0 30px 7px rgba(124,111,240,.18)}50%{box-shadow:inset 0 0 16px 4px rgba(34,211,238,.8),inset 0 0 54px 13px rgba(124,111,240,.32)}}@keyframes melBrandGlow{0%,100%{opacity:.78}50%{opacity:1}}#" + ID + "_border{position:fixed;inset:0;pointer-events:none;z-index:2147483647;border-radius:7px;animation:melBrandPulse 2.6s ease-in-out infinite}#" + ID + "_badge{position:fixed;top:10px;left:50%;transform:translateX(-50%);pointer-events:none;z-index:2147483647;font-family:-apple-system,Segoe UI,Roboto,sans-serif;font-weight:600;font-size:12px;line-height:1;white-space:nowrap;max-width:calc(100vw - 24px);box-sizing:border-box;color:#E2E8F0;background:linear-gradient(180deg,rgba(15,23,42,.94),rgba(15,23,42,.82));padding:5px 13px 5px 7px;border-radius:999px;letter-spacing:.2px;border:1px solid rgba(34,211,238,.45);box-shadow:0 0 16px 1px rgba(34,211,238,.4),0 4px 14px rgba(0,0,0,.45);display:flex;align-items:center;gap:8px;backdrop-filter:blur(6px);animation:melBrandGlow 2.6s ease-in-out infinite}#" + ID + "_logo{height:16px;width:auto;display:block;filter:drop-shadow(0 0 4px rgba(34,211,238,.55))}#" + ID + "_label{display:inline-flex;align-items:center;height:16px;line-height:1}@media (max-width:600px){#" + ID + "_badge{font-size:10px;padding:4px 10px 4px 6px;gap:6px;top:6px}#" + ID + "_logo{height:13px}#" + ID + "_label{height:13px}}";
|
|
63
63
|
(document.head || root).appendChild(style);
|
|
64
64
|
const border = document.createElement("div"); border.id = ID + "_border";
|
|
65
65
|
const badge = document.createElement("div"); badge.id = ID + "_badge";
|
|
66
66
|
const logo = document.createElement("img"); logo.id = ID + "_logo"; logo.src = LOGO; logo.alt = "Melaya";
|
|
67
|
-
|
|
67
|
+
const label = document.createElement("span"); label.id = ID + "_label"; label.textContent = "Controlled by Melaya";
|
|
68
|
+
badge.appendChild(logo); badge.appendChild(label);
|
|
68
69
|
root.appendChild(border); root.appendChild(badge);
|
|
69
70
|
};
|
|
70
71
|
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", inject); else inject();
|
|
71
72
|
try { new MutationObserver(() => { if (!document.getElementById(ID + "_border")) inject(); }).observe(document.documentElement, { childList: true }); } catch (e) {}
|
|
72
73
|
})();`;
|
|
73
74
|
// ── Stealth init script ────────────────────────────────────────────────────
|
|
74
|
-
// Runs in EVERY frame BEFORE page scripts (context.addInitScript).
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
75
|
+
// Runs in EVERY frame BEFORE page scripts (context.addInitScript).
|
|
76
|
+
//
|
|
77
|
+
// CRITICAL: this is a HEADED real Brave/Chrome, so its fingerprint (plugins,
|
|
78
|
+
// GPU, cores, memory, UA) is ALREADY genuine. Overriding those would INTRODUCE
|
|
79
|
+
// inconsistencies a detector catches (e.g. a spoofed WebGL vendor that disagrees
|
|
80
|
+
// with the real driver, or a patched function whose toString is not native).
|
|
81
|
+
// So we touch ONLY the two things a CDP session genuinely leaks:
|
|
82
|
+
// 1. navigator.webdriver (can read truthy under CDP), and
|
|
83
|
+
// 2. the Notification.permission vs permissions.query mismatch CDP introduces.
|
|
84
|
+
// Any function we replace is given a native-looking toString so the patch is not
|
|
85
|
+
// itself a tell. We do NOT fake plugins/webgl/hardware/languages/chrome — a real
|
|
86
|
+
// headed browser already has correct, self-consistent values.
|
|
80
87
|
const STEALTH_SCRIPT = `(() => {
|
|
81
88
|
const def = (o, k, get) => { try { Object.defineProperty(o, k, { get, configurable: true }); } catch (e) {} };
|
|
82
|
-
|
|
83
|
-
|
|
89
|
+
const nativeToString = (fn, name) => {
|
|
90
|
+
try {
|
|
91
|
+
const s = "function " + name + "() { [native code] }";
|
|
92
|
+
Object.defineProperty(fn, "toString", { value: function () { return s; }, configurable: true, writable: true });
|
|
93
|
+
} catch (e) {}
|
|
94
|
+
};
|
|
95
|
+
// 1. navigator.webdriver → false. The launch flag disables it, but some CDP
|
|
96
|
+
// builds still expose it truthy; keep it false as a belt-and-suspenders.
|
|
84
97
|
def(Object.getPrototypeOf(navigator) || navigator, "webdriver", () => false);
|
|
85
98
|
try { delete Navigator.prototype.webdriver; } catch (e) {}
|
|
86
|
-
//
|
|
87
|
-
try { window.chrome = window.chrome || {}; window.chrome.runtime = window.chrome.runtime || {}; } catch (e) {}
|
|
88
|
-
def(navigator, "languages", () => ["en-US", "en"]);
|
|
89
|
-
// Non-empty plugins/mimeTypes so length checks pass.
|
|
90
|
-
try { if (!navigator.plugins || navigator.plugins.length === 0) def(navigator, "plugins", () => [1, 2, 3, 4, 5]); } catch (e) {}
|
|
91
|
-
// Notification permission must agree between Notification.permission and
|
|
92
|
-
// permissions.query — a classic mismatch CDP introduces.
|
|
99
|
+
// 2. Notification.permission must agree with permissions.query (CDP mismatch).
|
|
93
100
|
try {
|
|
94
101
|
const q = navigator.permissions && navigator.permissions.query ? navigator.permissions.query.bind(navigator.permissions) : null;
|
|
95
|
-
if (q)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
if (q) {
|
|
103
|
+
const patched = function (p) {
|
|
104
|
+
return (p && p.name === "notifications")
|
|
105
|
+
? Promise.resolve({ state: (typeof Notification !== "undefined" ? Notification.permission : "default"), onchange: null })
|
|
106
|
+
: q(p);
|
|
107
|
+
};
|
|
108
|
+
nativeToString(patched, "query");
|
|
109
|
+
navigator.permissions.query = patched;
|
|
110
|
+
}
|
|
104
111
|
} catch (e) {}
|
|
105
|
-
def(navigator, "hardwareConcurrency", () => 8);
|
|
106
|
-
def(navigator, "deviceMemory", () => 8);
|
|
107
112
|
})();`;
|
|
108
113
|
// ── Humanized input helpers ────────────────────────────────────────────────
|
|
109
114
|
// Instant teleport-clicks and zero-delay typing are a behavioural bot tell.
|
|
@@ -458,13 +463,17 @@ export async function startBrowserBridge(opts) {
|
|
|
458
463
|
// Normalise engine to a known BrowserEngineId; default to "chrome".
|
|
459
464
|
const knownEngines = new Set(["chrome", "edge", "brave", "chromium"]);
|
|
460
465
|
const engineId = (knownEngines.has(engine) ? engine : "chrome");
|
|
461
|
-
// Resolve profile directory
|
|
462
|
-
//
|
|
463
|
-
//
|
|
464
|
-
//
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
466
|
+
// Resolve profile directory. The dedicated Melaya profile is PERSISTENT (a
|
|
467
|
+
// stable per-engine dir under ~/.melaya-runner/browser-profiles/), NOT a
|
|
468
|
+
// fresh per-session temp dir. Two reasons, both about real-world usability
|
|
469
|
+
// and anti-bot survival:
|
|
470
|
+
// 1. Logins persist. A fresh profile forces the user to sign in to every
|
|
471
|
+
// site on every launch, under bot scrutiny — the "can't log in" pain.
|
|
472
|
+
// 2. A cookieless, history-less profile is itself a strong bot signal.
|
|
473
|
+
// A warmed profile that accrues real cookies/history looks human.
|
|
474
|
+
// It is still isolated from the user's PERSONAL browser profile (separate
|
|
475
|
+
// dir), so this is a dedicated-but-warm profile, not their everyday one.
|
|
476
|
+
const spaceSpec = { kind: "persistent", id: `browser-profiles-${engineId}-${profile}` };
|
|
468
477
|
// Reject duplicate launches for the same sessionId.
|
|
469
478
|
if (interactiveSessions.has(sessionId)) {
|
|
470
479
|
log(`[browser-launch] sessionId=${sessionId.slice(0, 16)} already active; ignoring duplicate launch`);
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@melaya/runner",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "Run Melaya AI pipelines locally with your own LM Studio or Ollama models",
|
|
5
|
-
"license": "UNLICENSED",
|
|
6
|
-
"private": false,
|
|
7
|
-
"type": "module",
|
|
8
|
-
"bin": {
|
|
9
|
-
"melaya-runner": "dist/cli.js"
|
|
10
|
-
},
|
|
11
|
-
"main": "dist/index.js",
|
|
12
|
-
"files": [
|
|
13
|
-
"dist/**/*.js",
|
|
14
|
-
"dist/**/*.d.ts",
|
|
15
|
-
"dist/**/*.py",
|
|
16
|
-
"localRagIngest.py",
|
|
17
|
-
"localRagRetrieve.py",
|
|
18
|
-
"nltk_data/**",
|
|
19
|
-
"README.md"
|
|
20
|
-
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"build": "tsc && node -e \"const fs=require('fs'); fs.copyFileSync('localRagIngest.py','dist/localRagIngest.py'); fs.copyFileSync('localRagRetrieve.py','dist/localRagRetrieve.py'); fs.copyFileSync('src/assistantHost.py','dist/assistantHost.py')\"",
|
|
23
|
-
"test": "node --test --import tsx \"src/**/*.test.ts\"",
|
|
24
|
-
"prepublishOnly": "npm run build"
|
|
25
|
-
},
|
|
26
|
-
"dependencies": {
|
|
27
|
-
"chalk": "^5.3.0",
|
|
28
|
-
"commander": "^12.0.0",
|
|
29
|
-
"ora": "^8.0.0",
|
|
30
|
-
"playwright": "^1.48.0",
|
|
31
|
-
"socket.io-client": "^4.8.0"
|
|
32
|
-
},
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"@types/node": "^20.0.0",
|
|
35
|
-
"tsx": "^4.19.2",
|
|
36
|
-
"typescript": "^5.5.0"
|
|
37
|
-
},
|
|
38
|
-
"engines": {
|
|
39
|
-
"node": ">=18"
|
|
40
|
-
},
|
|
41
|
-
"publishConfig": {
|
|
42
|
-
"access": "public"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@melaya/runner",
|
|
3
|
+
"version": "1.1.16",
|
|
4
|
+
"description": "Run Melaya AI pipelines locally with your own LM Studio or Ollama models",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"private": false,
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"melaya-runner": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist/**/*.js",
|
|
14
|
+
"dist/**/*.d.ts",
|
|
15
|
+
"dist/**/*.py",
|
|
16
|
+
"localRagIngest.py",
|
|
17
|
+
"localRagRetrieve.py",
|
|
18
|
+
"nltk_data/**",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc && node -e \"const fs=require('fs'); fs.copyFileSync('localRagIngest.py','dist/localRagIngest.py'); fs.copyFileSync('localRagRetrieve.py','dist/localRagRetrieve.py'); fs.copyFileSync('src/assistantHost.py','dist/assistantHost.py')\"",
|
|
23
|
+
"test": "node --test --import tsx \"src/**/*.test.ts\"",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"chalk": "^5.3.0",
|
|
28
|
+
"commander": "^12.0.0",
|
|
29
|
+
"ora": "^8.0.0",
|
|
30
|
+
"playwright": "^1.48.0",
|
|
31
|
+
"socket.io-client": "^4.8.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^20.0.0",
|
|
35
|
+
"tsx": "^4.19.2",
|
|
36
|
+
"typescript": "^5.5.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
}
|
|
44
|
+
}
|