agent-device 0.17.2 → 0.17.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.
Files changed (86) hide show
  1. package/README.md +2 -2
  2. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.2.apk → agent-device-android-multitouch-helper-0.17.4.apk} +0 -0
  3. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.4.apk.sha256 +1 -0
  4. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.2.manifest.json → agent-device-android-multitouch-helper-0.17.4.manifest.json} +4 -4
  5. package/android-snapshot-helper/README.md +3 -0
  6. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.2.apk → agent-device-android-snapshot-helper-0.17.4.apk} +0 -0
  7. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.4.apk.sha256 +1 -0
  8. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.2.manifest.json → agent-device-android-snapshot-helper-0.17.4.manifest.json} +6 -6
  9. package/dist/src/123.js +1 -1
  10. package/dist/src/1231.js +1 -1
  11. package/dist/src/1352.js +1 -1
  12. package/dist/src/221.js +2 -2
  13. package/dist/src/2403.js +3 -3
  14. package/dist/src/2415.js +37 -29
  15. package/dist/src/4012.js +4 -0
  16. package/dist/src/5611.js +1 -0
  17. package/dist/src/5827.js +1 -0
  18. package/dist/src/6088.js +1 -0
  19. package/dist/src/6133.js +1 -0
  20. package/dist/src/7847.js +1 -1
  21. package/dist/src/9471.js +1 -1
  22. package/dist/src/9542.js +6 -3
  23. package/dist/src/9616.js +2 -1
  24. package/dist/src/9818.js +1 -1
  25. package/dist/src/android-snapshot-helper.d.ts +0 -1
  26. package/dist/src/android.js +5 -5
  27. package/dist/src/apple.js +1 -1
  28. package/dist/src/apps.js +10 -10
  29. package/dist/src/args.js +53 -14
  30. package/dist/src/batch.js +1 -1
  31. package/dist/src/cli-output.js +30 -0
  32. package/dist/src/cli.js +15 -16
  33. package/dist/src/command-surface.js +1 -1
  34. package/dist/src/contracts.d.ts +52 -0
  35. package/dist/src/contracts.js +1 -1
  36. package/dist/src/find.js +1 -1
  37. package/dist/src/generic.js +5 -5
  38. package/dist/src/index.d.ts +127 -8
  39. package/dist/src/index.js +1 -1
  40. package/dist/src/input-actions.js +1 -1
  41. package/dist/src/interaction.js +1 -1
  42. package/dist/src/react-native.js +1 -1
  43. package/dist/src/record-trace-recording.js +3 -3
  44. package/dist/src/selector-runtime.js +1 -1
  45. package/dist/src/selectors.d.ts +14 -0
  46. package/dist/src/selectors.js +1 -1
  47. package/dist/src/server.js +2 -2
  48. package/dist/src/session.js +8 -10
  49. package/dist/src/snapshot.js +2 -2
  50. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
  51. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +14 -0
  52. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +297 -0
  53. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +327 -0
  54. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +122 -173
  55. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandJournal.swift +153 -5
  56. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +171 -0
  57. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +0 -10
  58. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +64 -18
  59. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +200 -0
  60. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SequenceExecution.swift +450 -0
  61. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +82 -178
  62. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +425 -0
  63. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +77 -6
  64. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Transport.swift +10 -1
  65. package/ios-runner/README.md +5 -5
  66. package/ios-runner/RUNNER_PROTOCOL.md +0 -1
  67. package/package.json +3 -3
  68. package/server.json +2 -2
  69. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.2.apk.sha256 +0 -1
  70. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.2.apk.sha256 +0 -1
  71. package/dist/src/1534.js +0 -1
  72. package/dist/src/1620.js +0 -1
  73. package/dist/src/1644.js +0 -2
  74. package/dist/src/2284.js +0 -1
  75. package/dist/src/2474.js +0 -1
  76. package/dist/src/2672.js +0 -1
  77. package/dist/src/3393.js +0 -1
  78. package/dist/src/5898.js +0 -1
  79. package/dist/src/695.js +0 -1
  80. package/dist/src/7455.js +0 -1
  81. package/dist/src/8173.js +0 -27
  82. package/dist/src/8407.js +0 -1
  83. package/dist/src/8699.js +0 -1
  84. package/dist/src/9238.js +0 -4
  85. package/dist/src/9673.js +0 -1
  86. package/dist/src/9974.js +0 -1
