bridge-agent 0.13.8 → 0.13.9

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 (2) hide show
  1. package/dist/index.js +2 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -387,7 +387,7 @@ session. You may call bridge_get_role_prompt again at any time to refresh.
387
387
 
388
388
  If bridge_get_role_prompt is unavailable, fall back to default behavior for role=${t}.`}var Mi=S(require("os"));async function Fr(){return Mi.default.platform()!=="darwin"?null:{key:"sim_ios",displayName:"iOS Simulator",binaryPath:"xcrun",authStatus:"ok"}}var je=require("child_process"),Gr=require("fs/promises"),Wi=require("crypto"),pt=S(require("fs")),In=S(require("path")),Hr=S(require("os"));var jt=require("child_process"),$i=require("fs/promises"),Bi=S(require("path")),Ui=S(require("os"));async function wd(){return new Promise(t=>{let e=(0,jt.spawn)("xcrun",["simctl","list","devices","booted","--json"],{timeout:5e3}),n="";e.stdout.on("data",r=>{n+=r.toString("utf8")}),e.on("close",r=>{if(r!==0){t(null);return}try{let o=JSON.parse(n);for(let s of Object.values(o.devices)){let i=s.find(a=>a.state==="Booted");if(i){t(i.udid);return}}t(null)}catch{t(null)}}),e.on("error",()=>t(null))})}async function Sd(){return new Promise(t=>{let e=(0,jt.spawn)("xcrun",["simctl","list","devices","available","--json"],{timeout:5e3}),n="";e.stdout.on("data",r=>{n+=r.toString("utf8")}),e.on("close",r=>{if(r!==0){t([]);return}try{let o=JSON.parse(n),s=[];for(let[i,a]of Object.entries(o.devices)){for(let c of a){let l=i.replace(/^com\.apple\.CoreSimulator\.SimRuntime\./,"").replace(/-/g,".");if(s.push(`${c.name} (${l})`),s.length>=3)break}if(s.length>=3)break}t(s)}catch{t([])}}),e.on("error",()=>t([]))})}async function Wr(t){let e=[],n=null,r=await new Promise(s=>{let i=(0,jt.spawn)("xcrun",["simctl","help"],{timeout:2e3});i.on("close",a=>s(a===0)),i.on("error",()=>s(!1)),i.stdout?.resume(),i.stderr?.resume()});e.push({id:"xcrun_exists",status:r?"pass":"fail",label:"Xcode CLI tools",detail:r?void 0:"Xcode command-line tools not found. Install them to use the iOS Simulator panel.",fixCmd:r?void 0:"xcode-select --install"});let o=!1;if(r){let s=Bi.default.join(Ui.default.homedir(),".local/bin/idb");o=await(0,$i.access)(s).then(()=>!0).catch(()=>!1)}if(e.push({id:"idb_present",status:o?"pass":"fail",label:"idb",detail:o?void 0:"idb not found at ~/.local/bin/idb. Required for simulator automation.",fixCmd:o?void 0:"pip3 install fb-idb && brew install facebook/fb/idb-companion"}),r){let s=await new Promise(i=>{let a=(0,jt.spawn)("xcrun",["simctl","list","--json"],{timeout:5e3});a.on("close",c=>i(c===0)),a.on("error",()=>i(!1)),a.stdout?.resume(),a.stderr?.resume()});if(e.push({id:"simctl_ok",status:s?"pass":"fail",label:"simctl",detail:s?void 0:"simctl is not responding. Xcode may not be fully installed.",fixCmd:s?void 0:"sudo xcode-select --reset"}),s)if(n=await wd(),n)e.push({id:"booted_simulator",status:"pass",label:"Booted simulator"});else{let i=await Sd();e.push({id:"booted_simulator",status:"fail",label:"Booted simulator",detail:i.length>0?`No simulator is booted. Available: ${i.join(", ")}. Open Simulator.app and boot one.`:"No simulator is booted and no devices found. Open Xcode \u2192 Window \u2192 Devices and Simulators to add one.",fixCmd:"open -a Simulator"})}else e.push({id:"booted_simulator",status:"fail",label:"Booted simulator",detail:"Skipped \u2014 previous check failed"})}else e.push({id:"simctl_ok",status:"fail",label:"simctl",detail:"Skipped \u2014 previous check failed"}),e.push({id:"booted_simulator",status:"fail",label:"Booted simulator",detail:"Skipped \u2014 previous check failed"});return{checks:e,udid:n}}var qr=In.default.join(Hr.default.homedir(),".local/bin/idb");async function Fi(t){try{let e=await new Promise((s,i)=>{let a=(0,je.spawn)(qr,["describe","--udid",t,"--json"],{timeout:1e4}),c="",l="";a.stdout.on("data",d=>{c+=d.toString("utf8")}),a.stderr.on("data",d=>{l+=d.toString("utf8")}),a.on("close",d=>{d!==0?i(new Error(l||`idb exited ${d}`)):s(c)}),a.on("error",d=>i(d))}),n=JSON.parse(e),r=n.screen_dimensions?.width_points,o=n.screen_dimensions?.height_points;if(Number.isFinite(r)&&Number.isFinite(o))return{width:r,height:o}}catch(e){console.warn("[daemon] simulator.metadata.error",{udid:t,error:String(e)})}return{}}function kd(t,e,n){let r=Buffer.from(t,"utf-8"),o=Buffer.allocUnsafe(1+r.length+4);return o.writeUInt8(r.length,0),r.copy(o,1),o.writeUInt16BE(Math.max(0,Math.min(65535,e)),1+r.length),o.writeUInt16BE(Math.max(0,Math.min(65535,n)),1+r.length+2),o}function vd(t,e){let n=`/tmp/sim_frame_${e}.png`,r=`/tmp/sim_frame_${e}.jpg`;return new Promise(o=>{let s=(0,je.spawn)("xcrun",["simctl","io",t,"screenshot",n],{stdio:["ignore","ignore","ignore"]});s.on("close",async i=>{if(i!==0){o(null);return}try{await new Promise((a,c)=>{let l=(0,je.spawn)("sips",["-s","format","jpeg",n,"--out",r],{stdio:["ignore","ignore","ignore"]});l.on("close",d=>d===0?a():c(new Error(`sips exited ${d}`))),l.on("error",d=>c(d))}),o(await(0,Gr.readFile)(r))}catch{try{o(await(0,Gr.readFile)(n))}catch{o(null)}}}),s.on("error",()=>o(null))})}function En(t,e){return new Promise((n,r)=>{let o=(0,je.spawn)(qr,[...e,"--udid",t],{timeout:15e3}),s="";o.stderr.on("data",i=>{s+=i.toString("utf8")}),o.on("close",i=>{i!==0?r(new Error(s||`idb exited ${i}`)):n()}),o.on("error",i=>r(i))})}var xn=class{sessions=new Map;pendingSubscriptions=new Set;pendingUdids=new Map;pendingDaemonBootedUdids=new Set;bootedUdidsByAgent=new Map;ws=null;daemonId;installProc=new Map;cancelledInstalls=new Set;constructor(e){this.daemonId=e}updateWs(e){this.ws=e}async start(e){if(this.sessions.has(e)){console.warn("[daemon] simulator.start: session already exists",{agentId:e});return}let{checks:n,udid:r}=await Wr(e);if(this.sendSimHealth(e,n),n.find(u=>u.status==="fail")){if(this.bootedUdidsByAgent.has(e)){let u=this.bootedUdidsByAgent.get(e);this.pendingDaemonBootedUdids.delete(u),this.bootedUdidsByAgent.delete(e)}return}if(!r){this.sendError(e,"SPAWN_FAILED","No booted iOS simulator found");return}let s=[...this.sessions.values()].find(u=>u.udid===r);if(s){this.sendError(e,"DUPLICATE_SIMULATOR",`Simulator already attached as agent ${s.agentId}`,{existingAgentId:s.agentId,udid:r});return}let i=this.pendingUdids.get(r);if(i&&i!==e){this.sendError(e,"DUPLICATE_SIMULATOR",`Simulator already being attached as agent ${i}`,{existingAgentId:i,udid:r});return}this.pendingUdids.set(r,e);let a=this.pendingSubscriptions.has(e);this.pendingSubscriptions.delete(e);let c=await Fi(r);c.width!=null&&c.height!=null&&console.log("[daemon] simulator.metadata",{agentId:e,udid:r,logicalWidth:c.width,logicalHeight:c.height});let l=this.pendingDaemonBootedUdids.has(r);l&&(this.pendingDaemonBootedUdids.delete(r),this.bootedUdidsByAgent.delete(e));let d={agentId:e,udid:r,frameInterval:null,capturing:!1,subscribed:a,logicalWidth:c.width,logicalHeight:c.height,lastDescribeAt:Date.now(),daemonBooted:l};if(this.sessions.set(e,d),this.pendingUdids.delete(r),d.frameInterval=setInterval(async()=>{if(!(!d.subscribed||d.capturing)&&!(!this.ws||this.ws.bufferedAmount>256*1024)){d.capturing=!0;try{Date.now()-d.lastDescribeAt>=5e3&&(d.lastDescribeAt=Date.now(),Fi(r).then(p=>{p.width!=null&&p.height!=null&&(p.width!==d.logicalWidth||p.height!==d.logicalHeight)&&(console.log("[daemon] simulator.metadata.update",{agentId:e,udid:r,from:{logicalWidth:d.logicalWidth,logicalHeight:d.logicalHeight},to:p}),d.logicalWidth=p.width,d.logicalHeight=p.height)}).catch(()=>{}));let u=await vd(r,e);if(u&&this.ws&&this.ws.readyState===A.OPEN){let p=d.logicalWidth??0,f=d.logicalHeight??0,h=kd(e,p,f);this.ws.send(Buffer.concat([h,u]),{binary:!0})}}catch(u){console.error("[daemon] simulator.capture.error",{agentId:e,error:String(u)})}finally{d.capturing=!1}}},200),this.ws&&this.ws.readyState===A.OPEN){let u=(0,Wi.randomUUID)();this.ws.send(JSON.stringify({type:"session_started",agentId:e,sessionId:u})),this.ws.send(JSON.stringify({type:"agent_spawned",agentId:e,agentKey:"sim_ios",daemonId:this.daemonId}))}console.log("[daemon] simulator.started",{agentId:e,udid:r})}stop(e){let n=this.installProc.get(e);n&&(console.log("[daemon] simulator.install.cancelled",{agentId:e}),this.cancelledInstalls.add(e),n.kill("SIGTERM"),this.installProc.delete(e));let r=this.sessions.get(e);if(!r){for(let[i,a]of this.pendingUdids)if(a===e){this.pendingUdids.delete(i);break}return}r.frameInterval&&clearInterval(r.frameInterval);let o=r.udid,s=r.daemonBooted;this.sessions.delete(e),this.pendingUdids.delete(o),this.ws&&this.ws.readyState===A.OPEN&&this.ws.send(JSON.stringify({type:"exit",agentId:e,exitCode:0,signal:null})),console.log("[daemon] simulator.stop",{agentId:e,udid:o,daemonBooted:s}),s&&(0,je.spawn)("xcrun",["simctl","shutdown",o],{stdio:"ignore"}).on("error",i=>console.warn("[daemon] simulator.shutdown.error",{udid:o,err:String(i)}))}stopAll(){for(let e of[...this.installProc.keys()])this.stop(e);for(let e of[...this.sessions.keys()])this.stop(e)}subscribe(e){let n=this.sessions.get(e);n&&(n.subscribed=!0)}unsubscribe(e){let n=this.sessions.get(e);n&&(n.subscribed=!1)}async handle(e){let n=this.sessions.get(e.agentId);if(e.type==="sim_subscribe"){n?this.subscribe(e.agentId):this.pendingSubscriptions.add(e.agentId);return}if(e.type==="sim_unsubscribe"){this.pendingSubscriptions.delete(e.agentId),n&&this.unsubscribe(e.agentId);return}if(e.type==="sim_healthcheck"){let{checks:r}=await Wr(e.agentId);this.sendSimHealth(e.agentId,r);return}if(e.type==="sim_install_run"){await this.handleSimInstallRun(e.agentId);return}if(e.type==="sim_install_cancel"){this.handleSimInstallCancel(e.agentId);return}if(!n){console.warn("[daemon] simulator.handle: no session",{agentId:e.agentId,type:e.type});return}try{switch(e.type){case"sim_tap":{await En(n.udid,["ui","tap",String(e.x),String(e.y)]);break}case"sim_swipe":{await En(n.udid,["ui","swipe",String(e.x1),String(e.y1),String(e.x2),String(e.y2),"--duration",String(e.duration??.5)]);break}case"sim_key":{await En(n.udid,["ui","text",e.key]);break}case"sim_button":{console.log("[daemon] simulator.button.start",{agentId:e.agentId,button:e.button,udid:n.udid}),await En(n.udid,["ui","button",e.button]),console.log("[daemon] simulator.button.done",{agentId:e.agentId,button:e.button});break}case"sim_get_source":{let r=await new Promise((o,s)=>{let i=(0,je.spawn)(qr,["ui","describe-all","--udid",n.udid],{timeout:15e3}),a="",c="";i.stdout.on("data",l=>{a+=l.toString("utf8")}),i.stderr.on("data",l=>{c+=l.toString("utf8")}),i.on("close",l=>{l!==0?s(new Error(c||`idb exited ${l}`)):o(a)}),i.on("error",l=>s(l))});this.ws&&this.ws.readyState===A.OPEN&&this.ws.send(JSON.stringify({type:"sim_source",agentId:e.agentId,source:r}));break}}}catch(r){console.error("[daemon] simulator.handle.error",{agentId:e.agentId,type:e.type,error:String(r)})}}sendError(e,n,r,o){this.ws&&this.ws.readyState===A.OPEN&&this.ws.send(JSON.stringify({type:"error",code:n,message:r,agentId:e,...o}))}sendSimHealth(e,n){this.ws&&this.ws.readyState===A.OPEN&&this.ws.send(JSON.stringify({type:"sim_health",agentId:e,checks:n}))}resolveSimInstallScript(){let e=process.env.BRIDGE_SIM_INSTALL_SCRIPT;if(e)return e;let n=In.default.join(Hr.default.homedir(),".bridge/install-sim-prereqs.sh");if(pt.default.existsSync(n))return n;let r=In.default.join(__dirname,"../../../scripts/install-sim-prereqs.sh");return pt.default.existsSync(r)?r:null}async handleSimInstallRun(e){if(this.installProc.has(e)){this.sendInstallProgress(e,{step:"error",error:"already installing"});return}this.cancelledInstalls.delete(e);let n=this.resolveSimInstallScript();if(!n){this.sendInstallProgress(e,{step:"error",error:"install script not found"});return}try{pt.default.accessSync(n,pt.default.constants.F_OK|pt.default.constants.X_OK)}catch{this.sendInstallProgress(e,{step:"error",error:`install script not found at ${n}`});return}let r=(0,je.spawn)("bash",["-lc",n],{timeout:6e5});this.installProc.set(e,r);let o="pre_check",s="",i="";r.stdout?.on("data",a=>{s+=a.toString("utf8");let c;for(;(c=s.indexOf(`
