mobileboost-cli 0.2.0 → 0.2.1

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,5 +1,5 @@
1
1
  {
2
- "date": "2025-12-30T14:53:24.641Z",
2
+ "date": "2025-12-30T15:42:47.343Z",
3
3
  "preset": "node-server",
4
4
  "framework": {
5
5
  "name": "nitro",
@@ -1 +1 @@
1
- import{z as e}from"zod";import C from"node:fs";import v from"node:path";import $ from"sharp";import{R as r}from"./constants-Dh9o88yr.mjs";const N=e.object({fullImage:e.string(),croppedImage:e.string(),targetImage:e.string(),type:e.enum(["interaction","assert","tap"]).optional()}),P=e.object({base64_screenshot:e.string(),instruction:e.string(),action_history:e.array(e.any()).optional(),executionId:e.string().optional(),elementId:e.string().optional(),uiHierarchy:e.array(e.any()).optional()});function j(){const t=v.join(process.cwd(),"mobileboost.config.json");if(!C.existsSync(t))throw new Error('mobileboost.config.json not found. Run "mobileboost init" first.');const s=C.readFileSync(t,"utf-8");return JSON.parse(s)}function x(t){return t.replace(/^data:image\/\w+;base64,/,"")}async function F(t){const{fullImage:s,croppedImage:g,targetImage:u,type:f}=t,o=j().apiKey;if(!o)throw new Error("apiKey not configured in mobileboost.config.json");const c=f==="assert"?"assert":"interaction",l={org_id:o,full_image:x(s),cropped_image:x(g),target_image:x(u),type:c},n=await fetch("https://api.mobileboost.io/cli/describe_interaction",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(!n.ok){const d=await n.text();throw new Error(`Describe interaction failed: ${n.status} ${d}`)}const i=await n.json();return i.description||i.assertion_description||JSON.stringify(i)}async function H(t){const s="https://api.mobileboost.io/call_lambda",g=j().apiKey;if(!g)throw new Error("apiKey not configured in mobileboost.config.json");const u=Buffer.from(t.base64_screenshot,"base64"),f=await $(u).metadata(),o=f.width??1080,c=f.height??1920,l=Math.round(o/r),n=await $(u).resize({width:l,withoutEnlargement:!0}).toBuffer(),i=await $(n).metadata(),d=i.width??l,h=i.height??c*(l/o),I=r,O=r;console.log(`[AI Client] Resized screenshot: ${o}x${c} -> ${d}x${h} (Scale: ${I.toFixed(2)})`);const S={lambda_flow:"get_next_step",current_date:new Date().toLocaleDateString("en-GB",{day:"numeric",month:"long",year:"numeric"}),base64_screenshot:n.toString("base64"),getUI_elements:[],uiHierarchy:t.uiHierarchy??[],test_task_string:JSON.stringify([{id:"step-1",text:`1. ${t.instruction}`,plainText:t.instruction}]),image_width:d,image_height:h,action_history:t.action_history??[],orgKey:g,template_images:{},model_provider:"vellum",model_version:"claude-agent",fallbackModel:"claude-agent",utilize_fullTextAnnotation:!1,enableSortingOCR:!0,enableActionHistoryCut:!0,removeOverlappingText:!1,currentAndPreviousScreenMatch:!1,popupDetectionEnabled:!0,ocrProvider:"gcp",modelResponseDoubleCheckEnabled:!1,modelResponseDoubleCheckModel:"claude-3-5-sonnet-20240620"};console.log(`[AI Client] Sending payload with dimensions: ${d}x${h} (Original: ${o}x${c})`),console.log("[AI Client] Payload:",{payload:S});const a=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":"230948209348203948203948203948"},body:JSON.stringify(S)});if(!a.ok){const m=await a.text();throw console.error(`[AI Client] Backend error (${a.status}):`,m),new Error(`AI Backend Error: ${a.status} ${a.statusText}`)}const p=await a.json();console.log("[AI Client] Raw response from backend:",JSON.stringify(p,null,2)),console.log(`[AI Client] Applying scale factors: X=${I.toFixed(4)}, Y=${O.toFixed(4)}`);const k=m=>m.match(/([xy])=(\d+)/)?m.replace(/([xy])=(\d+)/g,(A,y,b)=>{const w=parseInt(b,10),_=Math.round(w*r);return`${y}=${_}`}):m.replace(/(^|;)(\d+);(\d+)(;|$)/,(A,y,b,w,_)=>{const E=parseInt(b,10),T=parseInt(w,10),z=Math.round(E*r),R=Math.round(T*r);return`${y}${z};${R}${_}`});return p.appetizeCommands&&(p.appetizeCommands=p.appetizeCommands.map(k)),p}export{P as F,F as K,N as P,H as W};
1
+ import{z as e}from"zod";import C from"node:fs";import v from"node:path";import $ from"sharp";import{R as r}from"./constants-Dh9o88yr.mjs";const N=e.object({fullImage:e.string(),croppedImage:e.string(),targetImage:e.string(),type:e.enum(["interaction","assert","tap"]).optional()}),P=e.object({base64_screenshot:e.string(),instruction:e.string(),action_history:e.array(e.any()).optional(),executionId:e.string().optional(),elementId:e.string().optional(),uiHierarchy:e.array(e.any()).optional()});function j(){const t=v.join(process.cwd(),"mobileboost.config.json");if(!C.existsSync(t))throw new Error('mobileboost.config.json not found. Run "mobileboost init" first.');const s=C.readFileSync(t,"utf-8");return JSON.parse(s)}function x(t){return t.replace(/^data:image\/\w+;base64,/,"")}async function F(t){const{fullImage:s,croppedImage:g,targetImage:u,type:f}=t,o=j().apiKey;if(!o)throw new Error("apiKey not configured in mobileboost.config.json");const c=f==="assert"?"assert":"interaction",l={org_id:o,full_image:x(s),cropped_image:x(g),target_image:x(u),type:c},n=await fetch("https://api.mobileboost.io/cli/describe_interaction",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(!n.ok){const d=await n.text();throw new Error(`Describe interaction failed: ${n.status} ${d}`)}const i=await n.json();return i.description||i.assertion_description||JSON.stringify(i)}async function H(t){const s="https://api.mobileboost.io/call_lambda",g=j().apiKey;if(!g)throw new Error("apiKey not configured in mobileboost.config.json");const u=Buffer.from(t.base64_screenshot,"base64"),f=await $(u).metadata(),o=f.width??1080,c=f.height??1920,l=Math.round(o/r),n=await $(u).resize({width:l,withoutEnlargement:!0}).toBuffer(),i=await $(n).metadata(),d=i.width??l,h=i.height??c*(l/o),I=r,A=r;console.log(`[AI Client] Resized screenshot: ${o}x${c} -> ${d}x${h} (Scale: ${I.toFixed(2)})`);const S={lambda_flow:"get_next_step",current_date:new Date().toLocaleDateString("en-GB",{day:"numeric",month:"long",year:"numeric"}),base64_screenshot:n.toString("base64"),getUI_elements:[],uiHierarchy:t.uiHierarchy??[],test_task_string:JSON.stringify([{id:"step-1",text:`1. ${t.instruction}`,plainText:t.instruction}]),image_width:d,image_height:h,action_history:t.action_history??[],orgKey:g,template_images:{},model_provider:"vellum",model_version:"claude-agent",fallbackModel:"claude-agent",utilize_fullTextAnnotation:!1,enableSortingOCR:!0,enableActionHistoryCut:!0,removeOverlappingText:!1,currentAndPreviousScreenMatch:!1,popupDetectionEnabled:!0,ocrProvider:"gcp",modelResponseDoubleCheckEnabled:!1,modelResponseDoubleCheckModel:"claude-3-5-sonnet-20240620"};console.log(`[AI Client] Sending payload with dimensions: ${d}x${h} (Original: ${o}x${c})`),console.log("[AI Client] Payload:",{payload:S});const a=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":"230948209348203948203948203948"},body:JSON.stringify(S)});if(!a.ok){const m=await a.text();throw console.error(`[AI Client] Backend error (${a.status}):`,m),new Error(`AI Backend Error: ${a.status} ${a.statusText}`)}const p=await a.json();console.log("[AI Client] Raw response from backend:",JSON.stringify(p,null,2)),console.log(`[AI Client] Applying scale factors: X=${I.toFixed(4)}, Y=${A.toFixed(4)}`);const O=m=>m.match(/([xy])=(\d+)/)?m.replace(/([xy])=(\d+)/g,(k,y,b)=>{const w=parseInt(b,10),_=Math.round(w*r);return`${y}=${_}`}):m.replace(/(^|;)(\d+);(\d+)(;|$)/,(k,y,b,w,_)=>{const E=parseInt(b,10),T=parseInt(w,10),z=Math.round(E*r),R=Math.round(T*r);return`${y}${z};${R}${_}`});return p.appetizeCommands&&(p.appetizeCommands=p.appetizeCommands.map(O)),p}export{P as F,F as K,N as P,H as W};
@@ -1 +1 @@
1
- import{c as b,a as y}from"./server.mjs";import w from"node:fs";import M from"node:path";import P from"node:crypto";import l from"sharp";import{a as E,i as F,o as v}from"./cache-CtBF0d8x.mjs";import{R as h}from"./constants-Dh9o88yr.mjs";import"@tanstack/history";import"@tanstack/router-core/ssr/client";import"@tanstack/router-core";import"node:async_hooks";import"@tanstack/router-core/ssr/server";import"../../index.mjs";import"node:http";import"node:stream";import"node:https";import"node:http2";import"node:url";import"tiny-invariant";import"seroval";import"react/jsx-runtime";import"@tanstack/react-router/ssr/server";import"@tanstack/react-router";import"zod";const $="https://cache.mobileboost.io";function x(){const e=M.join(process.cwd(),"mobileboost.config.json");if(!w.existsSync(e))throw new Error("mobileboost.config.json not found");const t=w.readFileSync(e,"utf-8");return JSON.parse(t)}function _(e,t,c,r,n,a){const o=a?`${a.width}x${a.height}`:"",i=`${e}${t||""}${c}${r}${n||""}${o}`;return P.createHash("sha256").update(i).digest("hex")}function S(e,t){return e.match(/([xy])=(\d+)/)?e.replace(/([xy])=(\d+)/g,(c,r,n)=>{const a=parseInt(n,10);let o;return t==="multiply"?o=Math.round(a*h):o=Math.round(a/h),`${r}=${o}`}):e.replace(/(^|;)(\d+);(\d+)(;|$)/,(c,r,n,a,o)=>{const i=parseInt(n,10),s=parseInt(a,10);let d,p;return t==="multiply"?(d=Math.round(i*h),p=Math.round(s*h)):(d=Math.round(i/h),p=Math.round(s/h)),`${r}${d};${p}${o}`})}const B=b("fcbe7e11d05240fa28a1dd79ec8c395f6c03682edbaeb19f469bd78d6399cdde",(e,t)=>O.__executeServer(e,t)),O=y({method:"POST"}).inputValidator(e=>v.parse(e)).handler(B,async({data:e})=>{try{const t=x().apiKey;if(!t)throw new Error("API Key missing");const c=_(t,e.filepath,e.stepNumber,e.stepDescription,e.platform,e.screenResolution),r=await Promise.all(e.executionData.map(async i=>{const s=Buffer.from(i.screenshot.replace(/^data:image\/\w+;base64,/,""),"base64"),d=(await l(s).metadata()).width??1080,p=Math.round(d/h),u=await l(s).resize({width:p,withoutEnlargement:!0}).toBuffer(),f=i.commands.map(g=>S(g,"divide"));return{screenshot:u.toString("base64"),commands:f}})),n=JSON.stringify(r),a=(n.length/(1024*1024)).toFixed(2);console.log(`[Cache Client] Populating cache with payload size: ~${a} MB (Hash: ${c})`);const o=await fetch(`${$}/populate-cache?hash=${c}`,{method:"POST",headers:{"Content-Type":"application/json"},body:n});return o.ok?{success:!0}:(console.error("Failed to populate cache:",await o.text()),{success:!1})}catch(t){return console.error("Error populating cache:",t),{success:!1,error:String(t)}}}),T=b("7d2aacaab26ab11cdc66f03a4ed01b8b38186abf16ab1f9306801ea7769aaa2a",(e,t)=>z.__executeServer(e,t)),z=y({method:"POST"}).inputValidator(e=>E.parse(e)).handler(T,async({data:e})=>{try{const t=x().apiKey;if(!t)throw new Error("API Key missing");const c=_(t,e.filepath,e.stepNumber,e.stepDescription,e.platform,e.screenResolution),r=Buffer.from(e.screenshot.replace(/^data:image\/\w+;base64,/,""),"base64"),n=(await l(r).metadata()).width??1080,a=Math.round(n/h),o=await l(r).resize({width:a,withoutEnlargement:!0}).toBuffer(),i=await l(o).metadata();console.log(i.width,i.height);const s=new FormData;s.append("hash",c);const d=new Blob([new Uint8Array(o)],{type:"image/png"}),p=(d.size/(1024*1024)).toFixed(2);console.log(`[Cache Client] Executing from cache with screenshot size: ${p} MB`),s.append("screenshot",d,"screenshot.png"),e.highest_used_index!==void 0&&e.highest_used_index!==null&&(console.log(`[Cache Client] Sending highest_used_index: ${e.highest_used_index} (Type: ${typeof e.highest_used_index})`),s.append("highest_used_index",String(e.highest_used_index)));const u=await fetch(`${$}/execute-from-cache`,{method:"POST",body:s});if(!u.ok){const m=await u.text();return console.warn("Cache lookup failed:",m),{found:!1}}const f=await u.json(),g=F.safeParse(f);if(g.success){const m={...g.data};return m.found&&m.cacheCommands&&(m.cacheCommands=m.cacheCommands.map(C=>S(C,"multiply"))),m}return console.error("Invalid cache response:",f),{found:!1}}catch(t){return console.error("Error executing from cache:",t),{found:!1,error:String(t)}}});export{T as executeFromCacheMutation_createServerFn_handler,B as populateCacheMutation_createServerFn_handler};
1
+ import{c as b,a as $}from"./server.mjs";import w from"node:fs";import M from"node:path";import P from"node:crypto";import l from"sharp";import{a as E,i as F,o as v}from"./cache-CtBF0d8x.mjs";import{R as h}from"./constants-Dh9o88yr.mjs";import"@tanstack/history";import"@tanstack/router-core/ssr/client";import"@tanstack/router-core";import"node:async_hooks";import"@tanstack/router-core/ssr/server";import"../../index.mjs";import"node:http";import"node:stream";import"node:https";import"node:http2";import"node:url";import"tiny-invariant";import"seroval";import"react/jsx-runtime";import"@tanstack/react-router/ssr/server";import"@tanstack/react-router";import"zod";const y="https://cache.mobileboost.io";function x(){const e=M.join(process.cwd(),"mobileboost.config.json");if(!w.existsSync(e))throw new Error("mobileboost.config.json not found");const t=w.readFileSync(e,"utf-8");return JSON.parse(t)}function _(e,t,c,r,n,a){const o=a?`${a.width}x${a.height}`:"",i=`${e}${t||""}${c}${r}${n||""}${o}`;return P.createHash("sha256").update(i).digest("hex")}function S(e,t){return e.match(/([xy])=(\d+)/)?e.replace(/([xy])=(\d+)/g,(c,r,n)=>{const a=parseInt(n,10);let o;return t==="multiply"?o=Math.round(a*h):o=Math.round(a/h),`${r}=${o}`}):e.replace(/(^|;)(\d+);(\d+)(;|$)/,(c,r,n,a,o)=>{const i=parseInt(n,10),s=parseInt(a,10);let d,p;return t==="multiply"?(d=Math.round(i*h),p=Math.round(s*h)):(d=Math.round(i/h),p=Math.round(s/h)),`${r}${d};${p}${o}`})}const B=b("fcbe7e11d05240fa28a1dd79ec8c395f6c03682edbaeb19f469bd78d6399cdde",(e,t)=>O.__executeServer(e,t)),O=$({method:"POST"}).inputValidator(e=>v.parse(e)).handler(B,async({data:e})=>{try{const t=x().apiKey;if(!t)throw new Error("API Key missing");const c=_(t,e.filepath,e.stepNumber,e.stepDescription,e.platform,e.screenResolution),r=await Promise.all(e.executionData.map(async i=>{const s=Buffer.from(i.screenshot.replace(/^data:image\/\w+;base64,/,""),"base64"),d=(await l(s).metadata()).width??1080,p=Math.round(d/h),u=await l(s).resize({width:p,withoutEnlargement:!0}).toBuffer(),f=i.commands.map(g=>S(g,"divide"));return{screenshot:u.toString("base64"),commands:f}})),n=JSON.stringify(r),a=(n.length/(1024*1024)).toFixed(2);console.log(`[Cache Client] Populating cache with payload size: ~${a} MB (Hash: ${c})`);const o=await fetch(`${y}/populate-cache?hash=${c}`,{method:"POST",headers:{"Content-Type":"application/json"},body:n});return o.ok?{success:!0}:(console.error("Failed to populate cache:",await o.text()),{success:!1})}catch(t){return console.error("Error populating cache:",t),{success:!1,error:String(t)}}}),T=b("7d2aacaab26ab11cdc66f03a4ed01b8b38186abf16ab1f9306801ea7769aaa2a",(e,t)=>z.__executeServer(e,t)),z=$({method:"POST"}).inputValidator(e=>E.parse(e)).handler(T,async({data:e})=>{try{const t=x().apiKey;if(!t)throw new Error("API Key missing");const c=_(t,e.filepath,e.stepNumber,e.stepDescription,e.platform,e.screenResolution),r=Buffer.from(e.screenshot.replace(/^data:image\/\w+;base64,/,""),"base64"),n=(await l(r).metadata()).width??1080,a=Math.round(n/h),o=await l(r).resize({width:a,withoutEnlargement:!0}).toBuffer(),i=await l(o).metadata();console.log(i.width,i.height);const s=new FormData;s.append("hash",c);const d=new Blob([new Uint8Array(o)],{type:"image/png"}),p=(d.size/(1024*1024)).toFixed(2);console.log(`[Cache Client] Executing from cache with screenshot size: ${p} MB`),s.append("screenshot",d,"screenshot.png"),e.highest_used_index!==void 0&&e.highest_used_index!==null&&(console.log(`[Cache Client] Sending highest_used_index: ${e.highest_used_index} (Type: ${typeof e.highest_used_index})`),s.append("highest_used_index",String(e.highest_used_index)));const u=await fetch(`${y}/execute-from-cache`,{method:"POST",body:s});if(!u.ok){const m=await u.text();return console.warn("Cache lookup failed:",m),{found:!1}}const f=await u.json(),g=F.safeParse(f);if(g.success){const m={...g.data};return m.found&&m.cacheCommands&&(m.cacheCommands=m.cacheCommands.map(C=>S(C,"multiply"))),m}return console.error("Invalid cache response:",f),{found:!1}}catch(t){return console.error("Error executing from cache:",t),{found:!1,error:String(t)}}});export{T as executeFromCacheMutation_createServerFn_handler,B as populateCacheMutation_createServerFn_handler};