mobridge-mcp 0.9.0 → 0.9.2

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.
@@ -1,2 +1,2 @@
1
- import{execFileSync as E}from"node:child_process";import{createHash as N}from"node:crypto";function x(t){const n=t?["-s",t]:[];return e=>E("adb",[...n,...e],{maxBuffer:64*1024*1024})}function L(t){const n=/\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/.exec(t||"");return n?[+n[1],+n[2],+n[3],+n[4]]:null}function R(t){const n={},e=/([\w-]+)="([^"]*)"/g;let i;for(;i=e.exec(t);)n[i[1]]=i[2].replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"');return n}const o=t=>t==="true";function O(t,n){const e=(t||"").toLowerCase();return e.includes("edittext")?"INPUT":e.includes("switch")?"SWITCH":e.includes("checkbox")?"CHECKBOX":e.includes("radio")?"RADIO":e.includes("button")?"BUTTON":e.includes("webview")?"WEB_VIEW":e.includes("recyclerview")||e.includes("listview")||e.includes("scrollview")||e.includes("gridview")?"LIST":e.includes("seekbar")?"SLIDER":e.includes("progress")?"PROGRESS":e.includes("tab")?"TAB":e.includes("imageview")||e.includes("imagebutton")?o(n.clickable)?"BUTTON":"IMAGE":e.includes("textview")?"TEXT":e.includes("edit")?"INPUT":o(n.clickable)?"BUTTON":"UNKNOWN"}function A(t,n){const e=[];return o(n.clickable)&&e.push("CLICK"),o(n["long-clickable"])&&e.push("LONG_CLICK"),t==="INPUT"&&e.push("FOCUS","SET_TEXT","CLEAR_TEXT"),o(n.scrollable)&&e.push("SCROLL_FORWARD","SCROLL_BACKWARD"),o(n.checkable)&&e.push("SELECT"),[...new Set(e)]}function D(t){if(t.role==="SCREEN")return!0;if(t.bounds&&t.bounds[0]===t.bounds[2]&&t.bounds[1]===t.bounds[3])return!1;const e=t.actions.length>0,i=t.text&&t.text.trim()||t.label&&t.label.trim(),r=["LIST","DIALOG","WEB_VIEW","CANVAS"].includes(t.role);return e||i||r}function S({serial:t=null,compact:n=!1}={}){const e=x(t);e(["shell","uiautomator","dump","/sdcard/msm_dump.xml"]);const i=e(["exec-out","cat","/sdcard/msm_dump.xml"]).toString("utf8"),r=[],a=[];let p=0,d=null;const h=/<(\/?)node\b([^>]*?)(\/?)>/g;let f;for(;f=h.exec(i);){if(f[1]==="/"){a.pop();continue}const u=f[3]==="/",s=R(f[2]),b="n"+p++,l=a.length?a[a.length-1]:null;!d&&s.package&&(d=s.package);const c=p===1?"SCREEN":O(s.class,s),g=o(s.password);r.push({nodeId:b,parentId:l,role:c,label:s["content-desc"]||null,text:s.text?s.text:null,value:c==="INPUT"?g?null:s.text||"":null,hint:null,resourceId:s["resource-id"]||null,className:s.class||null,state:{enabled:o(s.enabled),clickable:o(s.clickable),focused:o(s.focused),selected:o(s.selected),checked:s.checkable==="true"?o(s.checked):null,password:g},actions:A(c,s),bounds:L(s.bounds),source:"ACCESSIBILITY",confidence:1}),u||a.push(b)}let w=r;if(n){const u=new Set(r.filter(D).map(l=>l.nodeId)),s=new Map(r.map(l=>[l.nodeId,l])),b=l=>{let c=l.parentId?s.get(l.parentId):null;for(;c&&!u.has(c.nodeId);)c=c.parentId?s.get(c.parentId):null;return c?c.nodeId:null};w=r.filter(l=>u.has(l.nodeId)).map(l=>({...l,parentId:b(l)}))}const T=x(t)(["shell","wm","size"]).toString(),I=/(\d+)x(\d+)/.exec(T),C=I&&+I[1]>+I[2]?"landscape":"portrait",k=w.map(u=>`${u.role}|${u.text}|${u.label}|${u.resourceId}|${(u.bounds||[]).join(",")}`).join(`
2
- `),m=N("sha1").update(k).digest("hex").slice(0,8);return{schemaVersion:1,deviceId:t||"adb-default",snapshotId:"s_"+Date.now().toString(36),timestamp:Date.now(),packageName:d||"unknown.pkg",windowId:0,orientation:C,screenStateId:(d||"?")+":"+m,compact:n,nodes:w,treeHash:m,_rawNodeCount:r.length}}async function v({serial:t=null,compact:n=!0,timeoutMs:e=6e3,stableForMs:i=600}={}){const r=Date.now();let a=null,p=Date.now();for(;Date.now()-r<e;){const d=S({serial:t,compact:n});if(d.treeHash!==a)a=d.treeHash,p=Date.now();else if(Date.now()-p>=i)return d;await new Promise(h=>setTimeout(h,200))}return S({serial:t,compact:n})}export{S as captureSnapshot,x as makeAdb,v as waitStable};
1
+ import{execFileSync as E}from"node:child_process";import{createHash as N}from"node:crypto";function x(t){const n=t?["-s",t]:[];return e=>E("adb",[...n,...e],{maxBuffer:64*1024*1024})}function L(t){const n=/\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]/.exec(t||"");return n?[+n[1],+n[2],+n[3],+n[4]]:null}function A(t){const n={},e=/([\w-]+)="([^"]*)"/g;let u;for(;u=e.exec(t);)n[u[1]]=u[2].replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"');return n}const c=t=>t==="true";function R(t,n){const e=(t||"").toLowerCase();return e.includes("edittext")?"INPUT":e.includes("switch")?"SWITCH":e.includes("checkbox")?"CHECKBOX":e.includes("radio")?"RADIO":e.includes("button")?"BUTTON":e.includes("webview")?"WEB_VIEW":e.includes("recyclerview")||e.includes("listview")||e.includes("scrollview")||e.includes("gridview")?"LIST":e.includes("surfaceview")||e.includes("textureview")||e.includes("unityplayer")?"CANVAS":e.includes("seekbar")?"SLIDER":e.includes("progress")?"PROGRESS":e.includes("tab")?"TAB":e.includes("imageview")||e.includes("imagebutton")||e.endsWith(".image")?c(n.clickable)?"BUTTON":"IMAGE":e.includes("textview")?"TEXT":e.includes("edit")?"INPUT":c(n.clickable)?"BUTTON":c(n.scrollable)?"LIST":n.text&&n.text.trim()||n["content-desc"]&&n["content-desc"].trim()?"TEXT":"UNKNOWN"}function O(t,n){const e=[];return c(n.clickable)&&e.push("CLICK"),c(n["long-clickable"])&&e.push("LONG_CLICK"),t==="INPUT"&&e.push("FOCUS","SET_TEXT","CLEAR_TEXT"),c(n.scrollable)&&e.push("SCROLL_FORWARD","SCROLL_BACKWARD"),c(n.checkable)&&e.push("SELECT"),[...new Set(e)]}function D(t){if(t.role==="SCREEN")return!0;if(t.bounds&&t.bounds[0]===t.bounds[2]&&t.bounds[1]===t.bounds[3])return!1;const e=t.actions.length>0,u=t.text&&t.text.trim()||t.label&&t.label.trim(),o=["LIST","DIALOG","WEB_VIEW","CANVAS"].includes(t.role);return e||u||o}function T({serial:t=null,compact:n=!1}={}){const e=x(t);e(["shell","uiautomator","dump","/sdcard/msm_dump.xml"]);const u=e(["exec-out","cat","/sdcard/msm_dump.xml"]).toString("utf8"),o=[],a=[];let f=0,d=null;const h=/<(\/?)node\b([^>]*?)(\/?)>/g;let p;for(;p=h.exec(u);){if(p[1]==="/"){a.pop();continue}const i=p[3]==="/",s=A(p[2]),b="n"+f++,l=a.length?a[a.length-1]:null;!d&&s.package&&(d=s.package);const r=f===1?"SCREEN":R(s.class,s),g=c(s.password);o.push({nodeId:b,parentId:l,role:r,label:s["content-desc"]||null,text:s.text?s.text:null,value:r==="INPUT"?g?null:s.text||"":null,hint:null,resourceId:s["resource-id"]||null,className:s.class||null,state:{enabled:c(s.enabled),clickable:c(s.clickable),focused:c(s.focused),selected:c(s.selected),checked:s.checkable==="true"?c(s.checked):null,password:g},actions:O(r,s),bounds:L(s.bounds),source:"ACCESSIBILITY",confidence:1}),i||a.push(b)}let w=o;if(n){const i=new Set(o.filter(D).map(l=>l.nodeId)),s=new Map(o.map(l=>[l.nodeId,l])),b=l=>{let r=l.parentId?s.get(l.parentId):null;for(;r&&!i.has(r.nodeId);)r=r.parentId?s.get(r.parentId):null;return r?r.nodeId:null};w=o.filter(l=>i.has(l.nodeId)).map(l=>({...l,parentId:b(l)}))}const S=x(t)(["shell","wm","size"]).toString(),m=/(\d+)x(\d+)/.exec(S),C=m&&+m[1]>+m[2]?"landscape":"portrait",k=w.map(i=>`${i.role}|${i.text}|${i.label}|${i.resourceId}|${(i.bounds||[]).join(",")}`).join(`
2
+ `),I=N("sha1").update(k).digest("hex").slice(0,8);return{schemaVersion:1,deviceId:t||"adb-default",snapshotId:"s_"+Date.now().toString(36),timestamp:Date.now(),packageName:d||"unknown.pkg",windowId:0,orientation:C,screenStateId:(d||"?")+":"+I,compact:n,nodes:w,treeHash:I,_rawNodeCount:o.length}}async function _({serial:t=null,compact:n=!0,timeoutMs:e=6e3,stableForMs:u=600}={}){const o=Date.now();let a=null,f=Date.now();for(;Date.now()-o<e;){const d=T({serial:t,compact:n});if(d.treeHash!==a)a=d.treeHash,f=Date.now();else if(Date.now()-f>=u)return d;await new Promise(h=>setTimeout(h,200))}return T({serial:t,compact:n})}export{T as captureSnapshot,x as makeAdb,_ as waitStable};