389
389
  `))!==-1;){let l=s.slice(0,c);if(s=s.slice(c+1),!!l)if(l.startsWith("STEP:"))o=l.slice(5).trim(),this.sendInstallProgress(e,{step:o});else if(l.startsWith("BOOTED_UDID:")){let d=l.slice(12).trim();this.pendingDaemonBootedUdids.add(d),this.bootedUdidsByAgent.set(e,d)}else this.sendInstallProgress(e,{stream:"stdout",line:l})}}),r.stderr?.on("data",a=>{i+=a.toString("utf8");let c;for(;(c=i.indexOf(`
390
- `))!==-1;){let l=i.slice(0,c);i=i.slice(c+1),l&&this.sendInstallProgress(e,{stream:"stderr",line:l})}}),r.on("close",a=>{if(this.installProc.delete(e),a!==0){let l=this.bootedUdidsByAgent.get(e);l&&(this.pendingDaemonBootedUdids.delete(l),this.bootedUdidsByAgent.delete(e))}if(s){let l=s;s="",l.startsWith("STEP:")?(o=l.slice(5).trim(),this.sendInstallProgress(e,{step:o})):this.sendInstallProgress(e,{stream:"stdout",line:l})}if(i){let l=i;i="",this.sendInstallProgress(e,{stream:"stderr",line:l})}let c=this.cancelledInstalls.has(e);this.cancelledInstalls.delete(e),!c&&(a===0?this.sendInstallProgress(e,{step:"done",exitCode:0}):this.sendInstallProgress(e,{step:"error",exitCode:a??void 0,error:`install script exited with code ${a}`}))}),r.on("error",a=>{this.installProc.delete(e);let c=this.bootedUdidsByAgent.get(e);c&&(this.pendingDaemonBootedUdids.delete(c),this.bootedUdidsByAgent.delete(e));let l=this.cancelledInstalls.has(e);this.cancelledInstalls.delete(e),!l&&this.sendInstallProgress(e,{step:"error",error:String(a)})})}handleSimInstallCancel(e){let n=this.installProc.get(e);if(!n)return;this.cancelledInstalls.add(e);let r=this.bootedUdidsByAgent.get(e);r&&(this.pendingDaemonBootedUdids.delete(r),this.bootedUdidsByAgent.delete(e)),n.kill("SIGTERM"),this.installProc.delete(e),this.sendInstallProgress(e,{step:"error",error:"cancelled by user"})}sendInstallProgress(e,n){this.ws&&this.ws.readyState===A.OPEN&&this.ws.send(JSON.stringify({type:"sim_install_progress",agentId:e,...n}))}};Ke();Z();function ie(){return"0.13.8"}var eo=require("fs"),Zr=S(require("path")),ea=S(require("os"));var Zi=require("node:fs"),Pn=class{cache=new Map;get(e,n){let r=this.cache.get(e);if(r&&r.mtimeMs===n.mtimeMs&&r.size===n.size)return r.value}set(e,n,r){this.cache.set(e,{mtimeMs:n.mtimeMs,size:n.size,value:r})}invalidate(e){this.cache.delete(e)}clear(){this.cache.clear()}prune(e){for(let n of this.cache.keys())e.has(n)||this.cache.delete(n)}prunePrefix(e,n){for(let r of this.cache.keys())r.startsWith(e)&&!n.has(r)&&this.cache.delete(r)}get size(){return this.cache.size}},V=new Pn,Xf=new Pn;async function ae(t){try{let e=await Zi.promises.stat(t);return{mtimeMs:e.mtimeMs,size:e.size}}catch{return null}}function Se(){return new Promise(t=>setImmediate(t))}var Od=2e5,Td="ctx:";async function Pd(t){let e=Zr.default.join(ea.default.homedir(),".claude","projects");try{let n=await eo.promises.readdir(e,{withFileTypes:!0});for(let r of n){if(!r.isDirectory())continue;let o=Zr.default.join(e,r.name,`${t}.jsonl`);if(await ae(o))return o}}catch{}}async function Cd(t,e){let n=await ae(t);if(!n)return null;let r=Td+t,o=V.get(r,n);if(o!==void 0)return o;await Se();try{let i=(await eo.promises.readFile(t,"utf-8")).trim().split(`
390
+ `))!==-1;){let l=i.slice(0,c);i=i.slice(c+1),l&&this.sendInstallProgress(e,{stream:"stderr",line:l})}}),r.on("close",a=>{if(this.installProc.delete(e),a!==0){let l=this.bootedUdidsByAgent.get(e);l&&(this.pendingDaemonBootedUdids.delete(l),this.bootedUdidsByAgent.delete(e))}if(s){let l=s;s="",l.startsWith("STEP:")?(o=l.slice(5).trim(),this.sendInstallProgress(e,{step:o})):this.sendInstallProgress(e,{stream:"stdout",line:l})}if(i){let l=i;i="",this.sendInstallProgress(e,{stream:"stderr",line:l})}let c=this.cancelledInstalls.has(e);this.cancelledInstalls.delete(e),!c&&(a===0?this.sendInstallProgress(e,{step:"done",exitCode:0}):this.sendInstallProgress(e,{step:"error",exitCode:a??void 0,error:`install script exited with code ${a}`}))}),r.on("error",a=>{this.installProc.delete(e);let c=this.bootedUdidsByAgent.get(e);c&&(this.pendingDaemonBootedUdids.delete(c),this.bootedUdidsByAgent.delete(e));let l=this.cancelledInstalls.has(e);this.cancelledInstalls.delete(e),!l&&this.sendInstallProgress(e,{step:"error",error:String(a)})})}handleSimInstallCancel(e){let n=this.installProc.get(e);if(!n)return;this.cancelledInstalls.add(e);let r=this.bootedUdidsByAgent.get(e);r&&(this.pendingDaemonBootedUdids.delete(r),this.bootedUdidsByAgent.delete(e)),n.kill("SIGTERM"),this.installProc.delete(e),this.sendInstallProgress(e,{step:"error",error:"cancelled by user"})}sendInstallProgress(e,n){this.ws&&this.ws.readyState===A.OPEN&&this.ws.send(JSON.stringify({type:"sim_install_progress",agentId:e,...n}))}};Ke();Z();function ie(){return"0.13.9"}var eo=require("fs"),Zr=S(require("path")),ea=S(require("os"));var Zi=require("node:fs"),Pn=class{cache=new Map;get(e,n){let r=this.cache.get(e);if(r&&r.mtimeMs===n.mtimeMs&&r.size===n.size)return r.value}set(e,n,r){this.cache.set(e,{mtimeMs:n.mtimeMs,size:n.size,value:r})}invalidate(e){this.cache.delete(e)}clear(){this.cache.clear()}prune(e){for(let n of this.cache.keys())e.has(n)||this.cache.delete(n)}prunePrefix(e,n){for(let r of this.cache.keys())r.startsWith(e)&&!n.has(r)&&this.cache.delete(r)}get size(){return this.cache.size}},V=new Pn,Xf=new Pn;async function ae(t){try{let e=await Zi.promises.stat(t);return{mtimeMs:e.mtimeMs,size:e.size}}catch{return null}}function Se(){return new Promise(t=>setImmediate(t))}var Od=2e5,Td="ctx:";async function Pd(t){let e=Zr.default.join(ea.default.homedir(),".claude","projects");try{let n=await eo.promises.readdir(e,{withFileTypes:!0});for(let r of n){if(!r.isDirectory())continue;let o=Zr.default.join(e,r.name,`${t}.jsonl`);if(await ae(o))return o}}catch{}}async function Cd(t,e){let n=await ae(t);if(!n)return null;let r=Td+t,o=V.get(r,n);if(o!==void 0)return o;await Se();try{let i=(await eo.promises.readFile(t,"utf-8")).trim().split(`
391
391
  `);for(let a=i.length-1;a>=0;a--){let c=i[a]?.trim();if(c)try{let l=JSON.parse(c),d=l.message?.usage??l.usage;if(!d||typeof d!="object")continue;let u=d,p=(u.input_tokens??0)+(u.cache_creation_input_tokens??0)+(u.cache_read_input_tokens??0);if(p===0)continue;let h={usedPct:Math.min(100,Math.round(p/Od*100)),usedTokens:p};return V.set(r,n,h),h}catch{continue}}}catch{}return null}function to(t,e,n){let r,o=-1,s=!0,i=async()=>{if(s)try{if(r||(r=await Pd(e)),!r)return;let l=await Cd(r,o);if(!l||l.usedTokens===o)return;o=l.usedTokens,s&&n(t,l.usedPct,l.usedTokens)}catch{}},a=setTimeout(()=>{i()},5e3),c=setInterval(()=>{i()},6e4);return()=>{s=!1,clearTimeout(a),clearInterval(c)}}var $t=require("fs"),Cn=S(require("path")),oa=S(require("os"));Z();var ta=300*60*1e3,no={free:10,pro:40,max_5x:200,max_20x:200};function Bt(){let t=Q();try{let{statSync:e,readFileSync:n}=require("fs");if(!e(t,{throwIfNoEntry:!1}))return"pro";let o=JSON.parse(n(t,"utf-8")).claudeTier;if(typeof o=="string"&&o in no)return o}catch{}return"pro"}function Ad(t){if(!Array.isArray(t))return!1;for(let e of t)if(e&&typeof e=="object"&&e.type==="tool_result")return!0;return!1}var na="quota:";async function ra(){let t=Cn.default.join(oa.default.homedir(),".claude","projects"),n=Date.now()-ta,r=1/0,o=0,s=new Set;try{let a=await $t.promises.readdir(t,{withFileTypes:!0});for(let c of a){if(!c.isDirectory())continue;let l=Cn.default.join(t,c.name),d;try{d=(await $t.promises.readdir(l,{withFileTypes:!0})).filter(p=>p.isFile()&&p.name.endsWith(".jsonl")).map(p=>p.name)}catch{continue}for(let u of d){let p=Cn.default.join(l,u),f=await ae(p);if(!f)continue;await Se();let h=na+p;s.add(h);let g=V.get(h,f);if(g!==void 0){for(let x of g.events)x.epoch>=n&&(o++,x.epoch<r&&(r=x.epoch));continue}let w;try{if(f.size>20*1024*1024){let y=Math.max(0,f.size-10485760),b=await $t.promises.open(p,"r");try{let m=Buffer.alloc(f.size-y);await b.read(m,0,m.length,y);let k=m.toString("utf-8"),_=k.indexOf(`
