granclaw 0.0.1-beta.35 → 0.0.1-beta.37

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.
@@ -6,17 +6,19 @@
6
6
  *
7
7
  * stealthArgv() returns an argv fragment for the `agent-browser` boot command:
8
8
  *
9
- * --args --load-extension=<dir>
10
- * Loads the GranClaw stealth MV3 extension. The extension content script
11
- * runs at document_start in world=MAIN — before any page JS — patching
12
- * navigator.webdriver, UA, plugins, WebGL, canvas, audio, and more.
13
- * Works in Chrome 112+ new headless mode without a display (no Xvfb needed).
9
+ * --extension <dir>
10
+ * Loads the GranClaw stealth MV3 extension (repeatable). The extension
11
+ * content script runs at document_start in world=MAIN — before any page
12
+ * JS — patching navigator.webdriver, UA, plugins, WebGL, canvas, audio.
13
+ * MUST use --extension (not --args --load-extension=…): agent-browser's
14
+ * --args flag is NOT repeatable and silently drops all but the LAST value,
15
+ * which is how the stealth extension was leaking in production.
14
16
  *
15
- * --args --enable-extensions
16
- * Required to activate extension loading in headless mode.
17
- *
18
- * --args --disable-blink-features=AutomationControlled
19
- * Removes navigator.webdriver = true at the Chrome level, the #1 signal.
17
+ * --args "--disable-blink-features=AutomationControlled,--headless=new,…"
18
+ * ALL chromium flags must live inside a SINGLE --args value, comma-joined.
19
+ * agent-browser collapses repeated --args to the last one and splits each
20
+ * value on commas before forwarding to Chrome. --headless=new is required
21
+ * here because agent-browser does not auto-add it when --extension is set.
20
22
  *
21
23
  * --executable-path <path>
22
24
  * Uses real installed Chrome/Chromium instead of Playwright's bundled
@@ -198,26 +200,40 @@ function detectChromeUA() {
198
200
  function stealthArgv(options = {}) {
199
201
  if (process.env.GRANCLAW_STEALTH_DISABLED === '1')
200
202
  return [];
201
- const argv = [
202
- '--args', '--disable-blink-features=AutomationControlled',
203
- '--args', '--enable-extensions',
204
- // Enable the V8 heap memory API (performance.memory) disabled by default in headless.
205
- '--args', '--enable-precise-memory-info',
203
+ const argv = [];
204
+ // All Chromium command-line switches MUST live inside a single --args value.
205
+ // agent-browser's --args flag is NOT repeatable: only the LAST value survives,
206
+ // and that value is comma-split before being forwarded to Chrome. Emitting
207
+ // several --args flags was how every stealth switch except the last silently
208
+ // vanished in production, leaving navigator.webdriver detectable.
209
+ const chromeFlags = [
210
+ '--disable-blink-features=AutomationControlled',
211
+ // V8 heap memory API (performance.memory) — disabled by default in headless.
212
+ '--enable-precise-memory-info',
206
213
  ];
207
- // Override the UA using agent-browser's dedicated --user-agent flag (not via
208
- // --args). navigator.userAgent in Chrome 120+ has a non-configurable prototype
214
+ // agent-browser does not auto-add --headless=new once --extension is set,
215
+ // so headless contexts must request it explicitly. Headed previews must NOT
216
+ // include it (the orchestrator also passes --headed and Chrome refuses both).
217
+ if (options.headless !== false) {
218
+ chromeFlags.push('--headless=new');
219
+ }
220
+ argv.push('--args', chromeFlags.join(','));
221
+ // Override the UA using agent-browser's dedicated --user-agent flag.
222
+ // navigator.userAgent in Chrome 120+ has a non-configurable prototype
209
223
  // property that JS Object.defineProperty cannot patch, so the only reliable
210
- // fix is to set it at the browser level. We use the top-level flag rather than
211
- // --args because --args values are comma-separated and a UA string contains
224
+ // fix is to set it at the browser level. We use the top-level flag rather
225
+ // than --args because --args values are comma-split and a UA string contains
212
226
  // commas/spaces that would be mis-parsed.
213
227
  const ua = detectChromeUA();
214
228
  if (ua) {
215
229
  argv.push('--user-agent', ua);
216
230
  }
217
- // Build extension list: stealth + optional CapMonster
218
- const extDirs = [];
219
- if (exports.STEALTH_EXTENSION_DIR)
220
- extDirs.push(exports.STEALTH_EXTENSION_DIR);
231
+ // Extensions go through agent-browser's dedicated (repeatable) --extension
232
+ // flag NOT via --args --load-extension=… which is silently dropped by the
233
+ // single-value --args collapse described above.
234
+ if (exports.STEALTH_EXTENSION_DIR) {
235
+ argv.push('--extension', exports.STEALTH_EXTENSION_DIR);
236
+ }
221
237
  const capmonsterKey = options.capmonsterKey
222
238
  || process.env.CAPMONSTER_KEY
223
239
  || process.env.CAPMONSTER_API_KEY;
@@ -225,12 +241,7 @@ function stealthArgv(options = {}) {
225
241
  if (capmonsterKey && capmonsterEnabled) {
226
242
  const capmonsterDir = capmonsterExtensionDir(capmonsterKey);
227
243
  if (capmonsterDir)
228
- extDirs.push(capmonsterDir);
229
- }
230
- if (extDirs.length > 0) {
231
- const extList = extDirs.join(',');
232
- argv.push('--args', `--load-extension=${extList}`);
233
- argv.push('--args', `--disable-extensions-except=${extList}`);
244
+ argv.push('--extension', capmonsterDir);
234
245
  }
235
246
  const chrome = detectChromePath();
236
247
  if (chrome) {
@@ -1397,7 +1397,7 @@ function createServer() {
1397
1397
  '--session', req.params.id,
1398
1398
  '--headed',
1399
1399
  '--profile', profileDir,
1400
- ...(0, stealth_js_1.stealthArgv)(),
1400
+ ...(0, stealth_js_1.stealthArgv)({ headless: false }),
1401
1401
  'open', url,
1402
1402
  ];
1403
1403
  execFileSync('agent-browser', argv, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "granclaw",
3
- "version": "0.0.1-beta.35",
3
+ "version": "0.0.1-beta.37",
4
4
  "description": "A personal AI assistant you run on your own machine.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -43,6 +43,7 @@
43
43
  "express": "^4.19.2",
44
44
  "node-html-markdown": "^2.0.0",
45
45
  "posthog-node": "^5.29.2",
46
+ "telegramify-markdown": "^1.3.3",
46
47
  "undici": "^7.0.0",
47
48
  "ws": "^8.17.1"
48
49
  },