@@ -1 +1 @@
1
- import{createDaemonRuntimeSessionStore as e,setSessionSnapshot as t,captureSnapshot as r,dispatchCommand as n,runIosRunnerCommand as s,isCommandSupportedOnDevice as o,errorResponse as i,ensureDeviceReady as a,stopIosRunnerSession as l,resolveRunnerAppBundleId as u,getActiveAndroidSnapshotFreshness as c,resolveTargetDevice as d,context_contextFromFlags as f}from"./2415.js";import{closeIosApp as p}from"./apps.js";import{emitDiagnostic as m}from"./7599.js";import{asAppError as g,normalizeError as h,AppError as y}from"./9152.js";import{evaluateIsPredicate as w,isSupportedPredicate as _,localCommandPolicy as S,createAgentDevice as x}from"./123.js";import{splitIsSelectorArgs as k,extractNodeReadText as I,prefersValueForReadableText as v,findNodeByLabel as N,normalizeType as A}from"./7847.js";import{resolveRectCenter as P}from"./1620.js";import{getAndroidAppState as R}from"./8806.js";import{parseWaitPositionals as b}from"./2284.js";import{buildSnapshotPresentationKey as C,isApplePlatform as E,snapshotPresentationOptionsFromFlags as q}from"./1644.js";import{parseFindArgs as M}from"./7556.js";import{tryParseSelectorChain as D}from"./8407.js";async function O(e,t,r){let n=e.get(t),s=n?.device??await d(r??{});return n||await a(s),{session:n,device:s}}async function $(e,t,r){let n=!e&&"ios"===t.platform;try{return await r()}finally{n&&(await l(t.id),await K(t))}}async function K(e){let t=u();await p(e,t).catch(r=>{m({level:"debug",phase:"ios_sessionless_runner_host_close_failed",data:{deviceId:e.id,bundleId:t,error:r instanceof Error?r.message:String(r)}})})}function L(e,t,r,n){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function U(e){let{session:t,sessionName:r,device:n,snapshot:s,appBundleId:o}=e;return t?{...t,snapshot:s,lastComparisonSafeSnapshot:s?.comparisonSafe===!0?s:t.lastComparisonSafeSnapshot}:{name:r,device:n,createdAt:Date.now(),appBundleId:o,snapshot:s,...s?.comparisonSafe===!0?{lastComparisonSafeSnapshot:s}:{},actions:[]}}function T(e,t={}){return{artifacts:function(e,t={}){let r=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not create temporary files`)}}}(e,t),policy:S()}}async function G(e){let{device:t,node:r,flags:s,appBundleId:o,traceOutPath:i,surface:a,contextFromFlags:l}=e,u=I(r),c=P(r.rect);if(!c||"ios"===t.platform&&u&&!v(r.type??""))return u;try{let e=await n(t,"read",[String(c.x),String(c.y)],void 0,{...l(s,o,i),surface:a}),d=e&&"object"==typeof e?e:void 0,f="string"==typeof d?.text?d.text:"";if(f.trim())return f;return m({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:a,platform:t.platform}}),u}catch(e){return m({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:a,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),u}}let V=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function F(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,n]of V)void 0!==e[r]&&t.push(n);return t}(t);return 0===r.length?null:i("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function B(e,t){let r=await H(e);if(r)throw new y("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${r.foregroundPackage}. The tap likely escaped the app.`,r)}async function H(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let r=await R(e.device),n=r.package?.trim();return n&&n!==e.appBundleId&&("com.android.settings"===(t=n)||"com.android.systemui"===t||"com.google.android.permissioncontroller"===t||t.includes("launcher"))?{expectedPackage:e.appBundleId,foregroundPackage:n,activity:r.activity,hint:"com.google.android.permissioncontroller"===n?"Dismiss or allow the permission prompt, then retry the smoke assertion.":"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."}:null}function j(e){return"COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage}function W(e,t){let r=Array.isArray(e.selectorChain)?e.selectorChain:void 0,n=X(e),s=n?.kind==="ref"?Y(n.ref):void 0,o=n?.kind==="selector"?n.selector:void 0,i={...s?{ref:s}:{},...o?{selector:o}:{},...r?{selectorChain:r}:{}};if("attrs"===t)return i;let a="string"==typeof e.text?e.text:"";return{...i,text:a,refLabel:function(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}(a)}}function z(e){let t=X(e);return{...t?.kind==="ref"?{ref:Y(t.ref)}:{},...t?.kind==="selector"?{selector:t.selector}:{},..."string"==typeof e.text?{text:e.text}:{},...e.node&&"object"==typeof e.node?{node:e.node}:{}}}function J(e){let{selectorChain:t,...r}=e;return r}function Q(e,t,r,n){let s=e.get(t);s&&e.recordAction(s,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function X(e){let t=e.target;return t&&"object"==typeof t?"ref"===t.kind&&"string"==typeof t.ref?{kind:"ref",ref:t.ref}:"selector"===t.kind&&"string"==typeof t.selector?{kind:"selector",selector:t.selector}:void 0:void 0}function Y(e){return e.startsWith("@")?e.slice(1):e}let Z=["application","window","tabbar","scrollbar","image"],ee=new Set(["tab bar"]);async function et(e,t){var r;if(t.ok||(r=t.error.message,!/^wait timed out for (?:selector|text): /i.test(r)))return t;let n=await er(e).catch(()=>null);return n?i(t.error.code,`${t.error.message}. Current surface: ${n.summary}.`,{...t.error.details??{},currentSurface:n.details}):t}async function er(e){let t=[...(await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!0,snapshotCompact:!0},logPath:e.logPath??""})).snapshot.nodes].sort(es),n=en(t,6,{includeIdentifiers:!0});if(0===n.length)return null;let s=en(t.filter(e=>!ea(e)),4,{includeIdentifiers:!1}),o=en(t.filter(el),4,{includeIdentifiers:!0});return{summary:(s.length>0?s:n.slice(0,4)).join(", "),details:{labels:n,...o.length>0?{buttons:o}:{}}}}function en(e,t,r){let n=new Set,s=[];for(let o of e){let e=ei(o,r);if(!(!e||n.has(e))&&(n.add(e),s.push(e),s.length>=t))break}return s}function es(e,t){var r,n;return eo(e)-eo(t)||(r=e,n=t,r.rect&&n.rect?r.rect.y-n.rect.y||r.rect.x-n.rect.x:r.rect?-1:n.rect?1:(r.depth??0)-(n.depth??0)||r.index-n.index)}function eo(e){let t=!!ei(e,{includeIdentifiers:!1});return 2*!!ea(e)+ +!t}function ei(e,t){let r=(t.includeIdentifiers?[e.label,e.value,e.identifier]:[e.label,e.value]).map(e=>"string"==typeof e?e.trim():"").find(e=>e.length>0);return r?r.replace(/\s+/g," ").slice(0,80):""}function ea(e){let t=A(`${e.type??""} ${e.role??""} ${e.subrole??""}`),r=`${e.label??""} ${e.value??""}`.trim().toLowerCase();return Z.some(e=>t.includes(e))||ee.has(r)||r.endsWith(".fill")}function el(e){return A(`${e.type??""} ${e.role??""} ${e.subrole??""}`).includes("button")}function eu(e){var t;let{session:r,selectorExpression:n}=e;if(!r||"ios"!==r.device.platform||r.postGestureStabilization)return null;let s=D(n);if(!s||1!==s.selectors.length)return null;let o=s.selectors[0];if(!o||1!==o.terms.length)return null;let i=o.terms[0];return i&&"string"==typeof i.value&&("id"===(t=i.key)||"label"===t||"text"===t||"value"===t)?{key:i.key,value:i.value,raw:o.raw}:null}function ec(e,t={}){let r=g(e);if("ELEMENT_NOT_FOUND"===r.code)return!0===t.allowElementNotFound;if("COMMAND_FAILED"!==r.code)return!1;let n=r.message.toLowerCase();return n.includes("fetch failed")||n.includes("timed out")||n.includes("timeout")||n.includes("runner did not accept connection")||n.includes("invalid runner response")}async function ed(e){var t;let{req:r}=e;if("find"!==r.command)return null;let n=r.positionals??[];if(0===n.length)return i("INVALID_ARGS","find requires a locator or text");let s=M(n);if(!s.query)return i("INVALID_ARGS","find requires a value");if(r.flags?.findFirst&&r.flags?.findLast)return i("INVALID_ARGS","find accepts only one of --first or --last");let o=s.action;if("exists"!==(t=o)&&"wait"!==t&&"get_text"!==t&&"get_attrs"!==t)return null;let a=await eI(e,{requireSession:!1,capability:"find"});return a.ok?await eA(async()=>{let t=await a.runtime.selectors.find({session:e.sessionName,requestId:r.meta?.requestId,locator:s.locator,query:s.query,action:o,timeoutMs:s.timeoutMs});return Q(e.sessionStore,e.sessionName,r,function(e,t){if("exists"===t)return{found:!0};if("wait"===t)return{found:!0,waitedMs:e.waitedMs};let r="string"==typeof e.ref?e.ref:void 0;return"get_attrs"===t?{ref:r,action:"get attrs"}:{ref:r,action:"get text",text:"string"==typeof e.text?e.text:""}}(t,o)),"found"===t.kind?{found:!0,..."number"==typeof t.waitedMs?{waitedMs:t.waitedMs}:{}}:{..."string"==typeof t.ref?{ref:t.ref}:{},..."string"==typeof t.text?{text:t.text}:{},...t.node&&"object"==typeof t.node?{node:t.node}:{}}}):a.response}async function ef(e){let{req:t}=e;if("get"!==t.command)return null;let r=t.positionals?.[0];if("text"!==r&&"attrs"!==r)return i("INVALID_ARGS","get only supports text or attrs");let n=function(e){let t=e.positionals?.[1]??"";if(t.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:e.positionals.length>2?e.positionals.slice(2).join(" ").trim():""}};let r=e.positionals?.slice(1).join(" ").trim()??"";return r?{ok:!0,target:{kind:"selector",selector:r}}:{ok:!1,response:i("INVALID_ARGS","get requires @ref or selector expression")}}(t);if(!n.ok)return n.response;if("ref"===n.target.kind){let e=F("get",t.flags);if(e)return e}if("selector"===n.target.kind){let t=await eg(e,r,n.target.selector);if(t)return t}let s=await eI(e,{requireSession:!0,capability:"get"});return s.ok?await eA(async()=>{let o=await s.runtime.selectors.get({session:e.sessionName,requestId:t.meta?.requestId,property:r,target:n.target});return Q(e.sessionStore,e.sessionName,t,W(o,r)),z(o)}):s.response}async function ep(e){let{req:t}=e;if("is"!==t.command)return null;let r=(t.positionals?.[0]??"").toLowerCase();if(!_(r))return i("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:n}=k(t.positionals??[]);if(!n)return i("INVALID_ARGS","is requires a selector expression");let s=n.rest.join(" ").trim();if("text"===r&&!s)return i("INVALID_ARGS","is text requires expected text value");if("text"!==r&&n.rest.length>0)return i("INVALID_ARGS",`is ${r} does not accept trailing values`);let o=await eh(e,r,n.selectorExpression,s);if(o)return o;let a=await eI(e,{requireSession:!0,capability:"is"});if(!a.ok)return a.response;let l=await eA(async()=>{let o=await a.runtime.selectors.is({session:e.sessionName,requestId:t.meta?.requestId,predicate:r,selector:n.selectorExpression,expectedText:s});return Q(e.sessionStore,e.sessionName,t,o),J(o)});return await eP(e,l,`is ${r}`)}async function em(e){let{req:t,sessionName:r,sessionStore:n}=e,s=b(t.positionals??[]);if(!s)return i("INVALID_ARGS","wait requires a duration or text");let{session:a,device:l}=await O(n,r,t.flags);if("sleep"!==s.kind&&!o("wait",l))return i("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===s.kind){let t=await ey({...e,session:a,device:l,selectorExpression:s.selectorExpression,timeoutMs:s.timeoutMs});if(t)return t}let u=async()=>{let o=ek({...e,session:a,device:l}),i=await eA(async()=>{let e=await o.selectors.wait({session:r,requestId:t.meta?.requestId,target:function(e,t){if("sleep"===e.kind)return{kind:"sleep",durationMs:e.durationMs};if("selector"===e.kind)return{kind:"selector",selector:e.selectorExpression,timeoutMs:e.timeoutMs};if("ref"===e.kind){if(!t?.snapshot)throw new y("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new y("INVALID_ARGS","wait requires text");return{kind:"text",text:e.text,timeoutMs:e.timeoutMs}}(s,a)});return Q(n,r,t,e),{waitedMs:e.waitedMs,..."string"==typeof e.text?{text:e.text}:{},..."string"==typeof e.selector?{selector:e.selector}:{}}}),u=await et({req:t,logPath:e.logPath,session:a,device:l},i);return await eP(e,u,"wait")};return"sleep"===s.kind?await u():await $(a,l,u)}async function eg(e,t,r){let n=e.sessionStore.get(e.sessionName),s=eu({session:n,selectorExpression:r});if(!n||!s||"text"===t&&"id"!==s.key)return null;let o=await eS(e,n,s);if(ex(o))return o.response;if(!o)return null;let i=function(e,t,r){if(!r.found||!r.node)return null;let n={target:{kind:"selector",selector:t},node:r.node,selectorChain:[t]};return"attrs"===e?{kind:"attrs",...n}:"string"!=typeof r.text?null:{kind:"text",...n,text:r.text}}(t,s.raw,o);return i?(Q(e.sessionStore,e.sessionName,e.req,W(i,t)),{ok:!0,data:z(i)}):null}async function eh(e,t,r,n){var s,o,i,a,l;let u;if("hidden"===t)return null;let c=await ew(e,r);if(ex(c))return c.response;if(!c?.result.found||!c.result.node)return null;let d="exists"===t?{predicate:t,pass:!0,selector:c.selector.raw,matches:1,selectorChain:[c.selector.raw]}:(s=t,o=n,i=c.selector.raw,a=c.session,u=w({predicate:s,node:l=c.result.node,nodes:[l],expectedText:o,platform:a.device.platform}),{predicate:s,pass:u.pass,selector:i,..."text"===s?{text:u.actualText}:{},selectorChain:[i]});return d?(Q(e.sessionStore,e.sessionName,e.req,d),{ok:!0,data:J(d)}):null}async function ey(e){let t=eu({session:e.session,selectorExpression:e.selectorExpression});if(!e.session||!t)return null;let r=Date.now(),n=await eS(e,e.session,t);if(ex(n))return n.response;if(!n?.found)return null;let s={kind:"selector",selector:t.raw,waitedMs:Date.now()-r,selectorChain:[t.raw]};return Q(e.sessionStore,e.sessionName,e.req,s),await et({req:e.req,logPath:e.logPath,session:e.session,device:e.device},{ok:!0,data:s})}async function ew(e,t){let r=e.sessionStore.get(e.sessionName),n=eu({session:r,selectorExpression:t});if(!r||!n)return null;let s=await eS(e,r,n);return ex(s)?s:s?{session:r,selector:n,result:s}:null}async function e_(e,t,r){let n=await s(t.device,{command:"querySelector",selectorKey:r.key,selectorValue:r.value,appBundleId:t.appBundleId},{verbose:!!e.req.flags?.verbose,logPath:e.logPath,traceLogPath:t.trace?.outPath,requestId:e.req.meta?.requestId}),o=!0===n.found,i=function(e){let t=e.nodes;if(!Array.isArray(t))return;let r=t[0];if(r&&"object"==typeof r)return r}(n);return{found:o,..."string"==typeof n.text?{text:n.text}:{},...i?{node:i}:{}}}async function eS(e,t,r){try{return await e_(e,t,r)}catch(e){if(ec(e,{allowElementNotFound:!0}))return null;return{kind:"error",response:{ok:!1,error:h(e)}}}}function ex(e){return null!==e&&"kind"in e&&"error"===e.kind}function ek(n){return x({backend:function(e){let n,{req:s,session:o,device:i,logPath:a,sessionName:l,sessionStore:u}=e,d=0;return{platform:i.platform,captureSnapshot:async(e,f)=>{var p;let m,g={...s.flags,...(p=f,m={},p?.interactiveOnly!==void 0&&(m.snapshotInteractiveOnly=p.interactiveOnly),p?.compact!==void 0&&(m.snapshotCompact=p.compact),p?.scope!==void 0&&(m.snapshotScope=p.scope),p?.depth!==void 0&&(m.snapshotDepth=p.depth),p?.raw!==void 0&&(m.snapshotRaw=p.raw),m)},h=f?.scope??s.flags?.snapshotScope,y=Date.now(),w=C(q(g)),_="wait"===s.command||"find"===s.command;if(!_&&n&&y-d<750&&!c(o)&&!o?.postGestureStabilization)return n;if(!_&&o?.snapshot&&y-o.snapshot.createdAt<750&&o.snapshot.presentationKey===w&&!c(o)&&!o.postGestureStabilization)return d=o.snapshot.createdAt,n={snapshot:o.snapshot};let S=await r({device:i,session:o,flags:g,outPath:s.flags?.out,logPath:a??"",snapshotScope:h});return o&&(t(o,S.snapshot),u.set(l,o)),d=y,n={snapshot:S.snapshot}},readText:async(t,r)=>({text:await G({device:i,node:r,flags:s.flags,appBundleId:o?.appBundleId,traceOutPath:o?.trace?.outPath,surface:o?.surface,contextFromFlags:e.contextFromFlags??((e,t,r)=>f(a??"",e,t,r))})}),findText:async(t,r)=>({found:await ev(e,r)})}}(n),...T("selector commands",{plural:!0}),sessions:e({sessionName:n.sessionName,getSession:()=>n.session,recordOptions:{includeSnapshot:!0},setRecord:e=>{n.session&&e.snapshot&&(t(n.session,e.snapshot),n.sessionStore.set(n.sessionName,n.session))}})})}async function eI(e,t){let r=e.sessionStore.get(e.sessionName);if(!r&&t.requireSession)return{ok:!1,response:i("SESSION_NOT_FOUND","No active session. Run open first.")};let n=r?.device??await d(e.req.flags??{});return(r||await a(n),o(t.capability,n))?{ok:!0,runtime:ek({...e,session:r,device:n})}:{ok:!1,response:i("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function ev(e,t){let{device:r,session:n,req:o,logPath:i}=e;if("macos"===r.platform&&n?.surface&&"app"!==n.surface)return!!N((await eN(e)).nodes,t);if(E(r.platform)&&n?.appBundleId){let e=await s(r,{command:"findText",text:t,appBundleId:n?.appBundleId},{verbose:o.flags?.verbose,logPath:i,traceLogPath:n?.trace?.outPath,requestId:o.meta?.requestId});return e?.found===!0}return!!N((await eN(e)).nodes,t)}async function eN(e){let n=await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!1,snapshotCompact:!1},outPath:e.req.flags?.out,logPath:e.logPath??""});return e.session&&(t(e.session,n.snapshot),e.sessionStore.set(e.sessionName,e.session)),n.snapshot}async function eA(e){try{return{ok:!0,data:await e()}}catch(t){let e=g(t);return i(e.code,e.message,e.details)}}async function eP(e,t,r){var n;let s;if(t.ok)return t;let o=e.sessionStore.get(e.sessionName);if(!o)return t;try{s=await H(o)}catch{return t}return s?i(t.error.code,`${r} failed because ${"com.google.android.permissioncontroller"===(n=s).foregroundPackage?`Android permission dialog is blocking ${n.expectedPackage}`:`${n.foregroundPackage} is foreground instead of ${n.expectedPackage}`}.`,{...t.error.details??{},...s,blockedBy:"android_foreground_surface",originalMessage:t.error.message}):t}export{B as assertAndroidPressStayedInApp,U as buildSnapshotSession,T as createDaemonRuntimePolicy,ed as dispatchFindReadOnlyViaRuntime,ef as dispatchGetViaRuntime,ep as dispatchIsViaRuntime,em as dispatchWaitViaRuntime,j as isAndroidEscapeError,ec as isDirectIosSelectorFallbackError,eu as readSimpleIosSelectorTarget,G as readTextForNode,L as recordIfSession,F as refSnapshotFlagGuardResponse,O as resolveSessionDevice,$ as withSessionlessRunnerCleanup};
1
+ import{createDaemonRuntimeSessionStore as e,setSessionSnapshot as t,captureSnapshot as r,dispatchCommand as n,runIosRunnerCommand as s,isCommandSupportedOnDevice as o,errorResponse as i,ensureDeviceReady as a,stopIosRunnerSession as l,resolveRunnerAppBundleId as u,getActiveAndroidSnapshotFreshness as c,resolveTargetDevice as d,context_contextFromFlags as f}from"./2415.js";import{closeIosApp as p}from"./apps.js";import{emitDiagnostic as m}from"./7599.js";import{asAppError as g,normalizeError as h,AppError as y}from"./9152.js";import{evaluateIsPredicate as w,isSupportedPredicate as _,localCommandPolicy as S,createAgentDevice as x}from"./123.js";import{tryParseSelectorChain as k,extractNodeReadText as I,prefersValueForReadableText as v,findNodeByLabel as N,normalizeType as A,splitIsSelectorArgs as P}from"./7847.js";import{resolveRectCenter as R,isSparseSnapshotQualityVerdict as b,parseWaitPositionals as E}from"./6133.js";import{getAndroidAppState as q}from"./8806.js";import{buildSnapshotPresentationKey as C,isApplePlatform as M,snapshotPresentationOptionsFromFlags as D}from"./9616.js";import{parseFindArgs as O}from"./7556.js";async function $(e,t,r){let n=e.get(t),s=n?.device??await d(r??{});return n||await a(s),{session:n,device:s}}async function L(e,t,r){let n=!e&&"ios"===t.platform;try{return await r()}finally{n&&(await l(t.id),await U(t))}}async function U(e){let t=u();await p(e,t).catch(r=>{m({level:"debug",phase:"ios_sessionless_runner_host_close_failed",data:{deviceId:e.id,bundleId:t,error:r instanceof Error?r.message:String(r)}})})}function K(e,t,r,n){t&&e.recordAction(t,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function T(e){let{session:t,sessionName:r,device:n,snapshot:s,appBundleId:o}=e;return t?{...t,snapshot:s,lastComparisonSafeSnapshot:s?.comparisonSafe===!0?s:t.lastComparisonSafeSnapshot}:{name:r,device:n,createdAt:Date.now(),appBundleId:o,snapshot:s,...s?.comparisonSafe===!0?{lastComparisonSafeSnapshot:s}:{},actions:[]}}function G(e,t={}){return{artifacts:function(e,t={}){let r=!0===t.plural?"do":"does";return{resolveInput:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not resolve input artifacts`)},reserveOutput:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not reserve output artifacts`)},createTempFile:async()=>{throw new y("UNSUPPORTED_OPERATION",`${e} ${r} not create temporary files`)}}}(e,t),policy:S()}}async function V(e){let{device:t,node:r,flags:s,appBundleId:o,traceOutPath:i,surface:a,contextFromFlags:l}=e,u=I(r),c=R(r.rect);if(!c||"ios"===t.platform&&u&&!v(r.type??""))return u;try{let e=await n(t,"read",[String(c.x),String(c.y)],void 0,{...l(s,o,i),surface:a}),d=e&&"object"==typeof e?e:void 0,f="string"==typeof d?.text?d.text:"";if(f.trim())return f;return m({level:"warn",phase:"interaction_read_fallback",data:{reason:"empty_backend_text",nodeRef:r.ref,surface:a,platform:t.platform}}),u}catch(e){return m({level:"warn",phase:"interaction_read_fallback",data:{reason:"backend_read_failed",nodeRef:r.ref,surface:a,platform:t.platform,error:e instanceof Error?e.message:String(e)}}),u}}let F=[["snapshotDepth","--depth"],["snapshotScope","--scope"],["snapshotRaw","--raw"]];function B(e,t){let r=function(e){if(!e)return[];let t=[];for(let[r,n]of F)void 0!==e[r]&&t.push(n);return t}(t);return 0===r.length?null:i("INVALID_ARGS",`${e} @ref does not support ${r.join(", ")}.`)}async function j(e,t){let r=await H(e);if(r)throw new y("COMMAND_FAILED",`press ${t} left ${e.appBundleId} and foregrounded ${r.foregroundPackage}. The tap likely escaped the app.`,r)}async function H(e){var t;if("android"!==e.device.platform||!e.appBundleId)return null;let r=await q(e.device),n=r.package?.trim();return n&&n!==e.appBundleId&&("com.android.settings"===(t=n)||"com.android.systemui"===t||"com.google.android.permissioncontroller"===t||t.includes("launcher"))?{expectedPackage:e.appBundleId,foregroundPackage:n,activity:r.activity,hint:"com.google.android.permissioncontroller"===n?"Dismiss or allow the permission prompt, then retry the smoke assertion.":"Use screenshot as visual truth, then take a fresh snapshot -i before retrying."}:null}function W(e){return"COMMAND_FAILED"===e.code&&"string"==typeof e.details?.expectedPackage&&"string"==typeof e.details?.foregroundPackage}function z(e,t){let r=Array.isArray(e.selectorChain)?e.selectorChain:void 0,n=Y(e),s=n?.kind==="ref"?Z(n.ref):void 0,o=n?.kind==="selector"?n.selector:void 0,i={...s?{ref:s}:{},...o?{selector:o}:{},...r?{selectorChain:r}:{}};if("attrs"===t)return i;let a="string"==typeof e.text?e.text:"";return{...i,text:a,refLabel:function(e){let t=e.trim();if(!(!t||t.length>80||/[\r\n]/.test(t)))return t}(a)}}function Q(e){let t=Y(e);return{...t?.kind==="ref"?{ref:Z(t.ref)}:{},...t?.kind==="selector"?{selector:t.selector}:{},..."string"==typeof e.text?{text:e.text}:{},...e.node&&"object"==typeof e.node?{node:e.node}:{}}}function J(e){let{selectorChain:t,...r}=e;return r}function X(e,t,r,n){let s=e.get(t);s&&e.recordAction(s,{command:r.command,positionals:r.positionals??[],flags:r.flags??{},result:n})}function Y(e){let t=e.target;return t&&"object"==typeof t?"ref"===t.kind&&"string"==typeof t.ref?{kind:"ref",ref:t.ref}:"selector"===t.kind&&"string"==typeof t.selector?{kind:"selector",selector:t.selector}:void 0:void 0}function Z(e){return e.startsWith("@")?e.slice(1):e}let ee=["application","window","tabbar","scrollbar","image"],et=new Set(["tab bar"]);async function er(e,t){var r;if(t.ok||(r=t.error.message,!/^wait timed out for (?:selector|text): /i.test(r)))return t;let n=await en(e).catch(()=>null);return n?i(t.error.code,`${t.error.message}. Current surface: ${n.summary}.`,{...t.error.details??{},currentSurface:n.details}):t}async function en(e){let t=[...(await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!0},logPath:e.logPath??""})).snapshot.nodes].sort(eo),n=es(t,6,{includeIdentifiers:!0});if(0===n.length)return null;let s=es(t.filter(e=>!el(e)),4,{includeIdentifiers:!1}),o=es(t.filter(eu),4,{includeIdentifiers:!0});return{summary:(s.length>0?s:n.slice(0,4)).join(", "),details:{labels:n,...o.length>0?{buttons:o}:{}}}}function es(e,t,r){let n=new Set,s=[];for(let o of e){let e=ea(o,r);if(!(!e||n.has(e))&&(n.add(e),s.push(e),s.length>=t))break}return s}function eo(e,t){var r,n;return ei(e)-ei(t)||(r=e,n=t,r.rect&&n.rect?r.rect.y-n.rect.y||r.rect.x-n.rect.x:r.rect?-1:n.rect?1:(r.depth??0)-(n.depth??0)||r.index-n.index)}function ei(e){let t=!!ea(e,{includeIdentifiers:!1});return 2*!!el(e)+ +!t}function ea(e,t){let r=(t.includeIdentifiers?[e.label,e.value,e.identifier]:[e.label,e.value]).map(e=>"string"==typeof e?e.trim():"").find(e=>e.length>0);return r?r.replace(/\s+/g," ").slice(0,80):""}function el(e){let t=A(`${e.type??""} ${e.role??""} ${e.subrole??""}`),r=`${e.label??""} ${e.value??""}`.trim().toLowerCase();return ee.some(e=>t.includes(e))||et.has(r)||r.endsWith(".fill")}function eu(e){return A(`${e.type??""} ${e.role??""} ${e.subrole??""}`).includes("button")}function ec(e){var t;let{session:r,selectorExpression:n}=e;if(!r||"ios"!==r.device.platform||r.postGestureStabilization)return null;let s=k(n);if(!s||1!==s.selectors.length)return null;let o=s.selectors[0];if(!o||1!==o.terms.length)return null;let i=o.terms[0];return i&&"string"==typeof i.value&&("id"===(t=i.key)||"label"===t||"text"===t||"value"===t)?{key:i.key,value:i.value,raw:o.raw}:null}function ed(e,t={}){let r=g(e);if("ELEMENT_NOT_FOUND"===r.code)return!0===t.allowElementNotFound;if("COMMAND_FAILED"!==r.code)return!1;let n=r.message.toLowerCase();return n.includes("fetch failed")||n.includes("timed out")||n.includes("timeout")||n.includes("runner did not accept connection")||n.includes("invalid runner response")}async function ef(e){var t;let{req:r}=e;if("find"!==r.command)return null;let n=r.positionals??[];if(0===n.length)return i("INVALID_ARGS","find requires a locator or text");let s=O(n);if(!s.query)return i("INVALID_ARGS","find requires a value");if(r.flags?.findFirst&&r.flags?.findLast)return i("INVALID_ARGS","find accepts only one of --first or --last");let o=s.action;if("exists"!==(t=o)&&"wait"!==t&&"get_text"!==t&&"get_attrs"!==t)return null;let a=await ev(e,{requireSession:!1,capability:"find"});return a.ok?await eP(async()=>{let t=await a.runtime.selectors.find({session:e.sessionName,requestId:r.meta?.requestId,locator:s.locator,query:s.query,action:o,timeoutMs:s.timeoutMs});return X(e.sessionStore,e.sessionName,r,function(e,t){if("exists"===t)return{found:!0};if("wait"===t)return{found:!0,waitedMs:e.waitedMs};let r="string"==typeof e.ref?e.ref:void 0;return"get_attrs"===t?{ref:r,action:"get attrs"}:{ref:r,action:"get text",text:"string"==typeof e.text?e.text:""}}(t,o)),"found"===t.kind?{found:!0,..."number"==typeof t.waitedMs?{waitedMs:t.waitedMs}:{}}:{..."string"==typeof t.ref?{ref:t.ref}:{},..."string"==typeof t.text?{text:t.text}:{},...t.node&&"object"==typeof t.node?{node:t.node}:{}}}):a.response}async function ep(e){let{req:t}=e;if("get"!==t.command)return null;let r=t.positionals?.[0];if("text"!==r&&"attrs"!==r)return i("INVALID_ARGS","get only supports text or attrs");let n=function(e){let t=e.positionals?.[1]??"";if(t.startsWith("@"))return{ok:!0,target:{kind:"ref",ref:t,fallbackLabel:e.positionals.length>2?e.positionals.slice(2).join(" ").trim():""}};let r=e.positionals?.slice(1).join(" ").trim()??"";return r?{ok:!0,target:{kind:"selector",selector:r}}:{ok:!1,response:i("INVALID_ARGS","get requires @ref or selector expression")}}(t);if(!n.ok)return n.response;if("ref"===n.target.kind){let e=B("get",t.flags);if(e)return e}if("selector"===n.target.kind){let t=await eh(e,r,n.target.selector);if(t)return t}let s=await ev(e,{requireSession:!0,capability:"get"});return s.ok?await eP(async()=>{let o=await s.runtime.selectors.get({session:e.sessionName,requestId:t.meta?.requestId,property:r,target:n.target});return X(e.sessionStore,e.sessionName,t,z(o,r)),Q(o)}):s.response}async function em(e){let{req:t}=e;if("is"!==t.command)return null;let r=(t.positionals?.[0]??"").toLowerCase();if(!_(r))return i("INVALID_ARGS","is requires predicate: visible|hidden|exists|editable|selected|text");let{split:n}=P(t.positionals??[]);if(!n)return i("INVALID_ARGS","is requires a selector expression");let s=n.rest.join(" ").trim();if("text"===r&&!s)return i("INVALID_ARGS","is text requires expected text value");if("text"!==r&&n.rest.length>0)return i("INVALID_ARGS",`is ${r} does not accept trailing values`);let o=await ey(e,r,n.selectorExpression,s);if(o)return o;let a=await ev(e,{requireSession:!0,capability:"is"});if(!a.ok)return a.response;let l=await eP(async()=>{let o=await a.runtime.selectors.is({session:e.sessionName,requestId:t.meta?.requestId,predicate:r,selector:n.selectorExpression,expectedText:s});return X(e.sessionStore,e.sessionName,t,o),J(o)});return await eR(e,l,`is ${r}`)}async function eg(e){let{req:t,sessionName:r,sessionStore:n}=e,s=E(t.positionals??[]);if(!s)return i("INVALID_ARGS","wait requires a duration or text");let{session:a,device:l}=await $(n,r,t.flags);if("sleep"!==s.kind&&!o("wait",l))return i("UNSUPPORTED_OPERATION","wait is not supported on this device");if("selector"===s.kind){let t=await ew({...e,session:a,device:l,selectorExpression:s.selectorExpression,timeoutMs:s.timeoutMs});if(t)return t}let u=async()=>{let o=eI({...e,session:a,device:l}),i=await eP(async()=>{let e=await o.selectors.wait({session:r,requestId:t.meta?.requestId,target:function(e,t){if("sleep"===e.kind)return{kind:"sleep",durationMs:e.durationMs};if("selector"===e.kind)return{kind:"selector",selector:e.selectorExpression,timeoutMs:e.timeoutMs};if("ref"===e.kind){if(!t?.snapshot)throw new y("INVALID_ARGS","Ref wait requires an existing snapshot in session.");return{kind:"ref",ref:e.rawRef,timeoutMs:e.timeoutMs}}if(!e.text)throw new y("INVALID_ARGS","wait requires text");return{kind:"text",text:e.text,timeoutMs:e.timeoutMs}}(s,a)});return X(n,r,t,e),{waitedMs:e.waitedMs,..."string"==typeof e.text?{text:e.text}:{},..."string"==typeof e.selector?{selector:e.selector}:{}}}),u=await er({req:t,logPath:e.logPath,session:a,device:l},i);return await eR(e,u,"wait")};return"sleep"===s.kind?await u():await L(a,l,u)}async function eh(e,t,r){let n=e.sessionStore.get(e.sessionName),s=ec({session:n,selectorExpression:r});if(!n||!s||"text"===t&&"id"!==s.key)return null;let o=await ex(e,n,s);if(ek(o))return o.response;if(!o)return null;let i=function(e,t,r){if(!r.found||!r.node)return null;let n={target:{kind:"selector",selector:t},node:r.node,selectorChain:[t]};return"attrs"===e?{kind:"attrs",...n}:"string"!=typeof r.text?null:{kind:"text",...n,text:r.text}}(t,s.raw,o);return i?(X(e.sessionStore,e.sessionName,e.req,z(i,t)),{ok:!0,data:Q(i)}):null}async function ey(e,t,r,n){var s,o,i,a,l;let u;if("hidden"===t)return null;let c=await e_(e,r);if(ek(c))return c.response;if(!c?.result.found||!c.result.node)return null;let d="exists"===t?{predicate:t,pass:!0,selector:c.selector.raw,matches:1,selectorChain:[c.selector.raw]}:(s=t,o=n,i=c.selector.raw,a=c.session,u=w({predicate:s,node:l=c.result.node,nodes:[l],expectedText:o,platform:a.device.platform}),{predicate:s,pass:u.pass,selector:i,..."text"===s?{text:u.actualText}:{},selectorChain:[i]});return d?(X(e.sessionStore,e.sessionName,e.req,d),{ok:!0,data:J(d)}):null}async function ew(e){let t=ec({session:e.session,selectorExpression:e.selectorExpression});if(!e.session||!t)return null;let r=Date.now(),n=await ex(e,e.session,t);if(ek(n))return n.response;if(!n?.found)return null;let s={kind:"selector",selector:t.raw,waitedMs:Date.now()-r,selectorChain:[t.raw]};return X(e.sessionStore,e.sessionName,e.req,s),await er({req:e.req,logPath:e.logPath,session:e.session,device:e.device},{ok:!0,data:s})}async function e_(e,t){let r=e.sessionStore.get(e.sessionName),n=ec({session:r,selectorExpression:t});if(!r||!n)return null;let s=await ex(e,r,n);return ek(s)?s:s?{session:r,selector:n,result:s}:null}async function eS(e,t,r){let n=await s(t.device,{command:"querySelector",selectorKey:r.key,selectorValue:r.value,appBundleId:t.appBundleId},{verbose:!!e.req.flags?.verbose,logPath:e.logPath,traceLogPath:t.trace?.outPath,requestId:e.req.meta?.requestId}),o=!0===n.found,i=function(e){let t=e.nodes;if(!Array.isArray(t))return;let r=t[0];if(r&&"object"==typeof r)return r}(n);return{found:o,..."string"==typeof n.text?{text:n.text}:{},...i?{node:i}:{}}}async function ex(e,t,r){try{return await eS(e,t,r)}catch(e){if(ed(e,{allowElementNotFound:!0}))return null;return{kind:"error",response:{ok:!1,error:h(e)}}}}function ek(e){return null!==e&&"kind"in e&&"error"===e.kind}function eI(n){return x({backend:function(e){let n,{req:s,session:o,device:i,logPath:a,sessionName:l,sessionStore:u}=e,d=0;return{platform:i.platform,captureSnapshot:async(e,f)=>{var p;let m,g={...s.flags,...(p=f,m={},p?.interactiveOnly!==void 0&&(m.snapshotInteractiveOnly=p.interactiveOnly),p?.scope!==void 0&&(m.snapshotScope=p.scope),p?.depth!==void 0&&(m.snapshotDepth=p.depth),p?.raw!==void 0&&(m.snapshotRaw=p.raw),m)},h=f?.scope??s.flags?.snapshotScope,y=Date.now(),w=C(D(g)),_="wait"===s.command||"find"===s.command;if(!_&&n&&y-d<750&&!c(o)&&!o?.postGestureStabilization)return n;if(!_&&o?.snapshot&&y-o.snapshot.createdAt<750&&o.snapshot.presentationKey===w&&!c(o)&&!o.postGestureStabilization)return d=o.snapshot.createdAt,n={snapshot:o.snapshot};let S=await r({device:i,session:o,flags:g,outPath:s.flags?.out,logPath:a??"",snapshotScope:h});return o&&!b(S.snapshot.snapshotQuality)&&(t(o,S.snapshot),u.set(l,o)),d=y,n={snapshot:S.snapshot}},readText:async(t,r)=>({text:await V({device:i,node:r,flags:s.flags,appBundleId:o?.appBundleId,traceOutPath:o?.trace?.outPath,surface:o?.surface,contextFromFlags:e.contextFromFlags??((e,t,r)=>f(a??"",e,t,r))})}),findText:async(t,r)=>({found:await eN(e,r)})}}(n),...G("selector commands",{plural:!0}),sessions:e({sessionName:n.sessionName,getSession:()=>n.session,recordOptions:{includeSnapshot:!0},setRecord:e=>{n.session&&e.snapshot&&(t(n.session,e.snapshot),n.sessionStore.set(n.sessionName,n.session))}})})}async function ev(e,t){let r=e.sessionStore.get(e.sessionName);if(!r&&t.requireSession)return{ok:!1,response:i("SESSION_NOT_FOUND","No active session. Run open first.")};let n=r?.device??await d(e.req.flags??{});return(r||await a(n),o(t.capability,n))?{ok:!0,runtime:eI({...e,session:r,device:n})}:{ok:!1,response:i("UNSUPPORTED_OPERATION",`${t.capability} is not supported on this device`)}}async function eN(e,t){let{device:r,session:n,req:o,logPath:i}=e;if("macos"===r.platform&&n?.surface&&"app"!==n.surface)return!!N((await eA(e)).nodes,t);if(M(r.platform)&&n?.appBundleId){let e=await s(r,{command:"findText",text:t,appBundleId:n?.appBundleId},{verbose:o.flags?.verbose,logPath:i,traceLogPath:n?.trace?.outPath,requestId:o.meta?.requestId});return e?.found===!0}return!!N((await eA(e)).nodes,t)}async function eA(e){let n=await r({device:e.device,session:e.session,flags:{...e.req.flags,snapshotInteractiveOnly:!1},outPath:e.req.flags?.out,logPath:e.logPath??""});return e.session&&!b(n.snapshot.snapshotQuality)&&(t(e.session,n.snapshot),e.sessionStore.set(e.sessionName,e.session)),n.snapshot}async function eP(e){try{return{ok:!0,data:await e()}}catch(t){let e=g(t);return i(e.code,e.message,e.details)}}async function eR(e,t,r){var n;let s;if(t.ok)return t;let o=e.sessionStore.get(e.sessionName);if(!o)return t;try{s=await H(o)}catch{return t}return s?i(t.error.code,`${r} failed because ${"com.google.android.permissioncontroller"===(n=s).foregroundPackage?`Android permission dialog is blocking ${n.expectedPackage}`:`${n.foregroundPackage} is foreground instead of ${n.expectedPackage}`}.`,{...t.error.details??{},...s,blockedBy:"android_foreground_surface",originalMessage:t.error.message}):t}export{j as assertAndroidPressStayedInApp,T as buildSnapshotSession,G as createDaemonRuntimePolicy,ef as dispatchFindReadOnlyViaRuntime,ep as dispatchGetViaRuntime,em as dispatchIsViaRuntime,eg as dispatchWaitViaRuntime,W as isAndroidEscapeError,ed as isDirectIosSelectorFallbackError,ec as readSimpleIosSelectorTarget,V as readTextForNode,K as recordIfSession,B as refSnapshotFlagGuardResponse,$ as resolveSessionDevice,L as withSessionlessRunnerCleanup};
@@ -101,11 +101,25 @@ export declare type SnapshotNode = RawSnapshotNode & {
101
101
  ref: string;
102
102
  };