392
392
  `);w=_>=0?k.slice(_+1):k}finally{await b.close()}}else w=await $t.promises.readFile(p,"utf-8")}catch{continue}let E=0,O=1/0,T=[];for(let x of w.split(`
393
393
  `)){let y=x.trim();if(y)try{let b=JSON.parse(y);if(b.type!=="user")continue;let m=b.message;if(m?.role!=="user"||b.userType!==void 0&&b.userType!=="external"||Ad(m?.content)||b.isSidechain===!0||b.isMeta===!0)continue;let k=b.timestamp;if(typeof k!="string")continue;let _=Date.parse(k);if(isNaN(_)||_<n)continue;E++,T.push({epoch:_}),_<O&&(O=_)}catch{continue}}o+=E,O<r&&(r=O),V.set(h,f,{events:T})}}}catch{}V.prunePrefix(na,s);let i=isFinite(r)?r+ta:0;return{prompts5h:o,resetAt:i}}function sa(t){let e=!0,n=async()=>{if(e)try{let s=Bt(),i=no[s]??40,{prompts5h:a,resetAt:c}=await ra();e&&t({prompts5h:a,limit5h:i,resetAt:c,tier:s})}catch(s){console.warn("[claude-quota] poll failed",s)}};oo(async()=>{if(e)try{let s=Bt(),i=no[s]??40,{prompts5h:a,resetAt:c}=await ra();e&&t({prompts5h:a,limit5h:i,resetAt:c,tier:s})}catch{}});let r=setTimeout(()=>{n()},5e3),o=setInterval(()=>{n()},6e4);return()=>{e=!1,clearTimeout(r),clearInterval(o)}}var ro=null;function ia(){if(ro)try{ro()}catch{}}function oo(t){ro=t}var Ut=require("fs"),Ft=S(require("path")),so=S(require("os"));var aa=300*60*1e3,la={coding_plan:6e3};function Rd(){let t=Ft.default.join(so.default.homedir(),".jerico","settings.json");try{let{statSync:e,readFileSync:n}=require("fs");if(!e(t,{throwIfNoEntry:!1}))return"default";let o=JSON.parse(n(t,"utf-8")).qwenPlan;if(typeof o=="string"&&o in la)return o}catch{}return"default"}var ca="qwen:";async function Nd(){let t=Ft.default.join(so.default.homedir(),".qwen","projects"),n=Date.now()-aa,r=1/0,o=0,s=0,i=0,a=0,c=new Set;try{let d=await Ut.promises.readdir(t,{withFileTypes:!0});for(let u of d){if(!u.isDirectory())continue;let p=Ft.default.join(t,u.name,"chats"),f;try{f=(await Ut.promises.readdir(p,{withFileTypes:!0})).filter(g=>g.isFile()&&g.name.endsWith(".jsonl")).map(g=>g.name)}catch{continue}for(let h of f){let g=Ft.default.join(p,h),w=await ae(g);if(!w)continue;await Se();let E=ca+g;c.add(E);let O=V.get(E,w);if(O!==void 0){for(let y of O.events)y.epoch>=n&&(o++,s+=y.totalTokenCount,y.epoch<r&&(r=y.epoch)),y.epoch>a&&(a=y.epoch,typeof y.contextWindowSize=="number"&&y.contextWindowSize>0&&(i=Math.round(y.totalTokenCount/y.contextWindowSize*100)));continue}let T;try{if(w.size>20*1024*1024){let b=Math.max(0,w.size-10485760),m=await Ut.promises.open(g,"r");try{let k=Buffer.alloc(w.size-b);await m.read(k,0,k.length,b);let _=k.toString("utf-8"),I=_.indexOf(`
