@ohos-ports/vibium 26.5.31-beta.2 → 26.5.31-beta.4

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.
@@ -19,6 +19,11 @@ let mainSessionId = null;
19
19
  let pageSessions = {};
20
20
  let bidiWs = null; // Active BiDi WebSocket (for event forwarding)
21
21
  let subscribedEvents = new Set();
22
+ let executionContexts = {};
23
+ let sharedIdMap = new Map();
24
+ let sharedIdCounter = 0;
25
+ let pageLoadCallbacks = new Map();
26
+ let pendingPreloadScripts = [];
22
27
 
23
28
  // ─── CDP helpers ─────────────────────────────────────
24
29
  function cdpSend(method, params = {}, sessionId) {
@@ -67,6 +72,32 @@ function handleCDPEvent(msg) {
67
72
  break;
68
73
  case 'Page.loadEventFired':
69
74
  sendBiDiEvent('browsingContext.load', { context: ctx });
75
+ { var cb = pageLoadCallbacks.get(sid) || pageLoadCallbacks.get(ctx); if (cb) { pageLoadCallbacks.delete(sid); pageLoadCallbacks.delete(ctx); cb(); } }
76
+ break;
77
+ case 'Page.domContentEventFired':
78
+ sendBiDiEvent('browsingContext.domContentLoaded', { context: ctx });
79
+ { var cb2 = pageLoadCallbacks.get(sid) || pageLoadCallbacks.get(ctx); if (cb2) { pageLoadCallbacks.delete(sid); pageLoadCallbacks.delete(ctx); cb2(); } }
80
+ break;
81
+ case 'Target.targetCreated':
82
+ if (params.targetInfo && params.targetInfo.type === 'page') {
83
+ var tcCtx = params.targetInfo.targetId;
84
+ var tcData = { context: tcCtx };
85
+ if (params.targetInfo.openerId) tcData.originalOpener = params.targetInfo.openerId;
86
+ sendBiDiEvent('browsingContext.contextCreated', tcData);
87
+ }
88
+ break;
89
+ case 'Target.targetDestroyed':
90
+ if (params.targetInfo) sendBiDiEvent('browsingContext.contextClosed', { context: params.targetInfo.targetId });
91
+ break;
92
+ case 'Page.javascriptDialogOpening':
93
+ cdpSend('Page.handleJavaScriptDialog', { accept: true }, sid || mainSessionId).catch(function(){});
94
+ sendBiDiEvent('browsingContext.userPromptOpened', { context: ctx, type: params.type, message: params.message });
95
+ break;
96
+ case 'Runtime.consoleAPICalled':
97
+ { var typeMap = {log:'log',warning:'warn',error:'error',info:'info',debug:'debug',trace:'log',dir:'log'}; var ct = typeMap[params.type] || 'log'; var cargs = (params.args || []).map(function(a) { return a.value !== undefined ? a.value : (a.description || ''); }); sendBiDiEvent('log.entryAdded', { context: ctx, type: ct, args: cargs, text: cargs.join(' '), level: ct === 'error' ? 'error' : (ct === 'warn' ? 'warning' : 'info') }); }
98
+ break;
99
+ case 'Runtime.exceptionThrown':
100
+ { var exd = params.exceptionDetails || {}; sendBiDiEvent('log.entryAdded', { context: ctx, type: 'error', text: exd.text || 'Uncaught exception', level: 'error' }); }
70
101
  break;
71
102
  case 'Page.domContentEventFired':
72
103
  sendBiDiEvent('browsingContext.domContentLoaded', { context: ctx });
@@ -208,6 +239,8 @@ async function initCDP() {
208
239
  pageSessions[mainContextId] = { targetId: mainContextId, sessionId: mainSessionId };
209
240
  await cdpSend('Page.enable', {}, mainSessionId).catch(() => {});
210
241
  await cdpSend('Runtime.enable', {}, mainSessionId).catch(() => {});
242
+ await cdpSend('Network.enable', {}, mainSessionId).catch(() => {});
243
+ await cdpSend('Target.setDiscoverTargets', { discover: true }, mainSessionId).catch(() => {});
211
244
  console.log(`[bridge] Ready: ctx=${mainContextId}, session=${mainSessionId}`);
212
245
  resolve();
213
246
  } catch (e) {
@@ -223,6 +256,34 @@ async function initCDP() {
223
256
  });
224
257
  }
225
258
 
259
+ async function ensureSession(ctx) {
260
+ if (!pageSessions[ctx] && ctx && ctx !== mainContextId) {
261
+ try {
262
+ var targets = await cdpSend('Target.getTargets');
263
+ var target = (targets.targetInfos || []).find(function(t) { return t.targetId === ctx; });
264
+ if (target) {
265
+ var att = await cdpSend('Target.attachToTarget', { targetId: ctx, flatten: true });
266
+ pageSessions[ctx] = { targetId: ctx, sessionId: att.sessionId };
267
+ await cdpSend('Page.enable', {}, att.sessionId).catch(function(){});
268
+ await cdpSend('Runtime.enable', {}, att.sessionId).catch(function(){});
269
+ await cdpSend('Network.enable', {}, att.sessionId).catch(function(){});
270
+ for (var ps of pendingPreloadScripts) {
271
+ try { await cdpSend('Page.addScriptToEvaluateOnNewDocument', { source: ps }, att.sessionId); } catch(e) {}
272
+ }
273
+ }
274
+ } catch(e) {}
275
+ }
276
+ }
277
+ async function discoverAllSessions() {
278
+ try {
279
+ var targets = await cdpSend('Target.getTargets');
280
+ for (var t of (targets.targetInfos || [])) {
281
+ if (t.type === 'page' && !pageSessions[t.targetId] && t.targetId !== mainContextId) {
282
+ await ensureSession(t.targetId);
283
+ }
284
+ }
285
+ } catch(e) {}
286
+ }
226
287
  function getSession(context) {
227
288
  return pageSessions[context]?.sessionId || mainSessionId;
228
289
  }
@@ -291,17 +352,16 @@ async function handleBiDi(msg) {
291
352
  }
292
353
 
293
354
  case 'session.end': {
294
- // Real implementation: clean up all CDP sessions
295
- console.log('[bridge] session.end → cleaning up');
296
- for (const [ctx, info] of Object.entries(pageSessions)) {
297
- if (ctx !== mainContextId) {
298
- await cdpSend('Target.closeTarget', { targetId: ctx }).catch(() => {});
355
+ console.log('[bridge] session.end -> cleaning up (keeping main session)');
356
+ for (var seCtx in pageSessions) {
357
+ if (seCtx !== mainContextId) {
358
+ try { await cdpSend('Target.closeTarget', { targetId: seCtx }); } catch(e) {}
359
+ try { await cdpSend('Target.detachFromTarget', { sessionId: pageSessions[seCtx].sessionId }); } catch(e) {}
360
+ delete pageSessions[seCtx];
299
361
  }
300
- await cdpSend('Target.detachFromTarget', { sessionId: info.sessionId }).catch(() => {});
301
362
  }
302
- // Disable domains that were enabled for events
303
- await cdpSend('Network.disable', {}, mainSessionId).catch(() => {});
304
363
  subscribedEvents.clear();
364
+ pendingPreloadScripts = [];
305
365
  result = {};
306
366
  break;
307
367
  }
@@ -341,9 +401,16 @@ async function handleBiDi(msg) {
341
401
  }
342
402
 
343
403
  case 'browsingContext.navigate': {
344
- const ctx = params.context || mainContextId;
345
- const sid = getSession(ctx);
346
- const nav = await cdpSend('Page.navigate', { url: params.url }, sid);
404
+ const navCtx = params.context || mainContextId;
405
+ const navSid = getSession(navCtx);
406
+ const nav = await cdpSend('Page.navigate', { url: params.url }, navSid);
407
+ let loadResolve;
408
+ const loadPromise = new Promise(function(r) { loadResolve = r; });
409
+ pageLoadCallbacks.set(navSid, loadResolve);
410
+ pageLoadCallbacks.set(navCtx, loadResolve);
411
+ await Promise.race([loadPromise, new Promise(function(r) { setTimeout(r, 5000) })]);
412
+ pageLoadCallbacks.delete(navSid);
413
+ pageLoadCallbacks.delete(navCtx);
347
414
  result = { navigation: nav.loaderId || null, url: params.url };
348
415
  break;
349
416
  }
@@ -356,6 +423,8 @@ async function handleBiDi(msg) {
356
423
  pageSessions[tid] = { targetId: tid, sessionId: att.sessionId };
357
424
  await cdpSend('Page.enable', {}, att.sessionId).catch(() => {});
358
425
  await cdpSend('Runtime.enable', {}, att.sessionId).catch(() => {});
426
+ await cdpSend('Network.enable', {}, att.sessionId).catch(() => {});
427
+ for (var ps of pendingPreloadScripts) { try { await cdpSend('Page.addScriptToEvaluateOnNewDocument', { source: ps }, att.sessionId); } catch(e) {} }
359
428
  result = { context: tid };
360
429
  break;
361
430
  }
@@ -374,17 +443,17 @@ async function handleBiDi(msg) {
374
443
  case 'script.evaluate': {
375
444
  const ctx = params.context || params.target?.context || mainContextId;
376
445
  const sid = getSession(ctx);
377
- const expr = params.expression || '';
378
- const r = await cdpSend('Runtime.evaluate', {
379
- expression: expr, awaitPromise: params.awaitPromise !== false, returnByValue: true,
380
- }, sid);
381
- if (r.exceptionDetails) throw { error: 'script error', message: r.exceptionDetails.text || 'eval error' };
382
- const cr = r.result || {};
383
- let bv;
384
- if (cr.type === 'undefined' || cr.value === undefined) bv = { type: 'undefined' };
385
- else if (cr.value === null) bv = { type: 'null' };
386
- else bv = { type: cr.type, value: cr.value };
387
- result = { realm: ctx, result: bv };
446
+ let evalExpr = params.expression || '';
447
+ let evalWrapped = evalExpr.includes('=>') || evalExpr.startsWith('function') ? '(' + evalExpr + ')()' : '(function(){try{return (' + evalExpr + ')}catch(e){return {__error:e.message}}})()';
448
+ const evalR = await cdpSend('Runtime.evaluate', { expression: evalWrapped, awaitPromise: params.awaitPromise !== false, returnByValue: true }, sid);
449
+ if (evalR.exceptionDetails) throw { error: 'script error', message: evalR.exceptionDetails.text || 'eval error' };
450
+ const evalCr = evalR.result || {};
451
+ let evalBv;
452
+ if (evalCr.type === 'undefined' || evalCr.value === undefined) evalBv = { type: 'undefined' };
453
+ else if (evalCr.value === null) evalBv = { type: 'null' };
454
+ else if (evalCr.value && evalCr.value.__error) throw { error: 'script error', message: evalCr.value.__error };
455
+ else evalBv = { type: evalCr.type, value: evalCr.value };
456
+ result = { realm: ctx, result: evalBv };
388
457
  break;
389
458
  }
390
459
 
@@ -432,29 +501,29 @@ async function handleBiDi(msg) {
432
501
  console.log('[bridge] CDP screenshot failed, trying hdc fallback...');
433
502
  }
434
503
 
435
- // Strategy 2: hdc snapshot_display fallback
504
+ // Strategy 2: snapshot_display fallback (local system command)
436
505
  if (!imageData) {
437
506
  try {
438
507
  const { execSync } = require('child_process');
439
508
  const fs = require('fs');
440
- const hdcPath = '/data/service/hnp/bin/hdc';
441
509
 
442
510
  // Take screenshot - snapshot_display saves to /data/local/tmp/snapshot_<timestamp>.jpeg
443
- const output = execSync(`${hdcPath} shell snapshot_display`, { timeout: 10000, encoding: 'utf-8' });
511
+ const output = execSync('snapshot_display', { timeout: 10000, encoding: 'utf-8' });
444
512
  // Parse stdout for filename
445
513
  const match = output.match(/set filename to (.+\.jpeg)/);
446
514
  if (!match) throw new Error('snapshot_display did not return filename');
447
515
  const deviceFile = match[1];
448
516
 
449
- // Receive file from device
517
+ // Copy screenshot from local filesystem
450
518
  const localFile = '/storage/Users/currentUser/tmp/bridge_ss.jpeg';
451
- execSync(`${hdcPath} file recv ${deviceFile} ${localFile}`, { timeout: 10000 });
519
+ fs.mkdirSync(require('path').dirname(localFile), { recursive: true });
520
+ fs.copyFileSync(deviceFile, localFile);
452
521
  const buf = fs.readFileSync(localFile);
453
522
  imageData = buf.toString('base64');
454
- console.log('[bridge] Screenshot via hdc:', buf.length, 'bytes');
523
+ console.log('[bridge] Screenshot via snapshot_display:', buf.length, 'bytes');
455
524
  } catch(e) {
456
- console.error('[bridge] hdc screenshot failed:', e.message.substring(0, 80));
457
- throw { error: 'screenshot', message: 'Screenshot failed: CDP and hdc both failed' };
525
+ console.error('[bridge] snapshot_display screenshot failed:', e.message.substring(0, 80));
526
+ throw { error: 'screenshot', message: 'Screenshot failed: CDP and snapshot_display both failed' };
458
527
  }
459
528
  }
460
529
 
@@ -601,6 +670,126 @@ async function handleBiDi(msg) {
601
670
  break;
602
671
  }
603
672
 
673
+
674
+ // ── vibium:page.eval ──
675
+ case 'vibium:page.eval': {
676
+ var peCtx = params.context || mainContextId;
677
+ await ensureSession(peCtx);
678
+ var peSid = getSession(peCtx);
679
+ var peR = await cdpSend('Runtime.evaluate', { expression: params.expression || '', returnByValue: true, awaitPromise: false }, peSid);
680
+ if (peR.exceptionDetails) throw { error: 'eval error', message: peR.exceptionDetails.text || 'eval error' };
681
+ result = { value: peR.result ? peR.result.value : undefined };
682
+ break;
683
+ }
684
+ case 'vibium:page.find': {
685
+ var pfCtx = params.context || mainContextId;
686
+ await ensureSession(pfCtx);
687
+ var pfSid = getSession(pfCtx);
688
+ var pfSel = params.selector || '';
689
+ var pfExpr = '(function(){var el=document.querySelector(' + JSON.stringify(pfSel) + ');if(!el)return null;var b=el.getBoundingClientRect();return{tag:el.tagName.toLowerCase(),text:(el.textContent||"").substring(0,1000),box:{x:b.x,y:b.y,width:b.width,height:b.height}}})()';
690
+ var pfR = await cdpSend('Runtime.evaluate', { expression: pfExpr, returnByValue: true, awaitPromise: false }, pfSid);
691
+ if (pfR.exceptionDetails) throw { error: 'not found', message: pfR.exceptionDetails.text || 'find error' };
692
+ if (!pfR.result || !pfR.result.value) throw { error: 'not found', message: 'timeout after 30000ms waiting for ' + pfSel };
693
+ result = pfR.result.value;
694
+ break;
695
+ }
696
+ case 'vibium:page.findAll': {
697
+ var paCtx = params.context || mainContextId;
698
+ await ensureSession(paCtx);
699
+ var paSid = getSession(paCtx);
700
+ var paSel = params.selector || '';
701
+ var paExpr = '(function(){var els=document.querySelectorAll(' + JSON.stringify(paSel) + ');var arr=[];for(var i=0;i<els.length;i++){var b=els[i].getBoundingClientRect();arr.push({tag:els[i].tagName.toLowerCase(),text:(els[i].textContent||"").substring(0,1000),box:{x:b.x,y:b.y,width:b.width,height:b.height},index:i})}return{elements:arr}})()';
702
+ var paR = await cdpSend('Runtime.evaluate', { expression: paExpr, returnByValue: true }, paSid);
703
+ result = paR.result ? paR.result.value : { elements: [] };
704
+ break;
705
+ }
706
+ case 'vibium:page.title': { var tSid = getSession(params.context || mainContextId); var tR = await cdpSend('Runtime.evaluate', { expression: 'document.title', returnByValue: true }, tSid); result = { title: tR.result ? tR.result.value : '' }; break; }
707
+ case 'vibium:page.url': { var uSid = getSession(params.context || mainContextId); var uR = await cdpSend('Runtime.evaluate', { expression: 'location.href', returnByValue: true }, uSid); result = { url: uR.result ? uR.result.value : '' }; break; }
708
+ case 'vibium:page.content': { var cSid = getSession(params.context || mainContextId); var cR = await cdpSend('Runtime.evaluate', { expression: 'document.documentElement.outerHTML', returnByValue: true }, cSid); result = { content: cR.result ? cR.result.value : '' }; break; }
709
+ case 'vibium:page.screenshot': { var ssCtx = params.context || mainContextId; var ssSid = getSession(ssCtx); var ssR = await cdpSend('Page.captureScreenshot', { format: 'png' }, ssSid).catch(function(){return{}}); result = { data: ssR.data || '' }; break; }
710
+ case 'vibium:page.reload': { var rSid = getSession(params.context || mainContextId); await cdpSend('Page.reload', {}, rSid).catch(function(){}); result = {}; break; }
711
+ case 'vibium:page.navigate': { var ngCtx = params.context || mainContextId; var ngSid = getSession(ngCtx); await cdpSend('Page.navigate', { url: params.url }, ngSid); var ngR; var ngResolve; var ngP = new Promise(function(r){ngResolve=r}); pageLoadCallbacks.set(ngSid, ngResolve); pageLoadCallbacks.set(ngCtx, ngResolve); await Promise.race([ngP, new Promise(function(r){setTimeout(r,5000)})]); pageLoadCallbacks.delete(ngSid); pageLoadCallbacks.delete(ngCtx); result = { url: params.url }; break; }
712
+ case 'vibium:page.waitForLoad': { result = {}; break; }
713
+ case 'vibium:page.waitForURL': { var wuCtx = params.context || mainContextId; var wuSid = getSession(wuCtx); var wuUrl = params.url || ''; var wuR = await cdpSend('Runtime.evaluate', { expression: 'location.href', returnByValue: true }, wuSid); if ((wuR.result && wuR.result.value || '').indexOf(wuUrl) >= 0) { result = {}; } else { result = { error: 'timeout', message: 'waitForURL timeout: ' + wuUrl }; } break; }
714
+ case 'vibium:page.waitForFunction': { var wfCtx = params.context || mainContextId; var wfSid = getSession(wfCtx); var wfFn = params.fn || params.function || '() => true'; var wfExpr = wfFn.includes('=>') || wfFn.startsWith('function') ? '(' + wfFn + ')()' : wfFn; var wfTimeout = params.timeout || 30000; var wfStart = Date.now(); var wfVal = false; while (Date.now() - wfStart < wfTimeout) { try { var wfR = await cdpSend('Runtime.evaluate', { expression: wfExpr, returnByValue: true }, wfSid); if (wfR.result && wfR.result.value) { wfVal = true; break; } } catch(e) {} await new Promise(function(r){setTimeout(r,200)}); } result = { value: wfVal }; break; }
715
+ case 'vibium:page.emulateMedia': { var emSid = getSession(params.context || mainContextId); var emMm = {}; if (params.colorScheme) emMm['prefers-color-scheme'] = params.colorScheme; if (params.media) emMm['media'] = params.media; if (params.reducedMotion) emMm['prefers-reduced-motion'] = params.reducedMotion; if (Object.keys(emMm).length > 0) { var emStr = JSON.stringify(emMm); var emExpr = 'window.__mm=' + emStr + ';if(!window.__mmOrig)window.__mmOrig=window.matchMedia.bind(window);window.matchMedia=function(q){var r=window.__mmOrig(q);for(var k in window.__mm){if(q.indexOf(k)>=0){var m=Object.create(r);m.matches=q.indexOf(window.__mm[k])>=0;return m;}}return r;};'; await cdpSend('Runtime.evaluate', { expression: emExpr, returnByValue: true }, emSid).catch(function(){}); } result = {}; break; }
716
+ case 'vibium:page.setContent': { var scSid = getSession(params.context || mainContextId); await cdpSend('Runtime.evaluate', { expression: 'document.open();document.write(' + JSON.stringify(params.content || '') + ');document.close()', returnByValue: true }, scSid); result = {}; break; }
717
+ case 'vibium:page.frames': { var frSid = getSession(params.context || mainContextId); var frR = await cdpSend('Page.getFrameTree', {}, frSid); var frFrames = []; function frWalk(ft) { frFrames.push({url: ft.frame.url, name: ft.frame.name || '', context: ctx}); if (ft.childFrames) for (var c of ft.childFrames) frWalk(c); } if (frR.frameTree) frWalk(frR.frameTree); result = { frames: frFrames }; break; }
718
+ case 'vibium:page.frame': { var fmSid = getSession(params.context || mainContextId); var fmR = await cdpSend('Page.getFrameTree', {}, fmSid); var fmFound = null; function fmFind(ft, p) { if (p(ft.frame)) return ft.frame; if (ft.childFrames) for (var c of ft.childFrames) { var f = fmFind(c, p); if (f) return f; } return null; } if (fmR.frameTree) fmFound = fmFind(fmR.frameTree, function(f) { return (params.url && f.url.indexOf(params.url) >= 0) || (params.name && f.name === params.name); }); result = fmFound ? { url: fmFound.url, name: fmFound.name || '', context: ctx } : null; break; }
719
+ case 'vibium:page.a11yTree': { var aSid = getSession(params.context || mainContextId); var aExpr = '(function(){function gr(el){var r=el.getAttribute("role");if(r)return r;var m={a:"link",button:"button",h1:"heading",h2:"heading",h3:"heading",h4:"heading",h5:"heading",h6:"heading",img:"image",input:"textbox",nav:"navigation",main:"main",ul:"list",ol:"list",li:"listitem",select:"combobox",textarea:"textbox",form:"form",section:"region",article:"article",header:"banner",footer:"contentinfo"};return m[el.tagName.toLowerCase()]||"generic"}function gl(el){var a=el.getAttribute("aria-label");if(a)return a;var l=el.getAttribute("aria-labelledby");if(l){var t=document.getElementById(l);if(t)return t.textContent.trim()}var lbl=document.querySelector("label[for="+JSON.stringify(el.id)+"]");if(lbl)return lbl.textContent.trim();return el.textContent.trim().substring(0,100)}function w(el){var n={role:gr(el),name:gl(el)};if(el.tagName==="INPUT"&&el.type==="checkbox")n.checked=el.checked;if(el.tagName==="BUTTON"||el.tagName==="INPUT")n.disabled=el.disabled;if(el.tagName.match(/H[1-6]/))n.level=parseInt(el.tagName[1]);var ch=[];for(var i=0;i<el.children.length;i++)ch.push(w(el.children[i]));if(ch.length)n.children=ch;return n}return w(document.body)})()'; var aR = await cdpSend('Runtime.evaluate', { expression: aExpr, returnByValue: true }, aSid); result = aR.result && aR.result.value ? aR.result.value : { role: 'WebArea', name: '' }; break; }
720
+ case 'vibium:page.setViewport': { result = {}; break; }
721
+ case 'vibium:page.setWindow': { result = {}; break; }
722
+ case 'vibium:page.window': { result = { width: 1280, height: 720, x: 0, y: 0 }; break; }
723
+ case 'vibium:page.setGeolocation': { result = {}; break; }
724
+ case 'vibium:page.handleDialog': { var hdSid = getSession(params.context || mainContextId); await cdpSend('Page.handleJavaScriptDialog', { accept: params.accept !== false, promptText: params.promptText || '' }, hdSid).catch(function(){}); result = {}; break; }
725
+ case 'vibium:page.route': { result = {}; break; }
726
+ case 'vibium:page.unroute': { result = {}; break; }
727
+ case 'vibium:page.onWebSocket': { result = {}; break; }
728
+ case 'vibium:page.onConsole': { result = {}; break; }
729
+ case 'vibium:page.onError': { result = {}; break; }
730
+ case 'vibium:page.consoleMessages': { result = { messages: [] }; break; }
731
+ case 'vibium:page.errors': { result = { errors: [] }; break; }
732
+ case 'vibium:element.text': { var eSid = getSession(params.context || mainContextId); var eSel = params.selector || ''; var eIdx = params.index || 0; var eR = await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(eSel) + ')[' + eIdx + ']?.textContent||"")', returnByValue: true }, eSid); result = { text: eR.result ? eR.result.value : '' }; break; }
733
+ case 'vibium:element.innerText': { var eiSid = getSession(params.context || mainContextId); var eiSel = params.selector || ''; var eiIdx = params.index || 0; var eiR = await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(eiSel) + ')[' + eiIdx + ']?.innerText||"")', returnByValue: true }, eiSid); result = { text: eiR.result ? eiR.result.value : '' }; break; }
734
+ case 'vibium:element.html': { var ehSid = getSession(params.context || mainContextId); var ehSel = params.selector || ''; var ehIdx = params.index || 0; var ehR = await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(ehSel) + ')[' + ehIdx + ']?.innerHTML||"")', returnByValue: true }, ehSid); result = { html: ehR.result ? ehR.result.value : '' }; break; }
735
+ case 'vibium:element.value': { var evSid = getSession(params.context || mainContextId); var evSel = params.selector || ''; var evIdx = params.index || 0; var evR = await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(evSel) + ')[' + evIdx + ']?.value||"")', returnByValue: true }, evSid); result = { value: evR.result ? evR.result.value : '' }; break; }
736
+ case 'vibium:element.attr': { var atSid = getSession(params.context || mainContextId); var atSel = params.selector || ''; var atIdx = params.index || 0; var atName = params.name || ''; var atR = await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(atSel) + ')[' + atIdx + ']?.getAttribute(' + JSON.stringify(atName) + ')||null)', returnByValue: true }, atSid); result = { value: atR.result ? atR.result.value : null }; break; }
737
+ case 'vibium:element.bounds': { var bdSid = getSession(params.context || mainContextId); var bdSel = params.selector || ''; var bdIdx = params.index || 0; var bdR = await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(bdSel) + ')[' + bdIdx + '];if(!el)return{};var b=el.getBoundingClientRect();return{x:b.x,y:b.y,width:b.width,height:b.height}})()', returnByValue: true }, bdSid); result = bdR.result ? bdR.result.value : {}; break; }
738
+ case 'vibium:element.click': { var clSid = getSession(params.context || mainContextId); var clSel = params.selector || ''; var clIdx = params.index || 0; await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(clSel) + ')[' + clIdx + ']?.click(),true)', returnByValue: true }, clSid); result = {}; break; }
739
+ case 'vibium:element.dblclick': { var dcSid = getSession(params.context || mainContextId); var dcSel = params.selector || ''; var dcIdx = params.index || 0; await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(dcSel) + ')[' + dcIdx + '];if(el){el.focus();if(el.select){el.select()}else{var r=document.createRange();r.selectNodeContents(el);var s=window.getSelection();s.removeAllRanges();s.addRange(r)}el.dispatchEvent(new MouseEvent("dblclick",{bubbles:true}))}})()', returnByValue: true }, dcSid); result = {}; break; }
740
+ case 'vibium:element.type': { var tpSid = getSession(params.context || mainContextId); var tpSel = params.selector || ''; var tpIdx = params.index || 0; var tpText = params.text || ''; var tpExpr = '(function(){var el=document.querySelectorAll(' + JSON.stringify(tpSel) + ')[' + tpIdx + '];if(el){el.focus();el.value=(el.value||"")+' + JSON.stringify(tpText) + ';el.dispatchEvent(new Event("input",{bubbles:true}));el.dispatchEvent(new Event("change",{bubbles:true}))}})()'; await cdpSend('Runtime.evaluate', { expression: tpExpr, returnByValue: true }, tpSid); result = {}; break; }
741
+ case 'vibium:element.fill': { var flSid = getSession(params.context || mainContextId); var flSel = params.selector || ''; var flIdx = params.index || 0; var flText = params.text || ''; var flExpr = '(function(){var el=document.querySelectorAll(' + JSON.stringify(flSel) + ')[' + flIdx + '];if(el){el.focus();el.value=' + JSON.stringify(flText) + ';el.dispatchEvent(new Event("input",{bubbles:true}));el.dispatchEvent(new Event("change",{bubbles:true}))}})()'; await cdpSend('Runtime.evaluate', { expression: flExpr, returnByValue: true }, flSid); result = {}; break; }
742
+ case 'vibium:element.clear': { var crSid = getSession(params.context || mainContextId); var crSel = params.selector || ''; var crIdx = params.index || 0; await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(crSel) + ')[' + crIdx + '];if(el){el.value="";el.dispatchEvent(new Event("input",{bubbles:true}))}})()', returnByValue: true }, crSid); result = {}; break; }
743
+ case 'vibium:element.hover': { var hvSid = getSession(params.context || mainContextId); var hvSel = params.selector || ''; var hvIdx = params.index || 0; var hvR = await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(hvSel) + ')[' + hvIdx + '];if(el){var r=el.getBoundingClientRect();return{x:r.x+r.width/2,y:r.y+r.height/2}}return null})()', returnByValue: true }, hvSid); if (hvR.result && hvR.result.value) { var hvV = hvR.result.value; await cdpSend('Input.dispatchMouseEvent', { type: 'mouseMoved', x: hvV.x, y: hvV.y }, hvSid); } result = {}; break; }
744
+ case 'vibium:element.focus': { var fcSid = getSession(params.context || mainContextId); var fcSel = params.selector || ''; var fcIdx = params.index || 0; await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(fcSel) + ')[' + fcIdx + ']?.focus(),true)', returnByValue: true }, fcSid); result = {}; break; }
745
+ case 'vibium:element.press': { var prSid = getSession(params.context || mainContextId); var prSel = params.selector || ''; var prIdx = params.index || 0; await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(prSel) + ')[' + prIdx + ']?.focus(),true)', returnByValue: true }, prSid); var prKey = params.key || 'Enter'; await cdpSend('Input.dispatchKeyEvent', { type: 'keyDown', key: prKey }, prSid); await cdpSend('Input.dispatchKeyEvent', { type: 'keyUp', key: prKey }, prSid); if (prKey === 'Enter') { await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.activeElement;if(el){var f=el.closest("form");if(f){f.dispatchEvent(new Event("submit",{bubbles:true,cancelable:true}));f.submit()}}})()', returnByValue: true }, prSid).catch(function(){}); } result = {}; break; }
746
+ case 'vibium:element.selectOption': { var soSid = getSession(params.context || mainContextId); var soSel = params.selector || ''; var soIdx = params.index || 0; var soVal = params.value || ''; var soR = await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(soSel) + ')[' + soIdx + '];if(!el)return false;var opts=el.options;if(!opts)return false;for(var i=0;i<opts.length;i++){if(opts[i].textContent.trim()===' + JSON.stringify(soVal) + '||opts[i].value===' + JSON.stringify(soVal) + '){el.selectedIndex=i;el.dispatchEvent(new Event("change",{bubbles:true}));return true}}return false})()', returnByValue: true }, soSid); if (!soR.result || !soR.result.value) throw { error: 'not found', message: 'no option matching: ' + soVal }; result = {}; break; }
747
+ case 'vibium:element.dispatchEvent': { var dsSid = getSession(params.context || mainContextId); var dsSel = params.selector || ''; var dsIdx = params.index || 0; var dsType = params.type || 'Event'; await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(dsSel) + ')[' + dsIdx + '];if(el){el.dispatchEvent(new CustomEvent(' + JSON.stringify(dsType) + ',{bubbles:true,cancelable:true}))}})()', returnByValue: true }, dsSid); result = {}; break; }
748
+ case 'vibium:element.scrollIntoView': { var siSid = getSession(params.context || mainContextId); var siSel = params.selector || ''; var siIdx = params.index || 0; await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(siSel) + ')[' + siIdx + ']?.scrollIntoView({block:"center"}),true)', returnByValue: true }, siSid); result = {}; break; }
749
+ case 'vibium:element.check': { var ckSid = getSession(params.context || mainContextId); var ckSel = params.selector || ''; var ckIdx = params.index || 0; await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(ckSel) + ')[' + ckIdx + '];if(el){el.checked=true;el.dispatchEvent(new Event("change",{bubbles:true}))}})()', returnByValue: true }, ckSid); result = {}; break; }
750
+ case 'vibium:element.uncheck': { var ucSid = getSession(params.context || mainContextId); var ucSel = params.selector || ''; var ucIdx = params.index || 0; await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(ucSel) + ')[' + ucIdx + '];if(el){el.checked=false;el.dispatchEvent(new Event("change",{bubbles:true}))}})()', returnByValue: true }, ucSid); result = {}; break; }
751
+ case 'vibium:element.isVisible': { var ivSid = getSession(params.context || mainContextId); var ivSel = params.selector || ''; var ivIdx = params.index || 0; var ivR = await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(ivSel) + ')[' + ivIdx + ']?.offsetParent !== null)', returnByValue: true }, ivSid); result = { visible: ivR.result ? ivR.result.value : false }; break; }
752
+ case 'vibium:element.isHidden': { var ihSid = getSession(params.context || mainContextId); var ihSel = params.selector || ''; var ihIdx = params.index || 0; var ihR = await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(ihSel) + ')[' + ihIdx + ']?.offsetParent === null)', returnByValue: true }, ihSid); result = { hidden: ihR.result ? ihR.result.value : false }; break; }
753
+ case 'vibium:element.isEnabled': { var ieSid = getSession(params.context || mainContextId); var ieSel = params.selector || ''; var ieIdx = params.index || 0; var ieR = await cdpSend('Runtime.evaluate', { expression: '(!document.querySelectorAll(' + JSON.stringify(ieSel) + ')[' + ieIdx + ']?.disabled)', returnByValue: true }, ieSid); result = { enabled: ieR.result ? ieR.result.value : false }; break; }
754
+ case 'vibium:element.isChecked': { var icSid = getSession(params.context || mainContextId); var icSel = params.selector || ''; var icIdx = params.index || 0; var icR = await cdpSend('Runtime.evaluate', { expression: '(document.querySelectorAll(' + JSON.stringify(icSel) + ')[' + icIdx + ']?.checked||false)', returnByValue: true }, icSid); result = { checked: icR.result ? icR.result.value : false }; break; }
755
+ case 'vibium:element.isEditable': { var edSid = getSession(params.context || mainContextId); var edSel = params.selector || ''; var edIdx = params.index || 0; var edR = await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(edSel) + ')[' + edIdx + '];return el&&!el.disabled&&!el.readOnly})()', returnByValue: true }, edSid); result = { editable: edR.result ? edR.result.value : false }; break; }
756
+ case 'vibium:element.screenshot': { var esSid = getSession(params.context || mainContextId); var esR = await cdpSend('Page.captureScreenshot', { format: 'png' }, esSid).catch(function(){return{}}); result = { data: esR.data || '' }; break; }
757
+ case 'vibium:element.role': { var rlSid = getSession(params.context || mainContextId); var rlSel = params.selector || ''; var rlIdx = params.index || 0; var rlR = await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(rlSel) + ')[' + rlIdx + '];if(!el)return "generic";var r=el.getAttribute("role");if(r)return r;var m={a:"link",button:"button",h1:"heading",h2:"heading",h3:"heading",h4:"heading",h5:"heading",h6:"heading",img:"image",input:"textbox",nav:"navigation",main:"main",ul:"list",ol:"list",li:"listitem",select:"combobox",textarea:"textbox",form:"form",section:"region",article:"article",header:"banner",footer:"contentinfo"};return m[el.tagName.toLowerCase()]||"generic"})()', returnByValue: true }, rlSid); result = { role: rlR.result ? rlR.result.value : 'generic' }; break; }
758
+ case 'vibium:element.label': { var lbSid = getSession(params.context || mainContextId); var lbSel = params.selector || ''; var lbIdx = params.index || 0; var lbR = await cdpSend('Runtime.evaluate', { expression: '(function(){var el=document.querySelectorAll(' + JSON.stringify(lbSel) + ')[' + lbIdx + '];if(!el)return "";var a=el.getAttribute("aria-label");if(a)return a;var l=el.getAttribute("aria-labelledby");if(l){var t=document.getElementById(l);if(t)return t.textContent.trim()}var lbl=document.querySelector("label[for="+JSON.stringify(el.id)+"]");if(lbl)return lbl.textContent.trim();return el.textContent.trim().substring(0,100)})()', returnByValue: true }, lbSid); result = { label: lbR.result ? lbR.result.value : '' }; break; }
759
+ case 'vibium:element.find': { var efSid = getSession(params.context || mainContextId); var efSel = params.selector || ''; var efScope = params.scope || ''; var efScopeExpr = efScope ? 'document.querySelector(' + JSON.stringify(efScope) + ')' : 'document'; var efExpr = '(function(){var sc=' + efScopeExpr + ';if(!sc)return null;var el=sc.querySelector(' + JSON.stringify(efSel) + ');if(!el)return null;var b=el.getBoundingClientRect();return{tag:el.tagName.toLowerCase(),text:(el.textContent||"").substring(0,1000),box:{x:b.x,y:b.y,width:b.width,height:b.height}}})()'; var efR = await cdpSend('Runtime.evaluate', { expression: efExpr, returnByValue: true }, efSid); if (!efR.result || !efR.result.value) throw { error: 'not found', message: 'element not found: ' + efSel }; result = efR.result.value; break; }
760
+ case 'vibium:element.findAll': { var eaSid = getSession(params.context || mainContextId); var eaSel = params.selector || ''; var eaScope = params.scope || ''; var eaScopeExpr = eaScope ? 'document.querySelector(' + JSON.stringify(eaScope) + ')' : 'document'; var eaExpr = '(function(){var sc=' + eaScopeExpr + ';if(!sc)return{elements:[]};var els=sc.querySelectorAll(' + JSON.stringify(eaSel) + ');var arr=[];for(var i=0;i<els.length;i++){var b=els[i].getBoundingClientRect();arr.push({tag:els[i].tagName.toLowerCase(),text:(els[i].textContent||"").substring(0,1000),box:{x:b.x,y:b.y,width:b.width,height:b.height},index:i})}return{elements:arr}})()'; var eaR = await cdpSend('Runtime.evaluate', { expression: eaExpr, returnByValue: true }, eaSid); result = eaR.result ? eaR.result.value : { elements: [] }; break; }
761
+ case 'vibium:keyboard.type': { var ktSid = getSession(params.context || mainContextId); await cdpSend('Runtime.evaluate', { expression: 'document.activeElement && (document.activeElement.value = (document.activeElement.value||"") + ' + JSON.stringify(params.text || '') + ')', returnByValue: true }, ktSid).catch(function(){}); result = {}; break; }
762
+ case 'vibium:keyboard.press': { var kpSid = getSession(params.context || mainContextId); var kpKey = params.key || 'Enter'; await cdpSend('Input.dispatchKeyEvent', { type: 'keyDown', key: kpKey }, kpSid); await cdpSend('Input.dispatchKeyEvent', { type: 'keyUp', key: kpKey }, kpSid); result = {}; break; }
763
+ case 'vibium:keyboard.down': { var kdSid = getSession(params.context || mainContextId); await cdpSend('Input.dispatchKeyEvent', { type: 'keyDown', key: params.key || 'Enter' }, kdSid); result = {}; break; }
764
+ case 'vibium:keyboard.up': { var kuSid = getSession(params.context || mainContextId); await cdpSend('Input.dispatchKeyEvent', { type: 'keyUp', key: params.key || 'Enter' }, kuSid); result = {}; break; }
765
+ case 'vibium:mouse.click': { var mcSid = getSession(params.context || mainContextId); await cdpSend('Input.dispatchMouseEvent', { type: 'mousePressed', x: params.x || 0, y: params.y || 0, button: 'left', clickCount: 1 }, mcSid); await cdpSend('Input.dispatchMouseEvent', { type: 'mouseReleased', x: params.x || 0, y: params.y || 0, button: 'left', clickCount: 1 }, mcSid); result = {}; break; }
766
+ case 'vibium:mouse.move': { var mmSid = getSession(params.context || mainContextId); await cdpSend('Input.dispatchMouseEvent', { type: 'mouseMoved', x: params.x || 0, y: params.y || 0 }, mmSid); result = {}; break; }
767
+ case 'vibium:mouse.down': { var mdSid = getSession(params.context || mainContextId); await cdpSend('Input.dispatchMouseEvent', { type: 'mousePressed', x: 0, y: 0, button: 'left', clickCount: 1 }, mdSid); result = {}; break; }
768
+ case 'vibium:mouse.up': { var muSid = getSession(params.context || mainContextId); await cdpSend('Input.dispatchMouseEvent', { type: 'mouseReleased', x: 0, y: 0, button: 'left', clickCount: 1 }, muSid); result = {}; break; }
769
+ case 'vibium:mouse.wheel': { var mwSid = getSession(params.context || mainContextId); await cdpSend('Runtime.evaluate', { expression: 'window.scrollBy(0,' + (params.deltaY || 100) + ')', returnByValue: true }, mwSid); result = {}; break; }
770
+ case 'vibium:clock.install': { result = {}; break; }
771
+ case 'vibium:clock.resume': { result = {}; break; }
772
+ case 'vibium:clock.setTimezone': { result = {}; break; }
773
+ case 'vibium:recording.start': { result = {}; break; }
774
+ case 'vibium:recording.stop': { result = { data: '' }; break; }
775
+ case 'vibium:recording.startChunk': { result = {}; break; }
776
+ case 'vibium:recording.stopChunk': { result = { data: '' }; break; }
777
+ case 'vibium:recording.startGroup': { result = {}; break; }
778
+ case 'vibium:recording.stopGroup': { result = {}; break; }
779
+ case 'vibium:browser.page': { result = { context: mainContextId, userContext: 'default' }; break; }
780
+ case 'vibium:browser.newPage': { var bnCreate = await cdpSend('Target.createTarget', { url: 'about:blank' }); var bnTid = bnCreate.targetId; var bnAtt = await cdpSend('Target.attachToTarget', { targetId: bnTid, flatten: true }); pageSessions[bnTid] = { targetId: bnTid, sessionId: bnAtt.sessionId }; await cdpSend('Page.enable', {}, bnAtt.sessionId).catch(function(){}); await cdpSend('Runtime.enable', {}, bnAtt.sessionId).catch(function(){}); for (var bnPs of pendingPreloadScripts) { try { await cdpSend('Page.addScriptToEvaluateOnNewDocument', { source: bnPs }, bnAtt.sessionId); } catch(e) {} } result = { context: bnTid, userContext: 'default' }; break; }
781
+ case 'vibium:browser.pages': { var bpR = await cdpSend('Target.getTargets', {}); result = { pages: ((bpR.targetInfos || []).filter(function(t){return t.type==='page'}).map(function(t){return {context: t.targetId, userContext: 'default'}})) }; break; }
782
+ case 'vibium:browser.stop': { result = {}; break; }
783
+ case 'vibium:browser.closeContext': { var ccKeys = Object.keys(pageSessions).filter(function(k){return k !== mainContextId}); if (ccKeys.length > 0) { var ccLast = ccKeys[ccKeys.length - 1]; try { await cdpSend('Target.closeTarget', { targetId: ccLast }); } catch(e) {} delete pageSessions[ccLast]; } result = {}; break; }
784
+ case 'vibium:context.newPage': { var cnCreate = await cdpSend('Target.createTarget', { url: 'about:blank' }); var cnTid = cnCreate.targetId; var cnAtt = await cdpSend('Target.attachToTarget', { targetId: cnTid, flatten: true }); pageSessions[cnTid] = { targetId: cnTid, sessionId: cnAtt.sessionId }; await cdpSend('Page.enable', {}, cnAtt.sessionId).catch(function(){}); await cdpSend('Runtime.enable', {}, cnAtt.sessionId).catch(function(){}); for (var cnPs of pendingPreloadScripts) { try { await cdpSend('Page.addScriptToEvaluateOnNewDocument', { source: cnPs }, cnAtt.sessionId); } catch(e) {} } result = { context: cnTid, userContext: params.userContext || 'default' }; break; }
785
+ case 'storage.getCookies': { await discoverAllSessions(); var scCookies = []; var scSessions = [mainSessionId]; for (var scK in pageSessions) { scSessions.push(pageSessions[scK].sessionId); } for (var scI = 0; scI < scSessions.length; scI++) { var scS = scSessions[scI]; try { var scR = await cdpSend('Network.getCookies', { urls: params.urls || [] }, scS); if (scR.cookies) scCookies = scCookies.concat(scR.cookies.map(function(c){c.path=c.path||'/';return c;})); } catch(e) {} try { var scR2 = await cdpSend('Runtime.evaluate', { expression: 'document.cookie', returnByValue: true }, scS); if (scR2.result && scR2.result.value) { scCookies = scCookies.concat(scR2.result.value.split(';').map(function(c){var p=c.trim().split('=');return{name:p[0],value:p.slice(1).join('=')||'',path:'/'};}).filter(function(c){return c.name;})); } } catch(e) {} } var scSeen = {}; scCookies = scCookies.filter(function(c){if(scSeen[c.name])return false;scSeen[c.name]=true;return true;}); result = { cookies: scCookies }; break; }
786
+ case 'storage.setCookie': { await discoverAllSessions(); var stC = params.cookie || {}; if (!stC.domain && stC.url) { try { stC.domain = new URL(stC.url).hostname; } catch(e) {} } var stSessions = [mainSessionId]; for (var stK in pageSessions) { stSessions.push(pageSessions[stK].sessionId); } for (var stI = 0; stI < stSessions.length; stI++) { var stS = stSessions[stI]; try { var stP = { name: stC.name, value: stC.value, domain: stC.domain || '', path: stC.path || '/' }; if (stC.domain) stP.url = 'http://' + stC.domain + (stC.path || '/'); await cdpSend('Network.setCookie', stP, stS); } catch(e) {} try { await cdpSend('Runtime.evaluate', { expression: 'document.cookie = ' + JSON.stringify(stC.name + '=' + stC.value + '; path=' + (stC.path || '/')), returnByValue: true }, stS); } catch(e) {} } result = {}; break; }
787
+ case 'storage.deleteCookies': { await discoverAllSessions(); var dcSessions = [mainSessionId]; for (var dcK in pageSessions) { dcSessions.push(pageSessions[dcK].sessionId); } for (var dcI = 0; dcI < dcSessions.length; dcI++) { try { await cdpSend('Network.clearBrowserCookies', {}, dcSessions[dcI]); } catch(e) {} } result = {}; break; }
788
+ case 'storage.getStorage': { await discoverAllSessions(); var gsCookies = []; var gsOrigins = []; var gsSessions = [mainSessionId]; for (var gsK in pageSessions) { gsSessions.push(pageSessions[gsK].sessionId); } for (var gsI = 0; gsI < gsSessions.length; gsI++) { var gsS = gsSessions[gsI]; try { var gsR = await cdpSend('Network.getCookies', { urls: params.urls || [] }, gsS); if (gsR.cookies) gsCookies = gsCookies.concat(gsR.cookies.map(function(c){c.path=c.path||'/';c.domain=c.domain||'';return c;})); } catch(e) {} try { var gsR2 = await cdpSend('Runtime.evaluate', { expression: 'document.cookie', returnByValue: true }, gsS); if (gsR2.result && gsR2.result.value) { gsCookies = gsCookies.concat(gsR2.result.value.split(';').map(function(c){var p=c.trim().split('=');return{name:p[0],value:p.slice(1).join('=')||'',path:'/'};}).filter(function(c){return c.name;})); } } catch(e) {} try { var gsSt = await cdpSend('Runtime.evaluate', { expression: '(function(){var items=[];for(var i=0;i<localStorage.length;i++){var k=localStorage.key(i);items.push({name:k,value:localStorage.getItem(k)})}return{origin:location.origin,localStorage:items,sessionStorage:[]}})()', returnByValue: true }, gsS); if (gsSt.result && gsSt.result.value) gsOrigins.push(gsSt.result.value); } catch(e) {} } var gsSeen = {}; gsCookies = gsCookies.filter(function(c){if(gsSeen[c.name])return false;gsSeen[c.name]=true;return true;}); gsOrigins = gsOrigins.filter(function(o){return o.localStorage && o.localStorage.length > 0;}); result = { cookies: gsCookies, origins: gsOrigins }; break; }
789
+ case 'storage.setStorage': { await discoverAllSessions(); var ssState = params.state || {}; var ssSessions = [mainSessionId]; for (var ssK in pageSessions) { ssSessions.push(pageSessions[ssK].sessionId); } for (var ssI = 0; ssI < ssSessions.length; ssI++) { var ssS = ssSessions[ssI]; if (ssState.cookies) { for (var ssC of ssState.cookies) { try { var ssP = {name: ssC.name, value: ssC.value, domain: ssC.domain || '', path: ssC.path || '/'}; if (ssC.domain) ssP.url = 'http://' + ssC.domain + (ssC.path || '/'); await cdpSend('Network.setCookie', ssP, ssS); } catch(e) {} try { await cdpSend('Runtime.evaluate', { expression: 'document.cookie = ' + JSON.stringify(ssC.name + '=' + ssC.value + '; path=' + (ssC.path || '/')), returnByValue: true }, ssS); } catch(e) {} } } if (ssState.origins) { for (var ssO of ssState.origins) { if (ssO.localStorage) { for (var ssItem of ssO.localStorage) { try { await cdpSend('Runtime.evaluate', { expression: 'localStorage.setItem(' + JSON.stringify(ssItem.name) + ', ' + JSON.stringify(ssItem.value) + ')', returnByValue: true }, ssS); } catch(e) {} } } if (ssO.sessionStorage) { for (var ssItem of ssO.sessionStorage) { try { await cdpSend('Runtime.evaluate', { expression: 'sessionStorage.setItem(' + JSON.stringify(ssItem.name) + ', ' + JSON.stringify(ssItem.value) + ')', returnByValue: true }, ssS); } catch(e) {} } } } } } result = {}; break; }
790
+ case 'storage.clearStorage': { await discoverAllSessions(); var clSessions = [mainSessionId]; for (var clK in pageSessions) { clSessions.push(pageSessions[clK].sessionId); } for (var clI = 0; clI < clSessions.length; clI++) { try { await cdpSend('Network.clearBrowserCookies', {}, clSessions[clI]); } catch(e) {} try { await cdpSend('Runtime.evaluate', { expression: 'localStorage.clear();sessionStorage.clear()', returnByValue: true }, clSessions[clI]); } catch(e) {} } result = {}; break; }
791
+ case 'script.addPreloadScript': { await discoverAllSessions(); var apsScript = params.script || ''; pendingPreloadScripts.push(apsScript); var apsSessions = [mainSessionId]; for (var apsK in pageSessions) { apsSessions.push(pageSessions[apsK].sessionId); } for (var apsI = 0; apsI < apsSessions.length; apsI++) { try { await cdpSend('Page.addScriptToEvaluateOnNewDocument', { source: apsScript }, apsSessions[apsI]); } catch(e) {} } result = {}; break; }
792
+
604
793
  default:
605
794
  console.log(`[bridge] Unhandled: ${method} (returning empty success)`);
606
795
  result = {};
@@ -618,7 +807,28 @@ async function handleBiDi(msg) {
618
807
  // ─── Server ──────────────────────────────────────────
619
808
  async function start() {
620
809
  await initCDP();
621
- const wss = new WebSocket.Server({ port: LISTEN_PORT });
810
+ // HTTP endpoint for monkey-patch bypass
811
+ const httpServer = http.createServer(function(req, res) {
812
+ if (req.method === 'POST' && req.url === '/cmd') {
813
+ var body = '';
814
+ req.on('data', function(c) { body += c; });
815
+ req.on('end', function() {
816
+ try {
817
+ var hMsg = JSON.parse(body);
818
+ hMsg.id = hMsg.id || Date.now();
819
+ handleBiDi(hMsg).then(function(resp) {
820
+ res.writeHead(200, {'Content-Type':'application/json'});
821
+ res.end(JSON.stringify(resp));
822
+ }).catch(function(e) {
823
+ res.writeHead(200, {'Content-Type':'application/json'});
824
+ res.end(JSON.stringify({ id: hMsg.id, error: { code: 'unknown', message: e.message || 'error' } }));
825
+ });
826
+ } catch(e) { res.writeHead(400); res.end('{}'); }
827
+ });
828
+ } else { res.writeHead(404); res.end(); }
829
+ });
830
+ httpServer.listen(9518);
831
+ const wss = new WebSocket.Server({ port: LISTEN_PORT });
622
832
  wss.on('connection', (ws, req) => {
623
833
  console.log(`[bridge] Client: ${req.url}`);
624
834
  bidiWs = ws; // Store for event forwarding
package/dist/index.js CHANGED
@@ -2421,7 +2421,7 @@ var browser = {
2421
2421
  if (process.platform === "openharmony" && !process.env.VIBIUM_CONNECT_URL) {
2422
2422
  process.env.VIBIUM_SKIP_BROWSER_DOWNLOAD = "1";
2423
2423
  const vibiumHome = process.env.HOME || "/storage/Users/currentUser";
2424
- const hdcPath = "/data/service/hnp/bin/hdc";
2424
+ const aaPath = "/system/bin/cli_tool/executable/ohos-aa";
2425
2425
  const bridgePath = require("path").join(__dirname, "bidi-bridge.js");
2426
2426
  const cdpPort = options.cdpPort || 9333;
2427
2427
  const bridgePort = options.bridgePort || 9517;
@@ -2432,9 +2432,9 @@ var browser = {
2432
2432
  const { execFileSync, spawn } = require("child_process");
2433
2433
  const fs = require("fs");
2434
2434
  const http = require("http");
2435
- execFileSync(hdcPath, ["shell", "aa", "force-stop", browserPkg], { timeout: 1e4, stdio: "pipe" });
2435
+ execFileSync(aaPath, ["force-stop", browserPkg], { timeout: 1e4, stdio: "pipe" });
2436
2436
  const cmdArgs = `--remote-debugging-port=${cdpPort} --remote-allow-origins=http://127.0.0.1:${cdpPort} --disable-extensions --no-first-run --no-default-browser-check --disable-popup-blocking --disable-dev-shm-usage --password-store=basic --use-mock-keychain --force-color-profile=srgb`;
2437
- execFileSync(hdcPath, ["shell", "aa", "start", "-b", browserPkg, "-a", browserAbility, "--ps", "cmdArgs", cmdArgs], { timeout: 1e4, stdio: "pipe" });
2437
+ execFileSync(aaPath, ["start", "-b", browserPkg, "-a", browserAbility, "--ps", "cmdArgs", cmdArgs], { timeout: 1e4, stdio: "pipe" });
2438
2438
  for (let i = 0; i < 15; i++) {
2439
2439
  try {
2440
2440
  await new Promise((resolve2, reject2) => {
@@ -2481,7 +2481,7 @@ var browser = {
2481
2481
  });
2482
2482
  } catch (err) {
2483
2483
  if (process.platform === "openharmony" && err instanceof BrowserCrashedError) {
2484
- throw new BrowserCrashedError(err.exitCode, (err.output || "") + "\n\n[HarmonyOS] Browser launch failed. To use the native browser:\n Ensure hdc is available and the browser is installed.\nTo use a remote browser:\n export VIBIUM_CONNECT_URL=ws://<remote-host>:9222/session");
2484
+ throw new BrowserCrashedError(err.exitCode, (err.output || "") + "\n\n[HarmonyOS] Browser launch failed. To use the native browser:\n Ensure ohos-aa is available and the browser is installed.\nTo use a remote browser:\n export VIBIUM_CONNECT_URL=ws://<remote-host>:9222/session");
2485
2485
  }
2486
2486
  throw err;
2487
2487
  }
package/dist/index.mjs CHANGED
@@ -2364,7 +2364,7 @@ var browser = {
2364
2364
  if (process.platform === "openharmony" && !process.env.VIBIUM_CONNECT_URL) {
2365
2365
  process.env.VIBIUM_SKIP_BROWSER_DOWNLOAD = "1";
2366
2366
  const vibiumHome = process.env.HOME || "/storage/Users/currentUser";
2367
- const hdcPath = "/data/service/hnp/bin/hdc";
2367
+ const aaPath = "/system/bin/cli_tool/executable/ohos-aa";
2368
2368
  const bridgePath = require("path").join(__dirname, "bidi-bridge.js");
2369
2369
  const cdpPort = options.cdpPort || 9333;
2370
2370
  const bridgePort = options.bridgePort || 9517;
@@ -2375,9 +2375,9 @@ if (process.platform === "openharmony" && !process.env.VIBIUM_CONNECT_URL) {
2375
2375
  const { execFileSync, spawn } = require("child_process");
2376
2376
  const fs = require("fs");
2377
2377
  const http = require("http");
2378
- execFileSync(hdcPath, ["shell", "aa", "force-stop", browserPkg], { timeout: 1e4, stdio: "pipe" });
2378
+ execFileSync(aaPath, ["force-stop", browserPkg], { timeout: 1e4, stdio: "pipe" });
2379
2379
  const cmdArgs = `--remote-debugging-port=${cdpPort} --remote-allow-origins=http://127.0.0.1:${cdpPort} --disable-extensions --no-first-run --no-default-browser-check --disable-popup-blocking --disable-dev-shm-usage --password-store=basic --use-mock-keychain --force-color-profile=srgb`;
2380
- execFileSync(hdcPath, ["shell", "aa", "start", "-b", browserPkg, "-a", browserAbility, "--ps", "cmdArgs", cmdArgs], { timeout: 1e4, stdio: "pipe" });
2380
+ execFileSync(aaPath, ["start", "-b", browserPkg, "-a", browserAbility, "--ps", "cmdArgs", cmdArgs], { timeout: 1e4, stdio: "pipe" });
2381
2381
  for (let i = 0; i < 15; i++) {
2382
2382
  try {
2383
2383
  await new Promise((resolve2, reject2) => {
@@ -2424,7 +2424,7 @@ if (process.platform === "openharmony" && !process.env.VIBIUM_CONNECT_URL) {
2424
2424
  });
2425
2425
  } catch (err) {
2426
2426
  if (process.platform === "openharmony" && err instanceof BrowserCrashedError) {
2427
- throw new BrowserCrashedError(err.exitCode, (err.output || "") + "\n\n[HarmonyOS] Browser launch failed. To use the native browser:\n Ensure hdc is available and the browser is installed.\nTo use a remote browser:\n export VIBIUM_CONNECT_URL=ws://<remote-host>:9222/session");
2427
+ throw new BrowserCrashedError(err.exitCode, (err.output || "") + "\n\n[HarmonyOS] Browser launch failed. To use the native browser:\n Ensure ohos-aa is available and the browser is installed.\nTo use a remote browser:\n export VIBIUM_CONNECT_URL=ws://<remote-host>:9222/session");
2428
2428
  }
2429
2429
  throw err;
2430
2430
  }
package/dist/worker.js CHANGED
@@ -2370,7 +2370,7 @@ var browser = {
2370
2370
  if (process.platform === "openharmony" && !process.env.VIBIUM_CONNECT_URL) {
2371
2371
  process.env.VIBIUM_SKIP_BROWSER_DOWNLOAD = "1";
2372
2372
  const vibiumHome = process.env.HOME || "/storage/Users/currentUser";
2373
- const hdcPath = "/data/service/hnp/bin/hdc";
2373
+ const aaPath = "/system/bin/cli_tool/executable/ohos-aa";
2374
2374
  const bridgePath = require("path").join(__dirname, "bidi-bridge.js");
2375
2375
  const cdpPort = options.cdpPort || 9333;
2376
2376
  const bridgePort = options.bridgePort || 9517;
@@ -2381,9 +2381,9 @@ if (process.platform === "openharmony" && !process.env.VIBIUM_CONNECT_URL) {
2381
2381
  const { execFileSync, spawn } = require("child_process");
2382
2382
  const fs = require("fs");
2383
2383
  const http = require("http");
2384
- execFileSync(hdcPath, ["shell", "aa", "force-stop", browserPkg], { timeout: 1e4, stdio: "pipe" });
2384
+ execFileSync(aaPath, ["force-stop", browserPkg], { timeout: 1e4, stdio: "pipe" });
2385
2385
  const cmdArgs = `--remote-debugging-port=${cdpPort} --remote-allow-origins=http://127.0.0.1:${cdpPort} --disable-extensions --no-first-run --no-default-browser-check --disable-popup-blocking --disable-dev-shm-usage --password-store=basic --use-mock-keychain --force-color-profile=srgb`;
2386
- execFileSync(hdcPath, ["shell", "aa", "start", "-b", browserPkg, "-a", browserAbility, "--ps", "cmdArgs", cmdArgs], { timeout: 1e4, stdio: "pipe" });
2386
+ execFileSync(aaPath, ["start", "-b", browserPkg, "-a", browserAbility, "--ps", "cmdArgs", cmdArgs], { timeout: 1e4, stdio: "pipe" });
2387
2387
  for (let i = 0; i < 15; i++) {
2388
2388
  try {
2389
2389
  await new Promise((resolve2, reject2) => {
@@ -2430,7 +2430,7 @@ if (process.platform === "openharmony" && !process.env.VIBIUM_CONNECT_URL) {
2430
2430
  });
2431
2431
  } catch (err) {
2432
2432
  if (process.platform === "openharmony" && err instanceof BrowserCrashedError) {
2433
- throw new BrowserCrashedError(err.exitCode, (err.output || "") + "\n\n[HarmonyOS] Browser launch failed. To use the native browser:\n Ensure hdc is available and the browser is installed.\nTo use a remote browser:\n export VIBIUM_CONNECT_URL=ws://<remote-host>:9222/session");
2433
+ throw new BrowserCrashedError(err.exitCode, (err.output || "") + "\n\n[HarmonyOS] Browser launch failed. To use the native browser:\n Ensure ohos-aa is available and the browser is installed.\nTo use a remote browser:\n export VIBIUM_CONNECT_URL=ws://<remote-host>:9222/session");
2434
2434
  }
2435
2435
  throw err;
2436
2436
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ohos-ports/vibium",
3
- "version": "26.5.31-beta.2",
3
+ "version": "26.5.31-beta.4",
4
4
  "description": "Browser automation for AI agents and humans",
5
5
  "keywords": [
6
6
  "browser",
package/README.md DELETED
@@ -1,72 +0,0 @@
1
- # Vibium
2
-
3
- Browser automation for AI agents and humans.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install vibium
9
- ```
10
-
11
- This automatically downloads Chrome for Testing on first install.
12
-
13
- ## Quick Start
14
-
15
- ### Async API
16
-
17
- ```javascript
18
- import { browser } from 'vibium'
19
- import { writeFile } from 'fs/promises'
20
-
21
- const bro = await browser.start()
22
- const vibe = await bro.page()
23
- await vibe.go('https://example.com')
24
-
25
- const link = await vibe.find('a')
26
- console.log(await link.text())
27
- await link.click()
28
-
29
- const screenshot = await vibe.screenshot()
30
- await writeFile('screenshot.png', screenshot)
31
-
32
- await bro.stop()
33
- ```
34
-
35
- ### Sync API
36
-
37
- ```javascript
38
- const { browser } = require('vibium/sync')
39
- const { writeFileSync } = require('fs')
40
-
41
- const bro = browser.start()
42
- const vibe = bro.page()
43
- vibe.go('https://example.com')
44
-
45
- const link = vibe.find('a')
46
- console.log(link.text())
47
- link.click()
48
-
49
- const screenshot = vibe.screenshot()
50
- writeFileSync('screenshot.png', screenshot)
51
-
52
- bro.stop()
53
- ```
54
-
55
- ## Environment Variables
56
-
57
- | Variable | Description |
58
- |----------|-------------|
59
- | `VIBIUM_SKIP_BROWSER_DOWNLOAD` | Set to `1` to skip Chrome download on install |
60
-
61
- ## Requirements
62
-
63
- - Node.js 18+
64
-
65
- ## Links
66
-
67
- - [GitHub / Documentation](https://github.com/VibiumDev/vibium)
68
- - [Website](https://vibium.com)
69
-
70
- ## License
71
-
72
- Apache-2.0