vibelet 0.1.10 → 0.1.12

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.
package/bin/vibelet.mjs CHANGED
@@ -587,17 +587,19 @@ async function main() {
587
587
 
588
588
  if (command === 'stop') {
589
589
  process.stdout.write('Stopping vibelet daemon...\n');
590
+ // Always try graceful HTTP shutdown first — gives the daemon time to
591
+ // close sessions and flush logs before the service manager kills it.
592
+ await requestShutdown();
590
593
  if (backend.handlesProcessLifecycle) {
591
- // macOS launchd / Linux systemd: the service manager owns the process.
592
- // bootout/stop kills the process and unregisters the service in one step.
594
+ // macOS launchd / Linux systemd: unregister the service.
593
595
  backend.stop();
594
596
  } else {
595
- // Detached process: gracefully shut down via HTTP, then clean up PID file.
596
- await requestShutdown();
597
+ // Detached process: clean up PID file.
597
598
  backend.stop();
598
599
  }
599
- // Verify daemon is actually gone
600
- const stillAlive = await probeHealth(1_500);
600
+ // Verify daemon is actually gone (daemon's own shutdown timeout is 3s,
601
+ // plus a small margin for process teardown).
602
+ const stillAlive = await probeHealth(5_000);
601
603
  if (stillAlive) {
602
604
  fail('Daemon did not stop in time.');
603
605
  }
@@ -645,12 +647,8 @@ async function main() {
645
647
 
646
648
  if (command === 'restart') {
647
649
  process.stdout.write('Restarting vibelet daemon...\n');
648
- if (backend.handlesProcessLifecycle) {
649
- backend.stop();
650
- } else {
651
- await requestShutdown();
652
- backend.stop();
653
- }
650
+ await requestShutdown();
651
+ backend.stop();
654
652
  // Wait for daemon to actually stop
655
653
  const stillAlive = await probeHealth(5_000);
656
654
  if (stillAlive) {
package/dist/index.cjs CHANGED
@@ -83,7 +83,7 @@ process.stdin.resume();
83
83
  `)}function Lh(t){return Array.isArray(t)?t.map(e=>!e||typeof e!="object"?"":typeof e.text=="string"?e.text:typeof e.content=="string"?e.content:"").filter(Boolean).join(`
84
84
  `):""}function Mh(t){return Array.isArray(t)&&t.length>0&&t.every(e=>e&&typeof e=="object"&&e.type==="tool_reference")}function Nh(t){if(typeof t=="string")return t;let e=Lh(t);return e||(Mh(t)?"":JSON.stringify(t))}function Oh(t){return/requested permissions|haven't granted/i.test(t)}function Kl(t){return t.replace(Ph,"").replace(/\s+/g," ").trim()}function Bh(t){let e=t.toLowerCase();return e==="error"||e==="failed"||e==="unknown error"}function Dh(t){return/\brate limit\b/i.test(t)||/\busage limit\b/i.test(t)||/\bquota\b/i.test(t)||/\btoo many requests\b/i.test(t)||/\bcredit balance\b/i.test(t)||/\bcredits? remaining\b/i.test(t)||/\bmax(?:imum)? usage\b/i.test(t)}function Hh(t){return t.toLowerCase().startsWith("claude ")?t:`Claude usage limit reached. ${t}`}function Xl(t){let e=Kl(t.resultText??""),n=(t.stderrLines??[]).map(Kl).filter(Boolean).slice(-3),r=[e,...n].find(i=>!!i&&Dh(i));if(r)return Hh(r);let s=[e,...n].find(i=>!!i&&!Bh(i));return s?t.exitCode!=null&&s!==e?`Claude exited with code ${t.exitCode}: ${s}`:s:t.exitCode!=null?`Claude exited with code ${t.exitCode}`:"Claude returned an error result."}function Kn(t){return t.startsWith(ec)}var tn=class{proc=null;handler=null;sessionId="";buffer="";cwd="";approvalMode;sawFinalResult=!1;interrupted=!1;exitHandler=null;lastStderr=[];pendingPermissionDescriptions=new Map;emittedToolCallIds=new Set;replayPhase=!1;hookPort=null;hookSecret=null;hookFiles=null;buildClaudeEnv(){let e=v.buildSanitizedEnv();for(let n of Object.keys(e))n.startsWith("CMUX_")&&delete e[n];return e}async start(e,n,r){return this.cwd=e,this.approvalMode=r,n&&(this.sessionId=n),this.sessionId||(this.sessionId=`pending_${Date.now()}`),ee.info({sessionId:this.sessionId,cwd:e},"session initialized"),_.emit("driver.spawn",{agent:"claude",sessionId:this.sessionId,cwd:e}),this.sessionId}configureHookBridge(e,n){this.hookPort=e,this.hookSecret=n}sendPrompt(e){let n=["-p",e,"--output-format","stream-json","--verbose","--include-partial-messages"];this.sessionId&&!this.sessionId.startsWith("pending_")&&n.push("--resume",this.sessionId),Jn(this.hookFiles),this.hookFiles=null,this.approvalMode!=="acceptEdits"&&this.approvalMode!=="autoApprove"&&this.hookPort&&this.hookSecret&&(this.hookFiles=Jl(this.hookPort,this.hookSecret),n.push("--settings",this.hookFiles.settingsPath)),this.approvalMode==="acceptEdits"&&n.push("--permission-mode","acceptEdits"),this.approvalMode==="autoApprove"&&n.push("--dangerously-skip-permissions");let r=this.sessionId.startsWith("pending_")?"(new)":`(resume ${this.sessionId.slice(0,8)})`;ee.info({sessionId:this.sessionId,label:r,promptPreview:e.slice(0,50)},"running claude"),Ns(`New message: ${e.slice(0,60)}`),this.sawFinalResult=!1,this.interrupted=!1,this.lastStderr=[],this.pendingPermissionDescriptions.clear(),this.emittedToolCallIds.clear(),this.replayPhase=!0,this.proc=(0,Ql.spawn)(v.claudePath,n,{cwd:this.cwd||void 0,stdio:["ignore","pipe","pipe"],env:this.buildClaudeEnv()}),this.proc.on("error",s=>{let i=s.message;s.code==="ENOENT"&&this.cwd&&!(0,Zl.existsSync)(this.cwd)&&(i=`Working directory does not exist: ${this.cwd}`),ee.error({sessionId:this.sessionId,error:i,cwd:this.cwd},"spawn error"),_.emit("driver.error",{agent:"claude",sessionId:this.sessionId,error:i}),this.handler?.({type:"error",sessionId:this.sessionId,message:i})}),this.buffer="",this.proc.stdout.on("data",s=>{this.buffer+=s.toString();let i=this.buffer.split(`
85
85
  `);this.buffer=i.pop();for(let o of i)if(o.trim())try{this.handleRaw(JSON.parse(o))}catch{ee.warn({sessionId:this.sessionId,linePreview:o.slice(0,100)},"failed to parse stdout line")}}),this.proc.stderr.on("data",s=>{let i=s.toString().trim();i&&(ee.debug({sessionId:this.sessionId,stderr:i},"stderr"),this.lastStderr.push(i),this.lastStderr.length>10&&this.lastStderr.shift())}),this.proc.on("exit",(s,i)=>{ee.info({sessionId:this.sessionId,exitCode:s,signal:i},"process exited");let o=this.interrupted;this.proc=null,Jn(this.hookFiles),this.hookFiles=null,this.interrupted=!1,o&&!this.sawFinalResult?this.handler?.({type:"session.interrupted",sessionId:this.sessionId}):s&&s!==0&&!this.sawFinalResult&&(ee.error({sessionId:this.sessionId,exitCode:s,lastStderr:this.lastStderr.slice(-3)},"abnormal exit"),this.handler?.({type:"error",sessionId:this.sessionId,message:Xl({stderrLines:this.lastStderr,exitCode:s})})),this.exitHandler?.(s)})}respondApproval(e,n){if(ee.info({sessionId:this.sessionId,requestId:e,approved:n},"approval response"),!this.proc?.stdin?.writable)return ee.error({sessionId:this.sessionId},"cannot send approval: stdin not writable"),!1;let r=JSON.stringify({type:"control_response",request_id:e,permission_granted:n});return this.proc.stdin.write(r+`
86
- `),!0}setApprovalMode(e){this.approvalMode=e,ee.info({sessionId:this.sessionId,approvalMode:e},"approval mode updated")}interrupt(){this.proc&&!this.proc.killed&&(this.interrupted=!0,this.proc.kill("SIGTERM"),ee.info({sessionId:this.sessionId},"interrupted"))}stop(){if(!this.proc)return;this.proc.kill("SIGTERM");let e=this.proc;setTimeout(()=>{e.killed||e.kill("SIGKILL")},5e3).unref(),this.proc=null,Jn(this.hookFiles),this.hookFiles=null}onMessage(e){this.handler=e}onExit(e){this.exitHandler=e}handleRaw(e){let n=e.type;if(n==="system"&&e.subtype==="init"){let r=e.session_id??"";r&&r!==this.sessionId&&(ee.info({oldSessionId:this.sessionId,newSessionId:r},"session ID resolved"),_.emit("driver.init",{agent:"claude",sessionId:r}),this.sessionId=r);return}if(this.handler)switch(n){case"assistant":{if(this.replayPhase)break;let r=e.message?.content;if(!Array.isArray(r))break;for(let s of r)s.type==="tool_use"&&!this.emittedToolCallIds.has(s.id)&&(this.emittedToolCallIds.add(s.id),this.handler({type:"tool.call",sessionId:this.sessionId,toolName:s.name,input:s.input??{},toolCallId:s.id}));break}case"user":{if(this.replayPhase)break;let r=e.message?.content;if(!Array.isArray(r))break;for(let s of r)if(s.type==="tool_result"){let i=Nh(s.content);if(!i)continue;if(s.is_error===!0&&typeof s.tool_use_id=="string"&&Oh(i)){this.pendingPermissionDescriptions.set(s.tool_use_id,i);continue}this.handler({type:"tool.result",sessionId:this.sessionId,toolCallId:s.tool_use_id,output:i})}break}case"control_request":{this.replayPhase=!1;let r=e.request;r?.subtype==="can_use_tool"&&(_.emit("approval.request",{agent:"claude",sessionId:this.sessionId,toolName:r.tool_name}),this.handler({type:"approval.request",sessionId:this.sessionId,requestId:e.request_id,toolName:r.tool_name??"unknown",input:r.input??{},description:r.description??r.title??""}));break}case"stream_event":{this.replayPhase=!1;let r=e.event;r?.type==="content_block_delta"&&r?.delta?.type==="text_delta"&&r?.delta?.text&&this.handler({type:"text.delta",sessionId:this.sessionId,content:r.delta.text});break}case"result":{this.replayPhase=!1,this.sawFinalResult=!0;let r=typeof e.result=="string"?e.result:"";if(e.is_error){Ns("Claude failed."),this.handler({type:"error",sessionId:this.sessionId,message:Xl({resultText:r,stderrLines:this.lastStderr})});break}let s=Array.isArray(e.permission_denials)?e.permission_denials:[];if(s.length>0){let a=s[0]??{},l=typeof a.tool_use_id=="string"?a.tool_use_id:`missing_${Date.now()}`,c=typeof a.tool_name=="string"?a.tool_name:"unknown",u=a.tool_input&&typeof a.tool_input=="object"?a.tool_input:{},d=this.pendingPermissionDescriptions.get(l)??`Claude requested permissions to use ${c}.`;_.emit("approval.request",{agent:"claude",sessionId:this.sessionId,toolName:c}),this.handler({type:"approval.request",sessionId:this.sessionId,requestId:`${ec}${l}`,toolName:c,input:u,description:d})}this.pendingPermissionDescriptions.clear();let i=e.total_cost_usd,o=e.usage?{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens}:void 0;Ns("Claude finished. Run `claude --continue` to continue on desktop."),_.emit("session.done",{agent:"claude",sessionId:this.sessionId,cost:i,usage:o}),this.handler({type:"session.done",sessionId:this.sessionId,cost:i,usage:o});break}}}};var sc=require("child_process"),ic=require("fs");var Os=class{counters=new Map;timers=new Map;gauges=new Map;startTime=Date.now();logInterval=null;increment(e,n={}){this.counters.has(e)||this.counters.set(e,[]);let r=this.counters.get(e),s=JSON.stringify(n),i=r.find(o=>JSON.stringify(o.labels)===s);i?i.value++:r.push({value:1,labels:n})}gauge(e,n){this.gauges.set(e,n)}startTimer(e){let n=performance.now();return()=>{let r=Math.round(performance.now()-n),s=this.timers.get(e)??{count:0,totalMs:0,minMs:1/0,maxMs:0,lastMs:0};return s.count++,s.totalMs+=r,s.minMs=Math.min(s.minMs,r),s.maxMs=Math.max(s.maxMs,r),s.lastMs=r,this.timers.set(e,s),r}}snapshot(){let e={};for(let[s,i]of this.counters)e[s]=i.map(o=>({...o}));let n={};for(let[s,i]of this.timers)n[s]={...i,minMs:i.minMs===1/0?0:i.minMs};let r={};for(let[s,i]of this.gauges)r[s]=i;return{uptimeMs:Date.now()-this.startTime,counters:e,timers:n,gauges:r}}startPeriodicLog(e=6e4){this.logInterval||(this.logInterval=setInterval(()=>{let n=this.snapshot();R.info({metrics:n},"periodic metrics snapshot")},e),this.logInterval.unref())}stopPeriodicLog(){this.logInterval&&(clearInterval(this.logInterval),this.logInterval=null)}},w=new Os;var tc=require("node:fs"),Bs=require("node:path"),Fh="@vibelet/cli";function Uh(t){try{let e=JSON.parse((0,tc.readFileSync)(t,"utf8"));if(e.name===Fh&&typeof e.version=="string"&&e.version.length>0)return e.version}catch{}return null}function qh(){return"0.1.10"}var ft=qh();var x=R.child({module:"codex"});function jh(t){switch(t.kind){case"request-user-input-approval":return{provider:"codex",kind:t.kind,rpcId:t.rpcId,questionId:t.questionId,approveLabel:t.approveLabel,denyLabel:t.denyLabel};default:return{provider:"codex",kind:t.kind,rpcId:t.rpcId}}}function Wh(t){let e=t.approvalContext;if(!e||e.provider!=="codex")return null;switch(e.kind){case"command-execution":return{kind:e.kind,responseKind:"v2",rpcId:e.rpcId,toolName:t.toolName,input:t.input};case"file-change":return{kind:e.kind,responseKind:"v2",rpcId:e.rpcId,toolName:t.toolName,input:t.input};case"request-user-input-approval":return!e.questionId||!e.approveLabel||!e.denyLabel?null:{kind:e.kind,rpcId:e.rpcId,questionId:e.questionId,approveLabel:e.approveLabel,denyLabel:e.denyLabel,toolName:t.toolName,input:t.input};case"exec-command-legacy":return{kind:e.kind,rpcId:e.rpcId,toolName:t.toolName,input:t.input};case"apply-patch-legacy":return{kind:e.kind,rpcId:e.rpcId,toolName:t.toolName,input:t.input};default:return null}}function $(t){return!t||typeof t!="object"||Array.isArray(t)?null:t}function k(t){return typeof t=="string"&&t.trim().length>0?t.trim():null}var Gh=new Set(["aborted","interrupted","cancelled","canceled"]);function $h(t){let e=k(t);return e?e.toLowerCase():null}function zh(t){let e=k(t);return e?e.replace(/[^a-z0-9]/gi,"").toLowerCase():null}function Ds(t){return t?k(t.itemId)??k(t.id)??k(t.callId)??k(t.call_id):null}function Hs(t,e){let n={};for(let[r,s]of Object.entries(t))e.includes(r)||(n[r]=s);return n}function oc(t){return/\bapprove\b|\ballow\b|\baccept\b|\byes\b|\bcontinue\b|\bproceed\b|\brun\b|\bapply\b/i.test(t)}function ac(t){return/\bdeny\b|\breject\b|\bdecline\b|\bno\b|\bcancel\b|\babort\b|\bstop\b/i.test(t)}function Vh(t){if(!Array.isArray(t))return null;for(let e of t){let n=$(e);if(!n)continue;let r=k(n.id),s=Array.isArray(n.options)?n.options.map(l=>$(l)).filter(l=>!!l):[];if(!r||s.length===0)continue;let i=s.map(l=>k(l.label)).filter(l=>!!l);if(i.length<2)continue;let o=i.find(l=>oc(l))??i[0],a=i.find(l=>ac(l))??i[i.length-1];if(!(!o||!a||o===a))return{questionId:r,approveLabel:o,denyLabel:a}}return null}function Yh(t){if(!Array.isArray(t)||t.length===0)return!1;let e=t.map(s=>$(s)).filter(s=>!!s).flatMap(s=>(Array.isArray(s.options)?s.options:[]).map(o=>$(o)).filter(o=>!!o).map(o=>k(o.label)).filter(o=>!!o)),n=e.some(s=>oc(s)),r=e.some(s=>ac(s));return n&&r}function nc(t){let e=zh(t.type??t.itemType);if(e==="commandexecution")return{toolName:"Bash",input:Hs(t,["id","itemId","type","itemType","stdout","stderr","exitCode","exit_code","status","success","error"])};if(e==="filechange")return{toolName:"Patch",input:Hs(t,["id","itemId","type","itemType","stdout","stderr","exitCode","exit_code","status","success","error"])};if(e==="mcptoolcall"){let n=k(t.server),r=k(t.tool)??k(t.name);return r?{toolName:n?`mcp__${n}__${r}`:r,input:$(t.arguments)??$(t.input)??{}}:null}return null}function Jh(t){if(!Array.isArray(t))return"";for(let e of t){let n=$(e);if(!n)continue;let r=k(n.question)??k(n.header);if(r)return r}return""}function rc(t,e){return t==="autoApprove"?{approvalPolicy:"never",sandbox:"danger-full-access",sandboxPolicy:{type:"dangerFullAccess"}}:{approvalPolicy:"on-request",sandbox:"workspace-write",sandboxPolicy:{type:"workspaceWrite",writableRoots:[e],readOnlyAccess:{type:"fullAccess"},networkAccess:!0,excludeTmpdirEnvVar:!1,excludeSlashTmp:!1}}}var Xn=class{proc=null;handler=null;exitHandler=null;buffer="";rpcId=0;pending=new Map;threadId="";lastStderr=[];approvalRequests=new Map;toolContextByCallId=new Map;approvalMode;cwd="";async start(e,n,r){this.approvalMode=r,this.cwd=e,this.approvalRequests.clear(),this.toolContextByCallId.clear();let s=v.codexPath,i,o=this.buildSpawnArgs();if(v.isTransientPath(s)){let c=v.execViaLoginShell("codex",o);i=c.command,o=c.args,x.info({spawnCmd:i,argsPreview:o.slice(0,2)},"spawning via login shell")}else i=s,x.info({spawnCmd:i,args:o},"spawning");_.emit("driver.spawn",{agent:"codex",cwd:e,resumeSessionId:n}),this.lastStderr=[],this.proc=(0,sc.spawn)(i,o,{cwd:e||void 0,stdio:["pipe","pipe","pipe"],env:v.buildSanitizedEnv()}),this.proc.on("error",c=>{let u=c.message;c.code==="ENOENT"&&e&&!(0,ic.existsSync)(e)&&(u=`Working directory does not exist: ${e}`),x.error({error:u,cwd:e},"spawn error"),_.emit("driver.error",{agent:"codex",error:u})}),this.proc.stdout.on("data",c=>{this.buffer+=c.toString();let u=this.buffer.split(`
86
+ `),!0}setApprovalMode(e){this.approvalMode=e,ee.info({sessionId:this.sessionId,approvalMode:e},"approval mode updated")}interrupt(){this.proc&&!this.proc.killed&&(this.interrupted=!0,this.proc.kill("SIGTERM"),ee.info({sessionId:this.sessionId},"interrupted"))}stop(){if(!this.proc)return;this.proc.kill("SIGTERM");let e=this.proc;setTimeout(()=>{e.killed||e.kill("SIGKILL")},5e3).unref(),this.proc=null,Jn(this.hookFiles),this.hookFiles=null}onMessage(e){this.handler=e}onExit(e){this.exitHandler=e}handleRaw(e){let n=e.type;if(n==="system"&&e.subtype==="init"){let r=e.session_id??"";r&&r!==this.sessionId&&(ee.info({oldSessionId:this.sessionId,newSessionId:r},"session ID resolved"),_.emit("driver.init",{agent:"claude",sessionId:r}),this.sessionId=r);return}if(this.handler)switch(n){case"assistant":{if(this.replayPhase)break;let r=e.message?.content;if(!Array.isArray(r))break;for(let s of r)s.type==="tool_use"&&!this.emittedToolCallIds.has(s.id)&&(this.emittedToolCallIds.add(s.id),this.handler({type:"tool.call",sessionId:this.sessionId,toolName:s.name,input:s.input??{},toolCallId:s.id}));break}case"user":{if(this.replayPhase)break;let r=e.message?.content;if(!Array.isArray(r))break;for(let s of r)if(s.type==="tool_result"){let i=Nh(s.content);if(!i)continue;if(s.is_error===!0&&typeof s.tool_use_id=="string"&&Oh(i)){this.pendingPermissionDescriptions.set(s.tool_use_id,i);continue}this.handler({type:"tool.result",sessionId:this.sessionId,toolCallId:s.tool_use_id,output:i})}break}case"control_request":{this.replayPhase=!1;let r=e.request;r?.subtype==="can_use_tool"&&(_.emit("approval.request",{agent:"claude",sessionId:this.sessionId,toolName:r.tool_name}),this.handler({type:"approval.request",sessionId:this.sessionId,requestId:e.request_id,toolName:r.tool_name??"unknown",input:r.input??{},description:r.description??r.title??""}));break}case"stream_event":{this.replayPhase=!1;let r=e.event;r?.type==="content_block_delta"&&r?.delta?.type==="text_delta"&&r?.delta?.text&&this.handler({type:"text.delta",sessionId:this.sessionId,content:r.delta.text});break}case"result":{this.replayPhase=!1,this.sawFinalResult=!0;let r=typeof e.result=="string"?e.result:"";if(e.is_error){Ns("Claude failed."),this.handler({type:"error",sessionId:this.sessionId,message:Xl({resultText:r,stderrLines:this.lastStderr})});break}let s=Array.isArray(e.permission_denials)?e.permission_denials:[];if(s.length>0){let a=s[0]??{},l=typeof a.tool_use_id=="string"?a.tool_use_id:`missing_${Date.now()}`,c=typeof a.tool_name=="string"?a.tool_name:"unknown",u=a.tool_input&&typeof a.tool_input=="object"?a.tool_input:{},d=this.pendingPermissionDescriptions.get(l)??`Claude requested permissions to use ${c}.`;_.emit("approval.request",{agent:"claude",sessionId:this.sessionId,toolName:c}),this.handler({type:"approval.request",sessionId:this.sessionId,requestId:`${ec}${l}`,toolName:c,input:u,description:d})}this.pendingPermissionDescriptions.clear();let i=e.total_cost_usd,o=e.usage?{inputTokens:e.usage.input_tokens,outputTokens:e.usage.output_tokens}:void 0;Ns("Claude finished. Run `claude --continue` to continue on desktop."),_.emit("session.done",{agent:"claude",sessionId:this.sessionId,cost:i,usage:o}),this.handler({type:"session.done",sessionId:this.sessionId,cost:i,usage:o});break}}}};var sc=require("child_process"),ic=require("fs");var Os=class{counters=new Map;timers=new Map;gauges=new Map;startTime=Date.now();logInterval=null;increment(e,n={}){this.counters.has(e)||this.counters.set(e,[]);let r=this.counters.get(e),s=JSON.stringify(n),i=r.find(o=>JSON.stringify(o.labels)===s);i?i.value++:r.push({value:1,labels:n})}gauge(e,n){this.gauges.set(e,n)}startTimer(e){let n=performance.now();return()=>{let r=Math.round(performance.now()-n),s=this.timers.get(e)??{count:0,totalMs:0,minMs:1/0,maxMs:0,lastMs:0};return s.count++,s.totalMs+=r,s.minMs=Math.min(s.minMs,r),s.maxMs=Math.max(s.maxMs,r),s.lastMs=r,this.timers.set(e,s),r}}snapshot(){let e={};for(let[s,i]of this.counters)e[s]=i.map(o=>({...o}));let n={};for(let[s,i]of this.timers)n[s]={...i,minMs:i.minMs===1/0?0:i.minMs};let r={};for(let[s,i]of this.gauges)r[s]=i;return{uptimeMs:Date.now()-this.startTime,counters:e,timers:n,gauges:r}}startPeriodicLog(e=6e4){this.logInterval||(this.logInterval=setInterval(()=>{let n=this.snapshot();R.info({metrics:n},"periodic metrics snapshot")},e),this.logInterval.unref())}stopPeriodicLog(){this.logInterval&&(clearInterval(this.logInterval),this.logInterval=null)}},w=new Os;var tc=require("node:fs"),Bs=require("node:path"),Fh="@vibelet/cli";function Uh(t){try{let e=JSON.parse((0,tc.readFileSync)(t,"utf8"));if(e.name===Fh&&typeof e.version=="string"&&e.version.length>0)return e.version}catch{}return null}function qh(){return"0.1.12"}var ft=qh();var x=R.child({module:"codex"});function jh(t){switch(t.kind){case"request-user-input-approval":return{provider:"codex",kind:t.kind,rpcId:t.rpcId,questionId:t.questionId,approveLabel:t.approveLabel,denyLabel:t.denyLabel};default:return{provider:"codex",kind:t.kind,rpcId:t.rpcId}}}function Wh(t){let e=t.approvalContext;if(!e||e.provider!=="codex")return null;switch(e.kind){case"command-execution":return{kind:e.kind,responseKind:"v2",rpcId:e.rpcId,toolName:t.toolName,input:t.input};case"file-change":return{kind:e.kind,responseKind:"v2",rpcId:e.rpcId,toolName:t.toolName,input:t.input};case"request-user-input-approval":return!e.questionId||!e.approveLabel||!e.denyLabel?null:{kind:e.kind,rpcId:e.rpcId,questionId:e.questionId,approveLabel:e.approveLabel,denyLabel:e.denyLabel,toolName:t.toolName,input:t.input};case"exec-command-legacy":return{kind:e.kind,rpcId:e.rpcId,toolName:t.toolName,input:t.input};case"apply-patch-legacy":return{kind:e.kind,rpcId:e.rpcId,toolName:t.toolName,input:t.input};default:return null}}function $(t){return!t||typeof t!="object"||Array.isArray(t)?null:t}function k(t){return typeof t=="string"&&t.trim().length>0?t.trim():null}var Gh=new Set(["aborted","interrupted","cancelled","canceled"]);function $h(t){let e=k(t);return e?e.toLowerCase():null}function zh(t){let e=k(t);return e?e.replace(/[^a-z0-9]/gi,"").toLowerCase():null}function Ds(t){return t?k(t.itemId)??k(t.id)??k(t.callId)??k(t.call_id):null}function Hs(t,e){let n={};for(let[r,s]of Object.entries(t))e.includes(r)||(n[r]=s);return n}function oc(t){return/\bapprove\b|\ballow\b|\baccept\b|\byes\b|\bcontinue\b|\bproceed\b|\brun\b|\bapply\b/i.test(t)}function ac(t){return/\bdeny\b|\breject\b|\bdecline\b|\bno\b|\bcancel\b|\babort\b|\bstop\b/i.test(t)}function Vh(t){if(!Array.isArray(t))return null;for(let e of t){let n=$(e);if(!n)continue;let r=k(n.id),s=Array.isArray(n.options)?n.options.map(l=>$(l)).filter(l=>!!l):[];if(!r||s.length===0)continue;let i=s.map(l=>k(l.label)).filter(l=>!!l);if(i.length<2)continue;let o=i.find(l=>oc(l))??i[0],a=i.find(l=>ac(l))??i[i.length-1];if(!(!o||!a||o===a))return{questionId:r,approveLabel:o,denyLabel:a}}return null}function Yh(t){if(!Array.isArray(t)||t.length===0)return!1;let e=t.map(s=>$(s)).filter(s=>!!s).flatMap(s=>(Array.isArray(s.options)?s.options:[]).map(o=>$(o)).filter(o=>!!o).map(o=>k(o.label)).filter(o=>!!o)),n=e.some(s=>oc(s)),r=e.some(s=>ac(s));return n&&r}function nc(t){let e=zh(t.type??t.itemType);if(e==="commandexecution")return{toolName:"Bash",input:Hs(t,["id","itemId","type","itemType","stdout","stderr","exitCode","exit_code","status","success","error"])};if(e==="filechange")return{toolName:"Patch",input:Hs(t,["id","itemId","type","itemType","stdout","stderr","exitCode","exit_code","status","success","error"])};if(e==="mcptoolcall"){let n=k(t.server),r=k(t.tool)??k(t.name);return r?{toolName:n?`mcp__${n}__${r}`:r,input:$(t.arguments)??$(t.input)??{}}:null}return null}function Jh(t){if(!Array.isArray(t))return"";for(let e of t){let n=$(e);if(!n)continue;let r=k(n.question)??k(n.header);if(r)return r}return""}function rc(t,e){return t==="autoApprove"?{approvalPolicy:"never",sandbox:"danger-full-access",sandboxPolicy:{type:"dangerFullAccess"}}:{approvalPolicy:"on-request",sandbox:"workspace-write",sandboxPolicy:{type:"workspaceWrite",writableRoots:[e],readOnlyAccess:{type:"fullAccess"},networkAccess:!0,excludeTmpdirEnvVar:!1,excludeSlashTmp:!1}}}var Xn=class{proc=null;handler=null;exitHandler=null;buffer="";rpcId=0;pending=new Map;threadId="";lastStderr=[];approvalRequests=new Map;toolContextByCallId=new Map;approvalMode;cwd="";async start(e,n,r){this.approvalMode=r,this.cwd=e,this.approvalRequests.clear(),this.toolContextByCallId.clear();let s=v.codexPath,i,o=this.buildSpawnArgs();if(v.isTransientPath(s)){let c=v.execViaLoginShell("codex",o);i=c.command,o=c.args,x.info({spawnCmd:i,argsPreview:o.slice(0,2)},"spawning via login shell")}else i=s,x.info({spawnCmd:i,args:o},"spawning");_.emit("driver.spawn",{agent:"codex",cwd:e,resumeSessionId:n}),this.lastStderr=[],this.proc=(0,sc.spawn)(i,o,{cwd:e||void 0,stdio:["pipe","pipe","pipe"],env:v.buildSanitizedEnv()}),this.proc.on("error",c=>{let u=c.message;c.code==="ENOENT"&&e&&!(0,ic.existsSync)(e)&&(u=`Working directory does not exist: ${e}`),x.error({error:u,cwd:e},"spawn error"),_.emit("driver.error",{agent:"codex",error:u})}),this.proc.stdout.on("data",c=>{this.buffer+=c.toString();let u=this.buffer.split(`
87
87
  `);this.buffer=u.pop();for(let d of u)if(d.trim())try{this.handleRaw(JSON.parse(d))}catch{x.warn({linePreview:d.slice(0,200)},"failed to parse stdout line")}}),this.proc.stderr.on("data",c=>{let u=c.toString().trim();u&&(x.debug({stderr:u},"stderr"),this.lastStderr.push(u),this.lastStderr.length>10&&this.lastStderr.shift())}),this.proc.on("exit",c=>{x.info({threadId:this.threadId,exitCode:c},"process exited"),c&&c!==0&&x.error({threadId:this.threadId,exitCode:c,lastStderr:this.lastStderr.slice(-3)},"abnormal exit"),this.proc=null,this.approvalRequests.clear(),this.toolContextByCallId.clear();for(let[,{reject:u}]of this.pending)u(new Error(`Codex process exited with code ${c}`));this.pending.clear(),this.exitHandler?.(c),c&&this.handler&&this.threadId&&this.handler({type:"error",sessionId:this.threadId,message:`Codex process exited with code ${c}`})});let a=w.startTimer("rpc.duration");await this.rpc("initialize",{clientInfo:{name:"@vibelet/cli",version:ft},capabilities:{experimentalApi:!0}}),a(),this.rpcNotify("initialized",{});let l=rc(this.approvalMode,e);if(n){let c=await this.rpc("thread/resume",{threadId:n,approvalPolicy:l.approvalPolicy,sandbox:l.sandbox,persistExtendedHistory:!0});this.threadId=c?.thread?.id??n,x.info({threadId:this.threadId},"thread resumed"),_.emit("driver.init",{agent:"codex",sessionId:this.threadId})}else{let c=await this.rpc("thread/start",{cwd:e,approvalPolicy:l.approvalPolicy,sandbox:l.sandbox,experimentalRawEvents:!0,persistExtendedHistory:!0});this.threadId=c?.thread?.id??c?.threadId??"",x.info({threadId:this.threadId},"thread created"),_.emit("driver.init",{agent:"codex",sessionId:this.threadId})}return this.threadId}buildSpawnArgs(){return["app-server","--listen","stdio://"]}sendPrompt(e){let n=rc(this.approvalMode,this.cwd||process.cwd());x.info({threadId:this.threadId,promptPreview:e.slice(0,50)},"turn/start"),this.rpc("turn/start",{threadId:this.threadId,input:[{type:"text",text:e}],approvalPolicy:n.approvalPolicy,sandboxPolicy:n.sandboxPolicy}).then(r=>x.debug({resultPreview:JSON.stringify(r).slice(0,200)},"turn/start result")).catch(r=>{x.error({threadId:this.threadId,error:r.message},"sendPrompt error"),this.handler?.({type:"error",sessionId:this.threadId,message:r.message})})}respondApproval(e,n){if(!this.proc?.stdin?.writable)return!1;let r=this.approvalRequests.get(e),s=r?.rpcId??Number(e);if(!Number.isFinite(s))return!1;let i;if(!r)i=n?{decision:"approve"}:{decision:"deny",reason:"User denied from Vibelet"};else{switch(r.kind){case"command-execution":case"file-change":i={decision:n?"accept":"decline"};break;case"request-user-input-approval":i={answers:{[r.questionId]:{answers:[n?r.approveLabel:r.denyLabel]}}};break;case"exec-command-legacy":case"apply-patch-legacy":i={decision:n?"approved":"denied"};break;default:i={decision:n?"accept":"decline"};break}this.approvalRequests.delete(e)}return x.info({threadId:this.threadId,rpcId:s,approved:n},"approval response"),this.proc.stdin.write(JSON.stringify({jsonrpc:"2.0",id:s,result:i})+`
88
88
  `),!0}restorePendingApproval(e){let n=Wh(e);n&&this.approvalRequests.set(e.requestId,n)}interrupt(){this.rpc("turn/interrupt",{threadId:this.threadId}).catch(()=>{})}setApprovalMode(e){this.approvalMode=e,x.info({approvalMode:e},"approval mode updated (takes effect on subsequent turns)")}stop(){if(!this.proc)return;this.proc.kill("SIGTERM");let e=this.proc;setTimeout(()=>{e.killed||e.kill("SIGKILL")},5e3).unref(),this.proc=null,this.approvalRequests.clear(),this.toolContextByCallId.clear();for(let[,{reject:n}]of this.pending)n(new Error("Process stopped"));this.pending.clear()}onMessage(e){this.handler=e}onExit(e){this.exitHandler=e}rpc(e,n){let r=++this.rpcId,s=w.startTimer("rpc.duration");return new Promise((i,o)=>{if(this.pending.set(r,{resolve:a=>{s(),i(a)},reject:a=>{s(),o(a)}}),!this.proc?.stdin?.writable){this.pending.delete(r),s(),o(new Error("Process not available"));return}this.proc.stdin.write(JSON.stringify({jsonrpc:"2.0",method:e,id:r,params:n})+`
89
89
  `),setTimeout(()=>{this.pending.has(r)&&(this.pending.delete(r),x.error({method:e,rpcId:r,threadId:this.threadId},"RPC timeout"),s(),o(new Error(`RPC timeout: ${e}`)))},3e4).unref()})}rpcNotify(e,n){this.proc?.stdin?.writable&&this.proc.stdin.write(JSON.stringify({jsonrpc:"2.0",method:e,params:n})+`
@@ -92,9 +92,9 @@ process.stdin.resume();
92
92
  `)){let n=Qn(e);if(n&&!eg(n)&&!tg(n))return n}}function eg(t){return Xh.some(e=>t.startsWith(e))}function tg(t){let e=t.replace(/^['"`]+/,"").replace(/['"`\\]+$/,"").trim();return!!(!e||/^(\/|~\/|\.\/|\.\.\/)/.test(e)||/^[A-Za-z]:\\/.test(e))}function ng(t){for(let e=0;e<t.length;e+=1){let n=t[e];if(n==="\u3002"||n==="\uFF01"||n==="\uFF1F"||n==="\uFF1B")return e+1;if(n==="."||n==="!"||n==="?"||n===";"){let r=t[e+1];if(!r||/\s/.test(r))return e+1}}return-1}function Fs(t,e=80){if(typeof t!="string")return;let n=Zh(t);if(!n)return;let r=ng(n),i=(r>0?n.slice(0,r):n).replace(/[。!?;.!?;]+$/gu,"").trim();if(!(!i||lc(i)))return i.length<=e?i:`${i.slice(0,Math.max(1,e-3)).trimEnd()}...`}function We(t,e){for(let n of t){let r=Qn(n);if(!(!r||pt(r)))return r}return Fs(e)}var dc=require("child_process"),ht=require("fs/promises"),Ee=require("path"),Us=require("os"),fc=require("util");var rg=(0,fc.promisify)(dc.execFile),sg=R.child({module:"process-scanner"}),cc=1500,ig=15e3,rn=null,nn=null;function er(){rn=null}function og(t){return t.replace(/^['"]|['"]$/g,"")}function ag(t){return(t.match(/"[^"]*"|'[^']*'|\S+/g)??[]).map(og)}function qs(t){let e=ag(t);for(let n=0;n<e.length;n+=1){let r=e[n],s=(0,Ee.basename)(r);if(s==="claude"||s==="codex")return{agent:s,args:e.slice(n+1)}}return null}function lg(t,e){let n=qs(e);if(!n||n.agent!==t)return null;let{args:r}=n;if(t==="claude"){for(let s=0;s<r.length;s+=1){let i=r[s];if((i==="--resume"||i==="--session-id")&&r[s+1]&&!r[s+1].startsWith("-"))return r[s+1];if(i.startsWith("--resume="))return i.slice(9);if(i.startsWith("--session-id="))return i.slice(13)}return null}if(r[0]!=="resume")return null;for(let s=1;s<r.length;s+=1){let i=r[s];if(!i.startsWith("-"))return i}return null}function Zn(t){switch(t){case"high":return 3;case"medium":return 2;default:return 1}}function cg(t,e){return t==="claude"?e.includes("/.claude/projects/")&&!e.includes("/subagents/"):e.includes("/.codex/sessions/")}function ug(t,e){let n=qs(e);return!n||n.agent!==t?!1:n.args.includes("--continue")||n.args.includes("-c")}function dg(t){let e=lg(t.agent,t.command);if(e)return{agent:t.agent,pid:t.pid,cwd:t.cwd,command:t.command,sessionId:e,confidence:"high"};let n=[...new Set(t.sessionFiles)].filter(s=>cg(t.agent,s));if(n.length!==1)return null;let r=gt(t.agent,n[0]);return r?{agent:t.agent,pid:t.pid,cwd:t.cwd,command:t.command,sessionId:r,confidence:"medium",sessionFilePath:n[0]}:null}function fg(t,e){let n=t,r=e;return(Zn(e.confidence)>Zn(t.confidence)||Zn(e.confidence)===Zn(t.confidence)&&e.pid<t.pid)&&(n=e,r=t),{...n,cwd:n.cwd||r.cwd,title:n.title??r.title,sessionFilePath:n.sessionFilePath??r.sessionFilePath}}function pg(t){let e=new Map;for(let n of t){let r=`${n.agent}:${n.sessionId}`,s=e.get(r);e.set(r,s?fg(s,n):n)}return[...e.values()]}async function js(t,e){try{let{stdout:n}=await rg(t,e,{maxBuffer:8388608,timeout:cc});return n}catch(n){return sg.warn({file:t,args:e,timeoutMs:cc,error:String(n)},"process scan command failed"),""}}async function uc(t){if(!t.sessionFilePath)return t;let e=await sn(t.sessionFilePath,t.agent);return e?{...t,cwd:t.cwd||e.cwd,title:t.title??e.title}:null}async function hg(t){return(await js("lsof",["-a","-p",String(t),"-d","cwd","-Fn"])).split(`
93
93
  `).find(r=>r.startsWith("n"))?.slice(1).trim()??""}async function gg(t){let n=(await js("lsof",["-p",String(t),"-Fn"])).split(`
94
94
  `).filter(r=>r.startsWith("n")).map(r=>r.slice(1).trim()).filter(r=>r.endsWith(".jsonl")?r.includes("/.claude/projects/")||r.includes("/.codex/sessions/"):!1);return[...new Set(n)]}async function mg(){return(await js("pgrep",["-fal","(^|/)(claude|codex)( |$)|claude app-server|codex app-server"])).split(`
95
- `).map(e=>e.trim()).filter(Boolean).map(e=>{let n=e.match(/^(\d+)\s+(.*)$/);if(!n)return null;let r=Number(n[1]),s=n[2],i=qs(s);return!Number.isFinite(r)||!i?null:{pid:r,command:s,agent:i.agent}}).filter(e=>!!e)}async function yg(){let t=await mg();return Promise.all(t.map(async e=>({pid:e.pid,agent:e.agent,command:e.command,cwd:await hg(e.pid),sessionFiles:await gg(e.pid)})))}function Sg(t){return t.replace(/[^a-zA-Z0-9]/g,"-")}async function vg(t,e){if(!e)return null;try{if(t==="claude"){let o=(0,Ee.join)((0,Us.homedir)(),".claude","projects",Sg(e)),l=(await(0,ht.readdir)(o).catch(()=>[])).filter(f=>f.endsWith(".jsonl"));if(l.length===0)return null;let c=null;if(await Promise.all(l.map(async f=>{let p=await(0,ht.stat)((0,Ee.join)(o,f)).catch(()=>null);p&&(!c||p.mtimeMs>c.mtimeMs)&&(c={name:f,mtimeMs:p.mtimeMs})})),!c)return null;let u=(0,Ee.join)(o,c.name),d=gt(t,u);return d?{sessionId:d,filePath:u}:null}let n=(0,Ee.join)((0,Us.homedir)(),".codex","sessions"),r=null;async function s(o){let a=await(0,ht.readdir)(o,{withFileTypes:!0}).catch(()=>[]);for(let l of a){let c=(0,Ee.join)(o,l.name);if(l.isDirectory())await s(c);else if(l.name.endsWith(".jsonl")){let u=await(0,ht.stat)(c).catch(()=>null);if(!u||r&&u.mtimeMs<=r.mtimeMs)continue;let d=await sn(c,t);if(!d||d.cwd!==e)continue;r={path:c,mtimeMs:u.mtimeMs,sessionId:d.sessionId}}}}await s(n);let i=r;return i?{sessionId:i.sessionId,filePath:i.path}:null}catch{return null}}async function _g(){let t=await yg(),e=await Promise.all(t.map(async r=>{let s=dg(r);if(s)return uc(s);if(ug(r.agent,r.command))return null;let i=await vg(r.agent,r.cwd);return i?uc({agent:r.agent,pid:r.pid,cwd:r.cwd,command:r.command,sessionId:i.sessionId,confidence:"low",sessionFilePath:i.filePath}):null})),n=pg(e.filter(r=>r!==null));return rn={value:n,expiresAt:Date.now()+ig},n}async function pc(){return rn&&Date.now()<rn.expiresAt?rn.value:nn||(nn=_g().finally(()=>{nn=null}),nn)}var tr=R.child({module:"inventory"}),bg=2e3,wg={listScannedSessions:on,scanRunningSessions:pc,searchSessionContent:mc},mt={daemonActive:3,externalRunning:2,idle:1},hc={high:3,medium:2,low:1};function gc(t,e){return e.lastActivityAt.localeCompare(t.lastActivityAt)||t.sessionId.localeCompare(e.sessionId)}function Ig(t,e){let n=t.runtime.needsAttention?1:0,r=e.runtime.needsAttention?1:0,s=t.runtime.isResponding?1:0,i=e.runtime.isResponding?1:0;return r-n||i-s||mt[e.runtime.state]-mt[t.runtime.state]||gc(t,e)}function Ag(t,e){return mt[e.state]>mt[t.state]?e:mt[e.state]<mt[t.state]?t:hc[e.confidence]>hc[t.confidence]?e:t}function xg(t,e){return t?e?t.localeCompare(e)<=0?t:e:t:e}function Tg(t,e){return t?e?t.localeCompare(e)>=0?t:e:t:e}function kg(t,e){return e?t?!(pt(e)&&!pt(t)):!0:!1}function Gs(t="high",e="resumeSession"){return{state:"idle",confidence:t,resumeMode:e}}function Eg(t){return{sessionId:t.sessionId,agent:t.agent,cwd:t.cwd,title:t.title,createdAt:t.createdAt,lastActivityAt:t.lastActivityAt,sources:["record"],runtime:{...Gs(),...t.isResponding?{isResponding:!0}:{}},managed:t.managed,approvalMode:t.approvalMode}}function Cg(t,e){return{sessionId:t.sessionId,agent:t.agent,cwd:t.cwd,title:t.title,createdAt:e,lastActivityAt:e,sources:["process"],runtime:{state:"externalRunning",confidence:t.confidence,resumeMode:"resumeSession",pid:t.pid,command:t.command}}}function Pg(t){return{sessionId:t.sessionId,agent:t.agent,cwd:t.cwd,title:t.title,createdAt:t.createdAt,lastActivityAt:t.lastActivityAt,sources:["daemon"],runtime:{state:"daemonActive",confidence:"high",resumeMode:"reuseDriver",needsAttention:t.needsAttention||void 0,isResponding:t.isResponding||void 0},managed:t.managed,approvalMode:t.approvalMode}}function Rg(t,e){for(let n of e){let r=`${n.agent}:${n.sessionId}`,s=t.get(r);if(!s){t.set(r,{...n,sources:[...n.sources],runtime:{...n.runtime}});continue}let i=kg(s.title,n.title)?n.title:s.title,o=n.cwd||s.cwd,a=Ag(s.runtime,n.runtime),l=s.sources.slice();for(let f of n.sources)l.includes(f)||l.push(f);let c=n.sources.includes("process"),u=s.sources.includes("process")&&!s.sources.includes("daemon"),d=c?s.lastActivityAt:u?n.lastActivityAt:Tg(s.lastActivityAt,n.lastActivityAt);t.set(r,{...s,cwd:o,title:i,createdAt:xg(s.createdAt,n.createdAt),lastActivityAt:d,sources:l,runtime:a,managed:s.managed||n.managed,approvalMode:n.approvalMode??s.approvalMode})}}function Lg(...t){let e=new Map;for(let n of t)Rg(e,n);return[...e.values()]}function Mg(t,e,n,r,s){let i=r?.toLowerCase(),o=t.filter(a=>{if(e&&a.agent!==e||n&&a.cwd!==n)return!1;if(i){let l=(a.title??"").toLowerCase(),c=(a.cwd??"").toLowerCase(),u=l.includes(i)||c.includes(i),d=s?.has(a.sessionId)??!1;if(!u&&!d)return!1}return!0});return r&&tr.info({total:t.length,filtered:o.length,search:r,contentMatchIds:s?.size??0},"filter applied"),o}function Ng(t,e){if(!e)return 0;let n=0,r=t.length;for(;n<r;){let s=n+r>>1,i=t[s];(e.lastActivityAt.localeCompare(i.lastActivityAt)||i.sessionId.localeCompare(e.sessionId))>0?r=s:n=s+1}if(n>0){let s=t[n-1];if(s.lastActivityAt===e.lastActivityAt&&s.sessionId===e.sessionId)return n}return 0}function Og(t,e,n,r,s,i,o){let a=i?1/0:Math.max(1,e||50),l=Lg(t.sessionRecords.map(Eg),t.scannedSessions,t.runningSessions.map(S=>Cg(S,t.scannedAt)),t.activeSessions.map(Pg)),c=t.deletedSessionIds?.size?l.filter(S=>!t.deletedSessionIds?.has(S.sessionId)):l,u=Mg(c,r,s,i,o),d=u.filter(S=>S.runtime.state!=="idle"||S.managed).sort(Ig),f=u.filter(S=>S.runtime.state==="idle"&&!S.managed).sort(gc),p=Ng(f,n),h=f.slice(p,p+a),m=p+h.length<f.length&&h.length>0?{lastActivityAt:h[h.length-1].lastActivityAt,sessionId:h[h.length-1].sessionId}:void 0;return{sessions:n?h:[...d,...h],nextCursor:m}}function Ws(t,e,n,r){return new Promise(s=>{let i=Date.now(),o=!1,a=null,l=c=>{o||(o=!0,a&&(clearTimeout(a),a=null),s(c))};a=setTimeout(()=>{o||(tr.warn({source:t,timeoutMs:r,durationMs:Date.now()-i},"session inventory source timed out, using fallback"),l(n))},r),typeof a=="object"&&"unref"in a&&a.unref(),e().then(c=>{l(c)}).catch(c=>{o||tr.warn({source:t,error:String(c)},"session inventory source failed, using fallback"),l(n)})})}async function nr(t){let e=new Date().toISOString(),n={...wg,...t.loaders??{}},r=Math.max(250,t.sourceTimeoutMs??bg),[s,i,o]=await Promise.all([Ws("scanner.sessions",()=>n.listScannedSessions(t.agent,t.cwd),[],r),Ws("process.running_sessions",()=>n.scanRunningSessions(),[],r),t.search?Ws("scanner.search_content",()=>n.searchSessionContent(t.search,t.agent),void 0,r):Promise.resolve(void 0)]);return t.search&&tr.info({search:t.search,contentMatches:o?.size??0,scanned:s.length,records:t.sessionRecords.length,active:t.activeSessions.length},"search results"),Og({activeSessions:t.activeSessions,sessionRecords:t.sessionRecords,scannedSessions:s,runningSessions:i,scannedAt:e,deletedSessionIds:t.deletedSessionIds},t.limit,t.cursor,t.agent,t.cwd,t.search,o)}var Ce=R.child({module:"scanner"});function bc(t){let e=new Map;return{get(n){let r=e.get(n);if(r){if(Date.now()>r.expiresAt){e.delete(n);return}return r.value}},set(n,r){e.set(n,{value:r,expiresAt:Date.now()+t})},clear(){e.clear()}}}var wc=3e4,Ys=bc(wc),Js=bc(wc),$s=new Map,zs=new Map,rr=8;function ir(){Ys.clear(),Js.clear()}function Ks(t){return t.replace(/[^a-zA-Z0-9]/g,"-")}async function sr(t,e,n){if(t.length===0)return[];let r=Math.max(1,Math.min(e,t.length)),s=new Array(t.length),i=0;return await Promise.all(Array.from({length:r},async()=>{for(;;){let o=i;if(i+=1,o>=t.length)return;s[o]=await n(t[o],o)}})),s}function*Ic(t,e){let n=0,r=0;for(;n<t.length&&r<e;){let s=t.indexOf(`
95
+ `).map(e=>e.trim()).filter(Boolean).map(e=>{let n=e.match(/^(\d+)\s+(.*)$/);if(!n)return null;let r=Number(n[1]),s=n[2],i=qs(s);return!Number.isFinite(r)||!i?null:{pid:r,command:s,agent:i.agent}}).filter(e=>!!e)}async function yg(){let t=await mg();return Promise.all(t.map(async e=>({pid:e.pid,agent:e.agent,command:e.command,cwd:await hg(e.pid),sessionFiles:await gg(e.pid)})))}function Sg(t){return t.replace(/[^a-zA-Z0-9]/g,"-")}async function vg(t,e){if(!e)return null;try{if(t==="claude"){let o=(0,Ee.join)((0,Us.homedir)(),".claude","projects",Sg(e)),l=(await(0,ht.readdir)(o).catch(()=>[])).filter(f=>f.endsWith(".jsonl"));if(l.length===0)return null;let c=null;if(await Promise.all(l.map(async f=>{let p=await(0,ht.stat)((0,Ee.join)(o,f)).catch(()=>null);p&&(!c||p.mtimeMs>c.mtimeMs)&&(c={name:f,mtimeMs:p.mtimeMs})})),!c)return null;let u=(0,Ee.join)(o,c.name),d=gt(t,u);return d?{sessionId:d,filePath:u}:null}let n=(0,Ee.join)((0,Us.homedir)(),".codex","sessions"),r=null;async function s(o){let a=await(0,ht.readdir)(o,{withFileTypes:!0}).catch(()=>[]);for(let l of a){let c=(0,Ee.join)(o,l.name);if(l.isDirectory())await s(c);else if(l.name.endsWith(".jsonl")){let u=await(0,ht.stat)(c).catch(()=>null);if(!u||r&&u.mtimeMs<=r.mtimeMs)continue;let d=await sn(c,t);if(!d||d.cwd!==e)continue;r={path:c,mtimeMs:u.mtimeMs,sessionId:d.sessionId}}}}await s(n);let i=r;return i?{sessionId:i.sessionId,filePath:i.path}:null}catch{return null}}async function _g(){let t=await yg(),e=await Promise.all(t.map(async r=>{let s=dg(r);if(s)return uc(s);if(ug(r.agent,r.command))return null;let i=await vg(r.agent,r.cwd);return i?uc({agent:r.agent,pid:r.pid,cwd:r.cwd,command:r.command,sessionId:i.sessionId,confidence:"low",sessionFilePath:i.filePath}):null})),n=pg(e.filter(r=>r!==null));return rn={value:n,expiresAt:Date.now()+ig},n}async function pc(){return rn&&Date.now()<rn.expiresAt?rn.value:nn||(nn=_g().finally(()=>{nn=null}),nn)}var tr=R.child({module:"inventory"}),bg=2e3,wg={listScannedSessions:on,scanRunningSessions:pc,searchSessionContent:mc},mt={daemonActive:3,externalRunning:2,idle:1},hc={high:3,medium:2,low:1};function gc(t,e){return e.lastActivityAt.localeCompare(t.lastActivityAt)||t.sessionId.localeCompare(e.sessionId)}function Ig(t,e){let n=t.runtime.needsAttention?1:0,r=e.runtime.needsAttention?1:0,s=t.runtime.isResponding?1:0,i=e.runtime.isResponding?1:0;return r-n||i-s||mt[e.runtime.state]-mt[t.runtime.state]||gc(t,e)}function Ag(t,e){return mt[e.state]>mt[t.state]?e:mt[e.state]<mt[t.state]?t:hc[e.confidence]>hc[t.confidence]?e:t}function xg(t,e){return t?e?t.localeCompare(e)<=0?t:e:t:e}function Tg(t,e){return t?e?t.localeCompare(e)>=0?t:e:t:e}function kg(t,e){return e?t?!(pt(e)&&!pt(t)):!0:!1}function Gs(t="high",e="resumeSession"){return{state:"idle",confidence:t,resumeMode:e}}function Eg(t){return{sessionId:t.sessionId,agent:t.agent,cwd:t.cwd,title:t.title,createdAt:t.createdAt,lastActivityAt:t.lastActivityAt,sources:["record"],runtime:{...Gs()},managed:t.managed,approvalMode:t.approvalMode}}function Cg(t,e){return{sessionId:t.sessionId,agent:t.agent,cwd:t.cwd,title:t.title,createdAt:e,lastActivityAt:e,sources:["process"],runtime:{state:"externalRunning",confidence:t.confidence,resumeMode:"resumeSession",pid:t.pid,command:t.command}}}function Pg(t){return{sessionId:t.sessionId,agent:t.agent,cwd:t.cwd,title:t.title,createdAt:t.createdAt,lastActivityAt:t.lastActivityAt,sources:["daemon"],runtime:{state:"daemonActive",confidence:"high",resumeMode:"reuseDriver",needsAttention:t.needsAttention||void 0,isResponding:t.isResponding||void 0},managed:t.managed,approvalMode:t.approvalMode}}function Rg(t,e){for(let n of e){let r=`${n.agent}:${n.sessionId}`,s=t.get(r);if(!s){t.set(r,{...n,sources:[...n.sources],runtime:{...n.runtime}});continue}let i=kg(s.title,n.title)?n.title:s.title,o=n.cwd||s.cwd,a=Ag(s.runtime,n.runtime),l=s.sources.slice();for(let f of n.sources)l.includes(f)||l.push(f);let c=n.sources.includes("process"),u=s.sources.includes("process")&&!s.sources.includes("daemon"),d=c?s.lastActivityAt:u?n.lastActivityAt:Tg(s.lastActivityAt,n.lastActivityAt);t.set(r,{...s,cwd:o,title:i,createdAt:xg(s.createdAt,n.createdAt),lastActivityAt:d,sources:l,runtime:a,managed:s.managed||n.managed,approvalMode:n.approvalMode??s.approvalMode})}}function Lg(...t){let e=new Map;for(let n of t)Rg(e,n);return[...e.values()]}function Mg(t,e,n,r,s){let i=r?.toLowerCase(),o=t.filter(a=>{if(e&&a.agent!==e||n&&a.cwd!==n)return!1;if(i){let l=(a.title??"").toLowerCase(),c=(a.cwd??"").toLowerCase(),u=l.includes(i)||c.includes(i),d=s?.has(a.sessionId)??!1;if(!u&&!d)return!1}return!0});return r&&tr.info({total:t.length,filtered:o.length,search:r,contentMatchIds:s?.size??0},"filter applied"),o}function Ng(t,e){if(!e)return 0;let n=0,r=t.length;for(;n<r;){let s=n+r>>1,i=t[s];(e.lastActivityAt.localeCompare(i.lastActivityAt)||i.sessionId.localeCompare(e.sessionId))>0?r=s:n=s+1}if(n>0){let s=t[n-1];if(s.lastActivityAt===e.lastActivityAt&&s.sessionId===e.sessionId)return n}return 0}function Og(t,e,n,r,s,i,o){let a=i?1/0:Math.max(1,e||50),l=Lg(t.sessionRecords.map(Eg),t.scannedSessions,t.runningSessions.map(S=>Cg(S,t.scannedAt)),t.activeSessions.map(Pg)),c=t.deletedSessionIds?.size?l.filter(S=>!t.deletedSessionIds?.has(S.sessionId)):l,u=Mg(c,r,s,i,o),d=u.filter(S=>S.runtime.state!=="idle"||S.managed).sort(Ig),f=u.filter(S=>S.runtime.state==="idle"&&!S.managed).sort(gc),p=Ng(f,n),h=f.slice(p,p+a),m=p+h.length<f.length&&h.length>0?{lastActivityAt:h[h.length-1].lastActivityAt,sessionId:h[h.length-1].sessionId}:void 0;return{sessions:n?h:[...d,...h],nextCursor:m}}function Ws(t,e,n,r){return new Promise(s=>{let i=Date.now(),o=!1,a=null,l=c=>{o||(o=!0,a&&(clearTimeout(a),a=null),s(c))};a=setTimeout(()=>{o||(tr.warn({source:t,timeoutMs:r,durationMs:Date.now()-i},"session inventory source timed out, using fallback"),l(n))},r),typeof a=="object"&&"unref"in a&&a.unref(),e().then(c=>{l(c)}).catch(c=>{o||tr.warn({source:t,error:String(c)},"session inventory source failed, using fallback"),l(n)})})}async function nr(t){let e=new Date().toISOString(),n={...wg,...t.loaders??{}},r=Math.max(250,t.sourceTimeoutMs??bg),[s,i,o]=await Promise.all([Ws("scanner.sessions",()=>n.listScannedSessions(t.agent,t.cwd),[],r),Ws("process.running_sessions",()=>n.scanRunningSessions(),[],r),t.search?Ws("scanner.search_content",()=>n.searchSessionContent(t.search,t.agent),void 0,r):Promise.resolve(void 0)]);return t.search&&tr.info({search:t.search,contentMatches:o?.size??0,scanned:s.length,records:t.sessionRecords.length,active:t.activeSessions.length},"search results"),Og({activeSessions:t.activeSessions,sessionRecords:t.sessionRecords,scannedSessions:s,runningSessions:i,scannedAt:e,deletedSessionIds:t.deletedSessionIds},t.limit,t.cursor,t.agent,t.cwd,t.search,o)}var Ce=R.child({module:"scanner"});function bc(t){let e=new Map;return{get(n){let r=e.get(n);if(r){if(Date.now()>r.expiresAt){e.delete(n);return}return r.value}},set(n,r){e.set(n,{value:r,expiresAt:Date.now()+t})},clear(){e.clear()}}}var wc=3e4,Ys=bc(wc),Js=bc(wc),$s=new Map,zs=new Map,rr=8;function ir(){Ys.clear(),Js.clear()}function Ks(t){return t.replace(/[^a-zA-Z0-9]/g,"-")}async function sr(t,e,n){if(t.length===0)return[];let r=Math.max(1,Math.min(e,t.length)),s=new Array(t.length),i=0;return await Promise.all(Array.from({length:r},async()=>{for(;;){let o=i;if(i+=1,o>=t.length)return;s[o]=await n(t[o],o)}})),s}function*Ic(t,e){let n=0,r=0;for(;n<t.length&&r<e;){let s=t.indexOf(`
96
96
  `,n);s===-1&&(s=t.length);let i=t.substring(n,s);n=s+1,!(i.length===0||i.trim().length===0)&&(yield i,r+=1)}}var Vs=512*1024;async function Ac(t,e){if(e<=Vs)return(0,D.readFile)(t,"utf-8");let n=await(0,D.open)(t,"r");try{let r=Buffer.alloc(Vs),{bytesRead:s}=await n.read(r,0,Vs,0);return r.toString("utf-8",0,s)}finally{await n.close()}}function Zs(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>!e||typeof e!="object"?"":typeof e.text=="string"?e.text:typeof e.content=="string"?e.content:"").join(""):""}function xc(t){return t?.type==="response_item"&&t.payload?.type==="message"&&t.payload.role==="user"?Zs(t.payload.content):t?.type==="event_msg"&&t.payload?.type==="user_message"&&typeof t.payload.message=="string"?t.payload.message:""}function ei(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>!e||typeof e!="object"||e.type!=="text"?"":typeof e.text=="string"?e.text:"").join(""):""}var Bg=["<task-notification>","<local-command-caveat>","<local-command-stdout>","<local-command-stderr>","<command-name>","<command-message>","<command-args>","<system-reminder>","<environment_context>","# AGENTS.md instructions for "];function Dg(t,e){if(t?.isMeta===!0)return!0;let n=e.trim();return n?Bg.some(r=>n.startsWith(r)):!1}function ti(t){if(t?.type!=="user"||t.message?.role!=="user")return"";let e=ei(t.message.content);return Dg(t,e)?"":e}function Tc(t){let e=t.trim();return e.startsWith("# AGENTS.md instructions for ")||e.startsWith("<environment_context>")}function kc(t,e="scanner"){return{sessionId:t.sessionId,agent:t.agent,cwd:t.cwd,title:t.title,createdAt:t.createdAt,lastActivityAt:t.lastActivityAt,sources:[e],runtime:Gs()}}function gt(t,e){let n=(0,C.basename)(e,".jsonl");return t==="claude"?n||null:n.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i)?.[1]??null}async function Hg(t,e){let n=await Ac(t,e),r=Ic(n,64),s="",i="",o,a,l;for(let c of r){let u;try{u=JSON.parse(c)}catch{continue}if(!s&&typeof u.cwd=="string"&&(s=u.cwd),!i&&typeof u.sessionId=="string"&&(i=u.sessionId),o||(o=We([u.customTitle,u.summary])),!l){let d=ti(u),f=We([],d);f&&(a=d,l=f)}if(s&&(o||l))break}return s?{sessionId:i||gt("claude",t)||(0,C.basename)(t,".jsonl"),cwd:s,title:o??l??We([],a)}:null}async function Fg(t,e){let n=await Ac(t,e),r=Ic(n,96),s="",i="",o,a,l;for(let c of r){let u;try{u=JSON.parse(c)}catch{continue}if(s||(s=u.payload?.cwd??u.cwd??""),i||(i=u.payload?.id??u.id??""),o||(o=We([u.payload?.title,u.title])),!l){let d=xc(u),f=d&&!Tc(d)?We([],d):void 0;f&&(a=d,l=f)}if(s&&(o||l))break}return s?{sessionId:i||gt("codex",t)||(0,C.basename)(t,".jsonl"),cwd:s,title:o??l??We([],a)}:null}async function sn(t,e){let n=await(0,D.stat)(t).catch(()=>null);if(!n)return null;try{let r=n.size;if(e==="claude"){let i=await Hg(t,r);return i?{sessionId:i.sessionId,agent:e,cwd:i.cwd,title:i.title,createdAt:new Date(n.birthtimeMs).toISOString(),lastActivityAt:new Date(n.mtimeMs).toISOString(),filePath:t}:null}let s=await Fg(t,r);return s?{sessionId:s.sessionId,agent:e,cwd:s.cwd,title:s.title,createdAt:new Date(n.birthtimeMs).toISOString(),lastActivityAt:new Date(n.mtimeMs).toISOString(),filePath:t}:null}catch{return null}}async function yc(t){let e=(0,C.join)((0,me.homedir)(),".claude","projects");try{let n;t?n=[Ks(t)]:n=(await(0,D.readdir)(e,{withFileTypes:!0})).filter(a=>a.isDirectory()).map(a=>a.name);let r=[];for(let o of n){let a=(0,C.join)(e,o),l=await(0,D.readdir)(a).catch(()=>[]);for(let c of l)c.endsWith(".jsonl")&&r.push((0,C.join)(a,c))}return(await sr(r,rr,o=>sn(o,"claude"))).filter(o=>o!==null).map(o=>kc(o)).sort((o,a)=>a.lastActivityAt.localeCompare(o.lastActivityAt))}catch(n){return Ce.warn({error:String(n)},"failed to list claude sessions"),[]}}async function Sc(t){let e=(0,C.join)((0,me.homedir)(),".codex","sessions");try{let n=await(0,D.readdir)(e).catch(()=>[]),r=[];for(let o of n){let a=(0,C.join)(e,o),l=await(0,D.readdir)(a).catch(()=>[]);for(let c of l){let u=(0,C.join)(a,c),d=await(0,D.readdir)(u).catch(()=>[]);for(let f of d){let p=(0,C.join)(u,f),h=await(0,D.readdir)(p).catch(()=>[]);for(let g of h)g.endsWith(".jsonl")&&r.push((0,C.join)(p,g))}}}return(await sr(r,rr,o=>sn(o,"codex"))).filter(o=>o!==null).filter(o=>!t||o.cwd===t).map(o=>kc(o)).sort((o,a)=>a.lastActivityAt.localeCompare(o.lastActivityAt))}catch(n){return Ce.warn({error:String(n)},"failed to list codex sessions"),[]}}async function on(t,e){let r=`list:${(0,me.homedir)()}:${t??"all"}:${e??""}`,s=Ys.get(r);if(s)return s;let i=$s.get(r);if(i)return i;let o=(async()=>{let a;if(t==="claude")a=await yc(e);else if(t==="codex")a=await Sc(e);else{let[l,c]=await Promise.all([yc(e),Sc(e)]);a=[...l,...c].sort((u,d)=>d.lastActivityAt.localeCompare(u.lastActivityAt))}return Ys.set(r,a),a})();return $s.set(r,o),o.finally(()=>$s.delete(r)),o}async function mc(t,e){let r=`search:${(0,me.homedir)()}:${t}:${e??"all"}`,s=Js.get(r);if(s)return s;let i=zs.get(r);if(i)return i;let o=(async()=>{let a=new Set,l=t.toLowerCase();async function c(){let d=(0,C.join)((0,me.homedir)(),".claude","projects");try{let f=await(0,D.readdir)(d,{withFileTypes:!0}),p=[];for(let g of f){if(!g.isDirectory())continue;let m=(0,C.join)(d,g.name),S=await(0,D.readdir)(m).catch(()=>[]);for(let P of S)P.endsWith(".jsonl")&&p.push((0,C.join)(m,P))}let h=await sr(p,rr,g=>vc(g,l,"claude"));for(let g of h)g&&a.add(g)}catch(f){Ce.warn({error:String(f)},"failed to search claude files")}}async function u(){let d=(0,C.join)((0,me.homedir)(),".codex","sessions");try{let f=[];async function p(g){let m=await(0,D.readdir)(g,{withFileTypes:!0}).catch(()=>[]);for(let S of m){let P=(0,C.join)(g,S.name);S.isDirectory()?await p(P):S.name.endsWith(".jsonl")&&f.push(P)}}await p(d);let h=await sr(f,rr,g=>vc(g,l,"codex"));for(let g of h)g&&a.add(g)}catch(f){Ce.warn({error:String(f)},"failed to search codex files")}}return e==="claude"?await c():e==="codex"?await u():await Promise.all([c(),u()]),Js.set(r,a),a})();return zs.set(r,o),o.finally(()=>zs.delete(r)),o}async function vc(t,e,n){let r=(0,Xs.createReadStream)(t,{encoding:"utf-8"}),s=(0,Qs.createInterface)({input:r,crlfDelay:1/0}),i=n==="claude"?Ug:qg,o="",a=!1;try{for await(let l of s){if(!l.trim())continue;let c;try{c=JSON.parse(l)}catch{continue}if(o||(n==="claude"?typeof c.sessionId=="string"&&(o=c.sessionId):o=c.payload?.id??c.id??""),!a){let u=i(c);u&&u.toLowerCase().includes(e)&&(a=!0)}if(o&&a)break}}finally{s.close(),r.destroy()}return a?o||gt(n,t):null}function Ug(t){return t?.type==="user"&&t.message?.role==="user"?ti(t):t?.type==="assistant"&&t.message?.role==="assistant"?ei(t.message.content):""}function qg(t){if(t?.type==="response_item"&&t.payload?.type==="message"){let n=t.payload.role;if(n==="user"||n==="assistant")return Zs(t.payload.content)}let e=xc(t);return e||""}async function _c(t,e){let n=(0,Xs.createReadStream)(t,{encoding:"utf-8"}),r=(0,Qs.createInterface)({input:n,crlfDelay:1/0});try{for await(let s of r){if(!s.trim())continue;let i;try{i=JSON.parse(s)}catch{continue}if(e(i))break}}finally{r.close(),n.destroy()}}async function an(t,e,n){let r=[];if(e==="claude"){let s=(0,C.join)((0,me.homedir)(),".claude","projects");try{let i=n?[Ks(n)]:[],o=await(0,D.readdir)(s).catch(()=>[]),a=n?[...i,...o.filter(l=>l!==Ks(n))]:o;for(let l of a){let c=(0,C.join)(s,l,`${t}.jsonl`);try{if(await _c(c,u=>{if(u.type==="user"&&u.message?.role==="user"){let d=ti(u);d&&r.push({role:"user",content:d})}else if(u.type==="assistant"&&u.message?.role==="assistant"){let d=ei(u.message.content);d&&r.push({role:"assistant",content:d})}}),r.length>0)break}catch(u){u.code!=="ENOENT"&&Ce.warn({error:String(u)},"failed to read claude session file")}}}catch(i){Ce.warn({error:String(i)},"failed to read claude session history")}}else if(e==="codex"){let s=(0,C.join)((0,me.homedir)(),".codex","sessions");try{let i=await Ec(s,t);i&&await _c(i,o=>{if(o.type!=="response_item"||o.payload?.type!=="message")return;let a=o.payload.role;if(a!=="user"&&a!=="assistant")return;let l=Zs(o.payload.content);l&&(a==="user"&&Tc(l)||r.push({role:a,content:l}))})}catch(i){Ce.warn({error:String(i)},"failed to read codex session history")}}return r}async function Ec(t,e){try{let n=await(0,D.readdir)(t,{withFileTypes:!0});for(let r of n){let s=(0,C.join)(t,r.name);if(r.isDirectory()){let i=await Ec(s,e);if(i)return i}else if(r.name.includes(e)&&r.name.endsWith(".jsonl"))return s}}catch(n){Ce.warn({error:String(n)},"failed to walk codex sessions dir")}return null}var yt=require("fs"),Rc=require("path");var jg=500,Cc=200;function Wg(t){if(!Array.isArray(t))return[];let e=t.filter(n=>typeof n=="string"&&n.length>0);return e.length<=Cc?e:e.slice(-Cc)}function Gg(t){if(!Array.isArray(t))return[];let e=[];for(let n of t)typeof n!="string"||n.length===0||e.includes(n)||e.push(n);return e}function $g(t){if(!t||typeof t!="object"||Array.isArray(t))return;let e=t,n=typeof e.requestId=="string"?e.requestId:"",r=typeof e.toolName=="string"?e.toolName:"",s=typeof e.description=="string"?e.description:"",i=e.input&&typeof e.input=="object"&&!Array.isArray(e.input)?e.input:{};if(!n||!r||!s)return;let o=e.approvalContext;return o&&typeof o=="object"&&!Array.isArray(o)&&o.provider==="codex"&&typeof o.kind=="string"&&typeof o.rpcId=="number"?{requestId:n,toolName:r,input:i,description:s,approvalContext:{provider:"codex",kind:o.kind,rpcId:o.rpcId,...typeof o.questionId=="string"?{questionId:o.questionId}:{},...typeof o.approveLabel=="string"?{approveLabel:o.approveLabel}:{},...typeof o.denyLabel=="string"?{denyLabel:o.denyLabel}:{}}}:{requestId:n,toolName:r,input:i,description:s}}function Pc(t){return{...t,lastActivityAt:t.lastActivityAt??t.createdAt,acceptedClientMessageIds:Wg(t.acceptedClientMessageIds),pendingApproval:$g(t.pendingApproval)}}function zg(t){if(Array.isArray(t))return{records:t.map(Pc),deletedSessionIds:[]};if(t&&typeof t=="object"){let e=t;return{records:Array.isArray(e.records)?e.records.map(Pc):[],deletedSessionIds:Gg(e.deletedSessionIds)}}return{records:[],deletedSessionIds:[]}}var or=class{records;deletedSessionIds;debounceTimer=null;constructor(){let e=this.loadFromDisk();this.records=e.records,this.deletedSessionIds=new Set(e.deletedSessionIds)}getAll(){return this.records}getDeletedSessionIds(){return[...this.deletedSessionIds]}find(e){return this.records.find(n=>n.sessionId===e)}isDeleted(e){return this.deletedSessionIds.has(e)}upsert(e){this.deletedSessionIds.delete(e.sessionId);let n=this.records.findIndex(r=>r.sessionId===e.sessionId);n>=0?this.records[n]=e:this.records.unshift(e),this.scheduleSave()}remove(e){this.records=this.records.filter(n=>n.sessionId!==e),this.deletedSessionIds.add(e),this.scheduleSave()}flushSync(){this.debounceTimer&&(clearTimeout(this.debounceTimer),this.debounceTimer=null),this.saveToDisk()}scheduleSave(){this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this.debounceTimer=null,this.saveToDisk()},jg)}loadFromDisk(){try{let e=(0,yt.readFileSync)(qn,"utf-8");return zg(JSON.parse(e))}catch{}return{records:[],deletedSessionIds:[]}}saveToDisk(){(0,yt.mkdirSync)((0,Rc.dirname)(qn),{recursive:!0}),(0,yt.writeFileSync)(qn,JSON.stringify({records:this.records,deletedSessionIds:[...this.deletedSessionIds]},null,2))}};var St=require("path"),Lc=require("os");function ar(t){return t=t.replace(/^~/,"~"),t.startsWith("~/")||t==="~"?(0,St.join)((0,Lc.homedir)(),t.slice(2)):t}function Vg(t){let e=t.trim();if(!e)return"";let n=e.indexOf("#");n>0&&(e=e.slice(0,n));let r=e.match(/^(.*?)(:\d+(?::\d+)?)$/);return r&&(e=r[1]??e),e}function Mc(t,e){let n=ar(Vg(t));if(!n||(0,St.isAbsolute)(n))return n;let r=ar(e??"");return r?(0,St.resolve)(r,n):n}var Nc={approvalRequestV1:"vibelet.approvalRequest.v1"};var vt=require("fs"),Oc=require("path");function Yg(t){return!!(t&&typeof t=="object"&&typeof t.deviceId=="string"&&typeof t.pushToken=="string"&&t.platform==="expo"&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"&&(typeof t.lastSentAt=="string"||typeof t.lastSentAt>"u"))}function Jg(t){try{let e=(0,vt.readFileSync)(t,"utf8"),n=JSON.parse(e);return Array.isArray(n)?n.filter(Yg):[]}catch{return[]}}function ln(t,e){(0,vt.mkdirSync)((0,Oc.dirname)(t),{recursive:!0}),(0,vt.writeFileSync)(t,JSON.stringify(e,null,2)+`
97
- `,"utf8")}var lr=class{constructor(e=Ll){this.pushSubscriptionsPath=e;this.records=Jg(e)}records;list(){return this.records.map(e=>({...e}))}listTokens(){return this.records.map(e=>e.pushToken)}count(){return this.records.length}register(e,n){let r=new Date().toISOString(),s=this.records.find(o=>o.deviceId===e),i={deviceId:e,pushToken:n,platform:"expo",createdAt:s?.createdAt??r,updatedAt:r,...s?.lastSentAt?{lastSentAt:s.lastSentAt}:{}};this.records=[i,...this.records.filter(o=>o.deviceId!==e&&o.pushToken!==n)],ln(this.pushSubscriptionsPath,this.records)}unregister(e,n){let r=this.records.filter(s=>!(s.deviceId===e&&s.pushToken===n));return r.length===this.records.length?!1:(this.records=r,ln(this.pushSubscriptionsPath,this.records),!0)}unregisterToken(e){let n=this.records.filter(r=>r.pushToken!==e);return n.length===this.records.length?!1:(this.records=n,ln(this.pushSubscriptionsPath,this.records),!0)}markSent(e){if(e.length===0)return;let n=new Set(e),r=new Date().toISOString(),s=!1;for(let i of this.records)n.has(i.pushToken)&&(i.lastSentAt=r,s=!0);s&&ln(this.pushSubscriptionsPath,this.records)}reset(){this.records=[],ln(this.pushSubscriptionsPath,this.records)}};var z=R.child({module:"push"}),Kg="https://exp.host/--/api/v2/push/send",Xg="https://exp.host/--/api/v2/push/getReceipts",Qg=[0,1e3,3e3],cn=new lr;function Zg(t){return!!(t&&typeof t=="object"&&typeof t.daemonId=="string"&&typeof t.canonicalHost=="string"&&typeof t.sessionId=="string"&&(t.agent==="claude"||t.agent==="codex")&&(t.eventType==="reply_ready"||t.eventType==="approval_request")&&(typeof t.requestId>"u"||typeof t.requestId=="string"))}function em(t){return new Promise(e=>{setTimeout(e,t)})}function Bc(t){return t==="DeviceNotRegistered"}function tm(t,e){if(!Array.isArray(t.data))return{successfulTokens:[],ticketErrors:[]};let n=[],r=[];for(let[s,i]of t.data.entries()){let o=e[s];if(!(!o||!i||typeof i!="object")){if(i.status==="ok"){n.push(o);continue}r.push({token:o,ticket:i})}}return{successfulTokens:n,ticketErrors:r}}function nm(t,e){let n=new Map;if(!Array.isArray(t.data))return n;for(let[r,s]of t.data.entries()){let i=e[r];!i||!s||s.status!=="ok"||typeof s.id!="string"||s.id.length===0||n.set(s.id,i)}return n}function rm(t,e){let n=[],r=[],s=t.data;for(let[i,o]of e.entries()){let a=s?.[i];if(!a||typeof a!="object"){n.push(i);continue}a.status==="error"&&r.push({token:o,receipt:a})}return{pendingTicketIds:n,receiptErrors:r}}async function sm(t,e,n,r){let s=new Map(t);for(let i of Qg){if(s.size===0)return;i>0&&await n(i);let o;try{o=await e(Xg,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({ids:[...s.keys()]})})}catch(u){z.error({error:String(u),count:s.size},"push receipt request failed");return}if(!o.ok){z.error({status:o.status,statusText:o.statusText,count:s.size},"push receipt request returned error status");return}let a=await o.json().catch(()=>null);if(!a){z.error({count:s.size},"push receipt response was unreadable");return}let{pendingTicketIds:l,receiptErrors:c}=rm(a,s);for(let{token:u,receipt:d}of c){let f=d.details?.error;if(z.error({token:u,message:d.message,details:d.details,receiptStatus:d.status},"push receipt rejected"),Bc(f)){let p=r.unregisterToken(u);z.info({token:u,errorCode:f,removed:p},"push token removed after receipt rejection")}}s=new Map(l.map(u=>[u,s.get(u)]))}s.size>0&&z.warn({pendingReceipts:s.size},"push receipts still pending after polling")}function im(t){let e=t?.pushStore??cn,n=t?.fetchImpl??globalThis.fetch,r=t?.sleepImpl??em;return async function(i,o,a){let l=e.listTokens();if(l.length===0)return;let c=l.map(u=>({to:u,sound:"default",title:i,body:o,data:a,...Zg(a)&&a.eventType==="approval_request"?{categoryId:Nc.approvalRequestV1}:{}}));try{let u=await n(Kg,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)});if(!u.ok){z.error({status:u.status,statusText:u.statusText},"push send failed");return}let d=await u.json().catch(()=>null);if(!d){z.error({count:c.length},"push send returned unreadable response");return}let{successfulTokens:f,ticketErrors:p}=tm(d,l),h=nm(d,l);for(let{token:g,ticket:m}of p){let S=m.details?.error;if(z.error({token:g,message:m.message,details:m.details,ticketStatus:m.status},"push ticket rejected"),Bc(S)){let P=e.unregisterToken(g);z.info({token:g,errorCode:S,removed:P},"push token removed after ticket rejection")}}f.length>0&&(z.debug({count:f.length},"push sent"),e.markSent(f)),h.size>0&&await sm(h,n,r,e)}catch(u){z.error({error:String(u)},"push send error")}}}function ni(t,e){cn.register(t,e),z.info({deviceId:t,token:e,total:cn.count()},"push token registered")}function ri(t,e){let n=cn.unregister(t,e);z.info({deviceId:t,token:e,total:cn.count(),removed:n},"push token unregistered")}var cr=im();var b=R.child({module:"manager"}),om="Done.",am="Approval required",Dc=180,dr=200;function ur(...t){let e=[];for(let n of t)if(n?.length)for(let r of n)!r||e.includes(r)||(e.push(r),e.length>dr&&e.splice(0,e.length-dr));return e}function ce(t){return{sessionId:t.sessionId,agent:t.agent,cwd:t.cwd,approvalMode:t.approvalMode,acceptedClientMessageIds:ur(t.acceptedClientMessageIds),pendingApproval:t.agent==="codex"?t.pendingApproval:void 0,title:t.title,createdAt:t.createdAt,lastActivityAt:t.lastActivityAt,managed:t.managed,isResponding:t.isResponding||void 0}}function Hc(t){let e=t.pendingApproval?.requestId;return typeof e=="string"&&Kn(e)}function Fc(t,e,n){return{sessionId:t,agent:e,...n}}function lm(t){return t.startsWith(Ms)}function Uc(t){return t?{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}:{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"Denied from Vibelet"}}}var fr=class{constructor(e=cr){this.pushSender=e;this.startIdleSweep()}sessions=new Map;claudeHookSessions=new Map;store=new or;idleSweepInterval=null;startIdleSweep(){v.idleTimeoutMs<=0&&v.turnStallTimeoutMs<=0||(this.idleSweepInterval=setInterval(()=>this.sweepIdleSessions(),6e4),this.idleSweepInterval.unref())}stopIdleSweep(){this.idleSweepInterval&&(clearInterval(this.idleSweepInterval),this.idleSweepInterval=null)}sweepIdleSessions(){let e=Date.now(),n=v.idleTimeoutMs,r=v.turnStallTimeoutMs;if(n<=0&&r<=0)return;let s=3600*1e3;for(let[i,o]of this.sessions){if(!o.active&&!o.driver){if(o.clients.size===0){let l=e-o.lastActivityTs;l>=s&&(b.info({sessionId:o.sessionId,inactiveMs:l},"removing inactive session from memory"),w.increment("session.cleanup",{reason:"inactive"}),this.unregisterClaudeHookSession(o),this.sessions.delete(i))}continue}if(!o.active||!o.driver)continue;let a=e-o.lastActivityTs;if(o.isResponding){if(r<=0||o.pendingApproval||a<r)continue;b.warn({sessionId:o.sessionId,agent:o.agent,inactiveMs:a,turnStallTimeoutMs:r},"stopping stalled driver"),w.increment("driver.stall_timeout",{agent:o.agent}),_.emit("driver.stall_timeout",{sessionId:o.sessionId,agent:o.agent,idleMs:a}),o.isResponding=!1,o.currentReplyText="",this.broadcast(o.sessionId,{type:"error",sessionId:o.sessionId,message:`Agent stopped responding for over ${Math.ceil(r/1e3)}s. Send a new message to continue.`}),o.driver.stop(),o.active=!1,o.driver=null,this.updateGauges(),this.touchSession(o.sessionId);continue}o.pendingApproval||n<=0||a<n||(b.info({sessionId:o.sessionId,agent:o.agent,idleMs:a,timeoutMs:n},"stopping idle driver"),w.increment("driver.idle_timeout",{agent:o.agent}),_.emit("driver.idle_timeout",{sessionId:o.sessionId,agent:o.agent,idleMs:a}),o.driver.stop(),o.active=!1,o.driver=null,this.updateGauges(),this.touchSession(o.sessionId))}}bindDriverLifecycle(e,n,r,s){e.driver?.onMessage(i=>{if(b.debug({agent:n,context:r,msgType:i.type,sessionId:e.sessionId},"driver message received"),i.type!=="response"&&i.sessionId&&i.sessionId!==e.sessionId&&!this.sessions.has(i.sessionId)&&this.remapSessionId(e,i.sessionId,s),(i.type==="session.done"||i.type==="session.interrupted")&&(e.isResponding=!1,(i.type==="session.interrupted"||!Hc(e))&&(e.pendingApproval=void 0)),i.type==="approval.request"){if(n==="codex"&&e.approvalMode==="autoApprove"){if(e.driver?.respondApproval(i.requestId,!0)??!1){_.emit("approval.response",{sessionId:e.sessionId,requestId:i.requestId,approved:!0}),e.pendingApproval=void 0,e.isResponding=!0,this.touchSession(e.sessionId);return}b.warn({sessionId:e.sessionId,requestId:i.requestId},"failed to auto-approve codex request; falling back to pending approval flow")}e.isResponding=!1,e.pendingApproval={requestId:i.requestId,toolName:i.toolName,input:i.input,description:i.description,...i.approvalContext?{approvalContext:i.approvalContext}:{}},this.pushSender(am,this.buildPushBody(`${e.title||e.sessionId}: ${i.description||i.toolName}`),{sessionId:e.sessionId,agent:e.agent,requestId:i.requestId,eventType:"approval_request"})}n==="claude"&&i.type==="approval.request"&&Kn(i.requestId)&&(e.lastUserMessage?e.syntheticApprovalRetries[i.requestId]={message:e.lastUserMessage,toolName:i.toolName}:b.warn({sessionId:e.sessionId,requestId:i.requestId},"missing lastUserMessage for synthetic approval retry")),this.touchSession(e.sessionId,i.type!=="text.delta"),this.broadcast(e.sessionId,i),(i.type==="session.done"||i.type==="session.interrupted")&&e.bufferedPrompts.length>0&&this.flushBufferedPrompt(e)}),e.driver?.onExit?.(i=>{b.info({agent:n,context:r,exitCode:i,sessionId:e.sessionId},"driver exited"),_.emit("driver.exit",{sessionId:e.sessionId,agent:n,exitCode:i}),w.increment("driver.exit",{agent:n,abnormal:i&&i!==0?"true":"false"});let o=!!(e.pendingApproval&&(e.agent==="codex"||i===0&&Hc(e)));this.resolvePendingClaudeHookApprovals(e),e.active=!1,e.driver=null,e.isResponding=!1,e.currentReplyText="",o||(e.pendingApproval=void 0),this.updateGauges(),this.touchSession(e.sessionId)})}remapSessionId(e,n,r){if(!n||n===e.sessionId)return;let s=this.sessions.get(n);if(s&&s!==e){b.warn({oldSessionId:e.sessionId,newSessionId:n},"skipping session ID remap because target already exists");return}let i=e.sessionId;b.info({oldSessionId:i,newSessionId:n},"session ID updated"),this.store.remove(i),this.sessions.delete(i),e.sessionId=n,this.sessions.set(n,e),this.store.upsert(ce(e)),r&&this.reply(r,`id_update_${Date.now()}`,!0,{sessionId:n,oldSessionId:i})}flushBufferedPrompt(e,n=!1){if(!e.driver||!e.active||e.startupInProgress||e.pendingApproval||!n&&e.isResponding)return!1;let r=e.bufferedPrompts.shift();return r?(e.isResponding=!0,e.currentReplyText="",e.lastUserMessage=r,this.touchSession(e.sessionId),e.driver.sendPrompt(r),!0):!1}startPendingCodexSession(e,n){if(e.agent!=="codex"||!e.driver)return;let r=e.driver,s=e.sessionId,i=e.startupToken,o=w.startTimer("driver.spawn");(async()=>{try{let a=await r.start(e.cwd,void 0,e.approvalMode),l=o();if(this.sessions.get(s)!==e||e.startupToken!==i||e.driver!==r){b.info({pendingSessionId:s,actualSessionId:a},"discarding stale codex startup result");return}e.startupInProgress=!1,b.info({pendingSessionId:s,sessionId:a,spawnMs:l},"codex session ready"),a&&a!==s&&this.remapSessionId(e,a,n),this.flushBufferedPrompt(e,!0)}catch(a){if(o(),this.sessions.get(s)!==e||e.startupToken!==i){b.info({pendingSessionId:s,error:String(a)},"ignoring stale codex startup failure");return}e.startupInProgress=!1,e.bufferedPrompts=[],e.active=!1,e.driver=null,e.isResponding=!1,e.currentReplyText="",this.updateGauges(),this.touchSession(e.sessionId),b.error({sessionId:s,cwd:e.cwd,error:String(a)},"async codex createSession error"),this.broadcast(e.sessionId,{type:"error",sessionId:e.sessionId,message:`Failed to start Codex session: ${String(a)}`})}})()}configureDriverBeforeStart(e,n,r){if(e!=="claude"||!(n instanceof tn))return;let s=r??(0,si.randomUUID)().replace(/-/g,"");return n.configureHookBridge(v.port,s),s}registerClaudeHookSession(e){e.agent!=="claude"||!e.claudeHookSecret||this.claudeHookSessions.set(e.claudeHookSecret,e)}unregisterClaudeHookSession(e){if(e.agent!=="claude"||!e.claudeHookSecret)return;this.claudeHookSessions.get(e.claudeHookSecret)===e&&this.claudeHookSessions.delete(e.claudeHookSecret)}resolvePendingClaudeHookApprovals(e,n=en){for(let r of e.pendingClaudeHookApprovals.values())r.resolve(n);e.pendingClaudeHookApprovals.clear(),e.pendingApproval&&lm(e.pendingApproval.requestId)&&(e.pendingApproval=void 0)}resolveClaudeHookSession(e){if(!e)return;let n=e.trim();if(n)return this.claudeHookSessions.get(n)}handleClaudeSessionStartHook(e,n){let r=this.resolveClaudeHookSession(e);return r?(this.touchSession(r.sessionId),!0):(b.warn({secretPresent:!!e},"received Claude session-start hook for unknown session"),!1)}async handleClaudePermissionHook(e,n){let r=this.resolveClaudeHookSession(e);if(!r||r.agent!=="claude"||!r.active)return b.warn({secretPresent:!!e},"received Claude permission hook for unknown or inactive session"),en;if(r.approvalMode==="autoApprove")return Uc(!0);let i=(typeof n.tool_name=="string"?n.tool_name:typeof n.toolName=="string"?n.toolName:"").trim();if(!i)return en;let o=n.tool_input??n.toolInput,a=o&&typeof o=="object"&&!Array.isArray(o)?o:{},l=typeof n.tool_use_id=="string"?n.tool_use_id:typeof n.toolUseId=="string"?n.toolUseId:"",c=`${Ms}${l.trim()||(0,si.randomUUID)()}`,u=r.pendingClaudeHookApprovals.get(c);if(u)return u.promise;let d=`Claude requested permissions to use ${i}.`,f,p=new Promise(h=>{f=h});return r.pendingClaudeHookApprovals.set(c,{requestId:c,promise:p,resolve:h=>{r.pendingClaudeHookApprovals.delete(c),f(h)}}),r.pendingApproval={requestId:c,toolName:i,input:a,description:d},_.emit("approval.request",{agent:"claude",sessionId:r.sessionId,toolName:i}),this.touchSession(r.sessionId),this.broadcast(r.sessionId,{type:"approval.request",sessionId:r.sessionId,requestId:c,toolName:i,input:a,description:d}),p}async resolveReconnectSession(e,n,r){if(this.isDeletedSession(e))return;let s=new Date().toISOString(),i=r?.agent,o=r?.cwd??"",a=r?.approvalMode,l=r?.pendingApproval,c=r?.title??"",u=r?.createdAt??s,d=r?.lastActivityAt??s,f=ur(r?.acceptedClientMessageIds),p=r?"memory":"client",h=this.store.find(e);if(h)i=h.agent,o=h.cwd||o,a=h.approvalMode??a,l=h.pendingApproval??l,c=h.title||c,u=h.createdAt||u,d=h.lastActivityAt||d,f=ur(h.acceptedClientMessageIds,f),p="record";else if(!r){let m=(await on(n??i)).find(S=>S.sessionId===e);m&&(i=m.agent,o=m.cwd||o,c=m.title??c,u=m.createdAt,d=m.lastActivityAt,p="scanner")}if(!i&&n&&(i=n,p=r?"memory":"client"),!!i)return{agent:i,cwd:o,approvalMode:a,pendingApproval:l,title:c,createdAt:u,lastActivityAt:d,acceptedClientMessageIds:f,source:p,managed:r?.managed??h?.managed,isResponding:r?.isResponding||h?.isResponding||void 0}}collectReconnectPendingApprovals(){let e=[],n=new Set;for(let r of this.sessions.values()){if(!r.pendingApproval)continue;let s=`${r.agent}:${r.sessionId}:${r.pendingApproval.requestId}`;n.has(s)||(n.add(s),e.push(Fc(r.sessionId,r.agent,r.pendingApproval)))}for(let r of this.store.getAll()){if(!r.pendingApproval)continue;let s=`${r.agent}:${r.sessionId}:${r.pendingApproval.requestId}`;n.has(s)||(n.add(s),e.push(Fc(r.sessionId,r.agent,r.pendingApproval)))}return e}restoreDriverPendingApproval(e,n){n&&e.restorePendingApproval?.(n)}async reviveSessionForApproval(e){if(e.driver)return!0;if(!e.pendingApproval||e.agent!=="codex")return!1;let n=this.createDriver(e.agent),r=this.configureDriverBeforeStart(e.agent,n,e.claudeHookSecret);return await n.start(e.cwd,e.sessionId,e.approvalMode),this.restoreDriverPendingApproval(n,e.pendingApproval),e.driver=n,e.active=!0,e.isResponding=!1,e.currentReplyText="",e.startupInProgress=!1,e.bufferedPrompts=e.bufferedPrompts??[],e.startupToken=e.startupToken??0,e.claudeHookSecret=r??e.claudeHookSecret,e.pendingClaudeHookApprovals=e.pendingClaudeHookApprovals??new Map,this.registerClaudeHookSession(e),this.bindDriverLifecycle(e,e.agent," (approval resumed)"),this.store.upsert(ce(e)),this.updateGauges(),this.touchSession(e.sessionId),!0}buildPushBody(e){let n=e.replace(/\s+/g," ").trim();return n?n.length<=Dc?n:`${n.slice(0,Math.max(1,Dc-3)).trimEnd()}...`:om}currentPartialReplyText(e){return e?.isResponding&&e.currentReplyText.trim()?e.currentReplyText:void 0}touchSession(e,n=!0){let r=new Date().toISOString(),s=this.sessions.get(e);if(s){s.lastActivityAt=r,s.lastActivityTs=Date.now(),n&&this.store.upsert(ce(s));return}let i=this.store.find(e);i&&this.store.upsert({...i,lastActivityAt:r})}updateGauges(){let e=0;for(let n of this.sessions.values())n.active&&e++;w.gauge("session.active",e)}activeSessionSnapshots(){let e=[];for(let n of this.sessions.values())n.sessionId.startsWith("pending_")||n.active&&e.push({sessionId:n.sessionId,agent:n.agent,cwd:n.cwd,approvalMode:n.approvalMode,title:n.title,createdAt:n.createdAt,lastActivityAt:n.lastActivityAt,...n.pendingApproval?{needsAttention:!0}:{},...n.isResponding?{isResponding:!0}:{},managed:n.managed});return e}getDeletedSessionIds(){return new Set(this.store.getDeletedSessionIds())}isDeletedSession(e){return this.store.isDeleted(e)}async listRecentSessionsForContinue(e,n){return on(e,n)}async handle(e,n){switch(b.debug({action:n.action},"handling client message"),n.action){case"session.create":await this.createSession(e,n.id,n.agent,n.cwd,n.approvalMode,n.continueSession);break;case"session.resume":await this.resumeSession(e,n.id,n.sessionId,n.agent);break;case"session.send":await this.sendMessage(e,n.id,n.sessionId,n.message,n.agent,n.clientMessageId);break;case"session.approve":await this.approve(e,n.id,n.sessionId,n.requestId,n.approved);break;case"session.setApprovalMode":await this.setApprovalMode(e,n.id,n.sessionId,n.approvalMode);break;case"session.interrupt":this.interrupt(e,n.id,n.sessionId);break;case"session.stop":this.stopSession(e,n.id,n.sessionId);break;case"session.delete":this.deleteSession(e,n.id,n.sessionId);break;case"session.history":await this.sendHistory(e,n.id,n.sessionId,n.agent);break;case"reconnect.snapshot":await this.sendReconnectSnapshot(e,n.id,n.agent,n.cwd,n.search,n.activeSessionId,n.activeAgent);break;case"sessions.list":await this.listSessions(e,n.id,n.agent,n.cwd,n.search,n.limit,n.cursor);break}}removeClient(e){for(let n of this.sessions.values())n.clients.delete(e)}shutdown(){this.stopIdleSweep();for(let e of this.sessions.values()){try{this.resolvePendingClaudeHookApprovals(e),e.driver?.stop()}catch(n){b.error({sessionId:e.sessionId,agent:e.agent,error:String(n)},"failed to stop session on shutdown")}e.active=!1,e.driver=null,e.clients.clear(),this.unregisterClaudeHookSession(e)}this.claudeHookSessions.clear(),this.store.flushSync()}getActiveSessionCount(){let e=0;for(let n of this.sessions.values())n.active&&e++;return e}prewarmCaches(){nr({limit:50,activeSessions:this.activeSessionSnapshots(),sessionRecords:this.store.getAll(),deletedSessionIds:this.getDeletedSessionIds()}).catch(()=>{})}getDriverCounts(){let e={};for(let n of this.sessions.values())n.active&&(e[n.agent]=(e[n.agent]??0)+1);return e}async createSession(e,n,r,s,i,o){s=ar(s),b.info({agent:r,cwd:s,approvalMode:i,continueSession:o},"creating session");try{if(!(await(0,qc.stat)(s)).isDirectory()){this.reply(e,n,!1,void 0,`Path is not a directory: ${s}`);return}}catch{this.reply(e,n,!1,void 0,`Directory does not exist: ${s}`);return}if(o)try{let l=(await this.listRecentSessionsForContinue(r,s)).find(c=>!this.isDeletedSession(c.sessionId));if(l)return b.info({sessionId:l.sessionId,cwd:s},"continue mode: resuming last session"),this.resumeSession(e,n,l.sessionId,r,s,i);b.info("continue mode: no previous sessions found, creating new")}catch(a){b.warn({error:String(a)},"continue mode: error finding sessions, creating new")}try{let a=this.createDriver(r),l=this.configureDriverBeforeStart(r,a);if(r==="codex"){let p=`pending_${Date.now()}`;b.info({sessionId:p,agent:r,cwd:s},"session created (pending codex startup)"),w.increment("session.create",{agent:r}),_.emit("session.create",{sessionId:p,agent:r,cwd:s,approvalMode:i});let h={sessionId:p,agent:r,cwd:s,approvalMode:i,driver:a,clients:new Set([e]),title:"New session",createdAt:new Date().toISOString(),lastActivityAt:new Date().toISOString(),active:!0,lastActivityTs:Date.now(),isResponding:!1,currentReplyText:"",acceptedClientMessageIds:[],syntheticApprovalRetries:{},startupInProgress:!0,bufferedPrompts:[],startupToken:1,managed:!0,claudeHookSecret:l,pendingClaudeHookApprovals:new Map};this.sessions.set(p,h),this.registerClaudeHookSession(h),this.store.upsert(ce(h)),this.updateGauges(),ir(),er(),this.bindDriverLifecycle(h,r,"",e),this.reply(e,n,!0,{sessionId:p}),this.startPendingCodexSession(h,e);return}let c=w.startTimer("driver.spawn"),u=await a.start(s,void 0,i),d=c();b.info({sessionId:u,agent:r,spawnMs:d},"session created"),w.increment("session.create",{agent:r}),_.emit("session.create",{sessionId:u,agent:r,cwd:s,approvalMode:i});let f={sessionId:u,agent:r,cwd:s,approvalMode:i,driver:a,clients:new Set([e]),title:"New session",createdAt:new Date().toISOString(),lastActivityAt:new Date().toISOString(),active:!0,lastActivityTs:Date.now(),isResponding:!1,currentReplyText:"",acceptedClientMessageIds:[],syntheticApprovalRetries:{},startupInProgress:!1,bufferedPrompts:[],startupToken:0,managed:!0,claudeHookSecret:l,pendingClaudeHookApprovals:new Map};this.sessions.set(u,f),this.registerClaudeHookSession(f),this.store.upsert(ce(f)),this.updateGauges(),ir(),er(),this.bindDriverLifecycle(f,r,"",e),this.reply(e,n,!0,{sessionId:u})}catch(a){b.error({agent:r,cwd:s,error:String(a)},"createSession error"),this.reply(e,n,!1,void 0,String(a))}}async resumeSession(e,n,r,s,i,o){if(this.isDeletedSession(r)){this.reply(e,n,!1,void 0,"Session not found");return}let a=this.sessions.get(r);if(a&&a.active){a.clients.add(e),this.touchSession(a.sessionId);let f=await an(r,s,a.cwd),p=this.currentPartialReplyText(a);if(f.length>0||p||a.approvalMode||a.pendingApproval){let h={type:"session.history",sessionId:r,messages:f,isResponding:a.isResponding||void 0,partialReplyText:p,approvalMode:a.approvalMode,pendingApproval:a.pendingApproval};e.readyState===1&&e.send(JSON.stringify(h))}this.reply(e,n,!0,{sessionId:r});return}let l=this.store.find(r),c=i||l?.cwd||"",u=o??l?.approvalMode,d=l?.title??"Resumed session";try{let f=w.startTimer("driver.spawn"),p=this.createDriver(s),h=this.configureDriverBeforeStart(s,p),g=await p.start(c,r,u),m=f();b.info({sessionId:g,agent:s,spawnMs:m},"session resumed"),w.increment("session.resume",{agent:s}),_.emit("session.resume",{sessionId:g,agent:s,cwd:c});let S={sessionId:g,agent:s,cwd:c,approvalMode:u,driver:p,clients:new Set([e]),title:d,createdAt:l?.createdAt??new Date().toISOString(),lastActivityAt:new Date().toISOString(),active:!0,lastActivityTs:Date.now(),isResponding:!1,currentReplyText:"",acceptedClientMessageIds:l?.acceptedClientMessageIds??[],syntheticApprovalRetries:{},startupInProgress:!1,bufferedPrompts:[],startupToken:0,managed:l?.managed,pendingApproval:l?.pendingApproval,claudeHookSecret:h,pendingClaudeHookApprovals:new Map};this.sessions.set(g,S),this.registerClaudeHookSession(S),this.store.upsert(ce(S)),this.updateGauges(),this.bindDriverLifecycle(S,s," (resumed)",e),this.restoreDriverPendingApproval(p,S.pendingApproval);let P=await an(r,s,c);if(P.length>0||S.pendingApproval){b.info({sessionId:r,historyCount:P.length},"sending history messages");let se={type:"session.history",sessionId:g,messages:P,approvalMode:u,pendingApproval:S.pendingApproval};e.readyState===1&&e.send(JSON.stringify(se))}this.reply(e,n,!0,{sessionId:g})}catch(f){this.reply(e,n,!1,void 0,String(f))}}hasAcceptedClientMessage(e,n){return e.acceptedClientMessageIds.includes(n)}rememberAcceptedClientMessage(e,n){this.hasAcceptedClientMessage(e,n)||(e.acceptedClientMessageIds.push(n),e.acceptedClientMessageIds.length>dr&&e.acceptedClientMessageIds.splice(0,e.acceptedClientMessageIds.length-dr))}async sendMessage(e,n,r,s,i,o){if(this.isDeletedSession(r)){this.reply(e,n,!1,void 0,"Session not found");return}let a=this.sessions.get(r);if(!a||!a.driver){let l=await this.resolveReconnectSession(r,i,a);if(!l){b.warn({sessionId:r},"session not found in records or scanner"),this.reply(e,n,!1,void 0,"Session not found");return}b.info({sessionId:r,agent:l.agent,source:l.source},"auto-reconnecting session"),w.increment("session.reconnect",{agent:l.agent,source:l.source}),_.emit("session.reconnect",{sessionId:r,agent:l.agent,source:l.source});try{let c=this.createDriver(l.agent),u=this.configureDriverBeforeStart(l.agent,c,a?.claudeHookSecret);await c.start(l.cwd,r,l.approvalMode),this.restoreDriverPendingApproval(c,l.pendingApproval),a?(a.approvalMode=l.approvalMode,a.pendingApproval=l.pendingApproval,a.driver=c,a.active=!0,a.clients.add(e),a.lastActivityAt=l.lastActivityAt,a.lastActivityTs=Date.now(),a.isResponding=!1,a.currentReplyText="",a.acceptedClientMessageIds=ur(a.acceptedClientMessageIds,l.acceptedClientMessageIds),a.syntheticApprovalRetries=a.syntheticApprovalRetries??{},a.startupInProgress=!1,a.bufferedPrompts=a.bufferedPrompts??[],a.startupToken=a.startupToken??0,a.claudeHookSecret=u??a.claudeHookSecret,a.pendingClaudeHookApprovals=a.pendingClaudeHookApprovals??new Map):(a={sessionId:r,agent:l.agent,cwd:l.cwd,approvalMode:l.approvalMode,driver:c,clients:new Set([e]),title:l.title,createdAt:l.createdAt,lastActivityAt:l.lastActivityAt,active:!0,lastActivityTs:Date.now(),isResponding:!1,currentReplyText:"",acceptedClientMessageIds:l.acceptedClientMessageIds,syntheticApprovalRetries:{},startupInProgress:!1,bufferedPrompts:[],startupToken:0,managed:l.managed,pendingApproval:l.pendingApproval,claudeHookSecret:u,pendingClaudeHookApprovals:new Map},this.sessions.set(r,a)),this.registerClaudeHookSession(a),this.bindDriverLifecycle(a,l.agent," (reconnected)"),this.store.upsert(ce(a)),this.updateGauges()}catch(c){this.reply(e,n,!1,void 0,`Failed to reconnect: ${c}`);return}}if(a.clients.add(e),a.pendingApproval){this.reply(e,n,!1,void 0,"Resolve the pending approval before sending another message.");return}if(o&&this.hasAcceptedClientMessage(a,o)){this.reply(e,n,!0,{sessionId:r,clientMessageId:o,duplicate:!0});return}if(b.info({sessionId:r,clients:a.clients.size,hasDriver:!!a.driver,active:a.active},"sending message"),_.emit("session.send",{sessionId:r,agent:a.agent,messagePreview:s.slice(0,100)}),pt(a.title)){let l=Fs(s,50);l&&l!==a.title&&(a.title=l),this.store.upsert(ce(a))}if(o&&this.rememberAcceptedClientMessage(a,o),this.touchSession(a.sessionId),a.startupInProgress){a.isResponding=!0,a.currentReplyText="",a.lastUserMessage=s,a.bufferedPrompts.push(s),this.reply(e,n,!0,o?{sessionId:r,clientMessageId:o}:void 0);return}if(a.isResponding){a.bufferedPrompts.push(s),this.reply(e,n,!0,o?{sessionId:r,clientMessageId:o}:void 0);return}a.isResponding=!0,a.currentReplyText="",a.lastUserMessage=s,a.driver.sendPrompt(s),this.reply(e,n,!0,o?{sessionId:r,clientMessageId:o}:void 0)}async sendReconnectSnapshot(e,n,r,s,i,o,a){try{let l=this.getDeletedSessionIds(),c;try{c=await nr({agent:r,cwd:s,search:i,limit:50,activeSessions:this.activeSessionSnapshots(),sessionRecords:this.store.getAll(),deletedSessionIds:l})}catch(f){b.warn({error:String(f)},"failed to build reconnect snapshot session list"),c={sessions:[],nextCursor:void 0}}let u;if(o&&!l.has(o)){let f=a??c.sessions.find(g=>g.sessionId===o)?.agent,p=this.sessions.get(o);p&&p.clients.add(e);let h=await this.resolveReconnectSession(o,f,p);if(h){let g=await an(o,h.agent,p?.cwd??h.cwd);u={sessionId:o,agent:h.agent,messages:g,isResponding:p?.isResponding||h.isResponding||void 0,partialReplyText:this.currentPartialReplyText(p),approvalMode:p?.approvalMode??h.approvalMode,...p?.pendingApproval?{pendingApproval:p.pendingApproval}:{}}}}let d=this.collectReconnectPendingApprovals();w.increment("reconnect.snapshot",{activeSession:u?"true":"false"}),this.reply(e,n,!0,{snapshot:{sessions:c.sessions,nextCursor:c.nextCursor,...u?{activeSession:u}:{},...d.length>0?{pendingApprovals:d}:{}}})}catch(l){this.reply(e,n,!1,void 0,`Failed to build reconnect snapshot: ${String(l)}`)}}async approve(e,n,r,s,i){let o=this.sessions.get(r),a=o?.pendingApproval,l=o?.pendingClaudeHookApprovals.get(s);if(o&&l){o.pendingApproval=void 0,_.emit("approval.response",{sessionId:r,requestId:s,approved:i}),this.touchSession(o.sessionId),l.resolve(Uc(i)),o.isResponding=!0,this.reply(e,n,!0);return}let c=o?.syntheticApprovalRetries[s];if(o&&c&&Kn(s)){delete o.syntheticApprovalRetries[s],o.pendingApproval=void 0,_.emit("approval.response",{sessionId:r,requestId:s,approved:i}),this.touchSession(o.sessionId),this.reply(e,n,!0),i&&await this.retrySyntheticClaudeApproval(o,c);return}if(o&&!o.driver&&a)try{await this.reviveSessionForApproval(o)}catch(d){this.reply(e,n,!1,void 0,`Failed to restore approval session: ${String(d)}`);return}if(!o?.driver){this.reply(e,n,!1,void 0,"Session not found or inactive");return}if(_.emit("approval.response",{sessionId:r,requestId:s,approved:i}),!o.driver.respondApproval(s,i)){this.reply(e,n,!1,void 0,"Agent process is not running. Send a new message to continue.");return}o.pendingApproval=void 0,this.touchSession(o.sessionId),o.isResponding=!0,this.reply(e,n,!0)}async retrySyntheticClaudeApproval(e,n){if(e.agent==="claude")try{e.driver&&e.driver.stop();let r=["Write","Edit","NotebookEdit"].includes(n.toolName)?"acceptEdits":"autoApprove",s=this.createDriver(e.agent),i=this.configureDriverBeforeStart(e.agent,s,e.claudeHookSecret);await s.start(e.cwd,e.sessionId,r),e.driver=s,e.active=!0,e.isResponding=!0,e.currentReplyText="",e.lastUserMessage=n.message,e.startupInProgress=!1,e.bufferedPrompts=[],e.startupToken=0,e.claudeHookSecret=i??e.claudeHookSecret,e.pendingClaudeHookApprovals=e.pendingClaudeHookApprovals??new Map,this.registerClaudeHookSession(e),this.bindDriverLifecycle(e,e.agent," (approval retry)"),this.store.upsert(ce(e)),this.updateGauges(),this.touchSession(e.sessionId),b.info({sessionId:e.sessionId,toolName:n.toolName,retryApprovalMode:r},"retrying Claude turn after synthetic approval"),s.sendPrompt(n.message)}catch(r){e.driver=null,e.active=!1,e.isResponding=!1,e.startupInProgress=!1,e.bufferedPrompts=[],e.startupToken+=1,this.updateGauges(),this.touchSession(e.sessionId),b.error({sessionId:e.sessionId,error:String(r)},"failed to retry Claude turn after approval"),this.broadcast(e.sessionId,{type:"error",sessionId:e.sessionId,message:`Failed to continue after approval: ${String(r)}`})}}async setApprovalMode(e,n,r,s){let i=this.sessions.get(r);if(!i){let a=this.store.find(r);a?(a.approvalMode=s,this.store.upsert(a),b.info({sessionId:r,agent:a.agent,newMode:s},"approval mode changed (inactive session)")):b.info({sessionId:r,newMode:s},"approval mode changed (untracked session)"),this.reply(e,n,!0,{approvalMode:s});return}let o=i.approvalMode;i.approvalMode=s,this.store.upsert(ce(i)),b.info({sessionId:r,agent:i.agent,oldMode:o,newMode:s},"approval mode changed"),i.driver&&i.driver.setApprovalMode(s),this.reply(e,n,!0,{approvalMode:s})}interrupt(e,n,r){let s=this.sessions.get(r);if(!s?.driver){this.reply(e,n,!1,void 0,"Session not found or inactive");return}_.emit("session.interrupt",{sessionId:r,agent:s.agent}),s.driver.interrupt(),this.reply(e,n,!0)}stopSession(e,n,r){let s=this.sessions.get(r);if(!s){this.reply(e,n,!1,void 0,"Session not found");return}b.info({sessionId:r,agent:s.agent},"stopping session"),_.emit("session.stop",{sessionId:r,agent:s.agent}),this.resolvePendingClaudeHookApprovals(s),s.driver?.stop(),s.active=!1,s.driver=null,s.pendingApproval=void 0,s.startupInProgress=!1,s.bufferedPrompts=[],s.startupToken+=1,this.updateGauges(),this.touchSession(s.sessionId),this.reply(e,n,!0)}deleteSession(e,n,r){let s=this.sessions.get(r);s&&(b.info({sessionId:r,agent:s.agent},"deleting session"),this.resolvePendingClaudeHookApprovals(s),s.driver?.stop(),s.startupInProgress=!1,s.bufferedPrompts=[],s.startupToken+=1,this.unregisterClaudeHookSession(s),this.sessions.delete(r)),_.emit("session.delete",{sessionId:r}),this.store.remove(r),this.updateGauges(),ir(),er(),this.reply(e,n,!0)}async sendHistory(e,n,r,s){let i=this.sessions.get(r);if(!i&&this.isDeletedSession(r)){this.reply(e,n,!1,void 0,"Session not found");return}i&&i.clients.add(e);let o=i?.cwd??this.store.find(r)?.cwd??"",a=this.store.find(r),l=await an(r,s,o);b.info({sessionId:r,historyCount:l.length,isResponding:i?.isResponding,approvalMode:i?.approvalMode},"sending history");let c={type:"session.history",sessionId:r,messages:l,isResponding:i?.isResponding||void 0,partialReplyText:this.currentPartialReplyText(i),approvalMode:i?.approvalMode??a?.approvalMode,pendingApproval:i?.pendingApproval??a?.pendingApproval};e.readyState===1&&e.send(JSON.stringify(c)),this.reply(e,n,!0)}async listSessions(e,n,r,s,i,o=50,a){try{let l=await nr({agent:r,cwd:s,search:i,limit:o,cursor:a,activeSessions:this.activeSessionSnapshots(),sessionRecords:this.store.getAll(),deletedSessionIds:this.getDeletedSessionIds()});this.reply(e,n,!0,l)}catch(l){this.reply(e,n,!1,void 0,String(l))}}createDriver(e){switch(e){case"claude":return new tn;case"codex":return new Xn;default:throw new Error(`Unknown agent: ${e}`)}}broadcast(e,n){let r=this.sessions.get(e);if(!r){b.warn({sessionId:e,msgType:n.type},"broadcast target session not found");return}let s=JSON.stringify(n),i=r.clients.size,o=0,a=0;for(let l of r.clients)l.readyState===1?(l.send(s),o++):a++;if(a>0&&w.increment("broadcast.fail"),n.type!=="text.delta"&&b.debug({sessionId:e,msgType:n.type,sent:o,total:i},"broadcast"),n.type==="text.delta"){r.currentReplyText+=n.content;return}if(n.type==="session.done"){let l=r.title||e,c=this.buildPushBody(r.currentReplyText);r.currentReplyText="",this.pushSender(l,c,{sessionId:e,agent:r.agent,eventType:"reply_ready"});return}n.type==="session.interrupted"&&(r.currentReplyText="")}reply(e,n,r,s,i){if(e.readyState!==1)return;let o={type:"response",id:n,ok:r,data:s,error:i};e.send(JSON.stringify(o))}};function ii(t,e){if(!e.deviceId){e.respond({type:"response",id:t.id,ok:!1,error:"device_auth_required"});return}t.action==="push.register"?e.registerToken(e.deviceId,t.pushToken):e.unregisterToken(e.deviceId,t.pushToken),e.respond({type:"response",id:t.id,ok:!0})}var jc=require("child_process");function cm(t,e){return(0,jc.execFileSync)(t,e,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}function um(t){let e=t.split(`
97
+ `,"utf8")}var lr=class{constructor(e=Ll){this.pushSubscriptionsPath=e;this.records=Jg(e)}records;list(){return this.records.map(e=>({...e}))}listTokens(){return this.records.map(e=>e.pushToken)}count(){return this.records.length}register(e,n){let r=new Date().toISOString(),s=this.records.find(o=>o.deviceId===e),i={deviceId:e,pushToken:n,platform:"expo",createdAt:s?.createdAt??r,updatedAt:r,...s?.lastSentAt?{lastSentAt:s.lastSentAt}:{}};this.records=[i,...this.records.filter(o=>o.deviceId!==e&&o.pushToken!==n)],ln(this.pushSubscriptionsPath,this.records)}unregister(e,n){let r=this.records.filter(s=>!(s.deviceId===e&&s.pushToken===n));return r.length===this.records.length?!1:(this.records=r,ln(this.pushSubscriptionsPath,this.records),!0)}unregisterToken(e){let n=this.records.filter(r=>r.pushToken!==e);return n.length===this.records.length?!1:(this.records=n,ln(this.pushSubscriptionsPath,this.records),!0)}markSent(e){if(e.length===0)return;let n=new Set(e),r=new Date().toISOString(),s=!1;for(let i of this.records)n.has(i.pushToken)&&(i.lastSentAt=r,s=!0);s&&ln(this.pushSubscriptionsPath,this.records)}reset(){this.records=[],ln(this.pushSubscriptionsPath,this.records)}};var z=R.child({module:"push"}),Kg="https://exp.host/--/api/v2/push/send",Xg="https://exp.host/--/api/v2/push/getReceipts",Qg=[0,1e3,3e3],cn=new lr;function Zg(t){return!!(t&&typeof t=="object"&&typeof t.daemonId=="string"&&typeof t.canonicalHost=="string"&&typeof t.sessionId=="string"&&(t.agent==="claude"||t.agent==="codex")&&(t.eventType==="reply_ready"||t.eventType==="approval_request")&&(typeof t.requestId>"u"||typeof t.requestId=="string"))}function em(t){return new Promise(e=>{setTimeout(e,t)})}function Bc(t){return t==="DeviceNotRegistered"}function tm(t,e){if(!Array.isArray(t.data))return{successfulTokens:[],ticketErrors:[]};let n=[],r=[];for(let[s,i]of t.data.entries()){let o=e[s];if(!(!o||!i||typeof i!="object")){if(i.status==="ok"){n.push(o);continue}r.push({token:o,ticket:i})}}return{successfulTokens:n,ticketErrors:r}}function nm(t,e){let n=new Map;if(!Array.isArray(t.data))return n;for(let[r,s]of t.data.entries()){let i=e[r];!i||!s||s.status!=="ok"||typeof s.id!="string"||s.id.length===0||n.set(s.id,i)}return n}function rm(t,e){let n=[],r=[],s=t.data;for(let[i,o]of e.entries()){let a=s?.[i];if(!a||typeof a!="object"){n.push(i);continue}a.status==="error"&&r.push({token:o,receipt:a})}return{pendingTicketIds:n,receiptErrors:r}}async function sm(t,e,n,r){let s=new Map(t);for(let i of Qg){if(s.size===0)return;i>0&&await n(i);let o;try{o=await e(Xg,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({ids:[...s.keys()]})})}catch(u){z.error({error:String(u),count:s.size},"push receipt request failed");return}if(!o.ok){z.error({status:o.status,statusText:o.statusText,count:s.size},"push receipt request returned error status");return}let a=await o.json().catch(()=>null);if(!a){z.error({count:s.size},"push receipt response was unreadable");return}let{pendingTicketIds:l,receiptErrors:c}=rm(a,s);for(let{token:u,receipt:d}of c){let f=d.details?.error;if(z.error({token:u,message:d.message,details:d.details,receiptStatus:d.status},"push receipt rejected"),Bc(f)){let p=r.unregisterToken(u);z.info({token:u,errorCode:f,removed:p},"push token removed after receipt rejection")}}s=new Map(l.map(u=>[u,s.get(u)]))}s.size>0&&z.warn({pendingReceipts:s.size},"push receipts still pending after polling")}function im(t){let e=t?.pushStore??cn,n=t?.fetchImpl??globalThis.fetch,r=t?.sleepImpl??em;return async function(i,o,a){let l=e.listTokens();if(l.length===0)return;let c=l.map(u=>({to:u,sound:"default",title:i,body:o,data:a,...Zg(a)&&a.eventType==="approval_request"?{categoryId:Nc.approvalRequestV1}:{}}));try{let u=await n(Kg,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)});if(!u.ok){z.error({status:u.status,statusText:u.statusText},"push send failed");return}let d=await u.json().catch(()=>null);if(!d){z.error({count:c.length},"push send returned unreadable response");return}let{successfulTokens:f,ticketErrors:p}=tm(d,l),h=nm(d,l);for(let{token:g,ticket:m}of p){let S=m.details?.error;if(z.error({token:g,message:m.message,details:m.details,ticketStatus:m.status},"push ticket rejected"),Bc(S)){let P=e.unregisterToken(g);z.info({token:g,errorCode:S,removed:P},"push token removed after ticket rejection")}}f.length>0&&(z.debug({count:f.length},"push sent"),e.markSent(f)),h.size>0&&await sm(h,n,r,e)}catch(u){z.error({error:String(u)},"push send error")}}}function ni(t,e){cn.register(t,e),z.info({deviceId:t,token:e,total:cn.count()},"push token registered")}function ri(t,e){let n=cn.unregister(t,e);z.info({deviceId:t,token:e,total:cn.count(),removed:n},"push token unregistered")}var cr=im();var b=R.child({module:"manager"}),om="Done.",am="Approval required",Dc=180,dr=200;function ur(...t){let e=[];for(let n of t)if(n?.length)for(let r of n)!r||e.includes(r)||(e.push(r),e.length>dr&&e.splice(0,e.length-dr));return e}function ce(t){return{sessionId:t.sessionId,agent:t.agent,cwd:t.cwd,approvalMode:t.approvalMode,acceptedClientMessageIds:ur(t.acceptedClientMessageIds),pendingApproval:t.agent==="codex"?t.pendingApproval:void 0,title:t.title,createdAt:t.createdAt,lastActivityAt:t.lastActivityAt,managed:t.managed,isResponding:t.isResponding||void 0}}function Hc(t){let e=t.pendingApproval?.requestId;return typeof e=="string"&&Kn(e)}function Fc(t,e,n){return{sessionId:t,agent:e,...n}}function lm(t){return t.startsWith(Ms)}function Uc(t){return t?{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}:{continue:!0,suppressOutput:!0,hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"Denied from Vibelet"}}}var fr=class{constructor(e=cr){this.pushSender=e;this.startIdleSweep()}sessions=new Map;claudeHookSessions=new Map;store=new or;idleSweepInterval=null;startIdleSweep(){v.idleTimeoutMs<=0&&v.turnStallTimeoutMs<=0||(this.idleSweepInterval=setInterval(()=>this.sweepIdleSessions(),6e4),this.idleSweepInterval.unref())}stopIdleSweep(){this.idleSweepInterval&&(clearInterval(this.idleSweepInterval),this.idleSweepInterval=null)}sweepIdleSessions(){let e=Date.now(),n=v.idleTimeoutMs,r=v.turnStallTimeoutMs;if(n<=0&&r<=0)return;let s=3600*1e3;for(let[i,o]of this.sessions){if(!o.active&&!o.driver){if(o.clients.size===0){let l=e-o.lastActivityTs;l>=s&&(b.info({sessionId:o.sessionId,inactiveMs:l},"removing inactive session from memory"),w.increment("session.cleanup",{reason:"inactive"}),this.unregisterClaudeHookSession(o),this.sessions.delete(i))}continue}if(!o.active||!o.driver)continue;let a=e-o.lastActivityTs;if(o.isResponding){if(r<=0||o.pendingApproval||a<r)continue;b.warn({sessionId:o.sessionId,agent:o.agent,inactiveMs:a,turnStallTimeoutMs:r},"stopping stalled driver"),w.increment("driver.stall_timeout",{agent:o.agent}),_.emit("driver.stall_timeout",{sessionId:o.sessionId,agent:o.agent,idleMs:a}),o.isResponding=!1,o.currentReplyText="",this.broadcast(o.sessionId,{type:"error",sessionId:o.sessionId,message:`Agent stopped responding for over ${Math.ceil(r/1e3)}s. Send a new message to continue.`}),o.driver.stop(),o.active=!1,o.driver=null,this.updateGauges(),this.touchSession(o.sessionId);continue}o.pendingApproval||n<=0||a<n||(b.info({sessionId:o.sessionId,agent:o.agent,idleMs:a,timeoutMs:n},"stopping idle driver"),w.increment("driver.idle_timeout",{agent:o.agent}),_.emit("driver.idle_timeout",{sessionId:o.sessionId,agent:o.agent,idleMs:a}),o.driver.stop(),o.active=!1,o.driver=null,this.updateGauges(),this.touchSession(o.sessionId))}}bindDriverLifecycle(e,n,r,s){e.driver?.onMessage(i=>{if(b.debug({agent:n,context:r,msgType:i.type,sessionId:e.sessionId},"driver message received"),i.type!=="response"&&i.sessionId&&i.sessionId!==e.sessionId&&!this.sessions.has(i.sessionId)&&this.remapSessionId(e,i.sessionId,s),(i.type==="session.done"||i.type==="session.interrupted")&&(e.isResponding=!1,(i.type==="session.interrupted"||!Hc(e))&&(e.pendingApproval=void 0)),i.type==="approval.request"){if(n==="codex"&&e.approvalMode==="autoApprove"){if(e.driver?.respondApproval(i.requestId,!0)??!1){_.emit("approval.response",{sessionId:e.sessionId,requestId:i.requestId,approved:!0}),e.pendingApproval=void 0,e.isResponding=!0,this.touchSession(e.sessionId);return}b.warn({sessionId:e.sessionId,requestId:i.requestId},"failed to auto-approve codex request; falling back to pending approval flow")}e.isResponding=!1,e.pendingApproval={requestId:i.requestId,toolName:i.toolName,input:i.input,description:i.description,...i.approvalContext?{approvalContext:i.approvalContext}:{}},this.pushSender(am,this.buildPushBody(`${e.title||e.sessionId}: ${i.description||i.toolName}`),{sessionId:e.sessionId,agent:e.agent,requestId:i.requestId,eventType:"approval_request"})}n==="claude"&&i.type==="approval.request"&&Kn(i.requestId)&&(e.lastUserMessage?e.syntheticApprovalRetries[i.requestId]={message:e.lastUserMessage,toolName:i.toolName}:b.warn({sessionId:e.sessionId,requestId:i.requestId},"missing lastUserMessage for synthetic approval retry")),this.touchSession(e.sessionId,i.type!=="text.delta"),this.broadcast(e.sessionId,i),(i.type==="session.done"||i.type==="session.interrupted")&&e.bufferedPrompts.length>0&&this.flushBufferedPrompt(e)}),e.driver?.onExit?.(i=>{b.info({agent:n,context:r,exitCode:i,sessionId:e.sessionId},"driver exited"),_.emit("driver.exit",{sessionId:e.sessionId,agent:n,exitCode:i}),w.increment("driver.exit",{agent:n,abnormal:i&&i!==0?"true":"false"});let o=!!(e.pendingApproval&&(e.agent==="codex"||i===0&&Hc(e)));this.resolvePendingClaudeHookApprovals(e),e.active=!1,e.driver=null,e.isResponding=!1,e.currentReplyText="",o||(e.pendingApproval=void 0),this.updateGauges(),this.touchSession(e.sessionId)})}remapSessionId(e,n,r){if(!n||n===e.sessionId)return;let s=this.sessions.get(n);if(s&&s!==e){b.warn({oldSessionId:e.sessionId,newSessionId:n},"skipping session ID remap because target already exists");return}let i=e.sessionId;b.info({oldSessionId:i,newSessionId:n},"session ID updated"),this.store.remove(i),this.sessions.delete(i),e.sessionId=n,this.sessions.set(n,e),this.store.upsert(ce(e)),r&&this.reply(r,`id_update_${Date.now()}`,!0,{sessionId:n,oldSessionId:i})}flushBufferedPrompt(e,n=!1){if(!e.driver||!e.active||e.startupInProgress||e.pendingApproval||!n&&e.isResponding)return!1;let r=e.bufferedPrompts.shift();return r?(e.isResponding=!0,e.currentReplyText="",e.lastUserMessage=r,this.touchSession(e.sessionId),e.driver.sendPrompt(r),!0):!1}startPendingCodexSession(e,n){if(e.agent!=="codex"||!e.driver)return;let r=e.driver,s=e.sessionId,i=e.startupToken,o=w.startTimer("driver.spawn");(async()=>{try{let a=await r.start(e.cwd,void 0,e.approvalMode),l=o();if(this.sessions.get(s)!==e||e.startupToken!==i||e.driver!==r){b.info({pendingSessionId:s,actualSessionId:a},"discarding stale codex startup result");return}e.startupInProgress=!1,b.info({pendingSessionId:s,sessionId:a,spawnMs:l},"codex session ready"),a&&a!==s&&this.remapSessionId(e,a,n),this.flushBufferedPrompt(e,!0)}catch(a){if(o(),this.sessions.get(s)!==e||e.startupToken!==i){b.info({pendingSessionId:s,error:String(a)},"ignoring stale codex startup failure");return}e.startupInProgress=!1,e.bufferedPrompts=[],e.active=!1,e.driver=null,e.isResponding=!1,e.currentReplyText="",this.updateGauges(),this.touchSession(e.sessionId),b.error({sessionId:s,cwd:e.cwd,error:String(a)},"async codex createSession error"),this.broadcast(e.sessionId,{type:"error",sessionId:e.sessionId,message:`Failed to start Codex session: ${String(a)}`})}})()}configureDriverBeforeStart(e,n,r){if(e!=="claude"||!(n instanceof tn))return;let s=r??(0,si.randomUUID)().replace(/-/g,"");return n.configureHookBridge(v.port,s),s}registerClaudeHookSession(e){e.agent!=="claude"||!e.claudeHookSecret||this.claudeHookSessions.set(e.claudeHookSecret,e)}unregisterClaudeHookSession(e){if(e.agent!=="claude"||!e.claudeHookSecret)return;this.claudeHookSessions.get(e.claudeHookSecret)===e&&this.claudeHookSessions.delete(e.claudeHookSecret)}resolvePendingClaudeHookApprovals(e,n=en){for(let r of e.pendingClaudeHookApprovals.values())r.resolve(n);e.pendingClaudeHookApprovals.clear(),e.pendingApproval&&lm(e.pendingApproval.requestId)&&(e.pendingApproval=void 0)}resolveClaudeHookSession(e){if(!e)return;let n=e.trim();if(n)return this.claudeHookSessions.get(n)}handleClaudeSessionStartHook(e,n){let r=this.resolveClaudeHookSession(e);return r?(this.touchSession(r.sessionId),!0):(b.warn({secretPresent:!!e},"received Claude session-start hook for unknown session"),!1)}async handleClaudePermissionHook(e,n){let r=this.resolveClaudeHookSession(e);if(!r||r.agent!=="claude"||!r.active)return b.warn({secretPresent:!!e},"received Claude permission hook for unknown or inactive session"),en;if(r.approvalMode==="autoApprove")return Uc(!0);let i=(typeof n.tool_name=="string"?n.tool_name:typeof n.toolName=="string"?n.toolName:"").trim();if(!i)return en;let o=n.tool_input??n.toolInput,a=o&&typeof o=="object"&&!Array.isArray(o)?o:{},l=typeof n.tool_use_id=="string"?n.tool_use_id:typeof n.toolUseId=="string"?n.toolUseId:"",c=`${Ms}${l.trim()||(0,si.randomUUID)()}`,u=r.pendingClaudeHookApprovals.get(c);if(u)return u.promise;let d=`Claude requested permissions to use ${i}.`,f,p=new Promise(h=>{f=h});return r.pendingClaudeHookApprovals.set(c,{requestId:c,promise:p,resolve:h=>{r.pendingClaudeHookApprovals.delete(c),f(h)}}),r.pendingApproval={requestId:c,toolName:i,input:a,description:d},_.emit("approval.request",{agent:"claude",sessionId:r.sessionId,toolName:i}),this.touchSession(r.sessionId),this.broadcast(r.sessionId,{type:"approval.request",sessionId:r.sessionId,requestId:c,toolName:i,input:a,description:d}),p}async resolveReconnectSession(e,n,r){if(this.isDeletedSession(e))return;let s=new Date().toISOString(),i=r?.agent,o=r?.cwd??"",a=r?.approvalMode,l=r?.pendingApproval,c=r?.title??"",u=r?.createdAt??s,d=r?.lastActivityAt??s,f=ur(r?.acceptedClientMessageIds),p=r?"memory":"client",h=this.store.find(e);if(h)i=h.agent,o=h.cwd||o,a=h.approvalMode??a,l=h.pendingApproval??l,c=h.title||c,u=h.createdAt||u,d=h.lastActivityAt||d,f=ur(h.acceptedClientMessageIds,f),p="record";else if(!r){let m=(await on(n??i)).find(S=>S.sessionId===e);m&&(i=m.agent,o=m.cwd||o,c=m.title??c,u=m.createdAt,d=m.lastActivityAt,p="scanner")}if(!i&&n&&(i=n,p=r?"memory":"client"),!!i)return{agent:i,cwd:o,approvalMode:a,pendingApproval:l,title:c,createdAt:u,lastActivityAt:d,acceptedClientMessageIds:f,source:p,managed:r?.managed??h?.managed,isResponding:r?.isResponding||void 0}}collectReconnectPendingApprovals(){let e=[],n=new Set;for(let r of this.sessions.values()){if(!r.pendingApproval)continue;let s=`${r.agent}:${r.sessionId}:${r.pendingApproval.requestId}`;n.has(s)||(n.add(s),e.push(Fc(r.sessionId,r.agent,r.pendingApproval)))}for(let r of this.store.getAll()){if(!r.pendingApproval)continue;let s=`${r.agent}:${r.sessionId}:${r.pendingApproval.requestId}`;n.has(s)||(n.add(s),e.push(Fc(r.sessionId,r.agent,r.pendingApproval)))}return e}restoreDriverPendingApproval(e,n){n&&e.restorePendingApproval?.(n)}async reviveSessionForApproval(e){if(e.driver)return!0;if(!e.pendingApproval||e.agent!=="codex")return!1;let n=this.createDriver(e.agent),r=this.configureDriverBeforeStart(e.agent,n,e.claudeHookSecret);return await n.start(e.cwd,e.sessionId,e.approvalMode),this.restoreDriverPendingApproval(n,e.pendingApproval),e.driver=n,e.active=!0,e.isResponding=!1,e.currentReplyText="",e.startupInProgress=!1,e.bufferedPrompts=e.bufferedPrompts??[],e.startupToken=e.startupToken??0,e.claudeHookSecret=r??e.claudeHookSecret,e.pendingClaudeHookApprovals=e.pendingClaudeHookApprovals??new Map,this.registerClaudeHookSession(e),this.bindDriverLifecycle(e,e.agent," (approval resumed)"),this.store.upsert(ce(e)),this.updateGauges(),this.touchSession(e.sessionId),!0}buildPushBody(e){let n=e.replace(/\s+/g," ").trim();return n?n.length<=Dc?n:`${n.slice(0,Math.max(1,Dc-3)).trimEnd()}...`:om}currentPartialReplyText(e){return e?.isResponding&&e.currentReplyText.trim()?e.currentReplyText:void 0}touchSession(e,n=!0){let r=new Date().toISOString(),s=this.sessions.get(e);if(s){s.lastActivityAt=r,s.lastActivityTs=Date.now(),n&&this.store.upsert(ce(s));return}let i=this.store.find(e);i&&this.store.upsert({...i,lastActivityAt:r})}updateGauges(){let e=0;for(let n of this.sessions.values())n.active&&e++;w.gauge("session.active",e)}activeSessionSnapshots(){let e=[];for(let n of this.sessions.values())n.sessionId.startsWith("pending_")||n.active&&e.push({sessionId:n.sessionId,agent:n.agent,cwd:n.cwd,approvalMode:n.approvalMode,title:n.title,createdAt:n.createdAt,lastActivityAt:n.lastActivityAt,...n.pendingApproval?{needsAttention:!0}:{},...n.isResponding?{isResponding:!0}:{},managed:n.managed});return e}getDeletedSessionIds(){return new Set(this.store.getDeletedSessionIds())}isDeletedSession(e){return this.store.isDeleted(e)}async listRecentSessionsForContinue(e,n){return on(e,n)}async handle(e,n){switch(b.debug({action:n.action},"handling client message"),n.action){case"session.create":await this.createSession(e,n.id,n.agent,n.cwd,n.approvalMode,n.continueSession);break;case"session.resume":await this.resumeSession(e,n.id,n.sessionId,n.agent);break;case"session.send":await this.sendMessage(e,n.id,n.sessionId,n.message,n.agent,n.clientMessageId);break;case"session.approve":await this.approve(e,n.id,n.sessionId,n.requestId,n.approved);break;case"session.setApprovalMode":await this.setApprovalMode(e,n.id,n.sessionId,n.approvalMode);break;case"session.interrupt":this.interrupt(e,n.id,n.sessionId);break;case"session.stop":this.stopSession(e,n.id,n.sessionId);break;case"session.delete":this.deleteSession(e,n.id,n.sessionId);break;case"session.history":await this.sendHistory(e,n.id,n.sessionId,n.agent);break;case"reconnect.snapshot":await this.sendReconnectSnapshot(e,n.id,n.agent,n.cwd,n.search,n.activeSessionId,n.activeAgent);break;case"sessions.list":await this.listSessions(e,n.id,n.agent,n.cwd,n.search,n.limit,n.cursor);break}}removeClient(e){for(let n of this.sessions.values())n.clients.delete(e)}shutdown(){this.stopIdleSweep();for(let e of this.sessions.values()){try{this.resolvePendingClaudeHookApprovals(e),e.driver?.stop()}catch(n){b.error({sessionId:e.sessionId,agent:e.agent,error:String(n)},"failed to stop session on shutdown")}e.active=!1,e.driver=null,e.clients.clear(),this.unregisterClaudeHookSession(e)}this.claudeHookSessions.clear(),this.store.flushSync()}getActiveSessionCount(){let e=0;for(let n of this.sessions.values())n.active&&e++;return e}prewarmCaches(){nr({limit:50,activeSessions:this.activeSessionSnapshots(),sessionRecords:this.store.getAll(),deletedSessionIds:this.getDeletedSessionIds()}).catch(()=>{})}getDriverCounts(){let e={};for(let n of this.sessions.values())n.active&&(e[n.agent]=(e[n.agent]??0)+1);return e}async createSession(e,n,r,s,i,o){s=ar(s),b.info({agent:r,cwd:s,approvalMode:i,continueSession:o},"creating session");try{if(!(await(0,qc.stat)(s)).isDirectory()){this.reply(e,n,!1,void 0,`Path is not a directory: ${s}`);return}}catch{this.reply(e,n,!1,void 0,`Directory does not exist: ${s}`);return}if(o)try{let l=(await this.listRecentSessionsForContinue(r,s)).find(c=>!this.isDeletedSession(c.sessionId));if(l)return b.info({sessionId:l.sessionId,cwd:s},"continue mode: resuming last session"),this.resumeSession(e,n,l.sessionId,r,s,i);b.info("continue mode: no previous sessions found, creating new")}catch(a){b.warn({error:String(a)},"continue mode: error finding sessions, creating new")}try{let a=this.createDriver(r),l=this.configureDriverBeforeStart(r,a);if(r==="codex"){let p=`pending_${Date.now()}`;b.info({sessionId:p,agent:r,cwd:s},"session created (pending codex startup)"),w.increment("session.create",{agent:r}),_.emit("session.create",{sessionId:p,agent:r,cwd:s,approvalMode:i});let h={sessionId:p,agent:r,cwd:s,approvalMode:i,driver:a,clients:new Set([e]),title:"New session",createdAt:new Date().toISOString(),lastActivityAt:new Date().toISOString(),active:!0,lastActivityTs:Date.now(),isResponding:!1,currentReplyText:"",acceptedClientMessageIds:[],syntheticApprovalRetries:{},startupInProgress:!0,bufferedPrompts:[],startupToken:1,managed:!0,claudeHookSecret:l,pendingClaudeHookApprovals:new Map};this.sessions.set(p,h),this.registerClaudeHookSession(h),this.store.upsert(ce(h)),this.updateGauges(),ir(),er(),this.bindDriverLifecycle(h,r,"",e),this.reply(e,n,!0,{sessionId:p}),this.startPendingCodexSession(h,e);return}let c=w.startTimer("driver.spawn"),u=await a.start(s,void 0,i),d=c();b.info({sessionId:u,agent:r,spawnMs:d},"session created"),w.increment("session.create",{agent:r}),_.emit("session.create",{sessionId:u,agent:r,cwd:s,approvalMode:i});let f={sessionId:u,agent:r,cwd:s,approvalMode:i,driver:a,clients:new Set([e]),title:"New session",createdAt:new Date().toISOString(),lastActivityAt:new Date().toISOString(),active:!0,lastActivityTs:Date.now(),isResponding:!1,currentReplyText:"",acceptedClientMessageIds:[],syntheticApprovalRetries:{},startupInProgress:!1,bufferedPrompts:[],startupToken:0,managed:!0,claudeHookSecret:l,pendingClaudeHookApprovals:new Map};this.sessions.set(u,f),this.registerClaudeHookSession(f),this.store.upsert(ce(f)),this.updateGauges(),ir(),er(),this.bindDriverLifecycle(f,r,"",e),this.reply(e,n,!0,{sessionId:u})}catch(a){b.error({agent:r,cwd:s,error:String(a)},"createSession error"),this.reply(e,n,!1,void 0,String(a))}}async resumeSession(e,n,r,s,i,o){if(this.isDeletedSession(r)){this.reply(e,n,!1,void 0,"Session not found");return}let a=this.sessions.get(r);if(a&&a.active){a.clients.add(e),this.touchSession(a.sessionId);let f=await an(r,s,a.cwd),p=this.currentPartialReplyText(a);if(f.length>0||p||a.approvalMode||a.pendingApproval){let h={type:"session.history",sessionId:r,messages:f,isResponding:a.isResponding||void 0,partialReplyText:p,approvalMode:a.approvalMode,pendingApproval:a.pendingApproval};e.readyState===1&&e.send(JSON.stringify(h))}this.reply(e,n,!0,{sessionId:r});return}let l=this.store.find(r),c=i||l?.cwd||"",u=o??l?.approvalMode,d=l?.title??"Resumed session";try{let f=w.startTimer("driver.spawn"),p=this.createDriver(s),h=this.configureDriverBeforeStart(s,p),g=await p.start(c,r,u),m=f();b.info({sessionId:g,agent:s,spawnMs:m},"session resumed"),w.increment("session.resume",{agent:s}),_.emit("session.resume",{sessionId:g,agent:s,cwd:c});let S={sessionId:g,agent:s,cwd:c,approvalMode:u,driver:p,clients:new Set([e]),title:d,createdAt:l?.createdAt??new Date().toISOString(),lastActivityAt:new Date().toISOString(),active:!0,lastActivityTs:Date.now(),isResponding:!1,currentReplyText:"",acceptedClientMessageIds:l?.acceptedClientMessageIds??[],syntheticApprovalRetries:{},startupInProgress:!1,bufferedPrompts:[],startupToken:0,managed:l?.managed,pendingApproval:l?.pendingApproval,claudeHookSecret:h,pendingClaudeHookApprovals:new Map};this.sessions.set(g,S),this.registerClaudeHookSession(S),this.store.upsert(ce(S)),this.updateGauges(),this.bindDriverLifecycle(S,s," (resumed)",e),this.restoreDriverPendingApproval(p,S.pendingApproval);let P=await an(r,s,c);if(P.length>0||S.pendingApproval){b.info({sessionId:r,historyCount:P.length},"sending history messages");let se={type:"session.history",sessionId:g,messages:P,approvalMode:u,pendingApproval:S.pendingApproval};e.readyState===1&&e.send(JSON.stringify(se))}this.reply(e,n,!0,{sessionId:g})}catch(f){this.reply(e,n,!1,void 0,String(f))}}hasAcceptedClientMessage(e,n){return e.acceptedClientMessageIds.includes(n)}rememberAcceptedClientMessage(e,n){this.hasAcceptedClientMessage(e,n)||(e.acceptedClientMessageIds.push(n),e.acceptedClientMessageIds.length>dr&&e.acceptedClientMessageIds.splice(0,e.acceptedClientMessageIds.length-dr))}async sendMessage(e,n,r,s,i,o){if(this.isDeletedSession(r)){this.reply(e,n,!1,void 0,"Session not found");return}let a=this.sessions.get(r);if(!a||!a.driver){let l=await this.resolveReconnectSession(r,i,a);if(!l){b.warn({sessionId:r},"session not found in records or scanner"),this.reply(e,n,!1,void 0,"Session not found");return}b.info({sessionId:r,agent:l.agent,source:l.source},"auto-reconnecting session"),w.increment("session.reconnect",{agent:l.agent,source:l.source}),_.emit("session.reconnect",{sessionId:r,agent:l.agent,source:l.source});try{let c=this.createDriver(l.agent),u=this.configureDriverBeforeStart(l.agent,c,a?.claudeHookSecret);await c.start(l.cwd,r,l.approvalMode),this.restoreDriverPendingApproval(c,l.pendingApproval),a?(a.approvalMode=l.approvalMode,a.pendingApproval=l.pendingApproval,a.driver=c,a.active=!0,a.clients.add(e),a.lastActivityAt=l.lastActivityAt,a.lastActivityTs=Date.now(),a.isResponding=!1,a.currentReplyText="",a.acceptedClientMessageIds=ur(a.acceptedClientMessageIds,l.acceptedClientMessageIds),a.syntheticApprovalRetries=a.syntheticApprovalRetries??{},a.startupInProgress=!1,a.bufferedPrompts=a.bufferedPrompts??[],a.startupToken=a.startupToken??0,a.claudeHookSecret=u??a.claudeHookSecret,a.pendingClaudeHookApprovals=a.pendingClaudeHookApprovals??new Map):(a={sessionId:r,agent:l.agent,cwd:l.cwd,approvalMode:l.approvalMode,driver:c,clients:new Set([e]),title:l.title,createdAt:l.createdAt,lastActivityAt:l.lastActivityAt,active:!0,lastActivityTs:Date.now(),isResponding:!1,currentReplyText:"",acceptedClientMessageIds:l.acceptedClientMessageIds,syntheticApprovalRetries:{},startupInProgress:!1,bufferedPrompts:[],startupToken:0,managed:l.managed,pendingApproval:l.pendingApproval,claudeHookSecret:u,pendingClaudeHookApprovals:new Map},this.sessions.set(r,a)),this.registerClaudeHookSession(a),this.bindDriverLifecycle(a,l.agent," (reconnected)"),this.store.upsert(ce(a)),this.updateGauges()}catch(c){this.reply(e,n,!1,void 0,`Failed to reconnect: ${c}`);return}}if(a.clients.add(e),a.pendingApproval){this.reply(e,n,!1,void 0,"Resolve the pending approval before sending another message.");return}if(o&&this.hasAcceptedClientMessage(a,o)){this.reply(e,n,!0,{sessionId:r,clientMessageId:o,duplicate:!0});return}if(b.info({sessionId:r,clients:a.clients.size,hasDriver:!!a.driver,active:a.active},"sending message"),_.emit("session.send",{sessionId:r,agent:a.agent,messagePreview:s.slice(0,100)}),pt(a.title)){let l=Fs(s,50);l&&l!==a.title&&(a.title=l),this.store.upsert(ce(a))}if(o&&this.rememberAcceptedClientMessage(a,o),this.touchSession(a.sessionId),a.startupInProgress){a.isResponding=!0,a.currentReplyText="",a.lastUserMessage=s,a.bufferedPrompts.push(s),this.reply(e,n,!0,o?{sessionId:r,clientMessageId:o}:void 0);return}if(a.isResponding){a.bufferedPrompts.push(s),this.reply(e,n,!0,o?{sessionId:r,clientMessageId:o}:void 0);return}a.isResponding=!0,a.currentReplyText="",a.lastUserMessage=s,a.driver.sendPrompt(s),this.reply(e,n,!0,o?{sessionId:r,clientMessageId:o}:void 0)}async sendReconnectSnapshot(e,n,r,s,i,o,a){try{let l=this.getDeletedSessionIds(),c;try{c=await nr({agent:r,cwd:s,search:i,limit:50,activeSessions:this.activeSessionSnapshots(),sessionRecords:this.store.getAll(),deletedSessionIds:l})}catch(f){b.warn({error:String(f)},"failed to build reconnect snapshot session list"),c={sessions:[],nextCursor:void 0}}let u;if(o&&!l.has(o)){let f=a??c.sessions.find(g=>g.sessionId===o)?.agent,p=this.sessions.get(o);p&&p.clients.add(e);let h=await this.resolveReconnectSession(o,f,p);if(h){let g=await an(o,h.agent,p?.cwd??h.cwd);u={sessionId:o,agent:h.agent,messages:g,isResponding:p?.isResponding||void 0,partialReplyText:this.currentPartialReplyText(p),approvalMode:p?.approvalMode??h.approvalMode,...p?.pendingApproval?{pendingApproval:p.pendingApproval}:{}}}}let d=this.collectReconnectPendingApprovals();w.increment("reconnect.snapshot",{activeSession:u?"true":"false"}),this.reply(e,n,!0,{snapshot:{sessions:c.sessions,nextCursor:c.nextCursor,...u?{activeSession:u}:{},...d.length>0?{pendingApprovals:d}:{}}})}catch(l){this.reply(e,n,!1,void 0,`Failed to build reconnect snapshot: ${String(l)}`)}}async approve(e,n,r,s,i){let o=this.sessions.get(r),a=o?.pendingApproval,l=o?.pendingClaudeHookApprovals.get(s);if(o&&l){o.pendingApproval=void 0,_.emit("approval.response",{sessionId:r,requestId:s,approved:i}),this.touchSession(o.sessionId),l.resolve(Uc(i)),o.isResponding=!0,this.reply(e,n,!0);return}let c=o?.syntheticApprovalRetries[s];if(o&&c&&Kn(s)){delete o.syntheticApprovalRetries[s],o.pendingApproval=void 0,_.emit("approval.response",{sessionId:r,requestId:s,approved:i}),this.touchSession(o.sessionId),this.reply(e,n,!0),i&&await this.retrySyntheticClaudeApproval(o,c);return}if(o&&!o.driver&&a)try{await this.reviveSessionForApproval(o)}catch(d){this.reply(e,n,!1,void 0,`Failed to restore approval session: ${String(d)}`);return}if(!o?.driver){this.reply(e,n,!1,void 0,"Session not found or inactive");return}if(_.emit("approval.response",{sessionId:r,requestId:s,approved:i}),!o.driver.respondApproval(s,i)){this.reply(e,n,!1,void 0,"Agent process is not running. Send a new message to continue.");return}o.pendingApproval=void 0,this.touchSession(o.sessionId),o.isResponding=!0,this.reply(e,n,!0)}async retrySyntheticClaudeApproval(e,n){if(e.agent==="claude")try{e.driver&&e.driver.stop();let r=["Write","Edit","NotebookEdit"].includes(n.toolName)?"acceptEdits":"autoApprove",s=this.createDriver(e.agent),i=this.configureDriverBeforeStart(e.agent,s,e.claudeHookSecret);await s.start(e.cwd,e.sessionId,r),e.driver=s,e.active=!0,e.isResponding=!0,e.currentReplyText="",e.lastUserMessage=n.message,e.startupInProgress=!1,e.bufferedPrompts=[],e.startupToken=0,e.claudeHookSecret=i??e.claudeHookSecret,e.pendingClaudeHookApprovals=e.pendingClaudeHookApprovals??new Map,this.registerClaudeHookSession(e),this.bindDriverLifecycle(e,e.agent," (approval retry)"),this.store.upsert(ce(e)),this.updateGauges(),this.touchSession(e.sessionId),b.info({sessionId:e.sessionId,toolName:n.toolName,retryApprovalMode:r},"retrying Claude turn after synthetic approval"),s.sendPrompt(n.message)}catch(r){e.driver=null,e.active=!1,e.isResponding=!1,e.startupInProgress=!1,e.bufferedPrompts=[],e.startupToken+=1,this.updateGauges(),this.touchSession(e.sessionId),b.error({sessionId:e.sessionId,error:String(r)},"failed to retry Claude turn after approval"),this.broadcast(e.sessionId,{type:"error",sessionId:e.sessionId,message:`Failed to continue after approval: ${String(r)}`})}}async setApprovalMode(e,n,r,s){let i=this.sessions.get(r);if(!i){let a=this.store.find(r);a?(a.approvalMode=s,this.store.upsert(a),b.info({sessionId:r,agent:a.agent,newMode:s},"approval mode changed (inactive session)")):b.info({sessionId:r,newMode:s},"approval mode changed (untracked session)"),this.reply(e,n,!0,{approvalMode:s});return}let o=i.approvalMode;i.approvalMode=s,this.store.upsert(ce(i)),b.info({sessionId:r,agent:i.agent,oldMode:o,newMode:s},"approval mode changed"),i.driver&&i.driver.setApprovalMode(s),this.reply(e,n,!0,{approvalMode:s})}interrupt(e,n,r){let s=this.sessions.get(r);if(!s?.driver){this.reply(e,n,!1,void 0,"Session not found or inactive");return}_.emit("session.interrupt",{sessionId:r,agent:s.agent}),s.driver.interrupt(),this.reply(e,n,!0)}stopSession(e,n,r){let s=this.sessions.get(r);if(!s){this.reply(e,n,!1,void 0,"Session not found");return}b.info({sessionId:r,agent:s.agent},"stopping session"),_.emit("session.stop",{sessionId:r,agent:s.agent}),this.resolvePendingClaudeHookApprovals(s),s.driver?.stop(),s.active=!1,s.driver=null,s.pendingApproval=void 0,s.startupInProgress=!1,s.bufferedPrompts=[],s.startupToken+=1,this.updateGauges(),this.touchSession(s.sessionId),this.reply(e,n,!0)}deleteSession(e,n,r){let s=this.sessions.get(r);s&&(b.info({sessionId:r,agent:s.agent},"deleting session"),this.resolvePendingClaudeHookApprovals(s),s.driver?.stop(),s.startupInProgress=!1,s.bufferedPrompts=[],s.startupToken+=1,this.unregisterClaudeHookSession(s),this.sessions.delete(r)),_.emit("session.delete",{sessionId:r}),this.store.remove(r),this.updateGauges(),ir(),er(),this.reply(e,n,!0)}async sendHistory(e,n,r,s){let i=this.sessions.get(r);if(!i&&this.isDeletedSession(r)){this.reply(e,n,!1,void 0,"Session not found");return}i&&i.clients.add(e);let o=i?.cwd??this.store.find(r)?.cwd??"",a=this.store.find(r),l=await an(r,s,o);b.info({sessionId:r,historyCount:l.length,isResponding:i?.isResponding,approvalMode:i?.approvalMode},"sending history");let c={type:"session.history",sessionId:r,messages:l,isResponding:i?.isResponding||void 0,partialReplyText:this.currentPartialReplyText(i),approvalMode:i?.approvalMode??a?.approvalMode,pendingApproval:i?.pendingApproval??a?.pendingApproval};e.readyState===1&&e.send(JSON.stringify(c)),this.reply(e,n,!0)}async listSessions(e,n,r,s,i,o=50,a){try{let l=await nr({agent:r,cwd:s,search:i,limit:o,cursor:a,activeSessions:this.activeSessionSnapshots(),sessionRecords:this.store.getAll(),deletedSessionIds:this.getDeletedSessionIds()});this.reply(e,n,!0,l)}catch(l){this.reply(e,n,!1,void 0,String(l))}}createDriver(e){switch(e){case"claude":return new tn;case"codex":return new Xn;default:throw new Error(`Unknown agent: ${e}`)}}broadcast(e,n){let r=this.sessions.get(e);if(!r){b.warn({sessionId:e,msgType:n.type},"broadcast target session not found");return}let s=JSON.stringify(n),i=r.clients.size,o=0,a=0;for(let l of r.clients)l.readyState===1?(l.send(s),o++):a++;if(a>0&&w.increment("broadcast.fail"),n.type!=="text.delta"&&b.debug({sessionId:e,msgType:n.type,sent:o,total:i},"broadcast"),n.type==="text.delta"){r.currentReplyText+=n.content;return}if(n.type==="session.done"){let l=r.title||e,c=this.buildPushBody(r.currentReplyText);r.currentReplyText="",this.pushSender(l,c,{sessionId:e,agent:r.agent,eventType:"reply_ready"});return}n.type==="session.interrupted"&&(r.currentReplyText="")}reply(e,n,r,s,i){if(e.readyState!==1)return;let o={type:"response",id:n,ok:r,data:s,error:i};e.send(JSON.stringify(o))}};function ii(t,e){if(!e.deviceId){e.respond({type:"response",id:t.id,ok:!1,error:"device_auth_required"});return}t.action==="push.register"?e.registerToken(e.deviceId,t.pushToken):e.unregisterToken(e.deviceId,t.pushToken),e.respond({type:"response",id:t.id,ok:!0})}var jc=require("child_process");function cm(t,e){return(0,jc.execFileSync)(t,e,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}function um(t){let e=t.split(`
98
98
  `).map(n=>Number(n.trim())).filter(n=>Number.isFinite(n)&&n>0);return[...new Set(e)]}function Wc(t,e=cm){let n;try{n=um(e("lsof",["-ti",`tcp:${t}`]))}catch{return[]}return n.map(r=>{try{let s=e("ps",["-p",String(r),"-o","command="]);return s?{pid:r,command:s}:{pid:r}}catch{return{pid:r}}})}var _t=require("fs"),oi=require("os"),$c=require("crypto"),zc=require("path");function Vc(t){return(0,$c.randomBytes)(t).toString("base64url")}function dm(){return`d_${Vc(12)}`}function fm(){return(0,oi.hostname)()}function pm(){let t=(0,oi.hostname)().trim().toLowerCase();return t?t.endsWith(".local")?t:`${t}.local`:"localhost"}function hm(t){return{daemonId:dm(),daemonSecret:Vc(32),displayName:fm(),canonicalHost:pm(),port:t,createdAt:new Date().toISOString()}}function Gc(t,e){(0,_t.mkdirSync)((0,zc.dirname)(e),{recursive:!0}),(0,_t.writeFileSync)(e,JSON.stringify(t,null,2)+`
99
99
  `,"utf8")}function Yc(t,e=Pl){try{let r=(0,_t.readFileSync)(e,"utf8"),s=JSON.parse(r);if(typeof s.daemonId=="string"&&typeof s.daemonSecret=="string"&&typeof s.displayName=="string"&&typeof s.canonicalHost=="string"&&typeof s.createdAt=="string"){let i={daemonId:s.daemonId,daemonSecret:s.daemonSecret,displayName:s.displayName,canonicalHost:s.canonicalHost,port:typeof s.port=="number"&&Number.isFinite(s.port)?s.port:t,createdAt:s.createdAt};return i.port!==t&&(i.port=t,Gc(i,e)),i}}catch{}let n=hm(t);return Gc(n,e),n}var bt=require("crypto"),wt=require("fs"),Kc=require("path");function ai(t){return(0,bt.randomBytes)(t).toString("base64url")}function li(t){return(0,bt.createHash)("sha256").update(t).digest("hex")}function Jc(t,e){let n=Buffer.from(t),r=Buffer.from(e);return n.length!==r.length?!1:(0,bt.timingSafeEqual)(n,r)}function gm(t){try{let e=(0,wt.readFileSync)(t,"utf8"),n=JSON.parse(e);return Array.isArray(n)?n.filter(r=>r&&typeof r.deviceId=="string"&&typeof r.deviceName=="string"&&typeof r.tokenHash=="string"&&typeof r.createdAt=="string"&&typeof r.lastSeenAt=="string"&&(typeof r.revokedAt=="string"||r.revokedAt===null)):[]}catch{return[]}}function un(t,e){(0,wt.mkdirSync)((0,Kc.dirname)(t),{recursive:!0}),(0,wt.writeFileSync)(t,JSON.stringify(e,null,2)+`
100
100
  `,"utf8")}var pr=class{constructor(e=Rl){this.pairingsPath=e;this.records=gm(e)}records;windows=new Map;list(){return this.records.slice()}pairedCount(){return this.records.filter(e=>!e.revokedAt).length}openWindow(e=5*6e4){let n=`pair_${ai(8)}`,r=ai(24),s=new Date(Date.now()+e).toISOString(),i={pairingId:n,pairNonce:r,expiresAt:s};return this.windows.set(r,i),i}consumeWindow(e){let n=this.windows.get(e);return!n||(this.windows.delete(e),new Date(n.expiresAt).getTime()<Date.now())?null:n}issuePairToken(e,n){let r=new Date().toISOString(),s=ai(32),i={deviceId:e,deviceName:n,tokenHash:li(s),createdAt:r,lastSeenAt:r,revokedAt:null},o=this.records.findIndex(a=>a.deviceId===e);return o>=0?this.records[o]=i:this.records.unshift(i),un(this.pairingsPath,this.records),s}validatePairToken(e,n,r=!0){let s=this.records.find(o=>o.deviceId===e&&!o.revokedAt);if(!s)return!1;let i=li(n);return Jc(s.tokenHash,i)?(r&&(s.lastSeenAt=new Date().toISOString(),un(this.pairingsPath,this.records)),!0):!1}validateAnyPairToken(e,n=!0){let r=li(e),s=this.records.find(i=>!i.revokedAt&&Jc(i.tokenHash,r));return s?(n&&(s.lastSeenAt=new Date().toISOString(),un(this.pairingsPath,this.records)),s):null}revoke(e){let n=this.records.find(r=>r.deviceId===e&&!r.revokedAt);return n?(n.revokedAt=new Date().toISOString(),un(this.pairingsPath,this.records),!0):!1}reset(){this.records=[],this.windows.clear(),un(this.pairingsPath,this.records)}};function It(t){return t?t==="127.0.0.1"||t==="::1"||t==="::ffff:127.0.0.1":!1}function mm(t){return t&&t.match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||null}function Xc(t,e){return mm(t)??e}function ci(t,e){return!!(t&&e&&t===e)}function Qc(t,e,n,r=!0){return t?ci(t,e)?!0:!!n(t,r):!1}var eu=require("child_process");function ui(t){let e=t.split(".");return e.length!==4?!1:e.every(n=>/^\d+$/.test(n)&&Number(n)>=0&&Number(n)<=255)}function tu(t){if(!ui(t))return!1;let[e,n]=t.split(".").map(Number);return e===100&&n>=64&&n<=127}function ym(t){if(!ui(t))return!1;let[e,n]=t.split(".").map(Number);return e===169&&n===254}function Sm(t){if(!ui(t))return!1;let[e,n]=t.split(".").map(Number);return e===198&&(n===18||n===19)}function di(t){return!!t&&!ym(t)&&!Sm(t)}function At(t){if(!t)return;let e=t.trim().replace(/\.$/,"");return e?e.toLowerCase():void 0}function nu(t){return t?t.split(",").map(e=>e.trim()).filter(Boolean):[]}function vm(t){let e=[],n=[];for(let r of Object.values(t))if(r)for(let s of r)s.internal||s.family!=="IPv4"||di(s.address)&&(tu(s.address)?e.push(s.address):n.push(s.address));return[...e,...n]}function Zc(t){let e=JSON.parse(t),n=At(e.Self?.DNSName),r=(e.Self?.TailscaleIPs??[]).map(o=>At(o)).filter(o=>!!o).filter(o=>tu(o)&&di(o)),s=r[0]??n,i=[...n&&n!==s?[n]:[],...r.filter(o=>o!==s)];return{canonicalHost:s,fallbackHosts:i}}function ru(t=eu.execFileSync){let e=[process.env.TAILSCALE_SOCKET,"/tmp/tailscale.sock"].filter(Boolean);for(let n of e)try{let r=t("tailscale",["--socket",n,"status","--json"],{encoding:"utf8",stdio:["ignore","pipe","pipe"],timeout:1500});return Zc(r)}catch{}try{let n=t("tailscale",["status","--json"],{encoding:"utf8",stdio:["ignore","pipe","pipe"],timeout:1500});return Zc(n)}catch{return{fallbackHosts:[]}}}function su(t){let e=At(t.canonicalHost),n=At(t.configuredCanonicalHost)||At(t.tailscaleCanonicalHost)||e||"localhost",r=[...e&&e!==n?[e]:[],...t.configuredFallbackHosts??[],...t.tailscaleFallbackHosts??[],...vm(t.interfaces)].map(s=>At(s)).filter(s=>!!s).filter(s=>di(s)).filter((s,i,o)=>s!==n&&o.indexOf(s)===i);return{canonicalHost:n,fallbackHosts:r}}function iu(t){if(typeof t=="string")return t;if(Buffer.isBuffer(t))return t.toString("utf8");if(Array.isArray(t))return Buffer.concat(t).toString("utf8");if(t instanceof ArrayBuffer)return Buffer.from(t).toString("utf8");if(ArrayBuffer.isView(t)){let e=t;return Buffer.from(e.buffer,e.byteOffset,e.byteLength).toString("utf8")}return String(t)}var W=R.child({module:"daemon"}),dn=R.child({module:"ws"}),H=Yc(v.port),ue=new fr((t,e,n)=>cr(t,e,{daemonId:H.daemonId,canonicalHost:H.canonicalHost,...n??{}})),Re=new pr,hr=new Set,Pe=new WeakMap,ou=!1,uu=Date.now(),xt=null;function Tt(){let t=ru();return su({canonicalHost:H.canonicalHost,configuredCanonicalHost:v.canonicalHost,configuredFallbackHosts:nu(v.fallbackHosts),tailscaleCanonicalHost:t.canonicalHost,tailscaleFallbackHosts:t.fallbackHosts,interfaces:(0,lu.networkInterfaces)()})}async function fi(t){let e=[];for await(let r of t)e.push(Buffer.isBuffer(r)?r:Buffer.from(r));let n=Buffer.concat(e).toString("utf8");return n?JSON.parse(n):{}}function F(t,e,n){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(n,null,2))}function _m(t){let e=(0,gr.extname)(t).toLowerCase();return{".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".webp":"image/webp",".pdf":"application/pdf",".md":"text/markdown; charset=utf-8",".markdown":"text/markdown; charset=utf-8",".txt":"text/plain; charset=utf-8",".log":"text/plain; charset=utf-8",".json":"application/json; charset=utf-8",".js":"text/plain; charset=utf-8",".jsx":"text/plain; charset=utf-8",".ts":"text/plain; charset=utf-8",".tsx":"text/plain; charset=utf-8",".mjs":"text/plain; charset=utf-8",".cjs":"text/plain; charset=utf-8",".css":"text/plain; charset=utf-8",".html":"text/plain; charset=utf-8",".yml":"text/plain; charset=utf-8",".yaml":"text/plain; charset=utf-8"}[e]||"application/octet-stream"}function du(){let t=Re.openWindow(),e=Tt(),n=e.canonicalHost,r=H.port,s=e.fallbackHosts.length>0?e.fallbackHosts:void 0;if(v.relayUrl)try{let i=new URL(v.relayUrl);n=i.hostname,r=i.port?Number(i.port):i.protocol==="https:"?443:80,s=[e.canonicalHost,...s??[]].filter(Boolean)}catch{W.warn({relayUrl:v.relayUrl},"invalid VIBELET_RELAY_URL, ignoring")}return{type:"vibelet-pair",daemonId:H.daemonId,displayName:H.displayName,canonicalHost:n,fallbackHosts:s,port:r,pairNonce:t.pairNonce,expiresAt:t.expiresAt}}async function bm(t){let e=await(0,Ge.readdir)(t),n=[];for(let r of e){if(r.startsWith("."))continue;let s=await(0,Ge.stat)((0,gr.join)(t,r)).catch(()=>null);s&&n.push({name:r,isDirectory:s.isDirectory()})}return n.sort((r,s)=>r.isDirectory!==s.isDirectory?r.isDirectory?-1:1:r.name.localeCompare(s.name)),{entries:n}}var fn=(0,au.createServer)(async(t,e)=>{let n=new URL(t.url??"/",`http://localhost:${v.port}`);if(n.pathname==="/health"){let s=Tt(),i={status:"ok",version:ft,daemonId:H.daemonId,displayName:H.displayName,canonicalHost:s.canonicalHost,uptimeSeconds:Math.round((Date.now()-uu)/1e3),activeSessions:ue.getActiveSessionCount(),pairedDevices:Re.pairedCount(),wsClients:re.clients.size,drivers:ue.getDriverCounts(),metrics:w.snapshot()};v.relayUrl&&(i.relayUrl=v.relayUrl),F(e,200,i);return}if(t.method==="POST"&&n.pathname==="/pair/open"){if(!It(t.socket.remoteAddress)){F(e,403,{error:"forbidden"});return}F(e,200,du());return}if(t.method==="POST"&&n.pathname==="/pair/reset"){if(!It(t.socket.remoteAddress)){F(e,403,{error:"forbidden"});return}Re.reset(),F(e,200,{ok:!0});return}if(t.method==="POST"&&n.pathname==="/shutdown"){if(!It(t.socket.remoteAddress)){F(e,403,{error:"forbidden"});return}F(e,200,{status:"stopping"}),setTimeout(()=>$e("HTTP /shutdown request"),50);return}if(t.method==="POST"&&n.pathname==="/hook/claude/session-start"){if(!It(t.socket.remoteAddress)){F(e,403,{error:"forbidden"});return}try{let s=await fi(t),i=t.headers[Zt],o=Array.isArray(i)?i[0]:i;ue.handleClaudeSessionStartHook(o,s),F(e,200,{ok:!0})}catch(s){F(e,400,{error:String(s)})}return}if(t.method==="POST"&&n.pathname==="/hook/claude/permission-request"){if(!It(t.socket.remoteAddress)){F(e,403,{error:"forbidden"});return}try{let s=await fi(t),i=t.headers[Zt],o=Array.isArray(i)?i[0]:i,a=await ue.handleClaudePermissionHook(o,s);F(e,200,a)}catch(s){F(e,400,{error:String(s)})}return}if(t.method==="POST"&&n.pathname==="/pair/create"){try{let s=await fi(t);if(s.daemonId!==H.daemonId||typeof s.pairNonce!="string"||typeof s.deviceId!="string"||typeof s.deviceName!="string"){F(e,400,{error:"invalid_pair_request"});return}if(!Re.consumeWindow(s.pairNonce)){F(e,401,{error:"pair_window_expired"});return}let o=Re.issuePairToken(s.deviceId,s.deviceName),a=Tt();F(e,200,{daemonId:H.daemonId,displayName:H.displayName,canonicalHost:a.canonicalHost,fallbackHosts:a.fallbackHosts,port:H.port,deviceId:s.deviceId,pairToken:o})}catch(s){F(e,400,{error:String(s)})}return}let r=Xc(t.headers.authorization,n.searchParams.get("token"));if(!Qc(r,v.legacyToken,(s,i)=>Re.validateAnyPairToken(s,i),!1)){e.writeHead(401),e.end("Unauthorized");return}if(n.pathname==="/file"){let s=n.searchParams.get("path"),i=n.searchParams.get("cwd")||void 0;if(!s){e.writeHead(400),e.end("Missing path parameter");return}try{let o=Mc(s,i);if(!(await(0,Ge.stat)(o)).isFile()){e.writeHead(404),e.end("Not a file");return}let l=_m(o),c=await(0,Ge.readFile)(o);e.writeHead(200,{"Content-Type":l,"Content-Length":c.length}),e.end(c)}catch{e.writeHead(404),e.end("File not found")}return}e.writeHead(200),e.end(`Vibelet Daemon v${ft}`)}),re=new Hr.default({server:fn});fn.on("connection",t=>{hr.add(t),t.on("close",()=>{hr.delete(t)})});re.on("connection",(t,e)=>{let r=new URL(e.url??"/",`http://localhost:${v.port}`).searchParams.get("token");if(r&&ci(r,v.legacyToken))Pe.set(t,{authMode:"query_token"}),w.increment("ws.auth.success",{mode:"query_token"}),ue.prewarmCaches();else if(r){let s=Re.validateAnyPairToken(r);if(s)Pe.set(t,{authMode:"query_token",deviceId:s.deviceId}),w.increment("ws.auth.success",{mode:"query_token"}),ue.prewarmCaches();else{w.increment("ws.auth.failure",{mode:"query_token"}),t.close(4001,"Unauthorized");return}}dn.info({clients:re.clients.size},"client connected"),w.increment("ws.connect"),w.gauge("ws.clients",re.clients.size),_.emit("ws.connect",{clients:re.clients.size,authMode:Pe.get(t)?.authMode??"pending",deviceId:Pe.get(t)?.deviceId}),t.on("message",async s=>{try{let i=JSON.parse(iu(s));if(!i||typeof i.action!="string"){t.send(JSON.stringify({type:"error",sessionId:"",message:'Invalid message: missing or non-string "action" field'}));return}if(i.action==="ping"){t.send(JSON.stringify({type:"pong"}));return}let o=i;if(!Pe.has(t)){if(o.action==="auth.hello"&&o.daemonId===H.daemonId&&Re.validatePairToken(o.deviceId,o.pairToken)){Pe.set(t,{authMode:"auth_hello",deviceId:o.deviceId}),w.increment("ws.auth.success",{mode:"auth_hello"}),ue.prewarmCaches(),t.send(JSON.stringify({type:"response",id:o.id,ok:!0,data:{daemonId:H.daemonId,displayName:H.displayName}}));return}if(o.action==="auth.hello"){w.increment("ws.auth.failure",{mode:"auth_hello"}),t.send(JSON.stringify({type:"response",id:o.id,ok:!1,error:"auth_failed"})),t.close(4001,"Unauthorized");return}w.increment("ws.auth.failure",{mode:"missing"}),t.send(JSON.stringify({type:"error",sessionId:"",message:"Authentication required"})),t.close(4001,"Unauthorized");return}if(o.action==="log.report"){for(let a of o.entries)_.emitApp(a.event,a.level,a.data??{},a.ts),(a.level==="error"?W.error:a.level==="warn"?W.warn:W.info).call(W,{event:a.event,...a.data},`[app] ${a.event}`);t.send(JSON.stringify({type:"response",id:o.id,ok:!0}));return}if(o.action==="dirs.list"){try{let a=await bm(o.path);t.send(JSON.stringify({type:"response",id:o.id,ok:!0,data:a}))}catch(a){t.send(JSON.stringify({type:"response",id:o.id,ok:!1,error:String(a)}))}return}if(i.action==="push.register"){let a=Pe.get(t);ii(i,{deviceId:a?.deviceId,registerToken:ni,unregisterToken:ri,respond:l=>t.send(JSON.stringify(l))});return}if(i.action==="push.unregister"){let a=Pe.get(t);ii(i,{deviceId:a?.deviceId,registerToken:ni,unregisterToken:ri,respond:l=>t.send(JSON.stringify(l))});return}await ue.handle(t,o)}catch(i){dn.error({error:String(i)},"message handling error"),t.send(JSON.stringify({type:"error",sessionId:"",message:String(i)}))}}),t.on("close",s=>{dn.info({clients:re.clients.size,code:s},"client disconnected"),w.increment("ws.disconnect"),w.increment("ws.disconnect.code",{code:String(s)}),w.gauge("ws.clients",re.clients.size),_.emit("ws.disconnect",{clients:re.clients.size,code:s}),ue.removeClient(t)}),t.on("error",s=>{dn.error({error:s.message},"websocket error")})});function pi(){for(let t of hr)try{t.destroy()}catch{}hr.clear()}function fu(){let t=Gl({auditPath:ct,stdoutLogPath:jn,stderrLogPath:Wn,auditMaxBytes:v.auditMaxBytes,logMaxBytes:v.daemonLogMaxBytes});t.trimmedFiles>0&&W.info({trimmedFiles:t.trimmedFiles,reclaimedBytes:t.reclaimedBytes,files:t.files.filter(e=>e.trimmed).map(e=>({path:e.path,beforeBytes:e.beforeBytes,afterBytes:e.afterBytes}))},"trimmed vibelet storage")}function wm(){xt||(xt=setInterval(fu,v.storageHousekeepingIntervalMs),xt.unref())}function Im(){xt&&(clearInterval(xt),xt=null)}function $e(t,e=0){if(!ou){ou=!0,W.info({reason:t,exitCode:e},"shutting down"),_.emit("daemon.shutdown",{reason:t,exitCode:e,uptimeSeconds:Math.round((Date.now()-uu)/1e3)}),w.stopPeriodicLog(),Im(),ue.shutdown();for(let n of re.clients)try{n.close(1001,"Server shutting down"),n.terminate()}catch{}re.close(n=>{n&&W.error({error:String(n)},"websocket close error")}),fn.close(n=>{if(n){W.error({error:String(n)},"http close error"),pi(),process.exit(1);return}pi(),process.exit(e)}),setTimeout(()=>{W.error("force exiting after shutdown timeout"),pi(),process.exit(e||1)},3e3).unref()}}re.on("error",t=>{dn.error({error:t.message},"wss error")});fn.on("error",t=>{if(t.code==="EADDRINUSE"){let e=Wc(v.port).filter(n=>n.pid!==process.pid);W.error({port:v.port,occupants:e},"port is already in use. Stop the existing process or use VIBE_PORT=<port> to specify another port")}else W.error({error:String(t)},"server error");$e(`httpServer error: ${t.code??t.message}`,1)});process.once("SIGINT",()=>$e("SIGINT"));process.once("SIGTERM",()=>$e("SIGTERM"));process.once("SIGHUP",()=>$e("SIGHUP"));process.once("SIGTTIN",()=>$e("SIGTTIN"));process.once("SIGTSTP",()=>$e("SIGTSTP"));process.on("uncaughtException",t=>{W.error({error:String(t),stack:t.stack},"uncaughtException"),_.emit("daemon.error",{type:"uncaughtException",error:String(t)})});process.on("unhandledRejection",t=>{W.error({reason:String(t)},"unhandledRejection"),_.emit("daemon.error",{type:"unhandledRejection",reason:String(t)})});fn.listen(v.port,async()=>{fu(),_.emit("daemon.start",{port:v.port}),w.startPeriodicLog(),wm(),W.info({port:v.port,daemonId:H.daemonId,displayName:H.displayName,canonicalHost:Tt().canonicalHost,fallbackHosts:Tt().fallbackHosts,claudePath:v.claudePath,codexPath:v.codexPath,auditMaxBytes:v.auditMaxBytes,daemonLogMaxBytes:v.daemonLogMaxBytes,storageHousekeepingIntervalMs:v.storageHousekeepingIntervalMs,turnStallTimeoutMs:v.turnStallTimeoutMs},"daemon started");let t=Tt(),e=du();Yt(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibelet",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "macOS CLI for installing and running the Vibelet daemon",
5
5
  "private": false,
6
6
  "files": [