@@ -425,7 +425,7 @@ ${Di("bridge_get_my_task","bridge_complete_task","bridge_fail_task","bridge_get_
425
425
  `,{encoding:"utf-8",mode:384}))}catch{}}if(t.agentKey==="gemini"){let N=c?.cwd;if(N){let M=C.default.join(N,".gemini","settings.json");try{let K=R.default.readFileSync(M,"utf-8"),D=JSON.parse(K);D?.mcpServers?.bridge&&(delete D.mcpServers.bridge,R.default.writeFileSync(M,JSON.stringify(D,null,2)+`
426
426
  `,{encoding:"utf-8",mode:384}))}catch{}}}if(t.agentKey==="forge"){let N=c?.cwd;if(N){let M=C.default.join(N,".mcp.json");try{let K=R.default.readFileSync(M,"utf-8"),D=JSON.parse(K);D?.mcpServers?.bridge&&(delete D.mcpServers.bridge,R.default.writeFileSync(M,JSON.stringify(D,null,2)+`
427
427
  `,{encoding:"utf-8",mode:384}))}catch{}}}if(t.agentKey==="qwen"){let N=c?.cwd;if(N){let K=C.default.resolve(N)===C.default.resolve(L.default.homedir())?C.default.join(L.default.homedir(),".qwen"):C.default.join(N,".qwen"),D=C.default.join(K,"settings.json");try{let G=R.default.readFileSync(D,"utf-8"),z=JSON.parse(G);z?.mcpServers?.bridge&&(delete z.mcpServers.bridge,R.default.writeFileSync(D,JSON.stringify(z,null,2)+`
428
- `,{encoding:"utf-8",mode:384}))}catch{}}}},c)){if(t.agentKey==="gemini"&&setTimeout(()=>{if(!gt.get(t.agentId)){gt.set(t.agentId,!0);let m=Ye.get(t.agentId)??[];Ye.delete(t.agentId),m.length>0&&(console.warn("[daemon] gemini.ready.timeout_fallback",{agentId:t.agentId.slice(-8),flushing:m.length}),setTimeout(()=>{for(let k of m)n.write(t.agentId,k,"orchestrator");setTimeout(()=>{n.write(t.agentId,Buffer.from("\r").toString("base64"),"orchestrator")},1e3)},500))}},3e4),u==="fallback_home"&&e.readyState===A.OPEN){let m=t.daemonLocalPath?"daemon_override_missing":"not_found";console.warn("[daemon] cwd_fallback",{agentId:t.agentId,requestedCwd:t.cwd,actualCwd:L.default.homedir(),reason:m,projectId:t.projectId,daemonId:t.daemonId}),e.send(JSON.stringify({type:"cwd_fallback",agentId:t.agentId,requestedCwd:t.cwd,actualCwd:L.default.homedir(),source:"fallback_home",reason:m,projectId:t.projectId,daemonId:t.daemonId}))}e.readyState===A.OPEN&&e.send(JSON.stringify({type:"mcp_status",agentId:t.agentId,mcpConfigured:l,transport:l?d:void 0,projectId:c?.projectId,effectiveCwd:c?.cwd,cwdSource:u}))}else{let k=n.getLastError(t.agentId)?.includes("posix_spawnp failed")&&Zd(t.agentKey);e.readyState===A.OPEN&&(k?e.send(JSON.stringify({type:"error",code:"SPAWN_HELPER_BROKEN",message:"node-pty spawn-helper is not executable. Upgrade bridge-agent to v0.2.10+."})):e.send(JSON.stringify({type:"error",code:"SPAWN_FAILED",message:`Failed to spawn panel ${t.agentId}`})))}e.readyState===A.OPEN&&e.send(JSON.stringify({type:"agent_spawned",agentId:t.agentId,agentKey:t.agentKey,daemonId:t.daemonId,role:t.role,personaId:t.personaId}));break}case"input":{if(n.getAgentKey(t.agentId)==="gemini"&&t.source==="orchestrator"){if(!gt.get(t.agentId)){let a=Ye.get(t.agentId)??[];a.push(t.data),Ye.set(t.agentId,a),console.log("[daemon] gemini.input.buffered",{agentId:t.agentId.slice(-8),queued:a.length});break}if(Je.get(t.agentId)){let a=n.write(t.agentId,Buffer.from("\x1B").toString("base64"),"user");if(Je.set(t.agentId,!1),console.log("[daemon] gemini.shell_mode.esc_before_inject",{agentId:t.agentId.slice(-8)}),!a){e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}));break}setTimeout(()=>{!n.write(t.agentId,t.data,t.source)&&e.readyState===A.OPEN&&e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}))},100);break}}n.write(t.agentId,t.data,t.source)||e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}));break}case"kill":console.log("[daemon] kill.received",{agentId:t.agentId,force:t.force??!1}),ze.get(t.agentId)?.(),ze.delete(t.agentId),o.stop(t.agentId),n.kill(t.agentId,t.force),Bn.delete(t.agentId);break;case"resize":n.resize(t.agentId,t.cols,t.rows);break;case"sim_tap":case"sim_swipe":case"sim_key":case"sim_button":case"sim_get_source":case"sim_subscribe":case"sim_unsubscribe":case"sim_healthcheck":case"sim_install_run":case"sim_install_cancel":o.handle(t);break;case"detect_agents":Promise.all([dr(r.agentPaths),Fr()]).then(([s,i])=>{Kt=i?[...s,i]:s,e.readyState===A.OPEN&&e.send(JSON.stringify({type:"agents",list:Kt}))});break;case"dir_list":{let s=L.default.homedir(),i=(t.path||"~").replace(/^~/,s),a=C.default.resolve(i);if(a!==s&&!a.startsWith(s+C.default.sep)){e.readyState===A.OPEN&&e.send(JSON.stringify({type:"error",code:"INVALID_MSG",message:"Path outside home directory"}));return}try{let c=R.default.readdirSync(a,{withFileTypes:!0}).filter(l=>l.isDirectory()&&!l.name.startsWith(".")).map(l=>({name:l.name,path:C.default.join(a,l.name)})).sort((l,d)=>l.name.localeCompare(d.name));e.readyState===A.OPEN&&e.send(JSON.stringify({type:"dir_list_result",requestId:t.requestId,path:a,entries:c}))}catch(c){e.readyState===A.OPEN&&e.send(JSON.stringify({type:"dir_list_result",requestId:t.requestId,path:a,entries:[],error:c instanceof Error?c.message:"Cannot read directory"}))}break}case"persona_apply":{let s=n.getAgentKey(t.agentId);if(!s){console.warn("[daemon] persona_apply.no_panel",{agentId:t.agentId});break}let i;t.systemPrompt?i=`[BRIDGE-ORCH] Persona updated: ${t.personaId}
428
+ `,{encoding:"utf-8",mode:384}))}catch{}}}},c)){if(t.agentKey==="gemini"&&setTimeout(()=>{if(!gt.get(t.agentId)){gt.set(t.agentId,!0);let m=Ye.get(t.agentId)??[];Ye.delete(t.agentId),m.length>0&&(console.warn("[daemon] gemini.ready.timeout_fallback",{agentId:t.agentId.slice(-8),flushing:m.length}),setTimeout(()=>{for(let k of m)n.write(t.agentId,k,"orchestrator");setTimeout(()=>{n.write(t.agentId,Buffer.from("\r").toString("base64"),"orchestrator")},1e3)},500))}},3e4),u==="fallback_home"&&e.readyState===A.OPEN){let m=t.daemonLocalPath?"daemon_override_missing":"not_found";console.warn("[daemon] cwd_fallback",{agentId:t.agentId,requestedCwd:t.cwd,actualCwd:L.default.homedir(),reason:m,projectId:t.projectId,daemonId:t.daemonId}),e.send(JSON.stringify({type:"cwd_fallback",agentId:t.agentId,requestedCwd:t.cwd,actualCwd:L.default.homedir(),source:"fallback_home",reason:m,projectId:t.projectId,daemonId:t.daemonId}))}e.readyState===A.OPEN&&e.send(JSON.stringify({type:"mcp_status",agentId:t.agentId,mcpConfigured:l,transport:l?d:void 0,projectId:c?.projectId,effectiveCwd:c?.cwd,cwdSource:u}))}else{let k=n.getLastError(t.agentId)?.includes("posix_spawnp failed")&&Zd(t.agentKey);e.readyState===A.OPEN&&(k?e.send(JSON.stringify({type:"error",code:"SPAWN_HELPER_BROKEN",message:"node-pty spawn-helper is not executable. Upgrade bridge-agent to v0.2.10+."})):e.send(JSON.stringify({type:"error",code:"SPAWN_FAILED",message:`Failed to spawn panel ${t.agentId}`})))}e.readyState===A.OPEN&&e.send(JSON.stringify({type:"agent_spawned",agentId:t.agentId,agentKey:t.agentKey,daemonId:t.daemonId,role:t.role,personaId:t.personaId,projectId:t.projectId??c?.projectId,workspaceId:t.workspaceId??c?.workspaceId,cwd:t.cwd??c?.cwd}));break}case"input":{if(n.getAgentKey(t.agentId)==="gemini"&&t.source==="orchestrator"){if(!gt.get(t.agentId)){let a=Ye.get(t.agentId)??[];a.push(t.data),Ye.set(t.agentId,a),console.log("[daemon] gemini.input.buffered",{agentId:t.agentId.slice(-8),queued:a.length});break}if(Je.get(t.agentId)){let a=n.write(t.agentId,Buffer.from("\x1B").toString("base64"),"user");if(Je.set(t.agentId,!1),console.log("[daemon] gemini.shell_mode.esc_before_inject",{agentId:t.agentId.slice(-8)}),!a){e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}));break}setTimeout(()=>{!n.write(t.agentId,t.data,t.source)&&e.readyState===A.OPEN&&e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}))},100);break}}n.write(t.agentId,t.data,t.source)||e.send(JSON.stringify({type:"pty_dead",agentId:t.agentId}));break}case"kill":console.log("[daemon] kill.received",{agentId:t.agentId,force:t.force??!1}),ze.get(t.agentId)?.(),ze.delete(t.agentId),o.stop(t.agentId),n.kill(t.agentId,t.force),Bn.delete(t.agentId);break;case"resize":n.resize(t.agentId,t.cols,t.rows);break;case"sim_tap":case"sim_swipe":case"sim_key":case"sim_button":case"sim_get_source":case"sim_subscribe":case"sim_unsubscribe":case"sim_healthcheck":case"sim_install_run":case"sim_install_cancel":o.handle(t);break;case"detect_agents":Promise.all([dr(r.agentPaths),Fr()]).then(([s,i])=>{Kt=i?[...s,i]:s,e.readyState===A.OPEN&&e.send(JSON.stringify({type:"agents",list:Kt}))});break;case"dir_list":{let s=L.default.homedir(),i=(t.path||"~").replace(/^~/,s),a=C.default.resolve(i);if(a!==s&&!a.startsWith(s+C.default.sep)){e.readyState===A.OPEN&&e.send(JSON.stringify({type:"error",code:"INVALID_MSG",message:"Path outside home directory"}));return}try{let c=R.default.readdirSync(a,{withFileTypes:!0}).filter(l=>l.isDirectory()&&!l.name.startsWith(".")).map(l=>({name:l.name,path:C.default.join(a,l.name)})).sort((l,d)=>l.name.localeCompare(d.name));e.readyState===A.OPEN&&e.send(JSON.stringify({type:"dir_list_result",requestId:t.requestId,path:a,entries:c}))}catch(c){e.readyState===A.OPEN&&e.send(JSON.stringify({type:"dir_list_result",requestId:t.requestId,path:a,entries:[],error:c instanceof Error?c.message:"Cannot read directory"}))}break}case"persona_apply":{let s=n.getAgentKey(t.agentId);if(!s){console.warn("[daemon] persona_apply.no_panel",{agentId:t.agentId});break}let i;t.systemPrompt?i=`[BRIDGE-ORCH] Persona updated: ${t.personaId}
429
429
  ${t.systemPrompt}
430
430
  `:i=`[BRIDGE-ORCH] Persona assigned: ${t.personaId}
431
431
  Call bridge_get_persona({ id: "${t.personaId}" }) immediately for your authoritative operating instructions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bridge-agent",
3
- "version": "0.13.8",
3
+ "version": "0.13.9",
4
4
  "description": "Bridge local agent — connects your AI tools to Jerico",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",