103
103
 
104
+ /**
105
+ * Structured quality verdict computed once by the iOS runner's snapshot capture plan.
106
+ * The daemon renders it; it never re-derives degradation from node shapes.
107
+ */
108
+ declare type SnapshotQualityVerdict = {
109
+ state: 'healthy' | 'recovered' | 'sparse';
110
+ backend: 'tree' | 'queries' | 'private-ax';
111
+ reason?: string;
112
+ reasonCode?: 'ax-rejected' | 'sparse-tree' | 'budget' | 'no-nodes' | 'capture-failed';
113
+ effectiveDepth?: number;
114
+ collapsedLeafIndexes?: number[];
115
+ };
116
+
104
117
  declare type SnapshotState = {
105
118
  nodes: SnapshotNode[];
106
119
  createdAt: number;
107
120
  truncated?: boolean;
108
121
  backend?: SnapshotBackend;
122
+ snapshotQuality?: SnapshotQualityVerdict;
109
123
  comparisonSafe?: boolean;
110
124
  presentationKey?: string;
111
125
  };
@@ -1 +1 @@
1
- export{findSelectorChainMatch,formatSelectorFailure,isNodeEditable,isNodeVisible,resolveSelectorChain}from"./7847.js";export{isSelectorToken,parseSelectorChain,tryParseSelectorChain}from"./8407.js";
1
+ export{findSelectorChainMatch,formatSelectorFailure,isNodeEditable,isNodeVisible,isSelectorToken,parseSelectorChain,resolveSelectorChain,tryParseSelectorChain}from"./7847.js";
@@ -1,2 +1,2 @@
1
- import{isCommandName as t,listMcpCommandMetadata as r,formatCliOutput as e}from"./8173.js";import{readVersion as n}from"./9671.js";let i=function(r={}){return{execute:async(n,i)=>{var u;if(!t(n))throw Error(`Unknown command tool: ${n}`);let c=!(u=i)||"object"!=typeof u||Array.isArray(u)?{client:{},outputFormat:"optimized"}:{client:function(t){let r=t.stateDir,e={};if(void 0!==r&&("string"!=typeof r||0===r.length))throw Error("Expected stateDir to be a non-empty string.");return"string"==typeof r&&(e.stateDir=r),e}(u),outputFormat:function(t){if(void 0===t)return"optimized";if("optimized"!==t&&"json"!==t)throw Error('Expected mcpOutputFormat to be "optimized" or "json".');return t}(u.mcpOutputFormat)},p=function(t){if(!t||"object"!=typeof t||Array.isArray(t))return t;let{stateDir:r,mcpOutputFormat:e,...n}=t;return n}(i),l=await o(r,c.client),f=await (r.runCommand??s)(l,n,p);return{isError:!1,structuredContent:f,content:[{type:"text",text:function(t){if("json"===t.outputFormat)return a(t.result);let r=e({name:t.name,input:t.input,result:t.result});return"string"==typeof r?.text?r.text:a(r?.data??t.result)}({name:n,input:p,result:f,outputFormat:c.outputFormat})}]}}}}();async function o(t,r){if(t.createClient)return await t.createClient(r);let{createAgentDeviceClient:e}=await import("./9542.js");return e(r)}async function s(t,r,e){let n=await import("./command-surface.js");return await n.runCommand(t,r,e)}function a(t){return"string"==typeof t?t:JSON.stringify(t,null,2)}async function u(t){if("2.0"!==t.jsonrpc||"string"!=typeof t.method)return l(t.id??null,-32600,"Invalid JSON-RPC request.");if(void 0===t.id)return null;try{var r,e;return r=t.id,e=await c(t.method,t.params),{jsonrpc:"2.0",id:r,result:e}}catch(r){if(r instanceof f)return l(t.id,-32601,r.message);return l(t.id,-32602,r instanceof Error?r.message:String(r))}}async function c(t,e){switch(t){case"initialize":return{protocolVersion:"2025-11-25",capabilities:{tools:{}},serverInfo:{name:"agent-device",version:n()}};case"ping":return{};case"tools/list":return{tools:r().map(t=>{var r;return{name:t.name,description:t.description,inputSchema:{...r=t.inputSchema,properties:{...r.properties,stateDir:{type:"string",description:"Agent-device state directory."},mcpOutputFormat:{type:"string",enum:["optimized","json"],description:"MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately."}}}}})};case"tools/call":return await p(e);default:throw new f(`Unsupported MCP method: ${t}`)}}async function p(t){let r=function(t){if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Expected object parameters.");return t}(t),e=function(t,r){let e=t[r];if("string"!=typeof e||0===e.length)throw Error(`Expected ${r} to be a non-empty string.`);return e}(r,"name");try{return await i.execute(e,r.arguments)}catch(t){return function(t,r=!1){return{isError:r,content:[{type:"text",text:t}]}}(t instanceof Error?t.message:String(t),!0)}}function l(t,r,e){return{jsonrpc:"2.0",id:t,error:{code:r,message:e}}}class f extends Error{}async function d(){let t=function(t={}){let r=t.handlePayload??m,e=t.write??h,n=Promise.resolve();return{push:t=>{var i;let o=Array.isArray(i=t)?1===i.length?i[0]?.id??null:null:i.id??null;n=n.then(async()=>{let n=await r(t);n&&e(n)}).catch(t=>{e({jsonrpc:"2.0",id:o,error:{code:-32603,message:t instanceof Error?t.message:String(t)}})})},idle:async()=>{await n}}}(),r=new g(r=>{t.push(r)});process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{try{r.push(t)}catch(t){h({jsonrpc:"2.0",id:null,error:{code:-32700,message:t instanceof Error?t.message:String(t)}})}}),await new Promise(t=>{process.stdin.on("end",t),process.stdin.on("close",t),process.stdin.resume()}),await t.idle()}function m(t){return Array.isArray(t)?y(t):u(t)}async function y(t){let r=[];for(let n of t){var e;r.push(...(e=await u(n))?[e]:[])}return r.length>0?r:null}class g{buffer="";sink;constructor(t){this.sink=t}push(t){for(this.buffer+=t;;){let t=this.tryReadLineMessage();if(void 0!==t){this.emit(t);continue}break}}tryReadLineMessage(){let t=this.buffer.indexOf("\n");if(-1===t)return;let r=this.buffer.slice(0,t).trim();return this.buffer=this.buffer.slice(t+1),r.length>0?r:void 0}emit(t){let r=JSON.parse(t);Array.isArray(r),this.sink(r)}}function h(t){process.stdout.write(`${JSON.stringify(t)}
2
- `)}export{d as runAgentDeviceMcpServer};
1
+ import{formatCliOutput as t}from"./cli-output.js";import{listMcpCommandMetadata as r,isCommandName as e}from"./5611.js";import{readVersion as n}from"./9671.js";let i=function(r={}){return{execute:async(n,i)=>{var u;if(!e(n))throw Error(`Unknown command tool: ${n}`);let c=!(u=i)||"object"!=typeof u||Array.isArray(u)?{client:{},outputFormat:"optimized"}:{client:function(t){let r=t.stateDir,e={};if(void 0!==r&&("string"!=typeof r||0===r.length))throw Error("Expected stateDir to be a non-empty string.");return"string"==typeof r&&(e.stateDir=r),e}(u),outputFormat:function(t){if(void 0===t)return"optimized";if("optimized"!==t&&"json"!==t)throw Error('Expected mcpOutputFormat to be "optimized" or "json".');return t}(u.mcpOutputFormat)},p=function(t){if(!t||"object"!=typeof t||Array.isArray(t))return t;let{stateDir:r,mcpOutputFormat:e,...n}=t;return n}(i),f=await o(r,c.client),l=await (r.runCommand??s)(f,n,p);return{isError:!1,structuredContent:l,content:[{type:"text",text:function(r){if("json"===r.outputFormat)return a(r.result);let e=t({name:r.name,input:r.input,result:r.result});return"string"==typeof e?.text?e.text:a(e?.data??r.result)}({name:n,input:p,result:l,outputFormat:c.outputFormat})}]}}}}();async function o(t,r){if(t.createClient)return await t.createClient(r);let{createAgentDeviceClient:e}=await import("./9542.js");return e(r)}async function s(t,r,e){let n=await import("./command-surface.js");return await n.runCommand(t,r,e)}function a(t){return"string"==typeof t?t:JSON.stringify(t,null,2)}async function u(t){if("2.0"!==t.jsonrpc||"string"!=typeof t.method)return f(t.id??null,-32600,"Invalid JSON-RPC request.");if(void 0===t.id)return null;try{var r,e;return r=t.id,e=await c(t.method,t.params),{jsonrpc:"2.0",id:r,result:e}}catch(r){if(r instanceof l)return f(t.id,-32601,r.message);return f(t.id,-32602,r instanceof Error?r.message:String(r))}}async function c(t,e){switch(t){case"initialize":return{protocolVersion:"2025-11-25",capabilities:{tools:{}},serverInfo:{name:"agent-device",version:n()}};case"ping":return{};case"tools/list":return{tools:r().map(t=>{var r;return{name:t.name,description:t.description,inputSchema:{...r=t.inputSchema,properties:{...r.properties,stateDir:{type:"string",description:"Agent-device state directory."},mcpOutputFormat:{type:"string",enum:["optimized","json"],description:"MCP text content format. Defaults to optimized agent-friendly text; use json for JSON text. Structured content is always returned separately."}}}}})};case"tools/call":return await p(e);default:throw new l(`Unsupported MCP method: ${t}`)}}async function p(t){let r=function(t){if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Expected object parameters.");return t}(t),e=function(t,r){let e=t[r];if("string"!=typeof e||0===e.length)throw Error(`Expected ${r} to be a non-empty string.`);return e}(r,"name");try{return await i.execute(e,r.arguments)}catch(t){return function(t,r=!1){return{isError:r,content:[{type:"text",text:t}]}}(t instanceof Error?t.message:String(t),!0)}}function f(t,r,e){return{jsonrpc:"2.0",id:t,error:{code:r,message:e}}}class l extends Error{}async function m(){let t=function(t={}){let r=t.handlePayload??d,e=t.write??h,n=Promise.resolve();return{push:t=>{var i;let o=Array.isArray(i=t)?1===i.length?i[0]?.id??null:null:i.id??null;n=n.then(async()=>{let n=await r(t);n&&e(n)}).catch(t=>{e({jsonrpc:"2.0",id:o,error:{code:-32603,message:t instanceof Error?t.message:String(t)}})})},idle:async()=>{await n}}}(),r=new g(r=>{t.push(r)});process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{try{r.push(t)}catch(t){h({jsonrpc:"2.0",id:null,error:{code:-32700,message:t instanceof Error?t.message:String(t)}})}}),await new Promise(t=>{process.stdin.on("end",t),process.stdin.on("close",t),process.stdin.resume()}),await t.idle()}function d(t){return Array.isArray(t)?y(t):u(t)}async function y(t){let r=[];for(let n of t){var e;r.push(...(e=await u(n))?[e]:[])}return r.length>0?r:null}class g{buffer="";sink;constructor(t){this.sink=t}push(t){for(this.buffer+=t;;){let t=this.tryReadLineMessage();if(void 0!==t){this.emit(t);continue}break}}tryReadLineMessage(){let t=this.buffer.indexOf("\n");if(-1===t)return;let r=this.buffer.slice(0,t).trim();return this.buffer=this.buffer.slice(t+1),r.length>0?r:void 0}emit(t){let r=JSON.parse(t);Array.isArray(r),this.sink(r)}}function h(t){process.stdout.write(`${JSON.stringify(t)}
2
+ `)}export{m as runAgentDeviceMcpServer};