@quantiya/codevibe-codex-plugin 2.0.106 → 2.0.108

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/dist/server.js CHANGED
@@ -1,93 +1,95 @@
1
- "use strict";var vs=Object.create;var We=Object.defineProperty;var Is=Object.getOwnPropertyDescriptor;var Ss=Object.getOwnPropertyNames;var ws=Object.getPrototypeOf,Es=Object.prototype.hasOwnProperty;var Ps=(d,e)=>()=>(e||d((e={exports:{}}).exports,e),e.exports),bs=(d,e)=>{for(var t in e)We(d,t,{get:e[t],enumerable:!0})},Wt=(d,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Ss(e))!Es.call(d,s)&&s!==t&&We(d,s,{get:()=>e[s],enumerable:!(i=Is(e,s))||i.enumerable});return d};var k=(d,e,t)=>(t=d!=null?vs(ws(d)):{},Wt(e||!d||!d.__esModule?We(t,"default",{value:d,enumerable:!0}):t,d)),Rs=d=>Wt(We({},"__esModule",{value:!0}),d);var is=Ps((Or,Tn)=>{Tn.exports={name:"@quantiya/codevibe-codex-plugin",version:"2.0.106",description:"Control OpenAI Codex CLI from your iPhone and Android \u2014 real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",main:"dist/server.js",codevibe:{companionLauncher:"./libexec/companion-launcher"},files:["dist/**/*.js","libexec","hooks","README.md",".env.example"],scripts:{typecheck:"tsc --noEmit",build:"rm -rf dist && npm run typecheck && esbuild src/server.ts src/native-launch.ts --bundle --platform=node --target=node18 --minify --packages=external --outdir=dist",prepack:"node scripts/prepare-publish.js && npm run build",postpack:"node scripts/restore-dev.js",dev:"ts-node src/server.ts",start:"node dist/server.js",test:"jest --config jest.config.js"},keywords:["codex","codex-cli","openai","plugin","extension","mobile","ios","android","codevibe","companion","remote-control","ai","developer-tools"],author:"Quantiya <support@quantiya.ai>",license:"MIT",bugs:{email:"support@quantiya.ai"},homepage:"https://quantiya.ai/codevibe",engines:{node:">=22.0.0"},dependencies:{"@quantiya/codevibe-core":"^2.0.91","@quantiya/quorum-core":"^1.0.1",chokidar:"^4.0.0",dotenv:"^16.6.1",express:"^5.1.0",graphql:"^16.12.0","shell-quote":"1.9.0",uuid:"^13.0.0",ws:"^8.18.3"},bundledDependencies:["@quantiya/codevibe-core","@quantiya/quorum-core","chokidar","dotenv","express","graphql","shell-quote","uuid","ws"],devDependencies:{"@types/express":"^5.0.5","@types/jest":"^30.0.0","@types/node":"^24.10.1","@types/uuid":"^10.0.0","@types/ws":"^8.18.1",esbuild:"^0.28.0",jest:"^30.3.0","ts-jest":"^29.4.9","ts-node":"^10.9.2",typescript:"^5.9.3"},bundleDependencies:["@quantiya/codevibe-core","@quantiya/quorum-core","chokidar","dotenv","express","graphql","shell-quote","uuid","ws"]}});var Kn={};bs(Kn,{CodexCompanionServer:()=>bt,TERMINAL_SHUTDOWN_SIGNALS:()=>ls,TmuxPaneObserver:()=>Qe,classifyTmuxHasSessionError:()=>cs,extractShellCommandFromPromptText:()=>us,extractShellCommandPartsFromPromptText:()=>Ge,restoreCodexPersistOptionCommand:()=>ms,shellCommandPartsMatchExpected:()=>Pt});module.exports=Rs(Kn);var ye=require("uuid"),ve=k(require("crypto")),Ie=k(require("fs")),$=k(require("path")),$e=k(require("os")),jt=require("util"),Rt=require("child_process"),$t=require("shell-quote");var me=require("node:fs"),Y=k(require("node:path")),Zt=k(require("node:os")),_t=require("node:util");var ze=k(require("ws")),Se=require("node:fs"),we=k(require("node:path")),Jt=require("node:crypto");var F=class extends Error{constructor(t,i,s,n){super(t);this.code=t;this.rpcCode=i;this.diagnostic=s;this.handlerFailure=n;this.name="NativeClientError"}};function zt(d,e){let t=d.length<=128&&[...d].every(a=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/_.-".includes(a))?d:"UNKNOWN_NATIVE_METHOD",i=e instanceof Error?e:null,s=["Error","TypeError","RangeError","NativeClientError","NativeRuntimeError","NativeControlError","SyncEventClientError","SyncJournalError","ZodError"],n=e?.code??i?.message,r=typeof n=="string"&&n.length<=96&&(n.startsWith("NATIVE_")||n.startsWith("SYNC_")||["ENOENT","EACCES","EPERM","EIO"].includes(n))&&[...n].every(a=>"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".includes(a))?n:null,o=null;for(let a of(i?.stack??"").split(`
2
- `).slice(1)){for(let[l,p]of[["server.js","server"],["index.js","core"],["native-launch.js","native-launch"]]){let f="/dist/"+l+":",u=a.lastIndexOf(f);if(u<0)continue;let m=a.slice(u+f.length).split(")")[0].trim().split(":");if(m.length===2&&m.every(h=>h.length>0&&[...h].every(I=>"0123456789".includes(I)))){let[h,I]=m.map(Number);h>0&&h<1e5&&I>0&&I<1e7&&(o={module:p,line:h,column:I})}if(o)break}if(o)break}return new F("NATIVE_HANDLER_FAILED",void 0,void 0,{method:t,errorName:i&&s.includes(i.name)?i.name:"Error",causeCode:r,site:o})}var Je=class{constructor(e){this.options=e;this.socket=null;this.pending=new Map;this.handlers=new Set;this.accepting=!1;this.intentionalClose=!1;this.initialized=!1;this.requestPrefix="codevibe-"+(0,Jt.randomUUID)()+"-";this.sequence=0;this.instanceId=e.instanceId,this.endpoint={socketPath:e.socketPath,socketIdentity:{...e.socketIdentity},...e.alias?{alias:{...e.alias}}:{}}}async assertSocket(){this.options.assertOwner();let e=this.endpoint.socketPath;if(!we.isAbsolute(e)||we.normalize(e)!==e||e.includes(":")||e.includes("\0"))throw new F("NATIVE_SOCKET_UNSAFE");let t=await Se.promises.lstat(we.dirname(e)),i=await Se.promises.lstat(e),s=typeof process.getuid=="function"?process.getuid():void 0,n={rootDirectory:t.isDirectory(),rootNotSymlink:!t.isSymbolicLink(),rootPrivate:(t.mode&63)===0,ownerMatches:s===void 0||t.uid===s&&i.uid===s,socketType:i.isSocket(),socketNotSymlink:!i.isSymbolicLink(),socketIdentityMatches:i.dev===this.endpoint.socketIdentity.dev&&i.ino===this.endpoint.socketIdentity.ino};if(Object.values(n).some(o=>!o))throw new F("NATIVE_SOCKET_UNSAFE",void 0,n);let r=this.endpoint.alias;if(r){let o=await Se.promises.lstat(we.dirname(r.path)),a=await Se.promises.lstat(r.path);if(!o.isDirectory()||o.isSymbolicLink()||(o.mode&63)!==0||o.dev!==r.rootDev||o.ino!==r.rootIno||!a.isSymbolicLink()||a.dev!==r.dev||a.ino!==r.ino||s!==void 0&&(o.uid!==s||a.uid!==s)||await Se.promises.readlink(r.path)!==r.target||await Se.promises.realpath(r.path)!==e)throw new F("NATIVE_SOCKET_UNSAFE",void 0,{originalAliasMatches:!1})}this.options.assertOwner()}async connect(){try{await this.connectOnce()}catch(e){throw await this.close(),e}}async connectOnce(){if(this.socket||this.intentionalClose)throw new F("NATIVE_DISCONNECTED");await this.assertSocket();let e=new ze.default("ws+unix://"+this.endpoint.socketPath+":/");this.socket=e,this.accepting=!0,e.on("message",t=>this.receive(t.toString())),e.on("error",()=>this.fail(new F("NATIVE_DISCONNECTED"))),e.on("close",()=>{this.initialized=!1,this.accepting=!1,this.rejectPending(),this.intentionalClose||this.report(new F("NATIVE_DISCONNECTED"))}),await new Promise((t,i)=>{let s=setTimeout(()=>{o(new F("NATIVE_RPC_TIMEOUT",void 0,{webSocketOpenTimedOut:!0})),e.terminate()},2e3),n=()=>o(),r=()=>o(new F("NATIVE_DISCONNECTED")),o=a=>{clearTimeout(s),e.off("open",n),e.off("error",r),e.off("close",r),a?i(a):t()};e.once("open",n),e.once("error",r),e.once("close",r)}),await this.assertSocket(),await this.request("initialize",{clientInfo:{name:"codevibe-codex",version:this.options.pluginVersion},capabilities:{experimentalApi:!0,requestAttestation:!1}},2e3),await this.notify("initialized"),this.initialized=!0}report(e){try{Promise.resolve(this.options.onFailure(e)).catch(()=>{})}catch{}}rejectPending(){for(let e of this.pending.values())clearTimeout(e.timer),e.reject(new F("NATIVE_DISCONNECTED"));this.pending.clear()}fail(e){this.accepting=!1,this.initialized=!1,this.rejectPending(),this.intentionalClose||this.report(e),this.socket?.terminate()}receive(e){if(!this.accepting)return;let t;try{let s=JSON.parse(e);if(!s||typeof s!="object"||Array.isArray(s))throw Error();t=s}catch{this.fail(new F("NATIVE_PROTOCOL_INVALID"));return}if(typeof t.method=="string"){if(t.id!==void 0&&typeof t.id!="string"&&typeof t.id!="number"){this.fail(new F("NATIVE_PROTOCOL_INVALID"));return}let s;try{this.options.assertOwner(),s=this.options.onMessage(t)}catch(r){this.report(zt(t.method,r));return}let n=Promise.resolve(s).catch(r=>this.report(zt(t.method,r)));this.handlers.add(n),n.then(()=>this.handlers.delete(n));return}if(typeof t.id!="string")return;let i=this.pending.get(t.id);if(i)if(this.pending.delete(t.id),clearTimeout(i.timer),t.error!==void 0){let s=t.error?.code;i.reject(new F("NATIVE_RPC_REJECTED",typeof s=="number"?s:void 0))}else Object.prototype.hasOwnProperty.call(t,"result")?i.resolve(t.result):i.reject(new F("NATIVE_PROTOCOL_INVALID"))}async write(e){this.options.assertOwner();let t=this.socket;if(!t||t.readyState!==ze.default.OPEN||!this.accepting)throw new F("NATIVE_DISCONNECTED");await new Promise((i,s)=>t.send(JSON.stringify(e),n=>n?s(new F("NATIVE_DISCONNECTED")):i())),this.options.assertOwner()}async request(e,t,i=1e4,s){if(!this.initialized&&e!=="initialize")throw new F("NATIVE_DISCONNECTED");if(!Number.isFinite(i)||i<=0||i>3e5)throw new F("NATIVE_PROTOCOL_INVALID");if(s?.aborted)throw new F("NATIVE_REQUEST_CANCELLED");let n=this.requestPrefix+ ++this.sequence,o=new Promise((l,p)=>{let f=()=>{this.pending.delete(n),h.reject(new F("NATIVE_REQUEST_CANCELLED"))},u=()=>{s?.removeEventListener("abort",f),clearTimeout(m)},m=setTimeout(()=>{this.pending.delete(n),p(new F("NATIVE_RPC_TIMEOUT",void 0,{initializeTimedOut:e==="initialize",threadResumeTimedOut:e==="thread/resume",otherRpcTimedOut:e!=="initialize"&&e!=="thread/resume"})),s?.removeEventListener("abort",f)},i),h={resolve:I=>{u(),l(I)},reject:I=>{u(),p(I)},timer:m};this.pending.set(n,h),s?.addEventListener("abort",f,{once:!0}),s?.aborted&&f()}).then(l=>({value:l}),l=>({error:l}));try{s?.aborted||await this.write({id:n,method:e,params:t})}catch(l){let p=this.pending.get(n);throw p&&(clearTimeout(p.timer),this.pending.delete(n),p.reject(new F("NATIVE_DISCONNECTED"))),await o,l}let a=await o;if("error"in a)throw a.error;return a.value}async notify(e,t){await this.write({method:e,...t===void 0?{}:{params:t}})}async respond(e,t){if(!this.initialized)throw new F("NATIVE_DISCONNECTED");await this.write({id:e,result:t})}async close(){this.intentionalClose=!0,this.accepting=!1,this.initialized=!1,this.rejectPending();let e=this.socket;e&&e.readyState!==ze.default.CLOSED&&await new Promise(t=>{let i=setTimeout(()=>{e.terminate(),t()},2e3);e.once("close",()=>{clearTimeout(i),t()}),e.close()}),await this.joinHandlers(),this.socket=null}async joinHandlers(){await Promise.allSettled([...this.handlers])}};var V=class extends Error{constructor(t){super(t);this.code=t;this.name="NativeRuntimeError"}},Ee=()=>{throw new V("NATIVE_LAUNCH_AUTHORITY_INVALID")};function Ye(d){return!d||typeof d!="object"||Array.isArray(d)?Ee():d}function Ts(d,e){return Object.keys(d).sort().join(",")===e.sort().join(",")}function Yt(d){return typeof d=="number"&&Number.isSafeInteger(d)&&d>0}function Xt(d){try{process.kill(d,0)}catch{Ee()}}async function ei(d,e){if(!Y.isAbsolute(d)||Y.normalize(d)!==d||Y.basename(d)!=="launch.json")return Ee();let t=typeof process.getuid=="function"?process.getuid():void 0,i=await me.promises.open(d,me.constants.O_RDONLY|me.constants.O_NOFOLLOW),s,n;try{let o=await i.stat();if(!o.isFile()||o.nlink!==1||(o.mode&63)!==0||o.size>2*1024*1024||t!==void 0&&o.uid!==t)return Ee();let a=Ye(JSON.parse(await i.readFile("utf8")));if(!Ts(a,["version","instanceId","root","launcher","server","endpoint","plan"])||a.version!==1||a.instanceId!==e||typeof e!="string"||!e.length||!Yt(a.launcher?.pid)||a.launcher.host!==Zt.hostname()||!Yt(a.server?.pid)||a.root?.path!==Y.dirname(d)||!Number.isSafeInteger(a.root.dev)||!Number.isSafeInteger(a.root.ino)||a.root.uid!==t||!Y.isAbsolute(a.endpoint?.socketPath??"")||!Number.isSafeInteger(a.endpoint?.socketIdentity?.dev)||!Number.isSafeInteger(a.endpoint?.socketIdentity?.ino)||!Y.isAbsolute(a.plan?.workingDirectory??"")||a.plan.resumeThreadId!==null&&typeof a.plan.resumeThreadId!="string")return Ee();let l=await i.stat();if(o.dev!==l.dev||o.ino!==l.ino||o.size!==l.size||o.mtimeMs!==l.mtimeMs)return Ee();s=a,n={dev:o.dev,ino:o.ino,size:o.size,mtimeMs:o.mtimeMs}}finally{await i.close()}let r=()=>{let o=(0,me.lstatSync)(s.root.path),a=(0,me.lstatSync)(d);if(!o.isDirectory()||o.isSymbolicLink()||(o.mode&63)!==0||o.dev!==s.root.dev||o.ino!==s.root.ino||o.uid!==s.root.uid||!a.isFile()||a.isSymbolicLink()||a.nlink!==1||(a.mode&63)!==0||a.dev!==n.dev||a.ino!==n.ino||a.size!==n.size||a.mtimeMs!==n.mtimeMs||a.uid!==s.root.uid)return Ee();Xt(s.launcher.pid),Xt(s.server.pid)};return r(),{record:JSON.parse(JSON.stringify(s)),assertCurrent:r}}function Tt(d){let e=Ye(d);if(typeof e.id!="string"||!e.id.length)throw new V("NATIVE_ROOT_INVALID_ID");if(e.sessionId!==e.id||e.parentThreadId!=null)throw new V("NATIVE_ROOT_INVALID_SESSION");if(e.ephemeral!==!1)throw new V("NATIVE_ROOT_INVALID_PERSISTENCE");if(typeof e.cwd!="string"||!Y.isAbsolute(e.cwd))throw new V("NATIVE_ROOT_INVALID_CWD");if(!Number.isFinite(e.createdAt)||e.createdAt<0)throw new V("NATIVE_ROOT_INVALID_TIMESTAMP");if(e.path!==null&&(typeof e.path!="string"||!Y.isAbsolute(e.path)))throw new V("NATIVE_ROOT_INVALID_PATH");if(typeof e.cliVersion!="string")throw new V("NATIVE_ROOT_INVALID_VERSION");if(typeof e.modelProvider!="string")throw new V("NATIVE_ROOT_INVALID_PROVIDER");return{id:e.id,sessionId:e.sessionId,cwd:e.cwd,createdAt:e.createdAt,path:e.path,cliVersion:e.cliVersion,modelProvider:e.modelProvider}}var Xe=class{constructor(e){this.options=e;this.root=null;this.ready=!1;this.generation=0;this.bindingDepth=0;this.binding=Promise.resolve();this.closed=!1;this.refreshPending=null;this.pendingControls=new Map;this.pendingFiles=new Map;this.client=new Je({...e.authority.record.endpoint,instanceId:e.authority.record.instanceId,pluginVersion:e.pluginVersion,assertOwner:e.authority.assertCurrent,onMessage:t=>this.observe(t),onFailure:t=>t.handlerFailure?e.onFailure(t.code,t.handlerFailure):e.onFailure(t.code)})}get thread(){return this.root?{...this.root}:null}controlFacts(){return JSON.parse(JSON.stringify([...this.pendingFiles.values(),...this.pendingControls.values()]))}isCurrentControl(e){let t=e.id===void 0?void 0:this.pendingControls.get(e.id);return!this.closed&&!!t&&t.method===e.method&&(0,_t.isDeepStrictEqual)(t.params,e.params)}hasPendingControl(){return this.pendingControls.size>0}async start(){await this.client.connect();let e=this.options.authority.record.plan.resumeThreadId??this.options.recoveryThreadId;e&&await this.bind(await this.readMetadata(e))}bind(e){let t=this.options.authority.record.plan.resumeThreadId??this.options.recoveryThreadId;if(!this.root&&t&&e.id!==t)return Promise.reject(new V("NATIVE_ROOT_INVALID"));if(this.root&&e.id===this.root.id&&e.cwd!==this.root.cwd)return Promise.reject(new V("NATIVE_ROOT_INVALID"));if(this.root&&(0,_t.isDeepStrictEqual)(this.root,e)&&(this.ready||this.bindingDepth>0))return this.binding;(!this.root||this.root.id!==e.id)&&(this.generation++,this.ready=!1,this.pendingControls.clear(),this.pendingFiles.clear());let i=this.generation;this.root={...e},this.bindingDepth++;let s=this.binding.then(async()=>{if(this.closed)throw new V("NATIVE_BINDING_FAILED");await this.options.onRoot({...e}),i===this.generation&&!this.closed&&(this.ready=!0)});return this.binding=s.catch(()=>{}),s.then(()=>{this.bindingDepth--},()=>{this.bindingDepth--}),s}observe(e){if(this.closed)return;let t=e.params;if(e.method==="thread/started"){let s=t?.thread;return s?.ephemeral===!0||s?.parentThreadId!=null||s?.sessionId!==s?.id?void 0:this.bind(Tt(s))}if(!this.root||t?.threadId!==this.root.id)return;if(e.id!==void 0&&this.pendingControls.set(e.id,JSON.parse(JSON.stringify(e))),e.method==="serverRequest/resolved"&&this.pendingControls.delete(t.requestId),["item/started","item/completed"].includes(e.method)&&t.item?.type==="fileChange"&&this.pendingFiles.set(t.item.id,JSON.parse(JSON.stringify(e))),e.method==="item/completed"&&["commandExecution","fileChange"].includes(t.item?.type)){for(let[s,n]of this.pendingControls){let r=n.params;r.turnId===t.turnId&&r.itemId===t.item.id&&this.pendingControls.delete(s)}this.pendingFiles.delete(t.item.id)}if(!this.ready&&this.bindingDepth===0&&e.method==="turn/started"&&this.bind(this.root).catch(()=>{}),["item/agentMessage/delta","item/reasoning/textDelta","item/commandExecution/outputDelta"].includes(e.method))return;if(this.ready)return this.options.onMessage(e);let i=this.generation;return this.binding.then(()=>{if(!this.ready||this.closed||i!==this.generation)throw new V("NATIVE_BINDING_FAILED");return this.options.onMessage(e)})}async readMetadata(e){let t=await this.client.request("thread/resume",{threadId:e,excludeTurns:!0},2e3),i=Tt(Ye(t).thread);if(i.id!==e)throw new V("NATIVE_ROOT_INVALID");return i}refreshMetadata(){if(this.refreshPending)return this.refreshPending;if(!this.root||this.closed)return Promise.resolve(null);let e=this.root.id,t=(async()=>{let i=Date.now()+2e3;for(let s=0;s<10&&Date.now()<i;s++)try{let n=await this.client.request("thread/resume",{threadId:e,excludeTurns:!0},Math.max(1,i-Date.now())),r=Tt(Ye(n).thread);if(r.id!==e||this.root?.id!==e||this.closed)throw new V("NATIVE_ROOT_INVALID");return await this.bind(r),r}catch(n){if(!(n instanceof F)||n.code!=="NATIVE_RPC_REJECTED"||![-32600,-32601].includes(n.rpcCode??0))throw n;s<9&&Date.now()<i&&await new Promise(r=>setTimeout(r,Math.min(100,i-Date.now())))}return null})();return this.refreshPending=t,t.then(()=>{this.refreshPending=null},()=>{this.refreshPending=null}),t}async close(){this.closed=!0,await this.client.close(),await this.binding,await this.refreshPending?.catch(()=>{})}};var mi=require("node:crypto"),Z=require("node:util"),W=require("@quantiya/codevibe-core");var ti=require("node:crypto"),ii=k(require("node:path")),Ze=require("@quantiya/codevibe-core"),T=class extends Error{constructor(t){super(t);this.code=t;this.name="NativeControlError"}};function X(){throw new T("NATIVE_CONTROL_INVALID")}var ce=d=>!d||typeof d!="object"||Array.isArray(d)?X():d,B=d=>typeof d!="string"||!d.length?X():d,si=d=>(0,ti.createHash)("sha256").update(JSON.stringify(d)).digest("hex");function ni(d,e){let t=d.payload;if(d.type!=="event_msg"||t?.type!=="item_completed"||t.item?.type!=="AgentMessage"||t.item.delivery!=="async")return null;if(t.thread_id!==e||typeof t.turn_id!="string"||!t.turn_id.length)throw new T("NATIVE_QUESTION_MISMATCH");let i={type:"agentMessage",id:t.item.id,delivery:"async",questions:t.item.questions};return et(e,t.turn_id,i),{method:"item/completed",params:{threadId:e,turnId:t.turn_id,item:i}}}function ri(d,e){let t=d.payload;if(d.type!=="event_msg"||t?.type!=="item_completed"||!["UserMessage","FunctionCallOutput"].includes(t.item?.type))return null;if(t.thread_id!==e||typeof t.turn_id!="string"||!t.turn_id.length)throw new T("NATIVE_QUESTION_MISMATCH");let i=ce(t.item);B(i.id);let s;if(i.type==="UserMessage"){if(i.client_id!==null&&typeof i.client_id!="string"||!Array.isArray(i.content))return X();let n=i.content.map(r=>{let o=ce(r);if(o.type==="image"){if(typeof o.image_url=="string"==(typeof o.file_id=="string"))return X();let{image_url:a,file_id:l,...p}=o;return{...p,...a!==void 0?{url:B(a)}:{fileId:B(l)}}}if(o.type==="local_image")return{type:"localImage",detail:null,path:B(o.path)};if(o.type==="local_audio")return{type:"localAudio",path:B(o.path)};if(o.type==="audio"&&typeof o.audio_url=="string"){let{audio_url:a,...l}=o;return{...l,url:a}}return r});s={type:"userMessage",id:i.id,clientId:i.client_id,content:n}}else{if(i.namespace!=="functions"||i.name!=="request_user_input_async")return null;s={type:"functionCallOutput",id:i.id,name:i.name,namespace:i.namespace,output:B(i.output)}}return{method:"item/completed",params:{threadId:e,turnId:t.turn_id,item:s}}}function et(d,e,t){let i=ce(t);if(i.type!=="agentMessage"||i.delivery!=="async"||i.questions===null)return[];let s=B(i.id);return B(d),B(e),Array.isArray(i.questions)?i.questions.map((n,r)=>{let o=ce(n),a=B(o.title);if(o.options!==null&&(!Array.isArray(o.options)||!o.options.length||!o.options.every(p=>typeof p=="string"&&p.length>0)))return X();let l=o.options===null?null:[...o.options];return{key:si(["codex-native-question",d,s,r]),threadId:d,turnId:e,itemId:s,questionIndex:r,questionItemId:JSON.stringify(["request_user_input_async",s,r]),title:a,options:l}}):X()}function oi(d,e,t){if(t!==null&&t!==d.questionItemId)throw new T("NATIVE_QUESTION_MISMATCH");let i=e.trim(),s=Number(i),n=Number.isSafeInteger(s)&&String(s)===i,r;if(d.options?.length){if(!n){if(t!==null)throw new T("NATIVE_OPTION_INVALID");return{kind:"ordinary"}}if(s<1||s>d.options.length)throw new T("NATIVE_OPTION_INVALID");r=d.options[s-1]}else{if(t===null)return{kind:"ordinary"};if(!i.length)throw new T("NATIVE_OPTION_INVALID");r=e}return{kind:"answer",answer:r,output:JSON.stringify([{answer:r,question:d.title,questionItemId:d.questionItemId}])}}function Ct(d,e,t,i,s=2){let n=t.method==="item/commandExecution/requestApproval"?"command":t.method==="item/fileChange/requestApproval"?"file":null;if(!n)return null;if(typeof t.id!="string"&&typeof t.id!="number"||typeof t.id=="string"&&!t.id.length||typeof t.id=="number"&&(!Number.isSafeInteger(t.id)||t.id<0))return X();let r=ce(t.params),o=B(r.threadId),a=B(r.turnId),l=B(r.itemId);if(o!==e)throw new T("NATIVE_CONTROL_UNSUPPORTED");let p,f=!1;if(n==="command"){let m=new Set(["kind","threadId","turnId","itemId","startedAtMs","approvalId","environmentId","reason","networkApprovalContext","additionalPermissions","command","cwd","commandActions","proposedExecpolicyAmendment","proposedNetworkPolicyAmendments","availableDecisions"]);if(Object.keys(r).some(h=>!m.has(h))||r.kind!=null&&r.kind!=="command"||r.approvalId!=null||r.additionalPermissions!=null||r.networkApprovalContext!=null||r.environmentId!=="local"&&r.environmentId!==null||r.proposedNetworkPolicyAmendments!=null&&(!Array.isArray(r.proposedNetworkPolicyAmendments)||r.proposedNetworkPolicyAmendments.length))throw new T("NATIVE_CONTROL_UNSUPPORTED");if(B(r.command),B(r.cwd),!Array.isArray(r.availableDecisions))return X();if(p=r.availableDecisions,s===1){let h=p.length;p=p.filter(I=>I==="accept"||I==="cancel"),f=p.length!==h}}else{let m=new Set(["threadId","turnId","itemId","startedAtMs","reason","grantRoot"]);if(Object.keys(r).some(h=>!m.has(h))||r.grantRoot!=null)throw new T("NATIVE_CONTROL_UNSUPPORTED");if(p=s===1?["accept","decline"]:["accept","acceptForSession","cancel"],!i||i.nativeInstanceId!==d||i.threadId!==o||i.turnId!==a||i.item.type!=="fileChange"||i.item.id!==l||!Array.isArray(i.item.changes)||!i.item.changes.length)throw new T("NATIVE_CONTROL_UNSUPPORTED");for(let h of i.item.changes)if(B(h.path),ce(h.kind),typeof h.diff!="string")return X()}if(r.reason!=null&&typeof r.reason!="string")return X();let u=p.map((m,h)=>{let I,y;if(m==="accept")I=m,y=s===1?"Approve once":"Yes, proceed";else if(m==="cancel"||n==="file"&&m==="decline")I=m,y=m==="decline"?"Reject edit":s===1?"Cancel":"No, and tell Codex what to do differently";else if(m==="acceptForSession")I=m,y=n==="file"?"Yes, and don't ask again for these files":"Approve for this session";else if(n==="command"&&m&&typeof m=="object"&&!Array.isArray(m)){let w=ce(m),v=ce(w.acceptWithExecpolicyAmendment),S=v.execpolicy_amendment;if(Object.keys(w).length!==1||Object.keys(v).length!==1||!Array.isArray(S)||!S.length||!S.every(b=>typeof b=="string"&&b.length>0&&!b.includes("\0"))||r.proposedExecpolicyAmendment!=null&&(0,Ze.stableStringify)(S)!==(0,Ze.stableStringify)(r.proposedExecpolicyAmendment))throw new T("NATIVE_CONTROL_UNSUPPORTED");I=JSON.parse(JSON.stringify(m)),y="Yes, and don't ask again for commands that start with `"+S.map(b=>/^[A-Za-z0-9_./:@%+=,-]+$/.test(b)?b:"'"+b.split("'").join("'\\''")+"'").join(" ")+"`"}else throw new T("NATIVE_CONTROL_UNSUPPORTED");return{number:String(h+1),label:y,decision:I}});if(!u.length||new Set(u.map(m=>(0,Ze.stableStringify)(m.decision))).size!==u.length)throw new T("NATIVE_CONTROL_UNSUPPORTED");return{key:si(["codex-native-approval",d,o,a,l,t.id]),nativeInstanceId:d,threadId:o,turnId:a,itemId:l,requestId:t.id,kind:n,request:JSON.parse(JSON.stringify(t)),observedFile:i?JSON.parse(JSON.stringify(i)):null,choices:u,otherChoicesOnDesktop:f}}function Pe(d,e,t){let i=t.approvalPresentationVersion;if(i!==void 0&&i!==2)throw new T("NATIVE_CONTROL_UNSUPPORTED");return Ct(d,e,t.request,t.observedFile??void 0,i===2?2:1)}function ai(d,e){let t=d.choices.find(i=>i.number===e.trim());if(!t)throw new T("NATIVE_OPTION_INVALID");return{decision:JSON.parse(JSON.stringify(t.decision))}}function tt(d,e,t,i=[]){if(B(d),B(e),!t.length&&!i.length)return X();for(let s of i)if(!ii.isAbsolute(s)||s.includes("\0"))return X();return{threadId:d,clientUserMessageId:e,input:[...t.length?[{type:"text",text:t,text_elements:[]}]:[],...i.map(s=>({type:"localImage",detail:null,path:B(s)}))]}}function di(d,e){return{threadId:B(d),input:[],toolOutput:{namespace:"functions",name:"request_user_input_async",output:B(e),retain:!0}}}function Ce(d){let e=(d.options??[]).map((i,s)=>({number:String(s+1),text:i})),t=e.length?"Reply with the number of your choice.":"Type your answer.";return{content:[d.title,...e.map(i=>`${i.number}. ${i.text}`),t].join(`
1
+ "use strict";var As=Object.create;var tt=Object.defineProperty;var Os=Object.getOwnPropertyDescriptor;var xs=Object.getOwnPropertyNames;var ks=Object.getPrototypeOf,Ds=Object.prototype.hasOwnProperty;var Ms=(a,e)=>()=>(e||a((e={exports:{}}).exports,e),e.exports),Fs=(a,e)=>{for(var t in e)tt(a,t,{get:e[t],enumerable:!0})},ti=(a,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of xs(e))!Ds.call(a,s)&&s!==t&&tt(a,s,{get:()=>e[s],enumerable:!(i=Os(e,s))||i.enumerable});return a};var D=(a,e,t)=>(t=a!=null?As(ks(a)):{},ti(e||!a||!a.__esModule?tt(t,"default",{value:a,enumerable:!0}):t,a)),Ls=a=>ti(tt({},"__esModule",{value:!0}),a);var hs=Ms((io,Bn)=>{Bn.exports={name:"@quantiya/codevibe-codex-plugin",version:"2.0.108",description:"Control OpenAI Codex CLI from your iPhone and Android \u2014 real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",main:"dist/server.js",codevibe:{companionLauncher:"./libexec/companion-launcher"},files:["dist/**/*.js","libexec","hooks","README.md",".env.example"],scripts:{typecheck:"tsc --noEmit",build:"rm -rf dist && npm run typecheck && esbuild src/server.ts src/native-launch.ts --bundle --platform=node --target=node18 --minify --packages=external --outdir=dist",prepack:"node scripts/prepare-publish.js && npm run build",postpack:"node scripts/restore-dev.js",dev:"ts-node src/server.ts",start:"node dist/server.js",test:"jest --config jest.config.js"},keywords:["codex","codex-cli","openai","plugin","extension","mobile","ios","android","codevibe","companion","remote-control","ai","developer-tools"],author:"Quantiya <support@quantiya.ai>",license:"MIT",bugs:{email:"support@quantiya.ai"},homepage:"https://quantiya.ai/codevibe",engines:{node:">=22.0.0"},dependencies:{"@quantiya/codevibe-core":"^2.0.92","@quantiya/quorum-core":"^1.0.1",chokidar:"^4.0.0",dotenv:"^16.6.1",express:"^5.1.0",graphql:"^16.12.0","shell-quote":"1.9.0",uuid:"^13.0.0",ws:"^8.18.3"},bundledDependencies:["@quantiya/codevibe-core","@quantiya/quorum-core","chokidar","dotenv","express","graphql","shell-quote","uuid","ws"],devDependencies:{"@types/express":"^5.0.5","@types/jest":"^30.0.0","@types/node":"^24.10.1","@types/uuid":"^10.0.0","@types/ws":"^8.18.1",esbuild:"^0.28.0",jest:"^30.3.0","ts-jest":"^29.4.9","ts-node":"^10.9.2",typescript:"^5.9.3"},bundleDependencies:["@quantiya/codevibe-core","@quantiya/quorum-core","chokidar","dotenv","express","graphql","shell-quote","uuid","ws"]}});var Xn={};Fs(Xn,{CodexCompanionServer:()=>At,TERMINAL_SHUTDOWN_SIGNALS:()=>Ss,TmuxPaneObserver:()=>Je,classifyTmuxHasSessionError:()=>Es,extractShellCommandFromPromptText:()=>bs,extractShellCommandPartsFromPromptText:()=>et,nativeStopFailureFields:()=>Zt,restoreCodexPersistOptionCommand:()=>Ts,shellCommandPartsMatchExpected:()=>Nt});module.exports=Ls(Xn);var Se=require("uuid"),Ee=D(require("crypto")),Pe=D(require("fs")),W=D(require("path")),Ze=D(require("os")),Yt=require("util"),Ot=require("child_process"),Xt=require("shell-quote");var ge=require("node:fs"),Z=D(require("node:path")),di=D(require("node:os")),kt=require("node:util");var Be=D(require("ws")),be=require("node:fs"),Re=D(require("node:path")),si=require("node:crypto");var M=class extends Error{constructor(t,i,s,n){super(t);this.code=t;this.rpcCode=i;this.diagnostic=s;this.handlerFailure=n;this.name="NativeClientError"}};function ii(a,e){let t=a.length<=128&&[...a].every(d=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/_.-".includes(d))?a:"UNKNOWN_NATIVE_METHOD",i=e instanceof Error?e:null,s=["Error","TypeError","RangeError","NativeClientError","NativeRuntimeError","NativeControlError","SyncEventClientError","SyncJournalError","ZodError"],n=e?.code??i?.message,r=typeof n=="string"&&n.length<=96&&(n.startsWith("NATIVE_")||n.startsWith("SYNC_")||["ENOENT","EACCES","EPERM","EIO"].includes(n))&&[...n].every(d=>"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".includes(d))?n:null,o=null;for(let d of(i?.stack??"").split(`
2
+ `).slice(1)){for(let[l,u]of[["server.js","server"],["index.js","core"],["native-launch.js","native-launch"]]){let h="/dist/"+l+":",p=d.lastIndexOf(h);if(p<0)continue;let m=d.slice(p+h.length).split(")")[0].trim().split(":");if(m.length===2&&m.every(f=>f.length>0&&[...f].every(g=>"0123456789".includes(g)))){let[f,g]=m.map(Number);f>0&&f<1e5&&g>0&&g<1e7&&(o={module:u,line:f,column:g})}if(o)break}if(o)break}return new M("NATIVE_HANDLER_FAILED",void 0,void 0,{method:t,errorName:i&&s.includes(i.name)?i.name:"Error",causeCode:r,site:o})}var xe=class{constructor(e){this.options=e;this.socket=null;this.pending=new Map;this.handlers=new Set;this.accepting=!1;this.intentionalClose=!1;this.initialized=!1;this.requestPrefix="codevibe-"+(0,si.randomUUID)()+"-";this.sequence=0;if(e.maxPayloadBytes!==void 0&&(!Number.isSafeInteger(e.maxPayloadBytes)||e.maxPayloadBytes<1024||e.maxPayloadBytes>8*1024*1024))throw new M("NATIVE_PROTOCOL_INVALID");this.instanceId=e.instanceId,this.endpoint={socketPath:e.socketPath,socketIdentity:{...e.socketIdentity},...e.alias?{alias:{...e.alias}}:{}}}get isConnected(){return this.initialized&&this.accepting&&!this.intentionalClose&&this.socket?.readyState===Be.default.OPEN}async assertSocket(){this.options.assertOwner();let e=this.endpoint.socketPath;if(!Re.isAbsolute(e)||Re.normalize(e)!==e||e.includes(":")||e.includes("\0"))throw new M("NATIVE_SOCKET_UNSAFE");let t=await be.promises.lstat(Re.dirname(e)),i=await be.promises.lstat(e),s=typeof process.getuid=="function"?process.getuid():void 0,n={rootDirectory:t.isDirectory(),rootNotSymlink:!t.isSymbolicLink(),rootPrivate:(t.mode&63)===0,ownerMatches:s===void 0||t.uid===s&&i.uid===s,socketType:i.isSocket(),socketNotSymlink:!i.isSymbolicLink(),socketIdentityMatches:i.dev===this.endpoint.socketIdentity.dev&&i.ino===this.endpoint.socketIdentity.ino};if(Object.values(n).some(o=>!o))throw new M("NATIVE_SOCKET_UNSAFE",void 0,n);let r=this.endpoint.alias;if(r){let o=await be.promises.lstat(Re.dirname(r.path)),d=await be.promises.lstat(r.path);if(!o.isDirectory()||o.isSymbolicLink()||(o.mode&63)!==0||o.dev!==r.rootDev||o.ino!==r.rootIno||!d.isSymbolicLink()||d.dev!==r.dev||d.ino!==r.ino||s!==void 0&&(o.uid!==s||d.uid!==s)||await be.promises.readlink(r.path)!==r.target||await be.promises.realpath(r.path)!==e)throw new M("NATIVE_SOCKET_UNSAFE",void 0,{originalAliasMatches:!1})}this.options.assertOwner()}async connect(){try{await this.connectOnce()}catch(e){throw await this.close(),e}}async connectOnce(){if(this.socket||this.intentionalClose)throw new M("NATIVE_DISCONNECTED");await this.assertSocket();let e=new Be.default("ws+unix://"+this.endpoint.socketPath+":/",this.options.maxPayloadBytes===void 0?{}:{maxPayload:this.options.maxPayloadBytes});this.socket=e,this.accepting=!0,e.on("message",t=>this.receive(t.toString())),e.on("error",()=>this.fail(new M("NATIVE_DISCONNECTED"))),e.on("close",()=>{this.initialized=!1,this.accepting=!1,this.rejectPending(),this.intentionalClose||this.report(new M("NATIVE_DISCONNECTED"))}),await new Promise((t,i)=>{let s=setTimeout(()=>{o(new M("NATIVE_RPC_TIMEOUT",void 0,{webSocketOpenTimedOut:!0})),e.terminate()},2e3),n=()=>o(),r=()=>o(new M("NATIVE_DISCONNECTED")),o=d=>{clearTimeout(s),e.off("open",n),e.off("error",r),e.off("close",r),d?i(d):t()};e.once("open",n),e.once("error",r),e.once("close",r)}),await this.assertSocket(),await this.request("initialize",{clientInfo:{name:"codevibe-codex",version:this.options.pluginVersion},capabilities:{experimentalApi:!0,requestAttestation:!1}},2e3),await this.notify("initialized"),this.initialized=!0}report(e){try{Promise.resolve(this.options.onFailure(e)).catch(()=>{})}catch{}}rejectPending(){for(let e of this.pending.values())clearTimeout(e.timer),e.reject(new M("NATIVE_DISCONNECTED"));this.pending.clear()}fail(e){this.accepting=!1,this.initialized=!1,this.rejectPending(),this.intentionalClose||this.report(e),this.socket?.terminate()}receive(e){if(!this.accepting)return;let t;try{let s=JSON.parse(e);if(!s||typeof s!="object"||Array.isArray(s))throw Error();t=s}catch{this.fail(new M("NATIVE_PROTOCOL_INVALID"));return}if(typeof t.method=="string"){if(t.id!==void 0&&typeof t.id!="string"&&typeof t.id!="number"){this.fail(new M("NATIVE_PROTOCOL_INVALID"));return}let s;try{this.options.assertOwner()}catch{this.fail(new M("NATIVE_OWNER_CHANGED"));return}try{s=this.options.onMessage(t)}catch(r){this.report(ii(t.method,r));return}let n=Promise.resolve(s).catch(r=>this.report(ii(t.method,r)));this.handlers.add(n),n.then(()=>this.handlers.delete(n));return}if(typeof t.id!="string")return;let i=this.pending.get(t.id);if(i)if(this.pending.delete(t.id),clearTimeout(i.timer),t.error!==void 0){let s=t.error?.code;i.reject(new M("NATIVE_RPC_REJECTED",typeof s=="number"?s:void 0))}else Object.prototype.hasOwnProperty.call(t,"result")?i.resolve(t.result):i.reject(new M("NATIVE_PROTOCOL_INVALID"))}async write(e){this.options.assertOwner();let t=this.socket;if(!t||t.readyState!==Be.default.OPEN||!this.accepting)throw new M("NATIVE_DISCONNECTED");await new Promise((i,s)=>t.send(JSON.stringify(e),n=>n?s(new M("NATIVE_DISCONNECTED")):i())),this.options.assertOwner()}async request(e,t,i=1e4,s){if(!this.initialized&&e!=="initialize")throw new M("NATIVE_DISCONNECTED");if(!Number.isFinite(i)||i<=0||i>3e5)throw new M("NATIVE_PROTOCOL_INVALID");if(s?.aborted)throw new M("NATIVE_REQUEST_CANCELLED");let n=this.requestPrefix+ ++this.sequence,o=new Promise((l,u)=>{let h=()=>{this.pending.delete(n),f.reject(new M("NATIVE_REQUEST_CANCELLED"))},p=()=>{s?.removeEventListener("abort",h),clearTimeout(m)},m=setTimeout(()=>{this.pending.delete(n),u(new M("NATIVE_RPC_TIMEOUT",void 0,{initializeTimedOut:e==="initialize",threadResumeTimedOut:e==="thread/resume",otherRpcTimedOut:e!=="initialize"&&e!=="thread/resume"})),s?.removeEventListener("abort",h)},i),f={resolve:g=>{p(),l(g)},reject:g=>{p(),u(g)},timer:m};this.pending.set(n,f),s?.addEventListener("abort",h,{once:!0}),s?.aborted&&h()}).then(l=>({value:l}),l=>({error:l}));try{s?.aborted||await this.write({id:n,method:e,params:t})}catch(l){let u=this.pending.get(n);throw u&&(clearTimeout(u.timer),this.pending.delete(n),u.reject(new M("NATIVE_DISCONNECTED"))),await o,l}let d=await o;if("error"in d)throw d.error;return d.value}async notify(e,t){await this.write({method:e,...t===void 0?{}:{params:t}})}async respond(e,t){if(!this.initialized)throw new M("NATIVE_DISCONNECTED");await this.write({id:e,result:t})}async close(){this.intentionalClose=!0,this.accepting=!1,this.initialized=!1,this.rejectPending();let e=this.socket;e&&e.readyState!==Be.default.CLOSED&&await new Promise(t=>{let i=setTimeout(()=>{e.terminate(),t()},2e3);e.once("close",()=>{clearTimeout(i),t()}),e.close()}),await this.joinHandlers(),this.socket=null}async joinHandlers(){await Promise.allSettled([...this.handlers])}};var qs=256,ni=2*1024*1024;function $(){throw Error("NATIVE_QUESTION_RESUME_NOT_PROVEN")}function Ve(a){return!a||typeof a!="object"||Array.isArray(a)?$():a}async function ri(a,e,t,i,s){if(!i.length||i.length>64||i.some(o=>o.kind!=="async"||o.threadId!==t))return $();let n=()=>{a.assertCurrent(),s()},r=new xe({...a.record.endpoint,instanceId:a.record.instanceId,pluginVersion:e,maxPayloadBytes:4*1024*1024,assertOwner:n,onMessage:()=>{},onFailure:()=>{}});try{await r.connect();let o=Date.now()+2e3,d=async(w,E)=>{n();let R=o-Date.now();if(R<=0)return $();let b=Ve(await r.request(w,E,R));return n(),Buffer.byteLength(JSON.stringify(b))>ni?$():b},l=Ve((await d("thread/read",{threadId:t,includeTurns:!1})).thread);if(l.id!==t||l.sessionId!==t||l.ephemeral!==!1||l.parentThreadId!=null)return $();let u=new Set(i.map(w=>JSON.stringify([w.turnId,w.itemId]))),h=[],p=new Set,m=new Set,f;for(let w=0;w<8&&u.size;w++){let E=await d("thread/items/list",{threadId:t,limit:32,sortDirection:"desc",...f?{cursor:f}:{}});if(!Array.isArray(E.data)||!E.data.length||E.data.length>32)return $();for(let R of E.data){let b=Ve(R),_=Ve(b.item);if(typeof b.turnId!="string"||!b.turnId.length||typeof _.id!="string"||!_.id.length)return $();let x=JSON.stringify([b.turnId,_.id]);if(p.has(x))return $();if(p.add(x),h.push({turnId:b.turnId,item:_}),u.delete(x),!u.size)break}if(h.length>qs||Buffer.byteLength(JSON.stringify(h))>ni)return $();if(!u.size)break;if(typeof E.nextCursor!="string"||!E.nextCursor.length||m.has(E.nextCursor))return $();f=E.nextCursor,m.add(f)}if(u.size)return $();let g=new Set(i.map(w=>w.turnId)),y=[],S=new Set;f=void 0,m.clear();for(let w=0;w<8&&g.size;w++){let E=await d("thread/turns/list",{threadId:t,limit:32,sortDirection:"desc",itemsView:"notLoaded",...f?{cursor:f}:{}});if(!Array.isArray(E.data)||!E.data.length||E.data.length>32)return $();for(let R of E.data){let b=Ve(R);if(typeof b.id!="string"||typeof b.status!="string"||b.itemsView!=="notLoaded"||!Array.isArray(b.items)||b.items.length||S.has(b.id))return $();S.add(b.id),g.delete(b.id)&&y.push({id:b.id,status:b.status})}if(!g.size)break;if(typeof E.nextCursor!="string"||!E.nextCursor.length||m.has(E.nextCursor))return $();f=E.nextCursor,m.add(f)}if(g.size)return $();let I=await d("thread/items/list",{threadId:t,limit:1,sortDirection:"desc"});return!Array.isArray(I.data)||I.data.length!==1||I.data[0].turnId!==h[0].turnId||JSON.stringify(I.data[0].item)!==JSON.stringify(h[0].item)?$():{threadId:t,nativeInstanceId:a.record.instanceId,items:h,turns:y}}finally{await r.close()}}var H=class extends Error{constructor(t){super(t);this.code=t;this.name="NativeRuntimeError"}},Te=()=>{throw new H("NATIVE_LAUNCH_AUTHORITY_INVALID")};function it(a){return!a||typeof a!="object"||Array.isArray(a)?Te():a}function Bs(a,e){return Object.keys(a).sort().join(",")===e.sort().join(",")}function oi(a){return typeof a=="number"&&Number.isSafeInteger(a)&&a>0}function ai(a){try{process.kill(a,0)}catch{Te()}}async function li(a,e){if(!Z.isAbsolute(a)||Z.normalize(a)!==a||Z.basename(a)!=="launch.json")return Te();let t=typeof process.getuid=="function"?process.getuid():void 0,i=await ge.promises.open(a,ge.constants.O_RDONLY|ge.constants.O_NOFOLLOW),s,n;try{let o=await i.stat();if(!o.isFile()||o.nlink!==1||(o.mode&63)!==0||o.size>2*1024*1024||t!==void 0&&o.uid!==t)return Te();let d=it(JSON.parse(await i.readFile("utf8")));if(!Bs(d,["version","instanceId","root","launcher","server","endpoint","plan"])||d.version!==1||d.instanceId!==e||typeof e!="string"||!e.length||!oi(d.launcher?.pid)||d.launcher.host!==di.hostname()||!oi(d.server?.pid)||d.root?.path!==Z.dirname(a)||!Number.isSafeInteger(d.root.dev)||!Number.isSafeInteger(d.root.ino)||d.root.uid!==t||!Z.isAbsolute(d.endpoint?.socketPath??"")||!Number.isSafeInteger(d.endpoint?.socketIdentity?.dev)||!Number.isSafeInteger(d.endpoint?.socketIdentity?.ino)||!Z.isAbsolute(d.plan?.workingDirectory??"")||d.plan.resumeThreadId!==null&&typeof d.plan.resumeThreadId!="string")return Te();let l=await i.stat();if(o.dev!==l.dev||o.ino!==l.ino||o.size!==l.size||o.mtimeMs!==l.mtimeMs)return Te();s=d,n={dev:o.dev,ino:o.ino,size:o.size,mtimeMs:o.mtimeMs}}finally{await i.close()}let r=()=>{let o=(0,ge.lstatSync)(s.root.path),d=(0,ge.lstatSync)(a);if(!o.isDirectory()||o.isSymbolicLink()||(o.mode&63)!==0||o.dev!==s.root.dev||o.ino!==s.root.ino||o.uid!==s.root.uid||!d.isFile()||d.isSymbolicLink()||d.nlink!==1||(d.mode&63)!==0||d.dev!==n.dev||d.ino!==n.ino||d.size!==n.size||d.mtimeMs!==n.mtimeMs||d.uid!==s.root.uid)return Te();ai(s.launcher.pid),ai(s.server.pid)};return r(),{record:JSON.parse(JSON.stringify(s)),assertCurrent:r}}function xt(a){let e=it(a);if(typeof e.id!="string"||!e.id.length)throw new H("NATIVE_ROOT_INVALID_ID");if(e.sessionId!==e.id||e.parentThreadId!=null)throw new H("NATIVE_ROOT_INVALID_SESSION");if(e.ephemeral!==!1)throw new H("NATIVE_ROOT_INVALID_PERSISTENCE");if(typeof e.cwd!="string"||!Z.isAbsolute(e.cwd))throw new H("NATIVE_ROOT_INVALID_CWD");if(!Number.isFinite(e.createdAt)||e.createdAt<0)throw new H("NATIVE_ROOT_INVALID_TIMESTAMP");if(e.path!==null&&(typeof e.path!="string"||!Z.isAbsolute(e.path)))throw new H("NATIVE_ROOT_INVALID_PATH");if(typeof e.cliVersion!="string")throw new H("NATIVE_ROOT_INVALID_VERSION");if(typeof e.modelProvider!="string")throw new H("NATIVE_ROOT_INVALID_PROVIDER");return{id:e.id,sessionId:e.sessionId,cwd:e.cwd,createdAt:e.createdAt,path:e.path,cliVersion:e.cliVersion,modelProvider:e.modelProvider}}var st=class{constructor(e){this.options=e;this.root=null;this.ready=!1;this.generation=0;this.bindingDepth=0;this.binding=Promise.resolve();this.closed=!1;this.refreshPending=null;this.pendingControls=new Map;this.pendingFiles=new Map;this.client=new xe({...e.authority.record.endpoint,instanceId:e.authority.record.instanceId,pluginVersion:e.pluginVersion,assertOwner:e.authority.assertCurrent,onMessage:t=>this.observe(t),onFailure:t=>t.handlerFailure?e.onFailure(t.code,t.handlerFailure):e.onFailure(t.code)})}get thread(){return this.root?{...this.root}:null}controlFacts(){return JSON.parse(JSON.stringify([...this.pendingFiles.values(),...this.pendingControls.values()]))}isCurrentControl(e){let t=e.id===void 0?void 0:this.pendingControls.get(e.id);return!this.closed&&!!t&&t.method===e.method&&(0,kt.isDeepStrictEqual)(t.params,e.params)}hasPendingControl(){return this.pendingControls.size>0}readQuestionResumeWindow(e){let t=this.root?.id;return!t||this.closed?Promise.reject(new H("NATIVE_BINDING_FAILED")):ri(this.options.authority,this.options.pluginVersion,t,e,()=>{if(this.closed||this.root?.id!==t)throw new H("NATIVE_BINDING_FAILED")})}async start(){await this.client.connect();let e=this.options.recoveryThreadId??this.options.authority.record.plan.resumeThreadId;e&&await this.bind(await this.readMetadata(e))}bind(e){let t=this.options.recoveryThreadId??this.options.authority.record.plan.resumeThreadId;if(!this.root&&t&&e.id!==t)return Promise.reject(new H("NATIVE_ROOT_INVALID"));if(this.root&&e.id===this.root.id&&e.cwd!==this.root.cwd)return Promise.reject(new H("NATIVE_ROOT_INVALID"));if(this.root&&(0,kt.isDeepStrictEqual)(this.root,e)&&(this.ready||this.bindingDepth>0))return this.binding;(!this.root||this.root.id!==e.id)&&(this.generation++,this.ready=!1,this.pendingControls.clear(),this.pendingFiles.clear());let i=this.generation;this.root={...e},this.bindingDepth++;let s=this.binding.then(async()=>{if(this.closed)throw new H("NATIVE_BINDING_FAILED");await this.options.onRoot({...e}),i===this.generation&&!this.closed&&(this.ready=!0)});return this.binding=s.catch(()=>{}),s.then(()=>{this.bindingDepth--},()=>{this.bindingDepth--}),s}observe(e){if(this.closed)return;let t=e.params;if(e.method==="thread/started"){let s=t?.thread;return s?.ephemeral===!0||s?.parentThreadId!=null||s?.sessionId!==s?.id?void 0:this.bind(xt(s))}if(!this.root||t?.threadId!==this.root.id)return;if(e.id!==void 0&&this.pendingControls.set(e.id,JSON.parse(JSON.stringify(e))),e.method==="serverRequest/resolved"&&this.pendingControls.delete(t.requestId),["item/started","item/completed"].includes(e.method)&&t.item?.type==="fileChange"&&this.pendingFiles.set(t.item.id,JSON.parse(JSON.stringify(e))),e.method==="item/completed"&&["commandExecution","fileChange"].includes(t.item?.type)){for(let[s,n]of this.pendingControls){let r=n.params;r.turnId===t.turnId&&r.itemId===t.item.id&&this.pendingControls.delete(s)}this.pendingFiles.delete(t.item.id)}if(!this.ready&&this.bindingDepth===0&&e.method==="turn/started"&&this.bind(this.root).catch(()=>{}),["item/agentMessage/delta","item/reasoning/textDelta","item/commandExecution/outputDelta"].includes(e.method))return;if(this.ready)return this.options.onMessage(e);let i=this.generation;return this.binding.then(()=>{if(!this.ready||this.closed||i!==this.generation)throw new H("NATIVE_BINDING_FAILED");return this.options.onMessage(e)})}async readMetadata(e){let t=await this.client.request("thread/resume",{threadId:e,excludeTurns:!0},2e3),i=xt(it(t).thread);if(i.id!==e)throw new H("NATIVE_ROOT_INVALID");return i}refreshMetadata(){if(this.refreshPending)return this.refreshPending;if(!this.root||this.closed)return Promise.resolve(null);let e=this.root.id,t=(async()=>{let i=Date.now()+2e3;for(let s=0;s<10&&Date.now()<i;s++)try{let n=await this.client.request("thread/resume",{threadId:e,excludeTurns:!0},Math.max(1,i-Date.now())),r=xt(it(n).thread);if(r.id!==e||this.root?.id!==e||this.closed)throw new H("NATIVE_ROOT_INVALID");return await this.bind(r),r}catch(n){if(!(n instanceof M)||n.code!=="NATIVE_RPC_REJECTED"||![-32600,-32601].includes(n.rpcCode??0))throw n;s<9&&Date.now()<i&&await new Promise(r=>setTimeout(r,Math.min(100,i-Date.now())))}return null})();return this.refreshPending=t,t.then(()=>{this.refreshPending=null},()=>{this.refreshPending=null}),t}async close(){this.closed=!0,await this.client.close(),await this.binding,await this.refreshPending?.catch(()=>{})}};var lt=require("node:crypto"),Y=require("node:util"),U=require("@quantiya/codevibe-core");var ci=require("node:crypto"),ui=D(require("node:path")),nt=require("@quantiya/codevibe-core"),T=class extends Error{constructor(t){super(t);this.code=t;this.name="NativeControlError"}},le=class extends T{constructor(){super("NATIVE_CONTROL_UNSUPPORTED")}};function ee(){throw new T("NATIVE_CONTROL_INVALID")}var he=a=>!a||typeof a!="object"||Array.isArray(a)?ee():a,B=a=>typeof a!="string"||!a.length?ee():a,pi=a=>(0,ci.createHash)("sha256").update(JSON.stringify(a)).digest("hex");function hi(a,e){let t=a.payload;if(a.type!=="event_msg"||t?.type!=="item_completed"||t.item?.type!=="AgentMessage"||t.item.delivery!=="async")return null;if(t.thread_id!==e||typeof t.turn_id!="string"||!t.turn_id.length)throw new T("NATIVE_QUESTION_MISMATCH");let i={type:"agentMessage",id:t.item.id,delivery:"async",questions:t.item.questions};return rt(e,t.turn_id,i),{method:"item/completed",params:{threadId:e,turnId:t.turn_id,item:i}}}function mi(a,e){let t=a.payload;if(a.type!=="event_msg"||t?.type!=="item_completed"||!["UserMessage","FunctionCallOutput"].includes(t.item?.type))return null;if(t.thread_id!==e||typeof t.turn_id!="string"||!t.turn_id.length)throw new T("NATIVE_QUESTION_MISMATCH");let i=he(t.item);B(i.id);let s;if(i.type==="UserMessage"){if(i.client_id!==null&&typeof i.client_id!="string"||!Array.isArray(i.content))return ee();let n=i.content.map(r=>{let o=he(r);if(o.type==="image"){if(typeof o.image_url=="string"==(typeof o.file_id=="string"))return ee();let{image_url:d,file_id:l,...u}=o;return{...u,...d!==void 0?{url:B(d)}:{fileId:B(l)}}}if(o.type==="local_image")return{type:"localImage",detail:null,path:B(o.path)};if(o.type==="local_audio")return{type:"localAudio",path:B(o.path)};if(o.type==="audio"&&typeof o.audio_url=="string"){let{audio_url:d,...l}=o;return{...l,url:d}}return r});s={type:"userMessage",id:i.id,clientId:i.client_id,content:n}}else{if(i.namespace!=="functions"||i.name!=="request_user_input_async")return null;s={type:"functionCallOutput",id:i.id,name:i.name,namespace:i.namespace,output:B(i.output)}}return{method:"item/completed",params:{threadId:e,turnId:t.turn_id,item:s}}}function rt(a,e,t){let i=he(t);if(i.type!=="agentMessage"||i.delivery!=="async"||i.questions===null)return[];let s=B(i.id);return B(a),B(e),Array.isArray(i.questions)?i.questions.map((n,r)=>{let o=he(n),d=B(o.title);if(o.options!==null&&(!Array.isArray(o.options)||!o.options.length||!o.options.every(u=>typeof u=="string"&&u.length>0)))return ee();let l=o.options===null?null:[...o.options];return{key:pi(["codex-native-question",a,s,r]),threadId:a,turnId:e,itemId:s,questionIndex:r,questionItemId:JSON.stringify(["request_user_input_async",s,r]),title:d,options:l}}):ee()}function fi(a,e,t){if(t!==null&&t!==a.questionItemId)throw new T("NATIVE_QUESTION_MISMATCH");let i=e.trim(),s=Number(i),n=Number.isSafeInteger(s)&&String(s)===i,r;if(a.options?.length){if(!n){if(t!==null)throw new T("NATIVE_OPTION_INVALID");return{kind:"ordinary"}}if(s<1||s>a.options.length)throw new T("NATIVE_OPTION_INVALID");r=a.options[s-1]}else{if(t===null)return{kind:"ordinary"};if(!i.length)throw new T("NATIVE_OPTION_INVALID");r=e}return{kind:"answer",answer:r,output:JSON.stringify([{answer:r,question:a.title,questionItemId:a.questionItemId}])}}function Dt(a,e,t,i,s=2){let n=t.method==="item/commandExecution/requestApproval"?"command":t.method==="item/fileChange/requestApproval"?"file":null;if(!n)return null;if(typeof t.id!="string"&&typeof t.id!="number"||typeof t.id=="string"&&!t.id.length||typeof t.id=="number"&&(!Number.isSafeInteger(t.id)||t.id<0))return ee();let r=he(t.params),o=B(r.threadId),d=B(r.turnId),l=B(r.itemId);if(o!==e)throw new T("NATIVE_CONTROL_UNSUPPORTED");let u,h=!1;if(n==="command"){let m=new Set(["kind","threadId","turnId","itemId","startedAtMs","approvalId","environmentId","reason","networkApprovalContext","additionalPermissions","command","cwd","commandActions","proposedExecpolicyAmendment","proposedNetworkPolicyAmendments","availableDecisions"]);if(Object.keys(r).some(f=>!m.has(f))||r.kind!=null&&r.kind!=="command"||r.approvalId!=null||r.additionalPermissions!=null||r.networkApprovalContext!=null||r.environmentId!=null&&r.environmentId!=="local"||r.proposedNetworkPolicyAmendments!=null&&(!Array.isArray(r.proposedNetworkPolicyAmendments)||r.proposedNetworkPolicyAmendments.length))throw new le;if(B(r.command),B(r.cwd),!Array.isArray(r.availableDecisions))return ee();if(u=r.availableDecisions,s===1){let f=u.length;u=u.filter(g=>g==="accept"||g==="cancel"),h=u.length!==f}}else{let m=new Set(["threadId","turnId","itemId","startedAtMs","reason","grantRoot"]);if(Object.keys(r).some(f=>!m.has(f))||r.grantRoot!=null)throw new le;if(u=s===1?["accept","decline"]:["accept","acceptForSession","cancel"],!i||i.nativeInstanceId!==a||i.threadId!==o||i.turnId!==d||i.item.type!=="fileChange"||i.item.id!==l||!Array.isArray(i.item.changes)||!i.item.changes.length)throw new le;for(let f of i.item.changes)if(B(f.path),he(f.kind),typeof f.diff!="string")return ee()}if(r.reason!=null&&typeof r.reason!="string")return ee();let p=u.map((m,f)=>{let g,y;if(m==="accept")g=m,y=s===1?"Approve once":"Yes, proceed";else if(m==="cancel"||n==="file"&&m==="decline")g=m,y=m==="decline"?"Reject edit":s===1?"Cancel":"No, and tell Codex what to do differently";else if(m==="acceptForSession")g=m,y=n==="file"?"Yes, and don't ask again for these files":"Approve for this session";else if(n==="command"&&m&&typeof m=="object"&&!Array.isArray(m)){let S=he(m),I=he(S.acceptWithExecpolicyAmendment),w=I.execpolicy_amendment;if(Object.keys(S).length!==1||Object.keys(I).length!==1||!Array.isArray(w)||!w.length||!w.every(R=>typeof R=="string"&&R.length>0&&!R.includes("\0"))||r.proposedExecpolicyAmendment!=null&&(0,nt.stableStringify)(w)!==(0,nt.stableStringify)(r.proposedExecpolicyAmendment))throw new le;g=JSON.parse(JSON.stringify(m)),y="Yes, and don't ask again for commands that start with `"+w.map(R=>/^[A-Za-z0-9_./:@%+=,-]+$/.test(R)?R:"'"+R.split("'").join("'\\''")+"'").join(" ")+"`"}else throw new le;return{number:String(f+1),label:y,decision:g}});if(!p.length||new Set(p.map(m=>(0,nt.stableStringify)(m.decision))).size!==p.length)throw new le;return{key:pi(["codex-native-approval",a,o,d,l,t.id]),nativeInstanceId:a,threadId:o,turnId:d,itemId:l,requestId:t.id,kind:n,request:JSON.parse(JSON.stringify(t)),observedFile:i?JSON.parse(JSON.stringify(i)):null,choices:p,otherChoicesOnDesktop:h}}function ke(a,e,t){let i=t.approvalPresentationVersion;if(i!==void 0&&i!==2)throw new T("NATIVE_CONTROL_UNSUPPORTED");return Dt(a,e,t.request,t.observedFile??void 0,i===2?2:1)}function vi(a,e){let t=a.choices.find(i=>i.number===e.trim());if(!t)throw new T("NATIVE_OPTION_INVALID");return{decision:JSON.parse(JSON.stringify(t.decision))}}function ot(a,e,t,i=[]){if(B(a),B(e),!t.length&&!i.length)return ee();for(let s of i)if(!ui.isAbsolute(s)||s.includes("\0"))return ee();return{threadId:a,clientUserMessageId:e,input:[...t.length?[{type:"text",text:t,text_elements:[]}]:[],...i.map(s=>({type:"localImage",detail:null,path:B(s)}))]}}function gi(a,e){return{threadId:B(a),input:[],toolOutput:{namespace:"functions",name:"request_user_input_async",output:B(e),retain:!0}}}function De(a){let e=(a.options??[]).map((i,s)=>({number:String(s+1),text:i})),t=e.length?"Reply with the number of your choice.":"Type your answer.";return{content:[a.title,...e.map(i=>`${i.number}. ${i.text}`),t].join(`
3
3
 
4
- `),metadata:{isApprovalHint:!1,isQueuedQuestion:!0,prompt_source:"native_app_server",tool_name:"request_user_input_async",tool_use_id:d.itemId,turn_id:d.turnId,options:e,questions:[{question:d.title,multiSelect:!1,options:e,instructions:t}],submitMap:Object.fromEntries(e.map(i=>[i.number,i.number])),instructions:t}}}function it(d,e){e!==null&&B(e);let t=ce(d.request.params),i=d.kind==="command"?"Approve command?":"Approve file changes?",s=d.kind==="command"?`${B(t.command)}
4
+ `),metadata:{isApprovalHint:!1,isQueuedQuestion:!0,prompt_source:"native_app_server",tool_name:"request_user_input_async",tool_use_id:a.itemId,turn_id:a.turnId,options:e,questions:[{question:a.title,multiSelect:!1,options:e,instructions:t}],submitMap:Object.fromEntries(e.map(i=>[i.number,i.number])),instructions:t}}}function yi(a,e){e!==null&&B(e);let t=he(a.request.params),i=a.kind==="command"?"Approve command?":"Approve file changes?",s=a.kind==="command"?`${B(t.command)}
5
5
 
6
- Working directory: ${B(t.cwd)}`:d.observedFile.item.changes.map(o=>`${o.path}
6
+ Working directory: ${B(t.cwd)}`:a.observedFile.item.changes.map(o=>`${o.path}
7
7
  ${o.diff}`).join(`
8
8
 
9
- `),n=d.choices.map(o=>({number:o.number,text:o.label})),r="Reply with the number of your choice.";return{content:[i,s,...typeof t.reason=="string"&&t.reason.length?[t.reason]:[],...n.map(o=>`${o.number}. ${o.text}`),r,...d.otherChoicesOnDesktop?["Additional permission choices are available on desktop."]:[]].join(`
9
+ `),n=a.choices.map(o=>({number:o.number,text:o.label})),r="Reply with the number of your choice.";return{content:[i,s,...typeof t.reason=="string"&&t.reason.length?[t.reason]:[],...n.map(o=>`${o.number}. ${o.text}`),r,...a.otherChoicesOnDesktop?["Additional permission choices are available on desktop."]:[]].join(`
10
10
 
11
- `),metadata:{isApprovalHint:!0,isQueuedQuestion:!1,prompt_source:"native_app_server",tool_name:d.kind==="command"?"exec_command":"apply_patch",tool_use_id:d.itemId,turn_id:d.turnId,options:n,questions:[{question:i,multiSelect:!1,options:n,instructions:r}],submitMap:Object.fromEntries(n.map(o=>[o.number,o.number])),instructions:r,...e!==null?{preemptedQueuedQuestionId:e}:{}}}}var li=require("node:crypto");var Fe=()=>{throw new T("NATIVE_CONTROL_INVALID")};function ci(d){return!d||typeof d!="object"||Array.isArray(d)?Fe():d}function pi(d){try{return ci(JSON.parse(d.detailsJson))}catch{return Fe()}}function be(d){let e=pi(d),t=JSON.stringify(["request_user_input_async",d.itemId,e.questionIndex]);return!Number.isSafeInteger(e.questionIndex)||e.questionIndex<0||e.itemId!==d.itemId||e.questionItemId!==t||typeof e.title!="string"||!e.title.length||e.options!==null&&(!Array.isArray(e.options)||!e.options.every(i=>typeof i=="string"&&i.length))?Fe():{key:d.key,threadId:d.threadId,turnId:d.turnId,itemId:d.itemId,questionIndex:e.questionIndex,questionItemId:t,title:e.title,options:e.options===null?null:[...e.options]}}function ui(d){let e=d.controls.filter(l=>l.scope.sessionId===d.scope.sessionId&&l.scope.sessionGenerationId===d.scope.sessionGenerationId&&l.scope.expectedSessionKeyGen===d.scope.expectedSessionKeyGen&&l.threadId===d.threadId&&!l.cloudResolved),t=new Set(d.pendingApprovalKeys),i=t.size>0||d.otherNativeApprovalPending,s=e.filter(l=>l.state==="OPEN"&&l.answerEventId===null),n=Number(d.text.trim()),r=Number.isSafeInteger(n)&&String(n)===d.text.trim(),o;if(d.promptId!==null){if(o=e.find(l=>{try{return ci(JSON.parse(l.raiseJson)).promptId===d.promptId}catch{return Fe()}}),!o||o.state!=="OPEN"||o.answerEventId!==null||(o.kind==="async"?i:!t.has(o.key)))throw new T("NATIVE_QUESTION_MISMATCH")}else if(r){if(i||e.length)throw new T("NATIVE_CONTEXT_REQUIRED")}else if(!i&&d.text.trim().length&&!d.localImages?.length&&s.filter(f=>f.kind==="async").filter(f=>be(f).options===null).length)throw new T("NATIVE_CONTEXT_REQUIRED");if(o){if(d.localImages?.length)throw new T("NATIVE_OPTION_INVALID");if(o.nativeInstanceId!==d.nativeInstanceId)throw new T("NATIVE_CONTROL_UNSUPPORTED");if(o.kind==="async"){let l=be(o),p=oi(l,d.text,l.questionItemId);if(p.kind==="answer")return{intent:{kind:"async",threadId:d.threadId,questionItemId:l.questionItemId,output:p.output},controlKey:o.key,heldForApproval:!1}}else{let l=Pe(d.nativeInstanceId,d.threadId,pi(o));if(!l||l.kind!==o.kind||l.turnId!==o.turnId||l.itemId!==o.itemId)return Fe();let{decision:p}=ai(l,d.text);return{intent:{kind:"approval",method:l.kind,threadId:l.threadId,turnId:l.turnId,itemId:l.itemId,nativeInstanceId:l.nativeInstanceId,requestId:l.requestId,decision:p,detailsSha256:(0,li.createHash)("sha256").update(o.detailsJson).digest("hex")},controlKey:o.key,heldForApproval:!1}}}let a=tt(d.threadId,d.eventId,d.text,d.localImages);return{intent:{kind:"user",threadId:d.threadId,clientId:d.eventId,contentJson:JSON.stringify(a.input)},controlKey:null,heldForApproval:i}}var hi=require("node:crypto");var _s=2*1024*1024,Cs=d=>JSON.parse(JSON.stringify(d)),Ns=d=>(0,hi.createHash)("sha256").update(JSON.stringify(d)).digest("hex");function re(d){if(!d||typeof d!="object"||Array.isArray(d))throw Error("NATIVE_RECEIPT_INVALID");return d}function Nt(d){return typeof d=="string"&&d.length>0&&d.length<=512}function As(d){return Nt(d)||typeof d=="number"&&Number.isSafeInteger(d)&&d>=0}function Os(d){return{nativeInstanceId:d.nativeInstanceId,request:d.request,resolved:d.resolved,completed:d.completed,turnCompleted:d.turnCompleted}}function st(d,e){let t=re(d);if(Buffer.byteLength(JSON.stringify(t))>_s||Object.keys(t).sort().join(",")!=="completed,digest,nativeInstanceId,request,resolved,turnCompleted"||t.nativeInstanceId!==e||!Nt(e))throw Error("NATIVE_RECEIPT_INVALID");let i=re(t.request),s=re(t.resolved),n=re(t.turnCompleted),r=re(i.params),o=re(s.params),a=re(n.params),l=re(a.turn),p=i.method==="item/commandExecution/requestApproval"?"commandExecution":i.method==="item/fileChange/requestApproval"?"fileChange":null;if(!p||!As(i.id)||![r.threadId,r.turnId,r.itemId].every(Nt)||s.method!=="serverRequest/resolved"||o.threadId!==r.threadId||o.requestId!==i.id||n.method!=="turn/completed"||a.threadId!==r.threadId||l.id!==r.turnId||!["completed","failed","interrupted"].includes(l.status))throw Error("NATIVE_RECEIPT_INVALID");if(t.completed===null){if(p!=="fileChange"||l.status!=="interrupted")throw Error("NATIVE_RECEIPT_INVALID")}else{let u=re(t.completed),m=re(u.params),h=re(m.item);if(u.method!=="item/completed"||m.threadId!==r.threadId||m.turnId!==r.turnId||h.id!==r.itemId||h.type!==p||!["completed","failed","declined"].includes(h.status))throw Error("NATIVE_RECEIPT_INVALID")}let f=Os(t);if(t.digest!==Ns(f))throw Error("NATIVE_RECEIPT_INVALID");return{...Cs(f),digest:t.digest}}var H=d=>JSON.parse(JSON.stringify(d)),Re=d=>(0,mi.createHash)("sha256").update(d).digest("hex"),j=(d,e)=>d.sessionId===e.sessionId&&d.sessionGenerationId===e.sessionGenerationId&&d.expectedSessionKeyGen===e.expectedSessionKeyGen;function O(d){if(!d||typeof d!="object"||Array.isArray(d))throw new T("NATIVE_CONTROL_INVALID");return d}var Me=class extends T{constructor(){super("NATIVE_CONTROL_UNSUPPORTED")}},nt=class{constructor(e){this.options=e;this.accepting=!0;this.stopped=!1;this.factTail=Promise.resolve();this.pending=new Set;this.nativeRequests=new Map;this.approvalAuthorities=new Map;this.observedFiles=new Map;this.publications=new Map;this.resolutions=new Map;this.acknowledgements=new Map;this.rejectionSettlements=new Map;this.published=new Set;this.deferredQuestions=new Set;this.questionKeys=new Map;this.completedApprovals=new Map;this.recovery=null;this.owner=H(e.owner),this.instanceId=e.native.instanceId,this.accepting=!e.deferActivation,this.dispatch=new W.CodexNativeDispatcher({store:e.store,owner:this.owner,updateStatus:e.updateStatus,assertNativeTarget:t=>this.assertTarget(t),isNativeBlocked:t=>t.kind!=="approval"&&(this.nativeRequests.size>0||!!this.options.hasPendingControl?.()),send:t=>this.send(t),onFailure:t=>this.report(t)})}get isAccepting(){return this.accepting}get isActivationPending(){return!this.accepting&&!this.stopped}report(e){try{Promise.resolve(this.options.onFailure(e)).catch(()=>{})}catch{}}track(e){return this.pending.add(e),e.then(()=>this.pending.delete(e),()=>{this.pending.delete(e),this.report("NATIVE_ADAPTER_OPERATION_FAILED")}),e}assertTarget(e){if(this.options.assertCurrent(),this.options.native.instanceId!==this.instanceId||e&&e.threadId!==this.options.threadId||e?.kind==="approval"&&e.nativeInstanceId!==this.instanceId)throw new T("NATIVE_CONTROL_UNSUPPORTED");if(e?.kind==="approval"){let t=this.nativeRequests.get(e.requestId),i=this.approvalAuthorities.get(e.requestId);if(!t||this.options.isCurrentControl?.(t)===!1)throw new Me;if(!i||i.detailsSha256!==e.detailsSha256||t.method!==i.method||!(0,Z.isDeepStrictEqual)(t.params,i.params))throw new T("NATIVE_CONTROL_UNSUPPORTED")}}async send(e){if(this.assertTarget(e),e.kind==="user")await this.options.native.request("turn/start",{threadId:e.threadId,clientUserMessageId:e.clientId,input:JSON.parse(e.contentJson)});else if(e.kind==="async")await this.options.native.request("turn/start",di(e.threadId,e.output));else{let t=this.nativeRequests.get(e.requestId),i=t?O(t.params):null;if(!t||i?.threadId!==e.threadId||i.turnId!==e.turnId||i.itemId!==e.itemId||t.method!==(e.method==="command"?"item/commandExecution/requestApproval":"item/fileChange/requestApproval"))throw new T("NATIVE_CONTROL_UNSUPPORTED");await this.options.native.respond(e.requestId,{decision:e.decision})}}admit(e){let t;try{if(!this.accepting)throw new T("NATIVE_CONTROL_UNSUPPORTED");t=H(e)}catch(i){return this.track(Promise.reject(i))}return this.track((async()=>{if(this.assertTarget(),t.sessionId!==this.owner.scope.sessionId)throw new T("NATIVE_QUESTION_MISMATCH");let i=await this.options.store.snapshot(this.owner),s=i.entries.find(l=>l.event.eventId===t.eventId);if(i.rejections.some(l=>l.event.eventId===t.eventId)){let l=await this.options.store.rejectUnappliedInput(this.owner,(0,W.snapshotCodexNativeEvent)(t));if(!l)throw new T("NATIVE_CONTROL_INVALID");return this.settleRejection(l)}if(s){if(s.kind!=="INPUT"||!j(s.scope,this.owner.scope))throw new T("NATIVE_QUESTION_MISMATCH");let l=JSON.parse(s.bodyJson);if(s.phase==="PREPARED"&&l.kind==="user"){let f=await this.options.decode(H(t));if(JSON.stringify(tt(l.threadId,t.eventId,f.text,f.localImages).input)!==l.contentJson)throw new T("NATIVE_CONTROL_INVALID")}let p=await this.dispatch.admit(t,l,s.controlKey);return s.nativeReceiptSha256&&s.cloudAck!=="EXECUTED"&&this.startAcknowledgement(s),p}let n=await this.options.decode(H(t));this.assertTarget();let r=await this.options.store.snapshot(this.owner),o=this.pendingApprovalKeys(r.controls),a=this.firstQuestion(r.controls);try{let l=ui({...n,controls:r.controls.filter(p=>p.kind!=="async"||p.key===a?.key),scope:this.owner.scope,nativeInstanceId:this.instanceId,threadId:this.options.threadId,eventId:t.eventId,pendingApprovalKeys:o,otherNativeApprovalPending:this.nativeRequests.size>o.length||o.length===0&&!!this.options.hasPendingControl?.()});return await this.dispatch.admit(t,l.intent,l.controlKey)}catch(l){if(!(l instanceof T&&["NATIVE_QUESTION_MISMATCH","NATIVE_CONTEXT_REQUIRED","NATIVE_OPTION_INVALID"].includes(l.code)||l instanceof W.CodexNativeStateError&&["NATIVE_CONTROL_UNAVAILABLE","NATIVE_INPUT_REJECTED"].includes(l.code)))throw l;let p=(0,W.snapshotCodexNativeEvent)(t),u=(n.promptId?await this.options.store.rejectAnsweredControl(this.owner,p,n.promptId):null)??await this.options.store.rejectUnappliedInput(this.owner,p);if(!u)throw l;return this.settleRejection(u)}})())}settleRejection(e){let t=e.event.eventId,i=this.rejectionSettlements.get(t);if(i)return i;let s=this.track((async()=>{if(!this.accepting)return"RETAINED";this.assertTarget();let n=(await this.options.store.snapshot(this.owner)).rejections.find(r=>r.event.eventId===t);if(n.noticeOutcome==="MISSING"){if(!j(n.scope,this.owner.scope))return"RETAINED";let r=await this.options.publishRejectedInput(n);if(this.assertTarget(),r!=="RERAISED"&&r!=="OMITTED")return"RETAINED";await this.options.store.acknowledgeRejectionNotice(this.owner,t,r==="RERAISED"?"ACCEPTED":"OMITTED"),n={...n,noticeOutcome:r==="RERAISED"?"ACCEPTED":"OMITTED"},r==="OMITTED"&&this.report("NATIVE_REJECTION_NOTICE_OMITTED")}if(!n.noticeResolved){let r=JSON.parse(n.raiseJson);if(!await this.options.resolve({sessionId:n.scope.sessionId,promptId:r.promptId,ownerToken:r.ownerToken}))return"RETAINED";await this.options.store.resolveRejectionNotice(this.owner,t)}if(!n.cloudDelivered){let r=await this.options.updateStatus({eventId:t,sessionId:n.event.sessionId,timestamp:n.event.timestamp,deliveryStatus:W.DeliveryStatus.DELIVERED},{sessionGenerationId:n.scope.sessionGenerationId,type:n.event.type});await this.options.store.acknowledgeRejectedDelivery(this.owner,t,r)}return n.noticeOutcome==="ACCEPTED"?"REJECTED":"RETAINED"})());return this.rejectionSettlements.set(t,s),s.finally(()=>{this.rejectionSettlements.get(t)===s&&this.rejectionSettlements.delete(t)}).catch(()=>{}),s}pendingApprovalKeys(e){return e.filter(t=>t.kind!=="async"&&t.nativeInstanceId===this.instanceId&&j(t.scope,this.owner.scope)).filter(t=>{let i=O(JSON.parse(t.detailsJson)),s=this.nativeRequests.get(i.request.id);return!!s&&s.method===i.request.method&&(0,Z.isDeepStrictEqual)(s.params,i.request.params)&&this.options.isCurrentControl?.(s)!==!1}).map(t=>t.key)}observe(e){let t;try{if(t=H(e),!t.params||typeof t.params!="object"||Array.isArray(t.params))return Promise.resolve();let s=O(t.params);if(this.stopped||s.threadId!==this.options.threadId)return Promise.resolve();if(this.assertTarget(),t.id!==void 0){let n=this.nativeRequests.get(t.id);if(this.nativeRequests.set(t.id,t),n&&(n.method!==t.method||!(0,Z.isDeepStrictEqual)(n.params,t.params)))throw this.approvalAuthorities.delete(t.id),new T("NATIVE_CONTROL_INVALID")}t.method==="serverRequest/resolved"&&(this.nativeRequests.delete(s.requestId),this.approvalAuthorities.delete(s.requestId)),["item/started","item/completed"].includes(t.method)&&s.item?.type==="fileChange"&&this.observedFiles.set(s.item.id,{nativeInstanceId:this.instanceId,threadId:s.threadId,turnId:s.turnId,item:H(s.item)})}catch(s){return this.track(Promise.reject(s))}let i=this.factTail.then(()=>this.applyFact(t));return this.factTail=i.catch(()=>{}),this.track(i)}async snapshotControls(){return(await this.options.store.snapshot(this.owner)).controls}async applyFact(e){this.assertTarget();let t=O(e.params);if(e.id!==void 0){let i=(await this.snapshotControls()).filter(l=>l.nativeInstanceId===this.instanceId&&l.kind!=="async"&&O(JSON.parse(l.detailsJson)).request.id===e.id),s=i.find(l=>j(l.scope,this.owner.scope))??i[0],n=s?O(JSON.parse(s.detailsJson)).observedFile:void 0,r=s?Pe(this.instanceId,this.options.threadId,O(JSON.parse(s.detailsJson))):Ct(this.instanceId,this.options.threadId,e,this.observedFiles.get(t.itemId)??n);if(!r)return;if(s&&!(0,Z.isDeepStrictEqual)(O(JSON.parse(s.detailsJson)).request.params,e.params))throw new T("NATIVE_CONTROL_INVALID");if(s&&(s.state!=="OPEN"||!j(s.scope,this.owner.scope)))return;let o=s??this.control(r.key,r.kind,r.turnId,r.itemId,{request:r.request,observedFile:r.observedFile,approvalPresentationVersion:2});await this.options.store.putControl(this.owner,{...o,state:"OPEN",cloudResolved:!1,answerEventId:null,nativeResolutionSha256:null,nativeResolutionJson:null});let a=this.nativeRequests.get(r.requestId);if(!a||a.method!==e.method||!(0,Z.isDeepStrictEqual)(a.params,e.params)||this.options.isCurrentControl?.(a)===!1)return;this.approvalAuthorities.set(r.requestId,{method:e.method,params:H(e.params),detailsSha256:Re(o.detailsJson)}),await this.options.store.pauseOpenQuestions(this.owner),this.startPublication(o,it(r,this.pausedQuestionPromptId(await this.snapshotControls())));return}if(e.method==="serverRequest/resolved"){for(let i of await this.snapshotControls())i.kind!=="async"&&i.nativeInstanceId===this.instanceId&&O(JSON.parse(i.detailsJson)).request.id===t.requestId&&(await this.options.store.observeApprovalResolution(this.owner,i.key,{nativeInstanceId:this.instanceId,message:e}),this.startResolution(i.key));await this.reconcileApprovals(),await this.restorePausedQuestions();return}if(e.method==="item/completed"){let i=O(t.item);if(i.type==="agentMessage"&&i.delivery==="async")for(let n of et(t.threadId,t.turnId,i)){let r=(await this.snapshotControls()).find(a=>a.key===this.scopedKey(n.key));if(r){if(!(0,Z.isDeepStrictEqual)(JSON.parse(r.detailsJson),n))throw new T("NATIVE_CONTROL_INVALID");this.startPublication(r,Ce(n));continue}if(!await this.options.isFreshQuestion(n.threadId,n.turnId,n.itemId))continue;let o=this.control(n.key,"async",n.turnId,n.itemId,n);await this.options.store.putControl(this.owner,o),this.nativeRequests.size&&await this.options.store.pauseOpenQuestions(this.owner),this.startPublication(o,Ce(n))}i.type==="agentMessage"&&i.delivery==="async"&&this.questionKeys.set(i.id,et(t.threadId,t.turnId,i).map(n=>this.scopedKey(n.key)));let s=await this.options.store.snapshot(this.owner);for(let n of s.entries)this.receiptCandidate(n,i)&&(await this.options.store.reconcile(this.owner,n.event.eventId,{threadId:t.threadId,turnId:t.turnId,item:i}),this.startAcknowledgement(n),n.controlKey&&this.startResolution(n.controlKey));if(i.type==="functionCallOutput"&&i.namespace==="functions"&&i.name==="request_user_input_async")for(let n of s.controls.filter(r=>r.kind==="async"&&r.state!=="RESOLVED")){let r=JSON.parse(i.output);Array.isArray(r)&&r.some(o=>o?.questionItemId===JSON.parse(n.detailsJson).questionItemId)&&(await this.options.store.observeQuestionResolution(this.owner,n.key,{threadId:t.threadId,turnId:t.turnId,item:i}),this.startResolution(n.key))}if(i.type==="commandExecution"||i.type==="fileChange"){for(let n of s.controls)if(n.kind!=="async"&&n.nativeInstanceId===this.instanceId&&n.turnId===t.turnId&&n.itemId===i.id){await this.options.store.observeApprovalTerminalItem(this.owner,n.key,{nativeInstanceId:this.instanceId,message:e}),this.startResolution(n.key);let r=O(JSON.parse(n.detailsJson)).request;(0,Z.isDeepStrictEqual)(this.nativeRequests.get(r.id)?.params,r.params)&&(this.nativeRequests.delete(r.id),this.approvalAuthorities.delete(r.id))}if(s.entries.some(n=>this.canReceiveNativeReceipt(n)&&n.binding.kind==="approval"&&!n.nativeReceiptSha256&&n.binding.nativeId===i.id&&n.binding.turnId===t.turnId)){let n=H(e);delete O(O(n.params).item).aggregatedOutput,this.completedApprovals.set(i.id,n)}await this.reconcileApprovals(),this.observedFiles.delete(i.id),await this.restorePausedQuestions()}}if(e.method==="turn/completed"){if(await this.reconcileApprovals(e),t.turn.status==="interrupted")for(let i of await this.snapshotControls())i.kind==="async"&&i.nativeInstanceId===this.instanceId&&j(i.scope,this.owner.scope)&&i.threadId===t.threadId&&i.turnId===t.turn.id&&["OPEN","PAUSED"].includes(i.state)&&i.answerEventId===null&&(await this.options.store.observeQuestionInterruption(this.owner,i.key,{nativeInstanceId:this.instanceId,message:e}),this.startResolution(i.key));for(let[i,s]of this.completedApprovals)O(s.params).turnId===t.turn.id&&this.completedApprovals.delete(i)}}async restorePausedQuestions(){if(this.nativeRequests.size===0)for(let e of await this.snapshotControls())j(e.scope,this.owner.scope)&&e.kind==="async"&&e.state==="PAUSED"&&e.answerEventId===null&&await this.options.store.pauseControl(this.owner,e.key,!1)}pausedQuestionPromptId(e){let t=this.firstQuestion(e);return t?.state==="PAUSED"&&t.answerEventId===null?JSON.parse(t.raiseJson).promptId:null}firstQuestion(e){return e.find(t=>t.kind==="async"&&j(t.scope,this.owner.scope)&&t.nativeInstanceId===this.instanceId&&t.threadId===this.options.threadId&&!t.cloudResolved&&!["SESSION_ENDED","REHOMED"].includes(t.state))}async publishFirstQuestion(){if(!this.accepting)return;let e=this.firstQuestion(await this.snapshotControls());e&&this.isPresentable(e)&&this.startPublication(e,e.state==="UNCERTAIN"?this.uncertainPresentation():Ce(be(e)))}canReceiveNativeReceipt(e){return e.kind==="INPUT"?["ATTEMPTED","UNCERTAIN"].includes(e.phase):e.outcome==="UNKNOWN"}receiptCandidate(e,t){return this.canReceiveNativeReceipt(e)?e.binding.kind==="user"?t.type==="userMessage"&&t.clientId===e.binding.nativeId:e.binding.kind==="async"&&t.type==="functionCallOutput"&&typeof t.output=="string"&&Re(t.output)===e.binding.receiptMatchSha256:!1}reconcileHistoryItem(e){if(!this.accepting)return this.track(Promise.reject(new T("NATIVE_CONTROL_UNSUPPORTED")));let t=H(e),i=this.factTail.then(async()=>{if(this.assertTarget(),t.threadId!==this.options.threadId)throw new T("NATIVE_CONTROL_UNSUPPORTED");let s=O(t.item),n=await this.options.store.snapshot(this.owner);for(let r of n.entries)this.receiptCandidate(r,s)&&(await this.options.store.reconcile(this.owner,r.event.eventId,t),this.startAcknowledgement(r),r.controlKey&&this.startResolution(r.controlKey))});return this.factTail=i.catch(()=>{}),this.track(i)}async reconcileApprovals(e){let t=await this.options.store.snapshot(this.owner);for(let i of t.entries)if(this.canReceiveNativeReceipt(i)&&i.binding.kind==="approval"&&i.nativeReceiptSha256===null&&i.controlKey){let s=t.controls.find(o=>o.key===i.controlKey),n=this.completedApprovals.get(i.binding.nativeId),r=i.binding.approval?.method==="file"&&i.binding.approval.decision==="cancel"&&e?.method==="turn/completed"&&O(e.params).threadId===i.binding.threadId&&O(e.params).turn?.id===i.binding.turnId&&O(e.params).turn?.status==="interrupted";if(!s?.nativeResolutionJson||!O(JSON.parse(s.nativeResolutionJson)).message||!n&&!r||i.binding.approval?.decision==="cancel"&&(!e||O(e.params).turn.id!==i.binding.turnId))continue;await this.options.store.reconcileApproval(this.owner,i.event.eventId,{nativeInstanceId:this.instanceId,completed:n??null,...e?{turnCompleted:e}:{}}),this.completedApprovals.delete(i.binding.nativeId),this.startAcknowledgement(i),this.startResolution(i.controlKey)}}reconcileRetainedApproval(e){let t=st(e,this.instanceId),i=this.factTail.then(async()=>{this.assertTarget();let s=O(t.request.params);if(s.threadId!==this.options.threadId)return!1;let n=await this.options.store.snapshot(this.owner),r=n.controls.filter(o=>o.kind!=="async"&&o.nativeInstanceId===this.instanceId&&o.threadId===s.threadId&&o.turnId===s.turnId&&o.itemId===s.itemId&&O(JSON.parse(o.detailsJson)).request.id===t.request.id);if(!r.length)return!1;for(let o of r){let a=O(JSON.parse(o.detailsJson)).request;if(a.method!==t.request.method||!(0,Z.isDeepStrictEqual)(a.params,t.request.params))throw new T("NATIVE_CONTROL_INVALID");await this.options.store.observeApprovalResolution(this.owner,o.key,{nativeInstanceId:this.instanceId,message:t.resolved}),t.completed!==null&&await this.options.store.observeApprovalTerminalItem(this.owner,o.key,{nativeInstanceId:this.instanceId,message:t.completed});let l=this.nativeRequests.get(t.request.id);l?.method===t.request.method&&(0,Z.isDeepStrictEqual)(l.params,t.request.params)&&(this.nativeRequests.delete(t.request.id),this.approvalAuthorities.delete(t.request.id));let p=(await this.options.store.snapshot(this.owner)).entries.filter(f=>f.controlKey===o.key);for(let f of p){if(f.binding.kind!=="approval")throw new T("NATIVE_CONTROL_INVALID");if(!f.nativeReceiptSha256){if(!this.canReceiveNativeReceipt(f))continue;await this.options.store.reconcileApproval(this.owner,f.event.eventId,{nativeInstanceId:this.instanceId,completed:t.completed,turnCompleted:t.turnCompleted})}this.startAcknowledgement(f)}this.startResolution(o.key)}return await this.restorePausedQuestions(),!0});return this.factTail=i.then(()=>{},()=>{}),this.track(i)}scopedKey(e){return Re(JSON.stringify([this.owner.scope,e]))}control(e,t,i,s,n){let r=(0,W.newPromptRaise)({sessionId:this.owner.scope.sessionId,producerKind:"PLUGIN_APPROVAL",agentType:"CODEX",mobileActionable:!0}).record;return{key:this.scopedKey(e),kind:t,scope:H(this.owner.scope),nativeInstanceId:this.instanceId,threadId:this.options.threadId,turnId:i,itemId:s,detailsJson:JSON.stringify(n),raiseJson:JSON.stringify(r),state:"OPEN",cloudResolved:!1,answerEventId:null,nativeResolutionSha256:null,nativeResolutionJson:null}}startPublication(e,t){if(!this.accepting||this.published.has(e.key)||this.publications.has(e.key))return;let i=this.track((async()=>{let s=await this.snapshotControls(),n=s.find(r=>r.key===e.key);if(n?.kind==="async"&&(this.firstQuestion(s)?.key!==n.key||n.state==="RESOLVED")){this.deferredQuestions.add(n.key);return}!n||!this.isPresentable(n)||n.cloudResolved||!this.accepting||(this.deferredQuestions.delete(n.key),!(n.kind!=="async"&&n.state!=="UNCERTAIN"&&!this.pendingApprovalKeys([n]).length)&&await this.options.publish(H(n),H(t))==="RERAISED"&&this.published.add(e.key))})());this.publications.set(e.key,i),i.then(()=>this.publications.delete(e.key),()=>this.publications.delete(e.key))}isPresentable(e){return["OPEN","PAUSED"].includes(e.state)||e.state==="UNCERTAIN"&&JSON.parse(e.raiseJson).mobileActionable===!1}uncertainPresentation(){return{content:"An earlier mobile answer is unconfirmed. Continue on desktop; it will not be sent again automatically.",metadata:{nativeControlUncertain:!0,isApprovalHint:!1,isQueuedQuestion:!1}}}startResolution(e){if(this.resolutions.has(e))return;let t=this.track((async()=>{await this.publications.get(e)?.catch(()=>{}),await this.options.store.resolveControl(this.owner,e,this.options.resolve),await this.factTail,await this.publishFirstQuestion()})());this.resolutions.set(e,t),t.then(()=>this.resolutions.delete(e),()=>this.resolutions.delete(e))}startAcknowledgement(e){if(!j(e.scope,this.owner.scope)||e.cloudAck==="EXECUTED"||this.acknowledgements.has(e.event.eventId))return;let t=this.track(this.dispatch.acknowledgeExisting(e.event.eventId));this.acknowledgements.set(e.event.eventId,t),t.then(()=>this.acknowledgements.delete(e.event.eventId),()=>this.acknowledgements.delete(e.event.eventId))}isQuestionPublished(e){let t=this.questionKeys.get(e);return!!t?.length&&t.every(i=>this.published.has(i)||this.deferredQuestions.has(i))}async projectInputReceipt(e){if(this.assertTarget(),e.threadId!==this.options.threadId)throw new T("NATIVE_QUESTION_MISMATCH");let t=await this.options.store.snapshot(this.owner),i=O(e.item),s=Re((0,W.stableStringify)(H(e)));if(t.entries.some(o=>o.nativeReceiptSha256===s))return{echo:!0,text:null,images:[]};if(t.entries.some(o=>o.nativeReceiptSha256!==null&&o.binding.threadId===e.threadId&&o.binding.turnId===e.turnId&&(o.binding.kind==="user"&&i.type==="userMessage"&&i.clientId===o.binding.nativeId&&Re((0,W.stableStringify)(i.content))===o.binding.receiptMatchSha256||o.binding.kind==="async"&&i.type==="functionCallOutput"&&i.namespace==="functions"&&i.name==="request_user_input_async"&&typeof i.output=="string"&&Re(i.output)===o.binding.receiptMatchSha256)))return{echo:!0,text:null,images:[]};if(i.type==="userMessage"){if(!Array.isArray(i.content))throw new T("NATIVE_CONTROL_INVALID");return{echo:!1,text:i.content.map(a=>{if(!a||typeof a!="object"||typeof a.type!="string")throw new T("NATIVE_CONTROL_INVALID");if(a.type==="text"&&typeof a.text=="string")return a.text;if(a.type==="localImage"&&typeof a.path=="string"&&a.path.startsWith("/"))return null;if(a.type==="image"&&(typeof a.url=="string"&&a.url.length>0&&a.fileId===void 0||typeof a.fileId=="string"&&a.fileId.length>0&&a.url===void 0))return"[image]";if(a.type==="audio"&&typeof a.url=="string"&&a.url.length||a.type==="localAudio"&&typeof a.path=="string"&&a.path.startsWith("/"))return"[audio]";if(["skill","mention"].includes(a.type)&&typeof a.name=="string"&&a.name.length&&typeof a.path=="string"&&a.path.length)return`[${a.type}: ${a.name}]`;if(["text","localImage","image","audio","localAudio","skill","mention"].includes(a.type))throw new T("NATIVE_CONTROL_UNSUPPORTED");return"[unsupported native attachment]"}).filter(a=>a!==null).join(`
12
- `),images:i.content.filter(a=>a.type==="localImage").map(a=>a.path)}}if(i.type!=="functionCallOutput"||i.namespace!=="functions"||i.name!=="request_user_input_async")return{echo:!1,text:null,images:[]};let n=JSON.parse(i.output);if(!Array.isArray(n)||!n.length)throw new T("NATIVE_CONTROL_INVALID");return{echo:!1,text:n.map(o=>{let a=O(o),l=t.controls.find(p=>p.kind==="async"&&p.threadId===e.threadId&&JSON.parse(p.detailsJson).questionItemId===a.questionItemId);if(!l||typeof a.answer!="string"||a.question!==JSON.parse(l.detailsJson).title)throw new T("NATIVE_QUESTION_MISMATCH");return a.answer}).join(`
11
+ `),metadata:{isApprovalHint:!0,isQueuedQuestion:!1,prompt_source:"native_app_server",tool_name:a.kind==="command"?"exec_command":"apply_patch",tool_use_id:a.itemId,turn_id:a.turnId,options:n,questions:[{question:i,multiSelect:!1,options:n,instructions:r}],submitMap:Object.fromEntries(n.map(o=>[o.number,o.number])),instructions:r,...e!==null?{preemptedQueuedQuestionId:e}:{}}}}var Ii=require("node:crypto");var Ue=()=>{throw new T("NATIVE_CONTROL_INVALID")};function wi(a){return!a||typeof a!="object"||Array.isArray(a)?Ue():a}function Si(a){try{return wi(JSON.parse(a.detailsJson))}catch{return Ue()}}function ye(a){let e=Si(a),t=JSON.stringify(["request_user_input_async",a.itemId,e.questionIndex]);return!Number.isSafeInteger(e.questionIndex)||e.questionIndex<0||e.itemId!==a.itemId||e.questionItemId!==t||typeof e.title!="string"||!e.title.length||e.options!==null&&(!Array.isArray(e.options)||!e.options.every(i=>typeof i=="string"&&i.length))?Ue():{key:a.key,threadId:a.threadId,turnId:a.turnId,itemId:a.itemId,questionIndex:e.questionIndex,questionItemId:t,title:e.title,options:e.options===null?null:[...e.options]}}function Ei(a){let e=a.controls.filter(l=>l.scope.sessionId===a.scope.sessionId&&l.scope.sessionGenerationId===a.scope.sessionGenerationId&&l.scope.expectedSessionKeyGen===a.scope.expectedSessionKeyGen&&l.threadId===a.threadId&&!l.cloudResolved),t=new Set(a.pendingApprovalKeys),i=t.size>0||a.otherNativeApprovalPending,s=e.filter(l=>l.state==="OPEN"&&l.answerEventId===null),n=Number(a.text.trim()),r=Number.isSafeInteger(n)&&String(n)===a.text.trim(),o;if(a.promptId!==null){if(o=e.find(l=>{try{return wi(JSON.parse(l.raiseJson)).promptId===a.promptId}catch{return Ue()}}),!o||o.state!=="OPEN"||o.answerEventId!==null||(o.kind==="async"?i:!t.has(o.key)))throw new T("NATIVE_QUESTION_MISMATCH")}else if(r){if(i||e.length)throw new T("NATIVE_CONTEXT_REQUIRED")}else if(!i&&a.text.trim().length&&!a.localImages?.length&&s.filter(h=>h.kind==="async").filter(h=>ye(h).options===null).length)throw new T("NATIVE_CONTEXT_REQUIRED");if(o){if(a.localImages?.length)throw new T("NATIVE_OPTION_INVALID");if(o.nativeInstanceId!==a.nativeInstanceId)throw new T("NATIVE_CONTROL_UNSUPPORTED");if(o.kind==="async"){let l=ye(o),u=fi(l,a.text,l.questionItemId);if(u.kind==="answer")return{intent:{kind:"async",threadId:a.threadId,questionItemId:l.questionItemId,output:u.output},controlKey:o.key,heldForApproval:!1}}else{let l=ke(a.nativeInstanceId,a.threadId,Si(o));if(!l||l.kind!==o.kind||l.turnId!==o.turnId||l.itemId!==o.itemId)return Ue();let{decision:u}=vi(l,a.text);return{intent:{kind:"approval",method:l.kind,threadId:l.threadId,turnId:l.turnId,itemId:l.itemId,nativeInstanceId:l.nativeInstanceId,requestId:l.requestId,decision:u,detailsSha256:(0,Ii.createHash)("sha256").update(o.detailsJson).digest("hex")},controlKey:o.key,heldForApproval:!1}}}let d=ot(a.threadId,a.eventId,a.text,a.localImages);return{intent:{kind:"user",threadId:a.threadId,clientId:a.eventId,contentJson:JSON.stringify(d.input)},controlKey:null,heldForApproval:i}}var Pi=require("node:crypto");var Ke=class{constructor(e){this.instanceId=e;this.proof={instanceId:e,generation:0,threadId:null,ready:!1}}snapshot(){return{...this.proof}}invalidate(){return this.proof={instanceId:this.instanceId,generation:this.proof.generation+1,threadId:null,ready:!1},this.proof.generation}confirm(e,t){return e!==this.proof.generation||e<1||!this.validThread(t)||this.proof.ready&&this.proof.threadId!==t?!1:(this.proof={instanceId:this.instanceId,generation:e,threadId:t,ready:!0},!0)}receive(e){let t=e;return!t||t.instanceId!==this.instanceId||!Number.isSafeInteger(t.generation)||t.generation<0||typeof t.ready!="boolean"||(t.ready?!this.validThread(t.threadId)||t.generation<1:t.threadId!==null)||t.generation<this.proof.generation||t.generation===this.proof.generation&&this.proof.ready&&(!t.ready||t.threadId!==this.proof.threadId)?!1:(this.proof={instanceId:this.instanceId,generation:t.generation,threadId:t.threadId,ready:t.ready},!0)}matches(e){return this.proof.ready&&!!e&&this.proof.threadId===e}validThread(e){return typeof e=="string"&&e.length>0&&e.length<=512}};var Vs=2*1024*1024,Us=a=>JSON.parse(JSON.stringify(a)),Ks=a=>(0,Pi.createHash)("sha256").update(JSON.stringify(a)).digest("hex");function oe(a){if(!a||typeof a!="object"||Array.isArray(a))throw Error("NATIVE_RECEIPT_INVALID");return a}function Mt(a){return typeof a=="string"&&a.length>0&&a.length<=512}function Qs(a){return Mt(a)||typeof a=="number"&&Number.isSafeInteger(a)&&a>=0}function Hs(a){return{nativeInstanceId:a.nativeInstanceId,request:a.request,resolved:a.resolved,completed:a.completed,turnCompleted:a.turnCompleted}}function at(a,e){let t=oe(a);if(Buffer.byteLength(JSON.stringify(t))>Vs||Object.keys(t).sort().join(",")!=="completed,digest,nativeInstanceId,request,resolved,turnCompleted"||t.nativeInstanceId!==e||!Mt(e))throw Error("NATIVE_RECEIPT_INVALID");let i=oe(t.request),s=oe(t.resolved),n=oe(t.turnCompleted),r=oe(i.params),o=oe(s.params),d=oe(n.params),l=oe(d.turn),u=i.method==="item/commandExecution/requestApproval"?"commandExecution":i.method==="item/fileChange/requestApproval"?"fileChange":null;if(!u||!Qs(i.id)||![r.threadId,r.turnId,r.itemId].every(Mt)||s.method!=="serverRequest/resolved"||o.threadId!==r.threadId||o.requestId!==i.id||n.method!=="turn/completed"||d.threadId!==r.threadId||l.id!==r.turnId||!["completed","failed","interrupted"].includes(l.status))throw Error("NATIVE_RECEIPT_INVALID");if(t.completed===null){if(u!=="fileChange"||l.status!=="interrupted")throw Error("NATIVE_RECEIPT_INVALID")}else{let p=oe(t.completed),m=oe(p.params),f=oe(m.item);if(p.method!=="item/completed"||m.threadId!==r.threadId||m.turnId!==r.turnId||f.id!==r.itemId||f.type!==u||!["completed","failed","declined"].includes(f.status))throw Error("NATIVE_RECEIPT_INVALID")}let h=Hs(t);if(t.digest!==Ks(h))throw Error("NATIVE_RECEIPT_INVALID");return{...Us(h),digest:t.digest}}var K=a=>JSON.parse(JSON.stringify(a)),me=a=>(0,lt.createHash)("sha256").update(a).digest("hex"),Q=(a,e)=>a.sessionId===e.sessionId&&a.sessionGenerationId===e.sessionGenerationId&&a.expectedSessionKeyGen===e.expectedSessionKeyGen;function N(a){if(!a||typeof a!="object"||Array.isArray(a))throw new T("NATIVE_CONTROL_INVALID");return a}var Qe=class extends T{constructor(){super("NATIVE_CONTROL_UNSUPPORTED")}},dt=class{constructor(e){this.options=e;this.accepting=!0;this.stopped=!1;this.factTail=Promise.resolve();this.pending=new Set;this.nativeRequests=new Map;this.desktopOnlyNotices=new Set;this.approvalAuthorities=new Map;this.observedFiles=new Map;this.publications=new Map;this.publicationDemands=new Map;this.custodyPublications=new Map;this.custodyClosures=new Map;this.closedCustodies=new Set;this.custodyTransitionTail=Promise.resolve();this.resolutions=new Map;this.acknowledgements=new Map;this.rejectionSettlements=new Map;this.published=new Set;this.publicationTail=Promise.resolve();this.deferredQuestions=new Set;this.questionKeys=new Map;this.completedApprovals=new Map;this.recovery=null;this.admissionPaused=!1;this.owner=K(e.owner),this.instanceId=e.native.instanceId,this.accepting=!e.deferActivation,this.dispatch=new U.CodexNativeDispatcher({store:e.store,owner:this.owner,updateStatus:e.updateStatus,assertNativeTarget:t=>this.assertTarget(t),isNativeBlocked:t=>!this.isAccepting||t.kind!=="approval"&&(this.nativeRequests.size>0||!!this.options.hasPendingControl?.()),send:t=>this.send(t),onFailure:t=>this.report(t)})}get isAccepting(){return this.accepting&&!this.admissionPaused&&this.options.isControlReady?.()!==!1}get isAdmissionPaused(){return this.admissionPaused}get isActivationPending(){return!this.accepting&&!this.stopped}report(e){try{Promise.resolve(this.options.onFailure(e)).catch(()=>{})}catch{}}track(e){return this.pending.add(e),e.then(()=>this.pending.delete(e),()=>{this.pending.delete(e),this.report("NATIVE_ADAPTER_OPERATION_FAILED")}),e}assertTarget(e){if(this.options.assertCurrent(),this.options.native.instanceId!==this.instanceId||e&&e.threadId!==this.options.threadId||e?.kind==="approval"&&e.nativeInstanceId!==this.instanceId)throw new T("NATIVE_CONTROL_UNSUPPORTED");if(e?.kind==="approval"){let t=this.nativeRequests.get(e.requestId),i=this.approvalAuthorities.get(e.requestId);if(!t||this.options.isCurrentControl?.(t)===!1)throw new Qe;if(!i||i.detailsSha256!==e.detailsSha256||t.method!==i.method||!(0,Y.isDeepStrictEqual)(t.params,i.params))throw new T("NATIVE_CONTROL_UNSUPPORTED")}}async send(e){if(this.assertTarget(e),e.kind==="user")await this.options.native.request("turn/start",{threadId:e.threadId,clientUserMessageId:e.clientId,input:JSON.parse(e.contentJson)});else if(e.kind==="async")await this.options.native.request("turn/start",gi(e.threadId,e.output));else{let t=this.nativeRequests.get(e.requestId),i=t?N(t.params):null;if(!t||i?.threadId!==e.threadId||i.turnId!==e.turnId||i.itemId!==e.itemId||t.method!==(e.method==="command"?"item/commandExecution/requestApproval":"item/fileChange/requestApproval"))throw new T("NATIVE_CONTROL_UNSUPPORTED");await this.options.native.respond(e.requestId,{decision:e.decision})}}admit(e){let t;try{if(!this.accepting)throw new T("NATIVE_CONTROL_UNSUPPORTED");t=K(e)}catch(i){return this.track(Promise.reject(i))}return this.track((async()=>{if(this.assertTarget(),t.sessionId!==this.owner.scope.sessionId)throw new T("NATIVE_QUESTION_MISMATCH");let i=await this.options.store.snapshot(this.owner),s=i.entries.find(l=>l.event.eventId===t.eventId);if(i.rejections.some(l=>l.event.eventId===t.eventId)){let l=await this.options.store.rejectUnappliedInput(this.owner,(0,U.snapshotCodexNativeEvent)(t));if(!l)throw new T("NATIVE_CONTROL_INVALID");return this.settleRejection(l)}if(s){if(s.kind!=="INPUT"||!Q(s.scope,this.owner.scope))throw new T("NATIVE_QUESTION_MISMATCH");let l=JSON.parse(s.bodyJson);if(s.phase==="PREPARED"&&l.kind==="user"){let h=await this.options.decode(K(t));if(JSON.stringify(ot(l.threadId,t.eventId,h.text,h.localImages).input)!==l.contentJson)throw new T("NATIVE_CONTROL_INVALID")}let u=await this.dispatch.admit(t,l,s.controlKey);return s.nativeReceiptSha256&&s.cloudAck!=="EXECUTED"&&this.startAcknowledgement(s),u}let n=await this.options.decode(K(t));this.assertTarget();let r=await this.options.store.snapshot(this.owner),o=this.pendingApprovalKeys(r.controls),d=this.firstQuestion(r.controls);try{let l=Ei({...n,controls:r.controls.filter(u=>u.kind!=="async"||u.key===d?.key),scope:this.owner.scope,nativeInstanceId:this.instanceId,threadId:this.options.threadId,eventId:t.eventId,pendingApprovalKeys:o,otherNativeApprovalPending:this.nativeRequests.size>o.length||o.length===0&&!!this.options.hasPendingControl?.()});return await this.dispatch.admit(t,l.intent,l.controlKey)}catch(l){if(!(l instanceof T&&["NATIVE_QUESTION_MISMATCH","NATIVE_CONTEXT_REQUIRED","NATIVE_OPTION_INVALID"].includes(l.code)||l instanceof U.CodexNativeStateError&&["NATIVE_CONTROL_UNAVAILABLE","NATIVE_INPUT_REJECTED"].includes(l.code)))throw l;let u=(0,U.snapshotCodexNativeEvent)(t),p=(n.promptId?await this.options.store.rejectAnsweredControl(this.owner,u,n.promptId):null)??await this.options.store.rejectUnappliedInput(this.owner,u);if(!p)throw l;return this.settleRejection(p)}})())}settleRejection(e){let t=e.event.eventId,i=this.rejectionSettlements.get(t);if(i)return i;let s=this.track((async()=>{if(!this.accepting)return"RETAINED";this.assertTarget();let n=(await this.options.store.snapshot(this.owner)).rejections.find(r=>r.event.eventId===t);if(n.noticeOutcome==="MISSING"){if(!Q(n.scope,this.owner.scope))return"RETAINED";let r=await this.options.publishRejectedInput(n);if(this.assertTarget(),r!=="RERAISED"&&r!=="OMITTED")return"RETAINED";await this.options.store.acknowledgeRejectionNotice(this.owner,t,r==="RERAISED"?"ACCEPTED":"OMITTED"),n={...n,noticeOutcome:r==="RERAISED"?"ACCEPTED":"OMITTED"},r==="OMITTED"&&this.report("NATIVE_REJECTION_NOTICE_OMITTED")}if(!n.noticeResolved){let r=JSON.parse(n.raiseJson);if(!await this.options.resolve({sessionId:n.scope.sessionId,promptId:r.promptId,ownerToken:r.ownerToken}))return"RETAINED";await this.options.store.resolveRejectionNotice(this.owner,t)}if(!n.cloudDelivered){let r=await this.options.updateStatus({eventId:t,sessionId:n.event.sessionId,timestamp:n.event.timestamp,deliveryStatus:U.DeliveryStatus.DELIVERED},{sessionGenerationId:n.scope.sessionGenerationId,type:n.event.type});await this.options.store.acknowledgeRejectedDelivery(this.owner,t,r)}return n.noticeOutcome==="ACCEPTED"?"REJECTED":"RETAINED"})());return this.rejectionSettlements.set(t,s),s.finally(()=>{this.rejectionSettlements.get(t)===s&&this.rejectionSettlements.delete(t)}).catch(()=>{}),s}pendingApprovalKeys(e){return e.filter(t=>t.kind!=="async"&&t.nativeInstanceId===this.instanceId&&Q(t.scope,this.owner.scope)).filter(t=>{let i=N(JSON.parse(t.detailsJson)),s=this.nativeRequests.get(i.request.id);return!!s&&s.method===i.request.method&&(0,Y.isDeepStrictEqual)(s.params,i.request.params)&&this.options.isCurrentControl?.(s)!==!1}).map(t=>t.key)}observe(e){let t;try{if(t=K(e),!t.params||typeof t.params!="object"||Array.isArray(t.params))return Promise.resolve();let s=N(t.params);if(this.stopped||s.threadId!==this.options.threadId)return Promise.resolve();if(this.assertTarget(),t.id!==void 0){let n=this.nativeRequests.get(t.id);if(this.nativeRequests.set(t.id,t),n&&(n.method!==t.method||!(0,Y.isDeepStrictEqual)(n.params,t.params)))throw this.approvalAuthorities.delete(t.id),new T("NATIVE_CONTROL_INVALID")}t.method==="serverRequest/resolved"&&(this.nativeRequests.delete(s.requestId),this.approvalAuthorities.delete(s.requestId),this.desktopOnlyNotices.delete(s.requestId)),["item/started","item/completed"].includes(t.method)&&s.item?.type==="fileChange"&&this.observedFiles.set(s.item.id,{nativeInstanceId:this.instanceId,threadId:s.threadId,turnId:s.turnId,item:K(s.item)})}catch(s){return this.track(Promise.reject(s))}let i=this.factTail.then(()=>this.applyFact(t));return this.factTail=i.catch(()=>{}),this.track(i)}async snapshotControls(){return(await this.options.store.snapshot(this.owner)).controls}async applyFact(e){this.assertTarget();let t=N(e.params);if(e.id!==void 0){let i=(await this.snapshotControls()).filter(u=>u.nativeInstanceId===this.instanceId&&u.kind!=="async"&&N(JSON.parse(u.detailsJson)).request.id===e.id),s=i.find(u=>Q(u.scope,this.owner.scope))??i[0],n=s?N(JSON.parse(s.detailsJson)).observedFile:void 0,r;if(s)r=ke(this.instanceId,this.options.threadId,N(JSON.parse(s.detailsJson)));else try{r=Dt(this.instanceId,this.options.threadId,e,this.observedFiles.get(t.itemId)??n)}catch(u){if(!(u instanceof le))throw u;this.report(u.code)}if(!r){await this.options.store.pauseOpenQuestions(this.owner),!this.desktopOnlyNotices.has(e.id)&&this.options.onDesktopOnlyApproval&&(this.assertTarget(),this.options.isCurrentControl?.(e)!==!1&&(0,Y.isDeepStrictEqual)(this.nativeRequests.get(e.id),e)&&(await this.options.onDesktopOnlyApproval(K(e)),this.desktopOnlyNotices.add(e.id)));return}if(s&&!(0,Y.isDeepStrictEqual)(N(JSON.parse(s.detailsJson)).request.params,e.params))throw new T("NATIVE_CONTROL_INVALID");if(s&&(s.state!=="OPEN"||!Q(s.scope,this.owner.scope)))return;await this.options.store.pauseOpenQuestions(this.owner);let o=await this.withCustodyTransition(async()=>{let u=await this.snapshotControls(),h=u.filter(y=>y.kind!=="async"&&y.nativeInstanceId===this.instanceId&&y.threadId===this.options.threadId).map(y=>N(JSON.parse(y.detailsJson)).questionCustodySequence??0);if(h.some(y=>!Number.isSafeInteger(y)||y<0))throw new T("NATIVE_CONTROL_INVALID");let p=Math.max(0,...h)+1;if(!Number.isSafeInteger(p))throw new T("NATIVE_CONTROL_INVALID");let m=this.cloudQuestionPromptId(u),f=s?void 0:this.newCustodyMarker(m,u,p),g=s??this.control(r.key,r.kind,r.turnId,r.itemId,{request:r.request,observedFile:r.observedFile,approvalPresentationVersion:2,preemptedQueuedQuestionId:m,questionCustodySequence:p,...f&&{questionCustodyMarker:f}});return await this.options.store.putControl(this.owner,{...g,state:"OPEN",cloudResolved:!1,answerEventId:null,nativeResolutionSha256:null,nativeResolutionJson:null}),g}),d=this.nativeRequests.get(r.requestId);if(!d||d.method!==e.method||!(0,Y.isDeepStrictEqual)(d.params,e.params)||this.options.isCurrentControl?.(d)===!1)return;this.approvalAuthorities.set(r.requestId,{method:e.method,params:K(e.params),detailsSha256:me(o.detailsJson)});let l=this.approvalPresentation(o);l&&this.startPublication(o,l);return}if(e.method==="serverRequest/resolved"){for(let i of await this.snapshotControls())i.kind!=="async"&&i.nativeInstanceId===this.instanceId&&N(JSON.parse(i.detailsJson)).request.id===t.requestId&&(await this.options.store.observeApprovalResolution(this.owner,i.key,{nativeInstanceId:this.instanceId,message:e}),this.startResolution(i.key));await this.reconcileApprovals(),await this.restorePausedQuestions();return}if(e.method==="item/completed"){let i=N(t.item);if(i.type==="agentMessage"&&i.delivery==="async")for(let r of rt(t.threadId,t.turnId,i)){let o=(await this.snapshotControls()).find(l=>l.key===this.scopedKey(r.key));if(o){if(!(0,Y.isDeepStrictEqual)(JSON.parse(o.detailsJson),r))throw new T("NATIVE_CONTROL_INVALID");this.startPublication(o,De(r));continue}if(!await this.options.isFreshQuestion(r.threadId,r.turnId,r.itemId))continue;let d=this.control(r.key,"async",r.turnId,r.itemId,r);await this.options.store.putControl(this.owner,d),this.nativeRequests.size&&await this.options.store.pauseOpenQuestions(this.owner),this.startPublication(d,De(r))}i.type==="agentMessage"&&i.delivery==="async"&&this.questionKeys.set(i.id,rt(t.threadId,t.turnId,i).map(r=>this.scopedKey(r.key)));let s=await this.options.store.snapshot(this.owner);for(let r of s.entries)this.receiptCandidate(r,i)&&(await this.options.store.reconcile(this.owner,r.event.eventId,{threadId:t.threadId,turnId:t.turnId,item:i}),this.startAcknowledgement(r),r.controlKey&&this.startResolution(r.controlKey));let n=(0,U.parseCodexNativeQuestionAnswers)(i);if(n&&await this.closeAnsweredQuestions({threadId:t.threadId,turnId:t.turnId,item:i},s.controls,n),i.type==="commandExecution"||i.type==="fileChange"){for(let[r,o]of this.nativeRequests){let d=N(o.params);d.turnId===t.turnId&&d.itemId===i.id&&(this.nativeRequests.delete(r),this.approvalAuthorities.delete(r),this.desktopOnlyNotices.delete(r))}for(let r of s.controls)if(r.kind!=="async"&&r.nativeInstanceId===this.instanceId&&r.turnId===t.turnId&&r.itemId===i.id){await this.options.store.observeApprovalTerminalItem(this.owner,r.key,{nativeInstanceId:this.instanceId,message:e}),this.startResolution(r.key);let o=N(JSON.parse(r.detailsJson)).request;(0,Y.isDeepStrictEqual)(this.nativeRequests.get(o.id)?.params,o.params)&&(this.nativeRequests.delete(o.id),this.approvalAuthorities.delete(o.id))}if(s.entries.some(r=>this.canReceiveNativeReceipt(r)&&r.binding.kind==="approval"&&!r.nativeReceiptSha256&&r.binding.nativeId===i.id&&r.binding.turnId===t.turnId)){let r=K(e);delete N(N(r.params).item).aggregatedOutput,this.completedApprovals.set(i.id,r)}await this.reconcileApprovals(),this.observedFiles.delete(i.id),await this.restorePausedQuestions()}}if(e.method==="turn/completed"){if(await this.reconcileApprovals(e),t.turn.status==="interrupted")for(let i of await this.snapshotControls())i.kind==="async"&&i.nativeInstanceId===this.instanceId&&Q(i.scope,this.owner.scope)&&i.threadId===t.threadId&&i.turnId===t.turn.id&&["OPEN","PAUSED"].includes(i.state)&&i.answerEventId===null&&(await this.options.store.observeQuestionInterruption(this.owner,i.key,{nativeInstanceId:this.instanceId,message:e}),this.startResolution(i.key));for(let[i,s]of this.completedApprovals)N(s.params).turnId===t.turn.id&&this.completedApprovals.delete(i)}}matchesQuestionAnswer(e,t,i){if(e.kind!=="async"||e.threadId!==t)return!1;let s=N(JSON.parse(e.detailsJson));return s.questionItemId===i.questionItemId&&s.title===i.question&&(s.options===null||Array.isArray(s.options)&&s.options.includes(i.answer))}async closeAnsweredQuestions(e,t,i){for(let s of t)s.state!=="RESOLVED"&&i.some(n=>this.matchesQuestionAnswer(s,e.threadId,n))&&(await this.options.store.observeQuestionResolution(this.owner,s.key,e),this.startResolution(s.key))}async restorePausedQuestions(){if(this.nativeRequests.size===0){for(let e of await this.snapshotControls())Q(e.scope,this.owner.scope)&&e.kind==="async"&&e.state==="PAUSED"&&e.answerEventId===null&&await this.options.store.pauseControl(this.owner,e.key,!1);await this.publishFirstQuestion()}}cloudQuestionPromptId(e){let t=this.firstQuestion(e);return t?JSON.parse(t.raiseJson).promptId:null}firstQuestion(e){return e.find(t=>t.kind==="async"&&Q(t.scope,this.owner.scope)&&t.nativeInstanceId===this.instanceId&&t.threadId===this.options.threadId&&!t.cloudResolved&&!["SESSION_ENDED","REHOMED"].includes(t.state))}firstApproval(e){return e.find(t=>t.kind!=="async"&&Q(t.scope,this.owner.scope)&&t.nativeInstanceId===this.instanceId&&t.threadId===this.options.threadId&&!t.cloudResolved&&!["SESSION_ENDED","REHOMED"].includes(t.state)&&JSON.parse(t.raiseJson).mobileActionable===!0)}ownsApprovalSlot(e,t){return e.kind==="async"||JSON.parse(e.raiseJson).mobileActionable===!1||this.firstApproval(t)?.key===e.key}approvalPresentation(e){let t=N(JSON.parse(e.detailsJson)),i=t.preemptedQueuedQuestionId??null;if(i!==null&&(typeof i!="string"||!/^[a-f0-9]{8}-[a-f0-9]{4}-[1-8][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/.test(i)))throw new T("NATIVE_CONTROL_INVALID");let s=ke(this.instanceId,this.options.threadId,t);if(!s)return null;let n=yi(s,i);if(t.questionCustodySequence!==void 0){if(!Number.isSafeInteger(t.questionCustodySequence)||t.questionCustodySequence<1)throw new T("NATIVE_CONTROL_INVALID");let r=this.custodyMarker(e);i!==null&&r&&(n.metadata.native_question_custody={version:2,state:"PAUSED",queueId:r.queueId,questionPromptId:i,through:t.questionCustodySequence,custodyPromptId:r.raise.promptId})}return n}questionQueueId(){return me(JSON.stringify([this.instanceId,this.options.threadId]))}custodyRecord(e){let t=N(JSON.parse(e.detailsJson)),i=t.questionCustodyMarker;if(i===void 0)return null;let s=N(i),n=N(s.raise);if(s.queueId!==me(JSON.stringify([e.nativeInstanceId,e.threadId]))||s.questionPromptId!==t.preemptedQueuedQuestionId||typeof s.questionPromptId!="string"||!s.questionPromptId.length||!Number.isSafeInteger(s.through)||s.through<1||s.through>t.questionCustodySequence||typeof n.sessionId!="string"||!n.sessionId.length||n.producerKind!=="PLUGIN_APPROVAL"||n.mobileActionable!==!1||n.agentType!=="CODEX"||typeof n.promptId!="string"||!/^[a-f0-9]{8}-[a-f0-9-]{27}$/.test(n.promptId)||typeof n.ownerToken!="string"||!/^[a-f0-9]{64}$/.test(n.ownerToken))throw new T("NATIVE_CONTROL_INVALID");if(n.promptId!==(0,U.deriveOpenPromptId)(n.ownerToken))throw new T("NATIVE_CONTROL_INVALID");return K(i)}custodyMarker(e){let t=this.custodyRecord(e);if(!t)return null;let i=(0,lt.createHmac)("sha256",Buffer.from(t.raise.ownerToken,"hex")).update("codevibe-native-question-custody-v2\0"+JSON.stringify([e.scope.sessionId,e.scope.sessionGenerationId,e.scope.expectedSessionKeyGen])).digest("hex");return{...t,raise:{...t.raise,sessionId:e.scope.sessionId,ownerToken:i,promptId:(0,U.deriveOpenPromptId)(i)}}}newCustodyMarker(e,t,i){if(!(!e||!this.options.publishQuestionCustody||!this.options.resolveQuestionCustody)){for(let s of t)if(s.kind!=="async"&&!s.cloudResolved&&s.nativeInstanceId===this.instanceId&&Q(s.scope,this.owner.scope)){let n=this.custodyRecord(s),r=this.custodyMarker(s);if(n?.questionPromptId===e&&r&&!this.custodyClosures.has(r.raise.promptId)&&!this.closedCustodies.has(r.raise.promptId))return n}return{questionPromptId:e,queueId:this.questionQueueId(),through:i,raise:(0,U.newPromptRaise)({sessionId:this.owner.scope.sessionId,producerKind:"PLUGIN_APPROVAL",agentType:"CODEX",mobileActionable:!1,title:"Queued question is paused for approvals"}).record}}}publishCustody(e,t){if(!this.options.publishQuestionCustody)return Promise.resolve("CLOSED");let i=e.raise.promptId,s=this.custodyPublications.get(i),n=this.track((s?.then(()=>{},()=>{})??Promise.resolve()).then(async()=>{let o=await this.snapshotControls();return!this.accepting||this.closedCustodies.has(i)||!o.some(d=>!d.cloudResolved&&this.custodyMarker(d)?.raise.promptId===i)?"CLOSED":this.options.publishQuestionCustody(K(e),t)}));this.custodyPublications.set(i,n);let r=()=>{this.custodyPublications.get(i)===n&&this.custodyPublications.delete(i)};return n.then(r,r),n}async settleCustodies(){if(!this.options.resolveQuestionCustody)return;let e=await this.snapshotControls(),t=new Map;for(let s of e){let n=this.custodyMarker(s);n&&t.set(n.raise.promptId,n)}let i=[];for(let[s,n]of t){let r=await this.withCustodyTransition(async()=>{if(this.closedCustodies.has(s))return{};let o=this.custodyClosures.get(s);if(!o){if((await this.snapshotControls()).some(l=>!l.cloudResolved&&this.custodyMarker(l)?.raise.promptId===s))return{};o=this.track((async()=>{if(await this.custodyPublications.get(s)?.catch(()=>{}),!await this.options.resolveQuestionCustody(K(n)))throw Error("NATIVE_CUSTODY_CLOSE_UNCONFIRMED");this.closedCustodies.add(s)})()),this.custodyClosures.set(s,o);let d=()=>{this.custodyClosures.get(s)===o&&this.custodyClosures.delete(s)};o.then(d,d)}return{closing:o}});r.closing&&i.push(r.closing)}await Promise.all(i)}withCustodyTransition(e){let t=this.track(this.custodyTransitionTail.then(e));return this.custodyTransitionTail=t.then(()=>{},()=>{}),t}async publishFirstApproval(){if(!this.accepting)return;let e=await this.snapshotControls(),t=this.firstApproval(e);if(!t||!this.isPresentable(t)||!this.pendingApprovalKeys([t]).length)return;let i=this.approvalPresentation(t);i&&this.startPublication(t,i)}async publishFirstQuestion(){if(!this.accepting)return;let e=await this.snapshotControls(),t=this.firstQuestion(e);t&&this.isPresentable(t)&&this.startPublication(t,t.state==="UNCERTAIN"?this.uncertainPresentation():De(ye(t)))}canReceiveNativeReceipt(e){return e.kind==="INPUT"?["ATTEMPTED","UNCERTAIN"].includes(e.phase):e.outcome==="UNKNOWN"}receiptCandidate(e,t){return this.canReceiveNativeReceipt(e)?e.binding.kind==="user"?t.type==="userMessage"&&t.clientId===e.binding.nativeId:e.binding.kind==="async"&&t.type==="functionCallOutput"&&typeof t.output=="string"&&me(t.output)===e.binding.receiptMatchSha256:!1}reconcileHistoryItem(e){if(!this.accepting)return this.track(Promise.reject(new T("NATIVE_CONTROL_UNSUPPORTED")));let t=K(e),i=this.factTail.then(async()=>{if(this.assertTarget(),t.threadId!==this.options.threadId)throw new T("NATIVE_CONTROL_UNSUPPORTED");let s=N(t.item),n=await this.options.store.snapshot(this.owner);for(let o of n.entries)this.receiptCandidate(o,s)&&(await this.options.store.reconcile(this.owner,o.event.eventId,t),this.startAcknowledgement(o),o.controlKey&&this.startResolution(o.controlKey));let r=(0,U.parseCodexNativeQuestionAnswers)(s);r&&await this.closeAnsweredQuestions(t,n.controls,r)});return this.factTail=i.catch(()=>{}),this.track(i)}async reconcileApprovals(e){let t=await this.options.store.snapshot(this.owner);for(let i of t.entries)if(this.canReceiveNativeReceipt(i)&&i.binding.kind==="approval"&&i.nativeReceiptSha256===null&&i.controlKey){let s=t.controls.find(o=>o.key===i.controlKey),n=this.completedApprovals.get(i.binding.nativeId),r=i.binding.approval?.method==="file"&&i.binding.approval.decision==="cancel"&&e?.method==="turn/completed"&&N(e.params).threadId===i.binding.threadId&&N(e.params).turn?.id===i.binding.turnId&&N(e.params).turn?.status==="interrupted";if(!s?.nativeResolutionJson||!N(JSON.parse(s.nativeResolutionJson)).message||!n&&!r||i.binding.approval?.decision==="cancel"&&(!e||N(e.params).turn.id!==i.binding.turnId))continue;await this.options.store.reconcileApproval(this.owner,i.event.eventId,{nativeInstanceId:this.instanceId,completed:n??null,...e?{turnCompleted:e}:{}}),this.completedApprovals.delete(i.binding.nativeId),this.startAcknowledgement(i),this.startResolution(i.controlKey)}}reconcileRetainedApproval(e){let t=at(e,this.instanceId),i=this.factTail.then(async()=>{this.assertTarget();let s=N(t.request.params);if(s.threadId!==this.options.threadId)return!1;let n=await this.options.store.snapshot(this.owner),r=n.controls.filter(o=>o.kind!=="async"&&o.nativeInstanceId===this.instanceId&&o.threadId===s.threadId&&o.turnId===s.turnId&&o.itemId===s.itemId&&N(JSON.parse(o.detailsJson)).request.id===t.request.id);if(!r.length)return!1;for(let o of r){let d=N(JSON.parse(o.detailsJson)).request;if(d.method!==t.request.method||!(0,Y.isDeepStrictEqual)(d.params,t.request.params))throw new T("NATIVE_CONTROL_INVALID");await this.options.store.observeApprovalResolution(this.owner,o.key,{nativeInstanceId:this.instanceId,message:t.resolved}),t.completed!==null&&await this.options.store.observeApprovalTerminalItem(this.owner,o.key,{nativeInstanceId:this.instanceId,message:t.completed});let l=this.nativeRequests.get(t.request.id);l?.method===t.request.method&&(0,Y.isDeepStrictEqual)(l.params,t.request.params)&&(this.nativeRequests.delete(t.request.id),this.approvalAuthorities.delete(t.request.id));let u=(await this.options.store.snapshot(this.owner)).entries.filter(h=>h.controlKey===o.key);for(let h of u){if(h.binding.kind!=="approval")throw new T("NATIVE_CONTROL_INVALID");if(!h.nativeReceiptSha256){if(!this.canReceiveNativeReceipt(h))continue;await this.options.store.reconcileApproval(this.owner,h.event.eventId,{nativeInstanceId:this.instanceId,completed:t.completed,turnCompleted:t.turnCompleted})}this.startAcknowledgement(h)}this.startResolution(o.key)}return await this.restorePausedQuestions(),!0});return this.factTail=i.then(()=>{},()=>{}),this.track(i)}scopedKey(e){return me(JSON.stringify([this.owner.scope,e]))}control(e,t,i,s,n){let r=(0,U.newPromptRaise)({sessionId:this.owner.scope.sessionId,producerKind:"PLUGIN_APPROVAL",agentType:"CODEX",mobileActionable:!0}).record;return{key:this.scopedKey(e),kind:t,scope:K(this.owner.scope),nativeInstanceId:this.instanceId,threadId:this.options.threadId,turnId:i,itemId:s,detailsJson:JSON.stringify(n),raiseJson:JSON.stringify(r),state:"OPEN",cloudResolved:!1,answerEventId:null,nativeResolutionSha256:null,nativeResolutionJson:null}}serializePublication(e,t){let i=this.track(this.publicationTail.then(t));this.publicationTail=i.then(()=>{},()=>{}),this.publications.set(e,i);let s=()=>{if(this.publications.get(e)!==i)return;this.publications.delete(e);let n=this.publicationDemands.get(e);this.publicationDemands.delete(e),n&&this.startPublication(n.control,n.presentation)};return i.then(s,s),i}startPublication(e,t){if(!(!this.accepting||this.published.has(e.key))){if(this.publications.has(e.key)){this.publicationDemands.set(e.key,{control:e,presentation:t});return}this.serializePublication(e.key,async()=>{let i=await this.snapshotControls(),s=i.find(d=>d.key===e.key);if(s?.kind==="async"&&(this.firstQuestion(i)?.key!==s.key||s.state==="RESOLVED")){this.deferredQuestions.add(s.key);return}if(!s||!this.isPresentable(s)||s.cloudResolved||!this.accepting||!this.ownsApprovalSlot(s,i))return;if(s.kind==="async"&&(s.state==="PAUSED"||this.firstApproval(i))){this.deferredQuestions.add(s.key);return}if(this.deferredQuestions.delete(s.key),s.kind!=="async"&&s.state!=="UNCERTAIN"&&!this.pendingApprovalKeys([s]).length)return;let n=this.custodyMarker(s);if(n&&await this.publishCustody(n)!=="RERAISED")return;let r=await this.snapshotControls(),o=r.find(d=>d.key===s.key);!o||o.cloudResolved||!this.accepting||!this.isPresentable(o)||!this.ownsApprovalSlot(o,r)||o.kind!=="async"&&o.state!=="UNCERTAIN"&&!this.pendingApprovalKeys([o]).length||await this.options.publish(K(o),K(t))==="RERAISED"&&this.published.add(e.key)})}}isPresentable(e){return["OPEN","PAUSED"].includes(e.state)||e.state==="UNCERTAIN"&&JSON.parse(e.raiseJson).mobileActionable===!1}uncertainPresentation(){return{content:"An earlier mobile answer is unconfirmed. Continue on desktop; it will not be sent again automatically.",metadata:{nativeControlUncertain:!0,isApprovalHint:!1,isQueuedQuestion:!1}}}startResolution(e){if(this.resolutions.has(e))return;let t=this.track((async()=>{await this.publications.get(e)?.catch(()=>{}),await this.options.store.resolveControl(this.owner,e,this.options.resolve),await this.factTail,await this.publishFirstApproval(),await this.publishFirstQuestion(),await this.settleCustodies()})());this.resolutions.set(e,t),t.then(()=>this.resolutions.delete(e),()=>this.resolutions.delete(e))}startAcknowledgement(e){if(!Q(e.scope,this.owner.scope)||e.cloudAck==="EXECUTED"||this.acknowledgements.has(e.event.eventId))return;let t=this.track(this.dispatch.acknowledgeExisting(e.event.eventId));this.acknowledgements.set(e.event.eventId,t),t.then(()=>this.acknowledgements.delete(e.event.eventId),()=>this.acknowledgements.delete(e.event.eventId))}isQuestionPublished(e){let t=this.questionKeys.get(e);return!!t?.length&&t.every(i=>this.published.has(i)||this.deferredQuestions.has(i))}async projectInputReceipt(e){if(this.assertTarget(),e.threadId!==this.options.threadId)throw new T("NATIVE_QUESTION_MISMATCH");let t=await this.options.store.snapshot(this.owner),i=N(e.item),s=me((0,U.stableStringify)(K(e)));if(t.entries.some(o=>o.nativeReceiptSha256===s))return{echo:!0,text:null,images:[]};if(t.entries.some(o=>o.nativeReceiptSha256!==null&&o.binding.threadId===e.threadId&&o.binding.turnId===e.turnId&&(o.binding.kind==="user"&&i.type==="userMessage"&&i.clientId===o.binding.nativeId&&me((0,U.stableStringify)(i.content))===o.binding.receiptMatchSha256||o.binding.kind==="async"&&i.type==="functionCallOutput"&&i.namespace==="functions"&&i.name==="request_user_input_async"&&typeof i.output=="string"&&me(i.output)===o.binding.receiptMatchSha256)))return{echo:!0,text:null,images:[]};if(i.type==="userMessage"){let o=(0,U.parseCodexNativeQuestionAnswers)(i);if(o?.every(l=>t.controls.some(u=>this.matchesQuestionAnswer(u,e.threadId,l))))return{echo:!1,text:o.map(l=>l.answer).join(`
13
12
 
14
- `),images:[]}}refreshPromptTtls(e){return this.track((async()=>{if(!this.accepting)return;this.assertTarget();let t=r=>j(r.scope,this.owner.scope)&&r.nativeInstanceId===this.instanceId&&this.isPresentable(r)&&r.answerEventId===null&&!r.cloudResolved,i=await this.snapshotControls(),s=this.firstQuestion(i),n=i.filter(r=>t(r)&&(r.kind!=="async"||r.key===s?.key));n.length&&await e({sessionId:this.owner.scope.sessionId,promptIds:n.map(r=>JSON.parse(r.raiseJson).promptId)},async(r,o)=>{if(!this.accepting)return"CLOSED";this.assertTarget();let a=await this.snapshotControls(),l=this.firstQuestion(a),p=a.find(m=>t(m)&&(m.kind!=="async"||m.key===l?.key)&&JSON.parse(m.raiseJson).promptId===r);if(!p)return"CLOSED";let f;if(p.state==="UNCERTAIN")f=this.uncertainPresentation();else if(p.kind==="async")f=Ce(be(p));else{if(!this.pendingApprovalKeys([p]).length)return"CLOSED";let m=Pe(this.instanceId,this.options.threadId,O(JSON.parse(p.detailsJson)));if(!m)return"CLOSED";f=it(m,this.pausedQuestionPromptId(a))}let u=await this.options.publish(H(p),f,o);return u==="RERAISED"&&this.published.add(p.key),u})})())}prepareRehomes(){let e=this.factTail.then(async()=>{this.assertTarget();let t=await this.options.store.snapshot(this.owner);for(let i of t.controls){if(j(i.scope,this.owner.scope)||i.nativeInstanceId!==this.instanceId||!["SESSION_ENDED","UNCERTAIN"].includes(i.state)||!t.scopes.some(a=>j(a.scope,i.scope)&&a.state==="CLOSED"&&a.closureReason==="BACKEND_REPLACED"))continue;let s;if(i.kind==="async"){if(be(i),s=O(JSON.parse(i.detailsJson)).key,typeof s!="string"||!s.length)throw new T("NATIVE_CONTROL_INVALID")}else{let a=O(JSON.parse(i.detailsJson)),l=this.nativeRequests.get(a.request.id);if(!l||!(0,Z.isDeepStrictEqual)(l.params,a.request.params)||this.options.isCurrentControl?.(l)===!1)continue;let p=Pe(this.instanceId,this.options.threadId,a);if(!p)continue;s=p.key}if(!i.cloudResolved&&!await this.options.store.resolveControl(this.owner,i.key,this.options.resolve))throw new T("NATIVE_CONTROL_UNSUPPORTED");let n=O(JSON.parse(i.raiseJson)),r=i.state==="UNCERTAIN",o={...i,key:this.scopedKey(s),scope:H(this.owner.scope),raiseJson:JSON.stringify({...n,sessionId:this.owner.scope.sessionId,mobileActionable:r?!1:n.mobileActionable}),state:r?"UNCERTAIN":"OPEN",cloudResolved:!1,answerEventId:null,nativeResolutionSha256:null,nativeResolutionJson:null};if(await this.options.store.rehomeControl(this.owner,i.key,o),o.kind!=="async"){let a=O(JSON.parse(o.detailsJson)).request;this.options.isCurrentControl?.(a)!==!1&&(0,Z.isDeepStrictEqual)(this.nativeRequests.get(a.id)?.params,a.params)&&this.approvalAuthorities.set(a.id,{method:a.method,params:H(a.params),detailsSha256:Re(o.detailsJson)})}}(this.nativeRequests.size||this.options.hasPendingControl?.())&&await this.options.store.pauseOpenQuestions(this.owner)});return this.factTail=e.catch(()=>{}),this.track(e)}recover(){if(this.recovery)return this.recovery;if(!this.accepting)return Promise.resolve();let e=this.track((async()=>{this.assertTarget(),await this.prepareRehomes();let t=await this.options.store.snapshot(this.owner);for(let i of t.rejections)(!i.noticeResolved||!i.cloudDelivered)&&this.settleRejection(i);for(let i of t.controls)if(!i.cloudResolved){if(i.state==="RESOLVED"||t.scopes.some(s=>j(s.scope,i.scope)&&s.state==="CLOSED"))this.startResolution(i.key);else if(j(i.scope,this.owner.scope)&&i.nativeInstanceId===this.instanceId){if(i.state==="UNCERTAIN")this.startPublication(i,this.uncertainPresentation());else if(i.kind==="async")this.startPublication(i,Ce(be(i)));else if(this.pendingApprovalKeys([i]).length){let s=Pe(this.instanceId,this.options.threadId,O(JSON.parse(i.detailsJson)));s&&this.startPublication(i,it(s,this.pausedQuestionPromptId(t.controls)))}}}for(let i of t.entries)if(j(i.scope,this.owner.scope)){if(i.nativeReceiptSha256&&i.cloudAck!=="EXECUTED")this.startAcknowledgement(i);else if(i.kind==="INPUT"&&i.phase==="PREPARED"&&this.accepting){if(!await this.options.store.canAttempt(this.owner,i.event.eventId))continue;let s={...i.event,...JSON.parse(i.event.payloadJson)};try{this.assertTarget(JSON.parse(i.bodyJson))}catch(n){if(!(n instanceof Me))throw n;continue}try{await this.admit(s)}catch(n){if(!(n instanceof Me))throw n;let r=(await this.options.store.snapshot(this.owner)).entries.find(o=>o.event.eventId===i.event.eventId);if(!r||r.kind!=="INPUT"||r.phase!=="PREPARED")throw n}}}})());return this.recovery=e,e.then(()=>{this.recovery=null},()=>{this.recovery=null}),e}activate(){if(this.stopped)throw new T("NATIVE_CONTROL_UNSUPPORTED");this.accepting=!0}stopAdmission(){this.accepting=!1,this.stopped=!0,this.dispatch.stopAdmission()}async join(){for(;this.pending.size;)await Promise.allSettled([...this.pending]);await this.dispatch.join()}async close(e="TERMINAL"){this.stopAdmission(),await this.join(),await this.dispatch.close(e);for(let t of await this.snapshotControls())j(t.scope,this.owner.scope)&&!t.cloudResolved&&this.startResolution(t.key);await this.join()}async handoff(e){this.stopAdmission(),await this.join(),await this.dispatch.handoff(e)}};var as=require("@quantiya/codevibe-core"),g=require("@quantiya/codevibe-core");var fi=k(require("os")),gi=k(require("path")),yi=require("@quantiya/codevibe-core"),c=(0,yi.createLogger)({name:"codevibe-codex",logFile:gi.default.join(fi.default.tmpdir(),"codevibe-codex-mcp.log"),level:"debug"});var Ii=require("events"),A=k(require("fs")),ee=k(require("path")),Si=require("string_decoder"),rt=require("crypto"),wi=require("chokidar"),de=require("@quantiya/codevibe-core");var At=256*1024,xs=64*1024*1024,ks=16*1024*1024,Ds=64*1024,vi=100,Fs=250,Ms=["CHOKIDAR_USEPOLLING","CHOKIDAR_INTERVAL"];function Ls(d,e){let t=Ms.map(s=>[s,process.env[s]]);for(let[s]of t)delete process.env[s];let i;try{i=(0,wi.watch)(d,{...e,usePolling:!0})}finally{for(let[s,n]of t)n===void 0?delete process.env[s]:process.env[s]=n}if(i.options?.usePolling!==!0)throw i.close().catch(()=>{}),new Error("chokidar did not honour usePolling; refusing a native fs.watch");return i}function qs(d=process.env){let e=d.CODEX_HOME?.trim();return e?ee.resolve(e,"sessions"):(0,de.getConfig)().codex.sessionsDir}var ot=class extends Ii.EventEmitter{constructor(t={}){super();this.watcher=null;this.catchUpReadTimer=null;this.filePositions=new Map;this.activeLogFile=null;this.sessionId=null;this.isWatching=!1;this.startTime=0;this.sessionsDir=null;this.activeReads=new Map;this.ownedReads=new Set;this.pendingReads=new Set;this.readGeneration=0;this.oversizedRecordFiles=new Set;this.fileIdentities=new Map;this.bindSource=null;this.authoritativeSessionId=null;this.pendingTranscriptBind=null;this.transcriptBindGeneration=0;this.transcriptBindingsClosed=!1;this.activeTranscriptAdmissions=new Set;this.startBaselines=new Map;this.toolReplayBoundaries=new Map;if(this.maxBacklogBytes=t.maxBacklogBytes??xs,this.maxRecordBytes=t.maxRecordBytes??ks,this.beforeEntry=t.beforeEntry,this.restoreCursor=t.restoreCursor,this.beforeGap=t.beforeGap,this.beforeEntry!==void 0&&typeof this.beforeEntry!="function")throw new TypeError("beforeEntry must be a function");if(this.restoreCursor!==void 0&&typeof this.restoreCursor!="function"||this.beforeGap!==void 0&&typeof this.beforeGap!="function"||this.restoreCursor&&(!this.beforeEntry||!this.beforeGap))throw new TypeError("durable source restore requires entry and gap admission callbacks");if(!Number.isSafeInteger(this.maxBacklogBytes)||this.maxBacklogBytes<=0)throw new RangeError("maxBacklogBytes must be a positive safe integer");if(!Number.isSafeInteger(this.maxRecordBytes)||this.maxRecordBytes<=0)throw new RangeError("maxRecordBytes must be a positive safe integer")}start(){if(this.isWatching){c.warn("Session log watcher already running");return}this.transcriptBindGeneration++,this.transcriptBindingsClosed=!1;let t=qs();this.sessionsDir=t,c.info("Starting Codex session log watcher",{sessionsDir:t}),A.existsSync(t)||(c.info("Codex sessions directory does not exist yet, creating...",{sessionsDir:t}),A.mkdirSync(t,{recursive:!0})),this.startTime=Date.now(),this.readGeneration++,this.bindSource=null,this.authoritativeSessionId=null,this.snapshotStartBaselines(t),this.isWatching=!0,this.activeLogFile&&this.watchBoundRollout(this.activeLogFile),this.drainPendingTranscriptBind(),c.info("Session log watcher started; awaiting the SessionStart transcript bind")}stop(){this.transcriptBindingsClosed=!0,this.transcriptBindGeneration++,this.closeBoundRolloutWatch(),this.isWatching=!1,this.readGeneration++,this.filePositions.clear(),this.activeReads.clear(),this.pendingReads.clear(),this.oversizedRecordFiles.clear(),this.activeLogFile=null,this.sessionId=null,this.sessionsDir=null,this.bindSource=null,this.authoritativeSessionId=null,this.pendingTranscriptBind&&(this.pendingTranscriptBind.resolve({status:"rejected",reason:"watcher_stopped"}),this.pendingTranscriptBind=null),this.startBaselines.clear(),this.toolReplayBoundaries.clear(),this.fileIdentities.clear(),c.info("Session log watcher stopped")}async waitForTranscriptAdmissions(){for(;this.activeTranscriptAdmissions.size>0;)await Promise.all(Array.from(this.activeTranscriptAdmissions,t=>t.then(()=>{},()=>{})))}async waitForReads(){await Promise.all([...this.ownedReads])}retryActiveRead(){this.isWatching&&this.activeLogFile&&this.scheduleReadNewLines(this.activeLogFile)}getSessionId(){return this.sessionId}getActiveLogFile(){return this.activeLogFile}getToolReplayBoundary(t){if(t===this.activeLogFile)return this.toolReplayBoundaries.get(t)}refreshNativeOwnerBoundary(){if(!this.activeLogFile)return;let t=(0,de.captureToolReplayBoundary)(this.activeLogFile);this.readGeneration++,this.activeReads.delete(this.activeLogFile),this.pendingReads.delete(this.activeLogFile),this.toolReplayBoundaries.set(this.activeLogFile,t)}getBindSource(){return this.bindSource}getAuthoritativeSessionId(){return this.authoritativeSessionId}tryRealpath(t){try{return A.realpathSync(t)}catch{return null}}isInteractiveRollout(t){return!(!t||t.originator==="codex_exec"||t.threadSource==="subagent"||t.sourceSubagent)}identityOf(t){return{dev:t.dev,ino:t.ino}}identitiesEqual(t,i){return t.dev===i.dev&&t.ino===i.ino}computeSeedOffset(t){let i;try{i=A.statSync(t)}catch{return 0}if(this.getSessionAgeMs(t,i)>=this.startTime)return 0;let n=this.startBaselines.get(t);return n&&this.identitiesEqual(n.identity,this.identityOf(i))?n.size:i.size}applyBind(t,i){if(this.readGeneration++,this.activeReads.delete(t),this.pendingReads.delete(t),this.activeLogFile=t,this.bindSource=i,i==="heuristic"&&(this.authoritativeSessionId=null),!this.filePositions.has(t)){let s=(0,de.captureToolReplayBoundary)(t,this.computeSeedOffset(t));this.filePositions.set(t,s.byteOffset),this.toolReplayBoundaries.set(t,s)}this.toolReplayBoundaries.has(t)||this.toolReplayBoundaries.set(t,(0,de.captureToolReplayBoundary)(t,this.filePositions.get(t)));try{this.fileIdentities.set(t,this.identityOf(A.statSync(t)))}catch{this.fileIdentities.delete(t)}this.watchBoundRollout(t),this.scheduleReadNewLines(t)}watchBoundRollout(t){if(this.closeBoundRolloutWatch(),!this.isWatching||this.transcriptBindingsClosed)return;let i;try{i=Ls(t,{persistent:!0,ignoreInitial:!0,usePolling:!0,interval:vi,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}})}catch(s){c.error("Could not follow bound rollout by polling",{filePath:t,error:s instanceof Error?s.message:String(s)}),this.emit("error",s);return}this.watcher=i,i.on("add",s=>this.onFileAdded(s)),i.on("change",s=>this.onFileChanged(s)),i.on("error",s=>{c.error("Watcher error:",s),this.emit("error",s)}),i.on("ready",()=>{this.watcher===i&&(this.catchUpReadTimer=setTimeout(()=>{this.catchUpReadTimer=null,this.watcher===i&&this.activeLogFile===t&&this.scheduleReadNewLines(t)},Fs),this.catchUpReadTimer.unref?.())}),c.info("Following bound rollout",{filePath:t,pollIntervalMs:vi})}closeBoundRolloutWatch(){this.catchUpReadTimer&&(clearTimeout(this.catchUpReadTimer),this.catchUpReadTimer=null);let t=this.watcher;t&&(this.watcher=null,t.close().catch(i=>{c.warn("Bound rollout watcher close failed",{error:i instanceof Error?i.message:String(i)})}))}bindToFile(t){let i=this.tryRealpath(t);if(!i){c.warn("bindToFile: could not canonicalize path; skipping",{filePath:t});return}if(i===this.activeLogFile){this.bindSource="authoritative";return}c.info("bindToFile: authoritative bind to session rollout",{filePath:i}),this.applyBind(i,"authoritative")}async bindToSessionTranscript(t,i){if(typeof t!="string"||t.length===0)return{status:"rejected",reason:"missing_transcript_path"};if(this.transcriptBindingsClosed)return{status:"rejected",reason:"watcher_stopped"};if(!this.sessionsDir){let s=this.pendingTranscriptBind;if(s)return s.transcriptPath===t&&s.expectedSessionId===i?{status:"pending",completion:s.completion}:(c.warn("bindToSessionTranscript: conflicting startup bind rejected",{transcriptPath:t,expectedSessionId:i,pendingExpectedSessionId:s.expectedSessionId}),{status:"rejected",reason:"conflicting_startup_bind"});let n,r=new Promise(o=>{n=o});return this.pendingTranscriptBind={transcriptPath:t,expectedSessionId:i,completion:r,resolve:n},c.debug("bindToSessionTranscript: watcher not started yet; queued pending authoritative bind",{transcriptPath:t,expectedSessionId:i}),{status:"pending",completion:r}}return this.trackTranscriptAdmission(this.validateAndBindSessionTranscript(t,i,this.transcriptBindGeneration))}trackTranscriptAdmission(t){let i;return i=t.finally(()=>{this.activeTranscriptAdmissions.delete(i)}),this.activeTranscriptAdmissions.add(i),i}isTranscriptAdmissionCurrent(t,i){return!this.transcriptBindingsClosed&&this.transcriptBindGeneration===t&&this.sessionsDir===i}async validateAndBindSessionTranscript(t,i,s){let n=this.sessionsDir;if(!n||!this.isTranscriptAdmissionCurrent(s,n))return{status:"rejected",reason:"watcher_not_started"};let r=this.tryRealpath(t),o=this.tryRealpath(n);if(!r||!o)return{status:"rejected",reason:"canonicalization_failed"};let a=ee.relative(o,r);if(a===".."||a.startsWith(".."+ee.sep)||ee.isAbsolute(a))return c.warn("bindToSessionTranscript: path not under sessionsDir; rejecting",{transcriptPath:r}),{status:"rejected",reason:"outside_sessions_directory"};let l=ee.basename(r);if(!l.startsWith("rollout-")||!l.endsWith(".jsonl"))return{status:"rejected",reason:"invalid_rollout_filename"};let p=null;for(let f=0;f<3;f++){if(!this.isTranscriptAdmissionCurrent(s,n))return{status:"rejected",reason:"watcher_stopped"};if(p=this.readSessionMeta(r),p)break;if(await new Promise(u=>setTimeout(u,20)),!this.isTranscriptAdmissionCurrent(s,n))return{status:"rejected",reason:"watcher_stopped"}}return!p||p.id!==i?(c.debug("bindToSessionTranscript: meta missing or id mismatch; not binding",{transcriptPath:r,metaId:p?.id,expectedSessionId:i}),{status:"rejected",reason:"session_metadata_mismatch"}):this.isInteractiveRollout(p)?this.isTranscriptAdmissionCurrent(s,n)?(this.bindToFile(r),this.authoritativeSessionId=i,{status:"bound"}):{status:"rejected",reason:"watcher_stopped"}:(c.debug("bindToSessionTranscript: non-interactive rollout (codex_exec/subagent); not binding",{transcriptPath:r,originator:p.originator,threadSource:p.threadSource}),{status:"rejected",reason:"non_interactive_rollout"})}async drainPendingTranscriptBind(){let t=this.pendingTranscriptBind;if(!t)return;this.pendingTranscriptBind=null;let i;try{this.transcriptBindingsClosed?i={status:"rejected",reason:"watcher_stopped"}:i=await this.trackTranscriptAdmission(this.validateAndBindSessionTranscript(t.transcriptPath,t.expectedSessionId,this.transcriptBindGeneration))}catch(s){c.warn("bindToSessionTranscript: pending startup bind failed",{expectedSessionId:t.expectedSessionId,error:s instanceof Error?s.message:String(s)}),i={status:"rejected",reason:"startup_bind_failed"}}t.resolve(i)}onFileAdded(t){let i=this.tryRealpath(t);i&&(i===this.activeLogFile?this.scheduleReadNewLines(i):c.debug("Ignoring unowned rollout add; awaiting authoritative hook binding",{filePath:i}))}onFileChanged(t){let i=this.tryRealpath(t);i&&(this.activeLogFile&&i!==this.activeLogFile||this.activeLogFile&&this.scheduleReadNewLines(i))}readSessionMeta(t){let i=this.readFirstLogEntry(t);if(!i)return null;let s=i.payload||{};return{id:typeof s.id=="string"?s.id:void 0,timestamp:typeof i.timestamp=="string"?i.timestamp:void 0,originator:typeof s.originator=="string"?s.originator:void 0,cwd:typeof s.cwd=="string"?s.cwd:void 0,threadSource:typeof s.thread_source=="string"?s.thread_source:void 0,sourceSubagent:!!(s.source&&typeof s.source=="object"&&s.source.subagent)}}readFirstLogEntry(t){let i=null;try{i=A.openSync(t,"r");let s=new Si.StringDecoder("utf8"),n=Buffer.alloc(64*1024),r="",o=0,a=-1;for(;o<At;){let p=A.readSync(i,n,0,n.length,o);if(p<=0||(o+=p,r+=s.write(n.subarray(0,p)),a=r.indexOf(`
15
- `),a!==-1))break}r+=s.end();let l=a===-1?r:r.slice(0,a);return l.trim()?JSON.parse(l):null}catch{return null}finally{if(i!==null)try{A.closeSync(i)}catch{}}}snapshotStartBaselines(t){this.startBaselines.clear();try{for(let{filePath:i,size:s}of this.collectRecentSessionFiles(t,!0)){let n=this.tryRealpath(i);if(n)try{let r=A.statSync(n);this.startBaselines.set(n,{size:s,identity:this.identityOf(r)})}catch{}}}catch{}}getSessionAgeMs(t,i){let s=this.readSessionMeta(t);if(s?.timestamp){let n=Date.parse(s.timestamp);if(!Number.isNaN(n))return n}return i.birthtimeMs||i.ctimeMs}collectRecentSessionFiles(t,i=!1){let s=[],n=[t];for(;n.length>0;){let r=n.pop();if(!r)continue;let o;try{o=A.readdirSync(r,{withFileTypes:!0})}catch{continue}for(let a of o){let l=ee.join(r,a.name);if(a.isDirectory()){n.push(l);continue}if(!(!a.isFile()||!a.name.startsWith("rollout-")||!a.name.endsWith(".jsonl")))try{let p=A.statSync(l),f=p.birthtimeMs||p.ctimeMs,u=p.mtimeMs;(i||f>=this.startTime||u>=this.startTime-5e3)&&s.push({filePath:l,createdAt:f,modifiedAt:u,size:p.size})}catch{}}}return s}scheduleReadNewLines(t){let i=this.activeReads.get(t);if(i)return this.pendingReads.add(t),i;let s=this.readGeneration,n=Promise.resolve().then(()=>this.drainReadQueue(t,s));return this.activeReads.set(t,n),this.ownedReads.add(n),n.finally(()=>{this.ownedReads.delete(n),this.activeReads.get(t)===n&&(this.activeReads.delete(t),this.pendingReads.delete(t))}),n}async drainReadQueue(t,i){do this.pendingReads.delete(t),await this.readNewLines(t,i);while(i===this.readGeneration&&this.pendingReads.has(t))}async readNewLines(t,i){if(i!==this.readGeneration)return;let s=this.filePositions.get(t)||0,n=null;try{n=A.openSync(t,A.constants.O_RDONLY|(A.constants.O_NOFOLLOW??0));let r=A.fstatSync(n),o=this.identityOf(r),a=this.fileIdentities.get(t);if(a&&!this.identitiesEqual(a,o)){let S=this.readFirstLogEntryFromFd(n),P=S?.type==="session_meta"?S.payload.id:void 0;if(this.authoritativeSessionId&&P!==this.authoritativeSessionId){let b=new Error("Authoritative Codex rollout path was replaced by a different session");c.error("Refusing replaced rollout with mismatched session identity",{filePath:t,expectedSessionId:this.authoritativeSessionId,replacementSessionId:P}),this.emit("error",b);return}c.info("Session log inode replaced; resetting byte and decoder state",{filePath:t,oldPosition:s,oldIdentity:a,newIdentity:o}),s=0,this.filePositions.set(t,0),this.oversizedRecordFiles.delete(t)}if(this.fileIdentities.set(t,o),this.restoreCursor&&this.sessionId===null){let S=this.readFirstLogEntryFromFd(n);S?.type==="session_meta"&&this.processLogEntry(S)}let l=Object.freeze({transcriptPath:t,nativeSessionId:this.authoritativeSessionId??this.sessionId,fileIdentity:Object.freeze({...o})}),p=!1;if(this.restoreCursor){let S=this.toolReplayBoundaries.get(t)?.byteOffset??s,P=S<=r.size?S:0,b=this.readSourceAnchor(n,P),R=await this.restoreCursor(l,{byteOffset:P,anchor:b,discardUntilNewline:P>0&&!this.isNewlineBoundary(n,P)});if(i!==this.readGeneration)return;R!==null&&(this.verifySourcePosition(n,r.size,R),s=R.byteOffset,p=!0,this.filePositions.set(t,s),R.discardUntilNewline?this.oversizedRecordFiles.add(t):this.oversizedRecordFiles.delete(t))}let f=async(S,P,b,R)=>(p&&await this.beforeGap({startOffset:S,endOffset:P,reason:b,discardUntilNewline:R,anchor:this.readSourceAnchor(n,P,S)},l),i===this.readGeneration);if(r.size<s&&(c.info("Session log truncated/rotated; resetting cursor to 0",{filePath:t,oldPosition:s,size:r.size}),s=0,this.filePositions.set(t,0),this.oversizedRecordFiles.delete(t)),r.size<=s)return;if(r.size-s>this.maxBacklogBytes){if(s===0&&this.sessionId===null){let P=this.readFirstLogEntryFromFd(n);P?.type==="session_meta"&&this.processLogEntry(P)}let S=this.findRecentRecordBoundary(n,r.size);if(!await f(s,S.position,"BACKLOG_LIMIT",S.discardUntilNewline)||(c.warn("Codex rollout backlog exceeded live-mirror limit; skipping archival prefix",{filePath:t,oldPosition:s,newPosition:S.position,size:r.size,maxBacklogBytes:this.maxBacklogBytes,discardUntilNewline:S.discardUntilNewline}),s=S.position,this.filePositions.set(t,s),S.discardUntilNewline?this.oversizedRecordFiles.add(t):this.oversizedRecordFiles.delete(t),r.size<=s))return}let u=r.size,m=Buffer.allocUnsafe(64*1024),h=s,I=s,y=[],w=0,v=this.oversizedRecordFiles.has(t);for(;h<u;){if(i!==this.readGeneration)return;let S=Math.min(m.length,u-h),P=A.readSync(n,m,0,S,h);if(P<=0)break;let b=0;for(;b<P;){if(i!==this.readGeneration)return;let R=m.subarray(0,P).indexOf(10,b),_=R!==-1,D=_?R:P,N=D-b,ie=N+(_?1:0);if(v){if(h+=ie,!await f(I,h,"PARTIAL_RECORD",!_))return;this.filePositions.set(t,h),I=h,_&&(v=!1,this.oversizedRecordFiles.delete(t)),b=_?R+1:P;continue}if(N>0&&(y.push(Buffer.from(m.subarray(b,D))),w+=N),h+=ie,w>this.maxRecordBytes){if(c.warn("Discarding oversized Codex rollout JSONL record",{filePath:t,recordEnd:h,maxRecordBytes:this.maxRecordBytes}),!await f(I,h,"OVERSIZED_RECORD",!_))return;this.filePositions.set(t,h),I=h,y=[],w=0,v=!_,v?this.oversizedRecordFiles.add(t):this.oversizedRecordFiles.delete(t),b=_?R+1:P;continue}if(!_){b=P;continue}let q=Buffer.concat(y,w),G=q;y=[],w=0,q.length>0&&q[q.length-1]===13&&(q=q.subarray(0,q.length-1));let _e=q.toString("utf8");if(_e.trim()){let he;try{let se=JSON.parse(_e);if(!se||typeof se!="object"||Array.isArray(se)||typeof se.type!="string")throw new Error("Invalid Codex log entry shape");he=se}catch(se){if(c.warn("Failed to parse log line",{filePath:t,line:_e.substring(0,100),error:se}),!await f(I,h,"MALFORMED_RECORD",!1))return}if(he!==void 0){let se=!1;if(this.beforeEntry&&(se=await this.beforeEntry(he,Object.freeze({...l,startOffset:h-G.length-1,endOffset:h,sha256:(0,rt.createHash)("sha256").update(G).update(`
16
- `).digest("hex"),anchor:Object.freeze(this.framedSourceAnchor(G,h))}))==="handled",i!==this.readGeneration))return;try{se||this.processLogEntry(he)}catch(ne){c.warn("Failed to process log line",{filePath:t,error:ne})}}}else if(!await f(I,h,"EMPTY_RECORD",!1))return;if(i===this.readGeneration&&(this.filePositions.set(t,h),I=h),i!==this.readGeneration)return;b=R+1}}}catch(r){c.error("Error reading log file",{filePath:t,error:r}),this.emit("error",r)}finally{if(n!==null)try{A.closeSync(n)}catch{}}}framedSourceAnchor(t,i){let s=t.subarray(Math.max(0,t.length-(de.MAX_SYNC_SOURCE_ANCHOR_BYTES-1)));return{startOffset:i-s.length-1,endOffset:i,sha256:(0,rt.createHash)("sha256").update(s).update(`
17
- `).digest("hex")}}readSourceAnchor(t,i,s=0){if(i===0)return null;let n=Math.max(s,i-de.MAX_SYNC_SOURCE_ANCHOR_BYTES);if(n>=i)throw new Error("SYNC_SOURCE_POSITION_INVALID");let r=Buffer.allocUnsafe(i-n),o=0;for(;o<r.length;){let a=A.readSync(t,r,o,r.length-o,n+o);if(a<=0)throw new Error("SYNC_SOURCE_ANCHOR_UNAVAILABLE");o+=a}return{startOffset:n,endOffset:i,sha256:(0,rt.createHash)("sha256").update(r).digest("hex")}}isNewlineBoundary(t,i){if(i===0)return!0;let s=Buffer.allocUnsafe(1);return A.readSync(t,s,0,1,i-1)===1&&s[0]===10}verifySourcePosition(t,i,s){let{byteOffset:n,anchor:r,discardUntilNewline:o}=s;if(!Number.isSafeInteger(n)||n<0||n>i||typeof o!="boolean")throw new Error("SYNC_SOURCE_POSITION_INVALID");if(n===0){if(r!==null||o)throw new Error("SYNC_SOURCE_POSITION_INVALID");return}if(!r||!Number.isSafeInteger(r.startOffset)||r.startOffset<0||r.endOffset!==n||r.startOffset>=n||n-r.startOffset>de.MAX_SYNC_SOURCE_ANCHOR_BYTES||!/^[a-f0-9]{64}$/.test(r.sha256)||o===this.isNewlineBoundary(t,n))throw new Error("SYNC_SOURCE_POSITION_INVALID");if(this.readSourceAnchor(t,n,r.startOffset).sha256!==r.sha256)throw new Error("SYNC_SOURCE_ANCHOR_CHANGED")}findRecentRecordBoundary(t,i){let s=Math.max(0,i-this.maxBacklogBytes),n=s+Math.min(i-s,this.maxRecordBytes);{if(s===0)return{position:0,discardUntilNewline:!1};let r=Buffer.allocUnsafe(1);if(A.readSync(t,r,0,1,s-1)===1&&r[0]===10)return{position:s,discardUntilNewline:!1};let o=Buffer.allocUnsafe(Ds),a=s;for(;a<n;){let l=Math.min(o.length,n-a),p=A.readSync(t,o,0,l,a);if(p<=0)break;let f=o.subarray(0,p).indexOf(10);if(f!==-1)return{position:a+f+1,discardUntilNewline:!1};a+=p}if(a===n&&a<i&&n-s===this.maxRecordBytes){let l=Buffer.allocUnsafe(1);if(A.readSync(t,l,0,1,a)===1&&l[0]===10)return{position:a+1,discardUntilNewline:!1}}return{position:s,discardUntilNewline:!0}}}readFirstLogEntryFromFd(t){try{let i=[],s=0,n=Buffer.allocUnsafe(64*1024);for(;s<At;){let o=Math.min(n.length,At-s),a=A.readSync(t,n,0,o,s);if(a<=0)break;let l=n.subarray(0,a).indexOf(10);if(l!==-1){i.push(Buffer.from(n.subarray(0,l)));break}i.push(Buffer.from(n.subarray(0,a))),s+=a}if(i.length===0)return null;let r=Buffer.concat(i).toString("utf8");return r.trim()?JSON.parse(r):null}catch{return null}}processLogEntry(t){if(c.debug("Processing log entry",{type:t.type}),t.type==="session_meta"){let i=t.payload;this.sessionId=i.id,c.info("Codex session started",{sessionId:i.id,cwd:i.cwd,cliVersion:i.cli_version}),this.emit("session-started",i);return}this.emit("log-entry",t),t.type==="event_msg"&&t.payload?.type?this.emit(`event:${t.payload.type}`,t):t.type==="response_item"&&t.payload?.type&&this.emit(`response:${t.payload.type}`,t)}};var Ot=require("uuid"),lt=require("crypto"),U=require("@quantiya/codevibe-core");function Ne(d){if(typeof d!="string"||d.length>262144)return null;let e=/^\s*<send_user_message_question_reply>\s*([\s\S]*?)\s*<\/send_user_message_question_reply>\s*$/.exec(d);if(!e)return null;try{let t=JSON.parse(e[1]);if(!Array.isArray(t)||t.length===0||t.length>100)return null;let i=new Set,s=[];for(let n of t){if(!n||typeof n!="object"||Array.isArray(n)||typeof n.answer!="string"||!n.answer.trim()||typeof n.question!="string"||!n.question.trim()||typeof n.questionItemId!="string")return null;let r=JSON.parse(n.questionItemId);if(!Array.isArray(r)||r.length!==3||r[0]!=="request_user_input_async"||typeof r[1]!="string"||!r[1].trim()||r[1].length>512||!Number.isInteger(r[2])||r[2]<0||r[2]>=100)return null;let o=JSON.stringify(r);if(i.has(o))return null;i.add(o),s.push({callId:r[1],index:r[2],question:n.question,answer:n.answer})}return s}catch{return null}}function Le(d){if(d.type==="event_msg"&&d.payload?.type==="user_message")return d.payload.message;if(d.type==="response_item"&&d.payload?.type==="message"&&d.payload.role==="user"&&Array.isArray(d.payload.content)&&d.payload.content.every(e=>e?.type==="input_text"&&typeof e.text=="string"))return d.payload.content.map(e=>e.text).join(`
18
- `)}function Ei(d){return Ne(d)?.map(e=>e.answer).join(`
13
+ `),images:[]};if(!Array.isArray(i.content))throw new T("NATIVE_CONTROL_INVALID");return{echo:!1,text:i.content.map(l=>{if(!l||typeof l!="object"||typeof l.type!="string")throw new T("NATIVE_CONTROL_INVALID");if(l.type==="text"&&typeof l.text=="string")return l.text;if(l.type==="localImage"&&typeof l.path=="string"&&l.path.startsWith("/"))return null;if(l.type==="image"&&(typeof l.url=="string"&&l.url.length>0&&l.fileId===void 0||typeof l.fileId=="string"&&l.fileId.length>0&&l.url===void 0))return"[image]";if(l.type==="audio"&&typeof l.url=="string"&&l.url.length||l.type==="localAudio"&&typeof l.path=="string"&&l.path.startsWith("/"))return"[audio]";if(["skill","mention"].includes(l.type)&&typeof l.name=="string"&&l.name.length&&typeof l.path=="string"&&l.path.length)return`[${l.type}: ${l.name}]`;if(["text","localImage","image","audio","localAudio","skill","mention"].includes(l.type))throw new T("NATIVE_CONTROL_UNSUPPORTED");return"[unsupported native attachment]"}).filter(l=>l!==null).join(`
14
+ `),images:i.content.filter(l=>l.type==="localImage").map(l=>l.path)}}if(i.type!=="functionCallOutput"||i.namespace!=="functions"||i.name!=="request_user_input_async")return{echo:!1,text:null,images:[]};let n=JSON.parse(i.output);if(!Array.isArray(n)||!n.length)throw new T("NATIVE_CONTROL_INVALID");return{echo:!1,text:n.map(o=>{let d=N(o),l=t.controls.find(u=>u.kind==="async"&&u.threadId===e.threadId&&JSON.parse(u.detailsJson).questionItemId===d.questionItemId);if(!l||typeof d.answer!="string"||d.question!==JSON.parse(l.detailsJson).title)throw new T("NATIVE_QUESTION_MISMATCH");return d.answer}).join(`
19
15
 
20
- `)??d}var le=new Map,z=[],bi=24;function Ke(d){return typeof d=="string"?d.trim():""}function Ri(d){return typeof d=="string"?d:""}function at(d,e,t){let i=Ke(t);if(!i)return!1;let s=Ri(e),n=(0,lt.createHash)("sha256").update(i).digest("hex");return z.some(r=>r.textHash===n&&r.phase===s&&r.carrier!==d)}function Bs(d){let e=Ke(d),t=(0,lt.createHash)("sha256").update(e).digest("hex");return e.length>0&&z.some(i=>i.textHash===t&&i.phase==="final_answer")}function qe(d,e,t){let i=Ke(t);if(i)for(z.push({carrier:d,phase:Ri(e),textHash:(0,lt.createHash)("sha256").update(i).digest("hex")});z.length>bi;)z.shift()}function pe(d=!1){let e=d?z.filter(t=>t.phase==="question_reply"||t.phase==="user_prompt"):[];z.splice(0,z.length,...e)}function Ti(d,e,t){let i=[];if(t!==null){if(typeof t!="string"||Buffer.byteLength(t)>16*1024)throw new Error("INVALID_CODEX_SOURCE_PROJECTION");try{i=JSON.parse(t)}catch{throw new Error("INVALID_CODEX_SOURCE_PROJECTION")}if(!Array.isArray(i)||i.length>bi||i.some(r=>!r||Object.keys(r).sort().join(",")!=="carrier,phase,textHash"||!["agent_message","response_item","task_complete"].includes(r.carrier)||typeof r.phase!="string"||typeof r.textHash!="string"||!/^[a-f0-9]{64}$/.test(r.textHash)))throw new Error("INVALID_CODEX_SOURCE_PROJECTION")}let s=z.slice(),n=new Map(le);z.splice(0,z.length,...i);try{let r=kt(d,e),o=JSON.stringify(z);if(Buffer.byteLength(o)>16*1024)throw new Error("INVALID_CODEX_SOURCE_PROJECTION");return{event:r,projection:o}}finally{z.splice(0,z.length,...s),le.clear();for(let[r,o]of n)le.set(r,o)}}function Ks(d){let e=d?.content;return Array.isArray(e)?e.filter(t=>t&&(t.type==="output_text"||t.type==="text")).map(t=>typeof t?.text=="string"?t.text:"").join(""):""}function Us(d){let e=d?.summary;return!Array.isArray(e)||e.length===0?"":e.map(t=>typeof t=="string"?t:typeof t?.text=="string"?t.text:"").join(`
21
- `).trim()}function Vs(d){if(typeof d!="string")return"";let e=d.match(/"cmd"\s*:\s*"((?:\\.|[^"\\])*)"/);if(e)try{return JSON.parse(`"${e[1]}"`)}catch{return e[1]}return""}function Ae(d){if(typeof d!="string"||!d.startsWith(`*** Begin Patch
22
- `)||!d.endsWith(`
23
- *** End Patch`))return"";let e=d.split(`
24
- `);return e[0]!=="*** Begin Patch"||e[e.length-1]!=="*** End Patch"||e.filter(t=>t==="*** Begin Patch").length!==1||e.filter(t=>t==="*** End Patch").length!==1||!/^\*\*\* (?:Add|Update|Delete) File: [^\r\n]+$/.test(e[1]??"")?"":d}function Ue(d){if(typeof d!="string")return"";let e="[A-Za-z_$][\\w$]*",t='"(?:\\\\.|[^"\\\\])*"',i=d.match(new RegExp(`^\\s*(?:const|let|var)\\s+(${e})\\s*=\\s*await\\s+tools\\.apply_patch\\(\\s*(${t})\\s*\\)\\s*;\\s*(?:text\\(\\s*(${e})\\s*\\)\\s*;\\s*)?$`,"s")),s=d.match(new RegExp(`^\\s*(?:const|let|var)\\s+(${e})\\s*=\\s*(${t})\\s*;\\s*(?:const|let|var)\\s+(${e})\\s*=\\s*await\\s+tools\\.apply_patch\\(\\s*(${e})\\s*\\)\\s*;\\s*(?:text\\(\\s*(${e})\\s*\\)\\s*;\\s*)?$`,"s")),n;if(i&&(!i[3]||i[3]===i[1])?n=i[2]:s&&s[4]===s[1]&&(!s[5]||s[5]===s[3])&&(n=s[2]),!n)return"";try{return Ae(JSON.parse(n))}catch{return""}}var Qs=new Set(["exec","shell","shell_command","bash","run_command","run_cmd"]);function Pi(d,e){return typeof e!="string"?"":d==="apply_patch"?e:d==="exec"?Ue(e):typeof d=="string"&&Qs.has(d)?"":e.includes("*** Begin Patch")?e:""}function kt(d,e){let t={sessionId:e,source:U.EventSource.DESKTOP};if(d.type==="event_msg"&&d.payload?.type==="item_completed"&&d.payload.item?.type==="UserMessage")return pe(!0),null;let i=Ne(Le(d));if(i){let o=d.type==="response_item"?"response_item":"agent_message",a=JSON.stringify(i);return at(o,"question_reply",a)?null:(pe(!0),qe(o,"question_reply",a),{...t,type:U.EventType.USER_PROMPT,content:i.map(l=>l.answer).join(`
16
+ `),images:[]}}refreshPromptTtls(e){return this.track((async()=>{if(!this.accepting)return;this.assertTarget();let t=o=>Q(o.scope,this.owner.scope)&&o.nativeInstanceId===this.instanceId&&this.isPresentable(o)&&o.answerEventId===null&&!o.cloudResolved,i=await this.snapshotControls(),s=this.firstQuestion(i),n=i.filter(o=>t(o)&&this.ownsApprovalSlot(o,i)&&(o.kind!=="async"||o.key===s?.key)),r=new Map;for(let o of i)if(!o.cloudResolved&&Q(o.scope,this.owner.scope)&&o.nativeInstanceId===this.instanceId){let d=this.custodyMarker(o);d&&r.set(d.raise.promptId,d)}!n.length&&!r.size||await e({sessionId:this.owner.scope.sessionId,promptIds:[...n.map(o=>JSON.parse(o.raiseJson).promptId),...r.keys()]},(o,d)=>{let l=r.get(o);if(l)return this.publishCustody(l,d);let u=n.find(h=>JSON.parse(h.raiseJson).promptId===o);return u?this.serializePublication(u.key,async()=>{if(!this.accepting)return"CLOSED";this.assertTarget();let h=await this.snapshotControls(),p=this.firstQuestion(h),m=h.find(I=>t(I)&&this.ownsApprovalSlot(I,h)&&(I.kind!=="async"||I.key===p?.key)&&JSON.parse(I.raiseJson).promptId===o);if(!m)return"CLOSED";if(m.kind==="async"&&(m.state==="PAUSED"||this.firstApproval(h)))return"RETRY";let f;if(m.state==="UNCERTAIN")f=this.uncertainPresentation();else if(m.kind==="async")f=De(ye(m));else{if(!this.pendingApprovalKeys([m]).length)return"CLOSED";let I=this.approvalPresentation(m);if(!I)return"CLOSED";f=I}let g=this.custodyMarker(m);if(g&&await this.publishCustody(g)!=="RERAISED")return"RETRY";let y=(await this.snapshotControls()).find(I=>I.key===m.key);if(!y||y.cloudResolved||!this.accepting||!this.isPresentable(y))return"CLOSED";let S=await this.options.publish(K(y),f,d);return S==="RERAISED"&&this.published.add(m.key),S}):Promise.resolve("CLOSED")})})())}prepareRehomes(){let e=this.factTail.then(async()=>{this.assertTarget();let t=await this.options.store.snapshot(this.owner);for(let i of t.controls){if(Q(i.scope,this.owner.scope)||i.nativeInstanceId!==this.instanceId||!["SESSION_ENDED","UNCERTAIN"].includes(i.state)||!t.scopes.some(d=>Q(d.scope,i.scope)&&d.state==="CLOSED"&&d.closureReason==="BACKEND_REPLACED"))continue;let s;if(i.kind==="async"){if(ye(i),s=N(JSON.parse(i.detailsJson)).key,typeof s!="string"||!s.length)throw new T("NATIVE_CONTROL_INVALID")}else{let d=N(JSON.parse(i.detailsJson)),l=this.nativeRequests.get(d.request.id);if(!l||!(0,Y.isDeepStrictEqual)(l.params,d.request.params)||this.options.isCurrentControl?.(l)===!1)continue;let u=ke(this.instanceId,this.options.threadId,d);if(!u)continue;s=u.key}if(!i.cloudResolved&&!await this.options.store.resolveControl(this.owner,i.key,this.options.resolve))throw new T("NATIVE_CONTROL_UNSUPPORTED");let n=N(JSON.parse(i.raiseJson)),r=i.state==="UNCERTAIN",o={...i,key:this.scopedKey(s),scope:K(this.owner.scope),raiseJson:JSON.stringify({...n,sessionId:this.owner.scope.sessionId,mobileActionable:r?!1:n.mobileActionable}),state:r?"UNCERTAIN":"OPEN",cloudResolved:!1,answerEventId:null,nativeResolutionSha256:null,nativeResolutionJson:null};if(await this.options.store.rehomeControl(this.owner,i.key,o),o.kind!=="async"){let d=N(JSON.parse(o.detailsJson)).request;this.options.isCurrentControl?.(d)!==!1&&(0,Y.isDeepStrictEqual)(this.nativeRequests.get(d.id)?.params,d.params)&&this.approvalAuthorities.set(d.id,{method:d.method,params:K(d.params),detailsSha256:me(o.detailsJson)})}}(this.nativeRequests.size||this.options.hasPendingControl?.())&&await this.options.store.pauseOpenQuestions(this.owner)});return this.factTail=e.catch(()=>{}),this.track(e.then(()=>this.settleCustodies()))}restoreResumedQuestions(){let e=this.factTail.then(async()=>{if(this.assertTarget(),!this.options.readQuestionResumeWindow)return;let t=await this.options.store.snapshot(this.owner),i=t.controls.filter(n=>n.kind==="async"&&n.nativeInstanceId!==this.instanceId&&n.threadId===this.options.threadId&&n.state==="SESSION_ENDED"&&n.answerEventId===null&&n.nativeResolutionSha256===null&&t.scopes.some(r=>Q(r.scope,n.scope)&&r.state==="CLOSED"&&r.closureReason==="TERMINAL"));if(!i.length)return;let s;try{s=await this.options.readQuestionResumeWindow(K(i))}catch{this.assertTarget(),this.report("NATIVE_QUESTION_RESUME_NOT_PROVEN");return}if(this.assertTarget(),s.threadId!==this.options.threadId||s.nativeInstanceId!==this.instanceId)throw new T("NATIVE_QUESTION_MISMATCH");for(let n of s.items){let r=(0,U.parseCodexNativeQuestionAnswers)(n.item);r&&await this.closeAnsweredQuestions({threadId:s.threadId,...n},t.controls,r)}for(let n of i){let r=(await this.snapshotControls()).find(p=>p.key===n.key);if(!r||r.state!=="SESSION_ENDED"||r.nativeResolutionSha256||r.answerEventId)continue;let o=s.items.findIndex(p=>p.turnId===n.turnId&&N(p.item).id===n.itemId),d=s.turns.find(p=>p.id===n.turnId);if(o<0||d?.status!=="completed"){this.report("NATIVE_QUESTION_RESUME_NOT_PROVEN");continue}if(!r.cloudResolved&&!await this.options.store.resolveControl(this.owner,n.key,this.options.resolve)){this.report("NATIVE_QUESTION_RESUME_NOT_PROVEN");continue}let l=ye(n),u=this.control(l.key,"async",l.turnId,l.itemId,JSON.parse(n.detailsJson));await this.options.store.resumeQuestionControl(this.owner,n.key,u,{threadId:s.threadId,nativeInstanceId:s.nativeInstanceId,questionTurn:d,items:s.items.slice(0,o+1)});let h=this.questionKeys.get(l.itemId)??[];h.includes(u.key)||h.push(u.key),this.questionKeys.set(l.itemId,h)}(this.nativeRequests.size||this.options.hasPendingControl?.())&&await this.options.store.pauseOpenQuestions(this.owner)});return this.factTail=e.catch(()=>{}),this.track(e)}recover(){if(this.recovery)return this.recovery;if(!this.accepting)return Promise.resolve();let e=this.track((async()=>{this.assertTarget(),await this.prepareRehomes();let t=await this.options.store.snapshot(this.owner);for(let i of t.rejections)(!i.noticeResolved||!i.cloudDelivered)&&this.settleRejection(i);for(let i of t.controls)if(!i.cloudResolved){if(i.state==="RESOLVED"||t.scopes.some(s=>Q(s.scope,i.scope)&&s.state==="CLOSED"))this.startResolution(i.key);else if(Q(i.scope,this.owner.scope)&&i.nativeInstanceId===this.instanceId){if(i.state==="UNCERTAIN")this.startPublication(i,this.uncertainPresentation());else if(i.kind==="async")this.startPublication(i,De(ye(i)));else if(this.pendingApprovalKeys([i]).length){let s=this.approvalPresentation(i);s&&this.startPublication(i,s)}}}await this.publishFirstQuestion(),await this.settleCustodies();for(let i of t.entries)if(Q(i.scope,this.owner.scope)){if(i.nativeReceiptSha256&&i.cloudAck!=="EXECUTED")this.startAcknowledgement(i);else if(i.kind==="INPUT"&&i.phase==="PREPARED"&&this.isAccepting){if(!await this.options.store.canAttempt(this.owner,i.event.eventId))continue;let s={...i.event,...JSON.parse(i.event.payloadJson)};try{this.assertTarget(JSON.parse(i.bodyJson))}catch(n){if(!(n instanceof Qe))throw n;continue}try{await this.admit(s)}catch(n){if(!(n instanceof Qe))throw n;let r=(await this.options.store.snapshot(this.owner)).entries.find(o=>o.event.eventId===i.event.eventId);if(!r||r.kind!=="INPUT"||r.phase!=="PREPARED")throw n}}}})());return this.recovery=e,e.then(()=>{this.recovery=null},()=>{this.recovery=null}),e}activate(){if(this.stopped)throw new T("NATIVE_CONTROL_UNSUPPORTED");this.assertTarget(),this.admissionPaused=!1,this.accepting=!0}prepareAdmission(){if(this.stopped)throw new T("NATIVE_CONTROL_UNSUPPORTED");this.assertTarget(),this.accepting=!0,this.admissionPaused=!0}suspendAdmission(){this.stopped||(this.admissionPaused=!0)}stopAdmission(){this.accepting=!1,this.stopped=!0,this.dispatch.stopAdmission()}async join(){for(;this.pending.size;)await Promise.allSettled([...this.pending]);await this.dispatch.join()}async close(e="TERMINAL"){this.stopAdmission(),await this.join(),await this.dispatch.close(e);for(let t of await this.snapshotControls())Q(t.scope,this.owner.scope)&&!t.cloudResolved&&this.startResolution(t.key);await this.join(),await this.settleCustodies()}async handoff(e){this.stopAdmission(),await this.join(),await this.dispatch.handoff(e)}};var bi=require("node:timers/promises"),ct=class{constructor(e){this.options=e;this.phase="idle";this.operation=null;this.controller=null;this.followUp=!1}get isExhausted(){return this.phase==="exhausted"}request(){if(this.operation)return this.phase==="idle"&&(this.followUp=!0),this.operation;if(this.phase!=="idle")return Promise.resolve();this.phase="running";let e=new AbortController;this.controller=e;let t=()=>{try{return!e.signal.aborted&&this.options.current()}catch{return!1}},i=!1,s,n=new Promise(u=>{s=u}),r=()=>s();e.signal.addEventListener("abort",r,{once:!0});let o=setTimeout(()=>{i=!0,e.abort()},this.options.timeoutMs??6e4);o.unref();let d=(async()=>{for(let u of(this.options.delays??[1e3,5e3,15e3]).slice(0,3))try{if(await(this.options.wait?.(u,e.signal)??(0,bi.setTimeout)(u,void 0,{signal:e.signal,ref:!1})),!t())return;if(await this.options.recover(e.signal)&&this.options.isRecovered?.()!==!1){t()&&(this.phase="idle");return}}catch{if(!t())return}if(t()){this.phase="exhausted";try{await this.options.exhausted()}catch{}}})(),l=Promise.race([d,n]).then(async()=>{if(i&&this.phase==="running"){this.phase="exhausted";try{this.options.current()&&await this.options.exhausted()}catch{}}}).finally(()=>{clearTimeout(o),e.signal.removeEventListener("abort",r),this.phase==="running"&&(this.phase="exhausted"),this.controller===e&&(this.controller=null),this.operation===l&&(this.operation=null),this.followUp&&this.phase==="idle"&&(this.followUp=!1,this.request().catch(()=>{}))});return this.operation=l,l}readinessChanged(){this.phase==="exhausted"&&(this.phase="idle")}stop(){this.phase="stopped",this.followUp=!1,this.controller?.abort()}};var ut=class{constructor(){this.revision=0;this.ready=!1}get isReady(){return this.ready}capture(){return this.revision}invalidate(){this.revision++,this.ready=!1}commit(e,t,i){return e!==this.revision||(this.ready=!1,!t())||(i(),e!==this.revision||!t())?!1:(this.ready=!0,!0)}};var Is=require("@quantiya/codevibe-core"),v=require("@quantiya/codevibe-core");var Ri=D(require("os")),Ti=D(require("path")),_i=require("@quantiya/codevibe-core"),c=(0,_i.createLogger)({name:"codevibe-codex",logFile:Ti.default.join(Ri.default.tmpdir(),"codevibe-codex-mcp.log"),level:"debug"});var Ni=require("events"),O=D(require("fs")),te=D(require("path")),Ai=require("string_decoder"),pt=require("crypto"),Oi=require("chokidar"),ce=require("@quantiya/codevibe-core");var Ft=256*1024,js=64*1024*1024,Gs=16*1024*1024,$s=64*1024,Ci=100,Ws=250,zs=["CHOKIDAR_USEPOLLING","CHOKIDAR_INTERVAL"];function Js(a,e){let t=zs.map(s=>[s,process.env[s]]);for(let[s]of t)delete process.env[s];let i;try{i=(0,Oi.watch)(a,{...e,usePolling:!0})}finally{for(let[s,n]of t)n===void 0?delete process.env[s]:process.env[s]=n}if(i.options?.usePolling!==!0)throw i.close().catch(()=>{}),new Error("chokidar did not honour usePolling; refusing a native fs.watch");return i}function Ys(a=process.env){let e=a.CODEX_HOME?.trim();return e?te.resolve(e,"sessions"):(0,ce.getConfig)().codex.sessionsDir}var ht=class extends Ni.EventEmitter{constructor(t={}){super();this.watcher=null;this.catchUpReadTimer=null;this.filePositions=new Map;this.activeLogFile=null;this.sessionId=null;this.isWatching=!1;this.startTime=0;this.sessionsDir=null;this.activeReads=new Map;this.ownedReads=new Set;this.pendingReads=new Set;this.readGeneration=0;this.oversizedRecordFiles=new Set;this.fileIdentities=new Map;this.bindSource=null;this.authoritativeSessionId=null;this.pendingTranscriptBind=null;this.transcriptBindGeneration=0;this.transcriptBindingsClosed=!1;this.activeTranscriptAdmissions=new Set;this.startBaselines=new Map;this.toolReplayBoundaries=new Map;if(this.maxBacklogBytes=t.maxBacklogBytes??js,this.maxRecordBytes=t.maxRecordBytes??Gs,this.beforeEntry=t.beforeEntry,this.restoreCursor=t.restoreCursor,this.beforeGap=t.beforeGap,this.beforeEntry!==void 0&&typeof this.beforeEntry!="function")throw new TypeError("beforeEntry must be a function");if(this.restoreCursor!==void 0&&typeof this.restoreCursor!="function"||this.beforeGap!==void 0&&typeof this.beforeGap!="function"||this.restoreCursor&&(!this.beforeEntry||!this.beforeGap))throw new TypeError("durable source restore requires entry and gap admission callbacks");if(!Number.isSafeInteger(this.maxBacklogBytes)||this.maxBacklogBytes<=0)throw new RangeError("maxBacklogBytes must be a positive safe integer");if(!Number.isSafeInteger(this.maxRecordBytes)||this.maxRecordBytes<=0)throw new RangeError("maxRecordBytes must be a positive safe integer")}start(){if(this.isWatching){c.warn("Session log watcher already running");return}this.transcriptBindGeneration++,this.transcriptBindingsClosed=!1;let t=Ys();this.sessionsDir=t,c.info("Starting Codex session log watcher",{sessionsDir:t}),O.existsSync(t)||(c.info("Codex sessions directory does not exist yet, creating...",{sessionsDir:t}),O.mkdirSync(t,{recursive:!0})),this.startTime=Date.now(),this.readGeneration++,this.bindSource=null,this.authoritativeSessionId=null,this.snapshotStartBaselines(t),this.isWatching=!0,this.activeLogFile&&this.watchBoundRollout(this.activeLogFile),this.drainPendingTranscriptBind(),c.info("Session log watcher started; awaiting the SessionStart transcript bind")}stop(){this.transcriptBindingsClosed=!0,this.transcriptBindGeneration++,this.closeBoundRolloutWatch(),this.isWatching=!1,this.readGeneration++,this.filePositions.clear(),this.activeReads.clear(),this.pendingReads.clear(),this.oversizedRecordFiles.clear(),this.activeLogFile=null,this.sessionId=null,this.sessionsDir=null,this.bindSource=null,this.authoritativeSessionId=null,this.pendingTranscriptBind&&(this.pendingTranscriptBind.resolve({status:"rejected",reason:"watcher_stopped"}),this.pendingTranscriptBind=null),this.startBaselines.clear(),this.toolReplayBoundaries.clear(),this.fileIdentities.clear(),c.info("Session log watcher stopped")}async waitForTranscriptAdmissions(){for(;this.activeTranscriptAdmissions.size>0;)await Promise.all(Array.from(this.activeTranscriptAdmissions,t=>t.then(()=>{},()=>{})))}async waitForReads(){await Promise.all([...this.ownedReads])}retryActiveRead(){this.isWatching&&this.activeLogFile&&this.scheduleReadNewLines(this.activeLogFile)}getSessionId(){return this.sessionId}getActiveLogFile(){return this.activeLogFile}getToolReplayBoundary(t){if(t===this.activeLogFile)return this.toolReplayBoundaries.get(t)}refreshNativeOwnerBoundary(){if(!this.activeLogFile)return;let t=(0,ce.captureToolReplayBoundary)(this.activeLogFile);this.readGeneration++,this.activeReads.delete(this.activeLogFile),this.pendingReads.delete(this.activeLogFile),this.toolReplayBoundaries.set(this.activeLogFile,t)}getBindSource(){return this.bindSource}getAuthoritativeSessionId(){return this.authoritativeSessionId}tryRealpath(t){try{return O.realpathSync(t)}catch{return null}}isInteractiveRollout(t){return!(!t||t.originator==="codex_exec"||t.threadSource==="subagent"||t.sourceSubagent)}identityOf(t){return{dev:t.dev,ino:t.ino}}identitiesEqual(t,i){return t.dev===i.dev&&t.ino===i.ino}computeSeedOffset(t){let i;try{i=O.statSync(t)}catch{return 0}if(this.getSessionAgeMs(t,i)>=this.startTime)return 0;let n=this.startBaselines.get(t);return n&&this.identitiesEqual(n.identity,this.identityOf(i))?n.size:i.size}applyBind(t,i){if(this.readGeneration++,this.activeReads.delete(t),this.pendingReads.delete(t),this.activeLogFile=t,this.bindSource=i,i==="heuristic"&&(this.authoritativeSessionId=null),!this.filePositions.has(t)){let s=(0,ce.captureToolReplayBoundary)(t,this.computeSeedOffset(t));this.filePositions.set(t,s.byteOffset),this.toolReplayBoundaries.set(t,s)}this.toolReplayBoundaries.has(t)||this.toolReplayBoundaries.set(t,(0,ce.captureToolReplayBoundary)(t,this.filePositions.get(t)));try{this.fileIdentities.set(t,this.identityOf(O.statSync(t)))}catch{this.fileIdentities.delete(t)}this.watchBoundRollout(t),this.scheduleReadNewLines(t)}watchBoundRollout(t){if(this.closeBoundRolloutWatch(),!this.isWatching||this.transcriptBindingsClosed)return;let i;try{i=Js(t,{persistent:!0,ignoreInitial:!0,usePolling:!0,interval:Ci,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}})}catch(s){c.error("Could not follow bound rollout by polling",{filePath:t,error:s instanceof Error?s.message:String(s)}),this.emit("error",s);return}this.watcher=i,i.on("add",s=>this.onFileAdded(s)),i.on("change",s=>this.onFileChanged(s)),i.on("error",s=>{c.error("Watcher error:",s),this.emit("error",s)}),i.on("ready",()=>{this.watcher===i&&(this.catchUpReadTimer=setTimeout(()=>{this.catchUpReadTimer=null,this.watcher===i&&this.activeLogFile===t&&this.scheduleReadNewLines(t)},Ws),this.catchUpReadTimer.unref?.())}),c.info("Following bound rollout",{filePath:t,pollIntervalMs:Ci})}closeBoundRolloutWatch(){this.catchUpReadTimer&&(clearTimeout(this.catchUpReadTimer),this.catchUpReadTimer=null);let t=this.watcher;t&&(this.watcher=null,t.close().catch(i=>{c.warn("Bound rollout watcher close failed",{error:i instanceof Error?i.message:String(i)})}))}bindToFile(t){let i=this.tryRealpath(t);if(!i){c.warn("bindToFile: could not canonicalize path; skipping",{filePath:t});return}if(i===this.activeLogFile){this.bindSource="authoritative";return}c.info("bindToFile: authoritative bind to session rollout",{filePath:i}),this.applyBind(i,"authoritative")}async bindToSessionTranscript(t,i){if(typeof t!="string"||t.length===0)return{status:"rejected",reason:"missing_transcript_path"};if(this.transcriptBindingsClosed)return{status:"rejected",reason:"watcher_stopped"};if(!this.sessionsDir){let s=this.pendingTranscriptBind;if(s)return s.transcriptPath===t&&s.expectedSessionId===i?{status:"pending",completion:s.completion}:(c.warn("bindToSessionTranscript: conflicting startup bind rejected",{transcriptPath:t,expectedSessionId:i,pendingExpectedSessionId:s.expectedSessionId}),{status:"rejected",reason:"conflicting_startup_bind"});let n,r=new Promise(o=>{n=o});return this.pendingTranscriptBind={transcriptPath:t,expectedSessionId:i,completion:r,resolve:n},c.debug("bindToSessionTranscript: watcher not started yet; queued pending authoritative bind",{transcriptPath:t,expectedSessionId:i}),{status:"pending",completion:r}}return this.trackTranscriptAdmission(this.validateAndBindSessionTranscript(t,i,this.transcriptBindGeneration))}trackTranscriptAdmission(t){let i;return i=t.finally(()=>{this.activeTranscriptAdmissions.delete(i)}),this.activeTranscriptAdmissions.add(i),i}isTranscriptAdmissionCurrent(t,i){return!this.transcriptBindingsClosed&&this.transcriptBindGeneration===t&&this.sessionsDir===i}async validateAndBindSessionTranscript(t,i,s){let n=this.sessionsDir;if(!n||!this.isTranscriptAdmissionCurrent(s,n))return{status:"rejected",reason:"watcher_not_started"};let r=this.tryRealpath(t),o=this.tryRealpath(n);if(!r||!o)return{status:"rejected",reason:"canonicalization_failed"};let d=te.relative(o,r);if(d===".."||d.startsWith(".."+te.sep)||te.isAbsolute(d))return c.warn("bindToSessionTranscript: path not under sessionsDir; rejecting",{transcriptPath:r}),{status:"rejected",reason:"outside_sessions_directory"};let l=te.basename(r);if(!l.startsWith("rollout-")||!l.endsWith(".jsonl"))return{status:"rejected",reason:"invalid_rollout_filename"};let u=null;for(let h=0;h<3;h++){if(!this.isTranscriptAdmissionCurrent(s,n))return{status:"rejected",reason:"watcher_stopped"};if(u=this.readSessionMeta(r),u)break;if(await new Promise(p=>setTimeout(p,20)),!this.isTranscriptAdmissionCurrent(s,n))return{status:"rejected",reason:"watcher_stopped"}}return!u||u.id!==i?(c.debug("bindToSessionTranscript: meta missing or id mismatch; not binding",{transcriptPath:r,metaId:u?.id,expectedSessionId:i}),{status:"rejected",reason:"session_metadata_mismatch"}):this.isInteractiveRollout(u)?this.isTranscriptAdmissionCurrent(s,n)?(this.bindToFile(r),this.authoritativeSessionId=i,{status:"bound"}):{status:"rejected",reason:"watcher_stopped"}:(c.debug("bindToSessionTranscript: non-interactive rollout (codex_exec/subagent); not binding",{transcriptPath:r,originator:u.originator,threadSource:u.threadSource}),{status:"rejected",reason:"non_interactive_rollout"})}async drainPendingTranscriptBind(){let t=this.pendingTranscriptBind;if(!t)return;this.pendingTranscriptBind=null;let i;try{this.transcriptBindingsClosed?i={status:"rejected",reason:"watcher_stopped"}:i=await this.trackTranscriptAdmission(this.validateAndBindSessionTranscript(t.transcriptPath,t.expectedSessionId,this.transcriptBindGeneration))}catch(s){c.warn("bindToSessionTranscript: pending startup bind failed",{expectedSessionId:t.expectedSessionId,error:s instanceof Error?s.message:String(s)}),i={status:"rejected",reason:"startup_bind_failed"}}t.resolve(i)}onFileAdded(t){let i=this.tryRealpath(t);i&&(i===this.activeLogFile?this.scheduleReadNewLines(i):c.debug("Ignoring unowned rollout add; awaiting authoritative hook binding",{filePath:i}))}onFileChanged(t){let i=this.tryRealpath(t);i&&(this.activeLogFile&&i!==this.activeLogFile||this.activeLogFile&&this.scheduleReadNewLines(i))}readSessionMeta(t){let i=this.readFirstLogEntry(t);if(!i)return null;let s=i.payload||{};return{id:typeof s.id=="string"?s.id:void 0,timestamp:typeof i.timestamp=="string"?i.timestamp:void 0,originator:typeof s.originator=="string"?s.originator:void 0,cwd:typeof s.cwd=="string"?s.cwd:void 0,threadSource:typeof s.thread_source=="string"?s.thread_source:void 0,sourceSubagent:!!(s.source&&typeof s.source=="object"&&s.source.subagent)}}readFirstLogEntry(t){let i=null;try{i=O.openSync(t,"r");let s=new Ai.StringDecoder("utf8"),n=Buffer.alloc(64*1024),r="",o=0,d=-1;for(;o<Ft;){let u=O.readSync(i,n,0,n.length,o);if(u<=0||(o+=u,r+=s.write(n.subarray(0,u)),d=r.indexOf(`
17
+ `),d!==-1))break}r+=s.end();let l=d===-1?r:r.slice(0,d);return l.trim()?JSON.parse(l):null}catch{return null}finally{if(i!==null)try{O.closeSync(i)}catch{}}}snapshotStartBaselines(t){this.startBaselines.clear();try{for(let{filePath:i,size:s}of this.collectRecentSessionFiles(t,!0)){let n=this.tryRealpath(i);if(n)try{let r=O.statSync(n);this.startBaselines.set(n,{size:s,identity:this.identityOf(r)})}catch{}}}catch{}}getSessionAgeMs(t,i){let s=this.readSessionMeta(t);if(s?.timestamp){let n=Date.parse(s.timestamp);if(!Number.isNaN(n))return n}return i.birthtimeMs||i.ctimeMs}collectRecentSessionFiles(t,i=!1){let s=[],n=[t];for(;n.length>0;){let r=n.pop();if(!r)continue;let o;try{o=O.readdirSync(r,{withFileTypes:!0})}catch{continue}for(let d of o){let l=te.join(r,d.name);if(d.isDirectory()){n.push(l);continue}if(!(!d.isFile()||!d.name.startsWith("rollout-")||!d.name.endsWith(".jsonl")))try{let u=O.statSync(l),h=u.birthtimeMs||u.ctimeMs,p=u.mtimeMs;(i||h>=this.startTime||p>=this.startTime-5e3)&&s.push({filePath:l,createdAt:h,modifiedAt:p,size:u.size})}catch{}}}return s}scheduleReadNewLines(t){let i=this.activeReads.get(t);if(i)return this.pendingReads.add(t),i;let s=this.readGeneration,n=Promise.resolve().then(()=>this.drainReadQueue(t,s));return this.activeReads.set(t,n),this.ownedReads.add(n),n.finally(()=>{this.ownedReads.delete(n),this.activeReads.get(t)===n&&(this.activeReads.delete(t),this.pendingReads.delete(t))}),n}async drainReadQueue(t,i){do this.pendingReads.delete(t),await this.readNewLines(t,i);while(i===this.readGeneration&&this.pendingReads.has(t))}async readNewLines(t,i){if(i!==this.readGeneration)return;let s=this.filePositions.get(t)||0,n=null;try{n=O.openSync(t,O.constants.O_RDONLY|(O.constants.O_NOFOLLOW??0));let r=O.fstatSync(n),o=this.identityOf(r),d=this.fileIdentities.get(t);if(d&&!this.identitiesEqual(d,o)){let w=this.readFirstLogEntryFromFd(n),E=w?.type==="session_meta"?w.payload.id:void 0;if(this.authoritativeSessionId&&E!==this.authoritativeSessionId){let R=new Error("Authoritative Codex rollout path was replaced by a different session");c.error("Refusing replaced rollout with mismatched session identity",{filePath:t,expectedSessionId:this.authoritativeSessionId,replacementSessionId:E}),this.emit("error",R);return}c.info("Session log inode replaced; resetting byte and decoder state",{filePath:t,oldPosition:s,oldIdentity:d,newIdentity:o}),s=0,this.filePositions.set(t,0),this.oversizedRecordFiles.delete(t)}if(this.fileIdentities.set(t,o),this.restoreCursor&&this.sessionId===null){let w=this.readFirstLogEntryFromFd(n);w?.type==="session_meta"&&this.processLogEntry(w)}let l=Object.freeze({transcriptPath:t,nativeSessionId:this.authoritativeSessionId??this.sessionId,fileIdentity:Object.freeze({...o})}),u=!1;if(this.restoreCursor){let w=this.toolReplayBoundaries.get(t)?.byteOffset??s,E=w<=r.size?w:0,R=this.readSourceAnchor(n,E),b=await this.restoreCursor(l,{byteOffset:E,anchor:R,discardUntilNewline:E>0&&!this.isNewlineBoundary(n,E)});if(i!==this.readGeneration)return;b!==null&&(this.verifySourcePosition(n,r.size,b),s=b.byteOffset,u=!0,this.filePositions.set(t,s),b.discardUntilNewline?this.oversizedRecordFiles.add(t):this.oversizedRecordFiles.delete(t))}let h=async(w,E,R,b)=>(u&&await this.beforeGap({startOffset:w,endOffset:E,reason:R,discardUntilNewline:b,anchor:this.readSourceAnchor(n,E,w)},l),i===this.readGeneration);if(r.size<s&&(c.info("Session log truncated/rotated; resetting cursor to 0",{filePath:t,oldPosition:s,size:r.size}),s=0,this.filePositions.set(t,0),this.oversizedRecordFiles.delete(t)),r.size<=s)return;if(r.size-s>this.maxBacklogBytes){if(s===0&&this.sessionId===null){let E=this.readFirstLogEntryFromFd(n);E?.type==="session_meta"&&this.processLogEntry(E)}let w=this.findRecentRecordBoundary(n,r.size);if(!await h(s,w.position,"BACKLOG_LIMIT",w.discardUntilNewline)||(c.warn("Codex rollout backlog exceeded live-mirror limit; skipping archival prefix",{filePath:t,oldPosition:s,newPosition:w.position,size:r.size,maxBacklogBytes:this.maxBacklogBytes,discardUntilNewline:w.discardUntilNewline}),s=w.position,this.filePositions.set(t,s),w.discardUntilNewline?this.oversizedRecordFiles.add(t):this.oversizedRecordFiles.delete(t),r.size<=s))return}let p=r.size,m=Buffer.allocUnsafe(64*1024),f=s,g=s,y=[],S=0,I=this.oversizedRecordFiles.has(t);for(;f<p;){if(i!==this.readGeneration)return;let w=Math.min(m.length,p-f),E=O.readSync(n,m,0,w,f);if(E<=0)break;let R=0;for(;R<E;){if(i!==this.readGeneration)return;let b=m.subarray(0,E).indexOf(10,R),_=b!==-1,x=_?b:E,A=x-R,se=A+(_?1:0);if(I){if(f+=se,!await h(g,f,"PARTIAL_RECORD",!_))return;this.filePositions.set(t,f),g=f,_&&(I=!1,this.oversizedRecordFiles.delete(t)),R=_?b+1:E;continue}if(A>0&&(y.push(Buffer.from(m.subarray(R,x))),S+=A),f+=se,S>this.maxRecordBytes){if(c.warn("Discarding oversized Codex rollout JSONL record",{filePath:t,recordEnd:f,maxRecordBytes:this.maxRecordBytes}),!await h(g,f,"OVERSIZED_RECORD",!_))return;this.filePositions.set(t,f),g=f,y=[],S=0,I=!_,I?this.oversizedRecordFiles.add(t):this.oversizedRecordFiles.delete(t),R=_?b+1:E;continue}if(!_){R=E;continue}let q=Buffer.concat(y,S),z=q;y=[],S=0,q.length>0&&q[q.length-1]===13&&(q=q.subarray(0,q.length-1));let Oe=q.toString("utf8");if(Oe.trim()){let ve;try{let ne=JSON.parse(Oe);if(!ne||typeof ne!="object"||Array.isArray(ne)||typeof ne.type!="string")throw new Error("Invalid Codex log entry shape");ve=ne}catch(ne){if(c.warn("Failed to parse log line",{filePath:t,line:Oe.substring(0,100),error:ne}),!await h(g,f,"MALFORMED_RECORD",!1))return}if(ve!==void 0){let ne=!1;if(this.beforeEntry&&(ne=await this.beforeEntry(ve,Object.freeze({...l,startOffset:f-z.length-1,endOffset:f,sha256:(0,pt.createHash)("sha256").update(z).update(`
18
+ `).digest("hex"),anchor:Object.freeze(this.framedSourceAnchor(z,f))}))==="handled",i!==this.readGeneration))return;try{ne||this.processLogEntry(ve)}catch(re){c.warn("Failed to process log line",{filePath:t,error:re})}}}else if(!await h(g,f,"EMPTY_RECORD",!1))return;if(i===this.readGeneration&&(this.filePositions.set(t,f),g=f),i!==this.readGeneration)return;R=b+1}}}catch(r){c.error("Error reading log file",{filePath:t,error:r}),this.emit("error",r)}finally{if(n!==null)try{O.closeSync(n)}catch{}}}framedSourceAnchor(t,i){let s=t.subarray(Math.max(0,t.length-(ce.MAX_SYNC_SOURCE_ANCHOR_BYTES-1)));return{startOffset:i-s.length-1,endOffset:i,sha256:(0,pt.createHash)("sha256").update(s).update(`
19
+ `).digest("hex")}}readSourceAnchor(t,i,s=0){if(i===0)return null;let n=Math.max(s,i-ce.MAX_SYNC_SOURCE_ANCHOR_BYTES);if(n>=i)throw new Error("SYNC_SOURCE_POSITION_INVALID");let r=Buffer.allocUnsafe(i-n),o=0;for(;o<r.length;){let d=O.readSync(t,r,o,r.length-o,n+o);if(d<=0)throw new Error("SYNC_SOURCE_ANCHOR_UNAVAILABLE");o+=d}return{startOffset:n,endOffset:i,sha256:(0,pt.createHash)("sha256").update(r).digest("hex")}}isNewlineBoundary(t,i){if(i===0)return!0;let s=Buffer.allocUnsafe(1);return O.readSync(t,s,0,1,i-1)===1&&s[0]===10}verifySourcePosition(t,i,s){let{byteOffset:n,anchor:r,discardUntilNewline:o}=s;if(!Number.isSafeInteger(n)||n<0||n>i||typeof o!="boolean")throw new Error("SYNC_SOURCE_POSITION_INVALID");if(n===0){if(r!==null||o)throw new Error("SYNC_SOURCE_POSITION_INVALID");return}if(!r||!Number.isSafeInteger(r.startOffset)||r.startOffset<0||r.endOffset!==n||r.startOffset>=n||n-r.startOffset>ce.MAX_SYNC_SOURCE_ANCHOR_BYTES||!/^[a-f0-9]{64}$/.test(r.sha256)||o===this.isNewlineBoundary(t,n))throw new Error("SYNC_SOURCE_POSITION_INVALID");if(this.readSourceAnchor(t,n,r.startOffset).sha256!==r.sha256)throw new Error("SYNC_SOURCE_ANCHOR_CHANGED")}findRecentRecordBoundary(t,i){let s=Math.max(0,i-this.maxBacklogBytes),n=s+Math.min(i-s,this.maxRecordBytes);{if(s===0)return{position:0,discardUntilNewline:!1};let r=Buffer.allocUnsafe(1);if(O.readSync(t,r,0,1,s-1)===1&&r[0]===10)return{position:s,discardUntilNewline:!1};let o=Buffer.allocUnsafe($s),d=s;for(;d<n;){let l=Math.min(o.length,n-d),u=O.readSync(t,o,0,l,d);if(u<=0)break;let h=o.subarray(0,u).indexOf(10);if(h!==-1)return{position:d+h+1,discardUntilNewline:!1};d+=u}if(d===n&&d<i&&n-s===this.maxRecordBytes){let l=Buffer.allocUnsafe(1);if(O.readSync(t,l,0,1,d)===1&&l[0]===10)return{position:d+1,discardUntilNewline:!1}}return{position:s,discardUntilNewline:!0}}}readFirstLogEntryFromFd(t){try{let i=[],s=0,n=Buffer.allocUnsafe(64*1024);for(;s<Ft;){let o=Math.min(n.length,Ft-s),d=O.readSync(t,n,0,o,s);if(d<=0)break;let l=n.subarray(0,d).indexOf(10);if(l!==-1){i.push(Buffer.from(n.subarray(0,l)));break}i.push(Buffer.from(n.subarray(0,d))),s+=d}if(i.length===0)return null;let r=Buffer.concat(i).toString("utf8");return r.trim()?JSON.parse(r):null}catch{return null}}processLogEntry(t){if(c.debug("Processing log entry",{type:t.type}),t.type==="session_meta"){let i=t.payload;this.sessionId=i.id,c.info("Codex session started",{sessionId:i.id,cwd:i.cwd,cliVersion:i.cli_version}),this.emit("session-started",i);return}this.emit("log-entry",t),t.type==="event_msg"&&t.payload?.type?this.emit(`event:${t.payload.type}`,t):t.type==="response_item"&&t.payload?.type&&this.emit(`response:${t.payload.type}`,t)}};var Lt=require("uuid"),vt=require("crypto"),j=require("@quantiya/codevibe-core");function Me(a){if(typeof a!="string"||a.length>262144)return null;let e=/^\s*<send_user_message_question_reply>\s*([\s\S]*?)\s*<\/send_user_message_question_reply>\s*$/.exec(a);if(!e)return null;try{let t=JSON.parse(e[1]);if(!Array.isArray(t)||t.length===0||t.length>100)return null;let i=new Set,s=[];for(let n of t){if(!n||typeof n!="object"||Array.isArray(n)||typeof n.answer!="string"||!n.answer.trim()||typeof n.question!="string"||!n.question.trim()||typeof n.questionItemId!="string")return null;let r=JSON.parse(n.questionItemId);if(!Array.isArray(r)||r.length!==3||r[0]!=="request_user_input_async"||typeof r[1]!="string"||!r[1].trim()||r[1].length>512||!Number.isInteger(r[2])||r[2]<0||r[2]>=100)return null;let o=JSON.stringify(r);if(i.has(o))return null;i.add(o),s.push({callId:r[1],index:r[2],question:n.question,answer:n.answer})}return s}catch{return null}}function He(a){if(a.type==="event_msg"&&a.payload?.type==="user_message")return a.payload.message;if(a.type==="response_item"&&a.payload?.type==="message"&&a.payload.role==="user"&&Array.isArray(a.payload.content)&&a.payload.content.every(e=>e?.type==="input_text"&&typeof e.text=="string"))return a.payload.content.map(e=>e.text).join(`
20
+ `)}function xi(a){return Me(a)?.map(e=>e.answer).join(`
25
21
 
26
- `),metadata:{images:d.payload.images||[]}})}let s=Le(d),n=d.payload?.internal_chat_message_metadata_passthrough?.content_item_kinds,r=d.type==="response_item"&&Array.isArray(n)&&n.length>0&&Array.isArray(d.payload?.content)&&n.length===d.payload.content.length&&n.every(o=>o==="user.text");if(typeof s=="string"&&(r||d.type==="event_msg"&&d.payload?.type==="user_message")){let o=d.type==="response_item"?"response_item":"agent_message",a=typeof d.timestamp=="string"&&Number.isFinite(Date.parse(d.timestamp)),l=JSON.stringify([d.timestamp,s]);return a&&at(o,"user_prompt",l)?null:(pe(!0),a&&qe(o,"user_prompt",l),{...t,type:U.EventType.USER_PROMPT,content:s,metadata:{images:d.payload.images||[]}})}if(d.type==="event_msg"&&d.payload){let o=d.payload.type;switch(o){case"user_message":return pe(!0),{...t,type:U.EventType.USER_PROMPT,content:d.payload.message||"",metadata:{images:d.payload.images||[]}};case"agent_message":{let a=d.payload.message||"",l=d.payload.phase;return at("agent_message",l,a)?null:(qe("agent_message",l,a),{...t,type:U.EventType.ASSISTANT_RESPONSE,content:a,metadata:{phase:l}})}case"agent_reasoning":return{...t,type:U.EventType.REASONING,content:d.payload.text||""};case"task_started":return pe(!0),c.debug("Skipping task_started entry (turn boundary)"),null;case"task_complete":{let a=d.payload.error,l=typeof a?.message=="string"?a.message.trim():"";if(l){d.payload.last_agent_message&&c.warn("task_complete carried BOTH an error and a final message; relaying the error",{turnId:d.payload.turn_id});let u=typeof a?.codex_error_info=="string"?a.codex_error_info.trim():"",m=u!==""&&new RegExp(`(^|[^A-Za-z0-9_])${u.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}($|[^A-Za-z0-9_])`).test(l);return pe(!0),{...t,type:U.EventType.NOTIFICATION,content:u&&!m?`${l} (${u})`:l,metadata:{phase:"turn_error",turnId:d.payload.turn_id,...u?{codexErrorInfo:u}:{}}}}a!=null&&c.warn("task_complete carried an error with no extractable message; falling through to the message path",{turnId:d.payload.turn_id,errorShape:typeof a});let p=Ke(d.payload.last_agent_message),f=null;return p&&!Bs(p)?(qe("task_complete","final_answer",p),f={...t,type:U.EventType.ASSISTANT_RESPONSE,content:p,metadata:{phase:"final_answer"}}):c.debug("Skipping task_complete (final already emitted or empty)"),pe(!0),f}case"turn_aborted":{let a=typeof d.payload.reason=="string"?d.payload.reason.trim():"";return pe(!0),{...t,type:U.EventType.NOTIFICATION,content:a?`Turn aborted (${a})`:"Turn aborted",metadata:{phase:"turn_aborted",turnId:d.payload.turn_id,...a?{reason:a}:{}}}}case"token_count":return c.debug("Skipping token_count entry"),null;default:return c.debug("Unknown event_msg type",{type:o}),null}}if(d.type==="response_item"&&d.payload){let o=d.payload.type;if(o==="message"){if(d.payload.role!=="assistant")return c.debug("Skipping non-assistant response_item/message",{role:d.payload.role}),null;let a=Ks(d.payload),l=d.payload.phase;return!Ke(a)||at("response_item",l,a)?null:(qe("response_item",l,a),{...t,type:U.EventType.ASSISTANT_RESPONSE,content:a,metadata:{phase:l}})}if(o==="reasoning"){let a=Us(d.payload);return a?{...t,type:U.EventType.REASONING,content:a}:(c.debug("Skipping reasoning response_item (no readable summary)"),null)}if(o==="function_call"){let{name:a,arguments:l,call_id:p}=d.payload,f={};try{f=JSON.parse(l||"{}")}catch{f={raw:l}}let u=(0,Ot.v4)();le.set(p,{name:a,input:l,eventId:u});let m=Be(a),h=Hs(a,f);return{...t,type:U.EventType.TOOL_USE,content:h,metadata:{toolName:m,toolInput:f,callId:p,status:"running"}}}if(o==="function_call_output"){let{call_id:a,output:l}=d.payload,p=le.get(a);le.delete(a);let f=p?.name?Be(p.name):"Tool",u=xt(dt(l),500);return{...t,type:U.EventType.TOOL_USE,content:`${f} completed:
27
- ${u}`,metadata:{toolName:f,toolOutput:l,callId:a,status:"completed"}}}if(o==="custom_tool_call"){let{name:a,call_id:l,input:p,status:f}=d.payload;le.set(l,{name:a,input:p,eventId:(0,Ot.v4)()});let u=Pi(a,p);if(u){let I=$s(u),{oldString:y,newString:w}=js(u),v=I?`Editing: ${I.filePath}`:"Applying patch";return{...t,type:U.EventType.TOOL_USE,content:v,metadata:{tool_name:"Edit",tool_input:{file_path:I?.filePath||"",old_string:y,new_string:w},callId:l,status:f||"running"}}}let m=Vs(p),h=Be(a==="exec"?"shell":a||"tool");return{...t,type:U.EventType.TOOL_USE,content:m?`Running: ${m}`:`Running ${h}`,metadata:{toolName:h,toolInput:m?{command:m}:{raw:typeof p=="string"?p:""},callId:l,status:f||"running"}}}if(o==="custom_tool_call_output"){let{call_id:a,output:l}=d.payload,p=le.get(a);if(le.delete(a),Pi(p?.name,p?.input)){let m={};if(typeof l=="string")try{m=JSON.parse(l||"{}")}catch{m={raw:l}}else if(Array.isArray(l)){let S=dt(l);try{m=JSON.parse(S)}catch{m={raw:l,text:S}}}else m=l??{};let h=m!==null&&typeof m=="object"&&!Array.isArray(m)?m:null,I=typeof h?.output=="string"?h.output:void 0,y=h?.error,w=I!==void 0&&I.includes("Success"),v=typeof y=="string"?y:y!==void 0?JSON.stringify(y):"Unknown error";return{...t,type:U.EventType.TOOL_USE,content:w?"File edit applied successfully":`Edit failed: ${v}`,metadata:{toolName:"Edit",toolOutput:m,callId:a,status:"completed",success:w}}}let f=p?.name?Be(p.name==="exec"?"shell":p.name):"Tool",u=dt(l);return{...t,type:U.EventType.TOOL_USE,content:`${f} completed:
28
- ${xt(u,500)}`,metadata:{toolName:f,toolOutput:l,callId:a,status:"completed"}}}return c.debug("Unknown response_item type",{type:o}),null}return d.type==="turn_context"?(c.debug("Skipping turn_context entry"),null):(c.debug("Unhandled log entry type",{type:d.type}),null)}function Be(d){return{shell_command:"Bash",shell:"Bash",apply_patch:"Edit",write_file:"Write",read_file:"Read",list_files:"Glob",search_files:"Grep",web_search:"WebSearch",web_fetch:"WebFetch"}[d]||d}function Hs(d,e){switch(d){case"shell_command":case"shell":return`Running: ${e.command||"command"}`;case"read_file":return`Reading: ${e.file_path||e.path||"file"}`;case"write_file":return`Writing: ${e.file_path||e.path||"file"}`;case"list_files":return`Listing: ${e.path||"."}`;case"search_files":return`Searching for: ${e.pattern||e.query||"pattern"}`;case"web_search":return`Searching web: ${e.query||"query"}`;default:return`Running ${Be(d)}`}}function js(d){let e=[],t=[],i=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;for(let s of d.split(`
22
+ `)??a}var ue=new Map,J=[],Di=24;function $e(a){return typeof a=="string"?a.trim():""}function Mi(a){return typeof a=="string"?a:""}function mt(a,e,t){let i=$e(t);if(!i)return!1;let s=Mi(e),n=(0,vt.createHash)("sha256").update(i).digest("hex");return J.some(r=>r.textHash===n&&r.phase===s&&r.carrier!==a)}function Xs(a){let e=$e(a),t=(0,vt.createHash)("sha256").update(e).digest("hex");return e.length>0&&J.some(i=>i.textHash===t&&i.phase==="final_answer")}function je(a,e,t){let i=$e(t);if(i)for(J.push({carrier:a,phase:Mi(e),textHash:(0,vt.createHash)("sha256").update(i).digest("hex")});J.length>Di;)J.shift()}function fe(a=!1){let e=a?J.filter(t=>t.phase==="question_reply"||t.phase==="user_prompt"):[];J.splice(0,J.length,...e)}function Fi(a,e,t){let i=[];if(t!==null){if(typeof t!="string"||Buffer.byteLength(t)>16*1024)throw new Error("INVALID_CODEX_SOURCE_PROJECTION");try{i=JSON.parse(t)}catch{throw new Error("INVALID_CODEX_SOURCE_PROJECTION")}if(!Array.isArray(i)||i.length>Di||i.some(r=>!r||Object.keys(r).sort().join(",")!=="carrier,phase,textHash"||!["agent_message","response_item","task_complete"].includes(r.carrier)||typeof r.phase!="string"||typeof r.textHash!="string"||!/^[a-f0-9]{64}$/.test(r.textHash)))throw new Error("INVALID_CODEX_SOURCE_PROJECTION")}let s=J.slice(),n=new Map(ue);J.splice(0,J.length,...i);try{let r=Bt(a,e),o=JSON.stringify(J);if(Buffer.byteLength(o)>16*1024)throw new Error("INVALID_CODEX_SOURCE_PROJECTION");return{event:r,projection:o}}finally{J.splice(0,J.length,...s),ue.clear();for(let[r,o]of n)ue.set(r,o)}}function Zs(a){let e=a?.content;return Array.isArray(e)?e.filter(t=>t&&(t.type==="output_text"||t.type==="text")).map(t=>typeof t?.text=="string"?t.text:"").join(""):""}function en(a){let e=a?.summary;return!Array.isArray(e)||e.length===0?"":e.map(t=>typeof t=="string"?t:typeof t?.text=="string"?t.text:"").join(`
23
+ `).trim()}function tn(a){if(typeof a!="string")return"";let e=a.match(/"cmd"\s*:\s*"((?:\\.|[^"\\])*)"/);if(e)try{return JSON.parse(`"${e[1]}"`)}catch{return e[1]}return""}function Fe(a){if(typeof a!="string"||!a.startsWith(`*** Begin Patch
24
+ `)||!a.endsWith(`
25
+ *** End Patch`))return"";let e=a.split(`
26
+ `);return e[0]!=="*** Begin Patch"||e[e.length-1]!=="*** End Patch"||e.filter(t=>t==="*** Begin Patch").length!==1||e.filter(t=>t==="*** End Patch").length!==1||!/^\*\*\* (?:Add|Update|Delete) File: [^\r\n]+$/.test(e[1]??"")?"":a}function We(a){if(typeof a!="string")return"";let e="[A-Za-z_$][\\w$]*",t='"(?:\\\\.|[^"\\\\])*"',i=a.match(new RegExp(`^\\s*(?:const|let|var)\\s+(${e})\\s*=\\s*await\\s+tools\\.apply_patch\\(\\s*(${t})\\s*\\)\\s*;\\s*(?:text\\(\\s*(${e})\\s*\\)\\s*;\\s*)?$`,"s")),s=a.match(new RegExp(`^\\s*(?:const|let|var)\\s+(${e})\\s*=\\s*(${t})\\s*;\\s*(?:const|let|var)\\s+(${e})\\s*=\\s*await\\s+tools\\.apply_patch\\(\\s*(${e})\\s*\\)\\s*;\\s*(?:text\\(\\s*(${e})\\s*\\)\\s*;\\s*)?$`,"s")),n;if(i&&(!i[3]||i[3]===i[1])?n=i[2]:s&&s[4]===s[1]&&(!s[5]||s[5]===s[3])&&(n=s[2]),!n)return"";try{return Fe(JSON.parse(n))}catch{return""}}var sn=new Set(["exec","shell","shell_command","bash","run_command","run_cmd"]);function ki(a,e){return typeof e!="string"?"":a==="apply_patch"?e:a==="exec"?We(e):typeof a=="string"&&sn.has(a)?"":e.includes("*** Begin Patch")?e:""}function Bt(a,e){let t={sessionId:e,source:j.EventSource.DESKTOP};if(a.type==="event_msg"&&a.payload?.type==="item_completed"&&a.payload.item?.type==="UserMessage")return fe(!0),null;let i=Me(He(a));if(i){let o=a.type==="response_item"?"response_item":"agent_message",d=JSON.stringify(i);return mt(o,"question_reply",d)?null:(fe(!0),je(o,"question_reply",d),{...t,type:j.EventType.USER_PROMPT,content:i.map(l=>l.answer).join(`
27
+
28
+ `),metadata:{images:a.payload.images||[]}})}let s=He(a),n=a.payload?.internal_chat_message_metadata_passthrough?.content_item_kinds,r=a.type==="response_item"&&Array.isArray(n)&&n.length>0&&Array.isArray(a.payload?.content)&&n.length===a.payload.content.length&&n.every(o=>o==="user.text");if(typeof s=="string"&&(r||a.type==="event_msg"&&a.payload?.type==="user_message")){let o=a.type==="response_item"?"response_item":"agent_message",d=typeof a.timestamp=="string"&&Number.isFinite(Date.parse(a.timestamp)),l=JSON.stringify([a.timestamp,s]);return d&&mt(o,"user_prompt",l)?null:(fe(!0),d&&je(o,"user_prompt",l),{...t,type:j.EventType.USER_PROMPT,content:s,metadata:{images:a.payload.images||[]}})}if(a.type==="event_msg"&&a.payload){let o=a.payload.type;switch(o){case"user_message":return fe(!0),{...t,type:j.EventType.USER_PROMPT,content:a.payload.message||"",metadata:{images:a.payload.images||[]}};case"agent_message":{let d=a.payload.message||"",l=a.payload.phase;return mt("agent_message",l,d)?null:(je("agent_message",l,d),{...t,type:j.EventType.ASSISTANT_RESPONSE,content:d,metadata:{phase:l}})}case"agent_reasoning":return{...t,type:j.EventType.REASONING,content:a.payload.text||""};case"task_started":return fe(!0),c.debug("Skipping task_started entry (turn boundary)"),null;case"task_complete":{let d=a.payload.error,l=typeof d?.message=="string"?d.message.trim():"";if(l){a.payload.last_agent_message&&c.warn("task_complete carried BOTH an error and a final message; relaying the error",{turnId:a.payload.turn_id});let p=typeof d?.codex_error_info=="string"?d.codex_error_info.trim():"",m=p!==""&&new RegExp(`(^|[^A-Za-z0-9_])${p.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}($|[^A-Za-z0-9_])`).test(l);return fe(!0),{...t,type:j.EventType.NOTIFICATION,content:p&&!m?`${l} (${p})`:l,metadata:{phase:"turn_error",turnId:a.payload.turn_id,...p?{codexErrorInfo:p}:{}}}}d!=null&&c.warn("task_complete carried an error with no extractable message; falling through to the message path",{turnId:a.payload.turn_id,errorShape:typeof d});let u=$e(a.payload.last_agent_message),h=null;return u&&!Xs(u)?(je("task_complete","final_answer",u),h={...t,type:j.EventType.ASSISTANT_RESPONSE,content:u,metadata:{phase:"final_answer"}}):c.debug("Skipping task_complete (final already emitted or empty)"),fe(!0),h}case"turn_aborted":{let d=typeof a.payload.reason=="string"?a.payload.reason.trim():"";return fe(!0),{...t,type:j.EventType.NOTIFICATION,content:d?`Turn aborted (${d})`:"Turn aborted",metadata:{phase:"turn_aborted",turnId:a.payload.turn_id,...d?{reason:d}:{}}}}case"token_count":return c.debug("Skipping token_count entry"),null;default:return c.debug("Unknown event_msg type",{type:o}),null}}if(a.type==="response_item"&&a.payload){let o=a.payload.type;if(o==="message"){if(a.payload.role!=="assistant")return c.debug("Skipping non-assistant response_item/message",{role:a.payload.role}),null;let d=Zs(a.payload),l=a.payload.phase;return!$e(d)||mt("response_item",l,d)?null:(je("response_item",l,d),{...t,type:j.EventType.ASSISTANT_RESPONSE,content:d,metadata:{phase:l}})}if(o==="reasoning"){let d=en(a.payload);return d?{...t,type:j.EventType.REASONING,content:d}:(c.debug("Skipping reasoning response_item (no readable summary)"),null)}if(o==="function_call"){let{name:d,arguments:l,call_id:u}=a.payload,h={};try{h=JSON.parse(l||"{}")}catch{h={raw:l}}let p=(0,Lt.v4)();ue.set(u,{name:d,input:l,eventId:p});let m=Ge(d),f=nn(d,h);return{...t,type:j.EventType.TOOL_USE,content:f,metadata:{toolName:m,toolInput:h,callId:u,status:"running"}}}if(o==="function_call_output"){let{call_id:d,output:l}=a.payload,u=ue.get(d);ue.delete(d);let h=u?.name?Ge(u.name):"Tool",p=qt(ft(l),500);return{...t,type:j.EventType.TOOL_USE,content:`${h} completed:
29
+ ${p}`,metadata:{toolName:h,toolOutput:l,callId:d,status:"completed"}}}if(o==="custom_tool_call"){let{name:d,call_id:l,input:u,status:h}=a.payload;ue.set(l,{name:d,input:u,eventId:(0,Lt.v4)()});let p=ki(d,u);if(p){let g=on(p),{oldString:y,newString:S}=rn(p),I=g?`Editing: ${g.filePath}`:"Applying patch";return{...t,type:j.EventType.TOOL_USE,content:I,metadata:{tool_name:"Edit",tool_input:{file_path:g?.filePath||"",old_string:y,new_string:S},callId:l,status:h||"running"}}}let m=tn(u),f=Ge(d==="exec"?"shell":d||"tool");return{...t,type:j.EventType.TOOL_USE,content:m?`Running: ${m}`:`Running ${f}`,metadata:{toolName:f,toolInput:m?{command:m}:{raw:typeof u=="string"?u:""},callId:l,status:h||"running"}}}if(o==="custom_tool_call_output"){let{call_id:d,output:l}=a.payload,u=ue.get(d);if(ue.delete(d),ki(u?.name,u?.input)){let m={};if(typeof l=="string")try{m=JSON.parse(l||"{}")}catch{m={raw:l}}else if(Array.isArray(l)){let w=ft(l);try{m=JSON.parse(w)}catch{m={raw:l,text:w}}}else m=l??{};let f=m!==null&&typeof m=="object"&&!Array.isArray(m)?m:null,g=typeof f?.output=="string"?f.output:void 0,y=f?.error,S=g!==void 0&&g.includes("Success"),I=typeof y=="string"?y:y!==void 0?JSON.stringify(y):"Unknown error";return{...t,type:j.EventType.TOOL_USE,content:S?"File edit applied successfully":`Edit failed: ${I}`,metadata:{toolName:"Edit",toolOutput:m,callId:d,status:"completed",success:S}}}let h=u?.name?Ge(u.name==="exec"?"shell":u.name):"Tool",p=ft(l);return{...t,type:j.EventType.TOOL_USE,content:`${h} completed:
30
+ ${qt(p,500)}`,metadata:{toolName:h,toolOutput:l,callId:d,status:"completed"}}}return c.debug("Unknown response_item type",{type:o}),null}return a.type==="turn_context"?(c.debug("Skipping turn_context entry"),null):(c.debug("Unhandled log entry type",{type:a.type}),null)}function Ge(a){return{shell_command:"Bash",shell:"Bash",apply_patch:"Edit",write_file:"Write",read_file:"Read",list_files:"Glob",search_files:"Grep",web_search:"WebSearch",web_fetch:"WebFetch"}[a]||a}function nn(a,e){switch(a){case"shell_command":case"shell":return`Running: ${e.command||"command"}`;case"read_file":return`Reading: ${e.file_path||e.path||"file"}`;case"write_file":return`Writing: ${e.file_path||e.path||"file"}`;case"list_files":return`Listing: ${e.path||"."}`;case"search_files":return`Searching for: ${e.pattern||e.query||"pattern"}`;case"web_search":return`Searching web: ${e.query||"query"}`;default:return`Running ${Ge(a)}`}}function rn(a){let e=[],t=[],i=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;for(let s of a.split(`
29
31
  `))if(!(i.test(s)||s.startsWith("***")||s.startsWith("---")||s.startsWith("+++"))){if(s.startsWith("-"))e.push(s.slice(1));else if(s.startsWith("+"))t.push(s.slice(1));else if(s.startsWith(" ")){let n=s.slice(1);e.push(n),t.push(n)}}return{oldString:e.join(`
30
32
  `),newString:t.join(`
31
- `)}}function $s(d){if(!d)return null;let e=d.match(/\*\*\* (?:Update|Add|Delete) File: (.+)/);return e?{filePath:e[1].trim()}:null}function dt(d){if(d==null)return"";if(typeof d=="string")return d;if(Array.isArray(d))return d.map(e=>typeof e?.text=="string"?e.text:e?.type==="input_image"||typeof e?.image_url=="string"?"[image]":JSON.stringify(e??null)).join(`
32
- `);if(typeof d=="object"&&typeof d.text=="string")return d.text;try{return JSON.stringify(d)??""}catch{return String(d)}}function xt(d,e){return typeof d!="string"?xt(dt(d),e):d?d.length<=e?d:d.substring(0,e)+"...":""}function Dt(){le.clear(),pe()}var K=require("@quantiya/codevibe-core"),_i=3e3,Gs=8,Ws=10,zs=100;function Ci(d){let e=Buffer.byteLength(d.carryover);return{status:"partial",progressKey:`${d.fileIdentity.dev}:${d.fileIdentity.ino}:${d.size}:${d.endOfComplete}:${e}`,size:d.size,carryoverBytes:e,endOfComplete:d.endOfComplete}}var Js="tool_activity",Oe=class{constructor(e){this.consolidator=null;this.ledger=null;this.sessionMap=null;this.ownership=null;this.cursor=null;this.backendSessionId=null;this.rolloutId=null;this.transcriptPath=null;this.backstopTimer=null;this.backstopInFlight=null;this.cursorReady=Promise.resolve();this.cursorRepaired=!1;this.deps=e}static mintBackendSessionId(){return K.ToolActivitySessionMap.mintCodexBackendSessionId()}async recordedBackendSessionId(e){return new K.ToolActivitySessionMap({agent:"codex",logger:this.deps.logger,lock:new K.InProcessRolloutLock,root:this.deps.root}).ownerBackendSessionId(e)}get sessionId(){return this.backendSessionId}get rollout(){return this.rolloutId}isActive(){return this.consolidator!==null}async start(e,t,i){this.backendSessionId=e,this.rolloutId=t;let s=(0,K.createRolloutLock)({agent:"codex",logger:this.deps.logger,socketDir:this.deps.socketDir,root:this.deps.root});this.sessionMap=new K.ToolActivitySessionMap({agent:"codex",logger:this.deps.logger,lock:s,root:this.deps.root}),this.ownership=await this.sessionMap.claimOwnership(t,e);let n=new K.ToolActivityOutbox({agent:"codex",logger:this.deps.logger,root:this.deps.root});this.ledger=new K.ToolActivityLedger({agent:"codex",sessionId:e,logger:this.deps.logger,root:this.deps.root}),await this.deps.recoverPending?.(e,n,this.ledger);let r=this.buildTransport(),o=this.deps.selectTransport?await this.deps.selectTransport(e,r):r;this.consolidator=new K.ToolActivityConsolidator({agent:"codex",sessionId:e,logger:this.deps.logger,outbox:n,ledger:this.ledger,transport:o}),await this.consolidator.init(),i&&(this.bindTranscript(i),await this.cursorReady),this.deps.logger.info("[tool-activity] codex consolidator started",{sessionId:e,rollout:t,hasTranscript:!!i})}bindTranscript(e){if(!this.consolidator||!e||this.transcriptPath===e)return;this.transcriptPath=e;let t=new K.ToolReplayCursor({agent:"codex",sessionId:this.backendSessionId,canonicalPath:e,logger:this.deps.logger,root:this.deps.root,readBytes:this.deps.replayReadBytes,maxFrameBytes:this.deps.replayMaxFrameBytes});this.cursor=t,this.cursorRepaired=!1,this.cursorReady=t.load(this.deps.initialBoundary?.(e)),this.cursorReady.catch(s=>this.deps.logger.warn("[tool-activity] codex cursor load failed; replay retained",{sessionId:this.backendSessionId,err:String(s)}));let i=this.deps.backstopIntervalMs??3e3;i>0&&!this.backstopTimer&&(this.backstopTimer=setInterval(()=>{this.runTranscriptBackstop().catch(s=>this.deps.logger.warn("[tool-activity] codex transcript backstop failed",{sessionId:this.backendSessionId,err:String(s)}))},i),this.backstopTimer.unref?.())}async observeCall(e,t){if(!this.consolidator||!this.sessionMap||!this.ownership||!e.callId||!e.toolName)return;let i=this.consolidator;await this.sessionMap.bindCall(this.ownership,e.callId);let s={id:e.callId,tool:e.toolName,normalizedTarget:en(e.toolName,e.toolInput),ts:e.ts??new Date().toISOString(),byteOffset:e.byteOffset??0,...e.toolInput!==void 0?{digest:(0,K.digestOf)(e.toolInput)}:{}},n=await i.observe(s,t);return n==="closed"?await i.captureTerminal(s,this.deps.shutdownDrainMs??_i)?"sealed-terminal":"closed":n}async runTranscriptBackstop(e=!1){await this.runTranscriptBackstopTurn(e)}runTranscriptBackstopTurn(e=!1){if(this.backstopInFlight)return this.backstopInFlight;let t=this.cursor,i=this.cursorReady,s=this.consolidator;if(!s||!t)return Promise.resolve("caught-up");let r=(async()=>{if(await i,this.cursor!==t)return"more";if(!this.cursorRepaired){if(await s.repairLostWindows(t),this.cursor!==t)return"more";this.cursorRepaired=!0}return this.doTranscriptBackstop(t,e)})().finally(()=>{this.backstopInFlight===r&&(this.backstopInFlight=null)});return this.backstopInFlight=r,r}async doTranscriptBackstop(e,t=!1){let i=this.consolidator;if(!i)return"caught-up";this.ledger&&await this.ledger.reloadLegacyOwned();for(let s=0;s<Gs;s+=1){if(this.cursor!==e)return"caught-up";let n=await e.readFrames();if(n.missing)return"caught-up";if(n.frames.length===0)return n.carryover.length>0?Ci(n):"caught-up";let r=Number.POSITIVE_INFINITY,o=t?{includeInFlight:!0}:void 0;for(let a of n.frames)for(let l of Ys(a.line,a.startOffset))await this.observeCall(l,o)==="deferred-in-flight"&&(r=Math.min(r,a.startOffset));if(await i.flush(),r<n.endOfComplete)return await e.checkpoint(r,{fileIdentity:n.fileIdentity,size:n.size,carryover:""}),"more";if(await e.checkpoint(n.endOfComplete,{fileIdentity:n.fileIdentity,size:n.size,carryover:n.carryover}),!n.hasMore)return n.carryover.length>0?Ci(n):"caught-up"}return"more"}async flush(){await this.consolidator?.flush()}async abortStart(){this.backstopTimer&&clearInterval(this.backstopTimer),this.backstopTimer=null;try{await this.backstopInFlight?.catch(()=>{}),await this.consolidator?.shutdown()}finally{await this.ownership?.release(),this.ownership=null,this.consolidator=null,this.ledger=null,this.sessionMap=null,this.cursor=null}}async stop(){this.backstopTimer&&(clearInterval(this.backstopTimer),this.backstopTimer=null),await this.runTranscriptBackstop().catch(()=>{});let e=Math.max(1,Math.trunc(this.deps.shutdownPartialNoProgressTurns??zs)),t=null,i=0;for(;;){let s=await this.runTranscriptBackstopTurn(!0);if(s==="caught-up")break;if(typeof s!="string"){if(s.progressKey===t?i+=1:(t=s.progressKey,i=1),i>=e){this.deps.logger.warn("[tool-activity] deferring unchanged incomplete rollout suffix during shutdown; the next owner will re-read it from the durable complete-line boundary",{size:s.size,carryoverBytes:s.carryoverBytes,endOfComplete:s.endOfComplete,unchangedTurns:i});break}await new Promise(n=>setTimeout(n,Ws))}else t=null,i=0,await new Promise(n=>setImmediate(n))}await this.consolidator?.drainSends(this.deps.shutdownDrainMs??_i).catch(()=>{});try{await this.consolidator?.shutdown()}finally{await this.ownership?.release().catch(()=>{}),this.ownership=null,this.consolidator=null,this.ledger=null,this.sessionMap=null,this.cursor=null}}buildTransport(){let e=async(t,i,s)=>{let n=s?s.sessionKey:this.deps.getSessionKey();if(!n)throw new Error("[tool-activity] no session key at send (retryable)");let r=s?s.sessionKeyGen:this.deps.getSessionKeyGen();await this.deps.createEvent({sessionId:t,type:K.EventType.TOOL_ACTIVITY,source:K.EventSource.DESKTOP,content:this.deps.encryptContent(Js,n),metadata:{encrypted:this.deps.encryptMetadata({manifest:i.manifest},n)},timestamp:i.windowStart,isEncrypted:!0,clientEventId:i.clientEventId,...r?{expectedSessionKeyGen:r}:{}})};return{send:async(t,i)=>{try{await e(t,i)}catch(s){if((0,K.isSessionKeyStaleError)(s)&&this.deps.refreshSessionKey){let n=await this.deps.refreshSessionKey(t);if(!n)throw s;await e(t,i,n);return}throw s}}}}};function Ys(d,e){let t;try{t=JSON.parse(d)}catch{return[]}if(t?.type!=="response_item"||!t.payload)return[];let i=t.payload,s=typeof t.timestamp=="string"?t.timestamp:new Date(0).toISOString();if(i.type==="function_call"&&typeof i.call_id=="string"&&typeof i.name=="string"){let n;try{n=JSON.parse(i.arguments||"{}")}catch{n={raw:i.arguments}}return[{callId:i.call_id,toolName:Xs(i.name),toolInput:n,ts:s,byteOffset:e}]}if(i.type==="custom_tool_call"&&typeof i.call_id=="string"){let n=Zs(typeof i.input=="string"?i.input:""),r=n?{file_path:n,patch:i.input}:{patch:i.input};return[{callId:i.call_id,toolName:"Edit",toolInput:r,ts:s,byteOffset:e}]}return[]}function Xs(d){return d==="shell"||d==="shell_command"||d==="local_shell"?"Bash":d==="apply_patch"?"Edit":d}function Zs(d){let e=d.match(/^\*\*\* (?:Update|Add|Delete) File: (.+)$/m);return e?e[1].trim():void 0}function en(d,e){if(!e||typeof e!="object")return;let t=e,i=n=>typeof n=="string"&&n.length>0?n:void 0,s=Array.isArray(t.command)?t.command.filter(n=>typeof n=="string").join(" ").trim().split(/\s+/)[0]:typeof t.command=="string"?t.command.trim().split(/\s+/)[0]:void 0;return i(t.file_path)??i(t.path)??i(t.pattern)??i(t.url)??(s&&s.length>0?s:void 0)}var Ni=require("events"),Ai=require("@quantiya/codevibe-core");var ct=class d extends Ni.EventEmitter{constructor(){super();this.pendingCalls=new Map;this.timers=new Map;this.timeoutMs=(0,Ai.getConfig)().codex.approvalTimeoutMs,c.info("Approval detector initialized",{timeoutMs:this.timeoutMs})}onToolCallStart(t,i,s){c.debug("Tool call started",{callId:t,name:i});let n=this.parseInput(s),r=this.extractFilePath(i,s,n),o=this.extractDiff(i,s,n),a={callId:t,name:i,input:s,filePath:r,diff:o,parsedInput:n,timestamp:Date.now(),notificationSent:!1};if(this.pendingCalls.set(t,a),!this.shouldScheduleApprovalTimeout(i,n)){c.debug("Skipping approval timeout for non-escalated tool call",{callId:t,name:i});return}let l=setTimeout(()=>{this.checkPendingCall(t)},this.timeoutMs);this.timers.set(t,l)}onToolCallComplete(t){c.debug("Tool call completed",{callId:t}),this.pendingCalls.delete(t);let i=this.timers.get(t);i&&(clearTimeout(i),this.timers.delete(t))}checkPendingCall(t){let i=this.pendingCalls.get(t);if(!i||i.notificationSent)return;let s=Date.now()-i.timestamp;c.info("Tool call still pending after timeout",{callId:t,name:i.name,elapsedMs:s}),i.notificationSent=!0,this.pendingCalls.set(t,i),this.emit("approval-pending",{callId:t,toolName:i.name,hint:this.extractHint(i.name,i.input,i.filePath),filePath:i.filePath,diff:i.diff,toolInput:i.parsedInput,rawInput:i.input,elapsedMs:s})}extractHint(t,i,s){if(s)return`File: ${s}`;if(t==="apply_patch"&&i){let n=i.match(/\*\*\* (?:Update|Add|Delete) File: (.+)/);if(n)return`File: ${n[1].trim()}`}if(d.SHELL_TOOL_NAMES.has(t))try{let n=JSON.parse(i),r=typeof n.command=="string"?n.command:typeof n.cmd=="string"?n.cmd:void 0;if(r)return`Command: ${r.substring(0,50)}${r.length>50?"...":""}`}catch{}return`Tool: ${this.mapToolName(t)}`}mapToolName(t){return{exec_command:"Bash",shell_command:"Bash",shell:"Bash",exec:"Bash",local_shell:"Bash",apply_patch:"File Edit",write_file:"Write File",read_file:"Read File"}[t]||t}parseInput(t){if(t)try{return JSON.parse(t)}catch{return}}static{this.SHELL_TOOL_NAMES=new Set(["exec_command","shell_command","shell","exec","local_shell"])}shouldScheduleApprovalTimeout(t,i){return d.SHELL_TOOL_NAMES.has(t)?i?.sandbox_permissions==="require_escalated":!1}extractFilePath(t,i,s){if(t==="apply_patch"&&i){let r=i.match(/\*\*\* (?:Update|Add|Delete) File: (.+)/);if(r)return r[1].trim()}let n=s?.file_path||s?.path||s?.filePath;if(n&&typeof n=="string")return n}extractDiff(t,i,s){if(t==="apply_patch"&&i)return i;if(s?.diff&&typeof s.diff=="string")return s.diff}getPendingCalls(){return Array.from(this.pendingCalls.values())}hasPendingCalls(){return this.pendingCalls.size>0}clear(){for(let t of this.timers.values())clearTimeout(t);this.timers.clear(),this.pendingCalls.clear(),c.debug("Approval detector cleared")}shutdown(){this.clear(),this.removeAllListeners(),c.info("Approval detector shutdown")}};var Oi=require("child_process"),xi=require("util");var Ft=(0,xi.promisify)(Oi.exec),xe="__CODEVIBE_CODEX_KEY_ESCAPE__",pt=class{async sendLiteral(e,t){return this.sendTerminalOperation(e,async i=>{await this.sendLiteralViaTmux(i,t)})}async sendKey(e,t){return this.sendTerminalOperation(e,async i=>{await this.sendKeyViaTmux(i,t)})}async sendInput(e,t){c.info("Attempting to send input to Codex",{sessionId:e,input:t});try{let i=process.env.CODEVIBE_CODEX_TMUX_SESSION;return i?(c.info("Using tmux send-keys",{tmuxSession:i}),t===xe?await this.sendKeyViaTmux(i,"Escape"):await this.sendViaTmux(i,t),c.info("Successfully sent input to Codex",{sessionId:e,input:t}),!0):(c.error("No tmux session found - CodeVibe Companion launch is required",{sessionId:e,hint:"Start Codex CLI using `codevibe --agent codex`"}),!1)}catch(i){return c.error("Failed to send input to Codex",{sessionId:e,error:i instanceof Error?i.message:String(i)}),!1}}async sendTerminalOperation(e,t){let i=process.env.CODEVIBE_CODEX_TMUX_SESSION;if(!i)return c.error("No tmux session found - CodeVibe Companion launch is required",{sessionId:e,hint:"Start Codex CLI using `codevibe --agent codex`"}),!1;try{return await t(i),!0}catch(s){return c.error("Failed to send terminal input to Codex",{sessionId:e,error:s instanceof Error?s.message:String(s)}),!1}}async sendViaTmux(e,t){c.info("Sending via tmux",{sessionName:e,inputLength:t.length});try{await this.sendLiteralViaTmux(e,t),await this.delay(500);let i=`tmux send-keys -t "${e}" Enter`;await Ft(i),c.info("tmux send-keys completed")}catch(i){throw c.error("tmux send-keys failed",{sessionName:e,error:i}),i}}async sendLiteralViaTmux(e,t){let i=t.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\$/g,"\\$").replace(/`/g,"\\`"),s=`tmux send-keys -t "${e}" -l "${i}"`;await Ft(s)}async sendKeyViaTmux(e,t){c.info("Sending special key via tmux",{sessionName:e,key:t});try{let i=`tmux send-keys -t "${e}" ${t}`;await Ft(i),c.info("tmux special-key send completed")}catch(i){throw c.error("tmux special-key send failed",{sessionName:e,key:t,error:i}),i}}delay(e){return new Promise(t=>setTimeout(t,e))}isApprovalResponse(e){let t=e.trim().toLowerCase();return["y","n","a","q","e","yes","no"].includes(t)||/^[0-9]+$/.test(t)}};var E=k(require("fs")),ut=k(require("os")),J=k(require("path")),ke=require("crypto"),Di=require("child_process"),Fi=require("events"),Mi=require("util");var Ve=require("@quantiya/codevibe-core");function Mt(d){return d.replace(/(?:\x1B\]|\x9D)[^\x07\x1B\x9C\x9D]*(?:\x07|\x1B\\|\x9C)/g,"")}function oe(d){return Mt(d).replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])|\x9B[0-?]*[ -/]*[@-~]/g,"")}var Lt=(0,Mi.promisify)(Di.execFile),ki=512*1024,Te="writer.state",tn=2e3,sn=10,nn=16*1024*1024,rn=10080*60*1e3,Qe=class extends Fi.EventEmitter{constructor(t={}){super();this.sessionName=null;this.started=!1;this.pipeDirPath=null;this.pipeDirIdentity=null;this.pipeFilePath=null;this.pipeFileFd=null;this.pipeFileIdentity=null;this.writerStatePath=null;this.writerStateFd=null;this.writerStateIdentity=null;this.writerGeneration=null;this.pipeEnabled=!1;this.filePosition=0;this.pollTimer=null;this.processing=!1;this.pendingRead=!1;this.promptInspectionChain=Promise.resolve();this.lastPromptHash=null;this.lastPromptWasMenu=!1;this.lifecycleGeneration=0;this.retainedMirrors=[];this.retainedMirrorContainmentLost=!1;this.maxPaneFileBytes=t.maxPaneFileBytes??nn,this.stalePaneRetentionMs=t.stalePaneRetentionMs??rn,this.tempDir=t.tempDir??ut.tmpdir(),this.writerPath=J.resolve(__dirname,"..","libexec","pane-mirror-writer.js");let i=t.runtimePlatform??process.platform,s=t.runtimeRelease??ut.release();if(this.wslDetected=i==="linux"&&(/microsoft/i.test(s)||!!process.env.WSL_DISTRO_NAME||!!process.env.WSL_INTEROP),!Number.isSafeInteger(this.maxPaneFileBytes)||this.maxPaneFileBytes<=0)throw new RangeError("maxPaneFileBytes must be a positive safe integer");if(!Number.isSafeInteger(this.stalePaneRetentionMs)||this.stalePaneRetentionMs<0)throw new RangeError("stalePaneRetentionMs must be a non-negative safe integer")}async start(t){if(this.wslDetected)throw new Error("Tmux pane mirror fallback is disabled on unqualified WSL; using hook-based prompts only");if(this.started&&this.sessionName===t&&this.pipeEnabled){c.debug("Tmux pane observer already started",{sessionName:t});return}this.started&&await this.stop(),this.lifecycleGeneration++,this.sessionName=t,this.filePosition=0,this.lastPromptHash=null;try{if(this.cleanupStalePipeFiles(),this.reapOwnedRetainedMirrors(),this.retainedMirrorContainmentLost||this.retainedMirrors.length>0)throw new Error("Prior bounded tmux pane writer is still unconfirmed; refusing another mirror");this.createSecureMirror(),this.started=!0,await this.enablePipePane(),this.pipeEnabled=!0,this.startPolling()}catch(i){this.started=!1,this.lifecycleGeneration++;let s=this.writerGeneration===null;if(!s)try{await this.disablePipePane(),s=!0}catch(n){c.error("Failed to confirm tmux pane writer quiescence after startup failure",{disableError:n})}throw s&&(this.pipeEnabled=!1),this.clearPolling(),s?this.releaseSecureMirror():this.abandonSecureMirror(),this.resetLifecycleState(),i}c.info("Tmux pane observer started",{sessionName:t})}async stop(){if(!this.started&&this.pipeFileFd===null)return;this.started=!1,this.lifecycleGeneration++;let t=!1;try{await this.disablePipePane(),t=!0}catch(i){c.error("Failed to confirm tmux pane writer quiescence during stop",{error:i}),this.emit("observer-error",i)}t&&(this.pipeEnabled=!1),this.clearPolling(),t?this.releaseSecureMirror():this.abandonSecureMirror(),c.info("Tmux pane observer stopped",{sessionName:this.sessionName,writerQuiesced:t}),this.resetLifecycleState()}identityOf(t){return{dev:t.dev,ino:t.ino}}identitiesEqual(t,i){return t.dev===i.dev&&t.ino===i.ino}openMirrorFile(t){return E.openSync(t,E.constants.O_RDWR|E.constants.O_CREAT|E.constants.O_EXCL|(E.constants.O_NOFOLLOW??0),384)}truncateMirror(t){E.ftruncateSync(t,0)}createSecureMirror(){E.mkdirSync(this.tempDir,{recursive:!0,mode:448});let t=E.mkdtempSync(J.join(this.tempDir,`codevibe-codex-pane-${process.pid}-`));E.chmodSync(t,448);let i=J.join(t,"pane.log"),s=J.join(t,Te),n=null,r=null;try{n=this.openMirrorFile(i),E.fchmodSync(n,384);let o=E.fstatSync(n);if(!o.isFile())throw new Error("Tmux pane mirror is not a regular file");r=this.openMirrorFile(s),E.fchmodSync(r,384);let a=E.fstatSync(r);if(!a.isFile())throw new Error("Tmux pane writer state is not a regular file");E.writeSync(r,Buffer.from(`idle
33
- `),0,5,0),this.pipeDirPath=t,this.pipeDirIdentity=this.identityOf(E.lstatSync(t)),this.pipeFilePath=i,this.pipeFileFd=n,this.pipeFileIdentity=this.identityOf(o),this.writerStatePath=s,this.writerStateFd=r,this.writerStateIdentity=this.identityOf(a),n=null,r=null}catch(o){if(n!==null)try{E.closeSync(n)}catch{}if(r!==null)try{E.closeSync(r)}catch{}try{E.unlinkSync(i)}catch{}try{E.unlinkSync(s)}catch{}try{E.rmdirSync(t)}catch{}throw o}}pathMatchesMirrorIdentity(){if(!this.pipeFilePath||!this.pipeFileIdentity)return!1;try{let t=E.lstatSync(this.pipeFilePath);return t.isFile()&&!t.isSymbolicLink()&&this.identitiesEqual(this.pipeFileIdentity,this.identityOf(t))}catch{return!1}}quarantineIfIdentityMatches(t,i){let s=`${t}.reap-${process.pid}-${(0,ke.randomBytes)(6).toString("hex")}`;try{E.renameSync(t,s);let n=E.lstatSync(s);return this.identitiesEqual(i,this.identityOf(n))?s:(E.existsSync(t)||E.renameSync(s,t),null)}catch{return null}}restoreQuarantine(t,i){try{E.existsSync(i)||E.renameSync(t,i)}catch{}}pathMatchesIdentity(t,i){if(!t||!i)return!1;try{let s=E.lstatSync(t);return s.isFile()&&!s.isSymbolicLink()&&this.identitiesEqual(i,this.identityOf(s))}catch{return!1}}closeOwnedDescriptors(){if(this.pipeFileFd!==null)try{E.closeSync(this.pipeFileFd)}catch{}if(this.writerStateFd!==null)try{E.closeSync(this.writerStateFd)}catch{}this.pipeFileFd=null,this.writerStateFd=null}unlinkOwnedFile(t,i){if(!t||!i||!this.pathMatchesIdentity(t,i))return;let s=this.quarantineIfIdentityMatches(t,i);s&&E.unlinkSync(s)}releaseSecureMirror(){let t=this.pipeFilePath,i=this.writerStatePath,s=this.pipeDirPath,n=this.pipeFileIdentity,r=this.writerStateIdentity;this.closeOwnedDescriptors();try{this.unlinkOwnedFile(t,n)}catch{}try{this.unlinkOwnedFile(i,r)}catch{}if(s)try{E.rmdirSync(s)}catch{}this.pipeDirPath=null,this.pipeDirIdentity=null,this.pipeFilePath=null,this.pipeFileIdentity=null,this.writerStatePath=null,this.writerStateIdentity=null,this.writerGeneration=null}abandonSecureMirror(){let t=this.pipeDirPath,i=this.pipeFilePath;t&&this.pipeDirIdentity&&i&&this.pipeFileIdentity&&this.writerStatePath&&this.writerStateIdentity&&this.writerGeneration?this.retainedMirrors.push({dirPath:t,dirIdentity:this.pipeDirIdentity,panePath:i,paneIdentity:this.pipeFileIdentity,statePath:this.writerStatePath,stateIdentity:this.writerStateIdentity,writerGeneration:this.writerGeneration}):(t||i)&&(this.retainedMirrorContainmentLost=!0),this.closeOwnedDescriptors(),c.warn("Retaining bounded tmux pane mirror because writer quiescence is unconfirmed",{retainedDir:t,retainedFile:i,maxBytes:this.maxPaneFileBytes}),this.pipeDirPath=null,this.pipeDirIdentity=null,this.pipeFilePath=null,this.pipeFileIdentity=null,this.writerStatePath=null,this.writerStateIdentity=null,this.writerGeneration=null}resetLifecycleState(){this.sessionName=null,this.pipeDirPath=null,this.pipeDirIdentity=null,this.pipeFilePath=null,this.pipeFileFd=null,this.pipeFileIdentity=null,this.writerStatePath=null,this.writerStateFd=null,this.writerStateIdentity=null,this.writerGeneration=null,this.pipeEnabled=!1,this.filePosition=0,this.processing=!1,this.pendingRead=!1,this.lastPromptHash=null}async failClosedPipe(t){let i=!1;try{await this.disablePipePane(),i=!0}catch(s){c.error("Failed to confirm unsafe tmux pane writer quiescence",{disableError:s})}i&&(this.pipeEnabled=!1),this.clearPolling(),c.error("Tmux pane mirror entered fail-closed containment after integrity/cap failure",{error:t,writerQuiesced:i,independentlyBounded:!0}),this.emit("observer-error",t)}resetLastPromptHash(){this.lastPromptHash=null}async captureSnapshot(t=120,i=5e3){if(!this.sessionName)throw new Error("Tmux pane observer is not started");let s=Math.max(1,Math.floor(t)),n=Math.max(50,Math.floor(i));try{let{stdout:r}=await Lt("tmux",["capture-pane","-p","-e","-J","-S",`-${s}`,"-t",this.sessionName],{timeout:n,maxBuffer:2097152});return r}catch(r){throw c.error("Failed to capture tmux pane snapshot",{sessionName:this.sessionName,error:r}),this.emit("observer-error",r),r}}quoteShellArg(t){return`'${t.replace(/'/g,"'\\''")}'`}writerStatePathMatchesIdentity(){return this.pathMatchesIdentity(this.writerStatePath,this.writerStateIdentity)}writeWriterState(t){if(this.writerStateFd===null||!this.writerStateIdentity||!this.writerStatePathMatchesIdentity())throw new Error("Tmux pane writer state identity is not valid");let i=E.fstatSync(this.writerStateFd);if(!this.identitiesEqual(this.writerStateIdentity,this.identityOf(i)))throw new Error("Tmux pane writer state descriptor identity changed");let s=Buffer.from(t,"utf8");E.ftruncateSync(this.writerStateFd,0);let n=0;for(;n<s.length;){let r=E.writeSync(this.writerStateFd,s,n,s.length-n,n);if(r<=0)throw new Error("Short tmux pane writer-state write");n+=r}E.fsyncSync(this.writerStateFd)}readWriterState(){if(this.writerStateFd===null||!this.writerStateIdentity||!this.writerStatePathMatchesIdentity())throw new Error("Tmux pane writer state identity is not valid");let t=E.fstatSync(this.writerStateFd);if(!this.identitiesEqual(this.writerStateIdentity,this.identityOf(t)))throw new Error("Tmux pane writer state descriptor identity changed");let i=Math.min(t.size,512);if(i===0)return"";let s=Buffer.alloc(i),n=E.readSync(this.writerStateFd,s,0,i,0);return s.subarray(0,n).toString("utf8").trim()}async waitForWriterState(t,i,s=tn){let n=Date.now()+s;do{let r=this.readWriterState();if(i.some(o=>r.startsWith(`${o} ${t} `)))return r;if(Date.now()>=n)return null;await new Promise(o=>setTimeout(o,sn))}while(!0)}async enablePipePane(){if(!this.sessionName||!this.pipeFilePath||!this.writerStatePath)throw new Error("Tmux pane observer is not initialized");if(this.pipeFileFd===null||!this.pipeFileIdentity||!this.pathMatchesMirrorIdentity()||this.writerStateFd===null||!this.writerStateIdentity||!this.writerStatePathMatchesIdentity())throw new Error("Tmux pane mirror identity is not valid");let t=(0,ke.randomBytes)(16).toString("hex");this.writerGeneration=t,this.writeWriterState(`starting ${t}
34
- `);let i=[process.execPath,this.writerPath,this.pipeFilePath,String(this.pipeFileIdentity.dev),String(this.pipeFileIdentity.ino),this.writerStatePath,String(this.writerStateIdentity.dev),String(this.writerStateIdentity.ino),t,String(this.maxPaneFileBytes)].map(n=>this.quoteShellArg(n)).join(" ");try{await Lt("tmux",["pipe-pane","-O","-t",this.sessionName,i])}catch(n){throw this.writerGeneration=null,n}let s=await this.waitForWriterState(t,["ready","done"]);if(!s)throw new Error("Tmux pane writer did not confirm startup");if(s.startsWith(`done ${t} `))throw new Error("Tmux pane writer terminated during startup");c.debug("Enabled tmux pipe-pane mirroring",{sessionName:this.sessionName,pipeFilePath:this.pipeFilePath,writerGeneration:t})}async disablePipePane(){let t=this.writerGeneration;if(!this.sessionName||!t)return;let i=null;try{await Lt("tmux",["pipe-pane","-t",this.sessionName])}catch(r){i=r}if(!t){if(i)throw i;return}if(await this.waitForWriterState(t,["done"])){this.writerGeneration=null;return}let n=i instanceof Error?`: ${i.message}`:"";throw new Error(`Tmux pane writer quiescence was not confirmed${n}`)}startPolling(){this.clearPolling(),this.pollTimer=setInterval(()=>{this.processFileChanges()},100),this.pollTimer.unref?.()}clearPolling(){this.pollTimer&&clearInterval(this.pollTimer),this.pollTimer=null}async processFileChanges(){if(!(!this.started||!this.pipeFilePath)){if(this.processing){this.pendingRead=!0;return}this.processing=!0;try{do{this.pendingRead=!1;let t="";try{t=this.readAppendedChunk()}catch(i){c.error("Failed to read bounded tmux pane mirror",{error:i}),await this.failClosedPipe(i);return}await this.rotatePipeFileIfNeeded(),t&&this.queuePromptInspection(t,this.lifecycleGeneration)}while(this.pendingRead)}catch(t){c.error("Failed to process tmux pane changes",{error:t}),this.emit("observer-error",t)}finally{this.processing=!1}}}queuePromptInspection(t,i){this.promptInspectionChain=this.promptInspectionChain.then(async()=>{if(!(!this.started||this.lifecycleGeneration!==i))try{await this.inspectChunkForPrompt(t)}catch(s){c.error("Failed to inspect tmux pane delta",{error:s}),this.emit("observer-error",s)}})}async inspectChunkForPrompt(t){if(!this.lastPromptHash&&!this.looksLikePromptDelta(t))return;let i=await this.captureSnapshot();this.inspectSnapshotForPrompt(i,t)}inspectSnapshotForPrompt(t,i){let s=t?this.extractActivePromptBlock(t):null;if(!s){if(this.lastPromptHash){let r=this.lastPromptHash;this.lastPromptHash=null,this.lastPromptWasMenu=!1,this.emit("prompt-cleared",{promptHash:r})}t&&c.debug("tmux delta cue matched but no active dialog isolated (no candidate emitted)",{snapshotTail:t.split(`
35
- `).slice(-6).join("\\n")});return}let n=this.hashPromptSnapshot(s);n!==this.lastPromptHash&&(this.lastPromptHash&&(this.lastPromptWasMenu||(0,Ve.parseActiveTerminalMenu)(s))&&this.emit("prompt-cleared",{promptHash:this.lastPromptHash}),this.lastPromptHash=n,this.lastPromptWasMenu=!!(0,Ve.parseActiveTerminalMenu)(s),this.emit("prompt-candidate",{rawDelta:i,snapshot:s,promptHash:n,detectedAt:Date.now()}))}queueCurrentSnapshotInspection(t){this.promptInspectionChain=this.promptInspectionChain.then(async()=>{if(!(!this.started||this.lifecycleGeneration!==t))try{let i=await this.captureSnapshot();this.inspectSnapshotForPrompt(i,"")}catch(i){c.error("Failed to inspect tmux pane snapshot after rotation",{error:i}),this.emit("observer-error",i)}})}async rotatePipeFileIfNeeded(){let t=this.pipeFilePath,i=this.pipeFileFd,s=this.pipeFileIdentity,n=this.sessionName,r=this.lifecycleGeneration;if(!t||i===null||!s||!n||!this.started)return;let o;try{let l=E.fstatSync(i);if(!this.identitiesEqual(s,this.identityOf(l)))throw new Error("Tmux pane mirror descriptor identity changed");o=l.size}catch(l){await this.failClosedPipe(l);return}if(o<this.maxPaneFileBytes)return;let a="";try{await this.disablePipePane(),this.pipeEnabled=!1}catch(l){c.error("Tmux pane mirror rotation deferred because writer quiescence is unconfirmed",{error:l}),this.emit("observer-error",l),this.clearPolling();return}if(!(!this.started||this.lifecycleGeneration!==r||this.pipeFilePath!==t)){try{a=this.readAppendedChunk()}catch(l){c.error("Failed to drain final tmux pane suffix during rotation; mirror remains intact and disabled",{error:l}),this.emit("observer-error",l),this.clearPolling();return}try{this.truncateMirror(i);let l=E.fstatSync(i);if(!this.identitiesEqual(s,this.identityOf(l))||l.size!==0)throw new Error("Tmux pane mirror truncation could not be verified");if(!this.pathMatchesMirrorIdentity())throw new Error("Tmux pane mirror path was replaced during rotation")}catch(l){c.error("Tmux pane mirror remains disabled after truncation verification failure",{error:l}),this.emit("observer-error",l),this.clearPolling();return}if(this.filePosition=0,c.info("Rotated bounded tmux pane mirror",{sessionName:n,priorBytes:o,maxBytes:this.maxPaneFileBytes}),this.started&&this.lifecycleGeneration===r&&this.pipeFilePath===t&&this.sessionName===n)try{await this.enablePipePane(),this.pipeEnabled=!0}catch(l){this.pipeEnabled=!1,c.error("Tmux pane mirror remains disabled after re-enable failure",{error:l}),this.emit("observer-error",l),this.clearPolling()}a&&this.queuePromptInspection(a,r),this.pipeEnabled&&this.queueCurrentSnapshotInspection(r)}}retainedPathMatchesIdentity(t,i,s){try{let n=E.lstatSync(t);return(s==="file"?n.isFile():n.isDirectory())&&!n.isSymbolicLink()&&(typeof process.getuid!="function"||n.uid===process.getuid())&&this.identitiesEqual(i,this.identityOf(n))}catch{return!1}}readRetainedWriterState(t,i){let s=null;try{s=E.openSync(t,E.constants.O_RDONLY|(E.constants.O_NOFOLLOW??0));let n=E.fstatSync(s);if(!n.isFile()||typeof process.getuid=="function"&&n.uid!==process.getuid()||!this.identitiesEqual(i,this.identityOf(n))||n.size>512)return null;let r=Buffer.alloc(n.size),o=n.size===0?0:E.readSync(s,r,0,n.size,0);return r.subarray(0,o).toString("utf8").trim()}catch{return null}finally{if(s!==null)try{E.closeSync(s)}catch{}}}reapOwnedRetainedMirror(t){if(!this.retainedPathMatchesIdentity(t.dirPath,t.dirIdentity,"directory"))return!1;let i;try{i=E.readdirSync(t.dirPath).sort()}catch{return!1}if(i.length!==2||i[0]!=="pane.log"||i[1]!==Te||!this.retainedPathMatchesIdentity(t.panePath,t.paneIdentity,"file")||!this.retainedPathMatchesIdentity(t.statePath,t.stateIdentity,"file"))return!1;let s=new RegExp(`^done ${t.writerGeneration} \\d+ \\d+$`);if(!s.test(this.readRetainedWriterState(t.statePath,t.stateIdentity)??""))return!1;let n=this.quarantineIfIdentityMatches(t.dirPath,t.dirIdentity);if(!n)return!1;let r=!1;try{let o=J.join(n,"pane.log"),a=J.join(n,Te);if(!this.retainedPathMatchesIdentity(o,t.paneIdentity,"file"))throw new Error("pane identity changed");if(!this.retainedPathMatchesIdentity(a,t.stateIdentity,"file"))throw new Error("state identity changed");if(!s.test(this.readRetainedWriterState(a,t.stateIdentity)??""))throw new Error("writer generation is no longer done");if(this.unlinkOwnedFile(o,t.paneIdentity),this.unlinkOwnedFile(a,t.stateIdentity),E.existsSync(o)||E.existsSync(a))throw new Error("retained mirror unlink was incomplete");E.rmdirSync(n),r=!0,c.info("Removed completed same-owner tmux pane mirror",{retainedDir:t.dirPath})}catch{E.existsSync(n)&&this.restoreQuarantine(n,t.dirPath)}return r}reapOwnedRetainedMirrors(){this.retainedMirrors=this.retainedMirrors.filter(t=>!this.reapOwnedRetainedMirror(t))}cleanupStalePipeFiles(){let t=Date.now()-this.stalePaneRetentionMs,i;try{i=E.readdirSync(this.tempDir,{withFileTypes:!0})}catch{return}for(let s of i){let n=/^codevibe-codex-pane-(\d+)\.log$/.exec(s.name);if(n){let l=J.join(this.tempDir,s.name),p=null;try{let f=E.lstatSync(l);if(!f.isFile()||f.isSymbolicLink()||f.mtimeMs>t||typeof process.getuid=="function"&&f.uid!==process.getuid()||this.isProcessAlive(Number(n[1]))||(p=this.quarantineIfIdentityMatches(l,this.identityOf(f)),!p))continue;E.unlinkSync(p),p=null,c.info("Removed stale legacy tmux pane mirror",{candidate:l,ageMs:Date.now()-f.mtimeMs})}catch{p&&this.restoreQuarantine(p,l)}continue}let r=/^codevibe-codex-pane-(\d+)-[A-Za-z0-9_-]+$/.exec(s.name);if(!r||!s.isDirectory())continue;let o=J.join(this.tempDir,s.name),a=null;try{let l=E.lstatSync(o);if(!l.isDirectory()||l.isSymbolicLink()||l.mtimeMs>t||typeof process.getuid=="function"&&l.uid!==process.getuid())continue;let p=Number(r[1]);if(this.isProcessAlive(p)||(a=this.quarantineIfIdentityMatches(o,this.identityOf(l)),!a))continue;let f=J.join(a,"pane.log"),u=J.join(a,Te),m=E.readdirSync(a);if(m.some(h=>h!=="pane.log"&&h!==Te)){this.restoreQuarantine(a,o);continue}for(let h of m.map(I=>J.join(a,I))){let I=E.lstatSync(h);if(!I.isFile()||I.isSymbolicLink()||typeof process.getuid=="function"&&I.uid!==process.getuid()){this.restoreQuarantine(a,o),a=null;break}}if(!a)continue;if(m.includes(Te)){let h=E.readFileSync(u,"utf8").trim(),I=/^ready [a-f0-9]{32} (\d+)$/.exec(h);if(!(h==="idle"||/^done [a-f0-9]{32} \d+ \d+$/.test(h)||!!I)||I&&this.isProcessAlive(Number(I[1]))){this.restoreQuarantine(a,o);continue}}m.includes("pane.log")&&E.unlinkSync(f),m.includes(Te)&&E.unlinkSync(u),E.rmdirSync(a),a=null,c.info("Removed stale tmux pane mirror directory",{candidate:o,ageMs:Date.now()-l.mtimeMs})}catch{a&&this.restoreQuarantine(a,o)}}}isProcessAlive(t){try{return process.kill(t,0),!0}catch(i){return i?.code==="EPERM"}}readAppendedChunk(){if(!this.pipeFilePath||this.pipeFileFd===null||!this.pipeFileIdentity)return"";if(!this.pathMatchesMirrorIdentity())throw new Error("Tmux pane mirror path was replaced");let t=E.fstatSync(this.pipeFileFd);if(!this.identitiesEqual(this.pipeFileIdentity,this.identityOf(t)))throw new Error("Tmux pane mirror descriptor identity changed");if(t.size<=this.filePosition)return"";{let s=t.size-this.filePosition>ki?t.size-ki:this.filePosition,n=t.size-s,r=Buffer.alloc(n),o=0;for(;o<n;){let a=E.readSync(this.pipeFileFd,r,o,n-o,s+o);if(a===0)break;o+=a}return this.filePosition=s+o,r.subarray(0,o).toString("utf-8")}}looksLikePromptDelta(t){return/Would you like to run/i.test(t)||/[>›❯▸▶]\s*[1-9]\d?\.\s/.test(t)||/\x1b\[[0-9;]*m[^\n]{0,80}[1-9]\d?\.\s/.test(t)||/Press enter to confirm/i.test(t)||/enter to (?:submit|confirm|select|continue)/i.test(t)||/\besc to cancel\b/i.test(t)||/\bYes,\s+proceed\b/i.test(t)||/\bNo,\s+and tell Codex\b/i.test(t)||/don't ask again/i.test(t)||/Requesting permission for:|Do you want to proceed\?/i.test(t)||/\[(?:y\/n|Y\/n|y\/N)\]|\b(?:apply|approve|allow|reject|deny|continue)\b/i.test(t)}looksLikePromptSnapshot(t){return this.extractActivePromptBlock(t)!==null}extractActivePromptBlock(t){return this.extractActiveApprovalBlock(t)??(0,Ve.parseActiveTerminalMenu)(t)?.snapshot??null}extractActiveApprovalBlock(t){let s=oe(t).split(`
36
- `).map(h=>h.replace(/\s+$/,"")),n=h=>h.trim().length>0,r=h=>{let I=h.trim();return/^(?:[>›❯]\s*)?press enter to confirm(?: or esc to cancel)?$/i.test(I)||/^(?:[>›❯]\s*)?(?:press )?esc to cancel$/i.test(I)},o=h=>/Would you like to |Do you want to |The model would like to |Allow .+ to run|Requesting permission for:/i.test(h),a=h=>/^[>›❯\s]*[1-9][.)]\s+\S/.test(h),l=h=>/\[(?:y\/n|Y\/n|y\/N)\]/i.test(h),p=h=>{let I=new Set;for(let y of h)a(y)&&(/\bYes,\s+proceed\b/i.test(y)&&I.add("proceed"),/\bNo,\s+and tell Codex\b/i.test(y)&&I.add("reject"),/don't ask again/i.test(y)&&I.add("dont-ask"));return I.size},f=h=>a(h)&&(/\bYes,\s+proceed\b/i.test(h)||/\bNo,\s+and tell Codex\b/i.test(h)||/don't ask again/i.test(h)),u=-1;for(let h=s.length-1;h>=0;h--)if(n(s[h])){u=h;break}if(u===-1)return null;if(l(s[u])){let h=u;for(let I=u-1;I>=0&&u-I<=8&&!(!n(s[I])||r(s[I])||a(s[I]));I--)h=I;return s.slice(h,u+1).join(`
37
- `)}let m=-1;for(let h=s.length-1;h>=0;h--)if(r(s[h])){m=h;break}if(m===u){let h=-1;for(let y=m-1;y>=0&&!r(s[y]);y--)if(o(s[y])){h=y;break}if(h===-1)return null;let I=s.slice(h,m+1);return I.some(a)?I.join(`
38
- `):null}if(f(s[u])){let h=-1;for(let v=u-1;v>=0;v--){if(r(s[v]))return null;if(o(s[v])){h=v;break}}if(h===-1)return null;let I=v=>{let S=v.match(/^[>›❯\s]*([1-9])[.)]\s/);return S?parseInt(S[1],10):null},y=[],w=Number.POSITIVE_INFINITY;for(let v=u;v>h&&a(s[v]);v--){let S=I(s[v]);if(S===null||S>=w)break;y.push(s[v]),w=S}return p(y)<2?null:s.slice(h,u+1).join(`
39
- `)}return null}hashPromptSnapshot(t){let i=(0,Ve.parseActiveTerminalMenu)(Mt(t));if(i)return(0,ke.createHash)("sha256").update(i.identity).digest("hex");let s=oe(t).replace(/\r/g,`
33
+ `)}}function on(a){if(!a)return null;let e=a.match(/\*\*\* (?:Update|Add|Delete) File: (.+)/);return e?{filePath:e[1].trim()}:null}function ft(a){if(a==null)return"";if(typeof a=="string")return a;if(Array.isArray(a))return a.map(e=>typeof e?.text=="string"?e.text:e?.type==="input_image"||typeof e?.image_url=="string"?"[image]":JSON.stringify(e??null)).join(`
34
+ `);if(typeof a=="object"&&typeof a.text=="string")return a.text;try{return JSON.stringify(a)??""}catch{return String(a)}}function qt(a,e){return typeof a!="string"?qt(ft(a),e):a?a.length<=e?a:a.substring(0,e)+"...":""}function Vt(){ue.clear(),fe()}var V=require("@quantiya/codevibe-core"),Li=3e3,an=8,dn=10,ln=100;function qi(a){let e=Buffer.byteLength(a.carryover);return{status:"partial",progressKey:`${a.fileIdentity.dev}:${a.fileIdentity.ino}:${a.size}:${a.endOfComplete}:${e}`,size:a.size,carryoverBytes:e,endOfComplete:a.endOfComplete}}var cn="tool_activity",_e=class{constructor(e){this.consolidator=null;this.ledger=null;this.sessionMap=null;this.ownership=null;this.cursor=null;this.backendSessionId=null;this.rolloutId=null;this.transcriptPath=null;this.backstopTimer=null;this.backstopInFlight=null;this.cursorReady=Promise.resolve();this.cursorRepaired=!1;this.deps=e}static mintBackendSessionId(){return V.ToolActivitySessionMap.mintCodexBackendSessionId()}async recordedBackendSessionId(e){return new V.ToolActivitySessionMap({agent:"codex",logger:this.deps.logger,lock:new V.InProcessRolloutLock,root:this.deps.root}).ownerBackendSessionId(e)}get sessionId(){return this.backendSessionId}get rollout(){return this.rolloutId}isActive(){return this.consolidator!==null}async start(e,t,i){this.backendSessionId=e,this.rolloutId=t;let s=(0,V.createRolloutLock)({agent:"codex",logger:this.deps.logger,socketDir:this.deps.socketDir,root:this.deps.root});this.sessionMap=new V.ToolActivitySessionMap({agent:"codex",logger:this.deps.logger,lock:s,root:this.deps.root}),this.ownership=await this.sessionMap.claimOwnership(t,e);let n=new V.ToolActivityOutbox({agent:"codex",logger:this.deps.logger,root:this.deps.root});this.ledger=new V.ToolActivityLedger({agent:"codex",sessionId:e,logger:this.deps.logger,root:this.deps.root}),await this.deps.recoverPending?.(e,n,this.ledger);let r=this.buildTransport(),o=this.deps.selectTransport?await this.deps.selectTransport(e,r):r;this.consolidator=new V.ToolActivityConsolidator({agent:"codex",sessionId:e,logger:this.deps.logger,outbox:n,ledger:this.ledger,transport:o}),await this.consolidator.init(),i&&(this.bindTranscript(i),await this.cursorReady),this.deps.logger.info("[tool-activity] codex consolidator started",{sessionId:e,rollout:t,hasTranscript:!!i})}bindTranscript(e){if(!this.consolidator||!e||this.transcriptPath===e)return;this.transcriptPath=e;let t=new V.ToolReplayCursor({agent:"codex",sessionId:this.backendSessionId,canonicalPath:e,logger:this.deps.logger,root:this.deps.root,readBytes:this.deps.replayReadBytes,maxFrameBytes:this.deps.replayMaxFrameBytes});this.cursor=t,this.cursorRepaired=!1,this.cursorReady=t.load(this.deps.initialBoundary?.(e)),this.cursorReady.catch(s=>this.deps.logger.warn("[tool-activity] codex cursor load failed; replay retained",{sessionId:this.backendSessionId,err:String(s)}));let i=this.deps.backstopIntervalMs??3e3;i>0&&!this.backstopTimer&&(this.backstopTimer=setInterval(()=>{this.runTranscriptBackstop().catch(s=>this.deps.logger.warn("[tool-activity] codex transcript backstop failed",{sessionId:this.backendSessionId,err:String(s)}))},i),this.backstopTimer.unref?.())}async observeCall(e,t){if(!this.consolidator||!this.sessionMap||!this.ownership||!e.callId||!e.toolName)return;let i=this.consolidator;await this.sessionMap.bindCall(this.ownership,e.callId);let s={id:e.callId,tool:e.toolName,normalizedTarget:mn(e.toolName,e.toolInput),ts:e.ts??new Date().toISOString(),byteOffset:e.byteOffset??0,...e.toolInput!==void 0?{digest:(0,V.digestOf)(e.toolInput)}:{}},n=await i.observe(s,t);return n==="closed"?await i.captureTerminal(s,this.deps.shutdownDrainMs??Li)?"sealed-terminal":"closed":n}async runTranscriptBackstop(e=!1){await this.runTranscriptBackstopTurn(e)}runTranscriptBackstopTurn(e=!1){if(this.backstopInFlight)return this.backstopInFlight;let t=this.cursor,i=this.cursorReady,s=this.consolidator;if(!s||!t)return Promise.resolve("caught-up");let r=(async()=>{if(await i,this.cursor!==t)return"more";if(!this.cursorRepaired){if(await s.repairLostWindows(t),this.cursor!==t)return"more";this.cursorRepaired=!0}return this.doTranscriptBackstop(t,e)})().finally(()=>{this.backstopInFlight===r&&(this.backstopInFlight=null)});return this.backstopInFlight=r,r}async doTranscriptBackstop(e,t=!1){let i=this.consolidator;if(!i)return"caught-up";this.ledger&&await this.ledger.reloadLegacyOwned();for(let s=0;s<an;s+=1){if(this.cursor!==e)return"caught-up";let n=await e.readFrames();if(n.missing)return"caught-up";if(n.frames.length===0)return n.carryover.length>0?qi(n):"caught-up";let r=Number.POSITIVE_INFINITY,o=t?{includeInFlight:!0}:void 0;for(let d of n.frames)for(let l of un(d.line,d.startOffset))await this.observeCall(l,o)==="deferred-in-flight"&&(r=Math.min(r,d.startOffset));if(await i.flush(),r<n.endOfComplete)return await e.checkpoint(r,{fileIdentity:n.fileIdentity,size:n.size,carryover:""}),"more";if(await e.checkpoint(n.endOfComplete,{fileIdentity:n.fileIdentity,size:n.size,carryover:n.carryover}),!n.hasMore)return n.carryover.length>0?qi(n):"caught-up"}return"more"}async flush(){await this.consolidator?.flush()}async abortStart(){this.backstopTimer&&clearInterval(this.backstopTimer),this.backstopTimer=null;try{await this.backstopInFlight?.catch(()=>{}),await this.consolidator?.shutdown()}finally{await this.ownership?.release(),this.ownership=null,this.consolidator=null,this.ledger=null,this.sessionMap=null,this.cursor=null}}async stop(){this.backstopTimer&&(clearInterval(this.backstopTimer),this.backstopTimer=null),await this.runTranscriptBackstop().catch(()=>{});let e=Math.max(1,Math.trunc(this.deps.shutdownPartialNoProgressTurns??ln)),t=null,i=0;for(;;){let s=await this.runTranscriptBackstopTurn(!0);if(s==="caught-up")break;if(typeof s!="string"){if(s.progressKey===t?i+=1:(t=s.progressKey,i=1),i>=e){this.deps.logger.warn("[tool-activity] deferring unchanged incomplete rollout suffix during shutdown; the next owner will re-read it from the durable complete-line boundary",{size:s.size,carryoverBytes:s.carryoverBytes,endOfComplete:s.endOfComplete,unchangedTurns:i});break}await new Promise(n=>setTimeout(n,dn))}else t=null,i=0,await new Promise(n=>setImmediate(n))}await this.consolidator?.drainSends(this.deps.shutdownDrainMs??Li).catch(()=>{});try{await this.consolidator?.shutdown()}finally{await this.ownership?.release().catch(()=>{}),this.ownership=null,this.consolidator=null,this.ledger=null,this.sessionMap=null,this.cursor=null}}buildTransport(){let e=async(t,i,s)=>{let n=s?s.sessionKey:this.deps.getSessionKey();if(!n)throw new Error("[tool-activity] no session key at send (retryable)");let r=s?s.sessionKeyGen:this.deps.getSessionKeyGen();await this.deps.createEvent({sessionId:t,type:V.EventType.TOOL_ACTIVITY,source:V.EventSource.DESKTOP,content:this.deps.encryptContent(cn,n),metadata:{encrypted:this.deps.encryptMetadata({manifest:i.manifest},n)},timestamp:i.windowStart,isEncrypted:!0,clientEventId:i.clientEventId,...r?{expectedSessionKeyGen:r}:{}})};return{send:async(t,i)=>{try{await e(t,i)}catch(s){if((0,V.isSessionKeyStaleError)(s)&&this.deps.refreshSessionKey){let n=await this.deps.refreshSessionKey(t);if(!n)throw s;await e(t,i,n);return}throw s}}}}};function un(a,e){let t;try{t=JSON.parse(a)}catch{return[]}if(t?.type!=="response_item"||!t.payload)return[];let i=t.payload,s=typeof t.timestamp=="string"?t.timestamp:new Date(0).toISOString();if(i.type==="function_call"&&typeof i.call_id=="string"&&typeof i.name=="string"){let n;try{n=JSON.parse(i.arguments||"{}")}catch{n={raw:i.arguments}}return[{callId:i.call_id,toolName:pn(i.name),toolInput:n,ts:s,byteOffset:e}]}if(i.type==="custom_tool_call"&&typeof i.call_id=="string"){let n=hn(typeof i.input=="string"?i.input:""),r=n?{file_path:n,patch:i.input}:{patch:i.input};return[{callId:i.call_id,toolName:"Edit",toolInput:r,ts:s,byteOffset:e}]}return[]}function pn(a){return a==="shell"||a==="shell_command"||a==="local_shell"?"Bash":a==="apply_patch"?"Edit":a}function hn(a){let e=a.match(/^\*\*\* (?:Update|Add|Delete) File: (.+)$/m);return e?e[1].trim():void 0}function mn(a,e){if(!e||typeof e!="object")return;let t=e,i=n=>typeof n=="string"&&n.length>0?n:void 0,s=Array.isArray(t.command)?t.command.filter(n=>typeof n=="string").join(" ").trim().split(/\s+/)[0]:typeof t.command=="string"?t.command.trim().split(/\s+/)[0]:void 0;return i(t.file_path)??i(t.path)??i(t.pattern)??i(t.url)??(s&&s.length>0?s:void 0)}var Bi=require("events"),Vi=require("@quantiya/codevibe-core");var gt=class a extends Bi.EventEmitter{constructor(){super();this.pendingCalls=new Map;this.timers=new Map;this.timeoutMs=(0,Vi.getConfig)().codex.approvalTimeoutMs,c.info("Approval detector initialized",{timeoutMs:this.timeoutMs})}onToolCallStart(t,i,s){c.debug("Tool call started",{callId:t,name:i});let n=this.parseInput(s),r=this.extractFilePath(i,s,n),o=this.extractDiff(i,s,n),d={callId:t,name:i,input:s,filePath:r,diff:o,parsedInput:n,timestamp:Date.now(),notificationSent:!1};if(this.pendingCalls.set(t,d),!this.shouldScheduleApprovalTimeout(i,n)){c.debug("Skipping approval timeout for non-escalated tool call",{callId:t,name:i});return}let l=setTimeout(()=>{this.checkPendingCall(t)},this.timeoutMs);this.timers.set(t,l)}onToolCallComplete(t){c.debug("Tool call completed",{callId:t}),this.pendingCalls.delete(t);let i=this.timers.get(t);i&&(clearTimeout(i),this.timers.delete(t))}checkPendingCall(t){let i=this.pendingCalls.get(t);if(!i||i.notificationSent)return;let s=Date.now()-i.timestamp;c.info("Tool call still pending after timeout",{callId:t,name:i.name,elapsedMs:s}),i.notificationSent=!0,this.pendingCalls.set(t,i),this.emit("approval-pending",{callId:t,toolName:i.name,hint:this.extractHint(i.name,i.input,i.filePath),filePath:i.filePath,diff:i.diff,toolInput:i.parsedInput,rawInput:i.input,elapsedMs:s})}extractHint(t,i,s){if(s)return`File: ${s}`;if(t==="apply_patch"&&i){let n=i.match(/\*\*\* (?:Update|Add|Delete) File: (.+)/);if(n)return`File: ${n[1].trim()}`}if(a.SHELL_TOOL_NAMES.has(t))try{let n=JSON.parse(i),r=typeof n.command=="string"?n.command:typeof n.cmd=="string"?n.cmd:void 0;if(r)return`Command: ${r.substring(0,50)}${r.length>50?"...":""}`}catch{}return`Tool: ${this.mapToolName(t)}`}mapToolName(t){return{exec_command:"Bash",shell_command:"Bash",shell:"Bash",exec:"Bash",local_shell:"Bash",apply_patch:"File Edit",write_file:"Write File",read_file:"Read File"}[t]||t}parseInput(t){if(t)try{return JSON.parse(t)}catch{return}}static{this.SHELL_TOOL_NAMES=new Set(["exec_command","shell_command","shell","exec","local_shell"])}shouldScheduleApprovalTimeout(t,i){return a.SHELL_TOOL_NAMES.has(t)?i?.sandbox_permissions==="require_escalated":!1}extractFilePath(t,i,s){if(t==="apply_patch"&&i){let r=i.match(/\*\*\* (?:Update|Add|Delete) File: (.+)/);if(r)return r[1].trim()}let n=s?.file_path||s?.path||s?.filePath;if(n&&typeof n=="string")return n}extractDiff(t,i,s){if(t==="apply_patch"&&i)return i;if(s?.diff&&typeof s.diff=="string")return s.diff}getPendingCalls(){return Array.from(this.pendingCalls.values())}hasPendingCalls(){return this.pendingCalls.size>0}clear(){for(let t of this.timers.values())clearTimeout(t);this.timers.clear(),this.pendingCalls.clear(),c.debug("Approval detector cleared")}shutdown(){this.clear(),this.removeAllListeners(),c.info("Approval detector shutdown")}};var Ui=require("child_process"),Ki=require("util");var Ut=(0,Ki.promisify)(Ui.exec),Le="__CODEVIBE_CODEX_KEY_ESCAPE__",yt=class{async sendLiteral(e,t){return this.sendTerminalOperation(e,async i=>{await this.sendLiteralViaTmux(i,t)})}async sendKey(e,t){return this.sendTerminalOperation(e,async i=>{await this.sendKeyViaTmux(i,t)})}async sendInput(e,t){c.info("Attempting to send input to Codex",{sessionId:e,input:t});try{let i=process.env.CODEVIBE_CODEX_TMUX_SESSION;return i?(c.info("Using tmux send-keys",{tmuxSession:i}),t===Le?await this.sendKeyViaTmux(i,"Escape"):await this.sendViaTmux(i,t),c.info("Successfully sent input to Codex",{sessionId:e,input:t}),!0):(c.error("No tmux session found - CodeVibe Companion launch is required",{sessionId:e,hint:"Start Codex CLI using `codevibe --agent codex`"}),!1)}catch(i){return c.error("Failed to send input to Codex",{sessionId:e,error:i instanceof Error?i.message:String(i)}),!1}}async sendTerminalOperation(e,t){let i=process.env.CODEVIBE_CODEX_TMUX_SESSION;if(!i)return c.error("No tmux session found - CodeVibe Companion launch is required",{sessionId:e,hint:"Start Codex CLI using `codevibe --agent codex`"}),!1;try{return await t(i),!0}catch(s){return c.error("Failed to send terminal input to Codex",{sessionId:e,error:s instanceof Error?s.message:String(s)}),!1}}async sendViaTmux(e,t){c.info("Sending via tmux",{sessionName:e,inputLength:t.length});try{await this.sendLiteralViaTmux(e,t),await this.delay(500);let i=`tmux send-keys -t "${e}" Enter`;await Ut(i),c.info("tmux send-keys completed")}catch(i){throw c.error("tmux send-keys failed",{sessionName:e,error:i}),i}}async sendLiteralViaTmux(e,t){let i=t.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\$/g,"\\$").replace(/`/g,"\\`"),s=`tmux send-keys -t "${e}" -l "${i}"`;await Ut(s)}async sendKeyViaTmux(e,t){c.info("Sending special key via tmux",{sessionName:e,key:t});try{let i=`tmux send-keys -t "${e}" ${t}`;await Ut(i),c.info("tmux special-key send completed")}catch(i){throw c.error("tmux special-key send failed",{sessionName:e,key:t,error:i}),i}}delay(e){return new Promise(t=>setTimeout(t,e))}isApprovalResponse(e){let t=e.trim().toLowerCase();return["y","n","a","q","e","yes","no"].includes(t)||/^[0-9]+$/.test(t)}};var P=D(require("fs")),It=D(require("os")),X=D(require("path")),qe=require("crypto"),Hi=require("child_process"),ji=require("events"),Gi=require("util");var ze=require("@quantiya/codevibe-core");function Kt(a){return a.replace(/(?:\x1B\]|\x9D)[^\x07\x1B\x9C\x9D]*(?:\x07|\x1B\\|\x9C)/g,"")}function ae(a){return Kt(a).replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])|\x9B[0-?]*[ -/]*[@-~]/g,"")}var Qt=(0,Gi.promisify)(Hi.execFile),Qi=512*1024,Ce="writer.state",fn=2e3,vn=10,gn=16*1024*1024,yn=10080*60*1e3,Je=class extends ji.EventEmitter{constructor(t={}){super();this.sessionName=null;this.started=!1;this.pipeDirPath=null;this.pipeDirIdentity=null;this.pipeFilePath=null;this.pipeFileFd=null;this.pipeFileIdentity=null;this.writerStatePath=null;this.writerStateFd=null;this.writerStateIdentity=null;this.writerGeneration=null;this.pipeEnabled=!1;this.filePosition=0;this.pollTimer=null;this.processing=!1;this.pendingRead=!1;this.promptInspectionChain=Promise.resolve();this.lastPromptHash=null;this.lastPromptWasMenu=!1;this.lifecycleGeneration=0;this.retainedMirrors=[];this.retainedMirrorContainmentLost=!1;this.maxPaneFileBytes=t.maxPaneFileBytes??gn,this.stalePaneRetentionMs=t.stalePaneRetentionMs??yn,this.tempDir=t.tempDir??It.tmpdir(),this.writerPath=X.resolve(__dirname,"..","libexec","pane-mirror-writer.js");let i=t.runtimePlatform??process.platform,s=t.runtimeRelease??It.release();if(this.wslDetected=i==="linux"&&(/microsoft/i.test(s)||!!process.env.WSL_DISTRO_NAME||!!process.env.WSL_INTEROP),!Number.isSafeInteger(this.maxPaneFileBytes)||this.maxPaneFileBytes<=0)throw new RangeError("maxPaneFileBytes must be a positive safe integer");if(!Number.isSafeInteger(this.stalePaneRetentionMs)||this.stalePaneRetentionMs<0)throw new RangeError("stalePaneRetentionMs must be a non-negative safe integer")}async start(t){if(this.wslDetected)throw new Error("Tmux pane mirror fallback is disabled on unqualified WSL; using hook-based prompts only");if(this.started&&this.sessionName===t&&this.pipeEnabled){c.debug("Tmux pane observer already started",{sessionName:t});return}this.started&&await this.stop(),this.lifecycleGeneration++,this.sessionName=t,this.filePosition=0,this.lastPromptHash=null;try{if(this.cleanupStalePipeFiles(),this.reapOwnedRetainedMirrors(),this.retainedMirrorContainmentLost||this.retainedMirrors.length>0)throw new Error("Prior bounded tmux pane writer is still unconfirmed; refusing another mirror");this.createSecureMirror(),this.started=!0,await this.enablePipePane(),this.pipeEnabled=!0,this.startPolling()}catch(i){this.started=!1,this.lifecycleGeneration++;let s=this.writerGeneration===null;if(!s)try{await this.disablePipePane(),s=!0}catch(n){c.error("Failed to confirm tmux pane writer quiescence after startup failure",{disableError:n})}throw s&&(this.pipeEnabled=!1),this.clearPolling(),s?this.releaseSecureMirror():this.abandonSecureMirror(),this.resetLifecycleState(),i}c.info("Tmux pane observer started",{sessionName:t})}async stop(){if(!this.started&&this.pipeFileFd===null)return;this.started=!1,this.lifecycleGeneration++;let t=!1;try{await this.disablePipePane(),t=!0}catch(i){c.error("Failed to confirm tmux pane writer quiescence during stop",{error:i}),this.emit("observer-error",i)}t&&(this.pipeEnabled=!1),this.clearPolling(),t?this.releaseSecureMirror():this.abandonSecureMirror(),c.info("Tmux pane observer stopped",{sessionName:this.sessionName,writerQuiesced:t}),this.resetLifecycleState()}identityOf(t){return{dev:t.dev,ino:t.ino}}identitiesEqual(t,i){return t.dev===i.dev&&t.ino===i.ino}openMirrorFile(t){return P.openSync(t,P.constants.O_RDWR|P.constants.O_CREAT|P.constants.O_EXCL|(P.constants.O_NOFOLLOW??0),384)}truncateMirror(t){P.ftruncateSync(t,0)}createSecureMirror(){P.mkdirSync(this.tempDir,{recursive:!0,mode:448});let t=P.mkdtempSync(X.join(this.tempDir,`codevibe-codex-pane-${process.pid}-`));P.chmodSync(t,448);let i=X.join(t,"pane.log"),s=X.join(t,Ce),n=null,r=null;try{n=this.openMirrorFile(i),P.fchmodSync(n,384);let o=P.fstatSync(n);if(!o.isFile())throw new Error("Tmux pane mirror is not a regular file");r=this.openMirrorFile(s),P.fchmodSync(r,384);let d=P.fstatSync(r);if(!d.isFile())throw new Error("Tmux pane writer state is not a regular file");P.writeSync(r,Buffer.from(`idle
35
+ `),0,5,0),this.pipeDirPath=t,this.pipeDirIdentity=this.identityOf(P.lstatSync(t)),this.pipeFilePath=i,this.pipeFileFd=n,this.pipeFileIdentity=this.identityOf(o),this.writerStatePath=s,this.writerStateFd=r,this.writerStateIdentity=this.identityOf(d),n=null,r=null}catch(o){if(n!==null)try{P.closeSync(n)}catch{}if(r!==null)try{P.closeSync(r)}catch{}try{P.unlinkSync(i)}catch{}try{P.unlinkSync(s)}catch{}try{P.rmdirSync(t)}catch{}throw o}}pathMatchesMirrorIdentity(){if(!this.pipeFilePath||!this.pipeFileIdentity)return!1;try{let t=P.lstatSync(this.pipeFilePath);return t.isFile()&&!t.isSymbolicLink()&&this.identitiesEqual(this.pipeFileIdentity,this.identityOf(t))}catch{return!1}}quarantineIfIdentityMatches(t,i){let s=`${t}.reap-${process.pid}-${(0,qe.randomBytes)(6).toString("hex")}`;try{P.renameSync(t,s);let n=P.lstatSync(s);return this.identitiesEqual(i,this.identityOf(n))?s:(P.existsSync(t)||P.renameSync(s,t),null)}catch{return null}}restoreQuarantine(t,i){try{P.existsSync(i)||P.renameSync(t,i)}catch{}}pathMatchesIdentity(t,i){if(!t||!i)return!1;try{let s=P.lstatSync(t);return s.isFile()&&!s.isSymbolicLink()&&this.identitiesEqual(i,this.identityOf(s))}catch{return!1}}closeOwnedDescriptors(){if(this.pipeFileFd!==null)try{P.closeSync(this.pipeFileFd)}catch{}if(this.writerStateFd!==null)try{P.closeSync(this.writerStateFd)}catch{}this.pipeFileFd=null,this.writerStateFd=null}unlinkOwnedFile(t,i){if(!t||!i||!this.pathMatchesIdentity(t,i))return;let s=this.quarantineIfIdentityMatches(t,i);s&&P.unlinkSync(s)}releaseSecureMirror(){let t=this.pipeFilePath,i=this.writerStatePath,s=this.pipeDirPath,n=this.pipeFileIdentity,r=this.writerStateIdentity;this.closeOwnedDescriptors();try{this.unlinkOwnedFile(t,n)}catch{}try{this.unlinkOwnedFile(i,r)}catch{}if(s)try{P.rmdirSync(s)}catch{}this.pipeDirPath=null,this.pipeDirIdentity=null,this.pipeFilePath=null,this.pipeFileIdentity=null,this.writerStatePath=null,this.writerStateIdentity=null,this.writerGeneration=null}abandonSecureMirror(){let t=this.pipeDirPath,i=this.pipeFilePath;t&&this.pipeDirIdentity&&i&&this.pipeFileIdentity&&this.writerStatePath&&this.writerStateIdentity&&this.writerGeneration?this.retainedMirrors.push({dirPath:t,dirIdentity:this.pipeDirIdentity,panePath:i,paneIdentity:this.pipeFileIdentity,statePath:this.writerStatePath,stateIdentity:this.writerStateIdentity,writerGeneration:this.writerGeneration}):(t||i)&&(this.retainedMirrorContainmentLost=!0),this.closeOwnedDescriptors(),c.warn("Retaining bounded tmux pane mirror because writer quiescence is unconfirmed",{retainedDir:t,retainedFile:i,maxBytes:this.maxPaneFileBytes}),this.pipeDirPath=null,this.pipeDirIdentity=null,this.pipeFilePath=null,this.pipeFileIdentity=null,this.writerStatePath=null,this.writerStateIdentity=null,this.writerGeneration=null}resetLifecycleState(){this.sessionName=null,this.pipeDirPath=null,this.pipeDirIdentity=null,this.pipeFilePath=null,this.pipeFileFd=null,this.pipeFileIdentity=null,this.writerStatePath=null,this.writerStateFd=null,this.writerStateIdentity=null,this.writerGeneration=null,this.pipeEnabled=!1,this.filePosition=0,this.processing=!1,this.pendingRead=!1,this.lastPromptHash=null}async failClosedPipe(t){let i=!1;try{await this.disablePipePane(),i=!0}catch(s){c.error("Failed to confirm unsafe tmux pane writer quiescence",{disableError:s})}i&&(this.pipeEnabled=!1),this.clearPolling(),c.error("Tmux pane mirror entered fail-closed containment after integrity/cap failure",{error:t,writerQuiesced:i,independentlyBounded:!0}),this.emit("observer-error",t)}resetLastPromptHash(){this.lastPromptHash=null}async captureSnapshot(t=120,i=5e3){if(!this.sessionName)throw new Error("Tmux pane observer is not started");let s=Math.max(1,Math.floor(t)),n=Math.max(50,Math.floor(i));try{let{stdout:r}=await Qt("tmux",["capture-pane","-p","-e","-J","-S",`-${s}`,"-t",this.sessionName],{timeout:n,maxBuffer:2097152});return r}catch(r){throw c.error("Failed to capture tmux pane snapshot",{sessionName:this.sessionName,error:r}),this.emit("observer-error",r),r}}quoteShellArg(t){return`'${t.replace(/'/g,"'\\''")}'`}writerStatePathMatchesIdentity(){return this.pathMatchesIdentity(this.writerStatePath,this.writerStateIdentity)}writeWriterState(t){if(this.writerStateFd===null||!this.writerStateIdentity||!this.writerStatePathMatchesIdentity())throw new Error("Tmux pane writer state identity is not valid");let i=P.fstatSync(this.writerStateFd);if(!this.identitiesEqual(this.writerStateIdentity,this.identityOf(i)))throw new Error("Tmux pane writer state descriptor identity changed");let s=Buffer.from(t,"utf8");P.ftruncateSync(this.writerStateFd,0);let n=0;for(;n<s.length;){let r=P.writeSync(this.writerStateFd,s,n,s.length-n,n);if(r<=0)throw new Error("Short tmux pane writer-state write");n+=r}P.fsyncSync(this.writerStateFd)}readWriterState(){if(this.writerStateFd===null||!this.writerStateIdentity||!this.writerStatePathMatchesIdentity())throw new Error("Tmux pane writer state identity is not valid");let t=P.fstatSync(this.writerStateFd);if(!this.identitiesEqual(this.writerStateIdentity,this.identityOf(t)))throw new Error("Tmux pane writer state descriptor identity changed");let i=Math.min(t.size,512);if(i===0)return"";let s=Buffer.alloc(i),n=P.readSync(this.writerStateFd,s,0,i,0);return s.subarray(0,n).toString("utf8").trim()}async waitForWriterState(t,i,s=fn){let n=Date.now()+s;do{let r=this.readWriterState();if(i.some(o=>r.startsWith(`${o} ${t} `)))return r;if(Date.now()>=n)return null;await new Promise(o=>setTimeout(o,vn))}while(!0)}async enablePipePane(){if(!this.sessionName||!this.pipeFilePath||!this.writerStatePath)throw new Error("Tmux pane observer is not initialized");if(this.pipeFileFd===null||!this.pipeFileIdentity||!this.pathMatchesMirrorIdentity()||this.writerStateFd===null||!this.writerStateIdentity||!this.writerStatePathMatchesIdentity())throw new Error("Tmux pane mirror identity is not valid");let t=(0,qe.randomBytes)(16).toString("hex");this.writerGeneration=t,this.writeWriterState(`starting ${t}
36
+ `);let i=[process.execPath,this.writerPath,this.pipeFilePath,String(this.pipeFileIdentity.dev),String(this.pipeFileIdentity.ino),this.writerStatePath,String(this.writerStateIdentity.dev),String(this.writerStateIdentity.ino),t,String(this.maxPaneFileBytes)].map(n=>this.quoteShellArg(n)).join(" ");try{await Qt("tmux",["pipe-pane","-O","-t",this.sessionName,i])}catch(n){throw this.writerGeneration=null,n}let s=await this.waitForWriterState(t,["ready","done"]);if(!s)throw new Error("Tmux pane writer did not confirm startup");if(s.startsWith(`done ${t} `))throw new Error("Tmux pane writer terminated during startup");c.debug("Enabled tmux pipe-pane mirroring",{sessionName:this.sessionName,pipeFilePath:this.pipeFilePath,writerGeneration:t})}async disablePipePane(){let t=this.writerGeneration;if(!this.sessionName||!t)return;let i=null;try{await Qt("tmux",["pipe-pane","-t",this.sessionName])}catch(r){i=r}if(!t){if(i)throw i;return}if(await this.waitForWriterState(t,["done"])){this.writerGeneration=null;return}let n=i instanceof Error?`: ${i.message}`:"";throw new Error(`Tmux pane writer quiescence was not confirmed${n}`)}startPolling(){this.clearPolling(),this.pollTimer=setInterval(()=>{this.processFileChanges()},100),this.pollTimer.unref?.()}clearPolling(){this.pollTimer&&clearInterval(this.pollTimer),this.pollTimer=null}async processFileChanges(){if(!(!this.started||!this.pipeFilePath)){if(this.processing){this.pendingRead=!0;return}this.processing=!0;try{do{this.pendingRead=!1;let t="";try{t=this.readAppendedChunk()}catch(i){c.error("Failed to read bounded tmux pane mirror",{error:i}),await this.failClosedPipe(i);return}await this.rotatePipeFileIfNeeded(),t&&this.queuePromptInspection(t,this.lifecycleGeneration)}while(this.pendingRead)}catch(t){c.error("Failed to process tmux pane changes",{error:t}),this.emit("observer-error",t)}finally{this.processing=!1}}}queuePromptInspection(t,i){this.promptInspectionChain=this.promptInspectionChain.then(async()=>{if(!(!this.started||this.lifecycleGeneration!==i))try{await this.inspectChunkForPrompt(t)}catch(s){c.error("Failed to inspect tmux pane delta",{error:s}),this.emit("observer-error",s)}})}async inspectChunkForPrompt(t){if(!this.lastPromptHash&&!this.looksLikePromptDelta(t))return;let i=await this.captureSnapshot();this.inspectSnapshotForPrompt(i,t)}inspectSnapshotForPrompt(t,i){let s=t?this.extractActivePromptBlock(t):null;if(!s){if(this.lastPromptHash){let r=this.lastPromptHash;this.lastPromptHash=null,this.lastPromptWasMenu=!1,this.emit("prompt-cleared",{promptHash:r})}t&&c.debug("tmux delta cue matched but no active dialog isolated (no candidate emitted)",{snapshotTail:t.split(`
37
+ `).slice(-6).join("\\n")});return}let n=this.hashPromptSnapshot(s);n!==this.lastPromptHash&&(this.lastPromptHash&&(this.lastPromptWasMenu||(0,ze.parseActiveTerminalMenu)(s))&&this.emit("prompt-cleared",{promptHash:this.lastPromptHash}),this.lastPromptHash=n,this.lastPromptWasMenu=!!(0,ze.parseActiveTerminalMenu)(s),this.emit("prompt-candidate",{rawDelta:i,snapshot:s,promptHash:n,detectedAt:Date.now()}))}queueCurrentSnapshotInspection(t){this.promptInspectionChain=this.promptInspectionChain.then(async()=>{if(!(!this.started||this.lifecycleGeneration!==t))try{let i=await this.captureSnapshot();this.inspectSnapshotForPrompt(i,"")}catch(i){c.error("Failed to inspect tmux pane snapshot after rotation",{error:i}),this.emit("observer-error",i)}})}async rotatePipeFileIfNeeded(){let t=this.pipeFilePath,i=this.pipeFileFd,s=this.pipeFileIdentity,n=this.sessionName,r=this.lifecycleGeneration;if(!t||i===null||!s||!n||!this.started)return;let o;try{let l=P.fstatSync(i);if(!this.identitiesEqual(s,this.identityOf(l)))throw new Error("Tmux pane mirror descriptor identity changed");o=l.size}catch(l){await this.failClosedPipe(l);return}if(o<this.maxPaneFileBytes)return;let d="";try{await this.disablePipePane(),this.pipeEnabled=!1}catch(l){c.error("Tmux pane mirror rotation deferred because writer quiescence is unconfirmed",{error:l}),this.emit("observer-error",l),this.clearPolling();return}if(!(!this.started||this.lifecycleGeneration!==r||this.pipeFilePath!==t)){try{d=this.readAppendedChunk()}catch(l){c.error("Failed to drain final tmux pane suffix during rotation; mirror remains intact and disabled",{error:l}),this.emit("observer-error",l),this.clearPolling();return}try{this.truncateMirror(i);let l=P.fstatSync(i);if(!this.identitiesEqual(s,this.identityOf(l))||l.size!==0)throw new Error("Tmux pane mirror truncation could not be verified");if(!this.pathMatchesMirrorIdentity())throw new Error("Tmux pane mirror path was replaced during rotation")}catch(l){c.error("Tmux pane mirror remains disabled after truncation verification failure",{error:l}),this.emit("observer-error",l),this.clearPolling();return}if(this.filePosition=0,c.info("Rotated bounded tmux pane mirror",{sessionName:n,priorBytes:o,maxBytes:this.maxPaneFileBytes}),this.started&&this.lifecycleGeneration===r&&this.pipeFilePath===t&&this.sessionName===n)try{await this.enablePipePane(),this.pipeEnabled=!0}catch(l){this.pipeEnabled=!1,c.error("Tmux pane mirror remains disabled after re-enable failure",{error:l}),this.emit("observer-error",l),this.clearPolling()}d&&this.queuePromptInspection(d,r),this.pipeEnabled&&this.queueCurrentSnapshotInspection(r)}}retainedPathMatchesIdentity(t,i,s){try{let n=P.lstatSync(t);return(s==="file"?n.isFile():n.isDirectory())&&!n.isSymbolicLink()&&(typeof process.getuid!="function"||n.uid===process.getuid())&&this.identitiesEqual(i,this.identityOf(n))}catch{return!1}}readRetainedWriterState(t,i){let s=null;try{s=P.openSync(t,P.constants.O_RDONLY|(P.constants.O_NOFOLLOW??0));let n=P.fstatSync(s);if(!n.isFile()||typeof process.getuid=="function"&&n.uid!==process.getuid()||!this.identitiesEqual(i,this.identityOf(n))||n.size>512)return null;let r=Buffer.alloc(n.size),o=n.size===0?0:P.readSync(s,r,0,n.size,0);return r.subarray(0,o).toString("utf8").trim()}catch{return null}finally{if(s!==null)try{P.closeSync(s)}catch{}}}reapOwnedRetainedMirror(t){if(!this.retainedPathMatchesIdentity(t.dirPath,t.dirIdentity,"directory"))return!1;let i;try{i=P.readdirSync(t.dirPath).sort()}catch{return!1}if(i.length!==2||i[0]!=="pane.log"||i[1]!==Ce||!this.retainedPathMatchesIdentity(t.panePath,t.paneIdentity,"file")||!this.retainedPathMatchesIdentity(t.statePath,t.stateIdentity,"file"))return!1;let s=new RegExp(`^done ${t.writerGeneration} \\d+ \\d+$`);if(!s.test(this.readRetainedWriterState(t.statePath,t.stateIdentity)??""))return!1;let n=this.quarantineIfIdentityMatches(t.dirPath,t.dirIdentity);if(!n)return!1;let r=!1;try{let o=X.join(n,"pane.log"),d=X.join(n,Ce);if(!this.retainedPathMatchesIdentity(o,t.paneIdentity,"file"))throw new Error("pane identity changed");if(!this.retainedPathMatchesIdentity(d,t.stateIdentity,"file"))throw new Error("state identity changed");if(!s.test(this.readRetainedWriterState(d,t.stateIdentity)??""))throw new Error("writer generation is no longer done");if(this.unlinkOwnedFile(o,t.paneIdentity),this.unlinkOwnedFile(d,t.stateIdentity),P.existsSync(o)||P.existsSync(d))throw new Error("retained mirror unlink was incomplete");P.rmdirSync(n),r=!0,c.info("Removed completed same-owner tmux pane mirror",{retainedDir:t.dirPath})}catch{P.existsSync(n)&&this.restoreQuarantine(n,t.dirPath)}return r}reapOwnedRetainedMirrors(){this.retainedMirrors=this.retainedMirrors.filter(t=>!this.reapOwnedRetainedMirror(t))}cleanupStalePipeFiles(){let t=Date.now()-this.stalePaneRetentionMs,i;try{i=P.readdirSync(this.tempDir,{withFileTypes:!0})}catch{return}for(let s of i){let n=/^codevibe-codex-pane-(\d+)\.log$/.exec(s.name);if(n){let l=X.join(this.tempDir,s.name),u=null;try{let h=P.lstatSync(l);if(!h.isFile()||h.isSymbolicLink()||h.mtimeMs>t||typeof process.getuid=="function"&&h.uid!==process.getuid()||this.isProcessAlive(Number(n[1]))||(u=this.quarantineIfIdentityMatches(l,this.identityOf(h)),!u))continue;P.unlinkSync(u),u=null,c.info("Removed stale legacy tmux pane mirror",{candidate:l,ageMs:Date.now()-h.mtimeMs})}catch{u&&this.restoreQuarantine(u,l)}continue}let r=/^codevibe-codex-pane-(\d+)-[A-Za-z0-9_-]+$/.exec(s.name);if(!r||!s.isDirectory())continue;let o=X.join(this.tempDir,s.name),d=null;try{let l=P.lstatSync(o);if(!l.isDirectory()||l.isSymbolicLink()||l.mtimeMs>t||typeof process.getuid=="function"&&l.uid!==process.getuid())continue;let u=Number(r[1]);if(this.isProcessAlive(u)||(d=this.quarantineIfIdentityMatches(o,this.identityOf(l)),!d))continue;let h=X.join(d,"pane.log"),p=X.join(d,Ce),m=P.readdirSync(d);if(m.some(f=>f!=="pane.log"&&f!==Ce)){this.restoreQuarantine(d,o);continue}for(let f of m.map(g=>X.join(d,g))){let g=P.lstatSync(f);if(!g.isFile()||g.isSymbolicLink()||typeof process.getuid=="function"&&g.uid!==process.getuid()){this.restoreQuarantine(d,o),d=null;break}}if(!d)continue;if(m.includes(Ce)){let f=P.readFileSync(p,"utf8").trim(),g=/^ready [a-f0-9]{32} (\d+)$/.exec(f);if(!(f==="idle"||/^done [a-f0-9]{32} \d+ \d+$/.test(f)||!!g)||g&&this.isProcessAlive(Number(g[1]))){this.restoreQuarantine(d,o);continue}}m.includes("pane.log")&&P.unlinkSync(h),m.includes(Ce)&&P.unlinkSync(p),P.rmdirSync(d),d=null,c.info("Removed stale tmux pane mirror directory",{candidate:o,ageMs:Date.now()-l.mtimeMs})}catch{d&&this.restoreQuarantine(d,o)}}}isProcessAlive(t){try{return process.kill(t,0),!0}catch(i){return i?.code==="EPERM"}}readAppendedChunk(){if(!this.pipeFilePath||this.pipeFileFd===null||!this.pipeFileIdentity)return"";if(!this.pathMatchesMirrorIdentity())throw new Error("Tmux pane mirror path was replaced");let t=P.fstatSync(this.pipeFileFd);if(!this.identitiesEqual(this.pipeFileIdentity,this.identityOf(t)))throw new Error("Tmux pane mirror descriptor identity changed");if(t.size<=this.filePosition)return"";{let s=t.size-this.filePosition>Qi?t.size-Qi:this.filePosition,n=t.size-s,r=Buffer.alloc(n),o=0;for(;o<n;){let d=P.readSync(this.pipeFileFd,r,o,n-o,s+o);if(d===0)break;o+=d}return this.filePosition=s+o,r.subarray(0,o).toString("utf-8")}}looksLikePromptDelta(t){return/Would you like to run/i.test(t)||/[>›❯▸▶]\s*[1-9]\d?\.\s/.test(t)||/\x1b\[[0-9;]*m[^\n]{0,80}[1-9]\d?\.\s/.test(t)||/Press enter to confirm/i.test(t)||/enter to (?:submit|confirm|select|continue)/i.test(t)||/\besc to cancel\b/i.test(t)||/\bYes,\s+proceed\b/i.test(t)||/\bNo,\s+and tell Codex\b/i.test(t)||/don't ask again/i.test(t)||/Requesting permission for:|Do you want to proceed\?/i.test(t)||/\[(?:y\/n|Y\/n|y\/N)\]|\b(?:apply|approve|allow|reject|deny|continue)\b/i.test(t)}looksLikePromptSnapshot(t){return this.extractActivePromptBlock(t)!==null}extractActivePromptBlock(t){return this.extractActiveApprovalBlock(t)??(0,ze.parseActiveTerminalMenu)(t)?.snapshot??null}extractActiveApprovalBlock(t){let s=ae(t).split(`
38
+ `).map(f=>f.replace(/\s+$/,"")),n=f=>f.trim().length>0,r=f=>{let g=f.trim();return/^(?:[>›❯]\s*)?press enter to confirm(?: or esc to cancel)?$/i.test(g)||/^(?:[>›❯]\s*)?(?:press )?esc to cancel$/i.test(g)},o=f=>/Would you like to |Do you want to |The model would like to |Allow .+ to run|Requesting permission for:/i.test(f),d=f=>/^[>›❯\s]*[1-9][.)]\s+\S/.test(f),l=f=>/\[(?:y\/n|Y\/n|y\/N)\]/i.test(f),u=f=>{let g=new Set;for(let y of f)d(y)&&(/\bYes,\s+proceed\b/i.test(y)&&g.add("proceed"),/\bNo,\s+and tell Codex\b/i.test(y)&&g.add("reject"),/don't ask again/i.test(y)&&g.add("dont-ask"));return g.size},h=f=>d(f)&&(/\bYes,\s+proceed\b/i.test(f)||/\bNo,\s+and tell Codex\b/i.test(f)||/don't ask again/i.test(f)),p=-1;for(let f=s.length-1;f>=0;f--)if(n(s[f])){p=f;break}if(p===-1)return null;if(l(s[p])){let f=p;for(let g=p-1;g>=0&&p-g<=8&&!(!n(s[g])||r(s[g])||d(s[g]));g--)f=g;return s.slice(f,p+1).join(`
39
+ `)}let m=-1;for(let f=s.length-1;f>=0;f--)if(r(s[f])){m=f;break}if(m===p){let f=-1;for(let y=m-1;y>=0&&!r(s[y]);y--)if(o(s[y])){f=y;break}if(f===-1)return null;let g=s.slice(f,m+1);return g.some(d)?g.join(`
40
+ `):null}if(h(s[p])){let f=-1;for(let I=p-1;I>=0;I--){if(r(s[I]))return null;if(o(s[I])){f=I;break}}if(f===-1)return null;let g=I=>{let w=I.match(/^[>›❯\s]*([1-9])[.)]\s/);return w?parseInt(w[1],10):null},y=[],S=Number.POSITIVE_INFINITY;for(let I=p;I>f&&d(s[I]);I--){let w=g(s[I]);if(w===null||w>=S)break;y.push(s[I]),S=w}return u(y)<2?null:s.slice(f,p+1).join(`
41
+ `)}return null}hashPromptSnapshot(t){let i=(0,ze.parseActiveTerminalMenu)(Kt(t));if(i)return(0,qe.createHash)("sha256").update(i.identity).digest("hex");let s=ae(t).replace(/\r/g,`
40
42
  `).replace(/[ \t]+\n/g,`
41
- `).trim();return(0,ke.createHash)("sha256").update(s).digest("hex")}};var M=require("@quantiya/codevibe-core");function Li(d,e){if(d!=="write_stdin"||!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return!Number.isSafeInteger(t.session_id)||t.session_id<=0||typeof t.chars!="string"||t.chars.length===0||typeof t.environment_id!="string"||!t.environment_id||/[\r\n]/.test(t.environment_id)||typeof t.approval_id!="string"||!t.approval_id?null:{terminalId:t.session_id,chars:t.chars,environmentId:t.environment_id,approvalId:t.approval_id}}function on(d){if(!d.startsWith('"')||!d.endsWith('"'))return null;let e="";for(let t=1;t<d.length-1;t++){let i=d[t];if(i==='"'||i.charCodeAt(0)<32)return null;if(i!=="\\"){e+=i;continue}if(++t>=d.length-1)return null;let s=d[t],n={'"':'"',"\\":"\\",n:`
42
- `,r:"\r",t:" ",0:"\0"};if(Object.prototype.hasOwnProperty.call(n,s)){e+=n[s];continue}if(s!=="u"||d[t+1]!=="{")return null;let r=d.indexOf("}",t+2);if(r<0||r>=d.length-1)return null;let o=d.slice(t+2,r);if(!/^[0-9a-fA-F]{1,6}$/.test(o))return null;let a=Number.parseInt(o,16);if(a>1114111||a>=55296&&a<=57343)return null;e+=String.fromCodePoint(a),t=r}return e}function ht(d){let e=d.split(`
43
- `).map(l=>l.trim()),t=e.filter(l=>/^Would you like to send input to terminal /.test(l)),i=e.filter(l=>l.startsWith("Environment:")),s=e.filter(l=>l.startsWith("Input:"));if(t.length!==1||i.length!==1||s.length!==1)return null;let n=/^Would you like to send input to terminal ([1-9][0-9]*)\?$/.exec(t[0]),r=n?Number(n[1]):NaN,o=i[0].slice(12).trimStart(),a=on(s[0].slice(6).trimStart());return!Number.isSafeInteger(r)||!o||a===null||!a.length?null:{terminalId:r,environmentId:o,chars:a}}function qi(d,e){let t=ht(d);return!!t&&t.terminalId===e.terminalId&&t.environmentId===e.environmentId&&t.chars===e.chars}var ps=require("@quantiya/codevibe-core");var qt=k(require("express")),fe=k(require("fs")),Bi=k(require("path")),Ki=k(require("os"));var an=1800*1e3,dn=60*1e3,ln=1440*60*1e3;var mt=class{constructor(){this.assignedPort=0;this.portRefreshTimer=null;this.app=(0,qt.default)(),this.setupMiddleware(),this.setupRoutes(),this.tmuxSession=process.env.CODEVIBE_CODEX_TMUX_SESSION}getPort(){return this.assignedPort}setupMiddleware(){this.app.use(qt.default.json({limit:"1mb"})),this.app.use((e,t,i)=>{c.debug(`${e.method} ${e.path}`,{body:e.body}),i()})}setupRoutes(){this.app.get("/health",(e,t)=>{t.json({success:!0,service:"codevibe-codex",pid:process.pid,data:{status:"healthy",uptime:process.uptime()}})}),this.app.post("/event",this.handleEvent.bind(this))}async handleEvent(e,t){try{let i=e.body;if(!i.session_id||!i.hook_event_name){t.status(400).json({success:!1,error:"Missing session_id or hook_event_name"});return}let s=this.transformHookToEvent(i);if(c.info("Received hook event",{sessionId:i.session_id,hookEvent:i.hook_event_name,type:s.type}),this.eventHandler){let n=this.eventHandler(s);if(i.hook_event_name==="PermissionRequest"){n.catch(r=>{c.error("Error resolving PermissionRequest after acknowledgement:",r)}),t.json({success:!0});return}await n}t.json({success:!0})}catch(i){c.error("Error handling event:",i),t.status(500).json({success:!1,error:i instanceof Error?i.message:"Unknown error"})}}transformHookToEvent(e){let t={cwd:e.cwd,hook_event_name:e.hook_event_name,transcript_path:e.transcript_path,...e.metadata||{}},i,s;switch(e.hook_event_name){case"SessionStart":i="NOTIFICATION",s="Session started",t.source=e.source,t.model=e.model;break;case"UserPromptSubmit":i="USER_PROMPT",s=e.prompt||"";break;case"PreToolUse":i="NOTIFICATION",s="PreToolUse observed",t.tool_name=e.tool_name,t.tool_input=e.tool_input,t.tool_use_id=e.tool_use_id,t.approval_status="observed_pre_tool",t.requires_user_action=!1;break;case"PermissionRequest":i="NOTIFICATION",s="PermissionRequest observed",t.tool_name=e.tool_name,t.tool_input=e.tool_input,t.permission_mode=e.permission_mode,t.turn_id=e.turn_id,t.requires_user_action=!0;break;case"PostToolUse":i="TOOL_USE",s=JSON.stringify({tool_name:e.tool_name,tool_input:e.tool_input,tool_response:e.tool_response}),t.tool_name=e.tool_name,t.tool_input=e.tool_input,t.tool_use_id=e.tool_use_id;break;case"Stop":i="ASSISTANT_RESPONSE",s=e.last_assistant_message||"";break;default:i="NOTIFICATION",s=`Hook: ${e.hook_event_name}`}return{session_id:e.session_id,hook_event_name:e.hook_event_name,type:i,source:"DESKTOP",content:s,metadata:t}}onEvent(e){this.eventHandler=e}async start(){return new Promise((e,t)=>{try{this.server=this.app.listen(0,"localhost",()=>{let i=this.server.address();this.assignedPort=i.port,c.info(`HTTP API listening on http://localhost:${this.assignedPort}`),this.writePortFile(this.assignedPort),this.startPortFileKeepalive(),e(this.assignedPort)}),this.server.on("error",i=>{c.error("HTTP server error:",i),t(i)})}catch(i){t(i)}})}portFilePath(){return this.tmuxSession?Bi.join(Ki.tmpdir(),`codevibe-codex-${this.tmuxSession}.port`):null}writePortFile(e){let t=this.portFilePath();if(!t){c.warn("No CODEVIBE_CODEX_TMUX_SESSION set, skipping port file");return}try{fe.writeFileSync(t,e.toString()),c.info(`Port file written: ${t} -> ${e}`)}catch(i){c.error(`Failed to write port file: ${t}`,i)}}removePortFile(){let e=this.portFilePath();if(e)try{fe.existsSync(e)&&(fe.unlinkSync(e),c.info(`Port file removed: ${e}`))}catch(t){c.warn(`Failed to remove port file: ${e}`,t)}}startPortFileKeepalive(){this.portRefreshTimer&&(clearInterval(this.portRefreshTimer),this.portRefreshTimer=null);let e=Number(process.env.CODEVIBE_PORTFILE_REFRESH_MS),t=Number.isFinite(e)&&e>0?Math.min(ln,Math.max(dn,e)):an;this.portRefreshTimer=setInterval(()=>this.refreshPortFile(),t)}refreshPortFile(){let e=this.portFilePath();if(e)try{let t=new Date;fe.utimesSync(e,t,t)}catch(t){t?.code==="ENOENT"?this.writePortFile(this.assignedPort):c.warn(`Port-file refresh failed: ${e}`,t)}}async stop(){return this.portRefreshTimer&&(clearInterval(this.portRefreshTimer),this.portRefreshTimer=null),this.removePortFile(),new Promise(e=>{this.server?this.server.close(()=>{c.info("HTTP API stopped"),e()}):e()})}};var ft=class{constructor(e={}){this.pendingBySession=new Map;this.expiryMs=e.expiryMs??1e4,this.minFuzzyEchoLength=e.minFuzzyEchoLength??16,this.minFuzzyEchoRatio=e.minFuzzyEchoRatio??.35,this.now=e.now??Date.now}track(e,t){let i=this.normalize(t);if(!i)return;let s=this.validEntries(e);s.push({normalized:i,timestamp:this.now()}),this.pendingBySession.set(e,s)}forget(e,t){let i=this.normalize(t);if(!i)return;let s=!1,n=this.validEntries(e).filter(r=>!s&&r.normalized===i?(s=!0,!1):!0);this.replaceEntries(e,n)}consumeIfDuplicate(e,t){let i=this.normalize(t);if(!i)return null;let s=null,n=this.validEntries(e).filter(r=>{if(!s){let o=this.matchType(r.normalized,i);if(o)return s={matchType:o,originalLength:r.normalized.length,echoLength:i.length},!1}return!0});return this.replaceEntries(e,n),s}peekIfDuplicate(e,t){let i=this.normalize(t);if(!i)return null;for(let s of this.validEntries(e)){let n=this.matchType(s.normalized,i);if(n)return{matchType:n,originalLength:s.normalized.length,echoLength:i.length}}return null}validEntries(e){let t=this.now()-this.expiryMs;return(this.pendingBySession.get(e)||[]).filter(i=>i.timestamp>=t)}replaceEntries(e,t){t.length>0?this.pendingBySession.set(e,t):this.pendingBySession.delete(e)}matchType(e,t){if(e===t)return"exact";let i=t.length>=this.minFuzzyEchoLength,s=t.length/e.length>=this.minFuzzyEchoRatio;return i&&s&&e.endsWith(t)?"suffix":null}normalize(e){return e.replace(/\s+/g," ").trim()}};var Vi=k(require("crypto")),Qi=k(require("fs")),Hi=k(require("https")),gt=k(require("os")),ji=k(require("path")),cn="G-GS74YEQTB8",pn="lAfOF6OxRzSQ-NsLBRjhAg",un="www.google-analytics.com",hn=`/mp/collect?measurement_id=${cn}&api_secret=${pn}`,Ui=800;function mn(){try{let d=ji.resolve(__dirname,"..","package.json"),e=Qi.readFileSync(d,"utf-8"),t=JSON.parse(e);if(typeof t.version=="string"&&t.version.length>0&&t.version.length<30)return t.version}catch{}return"unknown"}var fn=mn();function gn(){let d=typeof process.getuid=="function"?process.getuid():0;return Vi.createHash("sha256").update(`${gt.hostname()}-${d}`).digest("hex").substring(0,36)}function yn(d){if(!d)return"";let e=gt.homedir(),t=d.replace(/[\n\r\t]/g," ");if(e&&e.length>0){let i=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");t=t.replace(new RegExp(i,"g"),"~")}return t=t.replace(/\/Users\/[^/\s"'`]+/g,"/Users/<user>").replace(/\/home\/[^/\s"'`]+/g,"/home/<user>").replace(/[^\x20-\x7E]/g,""),t.trim().substring(0,100)}function L(d,e){return new Promise(t=>{let i,s=!1,n=()=>{s||(s=!0,clearTimeout(r),t())},r=setTimeout(()=>{try{i?.destroy()}catch{}n()},Ui);typeof r.unref=="function"&&r.unref();try{let o={...e};typeof o.error_message=="string"&&(o.error_message=yn(o.error_message));let a=JSON.stringify({client_id:gn(),events:[{name:d,params:{agent:"codex",plugin_version:fn,platform:process.platform,source:process.env.CODEVIBE_TELEMETRY_SOURCE||"production",...o}}]});i=Hi.request({hostname:un,path:hn,method:"POST",headers:{"Content-Type":"application/json"},timeout:Ui},l=>{l.resume(),l.on("end",n),l.on("close",n),l.on("error",n)}),i.on("error",n),i.on("timeout",()=>{try{i?.destroy()}catch{}n()}),i.on("close",n),i.write(a),i.end()}catch{n()}})}var yt=class{constructor(){this.originated=new Set;this.externallyResolved=new Set}markOriginated(e){this.originated.add(e)}clearOriginated(e){this.originated.delete(e)}getOriginated(){return new Set(this.originated)}getExternallyResolved(){return new Set(this.externallyResolved)}isExternallyResolved(e){return this.externallyResolved.has(e)}dispatch(e){let{gateId:t}=e;return this.originated.has(t)?(this.originated.delete(t),this.externallyResolved.add(t),"self_echo"):(this.externallyResolved.add(t),"foreign")}clear(){this.originated.clear(),this.externallyResolved.clear()}};function $i(d){return`[CodeVibe] Decision recorded on another device: ${d} \u2014 type any number to dismiss the open AskUserQuestion`}var Gi=require("@quantiya/codevibe-core"),vn=new Set(["stall-retirement","stall-tmux-probe"]),In=1e3,vt;function Sn(d=process.env){let e=new Map,t=d.CODEVIBE_DEV_FAULTS;if(t&&(0,Gi.getEnvironment)()==="development")for(let i of t.split(",")){let[s,n]=i.trim().split(":");if(!vn.has(s))continue;let r=n===void 0?1:Number.parseInt(n,10);!Number.isSafeInteger(r)||r<=0||r>In||e.set(s,r)}return vt=e,e}function Bt(d){vt||Sn();let e=vt.get(d)??0;return e<=0?!1:(vt.set(d,e-1),!0)}async function Kt(d,e,t){let i;try{let s=(()=>{try{return Promise.resolve(d())}catch(o){return Promise.reject(o)}})(),n=new Promise(o=>{i=setTimeout(()=>o("timeout"),e),i.unref&&i.unref()}),r=await Promise.race([s.then(()=>"settled",()=>"settled"),n]);if(r==="timeout"){s.catch(()=>{});try{t?.()}catch{}}return r}finally{i&&clearTimeout(i)}}function De(d,e,t=25e3,i=()=>!0){let s=setTimeout(()=>{try{e()}catch{}let n=!1;try{n=i()}catch{n=!1}d(n?0:1)},t);return()=>clearTimeout(s)}var He=k(require("crypto")),C=k(require("fs")),St=k(require("os")),te=k(require("path")),Ji=require("@quantiya/codevibe-core"),Ut=2*1024*1024,wn=600*1e3,ae=1e3;function Yi(){return typeof process.getuid=="function"?process.getuid():void 0}function Vt(d,e){let t=Yi();if(t!==void 0&&d.uid!==t)throw new Error(`E1_STATE_FOREIGN_OWNER: ${e}`)}function Xi(d){C.mkdirSync(d,{recursive:!0,mode:448});let e=C.lstatSync(d);if(!e.isDirectory()||e.isSymbolicLink())throw new Error(`E1_STATE_ROOT_NOT_PRIVATE_DIRECTORY: ${d}`);Vt(e,d),process.platform!=="win32"&&C.chmodSync(d,448)}function Wi(d,e){let t=te.dirname(d);Xi(t);let i=`${JSON.stringify(e)}
44
- `;if(Buffer.byteLength(i,"utf8")>Ut)throw new Error(`E1_STATE_TOO_LARGE: ${d}`);let s=te.join(t,`.${te.basename(d)}.${process.pid}.${He.randomUUID()}.tmp`),n=C.constants.O_NOFOLLOW??0,r=null;try{r=C.openSync(s,C.constants.O_WRONLY|C.constants.O_CREAT|C.constants.O_EXCL|n,384),C.writeFileSync(r,i,{encoding:"utf8"}),C.fsyncSync(r),C.closeSync(r),r=null,process.platform!=="win32"&&C.chmodSync(s,384),C.renameSync(s,d),process.platform!=="win32"&&C.chmodSync(d,384);try{let o=C.openSync(t,C.constants.O_RDONLY);try{C.fsyncSync(o)}finally{C.closeSync(o)}}catch{}}finally{r!==null&&C.closeSync(r);try{C.unlinkSync(s)}catch(o){if(o.code!=="ENOENT")throw o}}}function zi(d){let e;try{e=C.lstatSync(d)}catch(s){if(s.code==="ENOENT")return null;throw s}if(!e.isFile()||e.isSymbolicLink())throw new Error(`E1_STATE_NOT_REGULAR_FILE: ${d}`);if(Vt(e,d),process.platform!=="win32"&&(e.mode&63)!==0)throw new Error(`E1_STATE_PERMISSIONS_LOOSE: ${d}`);if(e.size>Ut)throw new Error(`E1_STATE_TOO_LARGE: ${d}`);let t=C.constants.O_NOFOLLOW??0,i=C.openSync(d,C.constants.O_RDONLY|t);try{let s=C.fstatSync(i);if(Vt(s,d),!s.isFile()||e.dev!==s.dev||e.ino!==s.ino)throw new Error(`E1_STATE_FILE_CHANGED_DURING_OPEN: ${d}`);if(s.size>Ut)throw new Error(`E1_STATE_TOO_LARGE: ${d}`);return JSON.parse(C.readFileSync(i,{encoding:"utf8"}))}finally{C.closeSync(i)}}function Q(d){return d!==null&&typeof d=="object"&&!Array.isArray(d)}function x(d,e=256*1024){return typeof d=="string"&&Buffer.byteLength(d,"utf8")<=e}function Zi(d){if(!Q(d)||!x(d.promptId,512)||!x(d.ownerToken,512)||!x(d.sessionId,1024)||d.producerKind!=="PLUGIN_APPROVAL"||d.agentType!==void 0&&d.agentType!=="CODEX"||d.title!==void 0&&!x(d.title,4096)||typeof d.mobileActionable!="boolean"||typeof d.raisedAtMs!="number"||!Number.isFinite(d.raisedAtMs))return!1;try{return(0,Ji.deriveOpenPromptId)(d.ownerToken)===d.promptId}catch{return!1}}function En(d){if(!Q(d)||!Zi(d.record))return!1;for(let e of["contentPlain","resolutionDedupeKey","resolutionCompletionKey","resolutionCallId","suppressedObserverSnapshotKey"])if(d[e]!==void 0&&!x(d[e]))return!1;return!(d.metadataPlain!==void 0&&!Q(d.metadataPlain)||d.suppressTmuxObserverUntilResolved!==void 0&&typeof d.suppressTmuxObserverUntilResolved!="boolean")}function es(d){return Q(d)&&Zi(d.record)&&x(d.resolutionAt,128)&&!Number.isNaN(Date.parse(d.resolutionAt))&&typeof d.attempts=="number"&&Number.isSafeInteger(d.attempts)&&d.attempts>=0}function ts(d){if(!Q(d)||d.nativeQuestionTitleSha256!==void 0&&(typeof d.nativeQuestionTitleSha256!="string"||!/^[a-f0-9]{64}$/.test(d.nativeQuestionTitleSha256))||!x(d.promptId,512)||!["yes_no","numbered","text","queued_question"].includes(String(d.kind))||!Array.isArray(d.options)||d.options.length>100||!d.options.every(i=>Q(i)&&x(i.number,32)&&x(i.text,32*1024)&&(i.description===void 0||x(i.description,32*1024))&&(i.preview===void 0||x(i.preview,32*1024)))||!Q(d.submitMap)||!Object.entries(d.submitMap).every(([i,s])=>x(i,128)&&x(s,32*1024))||!x(d.promptText)||typeof d.createdAt!="number"||!Number.isFinite(d.createdAt)||!["permission_hook","tmux","heuristic","queued_question"].includes(String(d.source)))return!1;for(let i of["callId","dedupeKey","completionKey","ownerSessionId","observerMatchKey","observerPromptHash","terminalMenuIdentity"])if(d[i]!==void 0&&!x(d[i],32*1024))return!1;if(d.requiresFollowUpText!==void 0&&typeof d.requiresFollowUpText!="boolean")return!1;let e=d.preemptedQueuedQuestionId!==void 0,t=d.preemptedQueuedQuestionAt!==void 0;if(e!==t||e&&(!x(d.preemptedQueuedQuestionId,512)||d.preemptedQueuedQuestionId.trim().length===0||typeof d.preemptedQueuedQuestionAt!="number"||!Number.isFinite(d.preemptedQueuedQuestionAt)||d.preemptedQueuedQuestionAt<=0))return!1;if(d.allQuestions!==void 0){if(!Array.isArray(d.allQuestions)||d.allQuestions.length>100)return!1;for(let i of d.allQuestions){if(!Q(i)||!x(i.question,32*1024)||!Array.isArray(i.options)||i.options.length>100||i.header!==void 0&&!x(i.header,1024)||i.multiSelect!==void 0&&typeof i.multiSelect!="boolean")return!1;for(let s of i.options)if(typeof s=="string"){if(!x(s,32*1024))return!1}else if(Q(s)){if(!x(s.label,32*1024)||s.description!==void 0&&!x(s.description,32*1024)||s.preview!==void 0&&!x(s.preview,32*1024))return!1}else return!1}}return!0}function Pn(d){return Q(d)&&ts(d.prompt)&&x(d.content)&&Q(d.metadata)}function bn(d,e,t){if(!Q(d)||d.version!==1)throw new Error("E1_HANDOFF_UNSUPPORTED_VERSION");if(d.tmuxSession!==e||!x(d.backendSessionId,1024))throw new Error("E1_HANDOFF_INSTANCE_MISMATCH");if(typeof d.createdAtMs!="number"||!Number.isFinite(d.createdAtMs))throw new Error("E1_HANDOFF_INVALID_TIMESTAMP");if(d.createdAtMs>t+6e4||t-d.createdAtMs>wn)throw new Error("E1_HANDOFF_STALE");if(!Array.isArray(d.openRaises)||d.openRaises.length>ae||!d.openRaises.every(En))throw new Error("E1_HANDOFF_INVALID_OPEN_RAISES");if(!Array.isArray(d.pendingResolutions)||d.pendingResolutions.length>ae||!d.pendingResolutions.every(es))throw new Error("E1_HANDOFF_INVALID_PENDING_RESOLUTIONS");if(!Array.isArray(d.needsReRaisePromptIds)||d.needsReRaisePromptIds.length>ae||!d.needsReRaisePromptIds.every(s=>x(s,512)))throw new Error("E1_HANDOFF_INVALID_RERAISE_IDS");if(!Array.isArray(d.permissionOccurrences)||d.permissionOccurrences.length>ae)throw new Error("E1_HANDOFF_INVALID_OCCURRENCES");if(!d.permissionOccurrences.every(s=>Array.isArray(s)&&s.length===2&&x(s[0],256*1024)&&Array.isArray(s[1])&&s[1].length<=ae&&s[1].every(n=>Q(n)&&x(n.occurrenceKey,512)&&typeof n.hookObserved=="boolean"&&typeof n.jsonlObserved=="boolean")))throw new Error("E1_HANDOFF_INVALID_OCCURRENCES");if(d.waitingPermissionRequests!==void 0&&(!Array.isArray(d.waitingPermissionRequests)||d.waitingPermissionRequests.length>ae||!d.waitingPermissionRequests.every(s=>Q(s)&&x(s.occurrenceKey,512)&&(s.dedupeKey===void 0||x(s.dedupeKey))&&Q(s.payload)&&s.payload.hook_event_name==="PermissionRequest"&&(s.payload.metadata===void 0||Q(s.payload.metadata)))))throw new Error("E1_HANDOFF_INVALID_WAITING_REQUESTS");if(d.pendingInteractivePrompt!==null&&!ts(d.pendingInteractivePrompt))throw new Error("E1_HANDOFF_INVALID_ACTIVE_PROMPT");if(!Array.isArray(d.queuedInteractivePrompts)||d.queuedInteractivePrompts.length>ae||!d.queuedInteractivePrompts.every(Pn))throw new Error("E1_HANDOFF_INVALID_QUEUED_PROMPTS");if(!Array.isArray(d.resolvedApprovalDedupeKeys)||d.resolvedApprovalDedupeKeys.length>ae||!d.resolvedApprovalDedupeKeys.every(s=>Array.isArray(s)&&s.length===2&&x(s[0])&&typeof s[1]=="number"&&Number.isFinite(s[1])))throw new Error("E1_HANDOFF_INVALID_RESOLVED_KEYS");if(d.historicalQueuedQuestionPromptIds!==void 0&&(!Array.isArray(d.historicalQueuedQuestionPromptIds)||d.historicalQueuedQuestionPromptIds.length>ae||!d.historicalQueuedQuestionPromptIds.every(s=>x(s,512))))throw new Error("E1_HANDOFF_INVALID_HISTORICAL_QUESTION_IDS");return d}function Rn(d){if(!Q(d)||d.version!==1||!es(d.pending))throw new Error("E1_RESOLUTION_OUTBOX_INVALID_RECORD");if(typeof d.updatedAtMs!="number"||!Number.isFinite(d.updatedAtMs))throw new Error("E1_RESOLUTION_OUTBOX_INVALID_TIMESTAMP");return d}var It=class{constructor(e={}){let t=Yi()??"nouid";this.handoffRoot=e.handoffRoot??te.join(St.tmpdir(),`codevibe-codex-handoff-${t}`),this.resolutionRoot=e.resolutionRoot??te.join(St.homedir(),".codevibe","codex","e1-resolution-outbox"),this.now=e.now??Date.now}handoffPath(e){let t=He.createHash("sha256").update(e).digest("hex").slice(0,32);return te.join(this.handoffRoot,`${t}.json`)}resolutionPath(e){let t=He.createHash("sha256").update(e).digest("hex");return te.join(this.resolutionRoot,`${t}.json`)}writeHandoff(e){Wi(this.handoffPath(e.tmuxSession),e)}readHandoff(e){let t=zi(this.handoffPath(e));if(t===null)return null;try{return bn(t,e,this.now())}catch(i){if(i.message==="E1_HANDOFF_STALE")return this.removeHandoff(e),null;throw i}}removeHandoff(e){try{C.unlinkSync(this.handoffPath(e))}catch(t){if(t.code!=="ENOENT")throw t}}writeResolution(e){Wi(this.resolutionPath(e.record.promptId),{version:1,updatedAtMs:this.now(),pending:e})}removeResolution(e){try{C.unlinkSync(this.resolutionPath(e))}catch(t){if(t.code!=="ENOENT")throw t}}readResolutions(){let e;try{Xi(this.resolutionRoot),e=C.readdirSync(this.resolutionRoot).filter(s=>s.endsWith(".json"))}catch(s){if(s.code==="ENOENT")return{records:[],rejected:[]};throw s}let t=[],i=[];for(let s of e.slice(0,ae)){let n=te.join(this.resolutionRoot,s);try{let r=zi(n);if(r!==null){let o=Rn(r).pending;if(te.basename(this.resolutionPath(o.record.promptId))!==s)throw new Error("E1_RESOLUTION_OUTBOX_IDENTITY_MISMATCH");t.push(o)}}catch(r){i.push({file:n,reason:r instanceof Error?r.message:String(r)})}}return e.length>ae&&i.push({file:this.resolutionRoot,reason:`E1_RESOLUTION_OUTBOX_RECORD_LIMIT: ${e.length}`}),{records:t,rejected:i}}};var ds=(0,jt.promisify)(Rt.exec),_n=(0,jt.promisify)(Rt.execFile),Cn="/quit",ge="CODEVIBE_CODEX_TMUX_SESSION",je="CODEVIBE_CODEX_DAEMON_RECOVERY",Nn=1e3,An=1e4,wt=3,On=100,ls=["SIGINT","SIGTERM","SIGHUP"],xn=600*1e3,Qt=30*1e3,kn=/^(?:[a-z0-9]|esc|escape)$/;function rs(d,e){let t=d?.[e];return typeof t=="string"?t:Buffer.isBuffer(t)?t.toString("utf8"):""}function cs(d){if(typeof d?.code!="number")return"unknown";let e=`${rs(d,"stderr")}
45
- ${rs(d,"stdout")}`;return/^can't find session:/m.test(e)||/^no server running on /m.test(e)||/^error connecting to .* \((?:No such file or directory|Connection refused)\)$/m.test(e)?"absent":"unknown"}async function Dn(d,e){let t=async(i,s)=>{try{await ds(i)}catch(n){c.warn("tmux send-keys failed during self-terminate",{sessionName:d,label:s,error:String(n)})}};await t(`tmux send-keys -t "${d}" C-c`,"ctrl-c"),await new Promise(i=>setTimeout(i,200)),await t(`tmux send-keys -t "${d}" -l "${e}"`,"quit-text"),await new Promise(i=>setTimeout(i,500)),await t(`tmux send-keys -t "${d}" Enter`,"enter")}var Et=class extends Error{constructor(){super("NATIVE_BACKEND_RETIRED"),this.name="NativeBackendRetiredError"}};function Ge(d){let e=d.split(`
46
- `),t=r=>/^[\s>]*\d+\.\s/.test(r),i=-1;for(let r=e.length-1;r>=0;r-=1)if(/^\s*\$\s+/.test(e[r])){i=r;break}if(i===-1)return;let s=e[i].trim().match(/^\$\s+(.+)$/);if(!s?.[1]?.trim())return;let n=[s[1].trim()];for(let r=i+1;r<e.length;r+=1){let o=e[r];if(t(o)||/^\s*$/.test(o)||/^\s*\$\s+/.test(o))break;n.push(o.trim())}return n.length>0?n:void 0}function us(d){let e=Ge(d);if(!e)return;let t=e.join(" ").trim();return t.length>0?t:void 0}function Pt(d,e){return Fn(d,e).has(e)}function Fn(d,e){if(d.length===0)return new Set;let t=e,i=new Set([d[0]]);for(let s of d.slice(1)){let n=s,r=new Set;for(let o of i)for(let a of[""," ",`
47
- `]){let l=`${o}${a}${n}`;t.startsWith(l)&&r.add(l)}if(r.size===0)return new Set;i=r}return i}function Mn(d,e){if(!d||!e)return!1;if(hs(d,e))return!0;let t=Ge(d);if(t&&Pt(t,e))return!0;let i=d.split(/\r?\n/);for(let s=0;s<i.length;s++)if(/^\s*\$\s+/.test(i[s])){let n=i.slice(s).join(`
48
- `),r=Ge(n);if(r&&Pt(r,e))return!0}return!1}function Ln(d,e,t){let i=/^\[\u2026\s+\d+\s+lines\]\s+ctrl\s*\+\s*a\s+view\s+all$/i,s=d.split(`
49
- `).map(n=>n.trim()).filter(Boolean);return s.length<2||!i.test(s[s.length-1])||!t?!1:hs(t,e)}function hs(d,e){let t=Ht(e),i=fs(d,"2");if(!t||!i)return!1;let s=new Set;for(let n of gs(i)){let r=n.match(/^Yes, and don't ask again for commands that start with `([^`]*)`\s*\(p\)$/);if(!r)continue;let o=Ht(r[1]);o&&JSON.stringify(o)===JSON.stringify(t)&&s.add(JSON.stringify(o))}return s.size===1}function ms(d,e,t){let i=d.find(m=>m.number==="2");if(!i||!(/don't ask again|persist/i.test(i.text)||d.length>=3&&d.some(m=>m.number==="3")))return d;if(!(/\(p\)\s*$/i.test(i.text)?i:null))return null;let r="Yes, and don't ask again for commands that start with",o="Yes, and don't ask again (p)",a=fs(t,"2");if(!a)return null;let l=gs(a);if(l.has(o))return d.map(m=>m.number==="2"?{...m,text:o}:m);if(!e)return null;let p=new Map;for(let m of l){let h=m.match(/^Yes, and don't ask again for commands that start with `([^`]*)`\s*\(p\)$/);if(!h)continue;let I=Ht(h[1]);!I||!Bn(I,e)||p.set(JSON.stringify(I),I)}if(p.size!==1)return null;let f=[...p.values()][0],u=qn(f);return d.map(m=>m.number==="2"?{...m,text:`${r} \`${u}\` (p)`}:m)}function fs(d,e){if(!d)return null;let t=(0,M.normalizeSnapshot)(d).split(`
50
- `).map(o=>o.trim()),i=new RegExp(`^(?:[>\u203A\u276F\u25B8\u25B6\u279C\u27A4*\u25CF]\\s*)?${e}\\.\\s+(.*)$`),s=-1,n="";for(let o=t.length-1;o>=0;o-=1){let a=t[o].match(i);if(a){s=o,n=a[1];break}}if(s<0)return null;let r=[n];for(let o=s+1;o<t.length&&!(/^(?:[>›❯▸▶➜➤*●]\s*)?\d+\.\s+/.test(t[o])||!t[o]||(r.push(t[o]),/\(p\)\s*$/i.test(t[o])));o+=1);return r.some(o=>/\(p\)\s*$/i.test(o))?r:null}function gs(d){if(d.length===0||d.length>13)return new Set;let e=new Set([d[0]]);for(let t of d.slice(1)){let i=new Set;for(let s of e)i.add(`${s}${t}`),i.add(`${s} ${t}`);e=i}return e}function Ht(d){try{let e=(0,$t.parse)(d,t=>`\${${t}}`);return e.every(t=>typeof t=="string")?e:null}catch{return null}}function qn(d){return d.map(e=>/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)?e:`'${e.replace(/'/g,`'"'"'`)}'`).join(" ")}function os(d){return d.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Bn(d,e){if(d.length===0)return!1;let t;try{t=(0,$t.parse)(e,s=>`\${${s}}`)}catch{return!1}let i=[[]];for(let s of t){if(typeof s=="string"){i[i.length-1].push(s);continue}if("op"in s&&["&&","||",";","|","|&","&"].includes(s.op)){i.push([]);continue}return!1}return i.some(s=>d.every((n,r)=>s[r]===n))}var bt=class d{constructor(e){this.nativeAuthority=e;this.nativeRuntime=null;this.nativeControlOwner=null;this.nativeReplacementToken=null;this.nativeAdmissionToken=null;this.nativeDegraded=!1;this.nativeReplacementGate=null;this.nativeQuestionFrame=null;this.nativeMaintenance=null;this.nativeReceiptWork=new Map;this.tuiGemmaPort=null;this.sessionState=null;this.unsubscribe=null;this.sessionKey=null;this.sessionIsEncrypted=!1;this.sessionKeyGen=null;this.e1PromptRaises=new Map;this.e1PendingResolutions=new Map;this.e1ResolutionInFlight=new Map;this.e1RaiseInFlight=new Map;this.acknowledgedQueuedQuestionRaises=new WeakSet;this.e1NeedsReRaise=new Set;this.e1RetirementOrphans=new Map;this.e1ContentKeyIndex=new Map;this.e1TtlRefreshTimer=null;this.toolActivity=null;this.toolActivityStartPromise=null;this.toolActivityLegacyRecorders=new Map;this.pendingInteractivePrompt=null;this.promptGeneration=0;this.queuedInteractivePrompts=[];this.isInitializingSession=!1;this.bufferedLogEntries=[];this.logEntryChain=Promise.resolve();this.nativeSourceSelection=null;this.nativeSourceOwners=new Map;this.nativeSourceRetryTimer=null;this.hookEventChain=Promise.resolve();this.hooksActive=!1;this.hooksCompatibilityNoticeSent=!1;this.permissionRequestHookInFlight=null;this.queuedPermissionRequestDedupeKeys=new Map;this.queuedPermissionRequestSessionCounts=new Map;this.queuedPermissionRequestRegistrations=new Map;this.waitingPermissionRequests=new Map;this.permissionRequestOccurrencesByCompletionKey=new Map;this.deferredTmuxPromptCandidates=new Map;this.recoveryPermissionReplay=null;this.resolvedApprovalDedupeKeys=new Map;this.queuedQuestionCallIds=new Set;this.historicalQueuedQuestionPromptIds=new Set;this.subscribedSessionId=null;this.subscribedSessionState=null;this.terminalInputChain=Promise.resolve();this.terminalInputBlockedStates=new WeakSet;this.mobilePromptDeduper=new ft({expiryMs:1e4});this.launchSessionInitPromise=null;this.sessionStartedInitPromise=null;this.bootstrapSessionId=null;this.recoveryBootstrapOwnerBound=!1;this.resumeBackendSession=g.resumeOrCreateSession;this.sessionBootstrapFailureCount=0;this.sessionBootstrapRetryAt=0;this.retiredSessionRecoveryPromise=null;this.lifecycleGeneration=0;this.isStopping=!1;this.stopPromise=null;this.terminalRetirementRequested=!1;this.teardownStepsTimedOut=[];this.retirementOwed=!1;this.tmuxLifecycleTimer=null;this.tmuxLifecycleCheckInFlight=!1;this.tmuxLifecycleObservedAlive=!1;this.tmuxLifecycleInitDeadlineMs=Number.POSITIVE_INFINITY;this.v1Bridge=new yt;this.orchestrationClient=null;this.userDecisionUnsubscribe=null;this.tmuxParseInFlight=new Map;this.tmuxParseResultCache=new Map;this.cacheGeneration=0;this.sessionWatcher=new ot({restoreCursor:(t,i)=>this.retryNativeAdmission(()=>this.restoreNativeSource(t,i)),beforeGap:(t,i)=>this.retryNativeAdmission(()=>this.admitNativeSourceGap(t,i)),beforeEntry:(t,i)=>this.retryNativeAdmission(()=>this.admitNativeSourceEntry(t,i))}),e||(this.httpApi=new mt,this.approvalDetector=new ct,this.promptResponder=new pt,this.tmuxPaneObserver=new Qe),this.e1DurableState=new It({handoffRoot:process.env.CODEVIBE_CODEX_HANDOFF_ROOT,resolutionRoot:process.env.CODEVIBE_CODEX_E1_OUTBOX_ROOT})}hasNativeAuthority(){return this.nativeAuthority!==void 0}receiveNativeReceipt(e){let t=this.nativeAuthority,i=e;if(!t||this.isStopping||!process.connected||process.ppid!==t.record.launcher.pid||!i||i.instanceId!==t.record.instanceId)return;if(i.type==="CODEVIBE_NATIVE_RECEIPTS_UNAVAILABLE"){this.degradeNativeControl("NATIVE_RECEIPTS_UNAVAILABLE");return}if(i.type!=="CODEVIBE_NATIVE_RECEIPT")return;let s;try{t.assertCurrent(),s=st(i.receipt,t.record.instanceId)}catch{c.warn("Retained native receipt refused",{code:"NATIVE_RECEIPT_INVALID"});return}if(this.nativeReceiptWork.has(s.digest))return;let n=o=>{try{t.assertCurrent(),process.connected&&process.ppid===t.record.launcher.pid&&process.send?.({type:"CODEVIBE_NATIVE_RECEIPT_ACK",instanceId:t.record.instanceId,digest:s.digest,consumed:o},void 0,void 0,()=>{})}catch{}},r=(async()=>{let o=this.nativeReplacementGate;o&&await o.ready;let a=this.nativeControlOwner;if(!a||this.isStopping){n(!1);return}let l=await a.adapter.reconcileRetainedApproval(s);n(l)})().catch(()=>{c.warn("Retained native receipt pending",{code:"NATIVE_RECEIPT_NOT_PERSISTED"}),n(!1)});this.nativeReceiptWork.set(s.digest,r),r.then(()=>{this.nativeReceiptWork.get(s.digest)===r&&this.nativeReceiptWork.delete(s.digest)})}pollNativeReceipts(){try{!this.isStopping&&this.nativeAuthority&&process.connected&&process.ppid===this.nativeAuthority.record.launcher.pid&&(this.nativeAuthority.assertCurrent(),process.send?.({type:"CODEVIBE_NATIVE_RECEIPTS_POLL",instanceId:this.nativeAuthority.record.instanceId},void 0,void 0,()=>{}))}catch{}}setTuiGemmaPort(e){this.tuiGemmaPort=e}static{this.E1_TTL_REFRESH_MS=300*1e3}async start(){if(!this.nativeAuthority)throw new Error("Native launcher authority required;launch with codevibe --agent codex.");if(!["development","production"].includes((0,g.getEnvironment)()))throw Error("NATIVE_ENVIRONMENT_UNSUPPORTED");if(c.info("Starting CodeVibe Codex companion server",{environment:(0,g.getEnvironment)()}),this.appSyncClient=new g.AppSyncClient,!await this.appSyncClient.authenticateWithStoredTokens()){let t=(0,g.describeStoredAuthFailure)(this.appSyncClient.getLastAuthFailureKind(),this.appSyncClient.getLastAuthFailureDetail());c.error("Authentication with stored credentials failed",{kind:this.appSyncClient.getLastAuthFailureKind(),exitCode:t.exitCode}),console.error(t.message),process.exit(t.exitCode)}c.info("Authenticated successfully",{userId:this.appSyncClient.getCurrentUserId(),email:this.appSyncClient.getCurrentUserEmail()});try{let t=this.appSyncClient.getCurrentUserId(),i=AbortSignal.timeout(5e3),s=new Promise((o,a)=>i.addEventListener("abort",()=>a(new Error("status read timed out")),{once:!0})),n=await Promise.race([this.appSyncClient.getSubscriptionStatus(i),s]);if(this.appSyncClient.getCurrentUserId()!==t)throw new Error("account changed during read");n?.tier==="FREE"&&(c.info("User is on FREE tier: disabling hosted TUI parser port and using fast regex parser (Codex R1-F6, R2-F6)",{tier:n.tier}),this.tuiGemmaPort=null);let r=await Promise.race([this.appSyncClient.getCompanionSyncState(i),s]);if(this.appSyncClient.getCurrentUserId()!==t)throw new Error("account changed during read");if(n.tier!==r.tier)throw new Error("tier changed during read");c.info("Standalone Companion sync status",{tier:r.tier,protocol:r.protocol,syncState:r.usage?.syncState??null,resetAtEpochMs:r.resetAtEpochMs})}catch{c.warn("Standalone Companion sync status unavailable; cloud admission remains authoritative")}await this.restorePendingE1ResolutionsFromOutbox(),await(0,g.registerDeviceEncryptionKey)(this.appSyncClient,c),(0,g.startDeviceKeyWatcher)(this.appSyncClient,c),(0,g.pushDetectedAgents)(this.appSyncClient,c).catch(t=>{c.warn("Failed to update available agents (non-fatal)",{error:t?.message})}),this.setupEventHandlers(),this.sessionWatcher.start(),this.nativeRuntime=new Xe({authority:this.nativeAuthority,pluginVersion:is().version,recoveryThreadId:process.env[je]==="1"?process.env.CODEVIBE_CODEX_NATIVE_THREAD:void 0,onRoot:t=>this.bindNativeRoot(t),onMessage:t=>this.handleNativeMessage(t),onFailure:(t,i)=>this.degradeNativeControl(t,i)}),await this.nativeRuntime.start(),process.send?.({type:"CODEVIBE_NATIVE_READY",instanceId:this.nativeAuthority.record.instanceId}),c.info("CodeVibe Codex companion server started")}degradeNativeControl(e,t){this.isStopping||(this.nativeDegraded=!0,(e!=="NATIVE_CONTROL_INITIALIZATION_FAILED"||!this.nativeControlOwner?.adapter.isActivationPending)&&this.nativeControlOwner?.adapter.stopAdmission(),this.sessionState&&this.appSyncClient.stopHeartbeat(this.sessionState.sessionId),c.warn("Native mobile control unavailable;desktop remains independent",{code:e,...t?{handlerFailure:t}:{}}),e!=="NATIVE_CONTROL_INITIALIZATION_FAILED"&&process.send?.({type:"CODEVIBE_NATIVE_OBSERVER_DEGRADED",instanceId:this.nativeAuthority?.record.instanceId}))}async bindNativeRoot(e){if(!this.nativeAuthority||this.isStopping)throw Error("NATIVE_ROOT_OWNER_CHANGED");this.nativeAuthority.assertCurrent(),c.info("Native root binding started",{hasTranscript:e.path!==null}),process.send?.({type:"CODEVIBE_NATIVE_BOUND",instanceId:this.nativeAuthority.record.instanceId,threadId:e.id}),this.sessionState&&this.sessionState.codexSessionId!==e.id&&await this.endActiveSession("new-codex-session-started"),await this.ensureSessionStarted({id:e.id,cwd:e.cwd,timestamp:new Date(e.createdAt*1e3).toISOString(),cli_version:e.cliVersion,model_provider:e.modelProvider,source:"native-app-server",originator:"codevibe-native-observer",instructions:null});let t=this.sessionState;if(!t||t.codexSessionId!==e.id||this.nativeControlOwner?.state!==t)throw Error("NATIVE_ROOT_BINDING_INCOMPLETE");if(e.path&&this.sessionWatcher.getActiveLogFile()!==e.path){let i=await this.sessionWatcher.bindToSessionTranscript(e.path,e.id);c.info("Native transcript binding result",{status:i.status,...i.status==="rejected"?{reason:i.reason}:{}})}else c.info("Native transcript binding result",{status:e.path?"already_bound":"no_transcript_yet"});process.send?.({type:"CODEVIBE_NATIVE_BOUND",instanceId:this.nativeAuthority.record.instanceId,threadId:e.id})}async initializeNativeControl(e){let t=this.nativeRuntime,i=this.nativeAuthority;if(!t||!i||!e.codexSessionId)throw Error("NATIVE_ROOT_BINDING_INCOMPLETE");if(this.nativeControlOwner?.state===e)return;let s=e.userId,n=(0,g.getEnvironment)(),r=await g.keychainManager.getDeviceIdentity();if(n!=="development"&&n!=="production")throw Error("NATIVE_ENVIRONMENT_UNSUPPORTED");if(!r)throw Error("NATIVE_DEVICE_IDENTITY_UNAVAILABLE");let o=()=>{if(i.assertCurrent(),this.appSyncClient.getCurrentUserId()!==s||(0,g.getEnvironment)()!==n)throw Error("NATIVE_ACCOUNT_CHANGED")},a=await this.appSyncClient.getSession(e.sessionId);if(o(),!a?.sessionGenerationId||!a.sessionKeyGen||a.userId!==s||a.status!==g.SessionStatus.ACTIVE)throw Error("NATIVE_SCOPE_UNAVAILABLE");let l=await this.selectNativeSourceTransport(e);if(o(),l.protocol!=="SYNC_V2"||l.sessionScope.sessionGenerationId!==a.sessionGenerationId)throw Error("NATIVE_SIGNED_SCOPE_UNAVAILABLE");let p={sessionId:e.sessionId,sessionGenerationId:a.sessionGenerationId,expectedSessionKeyGen:a.sessionKeyGen},f=new as.CodexNativeStateStore({identity:{userId:s,environment:n,deviceId:r.deviceId,nativeThreadId:e.codexSessionId},assertAccount:o,readPrivateKey:async()=>{let h=await g.keychainManager.getDeviceIdentity();if(o(),!h||h.deviceId!==r.deviceId||h.publicKey!==r.publicKey)throw Error("NATIVE_DEVICE_IDENTITY_CHANGED");return h.privateKey},assertActiveScope:async h=>{await this.assertNativeActiveScope(e,h,o,s)}});this.nativeAdmissionToken?.state!==e&&(this.nativeAdmissionToken={state:e,token:this.nativeReplacementToken??(0,ye.v4)()});let u={token:this.nativeAdmissionToken.token,pid:process.pid,host:$e.hostname(),scope:p};await f.claim(u),this.nativeReplacementToken=null;let m=new nt({store:f,owner:u,threadId:e.codexSessionId,native:t.client,assertCurrent:()=>{if(o(),!this.isExpectedSessionStateCurrent(e)||t.thread?.id!==e.codexSessionId)throw Error("NATIVE_SCOPE_CHANGED")},decode:h=>this.decodeNativeMobileInput(h,e),updateStatus:this.appSyncClient.updateEventStatus.bind(this.appSyncClient),publish:(h,I,y)=>this.publishNativePrompt(e,h,I,y),publishRejectedInput:h=>{let I=JSON.parse(h.raiseJson),y=h.reason==="ALREADY_ANSWERED"?"This request already has a response. Your reply was not applied.":"Your reply was not applied to a native control. Reopen the current prompt and try again. If this continues, update the CodeVibe app.",w={native_input_rejected:!0,reason:h.reason,rejectedEventId:h.event.eventId},v={sessionId:e.sessionId,type:g.EventType.NOTIFICATION,source:g.EventSource.DESKTOP,content:y,metadata:w,...(0,g.raiseFieldsFromRecord)(I),timestamp:(0,g.prepareEventTimestamp)({orderingKey:e.sessionId})};return!this.isExpectedSessionStateCurrent(e)||h.scope.sessionId!==e.sessionId?Promise.resolve("CLOSED"):this.appSyncClient.publishCompanionPrompt(v,async()=>{let S=this.encryptForEmit(y,w,g.EventType.NOTIFICATION,e.sessionId);return!S||!this.isExpectedSessionStateCurrent(e)?!1:(await this.appSyncClient.createEvent({...v,content:S.content,metadata:S.metadata,isEncrypted:S.isEncrypted}),!0)})},resolve:h=>this.appSyncClient.resolveCompanionPrompt(h),isFreshQuestion:async(h,I,y)=>this.sessionState===e&&this.nativeQuestionFrame?.threadId===h&&this.nativeQuestionFrame.turnId===I&&this.nativeQuestionFrame.itemId===y,onFailure:h=>{c.warn("Native control operation retained",{code:h})},isCurrentControl:h=>t.isCurrentControl(h),hasPendingControl:()=>t.hasPendingControl(),deferActivation:!0});this.nativeControlOwner={state:e,store:f,owner:u,adapter:m};for(let h of t.controlFacts())await m.observe(h);this.nativeReplacementGate||(await m.prepareRehomes(),m.activate(),await m.recover()),this.pollNativeReceipts(),this.startE1TtlRefresh()}async assertNativeActiveScope(e,t,i,s=e.userId){let n=await this.appSyncClient.getSession(t.sessionId);if(i(),e.sessionId!==t.sessionId||!n||n.sessionId!==t.sessionId||n.userId!==s||n.sessionGenerationId!==t.sessionGenerationId||n.sessionKeyGen!==t.expectedSessionKeyGen)throw Error("NATIVE_SCOPE_CHANGED");if(n.status!==g.SessionStatus.ACTIVE)throw n.status!==g.SessionStatus.INACTIVE?Error("NATIVE_SCOPE_CHANGED"):(!this.isStopping&&this.sessionState===e&&(this.nativeDegraded=!0,this.nativeControlOwner?.state===e&&this.nativeControlOwner.adapter.stopAdmission(),this.appSyncClient.stopHeartbeat(e.sessionId),this.recoverRetiredBackendSession(e.sessionId).catch(()=>this.degradeNativeControl("NATIVE_RETIREMENT_RECOVERY_FAILED"))),new Et)}publishNativePrompt(e,t,i,s){if(!this.isExpectedSessionStateCurrent(e)||t.scope.sessionId!==e.sessionId)return Promise.resolve("CLOSED");let n=JSON.parse(t.raiseJson),r=n.mobileActionable?g.EventType.INTERACTIVE_PROMPT:g.EventType.NOTIFICATION,o={sessionId:e.sessionId,type:r,source:g.EventSource.DESKTOP,...i,...(0,g.raiseFieldsFromRecord)(n),timestamp:(0,g.prepareEventTimestamp)({orderingKey:e.sessionId})};return this.appSyncClient.publishCompanionPrompt(o,async()=>{let a=this.encryptForEmit(i.content,i.metadata,r,e.sessionId);return!a||!this.isExpectedSessionStateCurrent(e)?!1:(await this.appSyncClient.createEvent({...o,content:a.content,metadata:a.metadata,isEncrypted:a.isEncrypted}),!0)},{reRaiseToken:s})}async decodeNativeMobileInput(e,t){if(!this.isExpectedSessionStateCurrent(t)||e.sessionId!==t.sessionId)throw Error("NATIVE_SCOPE_CHANGED");let i=t.encryptionSnapshot.sessionKey;if(e.isEncrypted&&!i)throw Error("NATIVE_SESSION_KEY_UNAVAILABLE");let s=e.isEncrypted?g.cryptoService.decryptContent(e.content,i):e.content??"",n=typeof e.metadata=="string"?JSON.parse(e.metadata):e.metadata;if(n?.encrypted){if(!i)throw Error("NATIVE_SESSION_KEY_UNAVAILABLE");n=g.cryptoService.decryptMetadata(n.encrypted,i)}let r=e.promptId??null,o=n?.promptId??null;if(r!==null&&o!==null&&r!==o)throw Error("NATIVE_QUESTION_MISMATCH");let a=r??o;if(a!==null&&(typeof a!="string"||!a.length))throw Error("NATIVE_QUESTION_MISMATCH");let l=[];for(let p of e.attachments??[]){if(!p.type.startsWith("image/"))throw Error("NATIVE_ATTACHMENT_UNSUPPORTED");let f=await this.downloadAttachment(p,t.sessionId,i,e.isEncrypted??!1);if(!f||!this.isExpectedSessionStateCurrent(t))throw Error("NATIVE_ATTACHMENT_UNAVAILABLE");l.push(f)}return{text:s,promptId:a,localImages:l}}async handleNativeMessage(e){let t=this.nativeReplacementGate;t&&await t.ready;let i=this.nativeControlOwner;if(!i||this.isStopping)return;let s=e.params;try{e.method==="item/completed"&&s?.item?.type==="agentMessage"&&s.item.delivery==="async"||await i.adapter.observe(e)}catch(n){if(!(n instanceof Et))throw n;return}["thread/status/changed","turn/started","turn/completed"].includes(e.method)&&this.maintainNativeControl().catch(()=>{})}maintainNativeControl(){if(this.nativeMaintenance)return this.nativeMaintenance;if(this.isStopping||!this.sessionState||this.nativeReplacementGate)return Promise.resolve();let e=this.sessionState,t=(async()=>{this.nativeControlOwner||await this.initializeNativeControl(e);let i=await this.nativeRuntime?.refreshMetadata();if(this.sessionState!==e||this.isStopping||(i&&await this.bindNativeRoot(i),this.sessionState!==e||this.isStopping))return;let s=this.nativeControlOwner?.adapter;if(s?.isActivationPending){for(let n of this.nativeRuntime.controlFacts())await s.observe(n);await s.prepareRehomes(),s.activate()}await this.pruneSettledNativePredecessor(e),this.pollNativeReceipts(),await this.nativeControlOwner?.adapter.recover(),this.nativeDegraded&&this.nativeControlOwner?.adapter.isAccepting&&(this.nativeDegraded=!1,await this.appSyncClient.startHeartbeat(e.sessionId))})();return this.nativeMaintenance=t,t.then(()=>{this.nativeMaintenance=null},()=>{this.nativeMaintenance=null}),t}async pruneSettledNativePredecessor(e){let t=this.nativeControlOwner;if(!t||t.state!==e||this.sessionState!==e||this.isStopping)return;let i=await t.store.snapshot(t.owner);if(this.nativeControlOwner!==t||this.sessionState!==e||this.isStopping)return;let s=i.scopes.find(n=>{if(n.state!=="CLOSED"||n.scope.sessionId===t.owner.scope.sessionId)return!1;let r=o=>o.scope.sessionId===n.scope.sessionId;return i.entries.some(o=>r(o)&&o.kind==="INPUT")||i.entries.filter(r).every(o=>o.kind==="RETIRED_EVIDENCE"&&o.outcome!=="UNKNOWN")&&i.controls.filter(r).every(o=>o.cloudResolved&&["RESOLVED","REHOMED"].includes(o.state))});if(s)try{let n=AbortSignal.timeout(1e3);i.entries.some(r=>r.kind==="INPUT"&&r.scope.sessionId===s.scope.sessionId)&&await t.store.retirePayloads(t.owner,s.scope,async()=>{if(this.nativeControlOwner!==t||this.sessionState!==e||this.isStopping)throw Error("NATIVE_SCOPE_CHANGED")},r=>this.appSyncClient.confirmDesktopSyncRetirement(r,n)),await t.store.pruneSettled(t.owner,s.scope,r=>this.appSyncClient.confirmDesktopSyncRetirement(r,n))}catch{c.warn("Native predecessor cleanup retained for the next existing maintenance call",{code:"NATIVE_PREDECESSOR_PRUNE_PENDING"})}}async createLaunchSession(){if(this.isStopping)return;if(process.env[je]==="1"){c.info("Recovery daemon deferring backend bootstrap until the native rollout is known");return}let e=this.lifecycleGeneration,t=process.env.CODEVIBE_CODEX_TMUX_SESSION;if(!t){c.warn("No CODEVIBE_CODEX_TMUX_SESSION \u2014 skipping launch session");return}let i;this.launchSessionInitPromise=new Promise(s=>{i=s});try{let s=process.env.CODEX_WORKING_DIRECTORY||process.cwd(),n=this.getOrCreateBootstrapSessionId(),r=this.appSyncClient.getCurrentUserId();c.info("Creating launch session",{sessionId:n,projectPath:s});let o=!1;try{let a=await(0,g.resumeOrCreateSession)({sessionId:n,userId:r,agentType:g.AgentType.CODEX,projectPath:s,metadata:{launchSession:!0}},this.appSyncClient,c);if(n=a.sessionId,!this.isLifecycleCurrent(e)){await this.retireCancelledBootstrap(n,"launch_session");return}this.sessionKey=a.sessionKey,this.sessionKeyGen=a.sessionKeyGen,this.sessionIsEncrypted=!!a.sessionKey,o=!0,this.sessionState={sessionId:n,userId:r,projectPath:s,cwd:s,createdAt:new Date,subscriptionActive:!1,metadata:{launchSession:!0},encryptionSnapshot:{sessionKey:a.sessionKey,sessionIsEncrypted:!!a.sessionKey},codexSessionId:t,codexLogFile:void 0},this.clearSessionBootstrapFailure(),this.bootstrapSessionId=null,await L("daemon_init_step_completed",{step:"session_resume_or_create",path:"launch_session"})}catch(a){if(!this.isLifecycleCurrent(e)){let l=this.authoritativeSessionIdFromError(a)??n;await this.retireCancelledBootstrap(l,"launch_session_error");return}await L("daemon_init_step_failed",{step:"session_resume_or_create",path:"launch_session",error_class:a?.name||"Error",error_message:a?.message||String(a)}),a?.code==="ENCRYPTED_SESSION_NO_KEY"&&(this.sessionIsEncrypted=!0,this.sessionKey=null),this.bindBootstrapIdentityFromError(a),this.recordSessionBootstrapFailure(a,"launch_session"),c.error("Failed to create/resume launch session (non-fatal)",{error:a})}if(!o)return;await L("daemon_init_step_completed",{step:"session_state_set",path:"launch_session"});try{this.subscribeToMobileEvents(n)?await L("daemon_init_step_completed",{step:"subscribe_mobile_events",path:"launch_session"}):await L("daemon_init_step_failed",{step:"subscribe_mobile_events",path:"launch_session",error_class:"SubscriptionSetupFailed",error_message:"subscribeToMobileEvents returned false"})}catch(a){await L("daemon_init_step_failed",{step:"subscribe_mobile_events",path:"launch_session",error_class:a?.name||"Error",error_message:a?.message||String(a)}),c.error("Failed to subscribe to mobile events for launch session",{error:a})}try{await this.appSyncClient.startHeartbeat(n)?await L("daemon_init_step_completed",{step:"heartbeat_start",path:"launch_session"}):(await L("daemon_init_step_failed",{step:"heartbeat_start",path:"launch_session",error_class:"InitialHeartbeatNotPersisted",error_message:"Backend did not confirm the initial heartbeat mutation"}),c.error("Initial launch-session heartbeat was not persisted",{sessionId:n}))}catch(a){await L("daemon_init_step_failed",{step:"heartbeat_start",path:"launch_session",error_class:a?.name||"Error",error_message:a?.message||String(a)}),c.error("Failed to start heartbeat for launch session",{error:a})}try{await this.subscribeToOnApplyUserDecision(n)}catch(a){c.error("Failed to subscribe to onApplyUserDecision for launch session (non-fatal)",{error:a})}this.startMobileEndWatcher(n),c.info("Launch session created",{sessionId:n})}finally{i()}}encryptForEmit(e,t,i,s){let n=this.sessionState;if(!n||n.sessionId!==s||!n.encryptionSnapshot)return c.warn("Dropping event from stale or unresolved session generation (#638)",{type:i,sessionId:s,currentSessionId:n?.sessionId}),null;let{sessionKey:r,sessionIsEncrypted:o}=n.encryptionSnapshot,a=(0,g.encryptForEmit)(r,o,e,t);return a===null&&c.error("No session key for ENCRYPTED session \u2014 dropping event (fail-closed, #638)",{type:i,sessionId:s}),a}newE1Raise(e,t,i,s){let{record:n}=(0,g.newPromptRaise)({sessionId:e,producerKind:"PLUGIN_APPROVAL",mobileActionable:t,agentType:"CODEX",...i!==void 0&&{title:i}});return this.e1PromptRaises.set(n.promptId,{record:n,...s?.dedupeKey!==void 0?{resolutionDedupeKey:s.dedupeKey}:{},...s?.completionKey!==void 0?{resolutionCompletionKey:s.completionKey}:{},...s?.callId!==void 0?{resolutionCallId:s.callId}:{}}),this.e1TtlRefreshTimer||this.startE1TtlRefresh(),n}stashE1RaiseContent(e,t,i){let s=this.e1PromptRaises.get(e);s&&(s.contentPlain=t,s.metadataPlain=i)}async emitSuppressedPromptCarrier(e,t,i){return this.publishE1Prompt(e,t,g.EventType.NOTIFICATION,"\u26A0\uFE0F A prompt is waiting in your desktop terminal, but its options could not be shown here. Please answer it on your desktop.",{e1SuppressedPrompt:!0},i)}publishE1Prompt(e,t,i,s,n,r){let o=(0,g.prepareEventTimestamp)({orderingKey:e}),a={sessionId:e,type:i,source:g.EventSource.DESKTOP,content:s,metadata:n,...(0,g.raiseFieldsFromRecord)(t),timestamp:o},l=this.e1PromptRaises.get(t.promptId),p=()=>l?.record===t&&(0,g.isOpenPromptRaise)(l,this.e1PromptRaises.get(t.promptId));if(!p())return Promise.resolve("CLOSED");let f=u=>(p()&&(i===g.EventType.INTERACTIVE_PROMPT&&n.isQueuedQuestion===!0&&l&&(u==="RERAISED"?this.acknowledgedQueuedQuestionRaises.add(l):this.acknowledgedQueuedQuestionRaises.delete(l)),u==="RETRY"?this.e1NeedsReRaise.add(t.promptId):(u==="RERAISED"||u==="OMITTED")&&this.e1NeedsReRaise.delete(t.promptId)),u);return this.trackE1Raise(t.promptId,this.appSyncClient.publishCompanionPrompt(a,async()=>{let u=this.encryptForEmit(s,n,i,e);return u?(await this.appSyncClient.createEvent({...a,content:u.content,metadata:u.metadata,...i===g.EventType.NOTIFICATION&&{notificationText:s},...u.isEncrypted?{isEncrypted:!0}:{}}),!0):!1},{reRaiseToken:r}).then(f,u=>{throw f("RETRY"),u}))}raiseSuppressedBadge(e,t,i={}){if(t){if(this.hasRecentlyResolvedApprovalDedupeKey(e,t)){c.debug("Skipping suppressed-prompt carrier; approval completed while producer was in flight",{sessionId:e,dedupeKey:t});return}let n=`${e}::${t}`,r=this.e1ContentKeyIndex.get(n);if(r&&this.e1PromptRaises.has(r)){if(i.suppressTmuxObserverUntilResolved){let o=this.e1PromptRaises.get(r);o&&(o.suppressTmuxObserverUntilResolved=!0,i.observerSnapshot&&(o.suppressedObserverSnapshotKey=this.buildObserverSnapshotMatchKey(i.observerSnapshot)))}return}r&&this.e1ContentKeyIndex.delete(n)}let s=this.newE1Raise(e,!1,void 0,t?{dedupeKey:t,completionKey:i.completionKey}:void 0);if(i.suppressTmuxObserverUntilResolved){let n=this.e1PromptRaises.get(s.promptId);n&&(n.suppressTmuxObserverUntilResolved=!0,i.observerSnapshot&&(n.suppressedObserverSnapshotKey=this.buildObserverSnapshotMatchKey(i.observerSnapshot)))}t&&this.e1ContentKeyIndex.set(`${e}::${t}`,s.promptId),this.emitSuppressedPromptCarrier(e,s).catch(n=>{c.error("E1: failed to emit suppressed-prompt badge carrier",{sessionId:e,promptId:s.promptId,error:n instanceof Error?n.message:String(n)})})}snapshotOpenE1(e){return[...this.e1PromptRaises.values()].filter(t=>t.record.sessionId===e).map(t=>({record:{...t.record},...t.contentPlain!==void 0&&{contentPlain:t.contentPlain},...t.metadataPlain!==void 0&&{metadataPlain:t.metadataPlain},...t.resolutionDedupeKey!==void 0&&{resolutionDedupeKey:t.resolutionDedupeKey},...t.resolutionCompletionKey!==void 0&&{resolutionCompletionKey:t.resolutionCompletionKey},...t.resolutionCallId!==void 0&&{resolutionCallId:t.resolutionCallId},...t.suppressTmuxObserverUntilResolved!==void 0&&{suppressTmuxObserverUntilResolved:t.suppressTmuxObserverUntilResolved},...t.suppressedObserverSnapshotKey!==void 0&&{suppressedObserverSnapshotKey:t.suppressedObserverSnapshotKey}}))}buildDaemonHandoffSnapshot(e){let t=process.env[ge];if(!t)throw new Error("E1_DAEMON_HANDOFF_MISSING_TMUX_SESSION");return{version:1,createdAtMs:Date.now(),tmuxSession:t,backendSessionId:e.sessionId,openRaises:this.snapshotOpenE1(e.sessionId),pendingResolutions:[...this.e1PendingResolutions.values()].map(i=>({record:{...i.record},resolutionAt:i.resolutionAt,attempts:i.attempts})),needsReRaisePromptIds:[...this.e1NeedsReRaise],permissionOccurrences:[...this.permissionRequestOccurrencesByCompletionKey.entries()].map(([i,s])=>[i,s.map(n=>({...n}))]),waitingPermissionRequests:[...this.waitingPermissionRequests.values()].filter(i=>i.ownerState===e).map(({occurrenceKey:i,dedupeKey:s,payload:n})=>({occurrenceKey:i,dedupeKey:s,payload:n})),pendingInteractivePrompt:this.pendingInteractivePrompt?{...this.pendingInteractivePrompt}:null,queuedInteractivePrompts:this.queuedInteractivePrompts.map(i=>({prompt:{...i.prompt},content:i.content,metadata:{...i.metadata}})),resolvedApprovalDedupeKeys:[...this.resolvedApprovalDedupeKeys.entries()].filter(([,i])=>i>Date.now()-Qt),historicalQueuedQuestionPromptIds:[...this.historicalQueuedQuestionPromptIds].filter(i=>typeof i=="string"&&i.trim().length>0&&Buffer.byteLength(i,"utf8")<=512).slice(-1e3)}}persistDaemonHandoffState(e){for(let i of this.e1PendingResolutions.values())this.e1DurableState.writeResolution(i);let t=this.buildDaemonHandoffSnapshot(e);this.e1DurableState.writeHandoff(t),c.info("E1: persisted daemon handoff state",{sessionId:e.sessionId,openPrompts:t.openRaises.length,pendingResolutions:t.pendingResolutions.length,completionQueues:t.permissionOccurrences.length})}async adoptDaemonHandoffState(e){if(process.env[je]!=="1")return!1;let t=process.env[ge];if(!t)return!1;let i=this.e1DurableState.readHandoff(t);if(!i)return!1;let s=this.sessionState;if(!s||s.sessionId!==e)throw new Error("E1_DAEMON_HANDOFF_WITHOUT_CURRENT_SESSION");for(let a of i.pendingResolutions)this.e1PendingResolutions.has(a.record.promptId)||this.e1PendingResolutions.set(a.record.promptId,{record:{...a.record},resolutionAt:a.resolutionAt,attempts:a.attempts}),this.e1DurableState.writeResolution(a);for(let a of i.openRaises){let l={...a,record:{...a.record},...a.metadataPlain!==void 0&&{metadataPlain:{...a.metadataPlain}}};this.e1PromptRaises.set(l.record.promptId,l),i.backendSessionId!==e&&this.e1RetirementOrphans.set(l.record.promptId,{...l,record:{...l.record}}),l.resolutionDedupeKey&&this.e1ContentKeyIndex.set(`${e}::${l.resolutionDedupeKey}`,l.record.promptId)}this.permissionRequestOccurrencesByCompletionKey=new Map(i.permissionOccurrences.map(([a,l])=>[a,l.map(p=>({...p}))])),this.e1NeedsReRaise=new Set(i.needsReRaisePromptIds);for(let a of i.waitingPermissionRequests??[])this.waitingPermissionRequests.set(a.occurrenceKey,{...a,ownerState:s,context:this.buildApprovalPromptContextFromHookPayload(a.payload)});this.pendingInteractivePrompt=i.pendingInteractivePrompt?{...i.pendingInteractivePrompt,ownerSessionId:e}:null;let n=this.pendingInteractivePrompt,r=n?.completionKey?this.permissionRequestOccurrencesByCompletionKey.get(n.completionKey):void 0;this.recoveryPermissionReplay=n?.source==="permission_hook"&&n.completionKey&&n.dedupeKey&&this.isPermissionRequestOccurrenceKey(n.dedupeKey)&&r?.some(a=>a.occurrenceKey===n.dedupeKey)?{ownerSessionId:e,completionKey:n.completionKey,occurrenceKey:n.dedupeKey}:null,this.queuedInteractivePrompts=i.queuedInteractivePrompts.map(a=>({prompt:{...a.prompt,ownerSessionId:e},content:a.content,metadata:{...a.metadata},ownerState:s}));let o=Date.now()-Qt;for(let[a,l]of i.resolvedApprovalDedupeKeys){if(l<=o)continue;let p=`${i.backendSessionId}::`,f=a.startsWith(p)?`${e}::${a.slice(p.length)}`:a;this.resolvedApprovalDedupeKeys.set(f,l)}if(i.historicalQueuedQuestionPromptIds)for(let a of i.historicalQueuedQuestionPromptIds)this.recordHistoricalQueuedQuestionId(a);return i.backendSessionId!==e&&await this.drainRetirementOrphans(e),await this.drainPendingE1Resolutions(),await this.drainPendingE1ReRaises(),(this.e1PromptRaises.size>0||this.e1PendingResolutions.size>0)&&this.startE1TtlRefresh(),this.e1DurableState.removeHandoff(t),c.info("E1: adopted daemon handoff state",{fromSessionId:i.backendSessionId,replacementSessionId:e,openPrompts:i.openRaises.length,pendingResolutions:i.pendingResolutions.length,completionQueues:i.permissionOccurrences.length}),!0}parkRetirementOrphans(e){for(let t of this.snapshotOpenE1(e))this.e1RetirementOrphans.set(t.record.promptId,t)}async drainRetirementOrphans(e){if(this.e1RetirementOrphans.size===0){this.e1PendingResolutions.size>0&&!this.e1TtlRefreshTimer&&this.startE1TtlRefresh();return}c.info("E1 (\xA76a-4): re-homing parked retirement-orphan prompts onto replacement session",{replacementSessionId:e,count:this.e1RetirementOrphans.size});for(let[t,i]of[...this.e1RetirementOrphans]){let n=this.e1PromptRaises.get(t)??{record:{...i.record},...i.contentPlain!==void 0&&{contentPlain:i.contentPlain},...i.metadataPlain!==void 0&&{metadataPlain:i.metadataPlain},...i.resolutionDedupeKey!==void 0&&{resolutionDedupeKey:i.resolutionDedupeKey},...i.resolutionCompletionKey!==void 0&&{resolutionCompletionKey:i.resolutionCompletionKey},...i.resolutionCallId!==void 0&&{resolutionCallId:i.resolutionCallId}};for(let[o,a]of this.e1ContentKeyIndex.entries())a===t&&this.e1ContentKeyIndex.delete(o);n.record.sessionId=e,this.e1PromptRaises.set(t,n),n.resolutionDedupeKey&&this.e1ContentKeyIndex.set(`${e}::${n.resolutionDedupeKey}`,t);let r=await this.reRaiseOneE1(e,n,{untilAck:!0});if(r!=="RERAISED"&&r!=="OMITTED"){if(!this.e1RetirementOrphans.has(t))continue;break}this.e1RetirementOrphans.delete(t)}this.e1TtlRefreshTimer||this.startE1TtlRefresh()}isReRaiseTargetCurrent(e){return!this.isStopping&&this.sessionState!==null&&this.sessionState.sessionId===e}async reRaiseOneE1(e,t,i){let s=t.record;if(!(0,g.canRecoverPromptRaise)(t,this.e1RaiseInFlight.has(s.promptId)))return"RETRY";let n=s.mobileActionable&&t.contentPlain!==void 0,r=i?.untilAck??!1,o=4,a=4e3;for(let l=1;r||l<=o;l++){if(!(0,g.isOpenPromptRaise)(t,this.e1PromptRaises.get(s.promptId)))return"CLOSED";if(r&&!this.isReRaiseTargetCurrent(e))return this.e1NeedsReRaise.add(s.promptId),c.warn("E1: retirement re-raise aborted (stopping/superseded) \u2014 parked",{sessionId:e,promptId:s.promptId}),"RETRY";try{let p;return n?p=await this.publishE1Prompt(e,s,g.EventType.INTERACTIVE_PROMPT,t.contentPlain,t.metadataPlain??{},i?.reRaiseToken):(s.mobileActionable=!1,p=await this.emitSuppressedPromptCarrier(e,s,i?.reRaiseToken)),p==="RETRY"||p==="CLOSED"||(this.e1NeedsReRaise.delete(s.promptId),c.info("E1: prompt publication settled",{sessionId:e,promptId:s.promptId,actionable:n,disposition:p})),p}catch(p){if(!r&&l===o)return this.e1NeedsReRaise.add(s.promptId),c.error("E1: re-raise unacked after backoff \u2014 parked for retry-until-ack",{sessionId:e,promptId:s.promptId,error:p instanceof Error?p.message:String(p)}),"RETRY";if(r){let f=Date.now()+Math.min(250*2**(l-1),a);for(;Date.now()<f&&this.isReRaiseTargetCurrent(e);)await new Promise(u=>setTimeout(u,Math.min(50,f-Date.now())))}else await new Promise(f=>setTimeout(f,250*l))}}return"RETRY"}async drainPendingE1ReRaises(){if(this.e1NeedsReRaise.size!==0)for(let e of[...this.e1NeedsReRaise]){let t=this.e1PromptRaises.get(e);if(!t){this.e1NeedsReRaise.delete(e);continue}!this.sessionState||t.record.sessionId!==this.sessionState.sessionId||await this.reRaiseOneE1(t.record.sessionId,t)}}beginE1Resolution(e,t){if(this.e1PendingResolutions.has(e))return!0;let i=this.e1PromptRaises.get(e);if(!i||i.record.sessionId!==t)return!1;this.e1PromptRaises.delete(e),this.e1NeedsReRaise.delete(e),this.e1RetirementOrphans.delete(e);for(let[s,n]of this.e1ContentKeyIndex.entries())n===e&&this.e1ContentKeyIndex.delete(s);return this.e1PendingResolutions.set(e,{record:{...i.record},resolutionAt:new Date().toISOString(),attempts:0}),this.e1TtlRefreshTimer||this.startE1TtlRefresh(),!0}async emitE1Resolution(e){let t=this.e1ResolutionInFlight.get(e);if(t)return t;if(!this.e1PendingResolutions.has(e))return;let i=(async()=>{let s=this.e1PendingResolutions.get(e);if(s){try{this.e1DurableState.writeResolution(s)}catch(n){c.error("E1: failed to persist exact-clear outbox record",{promptId:e,error:n instanceof Error?n.message:String(n)})}try{let n=this.e1RaiseInFlight.get(e);if(n&&await n,s=this.e1PendingResolutions.get(e),!s)return;if(!await this.appSyncClient.resolveCompanionPrompt({sessionId:s.record.sessionId,promptId:s.record.promptId,ownerToken:s.record.ownerToken,resolutionAt:s.resolutionAt}))throw new Error("E1_PLUGIN_RESOLUTION_NOT_ACKNOWLEDGED: exact prompt id was not returned");this.e1PendingResolutions.delete(e);try{this.e1DurableState.removeResolution(e)}catch(o){c.warn("E1: exact-clear ACKed but outbox cleanup failed",{promptId:e,error:o instanceof Error?o.message:String(o)})}c.info("E1: plugin approval resolution acknowledged",{sessionId:s.record.sessionId,promptId:e})}catch(n){let r=this.e1PendingResolutions.get(e);c.warn("E1: plugin approval resolution unacknowledged; parked for retry",{sessionId:r?.record.sessionId,promptId:e,error:n instanceof Error?n.message:String(n)})}}})();this.e1ResolutionInFlight.set(e,i);try{await i}finally{this.e1ResolutionInFlight.get(e)===i&&this.e1ResolutionInFlight.delete(e)}}trackE1Raise(e,t){let i=t.then(()=>{},()=>{});return this.e1RaiseInFlight.set(e,i),i.then(()=>{this.e1RaiseInFlight.get(e)===i&&this.e1RaiseInFlight.delete(e)}),t}async drainPendingE1Resolutions(){for(let[e,t]of[...this.e1PendingResolutions.entries()])t.attempts+=1,await this.emitE1Resolution(e)}async restorePendingE1ResolutionsFromOutbox(){let{records:e,rejected:t}=this.e1DurableState.readResolutions();for(let i of t)c.error("E1: rejected unsafe or invalid resolution outbox record",i);for(let i of e){let s=this.e1PendingResolutions.get(i.record.promptId);(!s||i.attempts>s.attempts)&&this.e1PendingResolutions.set(i.record.promptId,{record:{...i.record},resolutionAt:i.resolutionAt,attempts:i.attempts})}e.length>0&&(c.info("E1: recovered pending exact-clear outbox records",{count:e.length}),await this.drainPendingE1Resolutions(),this.e1PendingResolutions.size>0&&!this.e1TtlRefreshTimer&&this.startE1TtlRefresh())}async drainPendingE1ResolutionsForLifecycleEnd(e={}){let t=e.maxWaitMs??4e3,i=e.retryDelayMs??250,s=Date.now()+Math.max(0,t),n=0;do{if(await this.drainPendingE1Resolutions(),this.e1PendingResolutions.size===0)return;if(n+=1,Date.now()>=s)break;await new Promise(r=>setTimeout(r,Math.min(i*n,Math.max(0,s-Date.now()))))}while(Date.now()<s);for(let r of this.e1PendingResolutions.values())this.e1DurableState.writeResolution(r);c.warn("E1: graceful lifecycle ended with durable exact-clear work pending",{count:this.e1PendingResolutions.size})}beginE1PromptResolutions(e,t){let i=[];for(let s of new Set(e))this.beginE1Resolution(s,t)&&i.push(s);return i}launchE1Resolutions(e){Promise.all([...e].map(t=>this.emitE1Resolution(t)))}async exactClearOpenE1ForLifecycleEnd(e){let t=[...this.e1PromptRaises.values()].filter(s=>s.record.sessionId===e).map(s=>s.record.promptId),i=this.beginE1PromptResolutions(t,e);await Promise.all(i.map(s=>this.emitE1Resolution(s)))}async refreshE1Ttls(){if(this.nativeAuthority){try{await this.nativeControlOwner?.adapter.refreshPromptTtls((i,s)=>this.appSyncClient.refreshSessionOpenPromptTtl(i,s))}catch{c.warn("Native prompt TTL refresh retained for the next existing tick")}try{await this.maintainNativeControl()}catch{c.warn("Native control recovery retained for the next existing tick")}return}await this.drainPendingE1Resolutions(),await this.drainPendingE1ReRaises();let e=this.sessionState?.sessionId;if(!e)return;let t=[...this.e1PromptRaises.values()].filter(i=>i.record.sessionId===e&&(0,g.canRecoverPromptRaise)(i,this.e1RaiseInFlight.has(i.record.promptId))).map(i=>i.record.promptId);if(t.length!==0)try{await this.appSyncClient.refreshSessionOpenPromptTtl({sessionId:e,promptIds:t},async(i,s)=>{let n=this.e1PromptRaises.get(i);return!n||n.record.sessionId!==e||this.sessionState?.sessionId!==e?"CLOSED":this.reRaiseOneE1(e,n,{reRaiseToken:s})})}catch(i){c.warn("E1: TTL-refresh tick failed (non-fatal, retries next tick)",{error:i instanceof Error?i.message:String(i)})}}startE1TtlRefresh(){this.e1TtlRefreshTimer&&clearInterval(this.e1TtlRefreshTimer),this.e1TtlRefreshTimer=setInterval(()=>{this.refreshE1Ttls()},d.E1_TTL_REFRESH_MS)}stopE1TtlRefresh(){this.e1TtlRefreshTimer&&(clearInterval(this.e1TtlRefreshTimer),this.e1TtlRefreshTimer=null)}isExpectedSessionStateCurrent(e){return!this.isStopping&&this.sessionState===e&&!this.terminalInputBlockedStates.has(e)}sendSessionPinnedInput(e,t,i){if(!this.isExpectedSessionStateCurrent(e)||this.terminalInputBlockedStates.has(e))return Promise.resolve(!1);let s=this.terminalInputChain.then(async()=>!this.isExpectedSessionStateCurrent(e)||this.terminalInputBlockedStates.has(e)||!await this.verifyNoActiveCodexChooser(e.sessionId)||i&&(await i(),!this.isExpectedSessionStateCurrent(e)||!await this.verifyNoActiveCodexChooser(e.sessionId)||!this.isExpectedSessionStateCurrent(e))||!await this.promptResponder.sendLiteral(e.sessionId,t)||(await new Promise(n=>setTimeout(n,500)),!this.isExpectedSessionStateCurrent(e))||!await this.verifyNoActiveCodexChooser(e.sessionId)?!1:this.promptResponder.sendKey(e.sessionId,"Enter"));return this.terminalInputChain=s.then(()=>{},()=>{}),s}async verifyNoActiveCodexChooser(e){try{let t=await this.tmuxPaneObserver.captureSnapshot();if(this.tmuxPaneObserver.extractActivePromptBlock(t))return!1;let s=oe(t).split(`
43
+ `).trim();return(0,qe.createHash)("sha256").update(s).digest("hex")}};var F=require("@quantiya/codevibe-core");function $i(a,e){if(a!=="write_stdin"||!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return!Number.isSafeInteger(t.session_id)||t.session_id<=0||typeof t.chars!="string"||t.chars.length===0||typeof t.environment_id!="string"||!t.environment_id||/[\r\n]/.test(t.environment_id)||typeof t.approval_id!="string"||!t.approval_id?null:{terminalId:t.session_id,chars:t.chars,environmentId:t.environment_id,approvalId:t.approval_id}}function In(a){if(!a.startsWith('"')||!a.endsWith('"'))return null;let e="";for(let t=1;t<a.length-1;t++){let i=a[t];if(i==='"'||i.charCodeAt(0)<32)return null;if(i!=="\\"){e+=i;continue}if(++t>=a.length-1)return null;let s=a[t],n={'"':'"',"\\":"\\",n:`
44
+ `,r:"\r",t:" ",0:"\0"};if(Object.prototype.hasOwnProperty.call(n,s)){e+=n[s];continue}if(s!=="u"||a[t+1]!=="{")return null;let r=a.indexOf("}",t+2);if(r<0||r>=a.length-1)return null;let o=a.slice(t+2,r);if(!/^[0-9a-fA-F]{1,6}$/.test(o))return null;let d=Number.parseInt(o,16);if(d>1114111||d>=55296&&d<=57343)return null;e+=String.fromCodePoint(d),t=r}return e}function wt(a){let e=a.split(`
45
+ `).map(l=>l.trim()),t=e.filter(l=>/^Would you like to send input to terminal /.test(l)),i=e.filter(l=>l.startsWith("Environment:")),s=e.filter(l=>l.startsWith("Input:"));if(t.length!==1||i.length!==1||s.length!==1)return null;let n=/^Would you like to send input to terminal ([1-9][0-9]*)\?$/.exec(t[0]),r=n?Number(n[1]):NaN,o=i[0].slice(12).trimStart(),d=In(s[0].slice(6).trimStart());return!Number.isSafeInteger(r)||!o||d===null||!d.length?null:{terminalId:r,environmentId:o,chars:d}}function Wi(a,e){let t=wt(a);return!!t&&t.terminalId===e.terminalId&&t.environmentId===e.environmentId&&t.chars===e.chars}var Ps=require("@quantiya/codevibe-core");var Ht=D(require("express")),Ie=D(require("fs")),zi=D(require("path")),Ji=D(require("os"));var wn=1800*1e3,Sn=60*1e3,En=1440*60*1e3;var St=class{constructor(){this.assignedPort=0;this.portRefreshTimer=null;this.app=(0,Ht.default)(),this.setupMiddleware(),this.setupRoutes(),this.tmuxSession=process.env.CODEVIBE_CODEX_TMUX_SESSION}getPort(){return this.assignedPort}setupMiddleware(){this.app.use(Ht.default.json({limit:"1mb"})),this.app.use((e,t,i)=>{c.debug(`${e.method} ${e.path}`,{body:e.body}),i()})}setupRoutes(){this.app.get("/health",(e,t)=>{t.json({success:!0,service:"codevibe-codex",pid:process.pid,data:{status:"healthy",uptime:process.uptime()}})}),this.app.post("/event",this.handleEvent.bind(this))}async handleEvent(e,t){try{let i=e.body;if(!i.session_id||!i.hook_event_name){t.status(400).json({success:!1,error:"Missing session_id or hook_event_name"});return}let s=this.transformHookToEvent(i);if(c.info("Received hook event",{sessionId:i.session_id,hookEvent:i.hook_event_name,type:s.type}),this.eventHandler){let n=this.eventHandler(s);if(i.hook_event_name==="PermissionRequest"){n.catch(r=>{c.error("Error resolving PermissionRequest after acknowledgement:",r)}),t.json({success:!0});return}await n}t.json({success:!0})}catch(i){c.error("Error handling event:",i),t.status(500).json({success:!1,error:i instanceof Error?i.message:"Unknown error"})}}transformHookToEvent(e){let t={cwd:e.cwd,hook_event_name:e.hook_event_name,transcript_path:e.transcript_path,...e.metadata||{}},i,s;switch(e.hook_event_name){case"SessionStart":i="NOTIFICATION",s="Session started",t.source=e.source,t.model=e.model;break;case"UserPromptSubmit":i="USER_PROMPT",s=e.prompt||"";break;case"PreToolUse":i="NOTIFICATION",s="PreToolUse observed",t.tool_name=e.tool_name,t.tool_input=e.tool_input,t.tool_use_id=e.tool_use_id,t.approval_status="observed_pre_tool",t.requires_user_action=!1;break;case"PermissionRequest":i="NOTIFICATION",s="PermissionRequest observed",t.tool_name=e.tool_name,t.tool_input=e.tool_input,t.permission_mode=e.permission_mode,t.turn_id=e.turn_id,t.requires_user_action=!0;break;case"PostToolUse":i="TOOL_USE",s=JSON.stringify({tool_name:e.tool_name,tool_input:e.tool_input,tool_response:e.tool_response}),t.tool_name=e.tool_name,t.tool_input=e.tool_input,t.tool_use_id=e.tool_use_id;break;case"Stop":i="ASSISTANT_RESPONSE",s=e.last_assistant_message||"";break;default:i="NOTIFICATION",s=`Hook: ${e.hook_event_name}`}return{session_id:e.session_id,hook_event_name:e.hook_event_name,type:i,source:"DESKTOP",content:s,metadata:t}}onEvent(e){this.eventHandler=e}async start(){return new Promise((e,t)=>{try{this.server=this.app.listen(0,"localhost",()=>{let i=this.server.address();this.assignedPort=i.port,c.info(`HTTP API listening on http://localhost:${this.assignedPort}`),this.writePortFile(this.assignedPort),this.startPortFileKeepalive(),e(this.assignedPort)}),this.server.on("error",i=>{c.error("HTTP server error:",i),t(i)})}catch(i){t(i)}})}portFilePath(){return this.tmuxSession?zi.join(Ji.tmpdir(),`codevibe-codex-${this.tmuxSession}.port`):null}writePortFile(e){let t=this.portFilePath();if(!t){c.warn("No CODEVIBE_CODEX_TMUX_SESSION set, skipping port file");return}try{Ie.writeFileSync(t,e.toString()),c.info(`Port file written: ${t} -> ${e}`)}catch(i){c.error(`Failed to write port file: ${t}`,i)}}removePortFile(){let e=this.portFilePath();if(e)try{Ie.existsSync(e)&&(Ie.unlinkSync(e),c.info(`Port file removed: ${e}`))}catch(t){c.warn(`Failed to remove port file: ${e}`,t)}}startPortFileKeepalive(){this.portRefreshTimer&&(clearInterval(this.portRefreshTimer),this.portRefreshTimer=null);let e=Number(process.env.CODEVIBE_PORTFILE_REFRESH_MS),t=Number.isFinite(e)&&e>0?Math.min(En,Math.max(Sn,e)):wn;this.portRefreshTimer=setInterval(()=>this.refreshPortFile(),t)}refreshPortFile(){let e=this.portFilePath();if(e)try{let t=new Date;Ie.utimesSync(e,t,t)}catch(t){t?.code==="ENOENT"?this.writePortFile(this.assignedPort):c.warn(`Port-file refresh failed: ${e}`,t)}}async stop(){return this.portRefreshTimer&&(clearInterval(this.portRefreshTimer),this.portRefreshTimer=null),this.removePortFile(),new Promise(e=>{this.server?this.server.close(()=>{c.info("HTTP API stopped"),e()}):e()})}};var Et=class{constructor(e={}){this.pendingBySession=new Map;this.expiryMs=e.expiryMs??1e4,this.minFuzzyEchoLength=e.minFuzzyEchoLength??16,this.minFuzzyEchoRatio=e.minFuzzyEchoRatio??.35,this.now=e.now??Date.now}track(e,t){let i=this.normalize(t);if(!i)return;let s=this.validEntries(e);s.push({normalized:i,timestamp:this.now()}),this.pendingBySession.set(e,s)}forget(e,t){let i=this.normalize(t);if(!i)return;let s=!1,n=this.validEntries(e).filter(r=>!s&&r.normalized===i?(s=!0,!1):!0);this.replaceEntries(e,n)}consumeIfDuplicate(e,t){let i=this.normalize(t);if(!i)return null;let s=null,n=this.validEntries(e).filter(r=>{if(!s){let o=this.matchType(r.normalized,i);if(o)return s={matchType:o,originalLength:r.normalized.length,echoLength:i.length},!1}return!0});return this.replaceEntries(e,n),s}peekIfDuplicate(e,t){let i=this.normalize(t);if(!i)return null;for(let s of this.validEntries(e)){let n=this.matchType(s.normalized,i);if(n)return{matchType:n,originalLength:s.normalized.length,echoLength:i.length}}return null}validEntries(e){let t=this.now()-this.expiryMs;return(this.pendingBySession.get(e)||[]).filter(i=>i.timestamp>=t)}replaceEntries(e,t){t.length>0?this.pendingBySession.set(e,t):this.pendingBySession.delete(e)}matchType(e,t){if(e===t)return"exact";let i=t.length>=this.minFuzzyEchoLength,s=t.length/e.length>=this.minFuzzyEchoRatio;return i&&s&&e.endsWith(t)?"suffix":null}normalize(e){return e.replace(/\s+/g," ").trim()}};var Xi=D(require("crypto")),Zi=D(require("fs")),es=D(require("https")),Pt=D(require("os")),ts=D(require("path")),Pn="G-GS74YEQTB8",bn="lAfOF6OxRzSQ-NsLBRjhAg",Rn="www.google-analytics.com",Tn=`/mp/collect?measurement_id=${Pn}&api_secret=${bn}`,Yi=800;function _n(){try{let a=ts.resolve(__dirname,"..","package.json"),e=Zi.readFileSync(a,"utf-8"),t=JSON.parse(e);if(typeof t.version=="string"&&t.version.length>0&&t.version.length<30)return t.version}catch{}return"unknown"}var Cn=_n();function Nn(){let a=typeof process.getuid=="function"?process.getuid():0;return Xi.createHash("sha256").update(`${Pt.hostname()}-${a}`).digest("hex").substring(0,36)}function An(a){if(!a)return"";let e=Pt.homedir(),t=a.replace(/[\n\r\t]/g," ");if(e&&e.length>0){let i=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");t=t.replace(new RegExp(i,"g"),"~")}return t=t.replace(/\/Users\/[^/\s"'`]+/g,"/Users/<user>").replace(/\/home\/[^/\s"'`]+/g,"/home/<user>").replace(/[^\x20-\x7E]/g,""),t.trim().substring(0,100)}function L(a,e){return new Promise(t=>{let i,s=!1,n=()=>{s||(s=!0,clearTimeout(r),t())},r=setTimeout(()=>{try{i?.destroy()}catch{}n()},Yi);typeof r.unref=="function"&&r.unref();try{let o={...e};typeof o.error_message=="string"&&(o.error_message=An(o.error_message));let d=JSON.stringify({client_id:Nn(),events:[{name:a,params:{agent:"codex",plugin_version:Cn,platform:process.platform,source:process.env.CODEVIBE_TELEMETRY_SOURCE||"production",...o}}]});i=es.request({hostname:Rn,path:Tn,method:"POST",headers:{"Content-Type":"application/json"},timeout:Yi},l=>{l.resume(),l.on("end",n),l.on("close",n),l.on("error",n)}),i.on("error",n),i.on("timeout",()=>{try{i?.destroy()}catch{}n()}),i.on("close",n),i.write(d),i.end()}catch{n()}})}var bt=class{constructor(){this.originated=new Set;this.externallyResolved=new Set}markOriginated(e){this.originated.add(e)}clearOriginated(e){this.originated.delete(e)}getOriginated(){return new Set(this.originated)}getExternallyResolved(){return new Set(this.externallyResolved)}isExternallyResolved(e){return this.externallyResolved.has(e)}dispatch(e){let{gateId:t}=e;return this.originated.has(t)?(this.originated.delete(t),this.externallyResolved.add(t),"self_echo"):(this.externallyResolved.add(t),"foreign")}clear(){this.originated.clear(),this.externallyResolved.clear()}};function is(a){return`[CodeVibe] Decision recorded on another device: ${a} \u2014 type any number to dismiss the open AskUserQuestion`}var ss=require("@quantiya/codevibe-core"),On=new Set(["stall-retirement","stall-tmux-probe"]),xn=1e3,Rt;function kn(a=process.env){let e=new Map,t=a.CODEVIBE_DEV_FAULTS;if(t&&(0,ss.getEnvironment)()==="development")for(let i of t.split(",")){let[s,n]=i.trim().split(":");if(!On.has(s))continue;let r=n===void 0?1:Number.parseInt(n,10);!Number.isSafeInteger(r)||r<=0||r>xn||e.set(s,r)}return Rt=e,e}function jt(a){Rt||kn();let e=Rt.get(a)??0;return e<=0?!1:(Rt.set(a,e-1),!0)}async function Gt(a,e,t){let i;try{let s=(()=>{try{return Promise.resolve(a())}catch(o){return Promise.reject(o)}})(),n=new Promise(o=>{i=setTimeout(()=>o("timeout"),e),i.unref&&i.unref()}),r=await Promise.race([s.then(()=>"settled",()=>"settled"),n]);if(r==="timeout"){s.catch(()=>{});try{t?.()}catch{}}return r}finally{i&&clearTimeout(i)}}function Ne(a,e,t=25e3,i=()=>!0){let s=setTimeout(()=>{try{e()}catch{}let n=!1;try{n=i()}catch{n=!1}a(n?0:1)},t);return()=>clearTimeout(s)}function ns(a,e,t,i,s=25e3){let n=!1,r=!1,o,d=u=>{r||(r=!0,o?.(),t(u))},l=()=>n&&e();return u=>{if(r)return;n||=u,o??=Ne(d,i,s,l);let h;try{h=a({retireBackendSession:n})}catch{d(1);return}h.then(()=>{let p=1;try{l()&&(p=0)}catch{}d(p)},()=>d(1))}}var Ye=D(require("crypto")),C=D(require("fs")),_t=D(require("os")),ie=D(require("path")),as=require("@quantiya/codevibe-core"),$t=2*1024*1024,Dn=600*1e3,de=1e3;function ds(){return typeof process.getuid=="function"?process.getuid():void 0}function Wt(a,e){let t=ds();if(t!==void 0&&a.uid!==t)throw new Error(`E1_STATE_FOREIGN_OWNER: ${e}`)}function ls(a){C.mkdirSync(a,{recursive:!0,mode:448});let e=C.lstatSync(a);if(!e.isDirectory()||e.isSymbolicLink())throw new Error(`E1_STATE_ROOT_NOT_PRIVATE_DIRECTORY: ${a}`);Wt(e,a),process.platform!=="win32"&&C.chmodSync(a,448)}function rs(a,e){let t=ie.dirname(a);ls(t);let i=`${JSON.stringify(e)}
46
+ `;if(Buffer.byteLength(i,"utf8")>$t)throw new Error(`E1_STATE_TOO_LARGE: ${a}`);let s=ie.join(t,`.${ie.basename(a)}.${process.pid}.${Ye.randomUUID()}.tmp`),n=C.constants.O_NOFOLLOW??0,r=null;try{r=C.openSync(s,C.constants.O_WRONLY|C.constants.O_CREAT|C.constants.O_EXCL|n,384),C.writeFileSync(r,i,{encoding:"utf8"}),C.fsyncSync(r),C.closeSync(r),r=null,process.platform!=="win32"&&C.chmodSync(s,384),C.renameSync(s,a),process.platform!=="win32"&&C.chmodSync(a,384);try{let o=C.openSync(t,C.constants.O_RDONLY);try{C.fsyncSync(o)}finally{C.closeSync(o)}}catch{}}finally{r!==null&&C.closeSync(r);try{C.unlinkSync(s)}catch(o){if(o.code!=="ENOENT")throw o}}}function os(a){let e;try{e=C.lstatSync(a)}catch(s){if(s.code==="ENOENT")return null;throw s}if(!e.isFile()||e.isSymbolicLink())throw new Error(`E1_STATE_NOT_REGULAR_FILE: ${a}`);if(Wt(e,a),process.platform!=="win32"&&(e.mode&63)!==0)throw new Error(`E1_STATE_PERMISSIONS_LOOSE: ${a}`);if(e.size>$t)throw new Error(`E1_STATE_TOO_LARGE: ${a}`);let t=C.constants.O_NOFOLLOW??0,i=C.openSync(a,C.constants.O_RDONLY|t);try{let s=C.fstatSync(i);if(Wt(s,a),!s.isFile()||e.dev!==s.dev||e.ino!==s.ino)throw new Error(`E1_STATE_FILE_CHANGED_DURING_OPEN: ${a}`);if(s.size>$t)throw new Error(`E1_STATE_TOO_LARGE: ${a}`);return JSON.parse(C.readFileSync(i,{encoding:"utf8"}))}finally{C.closeSync(i)}}function G(a){return a!==null&&typeof a=="object"&&!Array.isArray(a)}function k(a,e=256*1024){return typeof a=="string"&&Buffer.byteLength(a,"utf8")<=e}function cs(a){if(!G(a)||!k(a.promptId,512)||!k(a.ownerToken,512)||!k(a.sessionId,1024)||a.producerKind!=="PLUGIN_APPROVAL"||a.agentType!==void 0&&a.agentType!=="CODEX"||a.title!==void 0&&!k(a.title,4096)||typeof a.mobileActionable!="boolean"||typeof a.raisedAtMs!="number"||!Number.isFinite(a.raisedAtMs))return!1;try{return(0,as.deriveOpenPromptId)(a.ownerToken)===a.promptId}catch{return!1}}function Mn(a){if(!G(a)||!cs(a.record))return!1;for(let e of["contentPlain","resolutionDedupeKey","resolutionCompletionKey","resolutionCallId","suppressedObserverSnapshotKey"])if(a[e]!==void 0&&!k(a[e]))return!1;return!(a.metadataPlain!==void 0&&!G(a.metadataPlain)||a.suppressTmuxObserverUntilResolved!==void 0&&typeof a.suppressTmuxObserverUntilResolved!="boolean")}function us(a){return G(a)&&cs(a.record)&&k(a.resolutionAt,128)&&!Number.isNaN(Date.parse(a.resolutionAt))&&typeof a.attempts=="number"&&Number.isSafeInteger(a.attempts)&&a.attempts>=0}function ps(a){if(!G(a)||a.nativeQuestionTitleSha256!==void 0&&(typeof a.nativeQuestionTitleSha256!="string"||!/^[a-f0-9]{64}$/.test(a.nativeQuestionTitleSha256))||!k(a.promptId,512)||!["yes_no","numbered","text","queued_question"].includes(String(a.kind))||!Array.isArray(a.options)||a.options.length>100||!a.options.every(i=>G(i)&&k(i.number,32)&&k(i.text,32*1024)&&(i.description===void 0||k(i.description,32*1024))&&(i.preview===void 0||k(i.preview,32*1024)))||!G(a.submitMap)||!Object.entries(a.submitMap).every(([i,s])=>k(i,128)&&k(s,32*1024))||!k(a.promptText)||typeof a.createdAt!="number"||!Number.isFinite(a.createdAt)||!["permission_hook","tmux","heuristic","queued_question"].includes(String(a.source)))return!1;for(let i of["callId","dedupeKey","completionKey","ownerSessionId","observerMatchKey","observerPromptHash","terminalMenuIdentity"])if(a[i]!==void 0&&!k(a[i],32*1024))return!1;if(a.requiresFollowUpText!==void 0&&typeof a.requiresFollowUpText!="boolean")return!1;let e=a.preemptedQueuedQuestionId!==void 0,t=a.preemptedQueuedQuestionAt!==void 0;if(e!==t||e&&(!k(a.preemptedQueuedQuestionId,512)||a.preemptedQueuedQuestionId.trim().length===0||typeof a.preemptedQueuedQuestionAt!="number"||!Number.isFinite(a.preemptedQueuedQuestionAt)||a.preemptedQueuedQuestionAt<=0))return!1;if(a.allQuestions!==void 0){if(!Array.isArray(a.allQuestions)||a.allQuestions.length>100)return!1;for(let i of a.allQuestions){if(!G(i)||!k(i.question,32*1024)||!Array.isArray(i.options)||i.options.length>100||i.header!==void 0&&!k(i.header,1024)||i.multiSelect!==void 0&&typeof i.multiSelect!="boolean")return!1;for(let s of i.options)if(typeof s=="string"){if(!k(s,32*1024))return!1}else if(G(s)){if(!k(s.label,32*1024)||s.description!==void 0&&!k(s.description,32*1024)||s.preview!==void 0&&!k(s.preview,32*1024))return!1}else return!1}}return!0}function Fn(a){return G(a)&&ps(a.prompt)&&k(a.content)&&G(a.metadata)}function Ln(a,e,t){if(!G(a)||a.version!==1)throw new Error("E1_HANDOFF_UNSUPPORTED_VERSION");if(a.tmuxSession!==e||!k(a.backendSessionId,1024))throw new Error("E1_HANDOFF_INSTANCE_MISMATCH");if(typeof a.createdAtMs!="number"||!Number.isFinite(a.createdAtMs))throw new Error("E1_HANDOFF_INVALID_TIMESTAMP");if(a.createdAtMs>t+6e4||t-a.createdAtMs>Dn)throw new Error("E1_HANDOFF_STALE");if(!Array.isArray(a.openRaises)||a.openRaises.length>de||!a.openRaises.every(Mn))throw new Error("E1_HANDOFF_INVALID_OPEN_RAISES");if(!Array.isArray(a.pendingResolutions)||a.pendingResolutions.length>de||!a.pendingResolutions.every(us))throw new Error("E1_HANDOFF_INVALID_PENDING_RESOLUTIONS");if(!Array.isArray(a.needsReRaisePromptIds)||a.needsReRaisePromptIds.length>de||!a.needsReRaisePromptIds.every(s=>k(s,512)))throw new Error("E1_HANDOFF_INVALID_RERAISE_IDS");if(!Array.isArray(a.permissionOccurrences)||a.permissionOccurrences.length>de)throw new Error("E1_HANDOFF_INVALID_OCCURRENCES");if(!a.permissionOccurrences.every(s=>Array.isArray(s)&&s.length===2&&k(s[0],256*1024)&&Array.isArray(s[1])&&s[1].length<=de&&s[1].every(n=>G(n)&&k(n.occurrenceKey,512)&&typeof n.hookObserved=="boolean"&&typeof n.jsonlObserved=="boolean")))throw new Error("E1_HANDOFF_INVALID_OCCURRENCES");if(a.waitingPermissionRequests!==void 0&&(!Array.isArray(a.waitingPermissionRequests)||a.waitingPermissionRequests.length>de||!a.waitingPermissionRequests.every(s=>G(s)&&k(s.occurrenceKey,512)&&(s.dedupeKey===void 0||k(s.dedupeKey))&&G(s.payload)&&s.payload.hook_event_name==="PermissionRequest"&&(s.payload.metadata===void 0||G(s.payload.metadata)))))throw new Error("E1_HANDOFF_INVALID_WAITING_REQUESTS");if(a.pendingInteractivePrompt!==null&&!ps(a.pendingInteractivePrompt))throw new Error("E1_HANDOFF_INVALID_ACTIVE_PROMPT");if(!Array.isArray(a.queuedInteractivePrompts)||a.queuedInteractivePrompts.length>de||!a.queuedInteractivePrompts.every(Fn))throw new Error("E1_HANDOFF_INVALID_QUEUED_PROMPTS");if(!Array.isArray(a.resolvedApprovalDedupeKeys)||a.resolvedApprovalDedupeKeys.length>de||!a.resolvedApprovalDedupeKeys.every(s=>Array.isArray(s)&&s.length===2&&k(s[0])&&typeof s[1]=="number"&&Number.isFinite(s[1])))throw new Error("E1_HANDOFF_INVALID_RESOLVED_KEYS");if(a.historicalQueuedQuestionPromptIds!==void 0&&(!Array.isArray(a.historicalQueuedQuestionPromptIds)||a.historicalQueuedQuestionPromptIds.length>de||!a.historicalQueuedQuestionPromptIds.every(s=>k(s,512))))throw new Error("E1_HANDOFF_INVALID_HISTORICAL_QUESTION_IDS");return a}function qn(a){if(!G(a)||a.version!==1||!us(a.pending))throw new Error("E1_RESOLUTION_OUTBOX_INVALID_RECORD");if(typeof a.updatedAtMs!="number"||!Number.isFinite(a.updatedAtMs))throw new Error("E1_RESOLUTION_OUTBOX_INVALID_TIMESTAMP");return a}var Tt=class{constructor(e={}){let t=ds()??"nouid";this.handoffRoot=e.handoffRoot??ie.join(_t.tmpdir(),`codevibe-codex-handoff-${t}`),this.resolutionRoot=e.resolutionRoot??ie.join(_t.homedir(),".codevibe","codex","e1-resolution-outbox"),this.now=e.now??Date.now}handoffPath(e){let t=Ye.createHash("sha256").update(e).digest("hex").slice(0,32);return ie.join(this.handoffRoot,`${t}.json`)}resolutionPath(e){let t=Ye.createHash("sha256").update(e).digest("hex");return ie.join(this.resolutionRoot,`${t}.json`)}writeHandoff(e){rs(this.handoffPath(e.tmuxSession),e)}readHandoff(e){let t=os(this.handoffPath(e));if(t===null)return null;try{return Ln(t,e,this.now())}catch(i){if(i.message==="E1_HANDOFF_STALE")return this.removeHandoff(e),null;throw i}}removeHandoff(e){try{C.unlinkSync(this.handoffPath(e))}catch(t){if(t.code!=="ENOENT")throw t}}writeResolution(e){rs(this.resolutionPath(e.record.promptId),{version:1,updatedAtMs:this.now(),pending:e})}removeResolution(e){try{C.unlinkSync(this.resolutionPath(e))}catch(t){if(t.code!=="ENOENT")throw t}}readResolutions(){let e;try{ls(this.resolutionRoot),e=C.readdirSync(this.resolutionRoot).filter(s=>s.endsWith(".json"))}catch(s){if(s.code==="ENOENT")return{records:[],rejected:[]};throw s}let t=[],i=[];for(let s of e.slice(0,de)){let n=ie.join(this.resolutionRoot,s);try{let r=os(n);if(r!==null){let o=qn(r).pending;if(ie.basename(this.resolutionPath(o.record.promptId))!==s)throw new Error("E1_RESOLUTION_OUTBOX_IDENTITY_MISMATCH");t.push(o)}}catch(r){i.push({file:n,reason:r instanceof Error?r.message:String(r)})}}return e.length>de&&i.push({file:this.resolutionRoot,reason:`E1_RESOLUTION_OUTBOX_RECORD_LIMIT: ${e.length}`}),{records:t,rejected:i}}};var ws=(0,Yt.promisify)(Ot.exec),Vn=(0,Yt.promisify)(Ot.execFile),Un="/quit",we="CODEVIBE_CODEX_TMUX_SESSION",Xe="CODEVIBE_CODEX_DAEMON_RECOVERY",Kn=1e3,Qn=1e4,Ae=3,vs=100,Ss=["SIGINT","SIGTERM","SIGHUP"],Hn=600*1e3,zt=30*1e3,jn=/^(?:[a-z0-9]|esc|escape)$/;function gs(a,e){let t=a?.[e];return typeof t=="string"?t:Buffer.isBuffer(t)?t.toString("utf8"):""}function Es(a){if(typeof a?.code!="number")return"unknown";let e=`${gs(a,"stderr")}
47
+ ${gs(a,"stdout")}`;return/^can't find session:/m.test(e)||/^no server running on /m.test(e)||/^error connecting to .* \((?:No such file or directory|Connection refused)\)$/m.test(e)?"absent":"unknown"}async function Gn(a,e){let t=async(i,s)=>{try{await ws(i)}catch(n){c.warn("tmux send-keys failed during self-terminate",{sessionName:a,label:s,error:String(n)})}};await t(`tmux send-keys -t "${a}" C-c`,"ctrl-c"),await new Promise(i=>setTimeout(i,200)),await t(`tmux send-keys -t "${a}" -l "${e}"`,"quit-text"),await new Promise(i=>setTimeout(i,500)),await t(`tmux send-keys -t "${a}" Enter`,"enter")}var Ct=class extends Error{constructor(){super("NATIVE_BACKEND_RETIRED"),this.name="NativeBackendRetiredError"}};function et(a){let e=a.split(`
48
+ `),t=r=>/^[\s>]*\d+\.\s/.test(r),i=-1;for(let r=e.length-1;r>=0;r-=1)if(/^\s*\$\s+/.test(e[r])){i=r;break}if(i===-1)return;let s=e[i].trim().match(/^\$\s+(.+)$/);if(!s?.[1]?.trim())return;let n=[s[1].trim()];for(let r=i+1;r<e.length;r+=1){let o=e[r];if(t(o)||/^\s*$/.test(o)||/^\s*\$\s+/.test(o))break;n.push(o.trim())}return n.length>0?n:void 0}function bs(a){let e=et(a);if(!e)return;let t=e.join(" ").trim();return t.length>0?t:void 0}function Nt(a,e){return $n(a,e).has(e)}function $n(a,e){if(a.length===0)return new Set;let t=e,i=new Set([a[0]]);for(let s of a.slice(1)){let n=s,r=new Set;for(let o of i)for(let d of[""," ",`
49
+ `]){let l=`${o}${d}${n}`;t.startsWith(l)&&r.add(l)}if(r.size===0)return new Set;i=r}return i}function Wn(a,e){if(!a||!e)return!1;if(Rs(a,e))return!0;let t=et(a);if(t&&Nt(t,e))return!0;let i=a.split(/\r?\n/);for(let s=0;s<i.length;s++)if(/^\s*\$\s+/.test(i[s])){let n=i.slice(s).join(`
50
+ `),r=et(n);if(r&&Nt(r,e))return!0}return!1}function zn(a,e,t){let i=/^\[\u2026\s+\d+\s+lines\]\s+ctrl\s*\+\s*a\s+view\s+all$/i,s=a.split(`
51
+ `).map(n=>n.trim()).filter(Boolean);return s.length<2||!i.test(s[s.length-1])||!t?!1:Rs(t,e)}function Rs(a,e){let t=Jt(e),i=_s(a,"2");if(!t||!i)return!1;let s=new Set;for(let n of Cs(i)){let r=n.match(/^Yes, and don't ask again for commands that start with `([^`]*)`\s*\(p\)$/);if(!r)continue;let o=Jt(r[1]);o&&JSON.stringify(o)===JSON.stringify(t)&&s.add(JSON.stringify(o))}return s.size===1}function Ts(a,e,t){let i=a.find(m=>m.number==="2");if(!i||!(/don't ask again|persist/i.test(i.text)||a.length>=3&&a.some(m=>m.number==="3")))return a;if(!(/\(p\)\s*$/i.test(i.text)?i:null))return null;let r="Yes, and don't ask again for commands that start with",o="Yes, and don't ask again (p)",d=_s(t,"2");if(!d)return null;let l=Cs(d);if(l.has(o))return a.map(m=>m.number==="2"?{...m,text:o}:m);if(!e)return null;let u=new Map;for(let m of l){let f=m.match(/^Yes, and don't ask again for commands that start with `([^`]*)`\s*\(p\)$/);if(!f)continue;let g=Jt(f[1]);!g||!Yn(g,e)||u.set(JSON.stringify(g),g)}if(u.size!==1)return null;let h=[...u.values()][0],p=Jn(h);return a.map(m=>m.number==="2"?{...m,text:`${r} \`${p}\` (p)`}:m)}function _s(a,e){if(!a)return null;let t=(0,F.normalizeSnapshot)(a).split(`
52
+ `).map(o=>o.trim()),i=new RegExp(`^(?:[>\u203A\u276F\u25B8\u25B6\u279C\u27A4*\u25CF]\\s*)?${e}\\.\\s+(.*)$`),s=-1,n="";for(let o=t.length-1;o>=0;o-=1){let d=t[o].match(i);if(d){s=o,n=d[1];break}}if(s<0)return null;let r=[n];for(let o=s+1;o<t.length&&!(/^(?:[>›❯▸▶➜➤*●]\s*)?\d+\.\s+/.test(t[o])||!t[o]||(r.push(t[o]),/\(p\)\s*$/i.test(t[o])));o+=1);return r.some(o=>/\(p\)\s*$/i.test(o))?r:null}function Cs(a){if(a.length===0||a.length>13)return new Set;let e=new Set([a[0]]);for(let t of a.slice(1)){let i=new Set;for(let s of e)i.add(`${s}${t}`),i.add(`${s} ${t}`);e=i}return e}function Jt(a){try{let e=(0,Xt.parse)(a,t=>`\${${t}}`);return e.every(t=>typeof t=="string")?e:null}catch{return null}}function Jn(a){return a.map(e=>/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)?e:`'${e.replace(/'/g,`'"'"'`)}'`).join(" ")}function ys(a){return a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Yn(a,e){if(a.length===0)return!1;let t;try{t=(0,Xt.parse)(e,s=>`\${${s}}`)}catch{return!1}let i=[[]];for(let s of t){if(typeof s=="string"){i[i.length-1].push(s);continue}if("op"in s&&["&&","||",";","|","|&","&"].includes(s.op)){i.push([]);continue}return!1}return i.some(s=>a.every((n,r)=>s[r]===n))}function Zt(a){let e=a instanceof v.AppSyncGraphQLError?a.errorType:a instanceof Error?a.message:"",t=typeof e=="string"&&/^[A-Z][A-Z0-9_]{1,95}$/.test(e)?e:"NATIVE_OBSERVER_STOP_FAILED",i=a instanceof v.AppSyncGraphQLError?a.requestId:void 0;return{errorCode:t,...typeof i=="string"&&/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(i)&&{requestId:i}}}var At=class a{constructor(e){this.nativeAuthority=e;this.nativeRuntime=null;this.nativeControlOwner=null;this.nativeReplacementToken=null;this.nativeAdmissionToken=null;this.nativeDegraded=!1;this.nativeReceiptReadiness=null;this.nativeRetirement=null;this.nativeControlRecovery=null;this.nativeRecoveryReadinessGeneration=0;this.nativeAdmission=null;this.nativeInitialization=null;this.nativeControlNotice=null;this.nativeReplacementGate=null;this.nativeQuestionFrame=null;this.nativeMaintenance=null;this.nativeReceiptWork=new Map;this.tuiGemmaPort=null;this.sessionState=null;this.unsubscribe=null;this.sessionKey=null;this.sessionIsEncrypted=!1;this.sessionKeyGen=null;this.e1PromptRaises=new Map;this.e1PendingResolutions=new Map;this.e1ResolutionInFlight=new Map;this.e1RaiseInFlight=new Map;this.acknowledgedQueuedQuestionRaises=new WeakSet;this.e1NeedsReRaise=new Set;this.e1RetirementOrphans=new Map;this.e1ContentKeyIndex=new Map;this.e1TtlRefreshTimer=null;this.toolActivity=null;this.toolActivityStartPromise=null;this.toolActivityLegacyRecorders=new Map;this.pendingInteractivePrompt=null;this.promptGeneration=0;this.queuedInteractivePrompts=[];this.isInitializingSession=!1;this.bufferedLogEntries=[];this.logEntryChain=Promise.resolve();this.nativeSourceSelection=null;this.nativeSourceOwners=new Map;this.nativeSourceRetryTimer=null;this.hookEventChain=Promise.resolve();this.hooksActive=!1;this.hooksCompatibilityNoticeSent=!1;this.permissionRequestHookInFlight=null;this.queuedPermissionRequestDedupeKeys=new Map;this.queuedPermissionRequestSessionCounts=new Map;this.queuedPermissionRequestRegistrations=new Map;this.waitingPermissionRequests=new Map;this.permissionRequestOccurrencesByCompletionKey=new Map;this.deferredTmuxPromptCandidates=new Map;this.recoveryPermissionReplay=null;this.resolvedApprovalDedupeKeys=new Map;this.queuedQuestionCallIds=new Set;this.historicalQueuedQuestionPromptIds=new Set;this.subscribedSessionId=null;this.subscribedSessionState=null;this.terminalInputChain=Promise.resolve();this.terminalInputBlockedStates=new WeakSet;this.mobilePromptDeduper=new Et({expiryMs:1e4});this.launchSessionInitPromise=null;this.sessionStartedInitPromise=null;this.bootstrapSessionId=null;this.recoveryBootstrapOwnerBound=!1;this.resumeBackendSession=v.resumeOrCreateSession;this.sessionBootstrapFailureCount=0;this.sessionBootstrapRetryAt=0;this.retiredSessionRecoveryPromise=null;this.lifecycleGeneration=0;this.isStopping=!1;this.stopPromise=null;this.terminalRetirementRequested=!1;this.shutdownHostedRetirementUnconfirmed=!1;this.teardownStepsTimedOut=[];this.retirementOwed=!1;this.tmuxLifecycleTimer=null;this.tmuxLifecycleCheckInFlight=!1;this.tmuxLifecycleObservedAlive=!1;this.tmuxLifecycleInitDeadlineMs=Number.POSITIVE_INFINITY;this.v1Bridge=new bt;this.orchestrationClient=null;this.userDecisionUnsubscribe=null;this.tmuxParseInFlight=new Map;this.tmuxParseResultCache=new Map;this.cacheGeneration=0;this.sessionWatcher=new ht({restoreCursor:(t,i)=>this.retryNativeAdmission(()=>this.restoreNativeSource(t,i)),beforeGap:(t,i)=>this.retryNativeAdmission(()=>this.admitNativeSourceGap(t,i)),beforeEntry:(t,i)=>this.retryNativeAdmission(()=>this.admitNativeSourceEntry(t,i))}),e||(this.httpApi=new St,this.approvalDetector=new gt,this.promptResponder=new yt,this.tmuxPaneObserver=new Je),this.e1DurableState=new Tt({handoffRoot:process.env.CODEVIBE_CODEX_HANDOFF_ROOT,resolutionRoot:process.env.CODEVIBE_CODEX_E1_OUTBOX_ROOT})}nativeReceiptsReady(){let e=this.nativeRuntime,t=this.sessionState;return!!e?.thread&&!!t&&e.thread.id===t.codexSessionId&&this.nativeReceiptReadiness?.instanceId===this.nativeAuthority?.record.instanceId&&this.nativeReceiptReadiness?.matches(e.thread.id)===!0}controlAdmission(){return this.nativeAdmission??=new ut}hasNativeAuthority(){return this.nativeAuthority!==void 0}receiveNativeReceipt(e){let t=this.nativeAuthority,i=e;if(!t||this.isStopping||!process.connected||process.ppid!==t.record.launcher.pid||!i||i.instanceId!==t.record.instanceId)return;try{t.assertCurrent()}catch{return}if(i.type==="CODEVIBE_NATIVE_RECEIPTS_UNAVAILABLE"||i.type==="CODEVIBE_NATIVE_RECEIPTS_READY"){let o=this.nativeReceiptReadiness??=new Ke(t.record.instanceId),d=JSON.stringify(o.snapshot()),l=i.readiness;if(!l||l.ready!==(i.type==="CODEVIBE_NATIVE_RECEIPTS_READY")||!o.receive(l))return;let u=JSON.stringify(o.snapshot())!==d;u&&(this.controlAdmission().invalidate(),this.nativeDegraded=!0,this.nativeControlOwner?.adapter.suspendAdmission()),this.nativeReceiptsReady()?u&&this.scheduleNativeControlRecovery():this.degradeNativeControl("NATIVE_RECEIPTS_UNAVAILABLE");return}if(i.type!=="CODEVIBE_NATIVE_RECEIPT")return;let s;try{s=at(i.receipt,t.record.instanceId)}catch{c.warn("Retained native receipt refused",{code:"NATIVE_RECEIPT_INVALID"});return}if(this.nativeReceiptWork.has(s.digest))return;let n=o=>{try{t.assertCurrent(),process.connected&&process.ppid===t.record.launcher.pid&&process.send?.({type:"CODEVIBE_NATIVE_RECEIPT_ACK",instanceId:t.record.instanceId,digest:s.digest,consumed:o},void 0,void 0,()=>{})}catch{}},r=(async()=>{let o=this.nativeReplacementGate;o&&await o.ready;let d=this.nativeControlOwner;if(!d||this.isStopping){n(!1);return}let l=await d.adapter.reconcileRetainedApproval(s);n(l)})().catch(()=>{c.warn("Retained native receipt pending",{code:"NATIVE_RECEIPT_NOT_PERSISTED"}),n(!1)});this.nativeReceiptWork.set(s.digest,r),r.then(()=>{this.nativeReceiptWork.get(s.digest)===r&&this.nativeReceiptWork.delete(s.digest)})}pollNativeReceipts(){try{!this.isStopping&&this.nativeAuthority&&process.connected&&process.ppid===this.nativeAuthority.record.launcher.pid&&(this.nativeAuthority.assertCurrent(),process.send?.({type:"CODEVIBE_NATIVE_RECEIPTS_POLL",instanceId:this.nativeAuthority.record.instanceId},void 0,void 0,()=>{}))}catch{}}setTuiGemmaPort(e){this.tuiGemmaPort=e}static{this.E1_TTL_REFRESH_MS=300*1e3}async start(){if(!this.nativeAuthority)throw new Error("Native launcher authority required;launch with codevibe --agent codex.");if(!["development","production"].includes((0,v.getEnvironment)()))throw Error("NATIVE_ENVIRONMENT_UNSUPPORTED");if(c.info("Starting CodeVibe Codex companion server",{environment:(0,v.getEnvironment)()}),this.appSyncClient=new v.AppSyncClient,!await this.appSyncClient.authenticateWithStoredTokens()){let t=(0,v.describeStoredAuthFailure)(this.appSyncClient.getLastAuthFailureKind(),this.appSyncClient.getLastAuthFailureDetail());c.error("Authentication with stored credentials failed",{kind:this.appSyncClient.getLastAuthFailureKind(),exitCode:t.exitCode}),console.error(t.message),process.exit(t.exitCode)}c.info("Authenticated successfully",{userId:this.appSyncClient.getCurrentUserId(),email:this.appSyncClient.getCurrentUserEmail()});try{let t=this.appSyncClient.getCurrentUserId(),i=AbortSignal.timeout(5e3),s=new Promise((o,d)=>i.addEventListener("abort",()=>d(new Error("status read timed out")),{once:!0})),n=await Promise.race([this.appSyncClient.getSubscriptionStatus(i),s]);if(this.appSyncClient.getCurrentUserId()!==t)throw new Error("account changed during read");n?.tier==="FREE"&&(c.info("User is on FREE tier: disabling hosted TUI parser port and using fast regex parser (Codex R1-F6, R2-F6)",{tier:n.tier}),this.tuiGemmaPort=null);let r=await Promise.race([this.appSyncClient.getCompanionSyncState(i),s]);if(this.appSyncClient.getCurrentUserId()!==t)throw new Error("account changed during read");if(n.tier!==r.tier)throw new Error("tier changed during read");c.info("Standalone Companion sync status",{tier:r.tier,protocol:r.protocol,syncState:r.usage?.syncState??null,resetAtEpochMs:r.resetAtEpochMs})}catch{c.warn("Standalone Companion sync status unavailable; cloud admission remains authoritative")}await this.restorePendingE1ResolutionsFromOutbox(),await(0,v.registerDeviceEncryptionKey)(this.appSyncClient,c),(0,v.startDeviceKeyWatcher)(this.appSyncClient,c),(0,v.pushDetectedAgents)(this.appSyncClient,c).catch(t=>{c.warn("Failed to update available agents (non-fatal)",{error:t?.message})}),this.setupEventHandlers(),this.sessionWatcher.start(),this.nativeRuntime=new st({authority:this.nativeAuthority,pluginVersion:hs().version,recoveryThreadId:process.env[Xe]==="1"?process.env.CODEVIBE_CODEX_NATIVE_THREAD:void 0,onRoot:t=>this.bindNativeRoot(t),onMessage:t=>this.handleNativeMessage(t),onFailure:(t,i)=>this.handleNativeFailure(t,i)}),await this.nativeRuntime.start(),process.send?.({type:"CODEVIBE_NATIVE_READY",instanceId:this.nativeAuthority.record.instanceId}),c.info("CodeVibe Codex companion server started")}handleNativeFailure(e,t){if(!this.isStopping){if(e==="NATIVE_HANDLER_FAILED"){c.warn("Native callback was not applied;companion remains connected",{code:e,...t?{handlerFailure:t}:{}});return}this.degradeNativeControl(e),["NATIVE_DISCONNECTED","NATIVE_PROTOCOL_INVALID","NATIVE_SOCKET_UNSAFE","NATIVE_OWNER_CHANGED"].includes(e)&&process.send?.({type:"CODEVIBE_NATIVE_CONNECTION_FAILED",instanceId:this.nativeAuthority?.record.instanceId})}}degradeNativeControl(e){this.isStopping||(this.nativeDegraded=!0,this.controlAdmission().invalidate(),["NATIVE_CONTROL_INITIALIZATION_FAILED","NATIVE_RECEIPTS_UNAVAILABLE","NATIVE_RETIREMENT_RECOVERY_FAILED"].includes(e)?(this.nativeControlOwner?.adapter.suspendAdmission(),this.emitNativeControlHealthNotice(this.nativeControlRecovery?.isExhausted?"exhausted":"unavailable").catch(()=>{}),this.scheduleNativeControlRecovery()):this.nativeControlOwner?.adapter.stopAdmission(),c.warn("Native mobile control unavailable;desktop remains independent",{code:e}))}scheduleNativeControlRecovery(){let e=this.nativeRuntime,t=this.nativeAuthority;if(this.isStopping||!e||!t)return;if(!this.nativeControlRecovery){let s=this.appSyncClient.getCurrentUserId(),n=(0,v.getEnvironment)();this.nativeControlRecovery=new ct({current:()=>(t.assertCurrent(),!this.isStopping&&this.nativeRuntime===e&&this.nativeAuthority===t&&this.appSyncClient.getCurrentUserId()===s&&(0,v.getEnvironment)()===n),recover:r=>this.recoverNativeControlFeature(r),isRecovered:()=>this.controlAdmission().isReady&&!this.nativeDegraded&&this.nativeReceiptsReady(),exhausted:()=>this.emitNativeControlHealthNotice("exhausted")})}let i=this.nativeReceiptReadiness?.snapshot();i&&this.nativeReceiptsReady()&&i.generation>(this.nativeRecoveryReadinessGeneration??0)&&(this.nativeRecoveryReadinessGeneration=i.generation,this.nativeControlRecovery.readinessChanged()),this.nativeControlRecovery.request().catch(()=>{})}async recoverNativeControlFeature(e){if(e.aborted||this.isStopping||this.nativeReplacementGate)return!1;if(this.nativeRetirement){try{await this.recoverRetiredBackendSession(this.nativeRetirement.predecessor.sessionId,e)}catch{return!1}if(e.aborted||this.isStopping||this.nativeRetirement)return!1}let t=this.controlAdmission().capture();if(!this.nativeReceiptsReady())return this.pollNativeReceipts(),!1;try{return await this.maintainNativeControl(!0,e),await this.activateNativeControl(e,void 0,t)?(this.nativeControlOwner?.adapter.recover().catch(()=>{}),this.controlAdmission().isReady&&!this.nativeDegraded):!1}catch{return!1}}async activateNativeControl(e,t,i=this.controlAdmission().capture()){let s=this.nativeControlOwner,n=this.sessionState,r=this.nativeRuntime,o=this.nativeAuthority;if(!s||!n||!r||!o||s.state!==n)return!1;let d=()=>!e?.aborted&&!this.isStopping&&this.nativeReceiptsReady()&&this.nativeReplacementGate===(t??null)&&this.nativeControlOwner===s&&(!this.nativeRetirement||!!t&&this.nativeRetirement.stage==="finish"&&this.nativeRetirement.successor===n)&&this.sessionState===n&&this.nativeRuntime===r&&this.nativeAuthority===o&&this.appSyncClient.getCurrentUserId()===n.userId;if(!d())return!1;o.assertCurrent();for(let h of r.controlFacts())await s.adapter.observe(h);await s.adapter.restoreResumedQuestions(),await s.adapter.prepareRehomes(),await this.assertNativeActiveScope(n,s.owner.scope,()=>{if(o.assertCurrent(),!d())throw Error("NATIVE_CONTROL_VALIDATION_CHANGED")});let l=this.nativeDegraded,u=this.controlAdmission().commit(i,d,()=>{s.adapter.activate(),this.nativeDegraded=!1});return u&&l&&!t&&this.emitNativeControlHealthNotice("restored").catch(()=>{}),u}async emitNativeControlHealthNotice(e){let t=this.sessionState;if(!t||this.isStopping||this.sessionState!==t||this.nativeControlNotice?.state===t&&this.nativeControlNotice.kind===e)return;this.nativeControlNotice={state:t,kind:e};let i=e==="restored"?"Mobile control is available again. Previously unconfirmed actions were not resent.":e==="exhausted"?"Mobile control could not be restored automatically. Your desktop is still running. Restart CodeVibe Companion from the desktop to restore mobile control. Unconfirmed actions have not been resent.":"Mobile control is temporarily unavailable. Your desktop is still running. Recovery is in progress. Unconfirmed actions will not be resent.",s={native_control_health:e},n={sessionId:t.sessionId,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:i,metadata:s,timestamp:(0,v.prepareEventTimestamp)({orderingKey:t.sessionId})};await this.appSyncClient.publishCompanionNotice(n,async()=>{if(this.isStopping||this.sessionState!==t)return!1;let r=this.encryptForEmit(i,s,v.EventType.NOTIFICATION,t.sessionId);return r?(await this.appSyncClient.createEvent({...n,...r}),!0):!1})}async bindNativeRoot(e){if(!this.nativeAuthority||this.isStopping)throw Error("NATIVE_ROOT_OWNER_CHANGED");this.nativeAuthority.assertCurrent(),c.info("Native root binding started",{hasTranscript:e.path!==null}),process.send?.({type:"CODEVIBE_NATIVE_BOUND",instanceId:this.nativeAuthority.record.instanceId,threadId:e.id}),this.sessionState&&this.sessionState.codexSessionId!==e.id&&await this.endActiveSession("new-codex-session-started");let t=this.nativeRetirement;if(t&&t.meta.id!==e.id){if(t.stage==="retire")throw Error("NATIVE_RETIREMENT_INCOMPLETE");this.nativeRetirement=null}await this.ensureSessionStarted({id:e.id,cwd:e.cwd,timestamp:new Date(e.createdAt*1e3).toISOString(),cli_version:e.cliVersion,model_provider:e.modelProvider,source:"native-app-server",originator:"codevibe-native-observer",instructions:null});let i=this.sessionState;if(!i||i.codexSessionId!==e.id)throw Error("NATIVE_ROOT_BINDING_INCOMPLETE");if(this.nativeControlOwner?.state!==i){if(!this.nativeDegraded)throw Error("NATIVE_ROOT_BINDING_INCOMPLETE");this.scheduleNativeControlRecovery();return}if(this.nativeDegraded&&this.scheduleNativeControlRecovery(),e.path&&this.sessionWatcher.getActiveLogFile()!==e.path){let s=await this.sessionWatcher.bindToSessionTranscript(e.path,e.id);c.info("Native transcript binding result",{status:s.status,...s.status==="rejected"?{reason:s.reason}:{}})}else c.info("Native transcript binding result",{status:e.path?"already_bound":"no_transcript_yet"});process.send?.({type:"CODEVIBE_NATIVE_BOUND",instanceId:this.nativeAuthority.record.instanceId,threadId:e.id})}initializeNativeControl(e){let t=this.nativeInitialization;if(t)return t.state===e?t.work:t.work.then(()=>this.initializeNativeControl(e));if(this.isStopping||this.sessionState!==e)return Promise.reject(Error("NATIVE_ROOT_OWNER_CHANGED"));let i=this.initializeNativeControlOwner(e),s={state:e,work:i};this.nativeInitialization=s;let n=()=>{this.nativeInitialization===s&&(this.nativeInitialization=null)};return i.then(n,n),i}async initializeNativeControlOwner(e){let t=this.controlAdmission().capture(),i=this.nativeRuntime,s=this.nativeAuthority;if(!i||!s||!e.codexSessionId)throw Error("NATIVE_ROOT_BINDING_INCOMPLETE");if(this.nativeControlOwner?.state===e)return;let n=e.userId,r=(0,v.getEnvironment)(),o=await v.keychainManager.getDeviceIdentity();if(r!=="development"&&r!=="production")throw Error("NATIVE_ENVIRONMENT_UNSUPPORTED");if(!o)throw Error("NATIVE_DEVICE_IDENTITY_UNAVAILABLE");let d=()=>{if(s.assertCurrent(),this.appSyncClient.getCurrentUserId()!==n||(0,v.getEnvironment)()!==r)throw Error("NATIVE_ACCOUNT_CHANGED")},l=await this.appSyncClient.getSession(e.sessionId);if(d(),!l?.sessionGenerationId||!l.sessionKeyGen||l.userId!==n||l.status!==v.SessionStatus.ACTIVE)throw Error("NATIVE_SCOPE_UNAVAILABLE");let u=await this.selectNativeSourceTransport(e);if(d(),u.protocol!=="SYNC_V2"||u.sessionScope.sessionGenerationId!==l.sessionGenerationId)throw Error("NATIVE_SIGNED_SCOPE_UNAVAILABLE");let h={sessionId:e.sessionId,sessionGenerationId:l.sessionGenerationId,expectedSessionKeyGen:l.sessionKeyGen},p=new Is.CodexNativeStateStore({identity:{userId:n,environment:r,deviceId:o.deviceId,nativeThreadId:e.codexSessionId},assertAccount:d,readPrivateKey:async()=>{let g=await v.keychainManager.getDeviceIdentity();if(d(),!g||g.deviceId!==o.deviceId||g.publicKey!==o.publicKey)throw Error("NATIVE_DEVICE_IDENTITY_CHANGED");return g.privateKey},assertActiveScope:async g=>{await this.assertNativeActiveScope(e,g,d,n)}});this.nativeAdmissionToken?.state!==e&&(this.nativeAdmissionToken={state:e,token:this.nativeReplacementToken??(0,Se.v4)()});let m={token:this.nativeAdmissionToken.token,pid:process.pid,host:Ze.hostname(),scope:h};if(d(),this.isStopping||this.sessionState!==e||this.nativeRuntime!==i||this.nativeAuthority!==s)throw Error("NATIVE_ROOT_OWNER_CHANGED");await p.claim(m),this.nativeReplacementToken=null;let f=new dt({store:p,owner:m,threadId:e.codexSessionId,native:i.client,assertCurrent:()=>{if(d(),!this.isExpectedSessionStateCurrent(e)||i.thread?.id!==e.codexSessionId)throw Error("NATIVE_SCOPE_CHANGED")},decode:g=>this.decodeNativeMobileInput(g,e),updateStatus:this.appSyncClient.updateEventStatus.bind(this.appSyncClient),publish:(g,y,S)=>this.publishNativePrompt(e,g,y,S),publishRejectedInput:g=>{let y=JSON.parse(g.raiseJson),S=g.reason==="ALREADY_ANSWERED"?"This request already has a response. Your reply was not applied.":"Your reply was not applied to a native control. Reopen the current prompt and try again. If this continues, update the CodeVibe app.",I={native_input_rejected:!0,reason:g.reason,rejectedEventId:g.event.eventId},w={sessionId:e.sessionId,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:S,metadata:I,...(0,v.raiseFieldsFromRecord)(y),timestamp:(0,v.prepareEventTimestamp)({orderingKey:e.sessionId})};return!this.isExpectedSessionStateCurrent(e)||g.scope.sessionId!==e.sessionId?Promise.resolve("CLOSED"):this.appSyncClient.publishCompanionPrompt(w,async()=>{let E=this.encryptForEmit(S,I,v.EventType.NOTIFICATION,e.sessionId);return!E||!this.isExpectedSessionStateCurrent(e)?!1:(await this.appSyncClient.createEvent({...w,content:E.content,metadata:E.metadata,isEncrypted:E.isEncrypted}),!0)})},resolve:g=>this.appSyncClient.resolveCompanionPrompt(g),isFreshQuestion:async(g,y,S)=>this.sessionState===e&&this.nativeQuestionFrame?.threadId===g&&this.nativeQuestionFrame.turnId===y&&this.nativeQuestionFrame.itemId===S,onFailure:g=>{c.warn("Native control operation retained",{code:g})},onDesktopOnlyApproval:g=>this.emitNativeDesktopOnlyApproval(e,g),publishQuestionCustody:(g,y)=>this.publishNativeQuestionCustody(e,g,y),resolveQuestionCustody:g=>this.appSyncClient.resolveCompanionPrompt({sessionId:g.raise.sessionId,promptId:g.raise.promptId,ownerToken:g.raise.ownerToken}),isCurrentControl:g=>i.isCurrentControl(g),hasPendingControl:()=>i.hasPendingControl(),readQuestionResumeWindow:g=>i.readQuestionResumeWindow(g),deferActivation:!0,isControlReady:()=>this.controlAdmission().isReady&&!this.nativeDegraded&&this.nativeReceiptsReady()&&!this.isStopping&&!this.nativeReplacementGate&&!this.nativeRetirement&&this.nativeControlOwner?.adapter===f});if(d(),this.isStopping||this.sessionState!==e||this.nativeRuntime!==i||this.nativeAuthority!==s)throw Error("NATIVE_ROOT_OWNER_CHANGED");this.nativeControlOwner={state:e,store:p,owner:m,adapter:f},f.prepareAdmission();for(let g of i.controlFacts())await f.observe(g);this.nativeReplacementGate||(this.nativeDegraded||await this.activateNativeControl(void 0,void 0,t),f.isAccepting&&await f.recover()),this.pollNativeReceipts(),this.startE1TtlRefresh()}async assertNativeActiveScope(e,t,i,s=e.userId){let n=await this.appSyncClient.getSession(t.sessionId);if(i(),e.sessionId!==t.sessionId||!n||n.sessionId!==t.sessionId||n.userId!==s||n.sessionGenerationId!==t.sessionGenerationId||n.sessionKeyGen!==t.expectedSessionKeyGen)throw Error("NATIVE_SCOPE_CHANGED");if(n.status!==v.SessionStatus.ACTIVE)throw n.status!==v.SessionStatus.INACTIVE?Error("NATIVE_SCOPE_CHANGED"):(!this.isStopping&&this.sessionState===e&&(this.nativeDegraded=!0,this.controlAdmission().invalidate(),this.nativeControlOwner?.state===e&&this.nativeControlOwner.adapter.stopAdmission(),this.appSyncClient.stopHeartbeat(e.sessionId),this.recoverRetiredBackendSession(e.sessionId).catch(()=>this.degradeNativeControl("NATIVE_RETIREMENT_RECOVERY_FAILED"))),new Ct)}publishNativePrompt(e,t,i,s){if(!this.isExpectedSessionStateCurrent(e)||t.scope.sessionId!==e.sessionId)return Promise.resolve("CLOSED");let n=JSON.parse(t.raiseJson),r=n.mobileActionable?v.EventType.INTERACTIVE_PROMPT:v.EventType.NOTIFICATION,o={sessionId:e.sessionId,type:r,source:v.EventSource.DESKTOP,...i,...(0,v.raiseFieldsFromRecord)(n),timestamp:(0,v.prepareEventTimestamp)({orderingKey:e.sessionId})};return this.appSyncClient.publishCompanionPrompt(o,async()=>{let d=this.encryptForEmit(i.content,i.metadata,r,e.sessionId);return!d||!this.isExpectedSessionStateCurrent(e)?!1:(await this.appSyncClient.createEvent({...o,content:d.content,metadata:d.metadata,isEncrypted:d.isEncrypted}),!0)},{reRaiseToken:s})}publishNativeQuestionCustody(e,t,i){if(!this.isExpectedSessionStateCurrent(e)||t.raise.sessionId!==e.sessionId)return Promise.resolve("CLOSED");let s="Your queued question is paused while approvals are pending.",n={native_question_custody_marker:!0,native_question_custody:{version:2,state:"PAUSED",queueId:t.queueId,questionPromptId:t.questionPromptId,through:t.through,custodyPromptId:t.raise.promptId}},r={sessionId:e.sessionId,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:s,metadata:n,...(0,v.raiseFieldsFromRecord)(t.raise),timestamp:(0,v.prepareEventTimestamp)({orderingKey:e.sessionId})};return this.appSyncClient.publishCompanionPrompt(r,async()=>{if(!this.isExpectedSessionStateCurrent(e))return!1;let o=this.encryptForEmit(s,n,v.EventType.NOTIFICATION,e.sessionId);return o?(await this.appSyncClient.createEvent({...r,...o}),!0):!1},{reRaiseToken:i})}async emitNativeDesktopOnlyApproval(e,t){if(!this.isExpectedSessionStateCurrent(e)||this.nativeRuntime?.isCurrentControl(t)!==!0)return;let i="This approval requires desktop action. Review it in Codex on your computer. Your companion remains connected.",s={native_approval_desktop_only:!0,nativeMethod:t.method,nativeRequestId:t.id},n={sessionId:e.sessionId,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:i,metadata:s,timestamp:(0,v.prepareEventTimestamp)({orderingKey:e.sessionId})};await this.appSyncClient.publishCompanionNotice(n,async()=>{if(!this.isExpectedSessionStateCurrent(e)||this.nativeRuntime?.isCurrentControl(t)!==!0)return!1;let r=this.encryptForEmit(i,s,v.EventType.NOTIFICATION,e.sessionId);return r?(await this.appSyncClient.createEvent({...n,content:r.content,metadata:r.metadata,isEncrypted:r.isEncrypted}),!0):!1})}async decodeNativeMobileInput(e,t){if(!this.isExpectedSessionStateCurrent(t)||e.sessionId!==t.sessionId)throw Error("NATIVE_SCOPE_CHANGED");let i=t.encryptionSnapshot.sessionKey;if(e.isEncrypted&&!i)throw Error("NATIVE_SESSION_KEY_UNAVAILABLE");let s=e.isEncrypted?v.cryptoService.decryptContent(e.content,i):e.content??"",n=typeof e.metadata=="string"?JSON.parse(e.metadata):e.metadata;if(n?.encrypted){if(!i)throw Error("NATIVE_SESSION_KEY_UNAVAILABLE");n=v.cryptoService.decryptMetadata(n.encrypted,i)}let r=e.promptId??null,o=n?.promptId??null;if(r!==null&&o!==null&&r!==o)throw Error("NATIVE_QUESTION_MISMATCH");let d=r??o;if(d!==null&&(typeof d!="string"||!d.length))throw Error("NATIVE_QUESTION_MISMATCH");let l=[];for(let u of e.attachments??[]){if(!u.type.startsWith("image/"))throw Error("NATIVE_ATTACHMENT_UNSUPPORTED");let h=await this.downloadAttachment(u,t.sessionId,i,e.isEncrypted??!1);if(!h||!this.isExpectedSessionStateCurrent(t))throw Error("NATIVE_ATTACHMENT_UNAVAILABLE");l.push(h)}return{text:s,promptId:d,localImages:l}}async handleNativeMessage(e){let t=this.nativeReplacementGate;t&&await t.ready;let i=this.nativeControlOwner;if(!i||this.isStopping)return;let s=e.params;try{e.method==="item/completed"&&s?.item?.type==="agentMessage"&&s.item.delivery==="async"||await i.adapter.observe(e)}catch(n){if(!(n instanceof Ct))throw n;return}["thread/status/changed","turn/started","turn/completed"].includes(e.method)&&this.maintainNativeControl().catch(()=>{})}maintainNativeControl(e=!1,t){if(this.nativeMaintenance)return this.nativeMaintenance;if(t?.aborted||this.isStopping||this.nativeReplacementGate)return Promise.resolve();if(this.nativeDegraded&&!e)return this.scheduleNativeControlRecovery(),Promise.resolve();let i=this.controlAdmission().capture(),s=(async()=>{if(!this.sessionState&&e){let d=await this.nativeRuntime?.refreshMetadata();d&&!t?.aborted&&!this.isStopping&&await this.bindNativeRoot(d)}let n=this.sessionState;if(!n||t?.aborted||this.isStopping||this.nativeReplacementGate)return;this.nativeControlOwner||await this.initializeNativeControl(n);let r=await this.nativeRuntime?.refreshMetadata();if(t?.aborted||this.sessionState!==n||this.isStopping||(r&&await this.bindNativeRoot(r),t?.aborted||this.sessionState!==n||this.isStopping))return;let o=this.nativeControlOwner?.adapter;!e&&!this.nativeDegraded&&o&&(o.isActivationPending||o.isAdmissionPaused)&&await this.activateNativeControl(t,void 0,i),await this.pruneSettledNativePredecessor(n),this.pollNativeReceipts(),this.nativeControlOwner?.adapter.isAccepting&&await this.nativeControlOwner.adapter.recover()})();return this.nativeMaintenance=s,s.then(()=>{this.nativeMaintenance=null},()=>{this.nativeMaintenance=null}),s}async pruneSettledNativePredecessor(e){let t=this.nativeControlOwner;if(!t||t.state!==e||this.sessionState!==e||this.isStopping)return;let i=await t.store.snapshot(t.owner);if(this.nativeControlOwner!==t||this.sessionState!==e||this.isStopping)return;let s=i.scopes.find(n=>{if(n.state!=="CLOSED"||n.scope.sessionId===t.owner.scope.sessionId)return!1;let r=o=>o.scope.sessionId===n.scope.sessionId;return i.entries.some(o=>r(o)&&o.kind==="INPUT")||i.entries.filter(r).every(o=>o.kind==="RETIRED_EVIDENCE"&&o.outcome!=="UNKNOWN")&&i.controls.filter(r).every(o=>o.cloudResolved&&["RESOLVED","REHOMED"].includes(o.state))});if(s)try{let n=AbortSignal.timeout(1e3);i.entries.some(r=>r.kind==="INPUT"&&r.scope.sessionId===s.scope.sessionId)&&await t.store.retirePayloads(t.owner,s.scope,async()=>{if(this.nativeControlOwner!==t||this.sessionState!==e||this.isStopping)throw Error("NATIVE_SCOPE_CHANGED")},r=>this.appSyncClient.confirmDesktopSyncRetirement(r,n)),await t.store.pruneSettled(t.owner,s.scope,r=>this.appSyncClient.confirmDesktopSyncRetirement(r,n))}catch{c.warn("Native predecessor cleanup retained for the next existing maintenance call",{code:"NATIVE_PREDECESSOR_PRUNE_PENDING"})}}async createLaunchSession(){if(this.isStopping)return;if(process.env[Xe]==="1"){c.info("Recovery daemon deferring backend bootstrap until the native rollout is known");return}let e=this.lifecycleGeneration,t=process.env.CODEVIBE_CODEX_TMUX_SESSION;if(!t){c.warn("No CODEVIBE_CODEX_TMUX_SESSION \u2014 skipping launch session");return}let i;this.launchSessionInitPromise=new Promise(s=>{i=s});try{let s=process.env.CODEX_WORKING_DIRECTORY||process.cwd(),n=this.getOrCreateBootstrapSessionId(),r=this.appSyncClient.getCurrentUserId();c.info("Creating launch session",{sessionId:n,projectPath:s});let o=!1;try{let d=await(0,v.resumeOrCreateSession)({sessionId:n,userId:r,agentType:v.AgentType.CODEX,projectPath:s,metadata:{launchSession:!0}},this.appSyncClient,c);if(n=d.sessionId,!this.isLifecycleCurrent(e)){await this.retireCancelledBootstrap(n,"launch_session");return}this.sessionKey=d.sessionKey,this.sessionKeyGen=d.sessionKeyGen,this.sessionIsEncrypted=!!d.sessionKey,o=!0,this.sessionState={sessionId:n,userId:r,projectPath:s,cwd:s,createdAt:new Date,subscriptionActive:!1,metadata:{launchSession:!0},encryptionSnapshot:{sessionKey:d.sessionKey,sessionIsEncrypted:!!d.sessionKey},codexSessionId:t,codexLogFile:void 0},this.clearSessionBootstrapFailure(),this.bootstrapSessionId=null,await L("daemon_init_step_completed",{step:"session_resume_or_create",path:"launch_session"})}catch(d){if(!this.isLifecycleCurrent(e)){let l=this.authoritativeSessionIdFromError(d)??n;await this.retireCancelledBootstrap(l,"launch_session_error");return}await L("daemon_init_step_failed",{step:"session_resume_or_create",path:"launch_session",error_class:d?.name||"Error",error_message:d?.message||String(d)}),d?.code==="ENCRYPTED_SESSION_NO_KEY"&&(this.sessionIsEncrypted=!0,this.sessionKey=null),this.bindBootstrapIdentityFromError(d),this.recordSessionBootstrapFailure(d,"launch_session"),c.error("Failed to create/resume launch session (non-fatal)",{error:d})}if(!o)return;await L("daemon_init_step_completed",{step:"session_state_set",path:"launch_session"});try{this.subscribeToMobileEvents(n)?await L("daemon_init_step_completed",{step:"subscribe_mobile_events",path:"launch_session"}):await L("daemon_init_step_failed",{step:"subscribe_mobile_events",path:"launch_session",error_class:"SubscriptionSetupFailed",error_message:"subscribeToMobileEvents returned false"})}catch(d){await L("daemon_init_step_failed",{step:"subscribe_mobile_events",path:"launch_session",error_class:d?.name||"Error",error_message:d?.message||String(d)}),c.error("Failed to subscribe to mobile events for launch session",{error:d})}try{await this.appSyncClient.startHeartbeat(n)?await L("daemon_init_step_completed",{step:"heartbeat_start",path:"launch_session"}):(await L("daemon_init_step_failed",{step:"heartbeat_start",path:"launch_session",error_class:"InitialHeartbeatNotPersisted",error_message:"Backend did not confirm the initial heartbeat mutation"}),c.error("Initial launch-session heartbeat was not persisted",{sessionId:n}))}catch(d){await L("daemon_init_step_failed",{step:"heartbeat_start",path:"launch_session",error_class:d?.name||"Error",error_message:d?.message||String(d)}),c.error("Failed to start heartbeat for launch session",{error:d})}try{await this.subscribeToOnApplyUserDecision(n)}catch(d){c.error("Failed to subscribe to onApplyUserDecision for launch session (non-fatal)",{error:d})}this.startMobileEndWatcher(n),c.info("Launch session created",{sessionId:n})}finally{i()}}encryptForEmit(e,t,i,s){let n=this.sessionState;if(!n||n.sessionId!==s||!n.encryptionSnapshot)return c.warn("Dropping event from stale or unresolved session generation (#638)",{type:i,sessionId:s,currentSessionId:n?.sessionId}),null;let{sessionKey:r,sessionIsEncrypted:o}=n.encryptionSnapshot,d=(0,v.encryptForEmit)(r,o,e,t);return d===null&&c.error("No session key for ENCRYPTED session \u2014 dropping event (fail-closed, #638)",{type:i,sessionId:s}),d}newE1Raise(e,t,i,s){let{record:n}=(0,v.newPromptRaise)({sessionId:e,producerKind:"PLUGIN_APPROVAL",mobileActionable:t,agentType:"CODEX",...i!==void 0&&{title:i}});return this.e1PromptRaises.set(n.promptId,{record:n,...s?.dedupeKey!==void 0?{resolutionDedupeKey:s.dedupeKey}:{},...s?.completionKey!==void 0?{resolutionCompletionKey:s.completionKey}:{},...s?.callId!==void 0?{resolutionCallId:s.callId}:{}}),this.e1TtlRefreshTimer||this.startE1TtlRefresh(),n}stashE1RaiseContent(e,t,i){let s=this.e1PromptRaises.get(e);s&&(s.contentPlain=t,s.metadataPlain=i)}async emitSuppressedPromptCarrier(e,t,i){return this.publishE1Prompt(e,t,v.EventType.NOTIFICATION,"\u26A0\uFE0F A prompt is waiting in your desktop terminal, but its options could not be shown here. Please answer it on your desktop.",{e1SuppressedPrompt:!0},i)}publishE1Prompt(e,t,i,s,n,r){let o=(0,v.prepareEventTimestamp)({orderingKey:e}),d={sessionId:e,type:i,source:v.EventSource.DESKTOP,content:s,metadata:n,...(0,v.raiseFieldsFromRecord)(t),timestamp:o},l=this.e1PromptRaises.get(t.promptId),u=()=>l?.record===t&&(0,v.isOpenPromptRaise)(l,this.e1PromptRaises.get(t.promptId));if(!u())return Promise.resolve("CLOSED");let h=p=>(u()&&(i===v.EventType.INTERACTIVE_PROMPT&&n.isQueuedQuestion===!0&&l&&(p==="RERAISED"?this.acknowledgedQueuedQuestionRaises.add(l):this.acknowledgedQueuedQuestionRaises.delete(l)),p==="RETRY"?this.e1NeedsReRaise.add(t.promptId):(p==="RERAISED"||p==="OMITTED")&&this.e1NeedsReRaise.delete(t.promptId)),p);return this.trackE1Raise(t.promptId,this.appSyncClient.publishCompanionPrompt(d,async()=>{let p=this.encryptForEmit(s,n,i,e);return p?(await this.appSyncClient.createEvent({...d,content:p.content,metadata:p.metadata,...i===v.EventType.NOTIFICATION&&{notificationText:s},...p.isEncrypted?{isEncrypted:!0}:{}}),!0):!1},{reRaiseToken:r}).then(h,p=>{throw h("RETRY"),p}))}raiseSuppressedBadge(e,t,i={}){if(t){if(this.hasRecentlyResolvedApprovalDedupeKey(e,t)){c.debug("Skipping suppressed-prompt carrier; approval completed while producer was in flight",{sessionId:e,dedupeKey:t});return}let n=`${e}::${t}`,r=this.e1ContentKeyIndex.get(n);if(r&&this.e1PromptRaises.has(r)){if(i.suppressTmuxObserverUntilResolved){let o=this.e1PromptRaises.get(r);o&&(o.suppressTmuxObserverUntilResolved=!0,i.observerSnapshot&&(o.suppressedObserverSnapshotKey=this.buildObserverSnapshotMatchKey(i.observerSnapshot)))}return}r&&this.e1ContentKeyIndex.delete(n)}let s=this.newE1Raise(e,!1,void 0,t?{dedupeKey:t,completionKey:i.completionKey}:void 0);if(i.suppressTmuxObserverUntilResolved){let n=this.e1PromptRaises.get(s.promptId);n&&(n.suppressTmuxObserverUntilResolved=!0,i.observerSnapshot&&(n.suppressedObserverSnapshotKey=this.buildObserverSnapshotMatchKey(i.observerSnapshot)))}t&&this.e1ContentKeyIndex.set(`${e}::${t}`,s.promptId),this.emitSuppressedPromptCarrier(e,s).catch(n=>{c.error("E1: failed to emit suppressed-prompt badge carrier",{sessionId:e,promptId:s.promptId,error:n instanceof Error?n.message:String(n)})})}snapshotOpenE1(e){return[...this.e1PromptRaises.values()].filter(t=>t.record.sessionId===e).map(t=>({record:{...t.record},...t.contentPlain!==void 0&&{contentPlain:t.contentPlain},...t.metadataPlain!==void 0&&{metadataPlain:t.metadataPlain},...t.resolutionDedupeKey!==void 0&&{resolutionDedupeKey:t.resolutionDedupeKey},...t.resolutionCompletionKey!==void 0&&{resolutionCompletionKey:t.resolutionCompletionKey},...t.resolutionCallId!==void 0&&{resolutionCallId:t.resolutionCallId},...t.suppressTmuxObserverUntilResolved!==void 0&&{suppressTmuxObserverUntilResolved:t.suppressTmuxObserverUntilResolved},...t.suppressedObserverSnapshotKey!==void 0&&{suppressedObserverSnapshotKey:t.suppressedObserverSnapshotKey}}))}buildDaemonHandoffSnapshot(e){let t=process.env[we];if(!t)throw new Error("E1_DAEMON_HANDOFF_MISSING_TMUX_SESSION");return{version:1,createdAtMs:Date.now(),tmuxSession:t,backendSessionId:e.sessionId,openRaises:this.snapshotOpenE1(e.sessionId),pendingResolutions:[...this.e1PendingResolutions.values()].map(i=>({record:{...i.record},resolutionAt:i.resolutionAt,attempts:i.attempts})),needsReRaisePromptIds:[...this.e1NeedsReRaise],permissionOccurrences:[...this.permissionRequestOccurrencesByCompletionKey.entries()].map(([i,s])=>[i,s.map(n=>({...n}))]),waitingPermissionRequests:[...this.waitingPermissionRequests.values()].filter(i=>i.ownerState===e).map(({occurrenceKey:i,dedupeKey:s,payload:n})=>({occurrenceKey:i,dedupeKey:s,payload:n})),pendingInteractivePrompt:this.pendingInteractivePrompt?{...this.pendingInteractivePrompt}:null,queuedInteractivePrompts:this.queuedInteractivePrompts.map(i=>({prompt:{...i.prompt},content:i.content,metadata:{...i.metadata}})),resolvedApprovalDedupeKeys:[...this.resolvedApprovalDedupeKeys.entries()].filter(([,i])=>i>Date.now()-zt),historicalQueuedQuestionPromptIds:[...this.historicalQueuedQuestionPromptIds].filter(i=>typeof i=="string"&&i.trim().length>0&&Buffer.byteLength(i,"utf8")<=512).slice(-1e3)}}persistDaemonHandoffState(e){for(let i of this.e1PendingResolutions.values())this.e1DurableState.writeResolution(i);let t=this.buildDaemonHandoffSnapshot(e);this.e1DurableState.writeHandoff(t),c.info("E1: persisted daemon handoff state",{sessionId:e.sessionId,openPrompts:t.openRaises.length,pendingResolutions:t.pendingResolutions.length,completionQueues:t.permissionOccurrences.length})}async adoptDaemonHandoffState(e){if(process.env[Xe]!=="1")return!1;let t=process.env[we];if(!t)return!1;let i=this.e1DurableState.readHandoff(t);if(!i)return!1;let s=this.sessionState;if(!s||s.sessionId!==e)throw new Error("E1_DAEMON_HANDOFF_WITHOUT_CURRENT_SESSION");for(let d of i.pendingResolutions)this.e1PendingResolutions.has(d.record.promptId)||this.e1PendingResolutions.set(d.record.promptId,{record:{...d.record},resolutionAt:d.resolutionAt,attempts:d.attempts}),this.e1DurableState.writeResolution(d);for(let d of i.openRaises){let l={...d,record:{...d.record},...d.metadataPlain!==void 0&&{metadataPlain:{...d.metadataPlain}}};this.e1PromptRaises.set(l.record.promptId,l),i.backendSessionId!==e&&this.e1RetirementOrphans.set(l.record.promptId,{...l,record:{...l.record}}),l.resolutionDedupeKey&&this.e1ContentKeyIndex.set(`${e}::${l.resolutionDedupeKey}`,l.record.promptId)}this.permissionRequestOccurrencesByCompletionKey=new Map(i.permissionOccurrences.map(([d,l])=>[d,l.map(u=>({...u}))])),this.e1NeedsReRaise=new Set(i.needsReRaisePromptIds);for(let d of i.waitingPermissionRequests??[])this.waitingPermissionRequests.set(d.occurrenceKey,{...d,ownerState:s,context:this.buildApprovalPromptContextFromHookPayload(d.payload)});this.pendingInteractivePrompt=i.pendingInteractivePrompt?{...i.pendingInteractivePrompt,ownerSessionId:e}:null;let n=this.pendingInteractivePrompt,r=n?.completionKey?this.permissionRequestOccurrencesByCompletionKey.get(n.completionKey):void 0;this.recoveryPermissionReplay=n?.source==="permission_hook"&&n.completionKey&&n.dedupeKey&&this.isPermissionRequestOccurrenceKey(n.dedupeKey)&&r?.some(d=>d.occurrenceKey===n.dedupeKey)?{ownerSessionId:e,completionKey:n.completionKey,occurrenceKey:n.dedupeKey}:null,this.queuedInteractivePrompts=i.queuedInteractivePrompts.map(d=>({prompt:{...d.prompt,ownerSessionId:e},content:d.content,metadata:{...d.metadata},ownerState:s}));let o=Date.now()-zt;for(let[d,l]of i.resolvedApprovalDedupeKeys){if(l<=o)continue;let u=`${i.backendSessionId}::`,h=d.startsWith(u)?`${e}::${d.slice(u.length)}`:d;this.resolvedApprovalDedupeKeys.set(h,l)}if(i.historicalQueuedQuestionPromptIds)for(let d of i.historicalQueuedQuestionPromptIds)this.recordHistoricalQueuedQuestionId(d);return i.backendSessionId!==e&&await this.drainRetirementOrphans(e),await this.drainPendingE1Resolutions(),await this.drainPendingE1ReRaises(),(this.e1PromptRaises.size>0||this.e1PendingResolutions.size>0)&&this.startE1TtlRefresh(),this.e1DurableState.removeHandoff(t),c.info("E1: adopted daemon handoff state",{fromSessionId:i.backendSessionId,replacementSessionId:e,openPrompts:i.openRaises.length,pendingResolutions:i.pendingResolutions.length,completionQueues:i.permissionOccurrences.length}),!0}parkRetirementOrphans(e){for(let t of this.snapshotOpenE1(e))this.e1RetirementOrphans.set(t.record.promptId,t)}async drainRetirementOrphans(e){if(this.e1RetirementOrphans.size===0){this.e1PendingResolutions.size>0&&!this.e1TtlRefreshTimer&&this.startE1TtlRefresh();return}c.info("E1 (\xA76a-4): re-homing parked retirement-orphan prompts onto replacement session",{replacementSessionId:e,count:this.e1RetirementOrphans.size});for(let[t,i]of[...this.e1RetirementOrphans]){let n=this.e1PromptRaises.get(t)??{record:{...i.record},...i.contentPlain!==void 0&&{contentPlain:i.contentPlain},...i.metadataPlain!==void 0&&{metadataPlain:i.metadataPlain},...i.resolutionDedupeKey!==void 0&&{resolutionDedupeKey:i.resolutionDedupeKey},...i.resolutionCompletionKey!==void 0&&{resolutionCompletionKey:i.resolutionCompletionKey},...i.resolutionCallId!==void 0&&{resolutionCallId:i.resolutionCallId}};for(let[o,d]of this.e1ContentKeyIndex.entries())d===t&&this.e1ContentKeyIndex.delete(o);n.record.sessionId=e,this.e1PromptRaises.set(t,n),n.resolutionDedupeKey&&this.e1ContentKeyIndex.set(`${e}::${n.resolutionDedupeKey}`,t);let r=await this.reRaiseOneE1(e,n,{untilAck:!0});if(r!=="RERAISED"&&r!=="OMITTED"){if(!this.e1RetirementOrphans.has(t))continue;break}this.e1RetirementOrphans.delete(t)}this.e1TtlRefreshTimer||this.startE1TtlRefresh()}isReRaiseTargetCurrent(e){return!this.isStopping&&this.sessionState!==null&&this.sessionState.sessionId===e}async reRaiseOneE1(e,t,i){let s=t.record;if(!(0,v.canRecoverPromptRaise)(t,this.e1RaiseInFlight.has(s.promptId)))return"RETRY";let n=s.mobileActionable&&t.contentPlain!==void 0,r=i?.untilAck??!1,o=4,d=4e3;for(let l=1;r||l<=o;l++){if(!(0,v.isOpenPromptRaise)(t,this.e1PromptRaises.get(s.promptId)))return"CLOSED";if(r&&!this.isReRaiseTargetCurrent(e))return this.e1NeedsReRaise.add(s.promptId),c.warn("E1: retirement re-raise aborted (stopping/superseded) \u2014 parked",{sessionId:e,promptId:s.promptId}),"RETRY";try{let u;return n?u=await this.publishE1Prompt(e,s,v.EventType.INTERACTIVE_PROMPT,t.contentPlain,t.metadataPlain??{},i?.reRaiseToken):(s.mobileActionable=!1,u=await this.emitSuppressedPromptCarrier(e,s,i?.reRaiseToken)),u==="RETRY"||u==="CLOSED"||(this.e1NeedsReRaise.delete(s.promptId),c.info("E1: prompt publication settled",{sessionId:e,promptId:s.promptId,actionable:n,disposition:u})),u}catch(u){if(!r&&l===o)return this.e1NeedsReRaise.add(s.promptId),c.error("E1: re-raise unacked after backoff \u2014 parked for retry-until-ack",{sessionId:e,promptId:s.promptId,error:u instanceof Error?u.message:String(u)}),"RETRY";if(r){let h=Date.now()+Math.min(250*2**(l-1),d);for(;Date.now()<h&&this.isReRaiseTargetCurrent(e);)await new Promise(p=>setTimeout(p,Math.min(50,h-Date.now())))}else await new Promise(h=>setTimeout(h,250*l))}}return"RETRY"}async drainPendingE1ReRaises(){if(this.e1NeedsReRaise.size!==0)for(let e of[...this.e1NeedsReRaise]){let t=this.e1PromptRaises.get(e);if(!t){this.e1NeedsReRaise.delete(e);continue}!this.sessionState||t.record.sessionId!==this.sessionState.sessionId||await this.reRaiseOneE1(t.record.sessionId,t)}}beginE1Resolution(e,t){if(this.e1PendingResolutions.has(e))return!0;let i=this.e1PromptRaises.get(e);if(!i||i.record.sessionId!==t)return!1;this.e1PromptRaises.delete(e),this.e1NeedsReRaise.delete(e),this.e1RetirementOrphans.delete(e);for(let[s,n]of this.e1ContentKeyIndex.entries())n===e&&this.e1ContentKeyIndex.delete(s);return this.e1PendingResolutions.set(e,{record:{...i.record},resolutionAt:new Date().toISOString(),attempts:0}),this.e1TtlRefreshTimer||this.startE1TtlRefresh(),!0}async emitE1Resolution(e){let t=this.e1ResolutionInFlight.get(e);if(t)return t;if(!this.e1PendingResolutions.has(e))return;let i=(async()=>{let s=this.e1PendingResolutions.get(e);if(s){try{this.e1DurableState.writeResolution(s)}catch(n){c.error("E1: failed to persist exact-clear outbox record",{promptId:e,error:n instanceof Error?n.message:String(n)})}try{let n=this.e1RaiseInFlight.get(e);if(n&&await n,s=this.e1PendingResolutions.get(e),!s)return;if(!await this.appSyncClient.resolveCompanionPrompt({sessionId:s.record.sessionId,promptId:s.record.promptId,ownerToken:s.record.ownerToken,resolutionAt:s.resolutionAt}))throw new Error("E1_PLUGIN_RESOLUTION_NOT_ACKNOWLEDGED: exact prompt id was not returned");this.e1PendingResolutions.delete(e);try{this.e1DurableState.removeResolution(e)}catch(o){c.warn("E1: exact-clear ACKed but outbox cleanup failed",{promptId:e,error:o instanceof Error?o.message:String(o)})}c.info("E1: plugin approval resolution acknowledged",{sessionId:s.record.sessionId,promptId:e})}catch(n){let r=this.e1PendingResolutions.get(e);c.warn("E1: plugin approval resolution unacknowledged; parked for retry",{sessionId:r?.record.sessionId,promptId:e,error:n instanceof Error?n.message:String(n)})}}})();this.e1ResolutionInFlight.set(e,i);try{await i}finally{this.e1ResolutionInFlight.get(e)===i&&this.e1ResolutionInFlight.delete(e)}}trackE1Raise(e,t){let i=t.then(()=>{},()=>{});return this.e1RaiseInFlight.set(e,i),i.then(()=>{this.e1RaiseInFlight.get(e)===i&&this.e1RaiseInFlight.delete(e)}),t}async drainPendingE1Resolutions(){for(let[e,t]of[...this.e1PendingResolutions.entries()])t.attempts+=1,await this.emitE1Resolution(e)}async restorePendingE1ResolutionsFromOutbox(){let{records:e,rejected:t}=this.e1DurableState.readResolutions();for(let i of t)c.error("E1: rejected unsafe or invalid resolution outbox record",i);for(let i of e){let s=this.e1PendingResolutions.get(i.record.promptId);(!s||i.attempts>s.attempts)&&this.e1PendingResolutions.set(i.record.promptId,{record:{...i.record},resolutionAt:i.resolutionAt,attempts:i.attempts})}e.length>0&&(c.info("E1: recovered pending exact-clear outbox records",{count:e.length}),await this.drainPendingE1Resolutions(),this.e1PendingResolutions.size>0&&!this.e1TtlRefreshTimer&&this.startE1TtlRefresh())}async drainPendingE1ResolutionsForLifecycleEnd(e={}){let t=e.maxWaitMs??4e3,i=e.retryDelayMs??250,s=Date.now()+Math.max(0,t),n=0;do{if(await this.drainPendingE1Resolutions(),this.e1PendingResolutions.size===0)return;if(n+=1,Date.now()>=s)break;await new Promise(r=>setTimeout(r,Math.min(i*n,Math.max(0,s-Date.now()))))}while(Date.now()<s);for(let r of this.e1PendingResolutions.values())this.e1DurableState.writeResolution(r);c.warn("E1: graceful lifecycle ended with durable exact-clear work pending",{count:this.e1PendingResolutions.size})}beginE1PromptResolutions(e,t){let i=[];for(let s of new Set(e))this.beginE1Resolution(s,t)&&i.push(s);return i}launchE1Resolutions(e){Promise.all([...e].map(t=>this.emitE1Resolution(t)))}async exactClearOpenE1ForLifecycleEnd(e){let t=[...this.e1PromptRaises.values()].filter(s=>s.record.sessionId===e).map(s=>s.record.promptId),i=this.beginE1PromptResolutions(t,e);await Promise.all(i.map(s=>this.emitE1Resolution(s)))}async refreshE1Ttls(){if(this.nativeAuthority){try{await this.nativeControlOwner?.adapter.refreshPromptTtls((i,s)=>this.appSyncClient.refreshSessionOpenPromptTtl(i,s))}catch{c.warn("Native prompt TTL refresh retained for the next existing tick")}try{await this.maintainNativeControl()}catch{c.warn("Native control recovery retained for the next existing tick")}return}await this.drainPendingE1Resolutions(),await this.drainPendingE1ReRaises();let e=this.sessionState?.sessionId;if(!e)return;let t=[...this.e1PromptRaises.values()].filter(i=>i.record.sessionId===e&&(0,v.canRecoverPromptRaise)(i,this.e1RaiseInFlight.has(i.record.promptId))).map(i=>i.record.promptId);if(t.length!==0)try{await this.appSyncClient.refreshSessionOpenPromptTtl({sessionId:e,promptIds:t},async(i,s)=>{let n=this.e1PromptRaises.get(i);return!n||n.record.sessionId!==e||this.sessionState?.sessionId!==e?"CLOSED":this.reRaiseOneE1(e,n,{reRaiseToken:s})})}catch(i){c.warn("E1: TTL-refresh tick failed (non-fatal, retries next tick)",{error:i instanceof Error?i.message:String(i)})}}startE1TtlRefresh(){this.e1TtlRefreshTimer&&clearInterval(this.e1TtlRefreshTimer),this.e1TtlRefreshTimer=setInterval(()=>{this.refreshE1Ttls()},a.E1_TTL_REFRESH_MS)}stopE1TtlRefresh(){this.e1TtlRefreshTimer&&(clearInterval(this.e1TtlRefreshTimer),this.e1TtlRefreshTimer=null)}isExpectedSessionStateCurrent(e){return!this.isStopping&&this.sessionState===e&&!this.terminalInputBlockedStates.has(e)}sendSessionPinnedInput(e,t,i){if(!this.isExpectedSessionStateCurrent(e)||this.terminalInputBlockedStates.has(e))return Promise.resolve(!1);let s=this.terminalInputChain.then(async()=>!this.isExpectedSessionStateCurrent(e)||this.terminalInputBlockedStates.has(e)||!await this.verifyNoActiveCodexChooser(e.sessionId)||i&&(await i(),!this.isExpectedSessionStateCurrent(e)||!await this.verifyNoActiveCodexChooser(e.sessionId)||!this.isExpectedSessionStateCurrent(e))||!await this.promptResponder.sendLiteral(e.sessionId,t)||(await new Promise(n=>setTimeout(n,500)),!this.isExpectedSessionStateCurrent(e))||!await this.verifyNoActiveCodexChooser(e.sessionId)?!1:this.promptResponder.sendKey(e.sessionId,"Enter"));return this.terminalInputChain=s.then(()=>{},()=>{}),s}async verifyNoActiveCodexChooser(e){try{let t=await this.tmuxPaneObserver.captureSnapshot();if(this.tmuxPaneObserver.extractActivePromptBlock(t))return!1;let s=ae(t).split(`
51
53
  `).slice(-25).join(`
52
- `);return!/Press a number to choose/i.test(s)}catch(t){return c.warn("Failed to verify that no Codex chooser is active",{sessionId:e,error:t instanceof Error?t.message:String(t)}),!1}}sendVerifiedPromptInput(e,t,i){if(!this.isExpectedSessionStateCurrent(e))return Promise.resolve("stale");let s=this.terminalInputChain.then(async()=>{if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t||t.ownerSessionId!==e.sessionId)return"stale";if(t.kind==="queued_question"||t.source==="queued_question")try{return await this.deliverQueuedQuestionResponse(e,t,i)}catch(o){return c.error("Failed to deliver queued question response",{sessionId:e.sessionId,promptId:t.promptId,error:o instanceof Error?o.message:String(o)}),"unverified"}if(!t.observerMatchKey)return c.warn("Refusing mobile prompt input without a captured pane identity",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(t.terminalMenuIdentity)try{return await(0,ps.selectTerminalMenuOption)(t.terminalMenuIdentity,i,{current:()=>this.isExpectedSessionStateCurrent(e)&&this.pendingInteractivePrompt===t,read:async()=>(0,M.parseActiveTerminalMenu)(await this.tmuxPaneObserver.captureSnapshot()),key:o=>this.promptResponder.sendKey(e.sessionId,o),wait:()=>new Promise(o=>setTimeout(o,100))})}catch{return"unverified"}let n=null;try{let o=await this.tmuxPaneObserver.captureSnapshot(),a=this.tmuxPaneObserver.extractActiveApprovalBlock(o),l=a?(0,M.parseInteractivePrompt)(a):null;n=l?this.buildObserverPromptMatchKey(l,a??void 0):null}catch(o){return c.warn("Failed to re-probe Codex prompt before mobile input",{sessionId:e.sessionId,promptId:t.promptId,error:o instanceof Error?o.message:String(o)}),"unverified"}if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"stale";if(!n||n!==t.observerMatchKey)return c.warn("Refusing mobile input because the live Codex prompt changed",{sessionId:e.sessionId,promptId:t.promptId,hasLiveIdentity:!!n}),"unverified";let r=i===xe?await this.promptResponder.sendKey(e.sessionId,"Escape"):await this.promptResponder.sendLiteral(e.sessionId,i);return r?"sent":"send_failed"});return this.terminalInputChain=s.then(()=>{},()=>{}),s}sendVerifiedFollowUpAfterDismissal(e,t,i,s){let n=this.terminalInputChain.then(async()=>{let r=()=>this.isExpectedSessionStateCurrent(e)&&t.ownerSessionId===e.sessionId;return r()?!await this.verifyNoActiveCodexChooser(e.sessionId)||!r()||s&&(await s(),!r()||!await this.verifyNoActiveCodexChooser(e.sessionId)||!r())?"unverified":await this.promptResponder.sendLiteral(e.sessionId,i)?(await new Promise(o=>setTimeout(o,500)),r()?!await this.verifyNoActiveCodexChooser(e.sessionId)||!r()?"unverified":await this.promptResponder.sendKey(e.sessionId,"Enter")?"sent":"send_failed":"stale"):"send_failed":"stale"});return this.terminalInputChain=n.then(()=>{},()=>{}),n}sendConversationContinuation(e,t,i){if(!this.isExpectedSessionStateCurrent(e))return Promise.resolve("stale");let s=this.terminalInputChain.then(async()=>{if(!this.isExpectedSessionStateCurrent(e))return"stale";try{let n=new Set;for(;;){let r=await this.tmuxPaneObserver.captureSnapshot();if(!this.isExpectedSessionStateCurrent(e))return"stale";let o=this.tmuxPaneObserver.extractActivePromptBlock(r);if(!o)break;let a=this.tmuxPaneObserver.hashPromptSnapshot(o);if(n.has(a)||n.size>=4)return"unverified";if(n.add(a),!await this.promptResponder.sendKey(e.sessionId,"Escape"))return"send_failed";if(await new Promise(l=>setTimeout(l,200)),!this.isExpectedSessionStateCurrent(e))return"stale"}}catch(n){return c.warn("Failed to inspect Codex chooser before conversation continuation",{sessionId:e.sessionId,error:n instanceof Error?n.message:String(n)}),"unverified"}return i&&(await i(),!this.isExpectedSessionStateCurrent(e)||!await this.verifyNoActiveCodexChooser(e.sessionId)||!this.isExpectedSessionStateCurrent(e))?"unverified":await this.promptResponder.sendLiteral(e.sessionId,t)?(await new Promise(n=>setTimeout(n,500)),this.isExpectedSessionStateCurrent(e)?await this.verifyNoActiveCodexChooser(e.sessionId)?await this.promptResponder.sendKey(e.sessionId,"Enter")?"sent":"send_failed":"unverified":"stale"):"send_failed"});return this.terminalInputChain=s.then(()=>{},()=>{}),s}handleEventFromHook(e){if(this.nativeAuthority||this.isStopping)return Promise.resolve();let t=this.lifecycleGeneration,i=this.registerQueuedPermissionRequest(e,t),s=this.hookEventChain.then(()=>this.processHookEvent(e,t,i??void 0)),n=i?s.finally(()=>this.unregisterQueuedPermissionRequest(i)):s;return this.hookEventChain=n.catch(r=>{c.error("[Hooks] event handler failed",{hookEvent:e.hook_event_name,sessionId:e.session_id,error:r instanceof Error?r.message:String(r)})}),n}registerQueuedPermissionRequest(e,t){if(e.hook_event_name!=="PermissionRequest"||!this.sessionState||this.sessionWatcher.getAuthoritativeSessionId()!==e.session_id)return null;let i=this.sessionState.sessionId;this.queuedPermissionRequestSessionCounts.set(i,(this.queuedPermissionRequestSessionCounts.get(i)??0)+1);let s=this.buildApprovalPromptContextFromHookPayload(e),n=this.buildApprovalDedupeKey(s),r=`permission:${(0,ye.v4)()}`,o=n?`${i}::${n}`:void 0;o&&this.queuedPermissionRequestDedupeKeys.set(o,(this.queuedPermissionRequestDedupeKeys.get(o)??0)+1);let a={sessionId:i,lifecycleGeneration:t,context:s,dedupeKey:n,occurrenceKey:r,dedupeRegistryKey:o,disposition:"pending"};if(n){let p=this.permissionRequestOccurrencesByCompletionKey.get(n)??[];p.push({occurrenceKey:r,hookObserved:!1,jsonlObserved:!1}),this.permissionRequestOccurrencesByCompletionKey.set(n,p)}let l=this.queuedPermissionRequestRegistrations.get(i)??[];return l.push(a),this.queuedPermissionRequestRegistrations.set(i,l),a}async unregisterQueuedPermissionRequest(e){let t=this.queuedPermissionRequestSessionCounts.get(e.sessionId)??0;if(t<=1?this.queuedPermissionRequestSessionCounts.delete(e.sessionId):this.queuedPermissionRequestSessionCounts.set(e.sessionId,t-1),e.dedupeRegistryKey){let o=this.queuedPermissionRequestDedupeKeys.get(e.dedupeRegistryKey)??0;o<=1?this.queuedPermissionRequestDedupeKeys.delete(e.dedupeRegistryKey):this.queuedPermissionRequestDedupeKeys.set(e.dedupeRegistryKey,o-1)}let s=(this.queuedPermissionRequestRegistrations.get(e.sessionId)??[]).filter(o=>o!==e);s.length>0?this.queuedPermissionRequestRegistrations.set(e.sessionId,s):this.queuedPermissionRequestRegistrations.delete(e.sessionId),(e.disposition==="pending"||e.disposition==="dropped"||this.sessionState?.sessionId!==e.sessionId)&&this.removePermissionRequestOccurrence(e.dedupeKey,e.occurrenceKey);let n=this.deferredTmuxPromptCandidates.get(e);if(!n)return;if(this.deferredTmuxPromptCandidates.delete(e),!this.isLifecycleCurrent(e.lifecycleGeneration)){e.disposition="dropped",this.removePermissionRequestOccurrence(e.dedupeKey,e.occurrenceKey),c.debug("Discarding deferred tmux prompt after lifecycle invalidation",{sessionId:e.sessionId,lifecycleGeneration:e.lifecycleGeneration,currentLifecycleGeneration:this.lifecycleGeneration});return}let r=this.hasRecentlyResolvedApprovalDedupeKey(e.sessionId,e.occurrenceKey);if(e.disposition==="covered"||e.disposition==="resolved"||r){c.debug("Discarding deferred tmux prompt covered by its PermissionRequest",{sessionId:e.sessionId,dedupeKey:e.dedupeKey,disposition:e.disposition});return}if(!(e.disposition==="dropped"||this.sessionState?.sessionId!==e.sessionId)){c.debug("Replaying deferred tmux prompt after PermissionRequest produced no durable owner",{sessionId:e.sessionId,dedupeKey:e.dedupeKey});try{await this.handleTmuxPromptCandidate(n.snapshot,e,n.promptHash)}catch(o){c.error("Failed to replay deferred tmux prompt candidate",{sessionId:e.sessionId,error:o instanceof Error?o.message:String(o)})}}}removePermissionRequestOccurrence(e,t){if(!e||!t)return;let i=this.permissionRequestOccurrencesByCompletionKey.get(e);if(!i)return;let s=i.filter(n=>n.occurrenceKey!==t);s.length>0?this.permissionRequestOccurrencesByCompletionKey.set(e,s):this.permissionRequestOccurrencesByCompletionKey.delete(e)}observePermissionRequestCompletion(e,t){if(!e)return{shouldResolve:!0};let i=this.permissionRequestOccurrencesByCompletionKey.get(e);if(!i)return{shouldResolve:!0};let s=t==="hook"?"hookObserved":"jsonlObserved",n=i.find(o=>!o[s]);if(!n)return c.debug("Ignoring duplicate interactive-prompt completion observation",{completionKey:e,producer:t}),{shouldResolve:!1};let r=!n.hookObserved&&!n.jsonlObserved;return n[s]=!0,n.hookObserved&&n.jsonlObserved&&this.removePermissionRequestOccurrence(e,n.occurrenceKey),{shouldResolve:r,occurrenceKey:n.occurrenceKey}}isPermissionRequestOccurrenceKey(e){return e.startsWith("permission:")}consumeRecoveryPermissionReplay(e,t,i){let s=this.recoveryPermissionReplay,n=this.pendingInteractivePrompt;return!s||!t||s.ownerSessionId!==e.sessionId||s.completionKey!==t||n?.ownerSessionId!==e.sessionId||n.source!=="permission_hook"||n.dedupeKey!==s.occurrenceKey||n.completionKey!==s.completionKey?!1:(this.recoveryPermissionReplay=null,i&&(this.removePermissionRequestOccurrence(i.dedupeKey,i.occurrenceKey),i.occurrenceKey=s.occurrenceKey,i.disposition="covered"),c.info("[Hooks] Reused adopted PermissionRequest occurrence for one recovery replay",{sessionId:e.sessionId,completionKey:t,occurrenceKey:s.occurrenceKey}),!0)}async processHookEvent(e,t,i){if(!this.isLifecycleCurrent(t))return;let{session_id:s,hook_event_name:n,type:r,content:o,metadata:a}=e;c.info("[Hooks] Received event",{sessionId:s,hookEvent:n,type:r,contentLength:o?.length});let l=this.sessionWatcher.getAuthoritativeSessionId();if(l&&l!==s){c.warn("[Hooks] Rejecting event for foreign native session",{hookEvent:n,sessionId:s,authoritativeSessionId:l});return}if(a?.transcript_path){let u=await this.sessionWatcher.bindToSessionTranscript(a.transcript_path,s);if(!this.isLifecycleCurrent(t))return;let m=u.status==="pending"?await u.completion:u;if(!this.isLifecycleCurrent(t))return;if(m.status!=="bound"){c.warn("[Hooks] Rejecting event whose transcript ownership was not proven",{hookEvent:n,sessionId:s,reason:m.reason});return}}else if(l!==s){c.warn("[Hooks] Rejecting event without an owned transcript",{hookEvent:n,sessionId:s});return}if(!this.isLifecycleCurrent(t)||this.sessionWatcher.getAuthoritativeSessionId()!==s){c.warn("[Hooks] Rejecting event after ownership changed during admission",{hookEvent:n,sessionId:s,authoritativeSessionId:this.sessionWatcher.getAuthoritativeSessionId()});return}if(this.hooksActive=!0,n==="SessionStart"){if(this.launchSessionInitPromise&&(await this.launchSessionInitPromise,!this.isLifecycleCurrent(t)))return;if(this.sessionState){if(c.info("[Hooks] SessionStart \u2014 launch session already exists, updating codexSessionId",{existingSessionId:this.sessionState.sessionId,codexSessionId:s}),this.sessionState.codexSessionId=s,this.sessionState.metadata={...this.sessionState.metadata,codexSessionId:s,cliVersion:a?.model||"unknown",modelProvider:a?.model||"unknown",launchSession:void 0},this.appSyncClient.updateSession({sessionId:this.sessionState.sessionId,metadata:this.sessionState.metadata}).catch(u=>c.warn("Failed to update session metadata",{error:u})),await this.startTmuxObserverWithBeacon("session_start_existing"),!this.isLifecycleCurrent(t))return;await this.ensureToolActivityStarted(s)}else{let u={id:s,timestamp:new Date().toISOString(),cwd:a?.cwd||process.cwd(),originator:"hook",cli_version:a?.model||"unknown",instructions:null,source:a?.source||"startup",model_provider:a?.model||"unknown"};await this.ensureSessionStarted(u)}return}if(!this.sessionState){c.warn("[Hooks] Hook event for un-bootstrapped session \u2014 self-healing via session bootstrap (#638)",{hookEvent:n,sessionId:s});let u={id:s,timestamp:new Date().toISOString(),cwd:a?.cwd||process.cwd(),originator:"hook",cli_version:a?.model||"unknown",instructions:null,source:a?.source||"startup",model_provider:a?.model||"unknown"};if(await this.ensureSessionStarted(u),!this.isLifecycleCurrent(t))return;if(!this.sessionState){c.warn("[Hooks] Session still not initialized after self-heal, dropping event",{hook_event_name:n});return}}let p=this.sessionState,f=p.sessionId;if(r==="USER_PROMPT"){let u=Ne(o)!==null;if(await this.reconcileNativeQuestionReply(o,p),this.sessionState!==p||(u||(this.approvalDetector.clear(),this.clearInteractivePromptsForAcceptedInput(p)),(await this.selectNativeSourceTransport(p)).protocol==="SYNC_V2"))return}if(r==="USER_PROMPT"&&o){let u=this.consumeRecentMobilePrompt(f,o);if(u){c.info("[Hooks] Skipping duplicate USER_PROMPT from mobile",{sessionId:f,matchType:u.matchType,originalLength:u.originalLength,echoLength:u.echoLength});return}}if(n==="PreToolUse"){c.debug("[Hooks] PreToolUse observed; AppSync emission suppressed",{toolName:a?.tool_name||"unknown",sessionId:f});return}if(n==="PermissionRequest"){let u=i??this.registerQueuedPermissionRequest(e,t);if(!u){c.error("[Hooks] Dropping admitted PermissionRequest without occurrence registration",{sessionId:f,nativeSessionId:s});return}try{await this.handlePermissionRequestHook(e,p,u)}finally{i||await this.unregisterQueuedPermissionRequest(u)}return}if(n==="PostToolUse"){let u=a?.tool_name;if(this.isQueuedQuestionTool(u)){await this.handleQueuedQuestionHook(e,p);return}let m=this.buildApprovalPromptContextFromHookPayload(e),h=this.buildApprovalDedupeKey(m),I=this.firstString(a?.tool_use_id,a?.call_id,a?.callId)??"",y=this.observePermissionRequestCompletion(h,"hook");if(y.shouldResolve&&await this.clearResolvedInteractivePrompt(I,y.occurrenceKey??h),!this.isExpectedSessionStateCurrent(p)||this.toolActivity?.isActive()&&await this.toolActivity.observeCall({callId:a?.tool_use_id??a?.call_id??a?.callId,toolName:a?.tool_name,toolInput:a?.tool_input})!=="closed"||!this.isExpectedSessionStateCurrent(p))return;let w=await this.selectNativeSourceTransport(p);if(!this.isExpectedSessionStateCurrent(p))return;if(w.protocol==="SYNC_V2")throw new Error("SYNC_SOURCE_TOOL_NOT_ADMITTED");let v=this.encryptForEmit(o,a,g.EventType.TOOL_USE,f);if(!v)return;let S=v.content,P=v.metadata,b=v.isEncrypted,R=a?.tool_use_id??a?.call_id??a?.callId,_=typeof R=="string"&&R.length>0&&!!this.sessionKey,D=_?this.getToolActivityLegacyRecorder(f):void 0;D&&_&&D.markLegacyInFlight(R);try{let N=await this.appSyncClient.createEvent({sessionId:f,type:g.EventType.TOOL_USE,source:g.EventSource.DESKTOP,content:S,metadata:P,isEncrypted:b,timestamp:(0,g.prepareEventTimestamp)({orderingKey:f})});D&&_&&((0,g.isPersistedEventResult)(N)?await D.finalizeLegacyOwned([R]):D.clearLegacyInFlight(R))}catch(N){throw D&&_&&D.clearLegacyInFlight(R),N}return}if(r==="ASSISTANT_RESPONSE"||r==="USER_PROMPT"){if(r==="ASSISTANT_RESPONSE"){this.sessionWatcher.getBindSource()==="authoritative"&&this.sessionWatcher.getAuthoritativeSessionId()===s?c.debug("[Hooks] Suppressing Stop final \u2014 JSONL watcher authoritatively bound to this session (Bug #2)"):c.warn("[Hooks] Dropping Stop final after authoritative ownership changed",{authoritativeSessionId:this.sessionWatcher.getAuthoritativeSessionId()});return}let u=this.encryptForEmit(Ei(o),void 0,g.EventType.USER_PROMPT,f);if(!u)return;await this.appSyncClient.createEvent({sessionId:f,type:g.EventType.USER_PROMPT,source:g.EventSource.DESKTOP,content:u.content,isEncrypted:u.isEncrypted,timestamp:(0,g.prepareEventTimestamp)({orderingKey:f})});return}}mapToolName(e){return{shell_command:"Bash",shell:"Bash",apply_patch:"Edit",create_file:"Write",read_file:"Read"}[e]||e}trackMobilePrompt(e,t){this.mobilePromptDeduper.track(e,t),c.debug("Tracking mobile prompt for USER_PROMPT echo deduplication",{sessionId:e,promptLength:t.trim().length})}forgetMobilePrompt(e,t){this.mobilePromptDeduper.forget(e,t)}consumeRecentMobilePrompt(e,t){return this.mobilePromptDeduper.consumeIfDuplicate(e,t)}async trackDurableMobileEcho(e,t,i,s){if(!(0,g.requiresSyncInputDeliveryReceipt)(t)){this.trackMobilePrompt(e.sessionId,i);return}let n=await this.selectNativeSourceTransport(e);if(n.protocol!=="SYNC_V2"||!this.isExpectedSessionStateCurrent(e)||t.sessionId!==n.sessionScope.sessionId||t.sessionGenerationId!==n.sessionScope.sessionGenerationId)throw Error("SYNC_ECHO_OWNER_CHANGED");i.trim()&&await n.writer.mobileEchoes("codex").arm({eventId:t.eventId,timestamp:t.timestamp,type:t.type,lane:s},i,{nowMs:Date.now(),windowMs:1e4,allowSuffix:!0,normalization:"whitespace"})}setupEventHandlers(){this.sessionWatcher.on("session-started",async e=>{try{if(this.launchSessionInitPromise&&await this.launchSessionInitPromise,this.sessionState){c.info("[JSONL] Session already active, skipping",{currentSessionId:this.sessionState.sessionId,codexSessionId:e.id}),await this.ensureToolActivityStarted(e.id);return}await this.ensureSessionStarted(e)}catch(t){c.error("[JSONL] session-started handler failed (non-fatal) \u2014 next event retries",{codexSessionId:e?.id,error:String(t)})}}),this.sessionWatcher.on("log-entry",e=>{this.enqueueLogEntry(e)}),this.sessionWatcher.on("error",e=>{c.error("Session watcher error:",e)}),!this.nativeAuthority&&(this.approvalDetector.on("approval-pending",async e=>{try{await this.handleApprovalPending(e)}catch(t){c.error("approval-pending handler failed (non-fatal)",{error:String(t)})}}),this.tmuxPaneObserver.on("prompt-candidate",async e=>{try{await this.handleTmuxPromptCandidate(e.snapshot,void 0,e.promptHash)}catch(t){c.error("prompt-candidate handler failed (non-fatal)",{error:String(t)})}}),this.tmuxPaneObserver.on("prompt-cleared",e=>{let t=this.sessionState;t&&this.clearObservedInteractivePrompt(t,e.promptHash).catch(i=>{c.error("prompt-cleared handler failed (non-fatal)",{error:String(i)})})}),this.tmuxPaneObserver.on("observer-error",e=>{c.debug("Tmux pane observer error",{error:e})}))}async ensureSessionStarted(e,t){if(this.isStopping||(this.launchSessionInitPromise&&await this.launchSessionInitPromise,this.isStopping)||this.sessionState)return;process.env[je]==="1"&&await this.bindRecoveryBootstrapIdentity(e.id);let i=this.sessionBootstrapRetryAt-Date.now();if(i>0){c.warn("Session bootstrap is in retry backoff; hook will be retried later",{codexSessionId:e.id,retryDelayMs:i,failureCount:this.sessionBootstrapFailureCount});return}if(this.sessionStartedInitPromise){try{await this.sessionStartedInitPromise}catch{}return}let s=this.handleSessionStarted(e,t);this.sessionStartedInitPromise=s.catch(()=>{});try{await s}finally{this.sessionStartedInitPromise=null}}async handleSessionStarted(e,t){if(this.isStopping)return;let i=this.lifecycleGeneration;c.info("Handling new Codex session",{codexSessionId:e.id}),this.isInitializingSession=!0,this.bufferedLogEntries=[],this.sessionState&&await this.endActiveSession("new-codex-session-started");let s=this.nativeAuthority?e.cwd:process.env.CODEX_WORKING_DIRECTORY||e.cwd||process.cwd(),n=this.getOrCreateBootstrapSessionId(),r=this.appSyncClient.getCurrentUserId(),o={codexSessionId:e.id,cliVersion:e.cli_version,modelProvider:e.model_provider,...this.nativeAuthority?{codexNativeInstanceId:this.nativeAuthority.record.instanceId}:{}},a={sessionKey:null,sessionIsEncrypted:!0};try{let l={sessionId:n,userId:r,agentType:g.AgentType.CODEX,projectPath:s,metadata:o},p=await this.resumeOrCreateBootstrapSession(l);if(n=p.sessionId,!this.isLifecycleCurrent(i)){this.isInitializingSession=!1,await this.retireCancelledBootstrap(n,"session_started");return}this.sessionKey=p.sessionKey,this.sessionKeyGen=p.sessionKeyGen,this.sessionIsEncrypted=!!p.sessionKey,a={sessionKey:p.sessionKey,sessionIsEncrypted:!!p.sessionKey},await L("daemon_init_step_completed",{step:"session_resume_or_create",path:"session_started"})}catch(l){if(this.isInitializingSession=!1,!this.isLifecycleCurrent(i)){let p=this.authoritativeSessionIdFromError(l)??n;await this.retireCancelledBootstrap(p,"session_started_error");return}throw await L("daemon_init_step_failed",{step:"session_resume_or_create",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),l?.code==="ENCRYPTED_SESSION_NO_KEY"&&(this.sessionIsEncrypted=!0,this.sessionKey=null),this.bindBootstrapIdentityFromError(l),this.recordSessionBootstrapFailure(l,"session_started"),c.error("Failed to create/resume session:",l),l}try{this.sessionState={sessionId:n,userId:r,projectPath:s,cwd:e.cwd,createdAt:new Date,subscriptionActive:!1,metadata:o,encryptionSnapshot:a,codexSessionId:e.id,codexLogFile:this.sessionWatcher.getActiveLogFile()||void 0},this.clearSessionBootstrapFailure(),this.bootstrapSessionId=null,this.recoveryBootstrapOwnerBound=!1,await L("daemon_init_step_completed",{step:"session_state_set",path:"session_started"})}catch(l){await L("daemon_init_step_failed",{step:"session_state_set",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),c.error("Failed to set session state:",l)}if(this.nativeAuthority){if(!this.sessionState)throw Error("NATIVE_SESSION_BINDING_INCOMPLETE");await this.ensureToolActivityStarted(e.id);try{await this.initializeNativeControl(this.sessionState)}catch{this.degradeNativeControl("NATIVE_CONTROL_INITIALIZATION_FAILED"),this.startE1TtlRefresh()}}else await this.adoptDaemonHandoffState(n),this.sessionState&&this.rebindWaitingPermissionRequests(this.sessionState);await this.ensureToolActivityStarted(e.id);try{this.subscribeToMobileEvents(n)?await L("daemon_init_step_completed",{step:"subscribe_mobile_events",path:"session_started"}):await L("daemon_init_step_failed",{step:"subscribe_mobile_events",path:"session_started",error_class:"SubscriptionSetupFailed",error_message:"subscribeToMobileEvents returned false"})}catch(l){await L("daemon_init_step_failed",{step:"subscribe_mobile_events",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),c.error("Failed to subscribe to mobile events:",l)}if(t)try{await t()}catch(l){c.error("E1: pre-heartbeat re-raise hook failed (non-fatal)",{sessionId:n,error:l instanceof Error?l.message:String(l)})}try{await this.drainRetirementOrphans(n)}catch(l){c.error("E1: retirement-orphan drain failed (non-fatal)",{sessionId:n,error:l instanceof Error?l.message:String(l)})}try{(this.nativeAuthority&&this.nativeDegraded?!1:await this.appSyncClient.startHeartbeat(n))?await L("daemon_init_step_completed",{step:"heartbeat_start",path:"session_started"}):(await L("daemon_init_step_failed",{step:"heartbeat_start",path:"session_started",error_class:"InitialHeartbeatNotPersisted",error_message:"Backend did not confirm the initial heartbeat mutation"}),c.error("Initial session heartbeat was not persisted",{sessionId:n}))}catch(l){await L("daemon_init_step_failed",{step:"heartbeat_start",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),c.error("Failed to start heartbeat:",l)}try{await this.subscribeToOnApplyUserDecision(n)}catch(l){c.error("Failed to subscribe to onApplyUserDecision (non-fatal)",{error:l})}this.startMobileEndWatcher(n);try{await this.flushBufferedLogEntries(),await L("daemon_init_step_completed",{step:"flush_buffered_entries",path:"session_started"})}catch(l){await L("daemon_init_step_failed",{step:"flush_buffered_entries",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),c.error("Failed to flush buffered log entries:",l),this.bufferedLogEntries=[]}this.nativeAuthority||await this.startTmuxObserverWithBeacon("session_started"),this.isInitializingSession=!1}getOrCreateBootstrapSessionId(){return this.bootstrapSessionId||(this.bootstrapSessionId=Oe.mintBackendSessionId()),this.bootstrapSessionId}async bindRecoveryBootstrapIdentity(e){if(!(process.env[je]!=="1"||this.bootstrapSessionId||this.sessionState||!e)){if(this.nativeAuthority){let t=this.appSyncClient.getCurrentUserId(),i=this.nativeAuthority.record.instanceId,s=await g.keychainManager.getDeviceIdentity();if(!s)throw Error("NATIVE_DEVICE_IDENTITY_UNAVAILABLE");let n=()=>{if(this.nativeAuthority.assertCurrent(),this.appSyncClient.getCurrentUserId()!==t)throw Error("NATIVE_ACCOUNT_CHANGED")},r=await this.appSyncClient.listSessions();n();let o=[];for(let a of r){if(a.agentType!==g.AgentType.CODEX||a.status!==g.SessionStatus.ACTIVE)continue;let l=await this.appSyncClient.getSession(a.sessionId);if(n(),!l||l.userId!==t||l.status!==g.SessionStatus.ACTIVE||l.creatorDeviceId!==s.deviceId)continue;let p=l.metadata;if(typeof p=="string"&&(p=JSON.parse(p)),p?.encrypted){let f=await g.keychainManager.getDeviceIdentity();if(n(),!f||f.deviceId!==s.deviceId||f.publicKey!==s.publicKey)throw Error("NATIVE_DEVICE_IDENTITY_CHANGED");let u=l.encryptedKeys?.find(h=>h.deviceId===s.deviceId);if(!u)throw Error("NATIVE_SESSION_KEY_UNAVAILABLE");let m=g.cryptoService.decryptSessionKey(u,f.privateKey);p=g.cryptoService.decryptMetadata(p.encrypted,m)}p?.codexSessionId===e&&p.codexNativeInstanceId===i&&o.push(l.sessionId)}if(o.length>1)throw Error("NATIVE_BOOTSTRAP_AMBIGUOUS");o.length===1&&(this.bootstrapSessionId=o[0],this.recoveryBootstrapOwnerBound=!0);return}try{let t=await this.buildToolActivityIntegration().recordedBackendSessionId(e);if(!t){c.warn("Recovery daemon found no durable backend owner; a new session will be created",{rolloutId:e});return}if(!/^codex-[A-Za-z0-9_-]{1,180}$/.test(t)){c.warn("Recovery daemon ignored invalid durable backend owner",{rolloutId:e});return}this.bootstrapSessionId=t,this.recoveryBootstrapOwnerBound=!0,c.info("Recovery daemon reclaiming existing backend session",{rolloutId:e,sessionId:t})}catch(t){c.warn("Recovery daemon could not read the durable rollout owner; a new session will be created",{rolloutId:e,error:t instanceof Error?t.message:String(t)})}}}isSessionIdReservedRejection(e){return(e instanceof Error?e.message:String(e)).includes("SESSION_ID_RESERVED")}async resumeOrCreateBootstrapSession(e){try{return await this.resumeBackendSession(e,this.appSyncClient,c)}catch(t){if(!this.recoveryBootstrapOwnerBound||!this.isSessionIdReservedRejection(t))throw t;return c.warn("Recovery discarded a permanently reserved pending create; retrying the durable rollout owner",{sessionId:e.sessionId}),this.resumeBackendSession(e,this.appSyncClient,c)}}startTmuxLifecycleMonitor(){if(this.tmuxLifecycleTimer)return;let e=process.env[ge];e&&(this.tmuxLifecycleInitDeadlineMs=Date.now()+An,this.tmuxLifecycleTimer=setInterval(()=>{this.checkTmuxLifecycle(e)},Nn),this.tmuxLifecycleTimer.unref?.(),this.checkTmuxLifecycle(e))}async tmuxSessionState(e){try{return Bt("stall-tmux-probe")&&(c.warn("[dev-fault] stall-tmux-probe: terminality probe will never settle",{tmuxSession:e}),await new Promise(()=>{})),await _n("tmux",["has-session","-t",e],{timeout:5e3}),"alive"}catch(t){let i=cs(t);return i==="absent"?i:(c.warn("Could not inspect native Codex tmux session; preserving daemon",{tmuxSession:e,error:t instanceof Error?t.message:String(t)}),"unknown")}}async checkTmuxLifecycle(e){if(!(this.isStopping||this.tmuxLifecycleCheckInFlight)){this.tmuxLifecycleCheckInFlight=!0;try{let t=await this.tmuxSessionState(e);if(t==="alive"){this.tmuxLifecycleObservedAlive=!0;return}let i=this.tmuxLifecycleObservedAlive||Date.now()>=this.tmuxLifecycleInitDeadlineMs;if(t==="unknown"||!i||this.isStopping)return;this.stopTmuxLifecycleMonitor(),c.info("Native Codex tmux session ended; stopping companion daemon",{tmuxSession:e});let s=De(n=>process.exit(n),()=>c.error("Shutdown watchdog fired after native session end; exiting anyway",{watchdogMs:25e3,timedOutSteps:this.getTeardownStepsTimedOut(),durableObligationSettled:this.isDurableObligationSettledForExit()}),25e3,()=>this.isDurableObligationSettledForExit());this.stop().then(()=>{s(),process.exit(0)},n=>{s(),c.error("Failed to stop companion daemon after native session end",{error:n instanceof Error?n.message:String(n)}),process.exit(1)})}finally{this.tmuxLifecycleCheckInFlight=!1}}}stopTmuxLifecycleMonitor(){this.tmuxLifecycleTimer&&(clearInterval(this.tmuxLifecycleTimer),this.tmuxLifecycleTimer=null)}async shouldShutdownForTerminalSignal(e){if(e==="SIGHUP"){let t=process.env[ge];if(t){let i=await this.tmuxSessionState(t);if(i!=="absent")return c.info("Ignoring SIGHUP while native Codex tmux session remains available",{tmuxSession:t,state:i}),!1}}return!0}async stopForTerminalSignal(e){return await this.shouldShutdownForTerminalSignal(e)?(await this.stop(),!0):!1}isLifecycleCurrent(e){return!this.isStopping&&this.lifecycleGeneration===e}authoritativeSessionIdFromError(e){let t=e?.authoritativeSessionId;return typeof t=="string"&&t.length>0?t:null}async retireCancelledBootstrap(e,t){this.appSyncClient.stopHeartbeat(e),this.appSyncClient.cleanupSubscription(e);try{await this.appSyncClient.updateSession({sessionId:e,status:g.SessionStatus.INACTIVE}),c.info("Cancelled bootstrap row marked INACTIVE",{sessionId:e,path:t})}catch(i){c.warn("Cancelled bootstrap row could not be marked INACTIVE",{sessionId:e,path:t,error:i instanceof Error?i.message:String(i)})}}bindBootstrapIdentityFromError(e){let t=e?.authoritativeSessionId;typeof t!="string"||t.length===0||(this.bootstrapSessionId=t,c.info("Retained authoritative backend identity from failed bootstrap",{sessionId:t}))}recoverRetiredBackendSession(e){if(this.retiredSessionRecoveryPromise)return this.retiredSessionRecoveryPromise;if(this.isStopping)return Promise.resolve();let t=(async()=>{if(this.launchSessionInitPromise&&await this.launchSessionInitPromise,this.sessionStartedInitPromise&&await this.sessionStartedInitPromise,this.isStopping)return;let i=this.sessionState;if(!i||i.sessionId!==e)return;let s={id:i.codexSessionId||e,timestamp:new Date().toISOString(),cwd:i.cwd||i.projectPath,originator:"codevibe-retired-session-recovery",cli_version:String(i.metadata?.cliVersion??"unknown"),instructions:null,source:"codevibe",model_provider:String(i.metadata?.modelProvider??"unknown")};c.warn("Backend retired live Codex session; creating replacement row",{sessionId:e,codexSessionId:s.id});let n=null;if(this.nativeAuthority){let r;n={ready:new Promise(a=>{r=a}),release:r},this.nativeReplacementGate=n,this.nativeDegraded=!0}else this.parkRetirementOrphans(e);try{if(await this.endActiveSession("backend-generation-retired"),this.sessionWatcher.refreshNativeOwnerBoundary(),this.bootstrapSessionId=Oe.mintBackendSessionId(),this.recoveryBootstrapOwnerBound=!1,this.clearSessionBootstrapFailure(),await this.ensureSessionStarted(s),n){n.release(),await this.nativeRuntime.client.joinHandlers();let r=this.nativeControlOwner;if(!r||r.state===i||this.isStopping)throw Error("NATIVE_REPLACEMENT_INCOMPLETE");for(let o of this.nativeRuntime.controlFacts())await r.adapter.observe(o);if(await r.adapter.prepareRehomes(),r.adapter.activate(),await r.adapter.recover(),await r.adapter.join(),this.sessionState!==r.state)throw Error("NATIVE_REPLACEMENT_INCOMPLETE");await this.pruneSettledNativePredecessor(r.state),this.nativeDegraded=!1,await this.appSyncClient.startHeartbeat(r.state.sessionId)}}finally{n?.release(),this.nativeReplacementGate===n&&(this.nativeReplacementGate=null)}})();return this.retiredSessionRecoveryPromise=t.finally(()=>{this.retiredSessionRecoveryPromise=null}),this.retiredSessionRecoveryPromise}recordSessionBootstrapFailure(e,t){this.sessionBootstrapFailureCount+=1;let i=e instanceof Error?e.message:String(e),n=i.includes("SESSION_LIMIT_EXCEEDED")?6e4:Math.min(5e3*2**(this.sessionBootstrapFailureCount-1),6e4);this.sessionBootstrapRetryAt=Date.now()+n,c.warn("Session bootstrap retry scheduled",{path:t,requestedSessionId:this.bootstrapSessionId,failureCount:this.sessionBootstrapFailureCount,delayMs:n,error:i})}clearSessionBootstrapFailure(){this.sessionBootstrapFailureCount=0,this.sessionBootstrapRetryAt=0}async flushBufferedLogEntries(){if(this.bufferedLogEntries.length===0)return;let e=this.bufferedLogEntries;this.bufferedLogEntries=[],c.info("Flushing buffered log entries after session initialization",{count:e.length,sessionId:this.sessionState?.sessionId});let t=Promise.resolve();for(let i of e)t=this.enqueueLogEntry(i);await t.catch(()=>{})}enqueueLogEntry(e){let t=this.logEntryChain.then(async()=>{await this.handleLogEntry(e)});return this.logEntryChain=t.catch(i=>{c.error("[JSONL] log entry handler failed",{type:e.type,err:String(i)})}),t}selectNativeSourceTransport(e){if(this.sessionState!==e||this.isStopping)return Promise.reject(new Error("SYNC_SOURCE_OWNER_CHANGED"));if(this.nativeSourceSelection?.state===e)return this.nativeSourceSelection.pending;let t=this.appSyncClient.selectCompanionSourceTransport({sessionId:e.sessionId}),i={state:e,pending:t};return this.nativeSourceSelection=i,t.catch(()=>{this.nativeSourceSelection===i&&(this.nativeSourceSelection=null)}),t}async retryNativeAdmission(e){try{return await e()}catch(t){throw!this.isStopping&&!this.nativeSourceRetryTimer&&(this.nativeSourceRetryTimer=setTimeout(()=>{this.nativeSourceRetryTimer=null,this.sessionWatcher.retryActiveRead()},5e3),this.nativeSourceRetryTimer.unref()),t}}assertNativeSourceOwner(e){if(this.sessionState!==e.state||e.controller.signal.aborted)throw new Error("SYNC_SOURCE_OWNER_CHANGED")}async nativeSourceOwner(e){if(this.isStopping)throw new Error("SYNC_SOURCE_STOPPING");this.launchSessionInitPromise&&await this.launchSessionInitPromise,this.sessionStartedInitPromise&&await this.sessionStartedInitPromise;let t=this.sessionState;if(!t||!e.nativeSessionId||this.sessionWatcher.getActiveLogFile()!==e.transcriptPath||this.sessionWatcher.getAuthoritativeSessionId()!==null&&this.sessionWatcher.getAuthoritativeSessionId()!==e.nativeSessionId)throw new Error("SYNC_SOURCE_BOOTSTRAP_PENDING");let i=await this.selectNativeSourceTransport(t);if(this.sessionState!==t||this.isStopping)throw new Error("SYNC_SOURCE_OWNER_CHANGED");if(i.protocol==="LEGACY")return null;if(await this.ensureToolActivityStarted(e.nativeSessionId),this.sessionState!==t||this.isStopping||!this.toolActivity?.isActive())throw new Error("SYNC_SOURCE_OWNERSHIP_UNAVAILABLE");let s=ve.createHash("sha256").update(JSON.stringify([e.transcriptPath,e.nativeSessionId])).digest("hex"),n=`${i.sessionScope.sessionGenerationId}:${s}`,r=this.nativeSourceOwners.get(n);if(r)return this.assertNativeSourceOwner(r),r;let o={state:t,selection:i,streamSha256:s,cursor:i.writer.sourceStream({provider:"codex",streamSha256:s}),controller:new AbortController,drain:null,drainRequested:!1,retryTimer:null,retryMs:5e3};return this.nativeSourceOwners.set(n,o),o}async restoreNativeSource(e,t){let i=await this.nativeSourceOwner(e);if(!i)return null;await i.cursor.recover();let s=await i.cursor.open(t);return await i.selection.writer.mobileEchoes("codex").reconcile(i.streamSha256,s.byteOffset),this.assertNativeSourceOwner(i),this.drainNativeSource(i),{byteOffset:s.byteOffset,anchor:s.anchor,discardUntilNewline:s.discardUntilNewline}}async admitNativeSourceGap(e,t){let i=await this.nativeSourceOwner(t);if(!i)throw new Error("SYNC_SOURCE_PROTOCOL_CHANGED");await i.cursor.skip(e),this.assertNativeSourceOwner(i)}async admitNativeSourceEntry(e,t){let i=await this.nativeSourceOwner(t);if(!i)return;let s=this.logEntryChain.then(async()=>{this.assertNativeSourceOwner(i);let n=await i.cursor.load();if(!n)throw new Error("SYNC_SOURCE_CURSOR_MISSING");if(t.endOffset<=n.byteOffset)return;let r=null;if(this.nativeAuthority&&this.nativeControlOwner?.state===i.state){let f=ni(e,i.state.codexSessionId);if(f){let m=f.params,h={threadId:m.threadId,turnId:m.turnId,itemId:m.item.id};this.nativeQuestionFrame=h;try{await this.nativeControlOwner.adapter.observe(f)}finally{this.nativeQuestionFrame===h&&(this.nativeQuestionFrame=null)}}let u=ri(e,i.state.codexSessionId);u&&(await this.nativeControlOwner.adapter.observe(u),r=await this.nativeControlOwner.adapter.projectInputReceipt(u.params))}let o=Ti(e,i.state.sessionId,n.projection);if(this.nativeAuthority&&((e.type==="response_item"&&e.payload?.type==="message"&&e.payload.role==="user"||e.type==="event_msg"&&e.payload?.type==="user_message")&&(o.event=null),r&&(o.event=!r.echo&&r.text!==null?{sessionId:i.state.sessionId,source:g.EventSource.DESKTOP,type:g.EventType.USER_PROMPT,content:r.text,metadata:{images:r.images}}:null)),o.event&&!["USER_PROMPT","ASSISTANT_RESPONSE","REASONING","TOOL_USE","NOTIFICATION"].includes(o.event.type))throw new Error("SYNC_NATIVE_SPECIALIZED_PRODUCER_REQUIRED");let a={streamSha256:i.streamSha256,occurrence:`${t.startOffset}:${t.endOffset}`,sourceSha256:t.sha256,startOffset:t.startOffset,endOffset:t.endOffset},l=i.selection.writer.mobileEchoes("codex"),p=await this.handleLogEntry(e,{event:o.event});if(this.assertNativeSourceOwner(i),!this.isExpectedSessionStateCurrent(i.state))throw new Error("SYNC_SOURCE_OWNER_STOPPING");!this.nativeAuthority&&p?.type===g.EventType.USER_PROMPT&&await l.claim(a,p.content,e.timestamp)&&(p=void 0),await i.cursor.admit({provider:"codex",streamSha256:i.streamSha256,occurrence:`${t.startOffset}:${t.endOffset}`,sourceSha256:t.sha256,startOffset:t.startOffset,endOffset:t.endOffset,anchor:t.anchor},p?f=>i.selection.prepareEvent(p,f):null,o.projection),await l.reconcile(i.streamSha256,t.endOffset),this.drainNativeSource(i)});return this.logEntryChain=s.catch(n=>{c.warn("[sync-source] native admission retained for retry",{error:String(n)})}),await s,"handled"}drainNativeSource(e){if(e.controller.signal.aborted||this.isStopping||(e.drainRequested=!0,e.drain||e.retryTimer))return;e.drainRequested=!1;let t=(async()=>{let i=!1;try{await e.cursor.drain(64,e.controller.signal)===64&&(e.drainRequested=!0),e.retryMs=5e3}catch(s){i=!0,e.controller.signal.aborted||c.warn("[sync-source] cloud drain retained for retry",{error:String(s)}),e.retryMs=Math.min(e.retryMs*2,6e4)}e.drain=null,!e.controller.signal.aborted&&!this.isStopping&&this.sessionState===e.state&&(i?(e.retryTimer=setTimeout(()=>{e.retryTimer=null,this.drainNativeSource(e)},e.retryMs),e.retryTimer.unref()):e.drainRequested&&this.drainNativeSource(e))})();e.drain=t,t.catch(i=>c.error("[sync-source] unexpected drain failure",{error:String(i)}))}async stopNativeSources(e){this.nativeSourceRetryTimer&&clearTimeout(this.nativeSourceRetryTimer),this.nativeSourceRetryTimer=null;let t=[...this.nativeSourceOwners].filter(([,i])=>i.state===e);for(let[,i]of t)i.retryTimer&&clearTimeout(i.retryTimer),i.retryTimer=null,i.controller.abort(new Error("SYNC_SOURCE_STOPPED"));await Promise.all(t.map(([,i])=>i.drain?.catch(()=>{})));for(let[i]of t)this.nativeSourceOwners.delete(i);this.nativeSourceSelection?.state===e&&(this.nativeSourceSelection=null)}async handleLogEntry(e,t){if(!this.sessionState){if(this.isInitializingSession){this.bufferedLogEntries.push(e),c.debug("Buffering log entry until session initialization completes",{type:e.type,bufferedCount:this.bufferedLogEntries.length});return}c.warn("Received log entry but no active session");return}let i=this.sessionState,s=i.sessionId,{sessionKey:n,sessionIsEncrypted:r}=i.encryptionSnapshot;if(this.nativeAuthority||await this.reconcileNativeQuestionReply(Le(e),i),this.sessionState!==i)return;if(!this.nativeAuthority&&e.type==="event_msg"&&e.payload?.type==="turn_aborted"&&(this.approvalDetector.clear(),this.clearInteractivePromptsForAcceptedInput(i)),!this.nativeAuthority&&e.type==="response_item"&&e.payload){let y=e.payload.type;if(y==="function_call"||y==="custom_tool_call")this.isQueuedQuestionTool(e.payload.name)?this.queuedQuestionCallIds.add(e.payload.call_id):this.approvalDetector.onToolCallStart(e.payload.call_id,e.payload.name,e.payload.arguments||e.payload.input||"");else if(y==="function_call_output"||y==="custom_tool_call_output"){if(this.queuedQuestionCallIds.has(e.payload.call_id)){this.queuedQuestionCallIds.delete(e.payload.call_id),this.approvalDetector.onToolCallComplete(e.payload.call_id);return}let w=this.approvalDetector.getPendingCalls().find(P=>P.callId===e.payload.call_id);if(w&&this.isQueuedQuestionTool(w.name)){this.approvalDetector.onToolCallComplete(e.payload.call_id);return}let v=w?this.buildApprovalDedupeKey(this.buildApprovalPromptContextFromPendingCall(w)):void 0;this.approvalDetector.onToolCallComplete(e.payload.call_id);let S=this.observePermissionRequestCompletion(v,"jsonl");if(S.shouldResolve&&await this.clearResolvedInteractivePrompt(e.payload.call_id,S.occurrenceKey??v),!this.isExpectedSessionStateCurrent(i))return}}let o=t?t.event:kt(e,s);if(!o)return;o.timestamp=(0,g.prepareEventTimestamp)({orderingKey:s,agentClock:e.timestamp});let a=e.payload?.type,l=!1;if(this.toolActivity?.isActive()&&o.type===g.EventType.TOOL_USE){let y=a==="function_call"||a==="custom_tool_call",w=a==="function_call_output"||a==="custom_tool_call_output";if(y&&typeof e.payload?.call_id=="string"){let v=this.sessionWatcher.getActiveLogFile();v&&this.toolActivity.bindTranscript(v);let S=await this.toolActivity.observeCall({callId:e.payload.call_id,toolName:o.metadata?.toolName??o.metadata?.tool_name,toolInput:o.metadata?.toolInput??o.metadata?.tool_input,ts:e.timestamp});if(!this.isExpectedSessionStateCurrent(i)||S!=="closed")return;l=!0}if(w)return}let p=this.nativeAuthority&&e.type==="event_msg"&&a==="item_completed"&&(e.payload.item?.type==="UserMessage"||e.payload.item?.type==="AgentMessage"&&e.payload.item.phase==="final_answer");if(this.toolActivity?.isActive()&&(a==="user_message"||a==="agent_message"||p)){let y=this.toolActivity.flush();if(t?await y:await y.catch(w=>c.warn("[tool-activity] codex boundary flush failed",{sessionId:s,err:String(w)})),!this.isExpectedSessionStateCurrent(i))return}if(e.payload?.delivery==="async"&&await this.isAcknowledgedQueuedQuestionEcho(e,i))return;let f=a==="function_call"||a==="function_call_output",u=o.type===g.EventType.USER_PROMPT||o.type===g.EventType.ASSISTANT_RESPONSE||f&&(o.type===g.EventType.TOOL_USE||o.type===g.EventType.INTERACTIVE_PROMPT);if(!t&&!this.hooksActive&&u&&(await this.emitHooksCompatibilityModeNotice(i),!this.isExpectedSessionStateCurrent(i)))return;if(!t&&this.hooksActive){if(o.type===g.EventType.USER_PROMPT){c.debug("[JSONL] Skipping USER_PROMPT \u2014 hooks deliver it",{type:o.type});return}if(f&&(o.type===g.EventType.TOOL_USE||o.type===g.EventType.INTERACTIVE_PROMPT)&&!l){c.debug("[JSONL] Skipping function_call \u2014 hooks deliver this",{type:o.type,tool:e.payload?.name});return}}if(o.type===g.EventType.USER_PROMPT&&o.source===g.EventSource.DESKTOP){let y=t?null:this.consumeRecentMobilePrompt(s,o.content);if(y){c.info("[JSONL] Skipping duplicate USER_PROMPT from mobile",{sessionId:s,matchType:y.matchType,originalLength:y.originalLength,echoLength:y.echoLength});return}}if(this.sessionState!==i){c.warn("[JSONL] Dropping event from stale session generation (#638)",{sessionId:s,currentSessionId:this.sessionState?.sessionId});return}if(t)return o;let m=e.payload?.call_id,h=o.type===g.EventType.TOOL_USE&&typeof m=="string"&&m.length>0&&!!n,I=h?this.getToolActivityLegacyRecorder(s):void 0;I&&h&&I.markLegacyInFlight(m);try{let y=(0,g.encryptForEmit)(n,r,o.content,o.metadata);if(!y){c.error("No session key for ENCRYPTED session \u2014 dropping JSONL event (fail-closed, #638)",{type:o.type,sessionId:s});return}o.content=y.content,o.metadata=y.metadata,y.isEncrypted&&(o.isEncrypted=!0,c.debug("Event encrypted",{type:o.type}));let w=await this.appSyncClient.createEvent(o);c.debug("Event synced to backend",{type:o.type,encrypted:y.isEncrypted}),I&&h&&((0,g.isPersistedEventResult)(w)?await I.finalizeLegacyOwned([m]):I.clearLegacyInFlight(m))}catch(y){I&&h&&I.clearLegacyInFlight(m),c.error("Failed to sync event:",y)}}async handlePermissionRequestHook(e,t,i){if(!this.isExpectedSessionStateCurrent(t)){i&&(i.disposition="dropped");return}let s=i?.context??this.buildApprovalPromptContextFromHookPayload(e),n=i?.dedupeKey??this.buildApprovalDedupeKey(s);if(this.consumeRecoveryPermissionReplay(t,n,i))return;let r=i?.occurrenceKey??`permission:${(0,ye.v4)()}`,o={ownerState:t,context:s,dedupeKey:n,occurrenceKey:r,registration:i};this.permissionRequestHookInFlight=o;try{let a=await this.handlePermissionRequestHookWhileTracked(e,t,s,r,n);i&&(i.disposition=a)}finally{this.permissionRequestHookInFlight===o&&(this.permissionRequestHookInFlight=null)}}buildApprovalPromptContextFromHookPayload(e){let t=e.metadata||{},i=typeof t.tool_name=="string"?t.tool_name:"Tool",s=t.tool_input,n=this.firstString(s?.command,s?.cmd),r=Ae(n)||Ue(n),o=i==="apply_patch"?this.firstString(s?.patch,n,typeof s=="string"?s:void 0):void 0,l=Ae(o)||r,p=!!l,f=l?"apply_patch":i,u=l||this.stringifyToolInput(s),m=l?this.extractFilePathFromToolInput("apply_patch",void 0,l):this.extractFilePathFromToolInput(f,s,u),h=l?this.resolveHookPatchPath(m,t.cwd):m;return{toolName:f,framedPatch:p,toolInput:s,rawInput:u,filePath:h,diff:p?u:void 0,hint:h&&this.mapToolNameForApproval(f)==="Edit"?`File: ${h}`:this.buildPermissionRequestHint(f,s,u)}}resolveHookPatchPath(e,t){if(!e||$.isAbsolute(e))return e;if(!(typeof t!="string"||!$.isAbsolute(t)))return $.resolve(t,e)}async handlePermissionRequestHookWhileTracked(e,t,i=this.buildApprovalPromptContextFromHookPayload(e),s=`permission:${(0,ye.v4)()}`,n,r){let o=e.metadata||{},{toolName:a,toolInput:l,rawInput:p}=i,f=this.buildToolDetailsForInteractivePrompt(i),u=f.tool_name||this.mapToolNameForApproval(a),m=f.tool_input||this.buildFallbackToolInput(i),h=!!(u&&m);if(n??=this.buildApprovalDedupeKey({toolName:a,toolInput:l,filePath:i.filePath,rawInput:p,hint:i.hint}),this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,s))return"resolved";let I=this.promptGeneration,y=r??await this.tryParsePermissionRequestPromptFromTmux((N,ie)=>this.parsedPromptMatchesApprovalContext(N,i,ie),()=>this.isExpectedSessionStateCurrent(t)&&this.promptGeneration===I);if(!this.isExpectedSessionStateCurrent(t)||this.promptGeneration!==I)return c.warn("[Hooks] Dropping stale PermissionRequest after session/prompt generation changed",{sessionId:t.sessionId,currentSessionId:this.sessionState?.sessionId,generationAtStart:I,currentGeneration:this.promptGeneration}),"dropped";if(this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,s))return c.info("[Hooks] Dropping PermissionRequest completed while terminal options were being parsed",{sessionId:t.sessionId,toolName:a,occurrenceKey:s}),"resolved";let w=y?.parsedPrompt??null;if(!w)return y?.differentPrompt?(this.waitingPermissionRequests.set(s,{ownerState:t,context:i,occurrenceKey:s,dedupeKey:n,payload:e}),c.info("[Hooks] Queued PermissionRequest until its desktop dialog is visible",{sessionId:t.sessionId,occurrenceKey:s,toolName:a}),"waiting"):(c.warn("[Hooks] Suppressing PermissionRequest mobile prompt because exact Codex options are unavailable",{sessionId:t.sessionId,toolName:a,hint:i.hint}),this.raiseSuppressedBadge(t.sessionId,s,{suppressTmuxObserverUntilResolved:!0,observerSnapshot:y?.snapshot,completionKey:n}),"covered");let v=this.mapToolNameForApproval(a)==="Bash"?this.firstString(l?.command,l?.cmd):void 0,{presentation:S,failureReason:P}=this.buildCodexPromptPresentationDetailed(w,v,y?.snapshot);if(!S)return c.warn("[Hooks] Suppressing PermissionRequest mobile prompt because Codex presentation options are unavailable",{sessionId:t.sessionId,toolName:a,hint:i.hint,reason:P??"unsupported_options"}),this.raiseSuppressedBadge(t.sessionId,s,{suppressTmuxObserverUntilResolved:!0,observerSnapshot:y?.snapshot,completionKey:n}),"covered";let b=s,R=this.buildApprovalPromptContent(S.content,{toolName:u,toolInput:m,hint:i.hint,filePath:i.filePath}),_={promptId:b,kind:S.kind,options:S.options,submitMap:S.submitMap,promptText:R,createdAt:Date.now(),source:"permission_hook",dedupeKey:s,completionKey:n,ownerSessionId:t.sessionId,observerMatchKey:this.buildObserverPromptMatchKey(w,y?.snapshot),observerPromptHash:y?.snapshot?this.tmuxPaneObserver.hashPromptSnapshot(y.snapshot):void 0,requiresFollowUpText:S.requiresFollowUpText},D={isApprovalHint:!0,toolName:a,toolInput:l,hint:i.hint,filePath:i.filePath,diff:i.diff,rawInput:p,tool_name:u,tool_input:m,has_details:h,options:S.options,instructions:S.instructions,prompt_source:w?"permission_hook_tmux":"permission_hook",permission_mode:o.permission_mode,turn_id:o.turn_id,dedupe_key:s};return c.info("[Hooks] Sending PermissionRequest interactive prompt",{sessionId:t.sessionId,toolName:a,promptId:b,promptSource:D.prompt_source,occurrenceKey:s}),!this.isExpectedSessionStateCurrent(t)||this.promptGeneration!==I?(c.warn("[Hooks] Dropping stale PermissionRequest before enqueue after prompt generation changed",{sessionId:t.sessionId,generationAtStart:I,currentGeneration:this.promptGeneration}),"dropped"):(await this.enqueueOrEmitInteractivePrompt({prompt:_,content:R,metadata:D,ownerState:t}),this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,s)?"resolved":"covered")}isQueuedQuestionTool(e){return typeof e=="string"&&e==="request_user_input_async"}async reconcileNativeQuestionReply(e,t){let i=Ne(e);if(!(!i||!this.isExpectedSessionStateCurrent(t)))for(let s of i){let r=[this.pendingInteractivePrompt,...this.queuedInteractivePrompts.filter(o=>o.ownerState===t).map(o=>o.prompt)].find(o=>o?.kind==="queued_question"&&o.ownerSessionId===t.sessionId&&o.callId===s.callId&&o.dedupeKey===`queued-question::${s.callId}`&&(o.allQuestions?.length??1)===1&&s.index===0&&(o.nativeQuestionTitleSha256?o.nativeQuestionTitleSha256===ve.createHash("sha256").update(s.question.trim()).digest("hex"):o.promptText.trim()===s.question.trim()));if(r&&(await this.clearResolvedInteractivePrompt(s.callId,r.dedupeKey),!this.isExpectedSessionStateCurrent(t)))return}}recordHistoricalQueuedQuestionId(e){if(typeof e=="string"&&e.trim().length>0&&Buffer.byteLength(e,"utf8")<=512&&(this.historicalQueuedQuestionPromptIds.add(e),this.historicalQueuedQuestionPromptIds.size>2e3)){let t=this.historicalQueuedQuestionPromptIds.values();for(;this.historicalQueuedQuestionPromptIds.size>1e3;){let i=t.next();if(i.done)break;this.historicalQueuedQuestionPromptIds.delete(i.value)}}}isQueuedQuestionPromptId(e){if(!e)return!1;if(this.historicalQueuedQuestionPromptIds.has(e)||e.startsWith("q-")||e.startsWith("queued-question::")||this.queuedQuestionCallIds.has(e)||this.pendingInteractivePrompt?.kind==="queued_question"&&(this.pendingInteractivePrompt.promptId===e||this.pendingInteractivePrompt.callId===e||this.pendingInteractivePrompt.dedupeKey===e)||this.queuedInteractivePrompts.some(i=>i.prompt.kind==="queued_question"&&(i.prompt.promptId===e||i.prompt.callId===e||i.prompt.dedupeKey===e)))return!0;let t=this.e1PromptRaises.get(e);return!!(t&&(t.resolutionCallId&&(this.historicalQueuedQuestionPromptIds.has(t.resolutionCallId)||this.queuedQuestionCallIds.has(t.resolutionCallId))||t.resolutionDedupeKey&&(this.historicalQueuedQuestionPromptIds.has(t.resolutionDedupeKey)||t.resolutionDedupeKey.startsWith("queued-question::"))))}queuedQuestionText(e,t){return String(typeof e=="object"&&e!==null?e.title||e.question||e.prompt||`Question ${t+1}`:e)}normalizeQueuedQuestions(e){return Array.isArray(e)?e.slice(0,100).map((t,i)=>{let s=this.queuedQuestionText(t,i).slice(0,1024),r=(typeof t=="object"&&t!==null&&Array.isArray(t.options)?t.options:[]).slice(0,100).map(a=>{if(typeof a=="string")return a.slice(0,1024);if(typeof a=="object"&&a!==null){let l="label"in a?a.label:"text"in a?a.text:String(a),p=String(l).slice(0,1024),f=a.description?String(a.description).slice(0,1024):void 0,u=a.preview?String(a.preview).slice(0,1024):void 0;return{label:p,...f?{description:f}:{},...u?{preview:u}:{}}}return String(a).slice(0,1024)}).filter(a=>{let l=typeof a=="string"?a:a&&typeof a=="object"?a.label:"";return typeof l=="string"&&l.trim().length>0}),o=typeof t=="object"&&t!==null&&typeof t.header=="string"&&t.header.trim().length>0?t.header.trim().slice(0,1024):void 0;return{question:s,...o?{header:o}:{},options:r,multiSelect:typeof t=="object"&&t!==null?!!t.multiSelect:!1}}):[]}async emitQueuedQuestionDesktopNotice(e,t,i){let s={queued_question_desktop_only:!0,notice:t};try{let n=(0,g.prepareEventTimestamp)({orderingKey:e});await this.appSyncClient.publishCompanionNotice({sessionId:e,type:g.EventType.NOTIFICATION,source:g.EventSource.DESKTOP,content:t,metadata:s,timestamp:n},async()=>{if(!this.isExpectedSessionStateCurrent(i))return!1;let r=this.encryptForEmit(t,s,g.EventType.NOTIFICATION,e);return r?(await this.appSyncClient.createEvent({sessionId:e,type:g.EventType.NOTIFICATION,source:g.EventSource.DESKTOP,content:r.content,metadata:r.metadata,timestamp:n,...r.isEncrypted?{isEncrypted:!0}:{}}),!0):!1})}catch(n){c.warn("Failed to emit queued question desktop notice",{error:n})}}async handleQueuedQuestionHook(e,t){let i=e.metadata||{},s=i.tool_input,n=typeof s=="string"?(()=>{try{return JSON.parse(s)}catch{return{}}})():s||{},r=this.normalizeQueuedQuestions(n.questions);if(r.length===0){c.warn("[Hooks] Queued question tool called with empty questions array",{sessionId:t.sessionId,toolName:i.tool_name});return}if(r.length>1){c.info("Queued question has multiple questions; degrading to desktop notice",{sessionId:t.sessionId,questionCount:r.length}),await this.emitQueuedQuestionDesktopNotice(t.sessionId,"\u26A0\uFE0F Multiple questions queued in Codex TUI. Please answer them in your desktop terminal.",t);return}let o=r[0];if(o.multiSelect){c.info("Queued question uses multiSelect; degrading to desktop notice",{sessionId:t.sessionId}),await this.emitQueuedQuestionDesktopNotice(t.sessionId,"\u26A0\uFE0F This queued question uses multi-select, which cannot be answered from mobile. Please answer it in your desktop terminal.",t);return}if(!o.options||o.options.length===0){c.info("Queued question has no options; degrading to desktop notice",{sessionId:t.sessionId}),await this.emitQueuedQuestionDesktopNotice(t.sessionId,"\u26A0\uFE0F This queued question has no predefined options \u2014 please answer it in your desktop terminal.",t);return}let a=this.firstString(i.tool_use_id,i.call_id,i.callId)??`synth-${Date.now()}`;a.startsWith("synth-")||this.queuedQuestionCallIds.add(a);let l=`queued-question::${a}`,p=a;this.recordHistoricalQueuedQuestionId(a),this.recordHistoricalQueuedQuestionId(l);let f=o.question,u=o.options.map((v,S)=>{let P=String(S+1),b=typeof v=="string",R=b?v:v.label||"",_=b?void 0:v.description,D=b?void 0:v.preview;return{number:P,text:R,..._?{description:_}:{},...D?{preview:D}:{}}}),m=Object.fromEntries(u.map(v=>[v.number,v.number])),h="Reply with the number of your choice.",I=[{question:o.question,...o.header?{header:o.header}:{},multiSelect:!1,options:u,instructions:h}],y={promptId:p,callId:a,kind:"queued_question",options:u,submitMap:m,promptText:f,createdAt:Date.now(),source:"queued_question",dedupeKey:l,completionKey:l,ownerSessionId:t.sessionId,requiresFollowUpText:!1,allQuestions:r,nativeQuestionTitleSha256:ve.createHash("sha256").update(this.queuedQuestionText(n.questions[0],0).trim()).digest("hex")},w={isApprovalHint:!1,isQueuedQuestion:!0,tool_name:i.tool_name,tool_use_id:a,questions:I,options:u,submitMap:m,instructions:h,prompt_source:"queued_question",turn_id:i.turn_id,dedupe_key:l};c.info("[Hooks] Emitting queued question INTERACTIVE_PROMPT",{sessionId:t.sessionId,toolName:i.tool_name,promptId:p,optionsCount:u.length}),await this.enqueueOrEmitInteractivePrompt({prompt:y,content:f,metadata:w,ownerState:t})}queuedQuestionEchoSignature(e){if(!Array.isArray(e)||e.length!==1)return null;let t=e[0];if(!t||typeof t!="object")return null;let i=t.title??t.question;if(typeof i!="string"||!i.trim()||i.length>2048||!Array.isArray(t.options)||t.options.length===0||t.options.length>20)return null;let s=[];for(let n of t.options){let r=typeof n=="string"?n:n?.label??n?.text;if(typeof r!="string"||!r.trim()||r.length>2048)return null;s.push(r)}return JSON.stringify([i,s])}async isAcknowledgedQueuedQuestionEcho(e,t){let i=e.payload;if(e.type!=="event_msg"||i?.type!=="agent_message"||i.delivery!=="async"||i.phase!=="final_answer")return!1;let s=this.queuedQuestionEchoSignature(i.questions);if(!s)return!1;let n=[...this.e1PromptRaises.values()].filter(o=>o.record.sessionId===t.sessionId&&o.record.mobileActionable&&o.metadataPlain?.isQueuedQuestion===!0&&this.queuedQuestionEchoSignature(o.metadataPlain.questions)===s);if(n.length!==1)return!1;let r=n[0];return await this.e1RaiseInFlight.get(r.record.promptId),this.isExpectedSessionStateCurrent(t)&&this.e1PromptRaises.get(r.record.promptId)===r&&this.acknowledgedQueuedQuestionRaises.has(r)}isQueuedQuestionStrictHintLine(e){let t=e.trim();return/to answer$/i.test(t)?/^(?:⇥|->|<-|\bTab\b|[⇧⬆]?←|\b(?:Shift[+-]|S-)Left\b)\s+to answer$/i.test(t):!1}isQueuedQuestionHintLine(e){return this.isQueuedQuestionStrictHintLine(e)}matchQueuedQuestionCounter(e){return e.match(/^\s*\?\s*(\d+)\s+questions?(?:\s+·\s+\d{1,3}s)?\s*$/i)}hasQueuedQuestionHintLine(e){let t=e.split(`
53
- `);return t.some((i,s)=>{let n=i.trim();if(this.isQueuedQuestionStrictHintLine(n))return!0;if(/^to answer$/i.test(n)){let r=Math.max(0,s-2),o=Math.min(t.length-1,s+2);for(let a=r;a<=o;a++)if(a!==s&&(/^\s*•?\s*Queued follow-up inputs\s*$/i.test(t[a])||this.matchQueuedQuestionCounter(t[a])!==null))return!0}return!1})}hasQueuedInputsFragment(e){let t=e.split(`
54
- `),i=t.some(r=>/^\s*•?\s*Queued follow-up inputs\s*$/i.test(r)),s=t.some(r=>this.matchQueuedQuestionCounter(r)!==null),n=this.hasQueuedQuestionHintLine(e);return i||s||n}isModelStatusFooterLine(e){return/^[>›]/.test(e)?!1:/^(?:(?:GPT|Claude|Codex|DeepSeek)[-\s]\d[\w.-]*|o\d[\w.-]*)(?:\s+(?:xhigh|high|medium|low|fast|slow|default))*(?:\s+[·•|]\s+\S.*)?$/i.test(e)}isShortcutsOrStatusHintLine(e){if(/^[>›]/.test(e))return!1;let t=e.trim();if(t.length===0||/^← for agents · \? for shortcuts$/i.test(t))return!0;let i="(?:esc to interrupt|\\?\\s+for\\s+(?:shortcuts|help)|\\d+%\\s+context\\s+left|\u26A0\\s+\\d+\\s+warning.*)";return new RegExp(`^${i}(?:\\s{2,}${i})?$`,"i").test(t)}validateTrailingFooterLines(e){return e.length===0?!0:e.length>2?!1:e.length===1?this.isModelStatusFooterLine(e[0])||this.isShortcutsOrStatusHintLine(e[0]):this.isModelStatusFooterLine(e[0])&&this.isShortcutsOrStatusHintLine(e[1])}isAssistantExecutionLine(e){let t=e.trim();return!!(/^•\s*Working(?:\s*\(.*?\))?\s*$/i.test(t)||/^•\s*(?:Ran|Read|Edited|Searched|Thinking|Explored)\b/i.test(t)||/^•\s*(?:Applied|Done|Finished|Plan completed|I have finished|I've finished)\b/i.test(t)||/^•\s*Failed\s*\(exit\s+\d+\)/i.test(t)||/^✔\s*You approved\b/i.test(t)||/^\+\s*\d+\s+lines?\b/i.test(t)||/^└\s*(?:exit code \d+|Tip:|Read|[+]\s*\d+\s+lines)/i.test(t))}isHistoricalFooter(e,t){if(t<0||t>=e.length)return{isFooter:!1,footerStartIdx:-1};if(t>=2){let i=e[t-2].trim(),s=e[t-1].trim(),n=e[t].trim();if(/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(i)&&s.length>0&&n.length>0&&this.isModelStatusFooterLine(s)&&this.isShortcutsOrStatusHintLine(n))return{isFooter:!0,footerStartIdx:t-1}}if(t>=1){let i=e[t-1].trim(),s=e[t].trim();if(/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(i)&&s.length>0&&this.isModelStatusFooterLine(s))return{isFooter:!0,footerStartIdx:t}}return{isFooter:!1,footerStartIdx:-1}}isHistoricalTurnBoundary(e,t){if(t<0||t>=e.length)return!1;let i=e[t];return/^[>›]\s*Ask Codex to do anything\s*$/i.test(i)?!0:this.isHistoricalFooter(e,t).isFooter}isDraftPromptLine(e){return!(!/^[>›]/.test(e)||/^[>›]\s*Ask Codex to do anything\s*$/i.test(e)||/^[>›]\s*$/.test(e))}extractLiveQueuedQuestionWidget(e){let s=oe(e).split(`
54
+ `);return!/Press a number to choose/i.test(s)}catch(t){return c.warn("Failed to verify that no Codex chooser is active",{sessionId:e,error:t instanceof Error?t.message:String(t)}),!1}}sendVerifiedPromptInput(e,t,i){if(!this.isExpectedSessionStateCurrent(e))return Promise.resolve("stale");let s=this.terminalInputChain.then(async()=>{if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t||t.ownerSessionId!==e.sessionId)return"stale";if(t.kind==="queued_question"||t.source==="queued_question")try{return await this.deliverQueuedQuestionResponse(e,t,i)}catch(o){return c.error("Failed to deliver queued question response",{sessionId:e.sessionId,promptId:t.promptId,error:o instanceof Error?o.message:String(o)}),"unverified"}if(!t.observerMatchKey)return c.warn("Refusing mobile prompt input without a captured pane identity",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(t.terminalMenuIdentity)try{return await(0,Ps.selectTerminalMenuOption)(t.terminalMenuIdentity,i,{current:()=>this.isExpectedSessionStateCurrent(e)&&this.pendingInteractivePrompt===t,read:async()=>(0,F.parseActiveTerminalMenu)(await this.tmuxPaneObserver.captureSnapshot()),key:o=>this.promptResponder.sendKey(e.sessionId,o),wait:()=>new Promise(o=>setTimeout(o,100))})}catch{return"unverified"}let n=null;try{let o=await this.tmuxPaneObserver.captureSnapshot(),d=this.tmuxPaneObserver.extractActiveApprovalBlock(o),l=d?(0,F.parseInteractivePrompt)(d):null;n=l?this.buildObserverPromptMatchKey(l,d??void 0):null}catch(o){return c.warn("Failed to re-probe Codex prompt before mobile input",{sessionId:e.sessionId,promptId:t.promptId,error:o instanceof Error?o.message:String(o)}),"unverified"}if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"stale";if(!n||n!==t.observerMatchKey)return c.warn("Refusing mobile input because the live Codex prompt changed",{sessionId:e.sessionId,promptId:t.promptId,hasLiveIdentity:!!n}),"unverified";let r=i===Le?await this.promptResponder.sendKey(e.sessionId,"Escape"):await this.promptResponder.sendLiteral(e.sessionId,i);return r?"sent":"send_failed"});return this.terminalInputChain=s.then(()=>{},()=>{}),s}sendVerifiedFollowUpAfterDismissal(e,t,i,s){let n=this.terminalInputChain.then(async()=>{let r=()=>this.isExpectedSessionStateCurrent(e)&&t.ownerSessionId===e.sessionId;return r()?!await this.verifyNoActiveCodexChooser(e.sessionId)||!r()||s&&(await s(),!r()||!await this.verifyNoActiveCodexChooser(e.sessionId)||!r())?"unverified":await this.promptResponder.sendLiteral(e.sessionId,i)?(await new Promise(o=>setTimeout(o,500)),r()?!await this.verifyNoActiveCodexChooser(e.sessionId)||!r()?"unverified":await this.promptResponder.sendKey(e.sessionId,"Enter")?"sent":"send_failed":"stale"):"send_failed":"stale"});return this.terminalInputChain=n.then(()=>{},()=>{}),n}sendConversationContinuation(e,t,i){if(!this.isExpectedSessionStateCurrent(e))return Promise.resolve("stale");let s=this.terminalInputChain.then(async()=>{if(!this.isExpectedSessionStateCurrent(e))return"stale";try{let n=new Set;for(;;){let r=await this.tmuxPaneObserver.captureSnapshot();if(!this.isExpectedSessionStateCurrent(e))return"stale";let o=this.tmuxPaneObserver.extractActivePromptBlock(r);if(!o)break;let d=this.tmuxPaneObserver.hashPromptSnapshot(o);if(n.has(d)||n.size>=4)return"unverified";if(n.add(d),!await this.promptResponder.sendKey(e.sessionId,"Escape"))return"send_failed";if(await new Promise(l=>setTimeout(l,200)),!this.isExpectedSessionStateCurrent(e))return"stale"}}catch(n){return c.warn("Failed to inspect Codex chooser before conversation continuation",{sessionId:e.sessionId,error:n instanceof Error?n.message:String(n)}),"unverified"}return i&&(await i(),!this.isExpectedSessionStateCurrent(e)||!await this.verifyNoActiveCodexChooser(e.sessionId)||!this.isExpectedSessionStateCurrent(e))?"unverified":await this.promptResponder.sendLiteral(e.sessionId,t)?(await new Promise(n=>setTimeout(n,500)),this.isExpectedSessionStateCurrent(e)?await this.verifyNoActiveCodexChooser(e.sessionId)?await this.promptResponder.sendKey(e.sessionId,"Enter")?"sent":"send_failed":"unverified":"stale"):"send_failed"});return this.terminalInputChain=s.then(()=>{},()=>{}),s}handleEventFromHook(e){if(this.nativeAuthority||this.isStopping)return Promise.resolve();let t=this.lifecycleGeneration,i=this.registerQueuedPermissionRequest(e,t),s=this.hookEventChain.then(()=>this.processHookEvent(e,t,i??void 0)),n=i?s.finally(()=>this.unregisterQueuedPermissionRequest(i)):s;return this.hookEventChain=n.catch(r=>{c.error("[Hooks] event handler failed",{hookEvent:e.hook_event_name,sessionId:e.session_id,error:r instanceof Error?r.message:String(r)})}),n}registerQueuedPermissionRequest(e,t){if(e.hook_event_name!=="PermissionRequest"||!this.sessionState||this.sessionWatcher.getAuthoritativeSessionId()!==e.session_id)return null;let i=this.sessionState.sessionId;this.queuedPermissionRequestSessionCounts.set(i,(this.queuedPermissionRequestSessionCounts.get(i)??0)+1);let s=this.buildApprovalPromptContextFromHookPayload(e),n=this.buildApprovalDedupeKey(s),r=`permission:${(0,Se.v4)()}`,o=n?`${i}::${n}`:void 0;o&&this.queuedPermissionRequestDedupeKeys.set(o,(this.queuedPermissionRequestDedupeKeys.get(o)??0)+1);let d={sessionId:i,lifecycleGeneration:t,context:s,dedupeKey:n,occurrenceKey:r,dedupeRegistryKey:o,disposition:"pending"};if(n){let u=this.permissionRequestOccurrencesByCompletionKey.get(n)??[];u.push({occurrenceKey:r,hookObserved:!1,jsonlObserved:!1}),this.permissionRequestOccurrencesByCompletionKey.set(n,u)}let l=this.queuedPermissionRequestRegistrations.get(i)??[];return l.push(d),this.queuedPermissionRequestRegistrations.set(i,l),d}async unregisterQueuedPermissionRequest(e){let t=this.queuedPermissionRequestSessionCounts.get(e.sessionId)??0;if(t<=1?this.queuedPermissionRequestSessionCounts.delete(e.sessionId):this.queuedPermissionRequestSessionCounts.set(e.sessionId,t-1),e.dedupeRegistryKey){let o=this.queuedPermissionRequestDedupeKeys.get(e.dedupeRegistryKey)??0;o<=1?this.queuedPermissionRequestDedupeKeys.delete(e.dedupeRegistryKey):this.queuedPermissionRequestDedupeKeys.set(e.dedupeRegistryKey,o-1)}let s=(this.queuedPermissionRequestRegistrations.get(e.sessionId)??[]).filter(o=>o!==e);s.length>0?this.queuedPermissionRequestRegistrations.set(e.sessionId,s):this.queuedPermissionRequestRegistrations.delete(e.sessionId),(e.disposition==="pending"||e.disposition==="dropped"||this.sessionState?.sessionId!==e.sessionId)&&this.removePermissionRequestOccurrence(e.dedupeKey,e.occurrenceKey);let n=this.deferredTmuxPromptCandidates.get(e);if(!n)return;if(this.deferredTmuxPromptCandidates.delete(e),!this.isLifecycleCurrent(e.lifecycleGeneration)){e.disposition="dropped",this.removePermissionRequestOccurrence(e.dedupeKey,e.occurrenceKey),c.debug("Discarding deferred tmux prompt after lifecycle invalidation",{sessionId:e.sessionId,lifecycleGeneration:e.lifecycleGeneration,currentLifecycleGeneration:this.lifecycleGeneration});return}let r=this.hasRecentlyResolvedApprovalDedupeKey(e.sessionId,e.occurrenceKey);if(e.disposition==="covered"||e.disposition==="resolved"||r){c.debug("Discarding deferred tmux prompt covered by its PermissionRequest",{sessionId:e.sessionId,dedupeKey:e.dedupeKey,disposition:e.disposition});return}if(!(e.disposition==="dropped"||this.sessionState?.sessionId!==e.sessionId)){c.debug("Replaying deferred tmux prompt after PermissionRequest produced no durable owner",{sessionId:e.sessionId,dedupeKey:e.dedupeKey});try{await this.handleTmuxPromptCandidate(n.snapshot,e,n.promptHash)}catch(o){c.error("Failed to replay deferred tmux prompt candidate",{sessionId:e.sessionId,error:o instanceof Error?o.message:String(o)})}}}removePermissionRequestOccurrence(e,t){if(!e||!t)return;let i=this.permissionRequestOccurrencesByCompletionKey.get(e);if(!i)return;let s=i.filter(n=>n.occurrenceKey!==t);s.length>0?this.permissionRequestOccurrencesByCompletionKey.set(e,s):this.permissionRequestOccurrencesByCompletionKey.delete(e)}observePermissionRequestCompletion(e,t){if(!e)return{shouldResolve:!0};let i=this.permissionRequestOccurrencesByCompletionKey.get(e);if(!i)return{shouldResolve:!0};let s=t==="hook"?"hookObserved":"jsonlObserved",n=i.find(o=>!o[s]);if(!n)return c.debug("Ignoring duplicate interactive-prompt completion observation",{completionKey:e,producer:t}),{shouldResolve:!1};let r=!n.hookObserved&&!n.jsonlObserved;return n[s]=!0,n.hookObserved&&n.jsonlObserved&&this.removePermissionRequestOccurrence(e,n.occurrenceKey),{shouldResolve:r,occurrenceKey:n.occurrenceKey}}isPermissionRequestOccurrenceKey(e){return e.startsWith("permission:")}consumeRecoveryPermissionReplay(e,t,i){let s=this.recoveryPermissionReplay,n=this.pendingInteractivePrompt;return!s||!t||s.ownerSessionId!==e.sessionId||s.completionKey!==t||n?.ownerSessionId!==e.sessionId||n.source!=="permission_hook"||n.dedupeKey!==s.occurrenceKey||n.completionKey!==s.completionKey?!1:(this.recoveryPermissionReplay=null,i&&(this.removePermissionRequestOccurrence(i.dedupeKey,i.occurrenceKey),i.occurrenceKey=s.occurrenceKey,i.disposition="covered"),c.info("[Hooks] Reused adopted PermissionRequest occurrence for one recovery replay",{sessionId:e.sessionId,completionKey:t,occurrenceKey:s.occurrenceKey}),!0)}async processHookEvent(e,t,i){if(!this.isLifecycleCurrent(t))return;let{session_id:s,hook_event_name:n,type:r,content:o,metadata:d}=e;c.info("[Hooks] Received event",{sessionId:s,hookEvent:n,type:r,contentLength:o?.length});let l=this.sessionWatcher.getAuthoritativeSessionId();if(l&&l!==s){c.warn("[Hooks] Rejecting event for foreign native session",{hookEvent:n,sessionId:s,authoritativeSessionId:l});return}if(d?.transcript_path){let p=await this.sessionWatcher.bindToSessionTranscript(d.transcript_path,s);if(!this.isLifecycleCurrent(t))return;let m=p.status==="pending"?await p.completion:p;if(!this.isLifecycleCurrent(t))return;if(m.status!=="bound"){c.warn("[Hooks] Rejecting event whose transcript ownership was not proven",{hookEvent:n,sessionId:s,reason:m.reason});return}}else if(l!==s){c.warn("[Hooks] Rejecting event without an owned transcript",{hookEvent:n,sessionId:s});return}if(!this.isLifecycleCurrent(t)||this.sessionWatcher.getAuthoritativeSessionId()!==s){c.warn("[Hooks] Rejecting event after ownership changed during admission",{hookEvent:n,sessionId:s,authoritativeSessionId:this.sessionWatcher.getAuthoritativeSessionId()});return}if(this.hooksActive=!0,n==="SessionStart"){if(this.launchSessionInitPromise&&(await this.launchSessionInitPromise,!this.isLifecycleCurrent(t)))return;if(this.sessionState){if(c.info("[Hooks] SessionStart \u2014 launch session already exists, updating codexSessionId",{existingSessionId:this.sessionState.sessionId,codexSessionId:s}),this.sessionState.codexSessionId=s,this.sessionState.metadata={...this.sessionState.metadata,codexSessionId:s,cliVersion:d?.model||"unknown",modelProvider:d?.model||"unknown",launchSession:void 0},this.appSyncClient.updateSession({sessionId:this.sessionState.sessionId,metadata:this.sessionState.metadata}).catch(p=>c.warn("Failed to update session metadata",{error:p})),await this.startTmuxObserverWithBeacon("session_start_existing"),!this.isLifecycleCurrent(t))return;await this.ensureToolActivityStarted(s)}else{let p={id:s,timestamp:new Date().toISOString(),cwd:d?.cwd||process.cwd(),originator:"hook",cli_version:d?.model||"unknown",instructions:null,source:d?.source||"startup",model_provider:d?.model||"unknown"};await this.ensureSessionStarted(p)}return}if(!this.sessionState){c.warn("[Hooks] Hook event for un-bootstrapped session \u2014 self-healing via session bootstrap (#638)",{hookEvent:n,sessionId:s});let p={id:s,timestamp:new Date().toISOString(),cwd:d?.cwd||process.cwd(),originator:"hook",cli_version:d?.model||"unknown",instructions:null,source:d?.source||"startup",model_provider:d?.model||"unknown"};if(await this.ensureSessionStarted(p),!this.isLifecycleCurrent(t))return;if(!this.sessionState){c.warn("[Hooks] Session still not initialized after self-heal, dropping event",{hook_event_name:n});return}}let u=this.sessionState,h=u.sessionId;if(r==="USER_PROMPT"){let p=Me(o)!==null;if(await this.reconcileNativeQuestionReply(o,u),this.sessionState!==u||(p||(this.approvalDetector.clear(),this.clearInteractivePromptsForAcceptedInput(u)),(await this.selectNativeSourceTransport(u)).protocol==="SYNC_V2"))return}if(r==="USER_PROMPT"&&o){let p=this.consumeRecentMobilePrompt(h,o);if(p){c.info("[Hooks] Skipping duplicate USER_PROMPT from mobile",{sessionId:h,matchType:p.matchType,originalLength:p.originalLength,echoLength:p.echoLength});return}}if(n==="PreToolUse"){c.debug("[Hooks] PreToolUse observed; AppSync emission suppressed",{toolName:d?.tool_name||"unknown",sessionId:h});return}if(n==="PermissionRequest"){let p=i??this.registerQueuedPermissionRequest(e,t);if(!p){c.error("[Hooks] Dropping admitted PermissionRequest without occurrence registration",{sessionId:h,nativeSessionId:s});return}try{await this.handlePermissionRequestHook(e,u,p)}finally{i||await this.unregisterQueuedPermissionRequest(p)}return}if(n==="PostToolUse"){let p=d?.tool_name;if(this.isQueuedQuestionTool(p)){await this.handleQueuedQuestionHook(e,u);return}let m=this.buildApprovalPromptContextFromHookPayload(e),f=this.buildApprovalDedupeKey(m),g=this.firstString(d?.tool_use_id,d?.call_id,d?.callId)??"",y=this.observePermissionRequestCompletion(f,"hook");if(y.shouldResolve&&await this.clearResolvedInteractivePrompt(g,y.occurrenceKey??f),!this.isExpectedSessionStateCurrent(u)||this.toolActivity?.isActive()&&await this.toolActivity.observeCall({callId:d?.tool_use_id??d?.call_id??d?.callId,toolName:d?.tool_name,toolInput:d?.tool_input})!=="closed"||!this.isExpectedSessionStateCurrent(u))return;let S=await this.selectNativeSourceTransport(u);if(!this.isExpectedSessionStateCurrent(u))return;if(S.protocol==="SYNC_V2")throw new Error("SYNC_SOURCE_TOOL_NOT_ADMITTED");let I=this.encryptForEmit(o,d,v.EventType.TOOL_USE,h);if(!I)return;let w=I.content,E=I.metadata,R=I.isEncrypted,b=d?.tool_use_id??d?.call_id??d?.callId,_=typeof b=="string"&&b.length>0&&!!this.sessionKey,x=_?this.getToolActivityLegacyRecorder(h):void 0;x&&_&&x.markLegacyInFlight(b);try{let A=await this.appSyncClient.createEvent({sessionId:h,type:v.EventType.TOOL_USE,source:v.EventSource.DESKTOP,content:w,metadata:E,isEncrypted:R,timestamp:(0,v.prepareEventTimestamp)({orderingKey:h})});x&&_&&((0,v.isPersistedEventResult)(A)?await x.finalizeLegacyOwned([b]):x.clearLegacyInFlight(b))}catch(A){throw x&&_&&x.clearLegacyInFlight(b),A}return}if(r==="ASSISTANT_RESPONSE"||r==="USER_PROMPT"){if(r==="ASSISTANT_RESPONSE"){this.sessionWatcher.getBindSource()==="authoritative"&&this.sessionWatcher.getAuthoritativeSessionId()===s?c.debug("[Hooks] Suppressing Stop final \u2014 JSONL watcher authoritatively bound to this session (Bug #2)"):c.warn("[Hooks] Dropping Stop final after authoritative ownership changed",{authoritativeSessionId:this.sessionWatcher.getAuthoritativeSessionId()});return}let p=this.encryptForEmit(xi(o),void 0,v.EventType.USER_PROMPT,h);if(!p)return;await this.appSyncClient.createEvent({sessionId:h,type:v.EventType.USER_PROMPT,source:v.EventSource.DESKTOP,content:p.content,isEncrypted:p.isEncrypted,timestamp:(0,v.prepareEventTimestamp)({orderingKey:h})});return}}mapToolName(e){return{shell_command:"Bash",shell:"Bash",apply_patch:"Edit",create_file:"Write",read_file:"Read"}[e]||e}trackMobilePrompt(e,t){this.mobilePromptDeduper.track(e,t),c.debug("Tracking mobile prompt for USER_PROMPT echo deduplication",{sessionId:e,promptLength:t.trim().length})}forgetMobilePrompt(e,t){this.mobilePromptDeduper.forget(e,t)}consumeRecentMobilePrompt(e,t){return this.mobilePromptDeduper.consumeIfDuplicate(e,t)}async trackDurableMobileEcho(e,t,i,s){if(!(0,v.requiresSyncInputDeliveryReceipt)(t)){this.trackMobilePrompt(e.sessionId,i);return}let n=await this.selectNativeSourceTransport(e);if(n.protocol!=="SYNC_V2"||!this.isExpectedSessionStateCurrent(e)||t.sessionId!==n.sessionScope.sessionId||t.sessionGenerationId!==n.sessionScope.sessionGenerationId)throw Error("SYNC_ECHO_OWNER_CHANGED");i.trim()&&await n.writer.mobileEchoes("codex").arm({eventId:t.eventId,timestamp:t.timestamp,type:t.type,lane:s},i,{nowMs:Date.now(),windowMs:1e4,allowSuffix:!0,normalization:"whitespace"})}setupEventHandlers(){this.sessionWatcher.on("session-started",async e=>{try{if(this.launchSessionInitPromise&&await this.launchSessionInitPromise,this.sessionState){c.info("[JSONL] Session already active, skipping",{currentSessionId:this.sessionState.sessionId,codexSessionId:e.id}),await this.ensureToolActivityStarted(e.id);return}await this.ensureSessionStarted(e)}catch(t){c.error("[JSONL] session-started handler failed (non-fatal) \u2014 next event retries",{codexSessionId:e?.id,error:String(t)})}}),this.sessionWatcher.on("log-entry",e=>{this.enqueueLogEntry(e)}),this.sessionWatcher.on("error",e=>{c.error("Session watcher error:",e)}),!this.nativeAuthority&&(this.approvalDetector.on("approval-pending",async e=>{try{await this.handleApprovalPending(e)}catch(t){c.error("approval-pending handler failed (non-fatal)",{error:String(t)})}}),this.tmuxPaneObserver.on("prompt-candidate",async e=>{try{await this.handleTmuxPromptCandidate(e.snapshot,void 0,e.promptHash)}catch(t){c.error("prompt-candidate handler failed (non-fatal)",{error:String(t)})}}),this.tmuxPaneObserver.on("prompt-cleared",e=>{let t=this.sessionState;t&&this.clearObservedInteractivePrompt(t,e.promptHash).catch(i=>{c.error("prompt-cleared handler failed (non-fatal)",{error:String(i)})})}),this.tmuxPaneObserver.on("observer-error",e=>{c.debug("Tmux pane observer error",{error:e})}))}async ensureSessionStarted(e,t){if(this.isStopping||(this.launchSessionInitPromise&&await this.launchSessionInitPromise,this.isStopping)||this.sessionState)return;process.env[Xe]==="1"&&await this.bindRecoveryBootstrapIdentity(e.id);let i=this.sessionBootstrapRetryAt-Date.now();if(i>0){c.warn("Session bootstrap is in retry backoff; hook will be retried later",{codexSessionId:e.id,retryDelayMs:i,failureCount:this.sessionBootstrapFailureCount});return}if(this.sessionStartedInitPromise){try{await this.sessionStartedInitPromise}catch{}return}let s=this.handleSessionStarted(e,t);this.sessionStartedInitPromise=s.catch(()=>{});try{await s}finally{this.sessionStartedInitPromise=null}}async handleSessionStarted(e,t){if(this.isStopping)return;let i=this.lifecycleGeneration;c.info("Handling new Codex session",{codexSessionId:e.id}),this.isInitializingSession=!0,this.bufferedLogEntries=[],this.sessionState&&await this.endActiveSession("new-codex-session-started");let s=this.nativeAuthority?e.cwd:process.env.CODEX_WORKING_DIRECTORY||e.cwd||process.cwd(),n=this.getOrCreateBootstrapSessionId(),r=this.appSyncClient.getCurrentUserId(),o={codexSessionId:e.id,cliVersion:e.cli_version,modelProvider:e.model_provider,...this.nativeAuthority?{codexNativeInstanceId:this.nativeAuthority.record.instanceId}:{}},d={sessionKey:null,sessionIsEncrypted:!0};try{let l={sessionId:n,userId:r,agentType:v.AgentType.CODEX,projectPath:s,metadata:o},u=await this.resumeOrCreateBootstrapSession(l);if(n=u.sessionId,!this.isLifecycleCurrent(i)){this.isInitializingSession=!1,await this.retireCancelledBootstrap(n,"session_started");return}this.sessionKey=u.sessionKey,this.sessionKeyGen=u.sessionKeyGen,this.sessionIsEncrypted=!!u.sessionKey,d={sessionKey:u.sessionKey,sessionIsEncrypted:!!u.sessionKey},await L("daemon_init_step_completed",{step:"session_resume_or_create",path:"session_started"})}catch(l){if(this.isInitializingSession=!1,!this.isLifecycleCurrent(i)){let u=this.authoritativeSessionIdFromError(l)??n;await this.retireCancelledBootstrap(u,"session_started_error");return}throw await L("daemon_init_step_failed",{step:"session_resume_or_create",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),l?.code==="ENCRYPTED_SESSION_NO_KEY"&&(this.sessionIsEncrypted=!0,this.sessionKey=null),this.bindBootstrapIdentityFromError(l),this.recordSessionBootstrapFailure(l,"session_started"),c.error("Failed to create/resume session:",l),l}try{this.sessionState={sessionId:n,userId:r,projectPath:s,cwd:e.cwd,createdAt:new Date,subscriptionActive:!1,metadata:o,encryptionSnapshot:d,codexSessionId:e.id,codexLogFile:this.sessionWatcher.getActiveLogFile()||void 0},this.clearSessionBootstrapFailure(),this.bootstrapSessionId=null,this.recoveryBootstrapOwnerBound=!1,await L("daemon_init_step_completed",{step:"session_state_set",path:"session_started"})}catch(l){await L("daemon_init_step_failed",{step:"session_state_set",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),c.error("Failed to set session state:",l)}if(this.nativeAuthority){if(!this.sessionState)throw Error("NATIVE_SESSION_BINDING_INCOMPLETE");await this.ensureToolActivityStarted(e.id);try{await this.initializeNativeControl(this.sessionState)}catch{this.degradeNativeControl("NATIVE_CONTROL_INITIALIZATION_FAILED"),this.startE1TtlRefresh()}}else await this.adoptDaemonHandoffState(n),this.sessionState&&this.rebindWaitingPermissionRequests(this.sessionState);await this.ensureToolActivityStarted(e.id);try{this.subscribeToMobileEvents(n)?await L("daemon_init_step_completed",{step:"subscribe_mobile_events",path:"session_started"}):await L("daemon_init_step_failed",{step:"subscribe_mobile_events",path:"session_started",error_class:"SubscriptionSetupFailed",error_message:"subscribeToMobileEvents returned false"})}catch(l){await L("daemon_init_step_failed",{step:"subscribe_mobile_events",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),c.error("Failed to subscribe to mobile events:",l)}if(t)try{await t()}catch(l){c.error("E1: pre-heartbeat re-raise hook failed (non-fatal)",{sessionId:n,error:l instanceof Error?l.message:String(l)})}try{await this.drainRetirementOrphans(n)}catch(l){c.error("E1: retirement-orphan drain failed (non-fatal)",{sessionId:n,error:l instanceof Error?l.message:String(l)})}try{await this.appSyncClient.startHeartbeat(n)?await L("daemon_init_step_completed",{step:"heartbeat_start",path:"session_started"}):(await L("daemon_init_step_failed",{step:"heartbeat_start",path:"session_started",error_class:"InitialHeartbeatNotPersisted",error_message:"Backend did not confirm the initial heartbeat mutation"}),c.error("Initial session heartbeat was not persisted",{sessionId:n}))}catch(l){await L("daemon_init_step_failed",{step:"heartbeat_start",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),c.error("Failed to start heartbeat:",l)}try{await this.subscribeToOnApplyUserDecision(n)}catch(l){c.error("Failed to subscribe to onApplyUserDecision (non-fatal)",{error:l})}this.startMobileEndWatcher(n);try{await this.flushBufferedLogEntries(),await L("daemon_init_step_completed",{step:"flush_buffered_entries",path:"session_started"})}catch(l){await L("daemon_init_step_failed",{step:"flush_buffered_entries",path:"session_started",error_class:l?.name||"Error",error_message:l?.message||String(l)}),c.error("Failed to flush buffered log entries:",l),this.bufferedLogEntries=[]}this.nativeAuthority||await this.startTmuxObserverWithBeacon("session_started"),this.isInitializingSession=!1}getOrCreateBootstrapSessionId(){return this.bootstrapSessionId||(this.bootstrapSessionId=_e.mintBackendSessionId()),this.bootstrapSessionId}async bindRecoveryBootstrapIdentity(e){if(!(process.env[Xe]!=="1"||this.bootstrapSessionId||this.sessionState||!e)){if(this.nativeAuthority){let t=this.appSyncClient.getCurrentUserId(),i=this.nativeAuthority.record.instanceId,s=await v.keychainManager.getDeviceIdentity();if(!s)throw Error("NATIVE_DEVICE_IDENTITY_UNAVAILABLE");let n=()=>{if(this.nativeAuthority.assertCurrent(),this.appSyncClient.getCurrentUserId()!==t)throw Error("NATIVE_ACCOUNT_CHANGED")},r=await this.appSyncClient.listSessions();n();let o=[];for(let d of r){if(d.agentType!==v.AgentType.CODEX||d.status!==v.SessionStatus.ACTIVE)continue;let l=await this.appSyncClient.getSession(d.sessionId);if(n(),!l||l.userId!==t||l.status!==v.SessionStatus.ACTIVE||l.creatorDeviceId!==s.deviceId)continue;let u=l.metadata;if(typeof u=="string"&&(u=JSON.parse(u)),u?.encrypted){let h=await v.keychainManager.getDeviceIdentity();if(n(),!h||h.deviceId!==s.deviceId||h.publicKey!==s.publicKey)throw Error("NATIVE_DEVICE_IDENTITY_CHANGED");let p=l.encryptedKeys?.find(f=>f.deviceId===s.deviceId);if(!p)throw Error("NATIVE_SESSION_KEY_UNAVAILABLE");let m=v.cryptoService.decryptSessionKey(p,h.privateKey);u=v.cryptoService.decryptMetadata(u.encrypted,m)}u?.codexSessionId===e&&u.codexNativeInstanceId===i&&o.push(l.sessionId)}if(o.length>1)throw Error("NATIVE_BOOTSTRAP_AMBIGUOUS");o.length===1&&(this.bootstrapSessionId=o[0],this.recoveryBootstrapOwnerBound=!0);return}try{let t=await this.buildToolActivityIntegration().recordedBackendSessionId(e);if(!t){c.warn("Recovery daemon found no durable backend owner; a new session will be created",{rolloutId:e});return}if(!/^codex-[A-Za-z0-9_-]{1,180}$/.test(t)){c.warn("Recovery daemon ignored invalid durable backend owner",{rolloutId:e});return}this.bootstrapSessionId=t,this.recoveryBootstrapOwnerBound=!0,c.info("Recovery daemon reclaiming existing backend session",{rolloutId:e,sessionId:t})}catch(t){c.warn("Recovery daemon could not read the durable rollout owner; a new session will be created",{rolloutId:e,error:t instanceof Error?t.message:String(t)})}}}isSessionIdReservedRejection(e){return(e instanceof Error?e.message:String(e)).includes("SESSION_ID_RESERVED")}async resumeOrCreateBootstrapSession(e){try{return await this.resumeBackendSession(e,this.appSyncClient,c)}catch(t){if(!this.recoveryBootstrapOwnerBound||!this.isSessionIdReservedRejection(t))throw t;return c.warn("Recovery discarded a permanently reserved pending create; retrying the durable rollout owner",{sessionId:e.sessionId}),this.resumeBackendSession(e,this.appSyncClient,c)}}startTmuxLifecycleMonitor(){if(this.tmuxLifecycleTimer)return;let e=process.env[we];e&&(this.tmuxLifecycleInitDeadlineMs=Date.now()+Qn,this.tmuxLifecycleTimer=setInterval(()=>{this.checkTmuxLifecycle(e)},Kn),this.tmuxLifecycleTimer.unref?.(),this.checkTmuxLifecycle(e))}async tmuxSessionState(e){try{return jt("stall-tmux-probe")&&(c.warn("[dev-fault] stall-tmux-probe: terminality probe will never settle",{tmuxSession:e}),await new Promise(()=>{})),await Vn("tmux",["has-session","-t",e],{timeout:5e3}),"alive"}catch(t){let i=Es(t);return i==="absent"?i:(c.warn("Could not inspect native Codex tmux session; preserving daemon",{tmuxSession:e,error:t instanceof Error?t.message:String(t)}),"unknown")}}async checkTmuxLifecycle(e){if(!(this.isStopping||this.tmuxLifecycleCheckInFlight)){this.tmuxLifecycleCheckInFlight=!0;try{let t=await this.tmuxSessionState(e);if(t==="alive"){this.tmuxLifecycleObservedAlive=!0;return}let i=this.tmuxLifecycleObservedAlive||Date.now()>=this.tmuxLifecycleInitDeadlineMs;if(t==="unknown"||!i||this.isStopping)return;this.stopTmuxLifecycleMonitor(),c.info("Native Codex tmux session ended; stopping companion daemon",{tmuxSession:e});let s=Ne(n=>process.exit(n),()=>c.error("Shutdown watchdog fired after native session end; exiting anyway",{watchdogMs:25e3,timedOutSteps:this.getTeardownStepsTimedOut(),durableObligationSettled:this.isDurableObligationSettledForExit()}),25e3,()=>this.isDurableObligationSettledForExit());this.stop().then(()=>{s(),process.exit(0)},n=>{s(),c.error("Failed to stop companion daemon after native session end",{error:n instanceof Error?n.message:String(n)}),process.exit(1)})}finally{this.tmuxLifecycleCheckInFlight=!1}}}stopTmuxLifecycleMonitor(){this.tmuxLifecycleTimer&&(clearInterval(this.tmuxLifecycleTimer),this.tmuxLifecycleTimer=null)}async shouldShutdownForTerminalSignal(e){if(e==="SIGHUP"){let t=process.env[we];if(t){let i=await this.tmuxSessionState(t);if(i!=="absent")return c.info("Ignoring SIGHUP while native Codex tmux session remains available",{tmuxSession:t,state:i}),!1}}return!0}async stopForTerminalSignal(e){return await this.shouldShutdownForTerminalSignal(e)?(await this.stop(),!0):!1}isLifecycleCurrent(e){return!this.isStopping&&this.lifecycleGeneration===e}authoritativeSessionIdFromError(e){let t=e?.authoritativeSessionId;return typeof t=="string"&&t.length>0?t:null}async retireCancelledBootstrap(e,t){this.appSyncClient.stopHeartbeat(e),this.appSyncClient.cleanupSubscription(e);try{await this.appSyncClient.updateSession({sessionId:e,status:v.SessionStatus.INACTIVE}),c.info("Cancelled bootstrap row marked INACTIVE",{sessionId:e,path:t})}catch(i){c.warn("Cancelled bootstrap row could not be marked INACTIVE",{sessionId:e,path:t,error:i instanceof Error?i.message:String(i)})}}bindBootstrapIdentityFromError(e){let t=e?.authoritativeSessionId;typeof t!="string"||t.length===0||(this.bootstrapSessionId=t,c.info("Retained authoritative backend identity from failed bootstrap",{sessionId:t}))}recoverRetiredBackendSession(e,t){if(this.retiredSessionRecoveryPromise)return this.retiredSessionRecoveryPromise;if(this.isStopping)return Promise.resolve();let i=(async()=>{if(this.launchSessionInitPromise&&await this.launchSessionInitPromise,this.sessionStartedInitPromise&&await this.sessionStartedInitPromise,t?.aborted||this.isStopping)return;let s=this.nativeRetirement,n=s,r=s?.predecessor??this.sessionState;if(!r||r.sessionId!==e)return;if(!s&&this.sessionState!==r)throw Error("NATIVE_RETIREMENT_OWNER_CHANGED");let o=()=>{if(t?.aborted||this.isStopping)throw Error("NATIVE_RETIREMENT_CANCELLED");if(this.nativeAuthority&&(this.nativeAuthority.assertCurrent(),this.appSyncClient.getCurrentUserId()!==r.userId||n&&(this.nativeRetirement!==n||this.nativeRuntime?.thread?.id!==n.meta.id)))throw Error("NATIVE_RETIREMENT_OWNER_CHANGED")};o();let d=s?.meta??{id:r.codexSessionId||e,timestamp:new Date().toISOString(),cwd:r.cwd||r.projectPath,originator:"codevibe-retired-session-recovery",cli_version:String(r.metadata?.cliVersion??"unknown"),instructions:null,source:"codevibe",model_provider:String(r.metadata?.modelProvider??"unknown")};c.warn("Backend retired live Codex session; creating replacement row",{sessionId:e,codexSessionId:d.id});let l=null;if(this.nativeAuthority){let u;l={ready:new Promise(p=>{u=p}),release:u},this.nativeReplacementGate=l,this.nativeDegraded=!0,this.controlAdmission().invalidate()}else this.parkRetirementOrphans(e);n=this.nativeAuthority?this.nativeRetirement??={predecessor:r,meta:d,stage:"retire",bootstrapId:null,successor:null}:null;try{let u=this.controlAdmission().capture();if(!n||n.stage==="retire"){if(this.sessionState!==r)throw Error("NATIVE_RETIREMENT_OWNER_CHANGED");let h=this.endActiveSession("backend-generation-retired");if(u=this.controlAdmission().capture(),await h,this.sessionState)throw Error("NATIVE_RETIREMENT_INCOMPLETE");n&&(n.stage="bootstrap")}if(o(),this.sessionWatcher.refreshNativeOwnerBoundary(),!n||n.stage==="bootstrap"){let h=n?n.bootstrapId??=_e.mintBackendSessionId():_e.mintBackendSessionId();if(this.bootstrapSessionId=h,this.recoveryBootstrapOwnerBound=!1,this.clearSessionBootstrapFailure(),await this.ensureSessionStarted(d),o(),n){let p=this.sessionState;if(!p||p===r||p.sessionId!==h)throw Error("NATIVE_REPLACEMENT_INCOMPLETE");this.nativeControlOwner?.state!==p&&await this.initializeNativeControl(p),n.successor=p,n.stage="finish"}}if(n&&this.sessionState!==n.successor)throw Error("NATIVE_RETIREMENT_OWNER_CHANGED");if(l){l.release(),await this.nativeRuntime.client.joinHandlers(),o();let h=this.nativeControlOwner;if(!h||h.state===r||this.isStopping)throw Error("NATIVE_REPLACEMENT_INCOMPLETE");let p=await this.activateNativeControl(t,l,u);if(this.sessionState!==h.state)throw Error("NATIVE_REPLACEMENT_INCOMPLETE");if(await this.pruneSettledNativePredecessor(h.state),o(),!await this.appSyncClient.startHeartbeat(h.state.sessionId))throw Error("NATIVE_REPLACEMENT_HEARTBEAT_UNAVAILABLE");o(),p||(this.emitNativeControlHealthNotice("unavailable").catch(()=>{}),this.scheduleNativeControlRecovery())}this.nativeRetirement===n&&(this.nativeRetirement=null)}catch(u){throw n&&this.nativeRetirement===n&&this.degradeNativeControl("NATIVE_RETIREMENT_RECOVERY_FAILED"),u}finally{l?.release(),this.nativeReplacementGate===l&&(this.nativeReplacementGate=null)}this.nativeControlOwner?.adapter.isAccepting&&(l&&this.emitNativeControlHealthNotice("restored").catch(()=>{}),await this.nativeControlOwner.adapter.recover())})();return this.retiredSessionRecoveryPromise=i.finally(()=>{this.retiredSessionRecoveryPromise=null}),this.retiredSessionRecoveryPromise}recordSessionBootstrapFailure(e,t){this.sessionBootstrapFailureCount+=1;let i=e instanceof Error?e.message:String(e),n=i.includes("SESSION_LIMIT_EXCEEDED")?6e4:Math.min(5e3*2**(this.sessionBootstrapFailureCount-1),6e4);this.sessionBootstrapRetryAt=Date.now()+n,c.warn("Session bootstrap retry scheduled",{path:t,requestedSessionId:this.bootstrapSessionId,failureCount:this.sessionBootstrapFailureCount,delayMs:n,error:i})}clearSessionBootstrapFailure(){this.sessionBootstrapFailureCount=0,this.sessionBootstrapRetryAt=0}async flushBufferedLogEntries(){if(this.bufferedLogEntries.length===0)return;let e=this.bufferedLogEntries;this.bufferedLogEntries=[],c.info("Flushing buffered log entries after session initialization",{count:e.length,sessionId:this.sessionState?.sessionId});let t=Promise.resolve();for(let i of e)t=this.enqueueLogEntry(i);await t.catch(()=>{})}enqueueLogEntry(e){let t=this.logEntryChain.then(async()=>{await this.handleLogEntry(e)});return this.logEntryChain=t.catch(i=>{c.error("[JSONL] log entry handler failed",{type:e.type,err:String(i)})}),t}selectNativeSourceTransport(e){if(this.sessionState!==e||this.isStopping)return Promise.reject(new Error("SYNC_SOURCE_OWNER_CHANGED"));if(this.nativeSourceSelection?.state===e)return this.nativeSourceSelection.pending;let t=this.appSyncClient.selectCompanionSourceTransport({sessionId:e.sessionId}),i={state:e,pending:t};return this.nativeSourceSelection=i,t.catch(()=>{this.nativeSourceSelection===i&&(this.nativeSourceSelection=null)}),t}async retryNativeAdmission(e){try{return await e()}catch(t){throw!this.isStopping&&!this.nativeSourceRetryTimer&&(this.nativeSourceRetryTimer=setTimeout(()=>{this.nativeSourceRetryTimer=null,this.sessionWatcher.retryActiveRead()},5e3),this.nativeSourceRetryTimer.unref()),t}}assertNativeSourceOwner(e){if(this.sessionState!==e.state||e.controller.signal.aborted)throw new Error("SYNC_SOURCE_OWNER_CHANGED")}async nativeSourceOwner(e){if(this.isStopping)throw new Error("SYNC_SOURCE_STOPPING");this.launchSessionInitPromise&&await this.launchSessionInitPromise,this.sessionStartedInitPromise&&await this.sessionStartedInitPromise;let t=this.sessionState;if(!t||!e.nativeSessionId||this.sessionWatcher.getActiveLogFile()!==e.transcriptPath||this.sessionWatcher.getAuthoritativeSessionId()!==null&&this.sessionWatcher.getAuthoritativeSessionId()!==e.nativeSessionId)throw new Error("SYNC_SOURCE_BOOTSTRAP_PENDING");let i=await this.selectNativeSourceTransport(t);if(this.sessionState!==t||this.isStopping)throw new Error("SYNC_SOURCE_OWNER_CHANGED");if(i.protocol==="LEGACY")return null;if(await this.ensureToolActivityStarted(e.nativeSessionId),this.sessionState!==t||this.isStopping||!this.toolActivity?.isActive())throw new Error("SYNC_SOURCE_OWNERSHIP_UNAVAILABLE");let s=Ee.createHash("sha256").update(JSON.stringify([e.transcriptPath,e.nativeSessionId])).digest("hex"),n=`${i.sessionScope.sessionGenerationId}:${s}`,r=this.nativeSourceOwners.get(n);if(r)return this.assertNativeSourceOwner(r),r;let o={state:t,selection:i,streamSha256:s,cursor:i.writer.sourceStream({provider:"codex",streamSha256:s}),controller:new AbortController,drain:null,drainRequested:!1,retryTimer:null,retryMs:5e3};return this.nativeSourceOwners.set(n,o),o}async restoreNativeSource(e,t){let i=await this.nativeSourceOwner(e);if(!i)return null;await i.cursor.recover();let s=await i.cursor.open(t);return await i.selection.writer.mobileEchoes("codex").reconcile(i.streamSha256,s.byteOffset),this.assertNativeSourceOwner(i),this.drainNativeSource(i),{byteOffset:s.byteOffset,anchor:s.anchor,discardUntilNewline:s.discardUntilNewline}}async admitNativeSourceGap(e,t){let i=await this.nativeSourceOwner(t);if(!i)throw new Error("SYNC_SOURCE_PROTOCOL_CHANGED");await i.cursor.skip(e),this.assertNativeSourceOwner(i)}async admitNativeSourceEntry(e,t){let i=await this.nativeSourceOwner(t);if(!i)return;let s=this.logEntryChain.then(async()=>{this.assertNativeSourceOwner(i);let n=await i.cursor.load();if(!n)throw new Error("SYNC_SOURCE_CURSOR_MISSING");if(t.endOffset<=n.byteOffset)return;let r=null;if(this.nativeAuthority&&this.nativeControlOwner?.state===i.state){let h=hi(e,i.state.codexSessionId);if(h){let m=h.params,f={threadId:m.threadId,turnId:m.turnId,itemId:m.item.id};this.nativeQuestionFrame=f;try{await this.nativeControlOwner.adapter.observe(h)}finally{this.nativeQuestionFrame===f&&(this.nativeQuestionFrame=null)}}let p=mi(e,i.state.codexSessionId);p&&(await this.nativeControlOwner.adapter.observe(p),r=await this.nativeControlOwner.adapter.projectInputReceipt(p.params))}let o=Fi(e,i.state.sessionId,n.projection);if(this.nativeAuthority&&((e.type==="response_item"&&e.payload?.type==="message"&&e.payload.role==="user"||e.type==="event_msg"&&e.payload?.type==="user_message")&&(o.event=null),r&&(o.event=!r.echo&&r.text!==null?{sessionId:i.state.sessionId,source:v.EventSource.DESKTOP,type:v.EventType.USER_PROMPT,content:r.text,metadata:{images:r.images}}:null)),o.event&&!["USER_PROMPT","ASSISTANT_RESPONSE","REASONING","TOOL_USE","NOTIFICATION"].includes(o.event.type))throw new Error("SYNC_NATIVE_SPECIALIZED_PRODUCER_REQUIRED");let d={streamSha256:i.streamSha256,occurrence:`${t.startOffset}:${t.endOffset}`,sourceSha256:t.sha256,startOffset:t.startOffset,endOffset:t.endOffset},l=i.selection.writer.mobileEchoes("codex"),u=await this.handleLogEntry(e,{event:o.event});if(this.assertNativeSourceOwner(i),!this.isExpectedSessionStateCurrent(i.state))throw new Error("SYNC_SOURCE_OWNER_STOPPING");!this.nativeAuthority&&u?.type===v.EventType.USER_PROMPT&&await l.claim(d,u.content,e.timestamp)&&(u=void 0),await i.cursor.admit({provider:"codex",streamSha256:i.streamSha256,occurrence:`${t.startOffset}:${t.endOffset}`,sourceSha256:t.sha256,startOffset:t.startOffset,endOffset:t.endOffset,anchor:t.anchor},u?h=>i.selection.prepareEvent(u,h):null,o.projection),await l.reconcile(i.streamSha256,t.endOffset),this.drainNativeSource(i)});return this.logEntryChain=s.catch(n=>{c.warn("[sync-source] native admission retained for retry",{error:String(n)})}),await s,"handled"}drainNativeSource(e){if(e.controller.signal.aborted||this.isStopping||(e.drainRequested=!0,e.drain||e.retryTimer))return;e.drainRequested=!1;let t=(async()=>{let i=!1;try{await e.cursor.drain(64,e.controller.signal)===64&&(e.drainRequested=!0),e.retryMs=5e3}catch(s){i=!0,e.controller.signal.aborted||c.warn("[sync-source] cloud drain retained for retry",{error:String(s)}),e.retryMs=Math.min(e.retryMs*2,6e4)}e.drain=null,!e.controller.signal.aborted&&!this.isStopping&&this.sessionState===e.state&&(i?(e.retryTimer=setTimeout(()=>{e.retryTimer=null,this.drainNativeSource(e)},e.retryMs),e.retryTimer.unref()):e.drainRequested&&this.drainNativeSource(e))})();e.drain=t,t.catch(i=>c.error("[sync-source] unexpected drain failure",{error:String(i)}))}async stopNativeSources(e){this.nativeSourceRetryTimer&&clearTimeout(this.nativeSourceRetryTimer),this.nativeSourceRetryTimer=null;let t=[...this.nativeSourceOwners].filter(([,i])=>i.state===e);for(let[,i]of t)i.retryTimer&&clearTimeout(i.retryTimer),i.retryTimer=null,i.controller.abort(new Error("SYNC_SOURCE_STOPPED"));await Promise.all(t.map(([,i])=>i.drain?.catch(()=>{})));for(let[i]of t)this.nativeSourceOwners.delete(i);this.nativeSourceSelection?.state===e&&(this.nativeSourceSelection=null)}async handleLogEntry(e,t){if(!this.sessionState){if(this.isInitializingSession){this.bufferedLogEntries.push(e),c.debug("Buffering log entry until session initialization completes",{type:e.type,bufferedCount:this.bufferedLogEntries.length});return}c.warn("Received log entry but no active session");return}let i=this.sessionState,s=i.sessionId,{sessionKey:n,sessionIsEncrypted:r}=i.encryptionSnapshot;if(this.nativeAuthority||await this.reconcileNativeQuestionReply(He(e),i),this.sessionState!==i)return;if(!this.nativeAuthority&&e.type==="event_msg"&&e.payload?.type==="turn_aborted"&&(this.approvalDetector.clear(),this.clearInteractivePromptsForAcceptedInput(i)),!this.nativeAuthority&&e.type==="response_item"&&e.payload){let y=e.payload.type;if(y==="function_call"||y==="custom_tool_call")this.isQueuedQuestionTool(e.payload.name)?this.queuedQuestionCallIds.add(e.payload.call_id):this.approvalDetector.onToolCallStart(e.payload.call_id,e.payload.name,e.payload.arguments||e.payload.input||"");else if(y==="function_call_output"||y==="custom_tool_call_output"){if(this.queuedQuestionCallIds.has(e.payload.call_id)){this.queuedQuestionCallIds.delete(e.payload.call_id),this.approvalDetector.onToolCallComplete(e.payload.call_id);return}let S=this.approvalDetector.getPendingCalls().find(E=>E.callId===e.payload.call_id);if(S&&this.isQueuedQuestionTool(S.name)){this.approvalDetector.onToolCallComplete(e.payload.call_id);return}let I=S?this.buildApprovalDedupeKey(this.buildApprovalPromptContextFromPendingCall(S)):void 0;this.approvalDetector.onToolCallComplete(e.payload.call_id);let w=this.observePermissionRequestCompletion(I,"jsonl");if(w.shouldResolve&&await this.clearResolvedInteractivePrompt(e.payload.call_id,w.occurrenceKey??I),!this.isExpectedSessionStateCurrent(i))return}}let o=t?t.event:Bt(e,s);if(!o)return;o.timestamp=(0,v.prepareEventTimestamp)({orderingKey:s,agentClock:e.timestamp});let d=e.payload?.type,l=!1;if(this.toolActivity?.isActive()&&o.type===v.EventType.TOOL_USE){let y=d==="function_call"||d==="custom_tool_call",S=d==="function_call_output"||d==="custom_tool_call_output";if(y&&typeof e.payload?.call_id=="string"){let I=this.sessionWatcher.getActiveLogFile();I&&this.toolActivity.bindTranscript(I);let w=await this.toolActivity.observeCall({callId:e.payload.call_id,toolName:o.metadata?.toolName??o.metadata?.tool_name,toolInput:o.metadata?.toolInput??o.metadata?.tool_input,ts:e.timestamp});if(!this.isExpectedSessionStateCurrent(i)||w!=="closed")return;l=!0}if(S)return}let u=this.nativeAuthority&&e.type==="event_msg"&&d==="item_completed"&&(e.payload.item?.type==="UserMessage"||e.payload.item?.type==="AgentMessage"&&e.payload.item.phase==="final_answer");if(this.toolActivity?.isActive()&&(d==="user_message"||d==="agent_message"||u)){let y=this.toolActivity.flush();if(t?await y:await y.catch(S=>c.warn("[tool-activity] codex boundary flush failed",{sessionId:s,err:String(S)})),!this.isExpectedSessionStateCurrent(i))return}if(e.payload?.delivery==="async"&&await this.isAcknowledgedQueuedQuestionEcho(e,i))return;let h=d==="function_call"||d==="function_call_output",p=o.type===v.EventType.USER_PROMPT||o.type===v.EventType.ASSISTANT_RESPONSE||h&&(o.type===v.EventType.TOOL_USE||o.type===v.EventType.INTERACTIVE_PROMPT);if(!t&&!this.hooksActive&&p&&(await this.emitHooksCompatibilityModeNotice(i),!this.isExpectedSessionStateCurrent(i)))return;if(!t&&this.hooksActive){if(o.type===v.EventType.USER_PROMPT){c.debug("[JSONL] Skipping USER_PROMPT \u2014 hooks deliver it",{type:o.type});return}if(h&&(o.type===v.EventType.TOOL_USE||o.type===v.EventType.INTERACTIVE_PROMPT)&&!l){c.debug("[JSONL] Skipping function_call \u2014 hooks deliver this",{type:o.type,tool:e.payload?.name});return}}if(o.type===v.EventType.USER_PROMPT&&o.source===v.EventSource.DESKTOP){let y=t?null:this.consumeRecentMobilePrompt(s,o.content);if(y){c.info("[JSONL] Skipping duplicate USER_PROMPT from mobile",{sessionId:s,matchType:y.matchType,originalLength:y.originalLength,echoLength:y.echoLength});return}}if(this.sessionState!==i){c.warn("[JSONL] Dropping event from stale session generation (#638)",{sessionId:s,currentSessionId:this.sessionState?.sessionId});return}if(t)return o;let m=e.payload?.call_id,f=o.type===v.EventType.TOOL_USE&&typeof m=="string"&&m.length>0&&!!n,g=f?this.getToolActivityLegacyRecorder(s):void 0;g&&f&&g.markLegacyInFlight(m);try{let y=(0,v.encryptForEmit)(n,r,o.content,o.metadata);if(!y){c.error("No session key for ENCRYPTED session \u2014 dropping JSONL event (fail-closed, #638)",{type:o.type,sessionId:s});return}o.content=y.content,o.metadata=y.metadata,y.isEncrypted&&(o.isEncrypted=!0,c.debug("Event encrypted",{type:o.type}));let S=await this.appSyncClient.createEvent(o);c.debug("Event synced to backend",{type:o.type,encrypted:y.isEncrypted}),g&&f&&((0,v.isPersistedEventResult)(S)?await g.finalizeLegacyOwned([m]):g.clearLegacyInFlight(m))}catch(y){g&&f&&g.clearLegacyInFlight(m),c.error("Failed to sync event:",y)}}async handlePermissionRequestHook(e,t,i){if(!this.isExpectedSessionStateCurrent(t)){i&&(i.disposition="dropped");return}let s=i?.context??this.buildApprovalPromptContextFromHookPayload(e),n=i?.dedupeKey??this.buildApprovalDedupeKey(s);if(this.consumeRecoveryPermissionReplay(t,n,i))return;let r=i?.occurrenceKey??`permission:${(0,Se.v4)()}`,o={ownerState:t,context:s,dedupeKey:n,occurrenceKey:r,registration:i};this.permissionRequestHookInFlight=o;try{let d=await this.handlePermissionRequestHookWhileTracked(e,t,s,r,n);i&&(i.disposition=d)}finally{this.permissionRequestHookInFlight===o&&(this.permissionRequestHookInFlight=null)}}buildApprovalPromptContextFromHookPayload(e){let t=e.metadata||{},i=typeof t.tool_name=="string"?t.tool_name:"Tool",s=t.tool_input,n=this.firstString(s?.command,s?.cmd),r=Fe(n)||We(n),o=i==="apply_patch"?this.firstString(s?.patch,n,typeof s=="string"?s:void 0):void 0,l=Fe(o)||r,u=!!l,h=l?"apply_patch":i,p=l||this.stringifyToolInput(s),m=l?this.extractFilePathFromToolInput("apply_patch",void 0,l):this.extractFilePathFromToolInput(h,s,p),f=l?this.resolveHookPatchPath(m,t.cwd):m;return{toolName:h,framedPatch:u,toolInput:s,rawInput:p,filePath:f,diff:u?p:void 0,hint:f&&this.mapToolNameForApproval(h)==="Edit"?`File: ${f}`:this.buildPermissionRequestHint(h,s,p)}}resolveHookPatchPath(e,t){if(!e||W.isAbsolute(e))return e;if(!(typeof t!="string"||!W.isAbsolute(t)))return W.resolve(t,e)}async handlePermissionRequestHookWhileTracked(e,t,i=this.buildApprovalPromptContextFromHookPayload(e),s=`permission:${(0,Se.v4)()}`,n,r){let o=e.metadata||{},{toolName:d,toolInput:l,rawInput:u}=i,h=this.buildToolDetailsForInteractivePrompt(i),p=h.tool_name||this.mapToolNameForApproval(d),m=h.tool_input||this.buildFallbackToolInput(i),f=!!(p&&m);if(n??=this.buildApprovalDedupeKey({toolName:d,toolInput:l,filePath:i.filePath,rawInput:u,hint:i.hint}),this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,s))return"resolved";let g=this.promptGeneration,y=r??await this.tryParsePermissionRequestPromptFromTmux((A,se)=>this.parsedPromptMatchesApprovalContext(A,i,se),()=>this.isExpectedSessionStateCurrent(t)&&this.promptGeneration===g);if(!this.isExpectedSessionStateCurrent(t)||this.promptGeneration!==g)return c.warn("[Hooks] Dropping stale PermissionRequest after session/prompt generation changed",{sessionId:t.sessionId,currentSessionId:this.sessionState?.sessionId,generationAtStart:g,currentGeneration:this.promptGeneration}),"dropped";if(this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,s))return c.info("[Hooks] Dropping PermissionRequest completed while terminal options were being parsed",{sessionId:t.sessionId,toolName:d,occurrenceKey:s}),"resolved";let S=y?.parsedPrompt??null;if(!S)return y?.differentPrompt?(this.waitingPermissionRequests.set(s,{ownerState:t,context:i,occurrenceKey:s,dedupeKey:n,payload:e}),c.info("[Hooks] Queued PermissionRequest until its desktop dialog is visible",{sessionId:t.sessionId,occurrenceKey:s,toolName:d}),"waiting"):(c.warn("[Hooks] Suppressing PermissionRequest mobile prompt because exact Codex options are unavailable",{sessionId:t.sessionId,toolName:d,hint:i.hint}),this.raiseSuppressedBadge(t.sessionId,s,{suppressTmuxObserverUntilResolved:!0,observerSnapshot:y?.snapshot,completionKey:n}),"covered");let I=this.mapToolNameForApproval(d)==="Bash"?this.firstString(l?.command,l?.cmd):void 0,{presentation:w,failureReason:E}=this.buildCodexPromptPresentationDetailed(S,I,y?.snapshot);if(!w)return c.warn("[Hooks] Suppressing PermissionRequest mobile prompt because Codex presentation options are unavailable",{sessionId:t.sessionId,toolName:d,hint:i.hint,reason:E??"unsupported_options"}),this.raiseSuppressedBadge(t.sessionId,s,{suppressTmuxObserverUntilResolved:!0,observerSnapshot:y?.snapshot,completionKey:n}),"covered";let R=s,b=this.buildApprovalPromptContent(w.content,{toolName:p,toolInput:m,hint:i.hint,filePath:i.filePath}),_={promptId:R,kind:w.kind,options:w.options,submitMap:w.submitMap,promptText:b,createdAt:Date.now(),source:"permission_hook",dedupeKey:s,completionKey:n,ownerSessionId:t.sessionId,observerMatchKey:this.buildObserverPromptMatchKey(S,y?.snapshot),observerPromptHash:y?.snapshot?this.tmuxPaneObserver.hashPromptSnapshot(y.snapshot):void 0,requiresFollowUpText:w.requiresFollowUpText},x={isApprovalHint:!0,toolName:d,toolInput:l,hint:i.hint,filePath:i.filePath,diff:i.diff,rawInput:u,tool_name:p,tool_input:m,has_details:f,options:w.options,instructions:w.instructions,prompt_source:S?"permission_hook_tmux":"permission_hook",permission_mode:o.permission_mode,turn_id:o.turn_id,dedupe_key:s};return c.info("[Hooks] Sending PermissionRequest interactive prompt",{sessionId:t.sessionId,toolName:d,promptId:R,promptSource:x.prompt_source,occurrenceKey:s}),!this.isExpectedSessionStateCurrent(t)||this.promptGeneration!==g?(c.warn("[Hooks] Dropping stale PermissionRequest before enqueue after prompt generation changed",{sessionId:t.sessionId,generationAtStart:g,currentGeneration:this.promptGeneration}),"dropped"):(await this.enqueueOrEmitInteractivePrompt({prompt:_,content:b,metadata:x,ownerState:t}),this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,s)?"resolved":"covered")}isQueuedQuestionTool(e){return typeof e=="string"&&e==="request_user_input_async"}async reconcileNativeQuestionReply(e,t){let i=Me(e);if(!(!i||!this.isExpectedSessionStateCurrent(t)))for(let s of i){let r=[this.pendingInteractivePrompt,...this.queuedInteractivePrompts.filter(o=>o.ownerState===t).map(o=>o.prompt)].find(o=>o?.kind==="queued_question"&&o.ownerSessionId===t.sessionId&&o.callId===s.callId&&o.dedupeKey===`queued-question::${s.callId}`&&(o.allQuestions?.length??1)===1&&s.index===0&&(o.nativeQuestionTitleSha256?o.nativeQuestionTitleSha256===Ee.createHash("sha256").update(s.question.trim()).digest("hex"):o.promptText.trim()===s.question.trim()));if(r&&(await this.clearResolvedInteractivePrompt(s.callId,r.dedupeKey),!this.isExpectedSessionStateCurrent(t)))return}}recordHistoricalQueuedQuestionId(e){if(typeof e=="string"&&e.trim().length>0&&Buffer.byteLength(e,"utf8")<=512&&(this.historicalQueuedQuestionPromptIds.add(e),this.historicalQueuedQuestionPromptIds.size>2e3)){let t=this.historicalQueuedQuestionPromptIds.values();for(;this.historicalQueuedQuestionPromptIds.size>1e3;){let i=t.next();if(i.done)break;this.historicalQueuedQuestionPromptIds.delete(i.value)}}}isQueuedQuestionPromptId(e){if(!e)return!1;if(this.historicalQueuedQuestionPromptIds.has(e)||e.startsWith("q-")||e.startsWith("queued-question::")||this.queuedQuestionCallIds.has(e)||this.pendingInteractivePrompt?.kind==="queued_question"&&(this.pendingInteractivePrompt.promptId===e||this.pendingInteractivePrompt.callId===e||this.pendingInteractivePrompt.dedupeKey===e)||this.queuedInteractivePrompts.some(i=>i.prompt.kind==="queued_question"&&(i.prompt.promptId===e||i.prompt.callId===e||i.prompt.dedupeKey===e)))return!0;let t=this.e1PromptRaises.get(e);return!!(t&&(t.resolutionCallId&&(this.historicalQueuedQuestionPromptIds.has(t.resolutionCallId)||this.queuedQuestionCallIds.has(t.resolutionCallId))||t.resolutionDedupeKey&&(this.historicalQueuedQuestionPromptIds.has(t.resolutionDedupeKey)||t.resolutionDedupeKey.startsWith("queued-question::"))))}queuedQuestionText(e,t){return String(typeof e=="object"&&e!==null?e.title||e.question||e.prompt||`Question ${t+1}`:e)}normalizeQueuedQuestions(e){return Array.isArray(e)?e.slice(0,100).map((t,i)=>{let s=this.queuedQuestionText(t,i).slice(0,1024),r=(typeof t=="object"&&t!==null&&Array.isArray(t.options)?t.options:[]).slice(0,100).map(d=>{if(typeof d=="string")return d.slice(0,1024);if(typeof d=="object"&&d!==null){let l="label"in d?d.label:"text"in d?d.text:String(d),u=String(l).slice(0,1024),h=d.description?String(d.description).slice(0,1024):void 0,p=d.preview?String(d.preview).slice(0,1024):void 0;return{label:u,...h?{description:h}:{},...p?{preview:p}:{}}}return String(d).slice(0,1024)}).filter(d=>{let l=typeof d=="string"?d:d&&typeof d=="object"?d.label:"";return typeof l=="string"&&l.trim().length>0}),o=typeof t=="object"&&t!==null&&typeof t.header=="string"&&t.header.trim().length>0?t.header.trim().slice(0,1024):void 0;return{question:s,...o?{header:o}:{},options:r,multiSelect:typeof t=="object"&&t!==null?!!t.multiSelect:!1}}):[]}async emitQueuedQuestionDesktopNotice(e,t,i){let s={queued_question_desktop_only:!0,notice:t};try{let n=(0,v.prepareEventTimestamp)({orderingKey:e});await this.appSyncClient.publishCompanionNotice({sessionId:e,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:t,metadata:s,timestamp:n},async()=>{if(!this.isExpectedSessionStateCurrent(i))return!1;let r=this.encryptForEmit(t,s,v.EventType.NOTIFICATION,e);return r?(await this.appSyncClient.createEvent({sessionId:e,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:r.content,metadata:r.metadata,timestamp:n,...r.isEncrypted?{isEncrypted:!0}:{}}),!0):!1})}catch(n){c.warn("Failed to emit queued question desktop notice",{error:n})}}async handleQueuedQuestionHook(e,t){let i=e.metadata||{},s=i.tool_input,n=typeof s=="string"?(()=>{try{return JSON.parse(s)}catch{return{}}})():s||{},r=this.normalizeQueuedQuestions(n.questions);if(r.length===0){c.warn("[Hooks] Queued question tool called with empty questions array",{sessionId:t.sessionId,toolName:i.tool_name});return}if(r.length>1){c.info("Queued question has multiple questions; degrading to desktop notice",{sessionId:t.sessionId,questionCount:r.length}),await this.emitQueuedQuestionDesktopNotice(t.sessionId,"\u26A0\uFE0F Multiple questions queued in Codex TUI. Please answer them in your desktop terminal.",t);return}let o=r[0];if(o.multiSelect){c.info("Queued question uses multiSelect; degrading to desktop notice",{sessionId:t.sessionId}),await this.emitQueuedQuestionDesktopNotice(t.sessionId,"\u26A0\uFE0F This queued question uses multi-select, which cannot be answered from mobile. Please answer it in your desktop terminal.",t);return}if(!o.options||o.options.length===0){c.info("Queued question has no options; degrading to desktop notice",{sessionId:t.sessionId}),await this.emitQueuedQuestionDesktopNotice(t.sessionId,"\u26A0\uFE0F This queued question has no predefined options \u2014 please answer it in your desktop terminal.",t);return}let d=this.firstString(i.tool_use_id,i.call_id,i.callId)??`synth-${Date.now()}`;d.startsWith("synth-")||this.queuedQuestionCallIds.add(d);let l=`queued-question::${d}`,u=d;this.recordHistoricalQueuedQuestionId(d),this.recordHistoricalQueuedQuestionId(l);let h=o.question,p=o.options.map((I,w)=>{let E=String(w+1),R=typeof I=="string",b=R?I:I.label||"",_=R?void 0:I.description,x=R?void 0:I.preview;return{number:E,text:b,..._?{description:_}:{},...x?{preview:x}:{}}}),m=Object.fromEntries(p.map(I=>[I.number,I.number])),f="Reply with the number of your choice.",g=[{question:o.question,...o.header?{header:o.header}:{},multiSelect:!1,options:p,instructions:f}],y={promptId:u,callId:d,kind:"queued_question",options:p,submitMap:m,promptText:h,createdAt:Date.now(),source:"queued_question",dedupeKey:l,completionKey:l,ownerSessionId:t.sessionId,requiresFollowUpText:!1,allQuestions:r,nativeQuestionTitleSha256:Ee.createHash("sha256").update(this.queuedQuestionText(n.questions[0],0).trim()).digest("hex")},S={isApprovalHint:!1,isQueuedQuestion:!0,tool_name:i.tool_name,tool_use_id:d,questions:g,options:p,submitMap:m,instructions:f,prompt_source:"queued_question",turn_id:i.turn_id,dedupe_key:l};c.info("[Hooks] Emitting queued question INTERACTIVE_PROMPT",{sessionId:t.sessionId,toolName:i.tool_name,promptId:u,optionsCount:p.length}),await this.enqueueOrEmitInteractivePrompt({prompt:y,content:h,metadata:S,ownerState:t})}queuedQuestionEchoSignature(e){if(!Array.isArray(e)||e.length!==1)return null;let t=e[0];if(!t||typeof t!="object")return null;let i=t.title??t.question;if(typeof i!="string"||!i.trim()||i.length>2048||!Array.isArray(t.options)||t.options.length===0||t.options.length>20)return null;let s=[];for(let n of t.options){let r=typeof n=="string"?n:n?.label??n?.text;if(typeof r!="string"||!r.trim()||r.length>2048)return null;s.push(r)}return JSON.stringify([i,s])}async isAcknowledgedQueuedQuestionEcho(e,t){let i=e.payload;if(e.type!=="event_msg"||i?.type!=="agent_message"||i.delivery!=="async"||i.phase!=="final_answer")return!1;let s=this.queuedQuestionEchoSignature(i.questions);if(!s)return!1;let n=[...this.e1PromptRaises.values()].filter(o=>o.record.sessionId===t.sessionId&&o.record.mobileActionable&&o.metadataPlain?.isQueuedQuestion===!0&&this.queuedQuestionEchoSignature(o.metadataPlain.questions)===s);if(n.length!==1)return!1;let r=n[0];return await this.e1RaiseInFlight.get(r.record.promptId),this.isExpectedSessionStateCurrent(t)&&this.e1PromptRaises.get(r.record.promptId)===r&&this.acknowledgedQueuedQuestionRaises.has(r)}isQueuedQuestionStrictHintLine(e){let t=e.trim();return/to answer$/i.test(t)?/^(?:⇥|->|<-|\bTab\b|[⇧⬆]?←|\b(?:Shift[+-]|S-)Left\b)\s+to answer$/i.test(t):!1}isQueuedQuestionHintLine(e){return this.isQueuedQuestionStrictHintLine(e)}matchQueuedQuestionCounter(e){return e.match(/^\s*\?\s*(\d+)\s+questions?(?:\s+·\s+\d{1,3}s)?\s*$/i)}hasQueuedQuestionHintLine(e){let t=e.split(`
55
+ `);return t.some((i,s)=>{let n=i.trim();if(this.isQueuedQuestionStrictHintLine(n))return!0;if(/^to answer$/i.test(n)){let r=Math.max(0,s-2),o=Math.min(t.length-1,s+2);for(let d=r;d<=o;d++)if(d!==s&&(/^\s*•?\s*Queued follow-up inputs\s*$/i.test(t[d])||this.matchQueuedQuestionCounter(t[d])!==null))return!0}return!1})}hasQueuedInputsFragment(e){let t=e.split(`
56
+ `),i=t.some(r=>/^\s*•?\s*Queued follow-up inputs\s*$/i.test(r)),s=t.some(r=>this.matchQueuedQuestionCounter(r)!==null),n=this.hasQueuedQuestionHintLine(e);return i||s||n}isModelStatusFooterLine(e){return/^[>›]/.test(e)?!1:/^(?:(?:GPT|Claude|Codex|DeepSeek)[-\s]\d[\w.-]*|o\d[\w.-]*)(?:\s+(?:xhigh|high|medium|low|fast|slow|default))*(?:\s+[·•|]\s+\S.*)?$/i.test(e)}isShortcutsOrStatusHintLine(e){if(/^[>›]/.test(e))return!1;let t=e.trim();if(t.length===0||/^← for agents · \? for shortcuts$/i.test(t))return!0;let i="(?:esc to interrupt|\\?\\s+for\\s+(?:shortcuts|help)|\\d+%\\s+context\\s+left|\u26A0\\s+\\d+\\s+warning.*)";return new RegExp(`^${i}(?:\\s{2,}${i})?$`,"i").test(t)}validateTrailingFooterLines(e){return e.length===0?!0:e.length>2?!1:e.length===1?this.isModelStatusFooterLine(e[0])||this.isShortcutsOrStatusHintLine(e[0]):this.isModelStatusFooterLine(e[0])&&this.isShortcutsOrStatusHintLine(e[1])}isAssistantExecutionLine(e){let t=e.trim();return!!(/^•\s*Working(?:\s*\(.*?\))?\s*$/i.test(t)||/^•\s*(?:Ran|Read|Edited|Searched|Thinking|Explored)\b/i.test(t)||/^•\s*(?:Applied|Done|Finished|Plan completed|I have finished|I've finished)\b/i.test(t)||/^•\s*Failed\s*\(exit\s+\d+\)/i.test(t)||/^✔\s*You approved\b/i.test(t)||/^\+\s*\d+\s+lines?\b/i.test(t)||/^└\s*(?:exit code \d+|Tip:|Read|[+]\s*\d+\s+lines)/i.test(t))}isHistoricalFooter(e,t){if(t<0||t>=e.length)return{isFooter:!1,footerStartIdx:-1};if(t>=2){let i=e[t-2].trim(),s=e[t-1].trim(),n=e[t].trim();if(/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(i)&&s.length>0&&n.length>0&&this.isModelStatusFooterLine(s)&&this.isShortcutsOrStatusHintLine(n))return{isFooter:!0,footerStartIdx:t-1}}if(t>=1){let i=e[t-1].trim(),s=e[t].trim();if(/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(i)&&s.length>0&&this.isModelStatusFooterLine(s))return{isFooter:!0,footerStartIdx:t}}return{isFooter:!1,footerStartIdx:-1}}isHistoricalTurnBoundary(e,t){if(t<0||t>=e.length)return!1;let i=e[t];return/^[>›]\s*Ask Codex to do anything\s*$/i.test(i)?!0:this.isHistoricalFooter(e,t).isFooter}isDraftPromptLine(e){return!(!/^[>›]/.test(e)||/^[>›]\s*Ask Codex to do anything\s*$/i.test(e)||/^[>›]\s*$/.test(e))}extractLiveQueuedQuestionWidget(e){let s=ae(e).split(`
55
57
  `).slice(-25).join(`
56
58
  `).split(`
57
- `).map(y=>y.trim()).filter(y=>y.length>0);if(s.length<2)return null;let n=[];for(let y=0;y<=s.length-3;y++){let w=/^\s*•?\s*Queued follow-up inputs\s*$/i.test(s[y]),v=this.matchQueuedQuestionCounter(s[y+1]),S=/^to answer$/i.test(s[y+2]),b=this.isQueuedQuestionStrictHintLine(s[y+2])||S&&w&&v!==null;w&&v&&b&&n.push({headerIdx:y,counterIdx:y+1,hintIdx:y+2,count:parseInt(v[1],10)})}if(n.length===0){for(let y=s.length-1;y>=0;y--)if(/^[>›]/.test(s[y])){let w=s.slice(y+1);if(this.validateTrailingFooterLines(w)&&!/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(s[y]))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};break}return null}let r=n[n.length-1],o=r.hintIdx+1;if(o>=s.length)return null;let a=s[o],l=s.slice(o+1);if(!this.validateTrailingFooterLines(l))return l.some(w=>this.isAssistantExecutionLine(w))?null:{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};if(this.isDraftPromptLine(a))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};let u=/^[>›]\s*Ask Codex to do anything\s*$/i.test(a),m=/^[>›]\s*$/.test(a);if(!u&&!m)return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};let h=0;for(let y=r.headerIdx-1;y>=0;y--)if(this.isHistoricalTurnBoundary(s,y)){h=y+1;break}let I=s.slice(h,r.headerIdx);if(m){if(I.some(w=>/^[>›]\s*$/.test(w)))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};for(let w=0;w<I.length;w++){let v=I[w];if(/^[>›]/.test(v)&&!/^[>›]\s*Ask Codex to do anything\s*$/i.test(v)&&!I.slice(w+1).some(b=>this.isAssistantExecutionLine(b)))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0}}}else for(let y=0;y<I.length;y++){let w=I[y];if(/^[>›]/.test(w)&&!/^[>›]\s*Ask Codex to do anything\s*$/i.test(w)&&!I.slice(y+1).some(P=>/^[•✔└+]/i.test(P.trim())))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0}}return{hintLineIdx:r.hintIdx,composerIdx:o,count:r.count,dirtyComposerFound:!1}}isQueuedQuestionCollapsed(e){let t=this.extractLiveQueuedQuestionWidget(e);return t!==null&&!t.dirtyComposerFound}isExpandedMenuMatchingQuestion(e,t){let i=n=>n.trim().replace(/\s+/g," ").toLowerCase();if(i(e.prompt.promptText)!==i(t.promptText))return!1;let s=e.prompt.options;if(s.length===t.options.length+1){let n=s[s.length-1];if(n.number!==String(s.length)||!/^Other(?:\s*\(write an answer\))?$/i.test(n.text.trim()))return!1;s=s.slice(0,-1)}return s.length===t.options.length&&s.every((n,r)=>n.number===t.options[r].number&&i(n.text)===i(t.options[r].text))}isExpandedQuestionMatchingPrompt(e,t){let i=(0,M.parseActiveTerminalMenu)(e);if(i)return this.isExpandedMenuMatchingQuestion(i,t);let n=oe(e).split(`
59
+ `).map(y=>y.trim()).filter(y=>y.length>0);if(s.length<2)return null;let n=[];for(let y=0;y<=s.length-3;y++){let S=/^\s*•?\s*Queued follow-up inputs\s*$/i.test(s[y]),I=this.matchQueuedQuestionCounter(s[y+1]),w=/^to answer$/i.test(s[y+2]),R=this.isQueuedQuestionStrictHintLine(s[y+2])||w&&S&&I!==null;S&&I&&R&&n.push({headerIdx:y,counterIdx:y+1,hintIdx:y+2,count:parseInt(I[1],10)})}if(n.length===0){for(let y=s.length-1;y>=0;y--)if(/^[>›]/.test(s[y])){let S=s.slice(y+1);if(this.validateTrailingFooterLines(S)&&!/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(s[y]))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};break}return null}let r=n[n.length-1],o=r.hintIdx+1;if(o>=s.length)return null;let d=s[o],l=s.slice(o+1);if(!this.validateTrailingFooterLines(l))return l.some(S=>this.isAssistantExecutionLine(S))?null:{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};if(this.isDraftPromptLine(d))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};let p=/^[>›]\s*Ask Codex to do anything\s*$/i.test(d),m=/^[>›]\s*$/.test(d);if(!p&&!m)return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};let f=0;for(let y=r.headerIdx-1;y>=0;y--)if(this.isHistoricalTurnBoundary(s,y)){f=y+1;break}let g=s.slice(f,r.headerIdx);if(m){if(g.some(S=>/^[>›]\s*$/.test(S)))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0};for(let S=0;S<g.length;S++){let I=g[S];if(/^[>›]/.test(I)&&!/^[>›]\s*Ask Codex to do anything\s*$/i.test(I)&&!g.slice(S+1).some(R=>this.isAssistantExecutionLine(R)))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0}}}else for(let y=0;y<g.length;y++){let S=g[y];if(/^[>›]/.test(S)&&!/^[>›]\s*Ask Codex to do anything\s*$/i.test(S)&&!g.slice(y+1).some(E=>/^[•✔└+]/i.test(E.trim())))return{hintLineIdx:-1,composerIdx:-1,dirtyComposerFound:!0}}return{hintLineIdx:r.hintIdx,composerIdx:o,count:r.count,dirtyComposerFound:!1}}isQueuedQuestionCollapsed(e){let t=this.extractLiveQueuedQuestionWidget(e);return t!==null&&!t.dirtyComposerFound}isExpandedMenuMatchingQuestion(e,t){let i=n=>n.trim().replace(/\s+/g," ").toLowerCase();if(i(e.prompt.promptText)!==i(t.promptText))return!1;let s=e.prompt.options;if(s.length===t.options.length+1){let n=s[s.length-1];if(n.number!==String(s.length)||!/^Other(?:\s*\(write an answer\))?$/i.test(n.text.trim()))return!1;s=s.slice(0,-1)}return s.length===t.options.length&&s.every((n,r)=>n.number===t.options[r].number&&i(n.text)===i(t.options[r].text))}isExpandedQuestionMatchingPrompt(e,t){let i=(0,F.parseActiveTerminalMenu)(e);if(i)return this.isExpandedMenuMatchingQuestion(i,t);let n=ae(e).split(`
58
60
  `).slice(-25).join(`
59
61
  `);if(!/Press a number to choose/i.test(n))return!1;let r=n.split(`
60
- `).map(v=>v.trim()).filter(v=>v.length>0),o=-1;for(let v=r.length-1;v>=0;v--)if(/Press a number to choose/i.test(r[v])){o=v;break}if(o===-1)return!1;let a=r.findIndex((v,S)=>S>o&&/^[>›❯▸▶]?\s*1\.\s+/i.test(v));if(a===-1)return!1;let l=r.slice(o+1,a);if(l.some(v=>/›\s*Ask Codex to do anything/i.test(v)||/•\s*Working/i.test(v)))return!1;let p=t.promptText.trim().replace(/\s+/g," ");if(!/^Question \d+$/i.test(p)&&p.length>0){let v="";if(a>o+1)v=l.join(" ").trim().replace(/\s+/g," ");else{let _=[];for(let D=o-1;D>=0;D--){let N=r[D];if(/›\s*Ask Codex/i.test(N)||/•\s*Working/i.test(N)||/Queued follow-up inputs/i.test(N)||(_.unshift(N),_.join(" ").length>=p.length))break}v=_.join(" ").trim().replace(/\s+/g," ")}if(v.length===0)return!1;let S=v.toLowerCase()===p.toLowerCase(),P=/(?:\.{2,}|…)$/.test(v),b=v.replace(/(?:\.{2,}|…)$/,"").trim().toLowerCase(),R=P&&b.length>=8&&p.toLowerCase().startsWith(b);if(!S&&!R)return!1}let u=[],m=a;for(let v=a;v<r.length;v++){let S=r[v];if(/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(S)||/^•\s*Working/i.test(S))break;/^[>›❯▸▶]?\s*\d+\./.test(S)?(u.push(S),m=v):u.length>0&&u.length<=t.options.length&&(u[u.length-1]+=" "+S,m=v)}let h=r.slice(m+1),I=h.findIndex(v=>/^[>›]/.test(v));if(I!==-1){if(I!==0)return!1;let v=h[I];if(!/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(v))return!1;let S=h.slice(I+1);if(!this.validateTrailingFooterLines(S))return!1}else if(!this.validateTrailingFooterLines(h))return!1;let y=u;if(u.length===t.options.length+1){let v=String(t.options.length+1),S=u[u.length-1].trim();if(new RegExp(`^[>\u203A\u276F\u25B8\u25B6]?\\s*${v}\\.\\s+Other(?:\\s*\\(write an answer\\))?\\s*$`,"i").test(S))y=u.slice(0,t.options.length);else return!1}else if(u.length!==t.options.length)return!1;let w=y.join(`
61
- `);for(let v of t.options){let S=os(v.text.trim()),P=new RegExp(`(?:^|\\n)\\s*[>\u203A\u276F\u25B8\u25B6]?\\s*${os(v.number)}\\.\\s+${S}\\s*(?:\\r?\\n|$)`,"i"),b=w.match(P);if(!b||b.index===void 0)return!1;w=w.slice(b.index+b[0].length)}return!0}async deliverQueuedQuestionResponse(e,t,i,s){if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"stale";let n=await this.tmuxPaneObserver.captureSnapshot();if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";let o=oe(n).split(`
62
+ `).map(I=>I.trim()).filter(I=>I.length>0),o=-1;for(let I=r.length-1;I>=0;I--)if(/Press a number to choose/i.test(r[I])){o=I;break}if(o===-1)return!1;let d=r.findIndex((I,w)=>w>o&&/^[>›❯▸▶]?\s*1\.\s+/i.test(I));if(d===-1)return!1;let l=r.slice(o+1,d);if(l.some(I=>/›\s*Ask Codex to do anything/i.test(I)||/•\s*Working/i.test(I)))return!1;let u=t.promptText.trim().replace(/\s+/g," ");if(!/^Question \d+$/i.test(u)&&u.length>0){let I="";if(d>o+1)I=l.join(" ").trim().replace(/\s+/g," ");else{let _=[];for(let x=o-1;x>=0;x--){let A=r[x];if(/›\s*Ask Codex/i.test(A)||/•\s*Working/i.test(A)||/Queued follow-up inputs/i.test(A)||(_.unshift(A),_.join(" ").length>=u.length))break}I=_.join(" ").trim().replace(/\s+/g," ")}if(I.length===0)return!1;let w=I.toLowerCase()===u.toLowerCase(),E=/(?:\.{2,}|…)$/.test(I),R=I.replace(/(?:\.{2,}|…)$/,"").trim().toLowerCase(),b=E&&R.length>=8&&u.toLowerCase().startsWith(R);if(!w&&!b)return!1}let p=[],m=d;for(let I=d;I<r.length;I++){let w=r[I];if(/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(w)||/^•\s*Working/i.test(w))break;/^[>›❯▸▶]?\s*\d+\./.test(w)?(p.push(w),m=I):p.length>0&&p.length<=t.options.length&&(p[p.length-1]+=" "+w,m=I)}let f=r.slice(m+1),g=f.findIndex(I=>/^[>›]/.test(I));if(g!==-1){if(g!==0)return!1;let I=f[g];if(!/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(I))return!1;let w=f.slice(g+1);if(!this.validateTrailingFooterLines(w))return!1}else if(!this.validateTrailingFooterLines(f))return!1;let y=p;if(p.length===t.options.length+1){let I=String(t.options.length+1),w=p[p.length-1].trim();if(new RegExp(`^[>\u203A\u276F\u25B8\u25B6]?\\s*${I}\\.\\s+Other(?:\\s*\\(write an answer\\))?\\s*$`,"i").test(w))y=p.slice(0,t.options.length);else return!1}else if(p.length!==t.options.length)return!1;let S=y.join(`
63
+ `);for(let I of t.options){let w=ys(I.text.trim()),E=new RegExp(`(?:^|\\n)\\s*[>\u203A\u276F\u25B8\u25B6]?\\s*${ys(I.number)}\\.\\s+${w}\\s*(?:\\r?\\n|$)`,"i"),R=S.match(E);if(!R||R.index===void 0)return!1;S=S.slice(R.index+R[0].length)}return!0}async deliverQueuedQuestionResponse(e,t,i,s){if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"stale";let n=await this.tmuxPaneObserver.captureSnapshot();if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";let o=ae(n).split(`
62
64
  `).slice(-25).join(`
63
- `);if(!!this.tmuxPaneObserver.extractActiveApprovalBlock?.(n)||/Would you like to run\s+["`].*["`]/i.test(o)&&/Yes,\s+and\s+don't\s+ask\s+again/i.test(o)||!/Press a number to choose/i.test(o)&&/\[(?:y\/n|Y\/n|y\/N)\]/i.test(o))return c.warn("Refusing to deliver queued question input: active approval dialog or menu detected in pane",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(!o||o.trim().length<10)return c.warn("Pane snapshot is empty or incomplete; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";let l=this.extractLiveQueuedQuestionWidget(o),p=l?.count??s,f=l!==null&&!l.dirtyComposerFound,u=this.isExpandedQuestionMatchingPrompt(n,t),m=this.hasQueuedInputsFragment(o);if(!f&&!u)return(0,M.parseActiveTerminalMenu)(n)||/Press a number to choose/i.test(o)||m?(c.warn("Unmatched chooser dialog or partial queued widget visible in pane; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified"):/›\s*(?:Ask Codex to do anything|$)/m.test(o)&&!o.includes("Disconnected")?(c.info("Queued question already resolved on desktop; marking stale",{sessionId:e.sessionId,promptId:t.promptId}),await this.clearResolvedInteractivePrompt(t.callId??t.promptId,t.dedupeKey??t.promptId),"stale"):(c.warn("Queued question not found in pane but composer is unconfirmed; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified");if(f&&!u){if(/Press a number to choose/i.test(o))return c.warn("Unrelated or mismatched chooser active before S-Left expansion; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(!l||l.dirtyComposerFound)return c.warn("No active clean queued question widget boundary identified before S-Left expansion; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(c.info("Queued question dialog is collapsed; sending S-Left to expand",{sessionId:e.sessionId,promptId:t.promptId,hintLineIdx:l.hintLineIdx,composerIdx:l.composerIdx}),!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";if(!await this.promptResponder.sendKey(e.sessionId,"S-Left"))return"send_failed";let S=!1,P=Date.now();for(;Date.now()-P<350;){if(await new Promise(N=>setTimeout(N,50)),!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";let b=await this.tmuxPaneObserver.captureSnapshot();if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";let _=oe(b).split(`
65
+ `);if(!!this.tmuxPaneObserver.extractActiveApprovalBlock?.(n)||/Would you like to run\s+["`].*["`]/i.test(o)&&/Yes,\s+and\s+don't\s+ask\s+again/i.test(o)||!/Press a number to choose/i.test(o)&&/\[(?:y\/n|Y\/n|y\/N)\]/i.test(o))return c.warn("Refusing to deliver queued question input: active approval dialog or menu detected in pane",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(!o||o.trim().length<10)return c.warn("Pane snapshot is empty or incomplete; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";let l=this.extractLiveQueuedQuestionWidget(o),u=l?.count??s,h=l!==null&&!l.dirtyComposerFound,p=this.isExpandedQuestionMatchingPrompt(n,t),m=this.hasQueuedInputsFragment(o);if(!h&&!p)return(0,F.parseActiveTerminalMenu)(n)||/Press a number to choose/i.test(o)||m?(c.warn("Unmatched chooser dialog or partial queued widget visible in pane; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified"):/›\s*(?:Ask Codex to do anything|$)/m.test(o)&&!o.includes("Disconnected")?(c.info("Queued question already resolved on desktop; marking stale",{sessionId:e.sessionId,promptId:t.promptId}),await this.clearResolvedInteractivePrompt(t.callId??t.promptId,t.dedupeKey??t.promptId),"stale"):(c.warn("Queued question not found in pane but composer is unconfirmed; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified");if(h&&!p){if(/Press a number to choose/i.test(o))return c.warn("Unrelated or mismatched chooser active before S-Left expansion; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(!l||l.dirtyComposerFound)return c.warn("No active clean queued question widget boundary identified before S-Left expansion; failing closed as unverified",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(c.info("Queued question dialog is collapsed; sending S-Left to expand",{sessionId:e.sessionId,promptId:t.promptId,hintLineIdx:l.hintLineIdx,composerIdx:l.composerIdx}),!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";if(!await this.promptResponder.sendKey(e.sessionId,"S-Left"))return"send_failed";let w=!1,E=Date.now();for(;Date.now()-E<350;){if(await new Promise(A=>setTimeout(A,50)),!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";let R=await this.tmuxPaneObserver.captureSnapshot();if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";let _=ae(R).split(`
64
66
  `).slice(-25).join(`
65
- `);if(!!this.tmuxPaneObserver.extractActiveApprovalBlock?.(b)||/Would you like to run\s+["`].*["`]/i.test(_)&&/Yes,\s+and\s+don't\s+ask\s+again/i.test(_)||!/Press a number to choose/i.test(_)&&/\[(?:y\/n|Y\/n|y\/N)\]/i.test(_))return c.warn("Approval dialog appeared while expanding queued question; aborting",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(this.isExpandedQuestionMatchingPrompt(b,t)){S=!0;break}}if(!S)return c.warn("Queued question failed to expand to expected prompt after S-Left; failing closed",{sessionId:e.sessionId,promptId:t.promptId}),"unverified"}if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";if(c.info("Sending option selection for queued question",{sessionId:e.sessionId,promptId:t.promptId,input:i}),!await this.promptResponder.sendLiteral(e.sessionId,i))return"send_failed";let I=!1,y=()=>this.pendingInteractivePrompt!==t&&!!t.dedupeKey&&this.hasRecentlyResolvedApprovalDedupeKey(e.sessionId,t.dedupeKey),w=Date.now();for(;Date.now()-w<500;){if(await new Promise(N=>setTimeout(N,50)),!this.isExpectedSessionStateCurrent(e))return"stale";if(y()){I=!0;break}let v=await this.tmuxPaneObserver.captureSnapshot();if(!this.isExpectedSessionStateCurrent(e))return"stale";if(y()){I=!0;break}let P=oe(v).split(`
67
+ `);if(!!this.tmuxPaneObserver.extractActiveApprovalBlock?.(R)||/Would you like to run\s+["`].*["`]/i.test(_)&&/Yes,\s+and\s+don't\s+ask\s+again/i.test(_)||!/Press a number to choose/i.test(_)&&/\[(?:y\/n|Y\/n|y\/N)\]/i.test(_))return c.warn("Approval dialog appeared while expanding queued question; aborting",{sessionId:e.sessionId,promptId:t.promptId}),"unverified";if(this.isExpandedQuestionMatchingPrompt(R,t)){w=!0;break}}if(!w)return c.warn("Queued question failed to expand to expected prompt after S-Left; failing closed",{sessionId:e.sessionId,promptId:t.promptId}),"unverified"}if(!this.isExpectedSessionStateCurrent(e)||this.pendingInteractivePrompt!==t)return"unverified";if(c.info("Sending option selection for queued question",{sessionId:e.sessionId,promptId:t.promptId,input:i}),!await this.promptResponder.sendLiteral(e.sessionId,i))return"send_failed";let g=!1,y=()=>this.pendingInteractivePrompt!==t&&!!t.dedupeKey&&this.hasRecentlyResolvedApprovalDedupeKey(e.sessionId,t.dedupeKey),S=Date.now();for(;Date.now()-S<500;){if(await new Promise(A=>setTimeout(A,50)),!this.isExpectedSessionStateCurrent(e))return"stale";if(y()){g=!0;break}let I=await this.tmuxPaneObserver.captureSnapshot();if(!this.isExpectedSessionStateCurrent(e))return"stale";if(y()){g=!0;break}let E=ae(I).split(`
66
68
  `).slice(-25).join(`
67
- `);if(!P||P.trim().length<10||P.includes("Disconnected"))continue;let b=(0,M.parseActiveTerminalMenu)(v),R=this.isExpandedQuestionMatchingPrompt(v,t),_=!b&&!/Press a number to choose/i.test(P),D=/›\s*(?:Ask Codex to do anything|$)/m.test(P);if(_&&D){let N=this.extractLiveQueuedQuestionWidget(P);if(N&&N.count!==void 0&&p!==void 0&&N.count<p){I=!0;break}if(N===null){let ie=P.split(`
68
- `).map(G=>G.trim()).filter(G=>G.length>0),q=-1;for(let G=ie.length-1;G>=0;G--)if(/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(ie[G])){q=G;break}if(q!==-1){let G=ie.slice(q+1);if(this.validateTrailingFooterLines(G)){let _e=0;for(let ne=q-1;ne>=0;ne--)if(this.isHistoricalTurnBoundary(ie,ne)){_e=ne+1;break}let he=ie.slice(_e,q);if(!he.some((ne,Gt)=>!/^[>›]/.test(ne)||/^[>›]\s*Ask Codex to do anything\s*$/i.test(ne)?!1:!he.slice(Gt+1).some(ys=>/^[•✔└+]/i.test(ys.trim())))){let ne=he.join(`
69
- `);if(!this.hasQueuedInputsFragment(ne)){I=!0;break}}}}}}else if(!R&&(b||/Press a number to choose/i.test(P)&&D)&&[this.pendingInteractivePrompt,...this.queuedInteractivePrompts.filter(q=>q.ownerState===e).map(q=>q.prompt)].some(q=>q&&q!==t&&q.kind==="queued_question"&&q.ownerSessionId===e.sessionId&&this.isExpandedQuestionMatchingPrompt(v,q))){I=!0;break}}return I?(await this.clearResolvedInteractivePrompt(t.callId??t.promptId,t.dedupeKey??t.promptId),"sent"):(c.warn("Queued question chooser did not transition after option key dispatch",{sessionId:e.sessionId,promptId:t.promptId,input:i}),"unverified")}async emitHooksCompatibilityModeNotice(e){if(this.hooksCompatibilityNoticeSent||!this.isExpectedSessionStateCurrent(e))return;this.hooksCompatibilityNoticeSent=!0;let t="Codex hooks are not active. CodeVibe is using compatibility mode: mobile approvals still mirror the desktop prompt, but timeline events may be delayed or incomplete. Open Codex /hooks and trust/enable CodeVibe hooks for full fidelity.",i={compatibility_mode:!0,reason:"codex_hooks_inactive",action:"trust_enable_codevibe_hooks"};c.warn("Codex hooks inactive; running in compatibility mode",{sessionId:e.sessionId});try{let s=(0,g.prepareEventTimestamp)({orderingKey:e.sessionId}),n=await this.appSyncClient.publishCompanionNotice({sessionId:e.sessionId,type:g.EventType.NOTIFICATION,source:g.EventSource.DESKTOP,content:t,metadata:i,timestamp:s},async()=>{if(!this.isExpectedSessionStateCurrent(e))return!1;let r=this.encryptForEmit(t,i,g.EventType.NOTIFICATION,e.sessionId);return r?(await this.appSyncClient.createEvent({sessionId:e.sessionId,type:g.EventType.NOTIFICATION,source:g.EventSource.DESKTOP,content:r.content,metadata:r.metadata,timestamp:s,...r.isEncrypted?{isEncrypted:!0}:{}}),!0):!1});c.debug("Hooks compatibility notice publication outcome",{sessionId:e.sessionId,result:n})}catch(s){c.warn("Failed to emit hooks compatibility mode notification",{error:s})}}async handleApprovalPending(e){let t=this.sessionState;if(!t)return;if((this.queuedPermissionRequestSessionCounts.get(t.sessionId)??0)>0){c.debug("Skipping heuristic approval prompt while PermissionRequest owns the session prompt",{sessionId:t.sessionId,callId:e.callId});return}let i=this.buildApprovalDedupeKey(e);if(i&&this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,i)){c.info("Skipping heuristic approval prompt; same approval was already answered recently",{callId:e.callId,toolName:e.toolName,dedupeKey:i});return}if(i&&this.hasDurablePermissionHookFallbackByDedupeKey(t.sessionId,i)){c.debug("Skipping heuristic approval prompt already owned by a hook fallback",{sessionId:t.sessionId,callId:e.callId,dedupeKey:i});return}if(i&&this.hasActiveOrQueuedPermissionHookPrompt(t.sessionId,i)){this.mergeCallIdIntoPromptByDedupeKey(t.sessionId,i,e.callId),c.info("Skipping heuristic approval prompt; PermissionRequest hook already emitted it",{callId:e.callId,toolName:e.toolName,dedupeKey:i});return}c.info("Sending approval pending interactive prompt",e);let s=this.promptGeneration;try{let n=await this.tryParseInteractivePromptFromTmux();if(!this.isExpectedSessionStateCurrent(t)||this.promptGeneration!==s){c.warn("Dropping stale heuristic approval prompt after generation/session changed",{sessionId:t.sessionId,generationAtStart:s,currentGeneration:this.promptGeneration});return}let r=n?.parsedPrompt??null;if((this.queuedPermissionRequestSessionCounts.get(t.sessionId)??0)>0||r&&this.hasMatchingDurablePermissionHookFallback(r,t.sessionId,n?.snapshot)||r&&this.hasMatchingPermissionHookPrompt(r,t.sessionId,n?.snapshot)){c.debug("Skipping heuristic approval prompt after PermissionRequest claimed the terminal dialog",{sessionId:t.sessionId,callId:e.callId});return}let o=this.buildToolDetailsForInteractivePrompt(e,n?.snapshot),a=o.tool_name||this.mapToolNameForApproval(e.toolName),l=o.tool_input||this.buildFallbackToolInput(e),p=!!(a&&l);if(!r){c.warn("Suppressing heuristic approval prompt because exact Codex options are unavailable",{callId:e.callId,toolName:e.toolName,hint:e.hint}),this.raiseSuppressedBadge(t.sessionId,i);return}if(!this.parsedPromptMatchesApprovalContext(r,e,n?.snapshot)){c.warn("Suppressing heuristic approval prompt because parsed tmux prompt does not match the active tool",{callId:e.callId,toolName:e.toolName,hint:e.hint,parsedPromptText:r.promptText}),this.raiseSuppressedBadge(t.sessionId,i);return}let f=this.mapToolNameForApproval(e.toolName)==="Bash"?this.firstString(e.toolInput?.command,e.toolInput?.cmd):void 0,{presentation:u,failureReason:m}=this.buildCodexPromptPresentationDetailed(r,f,n?.snapshot);if(!u){c.warn("Suppressing heuristic approval prompt because Codex presentation options are unavailable",{callId:e.callId,toolName:e.toolName,hint:e.hint,reason:m??"unsupported_options"}),this.raiseSuppressedBadge(t.sessionId,i);return}let h=u.options,I=this.buildApprovalPromptContent(u.content,{toolName:a,toolInput:l,hint:e.hint,filePath:e.filePath}),y={promptId:e.callId,callId:e.callId,kind:u.kind,options:h,submitMap:u.submitMap,promptText:u.promptText,createdAt:Date.now(),source:r?"tmux":"heuristic",dedupeKey:i,ownerSessionId:t.sessionId,observerMatchKey:this.buildObserverPromptMatchKey(r,n?.snapshot),requiresFollowUpText:u.requiresFollowUpText},w={isApprovalHint:!0,toolName:e.toolName,toolInput:e.toolInput,hint:e.hint,callId:e.callId,filePath:e.filePath,diff:e.diff,rawInput:e.rawInput,tool_name:a,tool_input:l,has_details:p,options:h,instructions:u.instructions,prompt_source:r?"tmux":"heuristic",dedupe_key:i};if(c.debug("Interactive prompt (pre-encryption)",{sessionId:t.sessionId,callId:e.callId,contentPreview:I.substring(0,200),toolDetails:o,metadata:w}),!this.isExpectedSessionStateCurrent(t)||this.promptGeneration!==s){c.warn("Dropping stale heuristic approval prompt before enqueue after generation changed",{sessionId:t.sessionId,generationAtStart:s,currentGeneration:this.promptGeneration});return}await this.enqueueOrEmitInteractivePrompt({prompt:y,content:I,metadata:w,ownerState:t})}catch(n){c.error("Failed to send approval interactive prompt:",n)}}async handleTerminalMenu(e,t,i){if(!this.isExpectedSessionStateCurrent(t))return;let n=(0,M.parseActiveTerminalMenu)(e.snapshot)?.identity??e.identity;if(this.pendingInteractivePrompt?.terminalMenuIdentity===n&&this.pendingInteractivePrompt.ownerSessionId===t.sessionId)return;let r=(0,ye.v4)(),o={promptId:r,kind:"numbered",options:e.prompt.options,submitMap:e.prompt.submitMap,promptText:e.prompt.promptText,createdAt:Date.now(),source:"tmux",dedupeKey:`menu:${r}`,ownerSessionId:t.sessionId,observerMatchKey:this.buildObserverPromptMatchKey(e.prompt,e.snapshot),observerPromptHash:i??this.tmuxPaneObserver.hashPromptSnapshot(e.snapshot),terminalMenuIdentity:n};await this.enqueueOrEmitInteractivePrompt({prompt:o,ownerState:t,content:e.prompt.promptText,metadata:{options:e.prompt.options,instructions:"Reply with the number of the option you want",prompt_source:"tmux_live",dialog_kind:"terminal_menu",has_details:!1}}),c.info("Published live terminal menu",{sessionId:t.sessionId,promptId:o.promptId,optionsCount:o.options.length})}async handleTmuxPromptCandidate(e,t,i){let s=this.sessionState;if(!s){this.tmuxPaneObserver.resetLastPromptHash();return}let n=this.promptGeneration,r=this.tmuxPaneObserver.extractActiveApprovalBlock(e)?null:await(0,M.parseActiveTerminalMenuAsync)(e,this.tuiGemmaPort??void 0);if(this.promptGeneration!==n||!this.isExpectedSessionStateCurrent(s))return;if(r){let N=this.pendingInteractivePrompt;if(N?.kind==="queued_question"&&N.ownerSessionId===s.sessionId&&this.isExpandedMenuMatchingQuestion(r,N))return;await this.handleTerminalMenu(r,s,i);return}if(await this.promoteWaitingPermissionRequest(e,s)||!t&&this.deferTmuxPromptCandidateForPermissionHook(s.sessionId,e,i))return;let o=t?.occurrenceKey;if(o&&this.hasRecentlyResolvedApprovalDedupeKey(s.sessionId,o))return;let a=await(0,M.parseInteractivePromptAsync)(e,this.tuiGemmaPort??void 0);if(this.promptGeneration!==n||!this.isExpectedSessionStateCurrent(s))return;if(!a){this.raiseSuppressedBadge(s.sessionId,o??null);return}if(this.hasMatchingPermissionHookPrompt(a,s.sessionId,e)){c.debug("Skipping tmux prompt candidate already owned by PermissionRequest",{sessionId:s.sessionId,promptText:a.promptText});return}let l=this.getMostRecentPendingToolCall();if(!l){if(await new Promise(N=>setTimeout(N,500)),this.promptGeneration!==n||!this.isExpectedSessionStateCurrent(s)){c.warn("Dropping tmux prompt candidate after session or prompt generation changed",{sessionId:s.sessionId,currentSessionId:this.sessionState?.sessionId,generationAtStart:n,currentGeneration:this.promptGeneration});return}if(!t&&this.deferTmuxPromptCandidateForPermissionHook(s.sessionId,e,i))return;l=this.getMostRecentPendingToolCall()}let p=t?.context??(l?this.buildApprovalPromptContextFromPendingCall(l):null);if(p&&!this.parsedPromptMatchesApprovalContext(a,p,e)){c.warn("Skipping tmux-detected prompt because parsed prompt does not match pending tool call",{callId:l?.callId,toolName:l?.name,parsedPromptText:a.promptText}),this.raiseSuppressedBadge(s.sessionId,o??null);return}let f=p?null:this.buildApprovalPromptContextFromParsedPrompt(a),u=p||f;if(!u){c.warn("Skipping tmux-detected prompt because no tool context could be derived from the parsed prompt",{parsedPromptText:a.promptText}),this.raiseSuppressedBadge(s.sessionId,o??null);return}let m=this.mapToolNameForApproval(u.toolName)==="Bash"?this.firstString(u.toolInput?.command,u.toolInput?.cmd):void 0,{presentation:h,failureReason:I}=this.buildCodexPromptPresentationDetailed(a,m,e);if(!h){c.warn("Skipping tmux-detected prompt because Codex presentation options are unavailable",{parsedPromptText:a.promptText,reason:I??"unsupported_options"}),this.raiseSuppressedBadge(s.sessionId,o??null);return}let y=u?this.buildApprovalDedupeKey(u):void 0;if(y&&this.hasRecentlyResolvedApprovalDedupeKey(s.sessionId,y)){c.info("Skipping tmux-detected prompt; same approval was already answered recently",{promptText:a.promptText,dedupeKey:y});return}if(y&&this.hasActiveOrQueuedPermissionHookPrompt(s.sessionId,y)){l?.callId&&this.mergeCallIdIntoPromptByDedupeKey(s.sessionId,y,l.callId),c.info("Skipping tmux-detected prompt; PermissionRequest hook already emitted it",{promptText:a.promptText,dedupeKey:y});return}let w=u?this.buildToolDetailsForInteractivePrompt(u,e):{},v=w.tool_name||this.mapToolNameForApproval(l?.name),S=w.tool_input||(u?this.buildFallbackToolInput(u):void 0),P=!!(v&&S),R={promptId:l?.callId||(0,ye.v4)(),callId:l?.callId,kind:h.kind,options:h.options,submitMap:h.submitMap,promptText:h.promptText,createdAt:Date.now(),source:"tmux",dedupeKey:y,ownerSessionId:s.sessionId,observerMatchKey:this.buildObserverPromptMatchKey(a,e),observerPromptHash:i,requiresFollowUpText:h.requiresFollowUpText},_={options:h.options,instructions:h.instructions,prompt_source:"tmux_live",toolName:u?.toolName,toolInput:u?.toolInput,hint:u?.hint,filePath:u?.filePath,diff:u?.diff,rawInput:u?.rawInput,tool_name:v,tool_input:S,has_details:P,dedupe_key:y},D=this.buildApprovalPromptContent(h.content,{toolName:v,toolInput:S,hint:u?.hint,filePath:u?.filePath});if(this.promptGeneration!==n||!this.isExpectedSessionStateCurrent(s)){c.warn("Dropping tmux prompt candidate before emission: generation changed",{sessionId:s.sessionId,generationAtStart:n,currentGeneration:this.promptGeneration});return}try{await this.enqueueOrEmitInteractivePrompt({prompt:R,content:D,metadata:_,ownerState:s})&&c.info("Sent tmux-detected interactive prompt",{sessionId:s.sessionId,promptText:a.promptText,kind:a.kind})}catch(N){c.error("Failed to send tmux-detected interactive prompt",{error:N})}}async enqueueOrEmitInteractivePrompt(e){if(!this.isExpectedSessionStateCurrent(e.ownerState))return c.warn("Dropping interactive prompt from stale session generation",{sessionId:e.ownerState.sessionId,currentSessionId:this.sessionState?.sessionId,source:e.prompt.source}),!1;if(e.prompt.ownerSessionId??=e.ownerState.sessionId,e.prompt.dedupeKey&&this.hasRecentlyResolvedApprovalDedupeKey(e.ownerState.sessionId,e.prompt.dedupeKey))return c.debug("Skipping interactive prompt emission; same approval was already answered recently",{source:e.prompt.source,callId:e.prompt.callId,dedupeKey:e.prompt.dedupeKey}),!1;let t=this.pendingInteractivePrompt;if(t&&t.ownerSessionId!==e.ownerState.sessionId&&(c.warn("Discarding active prompt from a stale session generation",{activeSessionId:t.ownerSessionId,candidateSessionId:e.ownerState.sessionId}),this.pendingInteractivePrompt=null,t=null),t&&t.kind==="queued_question"&&e.prompt.kind!=="queued_question"){c.info("Preempting active queued question for higher-priority approval prompt",{queuedQuestionId:t.promptId,approvalCallId:e.prompt.callId});let i=Date.now();e.prompt.preemptedQueuedQuestionId=t.promptId,e.prompt.preemptedQueuedQuestionAt=i,e.prompt.createdAt=e.prompt.createdAt||i;let s={prompt:t,content:t.promptText,metadata:{isApprovalHint:!1,isQueuedQuestion:!0,options:t.options,submitMap:t.submitMap,instructions:"Reply with the number of your choice.",dedupe_key:t.dedupeKey,tool_name:"request_user_input_async",tool_use_id:t.callId,prompt_source:"queued_question",questions:t.allQuestions?[{question:t.promptText,multiSelect:!1,options:t.options,instructions:"Reply with the number of your choice."}]:void 0},ownerState:e.ownerState};this.queuedInteractivePrompts.unshift(s),this.pendingInteractivePrompt=e.prompt,t=e.prompt,this.emitQueuedQuestionDesktopNotice(e.ownerState.sessionId,"\u26A0\uFE0F Queued question paused \u2014 please answer the approval request first.",e.ownerState).catch(n=>{c.debug("Failed to emit queued question desktop notice",{err:n})})}if(!t||t===e.prompt){this.pendingInteractivePrompt=e.prompt;try{return await this.emitInteractivePromptEvent(e),!0}catch(i){throw this.pendingInteractivePrompt?.promptId===e.prompt.promptId&&(this.pendingInteractivePrompt=null),i}}if(this.isSameInteractivePrompt(t,e.prompt)){if(e.prompt.source==="permission_hook"&&t.source!=="permission_hook"){t.source="permission_hook",t.completionKey=e.prompt.completionKey??t.dedupeKey,t.dedupeKey=e.prompt.dedupeKey;let i=this.e1PromptRaises.get(t.promptId);i&&(i.resolutionDedupeKey=t.dedupeKey,i.resolutionCompletionKey=t.completionKey)}return!t.callId&&e.prompt.callId&&(t.callId=e.prompt.callId,c.debug("Merged callId into existing interactive prompt",{source:t.source,callId:e.prompt.callId,promptText:t.promptText})),c.debug("Skipping duplicate interactive prompt emission",{existingSource:t.source,candidateSource:e.prompt.source,existingCallId:t.callId,candidateCallId:e.prompt.callId,promptText:e.prompt.promptText}),!1}return this.queuedInteractivePrompts.some(i=>this.isSameInteractivePrompt(i.prompt,e.prompt))?(c.debug("Skipping duplicate queued interactive prompt",{candidateSource:e.prompt.source,candidateCallId:e.prompt.callId,promptText:e.prompt.promptText}),!1):((e.prompt.kind==="queued_question"||this.isQueuedQuestionPromptId(e.prompt.callId)||this.isQueuedQuestionPromptId(e.prompt.dedupeKey)||this.isQueuedQuestionPromptId(e.prompt.promptId))&&(this.recordHistoricalQueuedQuestionId(e.prompt.promptId),e.prompt.callId&&this.recordHistoricalQueuedQuestionId(e.prompt.callId),e.prompt.dedupeKey&&this.recordHistoricalQueuedQuestionId(e.prompt.dedupeKey)),this.queuedInteractivePrompts.push(e),c.info("Queued interactive prompt behind active prompt",{activeCallId:t.callId,queuedCallId:e.prompt.callId,queueLength:this.queuedInteractivePrompts.length}),!1)}async emitInteractivePromptEvent(e){if(!this.isExpectedSessionStateCurrent(e.ownerState))return;let t=e.ownerState.sessionId,i=this.e1PromptRaises.get(e.prompt.promptId),s=i?i.record:this.newE1Raise(t,!0,void 0,{...e.prompt.dedupeKey!==void 0?{dedupeKey:e.prompt.dedupeKey}:{},...e.prompt.completionKey!==void 0?{completionKey:e.prompt.completionKey}:{},...e.prompt.callId!==void 0?{callId:e.prompt.callId}:{}});e.prompt.promptId=s.promptId;let n=this.e1PromptRaises.get(s.promptId);n&&(n.resolutionDedupeKey??=e.prompt.dedupeKey,n.resolutionCompletionKey??=e.prompt.completionKey,n.resolutionCallId??=e.prompt.callId),(e.prompt.kind==="queued_question"||this.isQueuedQuestionPromptId(e.prompt.callId)||this.isQueuedQuestionPromptId(e.prompt.dedupeKey)||this.isQueuedQuestionPromptId(s.promptId))&&(this.recordHistoricalQueuedQuestionId(s.promptId),e.prompt.callId&&this.recordHistoricalQueuedQuestionId(e.prompt.callId),e.prompt.dedupeKey&&this.recordHistoricalQueuedQuestionId(e.prompt.dedupeKey)),e.prompt.dedupeKey&&this.e1ContentKeyIndex.set(`${t}::${e.prompt.dedupeKey}`,s.promptId),this.stashE1RaiseContent(s.promptId,e.content,e.metadata??{}),await this.publishE1Prompt(t,s,g.EventType.INTERACTIVE_PROMPT,e.content,e.metadata??{})}rebindWaitingPermissionRequests(e){for(let t of this.waitingPermissionRequests.values())t.ownerState.codexSessionId&&t.ownerState.codexSessionId===e.codexSessionId&&(t.ownerState=e)}async promoteWaitingPermissionRequest(e,t){if(!this.isExpectedSessionStateCurrent(t))return!1;let i=this.promptGeneration,s=await(0,M.parseInteractivePromptAsync)(e,this.tuiGemmaPort??void 0);if(this.promptGeneration!==i||!this.isExpectedSessionStateCurrent(t)||!s||this.hasMatchingPermissionHookPrompt(s,t.sessionId,e))return!1;for(let[n,r]of this.waitingPermissionRequests)if(this.isExpectedSessionStateCurrent(r.ownerState)&&this.parsedPromptMatchesApprovalContext(s,r.context,e)){this.waitingPermissionRequests.delete(n);try{await this.handlePermissionRequestHookWhileTracked(r.payload,t,r.context,n,r.dedupeKey,{parsedPrompt:s,snapshot:e})}catch(o){throw this.isExpectedSessionStateCurrent(t)&&!this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,n)&&this.waitingPermissionRequests.set(n,r),this.tmuxPaneObserver.resetLastPromptHash(),o}return!0}return!1}async emitNextQueuedInteractivePrompt(){if(this.pendingInteractivePrompt)return;if(this.queuedInteractivePrompts.length===0){let i=this.sessionState;if(i&&this.waitingPermissionRequests.size>0){let s=await this.tmuxPaneObserver.captureSnapshot();!(s&&await this.promoteWaitingPermissionRequest(s,i))&&this.isExpectedSessionStateCurrent(i)&&!this.pendingInteractivePrompt&&this.waitingPermissionRequests.size>0&&this.tmuxPaneObserver.resetLastPromptHash()}return}let e=this.queuedInteractivePrompts[0];if(!e)return;if(!this.isExpectedSessionStateCurrent(e.ownerState)){this.queuedInteractivePrompts.shift(),c.warn("Discarding queued prompt from stale session generation",{sessionId:e.ownerState.sessionId,currentSessionId:this.sessionState?.sessionId}),await this.emitNextQueuedInteractivePrompt();return}if(e.prompt.kind==="queued_question")try{let i=await this.tmuxPaneObserver.captureSnapshot();if(!this.queuedInteractivePrompts.includes(e))return;if(!this.isExpectedSessionStateCurrent(e.ownerState)){c.warn("Session changed during snapshot capture; withholding queued prompt",{promptId:e.prompt.promptId,sessionId:e.ownerState.sessionId,currentSessionId:this.sessionState?.sessionId});return}if(this.pendingInteractivePrompt)return;let n=oe(i).split(`
69
+ `);if(!E||E.trim().length<10||E.includes("Disconnected"))continue;let R=(0,F.parseActiveTerminalMenu)(I),b=this.isExpandedQuestionMatchingPrompt(I,t),_=!R&&!/Press a number to choose/i.test(E),x=/›\s*(?:Ask Codex to do anything|$)/m.test(E);if(_&&x){let A=this.extractLiveQueuedQuestionWidget(E);if(A&&A.count!==void 0&&u!==void 0&&A.count<u){g=!0;break}if(A===null){let se=E.split(`
70
+ `).map(z=>z.trim()).filter(z=>z.length>0),q=-1;for(let z=se.length-1;z>=0;z--)if(/^[>›]\s*(?:Ask Codex to do anything\s*)?$/i.test(se[z])){q=z;break}if(q!==-1){let z=se.slice(q+1);if(this.validateTrailingFooterLines(z)){let Oe=0;for(let re=q-1;re>=0;re--)if(this.isHistoricalTurnBoundary(se,re)){Oe=re+1;break}let ve=se.slice(Oe,q);if(!ve.some((re,ei)=>!/^[>›]/.test(re)||/^[>›]\s*Ask Codex to do anything\s*$/i.test(re)?!1:!ve.slice(ei+1).some(Ns=>/^[•✔└+]/i.test(Ns.trim())))){let re=ve.join(`
71
+ `);if(!this.hasQueuedInputsFragment(re)){g=!0;break}}}}}}else if(!b&&(R||/Press a number to choose/i.test(E)&&x)&&[this.pendingInteractivePrompt,...this.queuedInteractivePrompts.filter(q=>q.ownerState===e).map(q=>q.prompt)].some(q=>q&&q!==t&&q.kind==="queued_question"&&q.ownerSessionId===e.sessionId&&this.isExpandedQuestionMatchingPrompt(I,q))){g=!0;break}}return g?(await this.clearResolvedInteractivePrompt(t.callId??t.promptId,t.dedupeKey??t.promptId),"sent"):(c.warn("Queued question chooser did not transition after option key dispatch",{sessionId:e.sessionId,promptId:t.promptId,input:i}),"unverified")}async emitHooksCompatibilityModeNotice(e){if(this.hooksCompatibilityNoticeSent||!this.isExpectedSessionStateCurrent(e))return;this.hooksCompatibilityNoticeSent=!0;let t="Codex hooks are not active. CodeVibe is using compatibility mode: mobile approvals still mirror the desktop prompt, but timeline events may be delayed or incomplete. Open Codex /hooks and trust/enable CodeVibe hooks for full fidelity.",i={compatibility_mode:!0,reason:"codex_hooks_inactive",action:"trust_enable_codevibe_hooks"};c.warn("Codex hooks inactive; running in compatibility mode",{sessionId:e.sessionId});try{let s=(0,v.prepareEventTimestamp)({orderingKey:e.sessionId}),n=await this.appSyncClient.publishCompanionNotice({sessionId:e.sessionId,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:t,metadata:i,timestamp:s},async()=>{if(!this.isExpectedSessionStateCurrent(e))return!1;let r=this.encryptForEmit(t,i,v.EventType.NOTIFICATION,e.sessionId);return r?(await this.appSyncClient.createEvent({sessionId:e.sessionId,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:r.content,metadata:r.metadata,timestamp:s,...r.isEncrypted?{isEncrypted:!0}:{}}),!0):!1});c.debug("Hooks compatibility notice publication outcome",{sessionId:e.sessionId,result:n})}catch(s){c.warn("Failed to emit hooks compatibility mode notification",{error:s})}}async handleApprovalPending(e){let t=this.sessionState;if(!t)return;if((this.queuedPermissionRequestSessionCounts.get(t.sessionId)??0)>0){c.debug("Skipping heuristic approval prompt while PermissionRequest owns the session prompt",{sessionId:t.sessionId,callId:e.callId});return}let i=this.buildApprovalDedupeKey(e);if(i&&this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,i)){c.info("Skipping heuristic approval prompt; same approval was already answered recently",{callId:e.callId,toolName:e.toolName,dedupeKey:i});return}if(i&&this.hasDurablePermissionHookFallbackByDedupeKey(t.sessionId,i)){c.debug("Skipping heuristic approval prompt already owned by a hook fallback",{sessionId:t.sessionId,callId:e.callId,dedupeKey:i});return}if(i&&this.hasActiveOrQueuedPermissionHookPrompt(t.sessionId,i)){this.mergeCallIdIntoPromptByDedupeKey(t.sessionId,i,e.callId),c.info("Skipping heuristic approval prompt; PermissionRequest hook already emitted it",{callId:e.callId,toolName:e.toolName,dedupeKey:i});return}c.info("Sending approval pending interactive prompt",e);let s=this.promptGeneration;try{let n=await this.tryParseInteractivePromptFromTmux();if(!this.isExpectedSessionStateCurrent(t)||this.promptGeneration!==s){c.warn("Dropping stale heuristic approval prompt after generation/session changed",{sessionId:t.sessionId,generationAtStart:s,currentGeneration:this.promptGeneration});return}let r=n?.parsedPrompt??null;if((this.queuedPermissionRequestSessionCounts.get(t.sessionId)??0)>0||r&&this.hasMatchingDurablePermissionHookFallback(r,t.sessionId,n?.snapshot)||r&&this.hasMatchingPermissionHookPrompt(r,t.sessionId,n?.snapshot)){c.debug("Skipping heuristic approval prompt after PermissionRequest claimed the terminal dialog",{sessionId:t.sessionId,callId:e.callId});return}let o=this.buildToolDetailsForInteractivePrompt(e,n?.snapshot),d=o.tool_name||this.mapToolNameForApproval(e.toolName),l=o.tool_input||this.buildFallbackToolInput(e),u=!!(d&&l);if(!r){c.warn("Suppressing heuristic approval prompt because exact Codex options are unavailable",{callId:e.callId,toolName:e.toolName,hint:e.hint}),this.raiseSuppressedBadge(t.sessionId,i);return}if(!this.parsedPromptMatchesApprovalContext(r,e,n?.snapshot)){c.warn("Suppressing heuristic approval prompt because parsed tmux prompt does not match the active tool",{callId:e.callId,toolName:e.toolName,hint:e.hint,parsedPromptText:r.promptText}),this.raiseSuppressedBadge(t.sessionId,i);return}let h=this.mapToolNameForApproval(e.toolName)==="Bash"?this.firstString(e.toolInput?.command,e.toolInput?.cmd):void 0,{presentation:p,failureReason:m}=this.buildCodexPromptPresentationDetailed(r,h,n?.snapshot);if(!p){c.warn("Suppressing heuristic approval prompt because Codex presentation options are unavailable",{callId:e.callId,toolName:e.toolName,hint:e.hint,reason:m??"unsupported_options"}),this.raiseSuppressedBadge(t.sessionId,i);return}let f=p.options,g=this.buildApprovalPromptContent(p.content,{toolName:d,toolInput:l,hint:e.hint,filePath:e.filePath}),y={promptId:e.callId,callId:e.callId,kind:p.kind,options:f,submitMap:p.submitMap,promptText:p.promptText,createdAt:Date.now(),source:r?"tmux":"heuristic",dedupeKey:i,ownerSessionId:t.sessionId,observerMatchKey:this.buildObserverPromptMatchKey(r,n?.snapshot),requiresFollowUpText:p.requiresFollowUpText},S={isApprovalHint:!0,toolName:e.toolName,toolInput:e.toolInput,hint:e.hint,callId:e.callId,filePath:e.filePath,diff:e.diff,rawInput:e.rawInput,tool_name:d,tool_input:l,has_details:u,options:f,instructions:p.instructions,prompt_source:r?"tmux":"heuristic",dedupe_key:i};if(c.debug("Interactive prompt (pre-encryption)",{sessionId:t.sessionId,callId:e.callId,contentPreview:g.substring(0,200),toolDetails:o,metadata:S}),!this.isExpectedSessionStateCurrent(t)||this.promptGeneration!==s){c.warn("Dropping stale heuristic approval prompt before enqueue after generation changed",{sessionId:t.sessionId,generationAtStart:s,currentGeneration:this.promptGeneration});return}await this.enqueueOrEmitInteractivePrompt({prompt:y,content:g,metadata:S,ownerState:t})}catch(n){c.error("Failed to send approval interactive prompt:",n)}}async handleTerminalMenu(e,t,i){if(!this.isExpectedSessionStateCurrent(t))return;let n=(0,F.parseActiveTerminalMenu)(e.snapshot)?.identity??e.identity;if(this.pendingInteractivePrompt?.terminalMenuIdentity===n&&this.pendingInteractivePrompt.ownerSessionId===t.sessionId)return;let r=(0,Se.v4)(),o={promptId:r,kind:"numbered",options:e.prompt.options,submitMap:e.prompt.submitMap,promptText:e.prompt.promptText,createdAt:Date.now(),source:"tmux",dedupeKey:`menu:${r}`,ownerSessionId:t.sessionId,observerMatchKey:this.buildObserverPromptMatchKey(e.prompt,e.snapshot),observerPromptHash:i??this.tmuxPaneObserver.hashPromptSnapshot(e.snapshot),terminalMenuIdentity:n};await this.enqueueOrEmitInteractivePrompt({prompt:o,ownerState:t,content:e.prompt.promptText,metadata:{options:e.prompt.options,instructions:"Reply with the number of the option you want",prompt_source:"tmux_live",dialog_kind:"terminal_menu",has_details:!1}}),c.info("Published live terminal menu",{sessionId:t.sessionId,promptId:o.promptId,optionsCount:o.options.length})}async handleTmuxPromptCandidate(e,t,i){let s=this.sessionState;if(!s){this.tmuxPaneObserver.resetLastPromptHash();return}let n=this.promptGeneration,r=this.tmuxPaneObserver.extractActiveApprovalBlock(e)?null:await(0,F.parseActiveTerminalMenuAsync)(e,this.tuiGemmaPort??void 0);if(this.promptGeneration!==n||!this.isExpectedSessionStateCurrent(s))return;if(r){let A=this.pendingInteractivePrompt;if(A?.kind==="queued_question"&&A.ownerSessionId===s.sessionId&&this.isExpandedMenuMatchingQuestion(r,A))return;await this.handleTerminalMenu(r,s,i);return}if(await this.promoteWaitingPermissionRequest(e,s)||!t&&this.deferTmuxPromptCandidateForPermissionHook(s.sessionId,e,i))return;let o=t?.occurrenceKey;if(o&&this.hasRecentlyResolvedApprovalDedupeKey(s.sessionId,o))return;let d=await(0,F.parseInteractivePromptAsync)(e,this.tuiGemmaPort??void 0);if(this.promptGeneration!==n||!this.isExpectedSessionStateCurrent(s))return;if(!d){this.raiseSuppressedBadge(s.sessionId,o??null);return}if(this.hasMatchingPermissionHookPrompt(d,s.sessionId,e)){c.debug("Skipping tmux prompt candidate already owned by PermissionRequest",{sessionId:s.sessionId,promptText:d.promptText});return}let l=this.getMostRecentPendingToolCall();if(!l){if(await new Promise(A=>setTimeout(A,500)),this.promptGeneration!==n||!this.isExpectedSessionStateCurrent(s)){c.warn("Dropping tmux prompt candidate after session or prompt generation changed",{sessionId:s.sessionId,currentSessionId:this.sessionState?.sessionId,generationAtStart:n,currentGeneration:this.promptGeneration});return}if(!t&&this.deferTmuxPromptCandidateForPermissionHook(s.sessionId,e,i))return;l=this.getMostRecentPendingToolCall()}let u=t?.context??(l?this.buildApprovalPromptContextFromPendingCall(l):null);if(u&&!this.parsedPromptMatchesApprovalContext(d,u,e)){c.warn("Skipping tmux-detected prompt because parsed prompt does not match pending tool call",{callId:l?.callId,toolName:l?.name,parsedPromptText:d.promptText}),this.raiseSuppressedBadge(s.sessionId,o??null);return}let h=u?null:this.buildApprovalPromptContextFromParsedPrompt(d),p=u||h;if(!p){c.warn("Skipping tmux-detected prompt because no tool context could be derived from the parsed prompt",{parsedPromptText:d.promptText}),this.raiseSuppressedBadge(s.sessionId,o??null);return}let m=this.mapToolNameForApproval(p.toolName)==="Bash"?this.firstString(p.toolInput?.command,p.toolInput?.cmd):void 0,{presentation:f,failureReason:g}=this.buildCodexPromptPresentationDetailed(d,m,e);if(!f){c.warn("Skipping tmux-detected prompt because Codex presentation options are unavailable",{parsedPromptText:d.promptText,reason:g??"unsupported_options"}),this.raiseSuppressedBadge(s.sessionId,o??null);return}let y=p?this.buildApprovalDedupeKey(p):void 0;if(y&&this.hasRecentlyResolvedApprovalDedupeKey(s.sessionId,y)){c.info("Skipping tmux-detected prompt; same approval was already answered recently",{promptText:d.promptText,dedupeKey:y});return}if(y&&this.hasActiveOrQueuedPermissionHookPrompt(s.sessionId,y)){l?.callId&&this.mergeCallIdIntoPromptByDedupeKey(s.sessionId,y,l.callId),c.info("Skipping tmux-detected prompt; PermissionRequest hook already emitted it",{promptText:d.promptText,dedupeKey:y});return}let S=p?this.buildToolDetailsForInteractivePrompt(p,e):{},I=S.tool_name||this.mapToolNameForApproval(l?.name),w=S.tool_input||(p?this.buildFallbackToolInput(p):void 0),E=!!(I&&w),b={promptId:l?.callId||(0,Se.v4)(),callId:l?.callId,kind:f.kind,options:f.options,submitMap:f.submitMap,promptText:f.promptText,createdAt:Date.now(),source:"tmux",dedupeKey:y,ownerSessionId:s.sessionId,observerMatchKey:this.buildObserverPromptMatchKey(d,e),observerPromptHash:i,requiresFollowUpText:f.requiresFollowUpText},_={options:f.options,instructions:f.instructions,prompt_source:"tmux_live",toolName:p?.toolName,toolInput:p?.toolInput,hint:p?.hint,filePath:p?.filePath,diff:p?.diff,rawInput:p?.rawInput,tool_name:I,tool_input:w,has_details:E,dedupe_key:y},x=this.buildApprovalPromptContent(f.content,{toolName:I,toolInput:w,hint:p?.hint,filePath:p?.filePath});if(this.promptGeneration!==n||!this.isExpectedSessionStateCurrent(s)){c.warn("Dropping tmux prompt candidate before emission: generation changed",{sessionId:s.sessionId,generationAtStart:n,currentGeneration:this.promptGeneration});return}try{await this.enqueueOrEmitInteractivePrompt({prompt:b,content:x,metadata:_,ownerState:s})&&c.info("Sent tmux-detected interactive prompt",{sessionId:s.sessionId,promptText:d.promptText,kind:d.kind})}catch(A){c.error("Failed to send tmux-detected interactive prompt",{error:A})}}async enqueueOrEmitInteractivePrompt(e){if(!this.isExpectedSessionStateCurrent(e.ownerState))return c.warn("Dropping interactive prompt from stale session generation",{sessionId:e.ownerState.sessionId,currentSessionId:this.sessionState?.sessionId,source:e.prompt.source}),!1;if(e.prompt.ownerSessionId??=e.ownerState.sessionId,e.prompt.dedupeKey&&this.hasRecentlyResolvedApprovalDedupeKey(e.ownerState.sessionId,e.prompt.dedupeKey))return c.debug("Skipping interactive prompt emission; same approval was already answered recently",{source:e.prompt.source,callId:e.prompt.callId,dedupeKey:e.prompt.dedupeKey}),!1;let t=this.pendingInteractivePrompt;if(t&&t.ownerSessionId!==e.ownerState.sessionId&&(c.warn("Discarding active prompt from a stale session generation",{activeSessionId:t.ownerSessionId,candidateSessionId:e.ownerState.sessionId}),this.pendingInteractivePrompt=null,t=null),t&&t.kind==="queued_question"&&e.prompt.kind!=="queued_question"){c.info("Preempting active queued question for higher-priority approval prompt",{queuedQuestionId:t.promptId,approvalCallId:e.prompt.callId});let i=Date.now();e.prompt.preemptedQueuedQuestionId=t.promptId,e.prompt.preemptedQueuedQuestionAt=i,e.prompt.createdAt=e.prompt.createdAt||i;let s={prompt:t,content:t.promptText,metadata:{isApprovalHint:!1,isQueuedQuestion:!0,options:t.options,submitMap:t.submitMap,instructions:"Reply with the number of your choice.",dedupe_key:t.dedupeKey,tool_name:"request_user_input_async",tool_use_id:t.callId,prompt_source:"queued_question",questions:t.allQuestions?[{question:t.promptText,multiSelect:!1,options:t.options,instructions:"Reply with the number of your choice."}]:void 0},ownerState:e.ownerState};this.queuedInteractivePrompts.unshift(s),this.pendingInteractivePrompt=e.prompt,t=e.prompt,this.emitQueuedQuestionDesktopNotice(e.ownerState.sessionId,"\u26A0\uFE0F Queued question paused \u2014 please answer the approval request first.",e.ownerState).catch(n=>{c.debug("Failed to emit queued question desktop notice",{err:n})})}if(!t||t===e.prompt){this.pendingInteractivePrompt=e.prompt;try{return await this.emitInteractivePromptEvent(e),!0}catch(i){throw this.pendingInteractivePrompt?.promptId===e.prompt.promptId&&(this.pendingInteractivePrompt=null),i}}if(this.isSameInteractivePrompt(t,e.prompt)){if(e.prompt.source==="permission_hook"&&t.source!=="permission_hook"){t.source="permission_hook",t.completionKey=e.prompt.completionKey??t.dedupeKey,t.dedupeKey=e.prompt.dedupeKey;let i=this.e1PromptRaises.get(t.promptId);i&&(i.resolutionDedupeKey=t.dedupeKey,i.resolutionCompletionKey=t.completionKey)}return!t.callId&&e.prompt.callId&&(t.callId=e.prompt.callId,c.debug("Merged callId into existing interactive prompt",{source:t.source,callId:e.prompt.callId,promptText:t.promptText})),c.debug("Skipping duplicate interactive prompt emission",{existingSource:t.source,candidateSource:e.prompt.source,existingCallId:t.callId,candidateCallId:e.prompt.callId,promptText:e.prompt.promptText}),!1}return this.queuedInteractivePrompts.some(i=>this.isSameInteractivePrompt(i.prompt,e.prompt))?(c.debug("Skipping duplicate queued interactive prompt",{candidateSource:e.prompt.source,candidateCallId:e.prompt.callId,promptText:e.prompt.promptText}),!1):((e.prompt.kind==="queued_question"||this.isQueuedQuestionPromptId(e.prompt.callId)||this.isQueuedQuestionPromptId(e.prompt.dedupeKey)||this.isQueuedQuestionPromptId(e.prompt.promptId))&&(this.recordHistoricalQueuedQuestionId(e.prompt.promptId),e.prompt.callId&&this.recordHistoricalQueuedQuestionId(e.prompt.callId),e.prompt.dedupeKey&&this.recordHistoricalQueuedQuestionId(e.prompt.dedupeKey)),this.queuedInteractivePrompts.push(e),c.info("Queued interactive prompt behind active prompt",{activeCallId:t.callId,queuedCallId:e.prompt.callId,queueLength:this.queuedInteractivePrompts.length}),!1)}async emitInteractivePromptEvent(e){if(!this.isExpectedSessionStateCurrent(e.ownerState))return;let t=e.ownerState.sessionId,i=this.e1PromptRaises.get(e.prompt.promptId),s=i?i.record:this.newE1Raise(t,!0,void 0,{...e.prompt.dedupeKey!==void 0?{dedupeKey:e.prompt.dedupeKey}:{},...e.prompt.completionKey!==void 0?{completionKey:e.prompt.completionKey}:{},...e.prompt.callId!==void 0?{callId:e.prompt.callId}:{}});e.prompt.promptId=s.promptId;let n=this.e1PromptRaises.get(s.promptId);n&&(n.resolutionDedupeKey??=e.prompt.dedupeKey,n.resolutionCompletionKey??=e.prompt.completionKey,n.resolutionCallId??=e.prompt.callId),(e.prompt.kind==="queued_question"||this.isQueuedQuestionPromptId(e.prompt.callId)||this.isQueuedQuestionPromptId(e.prompt.dedupeKey)||this.isQueuedQuestionPromptId(s.promptId))&&(this.recordHistoricalQueuedQuestionId(s.promptId),e.prompt.callId&&this.recordHistoricalQueuedQuestionId(e.prompt.callId),e.prompt.dedupeKey&&this.recordHistoricalQueuedQuestionId(e.prompt.dedupeKey)),e.prompt.dedupeKey&&this.e1ContentKeyIndex.set(`${t}::${e.prompt.dedupeKey}`,s.promptId),this.stashE1RaiseContent(s.promptId,e.content,e.metadata??{}),await this.publishE1Prompt(t,s,v.EventType.INTERACTIVE_PROMPT,e.content,e.metadata??{})}rebindWaitingPermissionRequests(e){for(let t of this.waitingPermissionRequests.values())t.ownerState.codexSessionId&&t.ownerState.codexSessionId===e.codexSessionId&&(t.ownerState=e)}async promoteWaitingPermissionRequest(e,t){if(!this.isExpectedSessionStateCurrent(t))return!1;let i=this.promptGeneration,s=await(0,F.parseInteractivePromptAsync)(e,this.tuiGemmaPort??void 0);if(this.promptGeneration!==i||!this.isExpectedSessionStateCurrent(t)||!s||this.hasMatchingPermissionHookPrompt(s,t.sessionId,e))return!1;for(let[n,r]of this.waitingPermissionRequests)if(this.isExpectedSessionStateCurrent(r.ownerState)&&this.parsedPromptMatchesApprovalContext(s,r.context,e)){this.waitingPermissionRequests.delete(n);try{await this.handlePermissionRequestHookWhileTracked(r.payload,t,r.context,n,r.dedupeKey,{parsedPrompt:s,snapshot:e})}catch(o){throw this.isExpectedSessionStateCurrent(t)&&!this.hasRecentlyResolvedApprovalDedupeKey(t.sessionId,n)&&this.waitingPermissionRequests.set(n,r),this.tmuxPaneObserver.resetLastPromptHash(),o}return!0}return!1}async emitNextQueuedInteractivePrompt(){if(this.pendingInteractivePrompt)return;if(this.queuedInteractivePrompts.length===0){let i=this.sessionState;if(i&&this.waitingPermissionRequests.size>0){let s=await this.tmuxPaneObserver.captureSnapshot();!(s&&await this.promoteWaitingPermissionRequest(s,i))&&this.isExpectedSessionStateCurrent(i)&&!this.pendingInteractivePrompt&&this.waitingPermissionRequests.size>0&&this.tmuxPaneObserver.resetLastPromptHash()}return}let e=this.queuedInteractivePrompts[0];if(!e)return;if(!this.isExpectedSessionStateCurrent(e.ownerState)){this.queuedInteractivePrompts.shift(),c.warn("Discarding queued prompt from stale session generation",{sessionId:e.ownerState.sessionId,currentSessionId:this.sessionState?.sessionId}),await this.emitNextQueuedInteractivePrompt();return}if(e.prompt.kind==="queued_question")try{let i=await this.tmuxPaneObserver.captureSnapshot();if(!this.queuedInteractivePrompts.includes(e))return;if(!this.isExpectedSessionStateCurrent(e.ownerState)){c.warn("Session changed during snapshot capture; withholding queued prompt",{promptId:e.prompt.promptId,sessionId:e.ownerState.sessionId,currentSessionId:this.sessionState?.sessionId});return}if(this.pendingInteractivePrompt)return;let n=ae(i).split(`
70
72
  `).slice(-25).join(`
71
- `),r=/Press a number to choose/i.test(n),o=this.isQueuedQuestionCollapsed(n),a=o||this.isExpandedQuestionMatchingPrompt(n,e.prompt),l=/›\s*(?:Ask Codex to do anything|$)/m.test(n),p=this.hasQueuedInputsFragment(n);if(!(r||o||p)){if(!a&&l&&n.trim().length>=10&&!n.includes("Disconnected")){c.info("Queued question resolved while queued behind approval; discarding",{promptId:e.prompt.promptId});let f=this.queuedInteractivePrompts.indexOf(e);f>=0&&this.queuedInteractivePrompts.splice(f,1),await this.clearResolvedInteractivePrompt(e.prompt.callId??e.prompt.promptId,e.prompt.dedupeKey??e.prompt.promptId),await this.emitNextQueuedInteractivePrompt();return}}}catch(i){c.debug("Failed to inspect pane before emitting queued question",{err:i})}if(!this.isExpectedSessionStateCurrent(e.ownerState)||this.pendingInteractivePrompt)return;let t=this.queuedInteractivePrompts.indexOf(e);if(!(t<0)){this.queuedInteractivePrompts.splice(t,1),this.pendingInteractivePrompt=e.prompt;try{await this.emitInteractivePromptEvent(e),c.info("Emitted next queued interactive prompt",{callId:e.prompt.callId,queueLength:this.queuedInteractivePrompts.length})}catch(i){this.pendingInteractivePrompt===e.prompt&&this.isExpectedSessionStateCurrent(e.ownerState)?(this.pendingInteractivePrompt=null,c.error("Failed to emit queued interactive prompt",{error:i}),await this.emitNextQueuedInteractivePrompt()):c.warn("Failed to emit queued interactive prompt, but slot was preempted or session changed; preserving current state",{error:i,currentPromptId:this.pendingInteractivePrompt?.promptId})}}}async clearObservedInteractivePrompt(e,t){if(!this.isExpectedSessionStateCurrent(e))return;this.promptGeneration++,this.clearTmuxParseCache();let i=this.pendingInteractivePrompt;if(!i||i.ownerSessionId!==e.sessionId||i.observerPromptHash!==t){c.debug("Ignoring prompt-cleared for a non-current chooser occurrence",{sessionId:e.sessionId,clearedPromptHash:t,activePromptId:i?.promptId,activePromptHash:i?.observerPromptHash});return}this.pendingInteractivePrompt=null,i.callId&&this.approvalDetector.onToolCallComplete(i.callId),this.rememberResolvedApprovalDedupeKey(e.sessionId,i.dedupeKey);for(let n of this.queuedPermissionRequestRegistrations.get(e.sessionId)??[])n.occurrenceKey===i.dedupeKey&&(n.disposition="resolved",this.deferredTmuxPromptCandidates.delete(n),this.removePermissionRequestOccurrence(n.dedupeKey,n.occurrenceKey));let s=this.beginE1PromptResolutions(new Set([i.promptId]),e.sessionId);this.launchE1Resolutions(s),await this.emitNextQueuedInteractivePrompt()}async clearResolvedInteractivePrompt(e,t){if(!t){c.debug("Interactive prompt completion had no comparable dialog identity",{callId:e});return}let i=this.isPermissionRequestOccurrenceKey(t),s=this.pendingInteractivePrompt,n=!!s&&(s.dedupeKey===t||s.completionKey===t||s.kind!=="queued_question"&&!i&&!!e&&s.callId===e),r=this.sessionState?.sessionId??s?.ownerSessionId,o=this.queuedInteractivePrompts.find(v=>v.prompt.kind!=="queued_question"&&!i&&!!e&&v.prompt.callId===e||v.prompt.dedupeKey===t||v.prompt.completionKey===t),a=this.permissionRequestHookInFlight,l=a?.ownerState.sessionId===r&&(a?.dedupeKey===t||a?.occurrenceKey===t),f=(r?this.queuedPermissionRequestRegistrations.get(r)??[]:[]).find(v=>v.dedupeKey===t||v.occurrenceKey===t),u=[...this.waitingPermissionRequests.values()].find(v=>v.ownerState.sessionId===r&&(v.occurrenceKey===t||v.dedupeKey===t)),m=n?s?.dedupeKey:o?.prompt.dedupeKey??(l?a?.occurrenceKey:void 0)??f?.occurrenceKey??u?.occurrenceKey??t,h=new Set;if(n&&s&&h.add(s.promptId),o&&h.add(o.prompt.promptId),r&&m){let v=this.e1ContentKeyIndex.get(`${r}::${m}`);v&&h.add(v)}let I=[...this.e1PromptRaises.entries()].find(([,v])=>v.record.sessionId===r&&(v.resolutionDedupeKey===m||!i&&!!e&&v.resolutionCallId===e||v.resolutionCompletionKey===t));if(I&&h.add(I[0]),(n||l||f||u||h.size>0)&&this.rememberResolvedApprovalDedupeKey(r,m),n&&s&&(this.pendingInteractivePrompt=null),e&&this.queuedQuestionCallIds.has(e)&&this.queuedQuestionCallIds.delete(e),f&&(f.disposition="resolved"),m)for(let v of this.removeQueuedInteractivePromptByDedupeKey(m))h.add(v);let w=r?this.beginE1PromptResolutions(h,r):[];this.launchE1Resolutions(w),(n||!this.pendingInteractivePrompt&&o)&&await this.emitNextQueuedInteractivePrompt()}clearInteractivePromptsForAcceptedInput(e){let t=e.sessionId;this.promptGeneration++;let i=new Set,s=this.pendingInteractivePrompt;s?.ownerSessionId===t&&s.kind!=="queued_question"&&(i.add(s.promptId),this.rememberResolvedApprovalDedupeKey(t,s.dedupeKey),this.pendingInteractivePrompt=null);let n=[];for(let a of this.queuedInteractivePrompts)a.prompt.ownerSessionId===t&&a.prompt.kind!=="queued_question"?(i.add(a.prompt.promptId),this.rememberResolvedApprovalDedupeKey(t,a.prompt.dedupeKey)):n.push(a);this.queuedInteractivePrompts=n;let r=new Set;s?.ownerSessionId===t&&s.kind==="queued_question"&&(r.add(s.promptId),s.callId&&r.add(s.callId),s.dedupeKey&&r.add(s.dedupeKey));for(let a of this.queuedInteractivePrompts)a.prompt.ownerSessionId===t&&a.prompt.kind==="queued_question"&&(r.add(a.prompt.promptId),a.prompt.callId&&r.add(a.prompt.callId),a.prompt.dedupeKey&&r.add(a.prompt.dedupeKey));for(let[a,l]of this.e1PromptRaises.entries())l.record.sessionId===t&&(r.has(a)||l.resolutionCallId&&r.has(l.resolutionCallId)||l.resolutionDedupeKey&&r.has(l.resolutionDedupeKey)||l.resolutionCompletionKey&&r.has(l.resolutionCompletionKey)||i.add(a));for(let a of this.queuedPermissionRequestRegistrations.get(t)??[])a.disposition="resolved",this.rememberResolvedApprovalDedupeKey(t,a.occurrenceKey),this.deferredTmuxPromptCandidates.delete(a);for(let[a,l]of this.waitingPermissionRequests)l.ownerState.sessionId===t&&(this.rememberResolvedApprovalDedupeKey(t,a),this.waitingPermissionRequests.delete(a));this.permissionRequestOccurrencesByCompletionKey.clear();let o=this.beginE1PromptResolutions(i,t);this.launchE1Resolutions(o)}removeQueuedInteractivePromptByDedupeKey(e){let t=this.queuedInteractivePrompts.length,i=this.queuedInteractivePrompts.filter(s=>s.prompt.dedupeKey===e);for(let s of i)this.rememberResolvedApprovalDedupeKey(s.ownerState.sessionId,s.prompt.dedupeKey);return this.queuedInteractivePrompts=this.queuedInteractivePrompts.filter(s=>s.prompt.dedupeKey!==e),this.queuedInteractivePrompts.length!==t&&c.debug("Removed resolved deduped tool call from interactive prompt queue",{dedupeKey:e,removed:t-this.queuedInteractivePrompts.length}),i.map(s=>s.prompt.promptId)}mergeCallIdIntoPromptByDedupeKey(e,t,i){let s=this.pendingInteractivePrompt;if(s?.ownerSessionId===e&&(s.completionKey??s.dedupeKey)===t&&!s.callId){s.callId=i;let r=this.e1PromptRaises.get(s.promptId);r&&(r.resolutionCallId??=i),c.debug("Merged callId into active deduped interactive prompt",{source:s.source,callId:i,dedupeKey:t});return}let n=this.queuedInteractivePrompts.find(r=>r.prompt.ownerSessionId===e&&(r.prompt.completionKey??r.prompt.dedupeKey)===t&&!r.prompt.callId);n&&(n.prompt.callId=i,c.debug("Merged callId into queued deduped interactive prompt",{source:n.prompt.source,callId:i,dedupeKey:t}))}isSameInteractivePrompt(e,t){if(e.ownerSessionId!==t.ownerSessionId||Date.now()-e.createdAt>xn)return!1;if(e.callId&&t.callId)return e.callId===t.callId;let s=e.completionKey??e.dedupeKey,n=t.completionKey??t.dedupeKey;return e.source!==t.source&&s&&s===n&&e.observerMatchKey&&e.observerMatchKey===t.observerMatchKey?!0:e.dedupeKey&&t.dedupeKey?e.dedupeKey===t.dedupeKey:e.kind===t.kind&&this.normalizePromptDedupeText(e.promptText)===this.normalizePromptDedupeText(t.promptText)}normalizePromptDedupeText(e){return e.replace(/\s+/g," ").trim().toLowerCase()}async startTmuxObserver(){let e=process.env.CODEVIBE_CODEX_TMUX_SESSION;if(!e)return c.debug("Skipping tmux pane observer start - no tmux session in environment"),!0;try{return await this.tmuxPaneObserver.start(e),!0}catch(t){return c.warn("Failed to start tmux pane observer",{tmuxSession:e,error:t}),!1}}async startTmuxObserverWithBeacon(e){try{await this.startTmuxObserver()?await L("daemon_init_step_completed",{step:"tmux_observer_start",path:e}):await L("daemon_init_step_failed",{step:"tmux_observer_start",path:e,error_class:"TmuxObserverStartFailed",error_message:"tmuxPaneObserver.start threw (see plugin log)"})}catch(t){await L("daemon_init_step_failed",{step:"tmux_observer_start",path:e,error_class:t?.name||"Error",error_message:t?.message||String(t)}),c.error("Failed to start tmux observer:",t)}}static{this.MAX_TMUX_PARSE_CACHE_SIZE=50}evictExpiredTmuxParseCache(){let e=Date.now();for(let[t,i]of this.tmuxParseResultCache.entries())e-i.timestamp>=3500&&this.tmuxParseResultCache.delete(t)}setTmuxParseCache(e,t){if(this.evictExpiredTmuxParseCache(),this.tmuxParseResultCache.size>=d.MAX_TMUX_PARSE_CACHE_SIZE){let i=this.tmuxParseResultCache.keys().next().value;i&&this.tmuxParseResultCache.delete(i)}this.tmuxParseResultCache.set(e,{result:t,timestamp:Date.now()})}clearTmuxParseCache(){this.cacheGeneration++,this.tmuxParseResultCache.clear(),this.tmuxParseInFlight.clear()}async tryParseInteractivePromptFromTmux(e){try{let t=this.cacheGeneration,i=this.promptGeneration,s=Date.now(),n=e?.deadline??(e?.timeoutMs?s+e.timeoutMs:void 0),r=n?Math.max(50,n-Date.now()):e?.timeoutMs??5e3,o=await this.tmuxPaneObserver.captureSnapshot(120,r);if(n&&Date.now()>=n)return null;let a=this.tmuxPaneObserver.extractActiveApprovalBlock(o),l=null;if(a){this.evictExpiredTmuxParseCache();let p=this.tmuxParseResultCache.get(a);if(p&&Date.now()-p.timestamp<3500)l=p.result;else if(this.tmuxParseInFlight.has(a)){let f=this.tmuxParseInFlight.get(a),u=n?Math.max(50,n-Date.now()):e?.timeoutMs??2e3;l=await Promise.race([f,new Promise(m=>setTimeout(()=>m(null),u))])}else{let f=n?Math.max(50,n-Date.now()):e?.timeoutMs??2e3,u=(0,M.parseInteractivePromptAsync)(a,this.tuiGemmaPort??void 0,{...e,timeoutMs:f});this.tmuxParseInFlight.set(a,u);try{l=await u,this.cacheGeneration===t&&this.setTmuxParseCache(a,l)}finally{this.tmuxParseInFlight.get(a)===u&&this.tmuxParseInFlight.delete(a)}}}return c.debug("tmux prompt parse result",{parsed:!!l,kind:l?.kind,promptText:l?.promptText,isolated:!!a,snapshotPreview:this.summarizePromptSnapshot(a??o)}),{parsedPrompt:l,snapshot:a??o,promptGeneration:i}}catch(t){return c.debug("tmux prompt parsing unavailable",{error:t}),null}}async tryParsePermissionRequestPromptFromTmux(e,t){let n=Date.now()+3200,r=null;for(let o=0;o<25;o+=1){if(t&&!t())return null;let a=Date.now();if(a>=n)break;if(o>0){let f=Math.min(125,n-a);if(f<=0)break;if(await new Promise(u=>setTimeout(u,f)),t&&!t())return null;if(Date.now()>=n)break}let l=Math.max(50,n-Date.now()),p=await this.tryParseInteractivePromptFromTmux({deadline:n,timeoutMs:Math.min(2e3,l)});if(p&&(r=p),p?.parsedPrompt&&(!e||e(p.parsedPrompt,p.snapshot)))return p}return r?.snapshot?{parsedPrompt:null,snapshot:r.snapshot,promptGeneration:r.promptGeneration,...r.parsedPrompt?{differentPrompt:!0}:{}}:null}buildPromptPresentation(e){return e?{content:e.promptText,promptText:e.promptText,kind:e.kind,options:e.options,submitMap:e.submitMap,instructions:this.buildPromptInstructions(e),requiresFollowUpText:e.requiresFollowUpText}:{content:"Codex is waiting for approval.",promptText:"Codex is waiting for approval.",kind:"yes_no",options:[{number:"1",text:'Yes (sends "y")'},{number:"2",text:'No, tell Codex what to change (sends "n <instructions>")'}],submitMap:{1:"y",2:"n"},instructions:"Reply with 1 to approve, or 2 followed by what to change",requiresFollowUpText:!0}}buildCodexPromptPresentationDetailed(e,t,i){let s=this.buildPromptPresentation(e),n=i?ht(i):null;n&&(s.content=`Would you like to send input to terminal ${n.terminalId}?
73
+ `),r=/Press a number to choose/i.test(n),o=this.isQueuedQuestionCollapsed(n),d=o||this.isExpandedQuestionMatchingPrompt(n,e.prompt),l=/›\s*(?:Ask Codex to do anything|$)/m.test(n),u=this.hasQueuedInputsFragment(n);if(!(r||o||u)){if(!d&&l&&n.trim().length>=10&&!n.includes("Disconnected")){c.info("Queued question resolved while queued behind approval; discarding",{promptId:e.prompt.promptId});let h=this.queuedInteractivePrompts.indexOf(e);h>=0&&this.queuedInteractivePrompts.splice(h,1),await this.clearResolvedInteractivePrompt(e.prompt.callId??e.prompt.promptId,e.prompt.dedupeKey??e.prompt.promptId),await this.emitNextQueuedInteractivePrompt();return}}}catch(i){c.debug("Failed to inspect pane before emitting queued question",{err:i})}if(!this.isExpectedSessionStateCurrent(e.ownerState)||this.pendingInteractivePrompt)return;let t=this.queuedInteractivePrompts.indexOf(e);if(!(t<0)){this.queuedInteractivePrompts.splice(t,1),this.pendingInteractivePrompt=e.prompt;try{await this.emitInteractivePromptEvent(e),c.info("Emitted next queued interactive prompt",{callId:e.prompt.callId,queueLength:this.queuedInteractivePrompts.length})}catch(i){this.pendingInteractivePrompt===e.prompt&&this.isExpectedSessionStateCurrent(e.ownerState)?(this.pendingInteractivePrompt=null,c.error("Failed to emit queued interactive prompt",{error:i}),await this.emitNextQueuedInteractivePrompt()):c.warn("Failed to emit queued interactive prompt, but slot was preempted or session changed; preserving current state",{error:i,currentPromptId:this.pendingInteractivePrompt?.promptId})}}}async clearObservedInteractivePrompt(e,t){if(!this.isExpectedSessionStateCurrent(e))return;this.promptGeneration++,this.clearTmuxParseCache();let i=this.pendingInteractivePrompt;if(!i||i.ownerSessionId!==e.sessionId||i.observerPromptHash!==t){c.debug("Ignoring prompt-cleared for a non-current chooser occurrence",{sessionId:e.sessionId,clearedPromptHash:t,activePromptId:i?.promptId,activePromptHash:i?.observerPromptHash});return}this.pendingInteractivePrompt=null,i.callId&&this.approvalDetector.onToolCallComplete(i.callId),this.rememberResolvedApprovalDedupeKey(e.sessionId,i.dedupeKey);for(let n of this.queuedPermissionRequestRegistrations.get(e.sessionId)??[])n.occurrenceKey===i.dedupeKey&&(n.disposition="resolved",this.deferredTmuxPromptCandidates.delete(n),this.removePermissionRequestOccurrence(n.dedupeKey,n.occurrenceKey));let s=this.beginE1PromptResolutions(new Set([i.promptId]),e.sessionId);this.launchE1Resolutions(s),await this.emitNextQueuedInteractivePrompt()}async clearResolvedInteractivePrompt(e,t){if(!t){c.debug("Interactive prompt completion had no comparable dialog identity",{callId:e});return}let i=this.isPermissionRequestOccurrenceKey(t),s=this.pendingInteractivePrompt,n=!!s&&(s.dedupeKey===t||s.completionKey===t||s.kind!=="queued_question"&&!i&&!!e&&s.callId===e),r=this.sessionState?.sessionId??s?.ownerSessionId,o=this.queuedInteractivePrompts.find(I=>I.prompt.kind!=="queued_question"&&!i&&!!e&&I.prompt.callId===e||I.prompt.dedupeKey===t||I.prompt.completionKey===t),d=this.permissionRequestHookInFlight,l=d?.ownerState.sessionId===r&&(d?.dedupeKey===t||d?.occurrenceKey===t),h=(r?this.queuedPermissionRequestRegistrations.get(r)??[]:[]).find(I=>I.dedupeKey===t||I.occurrenceKey===t),p=[...this.waitingPermissionRequests.values()].find(I=>I.ownerState.sessionId===r&&(I.occurrenceKey===t||I.dedupeKey===t)),m=n?s?.dedupeKey:o?.prompt.dedupeKey??(l?d?.occurrenceKey:void 0)??h?.occurrenceKey??p?.occurrenceKey??t,f=new Set;if(n&&s&&f.add(s.promptId),o&&f.add(o.prompt.promptId),r&&m){let I=this.e1ContentKeyIndex.get(`${r}::${m}`);I&&f.add(I)}let g=[...this.e1PromptRaises.entries()].find(([,I])=>I.record.sessionId===r&&(I.resolutionDedupeKey===m||!i&&!!e&&I.resolutionCallId===e||I.resolutionCompletionKey===t));if(g&&f.add(g[0]),(n||l||h||p||f.size>0)&&this.rememberResolvedApprovalDedupeKey(r,m),n&&s&&(this.pendingInteractivePrompt=null),e&&this.queuedQuestionCallIds.has(e)&&this.queuedQuestionCallIds.delete(e),h&&(h.disposition="resolved"),m)for(let I of this.removeQueuedInteractivePromptByDedupeKey(m))f.add(I);let S=r?this.beginE1PromptResolutions(f,r):[];this.launchE1Resolutions(S),(n||!this.pendingInteractivePrompt&&o)&&await this.emitNextQueuedInteractivePrompt()}clearInteractivePromptsForAcceptedInput(e){let t=e.sessionId;this.promptGeneration++;let i=new Set,s=this.pendingInteractivePrompt;s?.ownerSessionId===t&&s.kind!=="queued_question"&&(i.add(s.promptId),this.rememberResolvedApprovalDedupeKey(t,s.dedupeKey),this.pendingInteractivePrompt=null);let n=[];for(let d of this.queuedInteractivePrompts)d.prompt.ownerSessionId===t&&d.prompt.kind!=="queued_question"?(i.add(d.prompt.promptId),this.rememberResolvedApprovalDedupeKey(t,d.prompt.dedupeKey)):n.push(d);this.queuedInteractivePrompts=n;let r=new Set;s?.ownerSessionId===t&&s.kind==="queued_question"&&(r.add(s.promptId),s.callId&&r.add(s.callId),s.dedupeKey&&r.add(s.dedupeKey));for(let d of this.queuedInteractivePrompts)d.prompt.ownerSessionId===t&&d.prompt.kind==="queued_question"&&(r.add(d.prompt.promptId),d.prompt.callId&&r.add(d.prompt.callId),d.prompt.dedupeKey&&r.add(d.prompt.dedupeKey));for(let[d,l]of this.e1PromptRaises.entries())l.record.sessionId===t&&(r.has(d)||l.resolutionCallId&&r.has(l.resolutionCallId)||l.resolutionDedupeKey&&r.has(l.resolutionDedupeKey)||l.resolutionCompletionKey&&r.has(l.resolutionCompletionKey)||i.add(d));for(let d of this.queuedPermissionRequestRegistrations.get(t)??[])d.disposition="resolved",this.rememberResolvedApprovalDedupeKey(t,d.occurrenceKey),this.deferredTmuxPromptCandidates.delete(d);for(let[d,l]of this.waitingPermissionRequests)l.ownerState.sessionId===t&&(this.rememberResolvedApprovalDedupeKey(t,d),this.waitingPermissionRequests.delete(d));this.permissionRequestOccurrencesByCompletionKey.clear();let o=this.beginE1PromptResolutions(i,t);this.launchE1Resolutions(o)}removeQueuedInteractivePromptByDedupeKey(e){let t=this.queuedInteractivePrompts.length,i=this.queuedInteractivePrompts.filter(s=>s.prompt.dedupeKey===e);for(let s of i)this.rememberResolvedApprovalDedupeKey(s.ownerState.sessionId,s.prompt.dedupeKey);return this.queuedInteractivePrompts=this.queuedInteractivePrompts.filter(s=>s.prompt.dedupeKey!==e),this.queuedInteractivePrompts.length!==t&&c.debug("Removed resolved deduped tool call from interactive prompt queue",{dedupeKey:e,removed:t-this.queuedInteractivePrompts.length}),i.map(s=>s.prompt.promptId)}mergeCallIdIntoPromptByDedupeKey(e,t,i){let s=this.pendingInteractivePrompt;if(s?.ownerSessionId===e&&(s.completionKey??s.dedupeKey)===t&&!s.callId){s.callId=i;let r=this.e1PromptRaises.get(s.promptId);r&&(r.resolutionCallId??=i),c.debug("Merged callId into active deduped interactive prompt",{source:s.source,callId:i,dedupeKey:t});return}let n=this.queuedInteractivePrompts.find(r=>r.prompt.ownerSessionId===e&&(r.prompt.completionKey??r.prompt.dedupeKey)===t&&!r.prompt.callId);n&&(n.prompt.callId=i,c.debug("Merged callId into queued deduped interactive prompt",{source:n.prompt.source,callId:i,dedupeKey:t}))}isSameInteractivePrompt(e,t){if(e.ownerSessionId!==t.ownerSessionId||Date.now()-e.createdAt>Hn)return!1;if(e.callId&&t.callId)return e.callId===t.callId;let s=e.completionKey??e.dedupeKey,n=t.completionKey??t.dedupeKey;return e.source!==t.source&&s&&s===n&&e.observerMatchKey&&e.observerMatchKey===t.observerMatchKey?!0:e.dedupeKey&&t.dedupeKey?e.dedupeKey===t.dedupeKey:e.kind===t.kind&&this.normalizePromptDedupeText(e.promptText)===this.normalizePromptDedupeText(t.promptText)}normalizePromptDedupeText(e){return e.replace(/\s+/g," ").trim().toLowerCase()}async startTmuxObserver(){let e=process.env.CODEVIBE_CODEX_TMUX_SESSION;if(!e)return c.debug("Skipping tmux pane observer start - no tmux session in environment"),!0;try{return await this.tmuxPaneObserver.start(e),!0}catch(t){return c.warn("Failed to start tmux pane observer",{tmuxSession:e,error:t}),!1}}async startTmuxObserverWithBeacon(e){try{await this.startTmuxObserver()?await L("daemon_init_step_completed",{step:"tmux_observer_start",path:e}):await L("daemon_init_step_failed",{step:"tmux_observer_start",path:e,error_class:"TmuxObserverStartFailed",error_message:"tmuxPaneObserver.start threw (see plugin log)"})}catch(t){await L("daemon_init_step_failed",{step:"tmux_observer_start",path:e,error_class:t?.name||"Error",error_message:t?.message||String(t)}),c.error("Failed to start tmux observer:",t)}}static{this.MAX_TMUX_PARSE_CACHE_SIZE=50}evictExpiredTmuxParseCache(){let e=Date.now();for(let[t,i]of this.tmuxParseResultCache.entries())e-i.timestamp>=3500&&this.tmuxParseResultCache.delete(t)}setTmuxParseCache(e,t){if(this.evictExpiredTmuxParseCache(),this.tmuxParseResultCache.size>=a.MAX_TMUX_PARSE_CACHE_SIZE){let i=this.tmuxParseResultCache.keys().next().value;i&&this.tmuxParseResultCache.delete(i)}this.tmuxParseResultCache.set(e,{result:t,timestamp:Date.now()})}clearTmuxParseCache(){this.cacheGeneration++,this.tmuxParseResultCache.clear(),this.tmuxParseInFlight.clear()}async tryParseInteractivePromptFromTmux(e){try{let t=this.cacheGeneration,i=this.promptGeneration,s=Date.now(),n=e?.deadline??(e?.timeoutMs?s+e.timeoutMs:void 0),r=n?Math.max(50,n-Date.now()):e?.timeoutMs??5e3,o=await this.tmuxPaneObserver.captureSnapshot(120,r);if(n&&Date.now()>=n)return null;let d=this.tmuxPaneObserver.extractActiveApprovalBlock(o),l=null;if(d){this.evictExpiredTmuxParseCache();let u=this.tmuxParseResultCache.get(d);if(u&&Date.now()-u.timestamp<3500)l=u.result;else if(this.tmuxParseInFlight.has(d)){let h=this.tmuxParseInFlight.get(d),p=n?Math.max(50,n-Date.now()):e?.timeoutMs??2e3;l=await Promise.race([h,new Promise(m=>setTimeout(()=>m(null),p))])}else{let h=n?Math.max(50,n-Date.now()):e?.timeoutMs??2e3,p=(0,F.parseInteractivePromptAsync)(d,this.tuiGemmaPort??void 0,{...e,timeoutMs:h});this.tmuxParseInFlight.set(d,p);try{l=await p,this.cacheGeneration===t&&this.setTmuxParseCache(d,l)}finally{this.tmuxParseInFlight.get(d)===p&&this.tmuxParseInFlight.delete(d)}}}return c.debug("tmux prompt parse result",{parsed:!!l,kind:l?.kind,promptText:l?.promptText,isolated:!!d,snapshotPreview:this.summarizePromptSnapshot(d??o)}),{parsedPrompt:l,snapshot:d??o,promptGeneration:i}}catch(t){return c.debug("tmux prompt parsing unavailable",{error:t}),null}}async tryParsePermissionRequestPromptFromTmux(e,t){let n=Date.now()+3200,r=null;for(let o=0;o<25;o+=1){if(t&&!t())return null;let d=Date.now();if(d>=n)break;if(o>0){let h=Math.min(125,n-d);if(h<=0)break;if(await new Promise(p=>setTimeout(p,h)),t&&!t())return null;if(Date.now()>=n)break}let l=Math.max(50,n-Date.now()),u=await this.tryParseInteractivePromptFromTmux({deadline:n,timeoutMs:Math.min(2e3,l)});if(u&&(r=u),u?.parsedPrompt&&(!e||e(u.parsedPrompt,u.snapshot)))return u}return r?.snapshot?{parsedPrompt:null,snapshot:r.snapshot,promptGeneration:r.promptGeneration,...r.parsedPrompt?{differentPrompt:!0}:{}}:null}buildPromptPresentation(e){return e?{content:e.promptText,promptText:e.promptText,kind:e.kind,options:e.options,submitMap:e.submitMap,instructions:this.buildPromptInstructions(e),requiresFollowUpText:e.requiresFollowUpText}:{content:"Codex is waiting for approval.",promptText:"Codex is waiting for approval.",kind:"yes_no",options:[{number:"1",text:'Yes (sends "y")'},{number:"2",text:'No, tell Codex what to change (sends "n <instructions>")'}],submitMap:{1:"y",2:"n"},instructions:"Reply with 1 to approve, or 2 followed by what to change",requiresFollowUpText:!0}}buildCodexPromptPresentationDetailed(e,t,i){let s=this.buildPromptPresentation(e),n=i?wt(i):null;n&&(s.content=`Would you like to send input to terminal ${n.terminalId}?
72
74
  Environment: ${n.environmentId}
73
- Input: ${JSON.stringify(n.chars)}`,s.promptText=s.content);let o=ms(s.options,t,i);if(o||(o=s.options.filter(l=>l.number!=="2"),c.info("[Hooks] Degraded Codex prompt presentation: persistent rule unverified; delivering one-time options",{remainingOptions:o.map(l=>l.number)})),s.options.length===0)return{presentation:null,failureReason:"unparseable_dialog"};if(o.length===0)return{presentation:null,failureReason:"no_actionable_options"};let a=this.buildSubmitMapFromCodexOptionHotkeys(o);return!a||Object.keys(a).length===0?{presentation:null,failureReason:"unsupported_hotkey"}:{presentation:{...s,options:o,submitMap:a,instructions:this.buildCodexPermissionInstructions(o),requiresFollowUpText:this.optionsRequireFollowUpText(o)}}}buildCodexPromptPresentation(e,t,i){return this.buildCodexPromptPresentationDetailed(e,t,i).presentation}buildSubmitMapFromCodexOptionHotkeys(e){let t={};for(let i of e){let s=i.text.match(/\(([^)]+)\)\s*$/)?.[1]?.trim().toLowerCase();if(!s||!kn.test(s))return null;s==="esc"||s==="escape"?t[i.number]=xe:t[i.number]=s}return t}buildCodexPermissionInstructions(e){let t=e.find(r=>/\((?:y|yes)\)\s*$/i.test(r.text)),i=e.find(r=>/\(p\)\s*$/i.test(r.text)),s=e.find(r=>/\((?:esc|escape)\)\s*$/i.test(r.text)),n=[];return t&&n.push(`${t.number} to approve`),i&&n.push(`${i.number} to persist the desktop allow rule`),s&&n.push(`${s.number} followed by what to change`),n.length>0?`Reply with ${n.join(", ")}`:"Reply with the number of the option you want"}optionsRequireFollowUpText(e){return e.some(t=>/what to (?:do differently|change)|instructions/i.test(t.text))}getMostRecentPendingToolCall(){let e=this.approvalDetector.getPendingCalls();return e.length===0?null:e.reduce((t,i)=>i.timestamp>t.timestamp?i:t)}hasActiveOrQueuedPermissionHookPrompt(e,t){let i=this.pendingInteractivePrompt;return i?.ownerSessionId===e&&i.source==="permission_hook"&&(i.completionKey??i.dedupeKey)===t?!0:this.queuedInteractivePrompts.some(s=>s.prompt.ownerSessionId===e&&s.prompt.source==="permission_hook"&&(s.prompt.completionKey??s.prompt.dedupeKey)===t)||[...this.waitingPermissionRequests.values()].some(s=>s.ownerState.sessionId===e&&s.dedupeKey===t)}hasDurablePermissionHookFallback(e){return[...this.e1PromptRaises.values()].some(t=>t.record.sessionId===e&&t.suppressTmuxObserverUntilResolved===!0)}hasDurablePermissionHookFallbackByDedupeKey(e,t){return[...this.e1PromptRaises.values()].some(i=>i.record.sessionId===e&&i.suppressTmuxObserverUntilResolved===!0&&(i.resolutionDedupeKey===t||i.resolutionCompletionKey===t))}hasMatchingDurablePermissionHookFallback(e,t,i){let s=this.buildApprovalPromptContextFromParsedPrompt(e),n=s?this.buildApprovalDedupeKey(s):void 0;if(n&&this.hasDurablePermissionHookFallbackByDedupeKey(t,n))return!0;if(!i)return!1;let r=this.buildObserverSnapshotMatchKey(i);return[...this.e1PromptRaises.values()].some(o=>o.record.sessionId===t&&o.suppressTmuxObserverUntilResolved===!0&&o.suppressedObserverSnapshotKey===r)}deferTmuxPromptCandidateForPermissionHook(e,t,i){let s=this.queuedPermissionRequestSessionCounts.get(e)??0,n=this.hasDurablePermissionHookFallback(e);if(s<=0&&!n)return!1;let r=(0,M.parseInteractivePrompt)(t);if(r&&this.hasMatchingDurablePermissionHookFallback(r,e,t))return c.debug("Skipping tmux repaint already owned by a durable PermissionRequest fallback",{sessionId:e,promptText:r.promptText}),!0;if(r&&this.hasMatchingPermissionHookPrompt(r,e,t))return c.debug("Skipping tmux repaint already owned by an actionable PermissionRequest",{sessionId:e,promptText:r.promptText}),!0;if(r&&s<=0)return!1;if(s>0){let o=this.queuedPermissionRequestRegistrations.get(e)??[],a=r?o.find(f=>this.parsedPromptMatchesApprovalContext(r,f.context,t)):void 0,l=!r&&this.permissionRequestHookInFlight?.ownerState.sessionId===e?this.permissionRequestHookInFlight.registration:void 0,p=a??l??(o.length===1&&(!r||!n)?o[0]:void 0);if(p&&this.deferredTmuxPromptCandidates.set(p,{snapshot:t,promptHash:i}),r&&!p)return!1}return c.debug("Skipping tmux prompt candidate while PermissionRequest owns the session prompt",{sessionId:e,toolName:this.permissionRequestHookInFlight?.context.toolName,ownership:s>0?"queued_or_in_flight":"durable_prompt"}),!0}hasMatchingPermissionHookPrompt(e,t,i){let s=this.buildObserverPromptMatchKey(e,i);return[this.pendingInteractivePrompt,...this.queuedInteractivePrompts.map(r=>r.prompt)].some(r=>r?.source==="permission_hook"&&r.ownerSessionId===t&&r.observerMatchKey===s)}buildObserverPromptMatchKey(e,t){let s=(t?(0,M.parseInteractivePrompt)(t):null)??e,n=s.options.map(a=>`${a.number}:${this.normalizeObserverPromptText(a.text)}`).join("|"),r=[s.kind,this.normalizeObserverPromptText(s.promptText),n].join("::"),o=t?ht(t):null;if(o){let a=JSON.stringify([o.terminalId,o.environmentId,o.chars,r]);return`terminal-input:${ve.createHash("sha256").update(a).digest("hex")}`}return`observer:${ve.createHash("sha256").update(r).digest("hex").slice(0,16)}`}buildObserverSnapshotMatchKey(e){let t=this.normalizeObserverPromptText(e);return`snapshot:${ve.createHash("sha256").update(t).digest("hex").slice(0,16)}`}normalizeObserverPromptText(e){return e.replace(/\r\n?/g,`
75
+ Input: ${JSON.stringify(n.chars)}`,s.promptText=s.content);let o=Ts(s.options,t,i);if(o||(o=s.options.filter(l=>l.number!=="2"),c.info("[Hooks] Degraded Codex prompt presentation: persistent rule unverified; delivering one-time options",{remainingOptions:o.map(l=>l.number)})),s.options.length===0)return{presentation:null,failureReason:"unparseable_dialog"};if(o.length===0)return{presentation:null,failureReason:"no_actionable_options"};let d=this.buildSubmitMapFromCodexOptionHotkeys(o);return!d||Object.keys(d).length===0?{presentation:null,failureReason:"unsupported_hotkey"}:{presentation:{...s,options:o,submitMap:d,instructions:this.buildCodexPermissionInstructions(o),requiresFollowUpText:this.optionsRequireFollowUpText(o)}}}buildCodexPromptPresentation(e,t,i){return this.buildCodexPromptPresentationDetailed(e,t,i).presentation}buildSubmitMapFromCodexOptionHotkeys(e){let t={};for(let i of e){let s=i.text.match(/\(([^)]+)\)\s*$/)?.[1]?.trim().toLowerCase();if(!s||!jn.test(s))return null;s==="esc"||s==="escape"?t[i.number]=Le:t[i.number]=s}return t}buildCodexPermissionInstructions(e){let t=e.find(r=>/\((?:y|yes)\)\s*$/i.test(r.text)),i=e.find(r=>/\(p\)\s*$/i.test(r.text)),s=e.find(r=>/\((?:esc|escape)\)\s*$/i.test(r.text)),n=[];return t&&n.push(`${t.number} to approve`),i&&n.push(`${i.number} to persist the desktop allow rule`),s&&n.push(`${s.number} followed by what to change`),n.length>0?`Reply with ${n.join(", ")}`:"Reply with the number of the option you want"}optionsRequireFollowUpText(e){return e.some(t=>/what to (?:do differently|change)|instructions/i.test(t.text))}getMostRecentPendingToolCall(){let e=this.approvalDetector.getPendingCalls();return e.length===0?null:e.reduce((t,i)=>i.timestamp>t.timestamp?i:t)}hasActiveOrQueuedPermissionHookPrompt(e,t){let i=this.pendingInteractivePrompt;return i?.ownerSessionId===e&&i.source==="permission_hook"&&(i.completionKey??i.dedupeKey)===t?!0:this.queuedInteractivePrompts.some(s=>s.prompt.ownerSessionId===e&&s.prompt.source==="permission_hook"&&(s.prompt.completionKey??s.prompt.dedupeKey)===t)||[...this.waitingPermissionRequests.values()].some(s=>s.ownerState.sessionId===e&&s.dedupeKey===t)}hasDurablePermissionHookFallback(e){return[...this.e1PromptRaises.values()].some(t=>t.record.sessionId===e&&t.suppressTmuxObserverUntilResolved===!0)}hasDurablePermissionHookFallbackByDedupeKey(e,t){return[...this.e1PromptRaises.values()].some(i=>i.record.sessionId===e&&i.suppressTmuxObserverUntilResolved===!0&&(i.resolutionDedupeKey===t||i.resolutionCompletionKey===t))}hasMatchingDurablePermissionHookFallback(e,t,i){let s=this.buildApprovalPromptContextFromParsedPrompt(e),n=s?this.buildApprovalDedupeKey(s):void 0;if(n&&this.hasDurablePermissionHookFallbackByDedupeKey(t,n))return!0;if(!i)return!1;let r=this.buildObserverSnapshotMatchKey(i);return[...this.e1PromptRaises.values()].some(o=>o.record.sessionId===t&&o.suppressTmuxObserverUntilResolved===!0&&o.suppressedObserverSnapshotKey===r)}deferTmuxPromptCandidateForPermissionHook(e,t,i){let s=this.queuedPermissionRequestSessionCounts.get(e)??0,n=this.hasDurablePermissionHookFallback(e);if(s<=0&&!n)return!1;let r=(0,F.parseInteractivePrompt)(t);if(r&&this.hasMatchingDurablePermissionHookFallback(r,e,t))return c.debug("Skipping tmux repaint already owned by a durable PermissionRequest fallback",{sessionId:e,promptText:r.promptText}),!0;if(r&&this.hasMatchingPermissionHookPrompt(r,e,t))return c.debug("Skipping tmux repaint already owned by an actionable PermissionRequest",{sessionId:e,promptText:r.promptText}),!0;if(r&&s<=0)return!1;if(s>0){let o=this.queuedPermissionRequestRegistrations.get(e)??[],d=r?o.find(h=>this.parsedPromptMatchesApprovalContext(r,h.context,t)):void 0,l=!r&&this.permissionRequestHookInFlight?.ownerState.sessionId===e?this.permissionRequestHookInFlight.registration:void 0,u=d??l??(o.length===1&&(!r||!n)?o[0]:void 0);if(u&&this.deferredTmuxPromptCandidates.set(u,{snapshot:t,promptHash:i}),r&&!u)return!1}return c.debug("Skipping tmux prompt candidate while PermissionRequest owns the session prompt",{sessionId:e,toolName:this.permissionRequestHookInFlight?.context.toolName,ownership:s>0?"queued_or_in_flight":"durable_prompt"}),!0}hasMatchingPermissionHookPrompt(e,t,i){let s=this.buildObserverPromptMatchKey(e,i);return[this.pendingInteractivePrompt,...this.queuedInteractivePrompts.map(r=>r.prompt)].some(r=>r?.source==="permission_hook"&&r.ownerSessionId===t&&r.observerMatchKey===s)}buildObserverPromptMatchKey(e,t){let s=(t?(0,F.parseInteractivePrompt)(t):null)??e,n=s.options.map(d=>`${d.number}:${this.normalizeObserverPromptText(d.text)}`).join("|"),r=[s.kind,this.normalizeObserverPromptText(s.promptText),n].join("::"),o=t?wt(t):null;if(o){let d=JSON.stringify([o.terminalId,o.environmentId,o.chars,r]);return`terminal-input:${Ee.createHash("sha256").update(d).digest("hex")}`}return`observer:${Ee.createHash("sha256").update(r).digest("hex").slice(0,16)}`}buildObserverSnapshotMatchKey(e){let t=this.normalizeObserverPromptText(e);return`snapshot:${Ee.createHash("sha256").update(t).digest("hex").slice(0,16)}`}normalizeObserverPromptText(e){return e.replace(/\r\n?/g,`
74
76
  `).split(`
75
77
  `).map(t=>t.replace(/[ \t]+$/g,"")).join(`
76
- `).trim()}hasRecentlyResolvedApprovalDedupeKey(e,t){return e?(this.pruneResolvedApprovalDedupeKeys(),this.resolvedApprovalDedupeKeys.has(`${e}::${t}`)):!1}rememberResolvedApprovalDedupeKey(e,t){!e||!t||(this.pruneResolvedApprovalDedupeKeys(),this.waitingPermissionRequests.get(t)?.ownerState.sessionId===e&&this.waitingPermissionRequests.delete(t),this.resolvedApprovalDedupeKeys.set(`${e}::${t}`,Date.now()))}pruneResolvedApprovalDedupeKeys(){let e=Date.now()-Qt;for(let[t,i]of this.resolvedApprovalDedupeKeys.entries())i<e&&this.resolvedApprovalDedupeKeys.delete(t)}buildApprovalDedupeKey(e){let t=e.toolName||"Tool",i=this.firstString(e.toolInput?.command,e.toolInput?.cmd,e.rawInput);if(i)return`command:${this.hashDedupeValue(`${this.mapToolNameForApproval(t)||t}:${i}`)}`;let s=this.firstString(e.filePath,e.toolInput?.file_path,e.toolInput?.path,e.toolInput?.filePath);if(s)return`file:${this.hashDedupeValue(`${t}:${s}`)}`;let n=this.firstString(e.hint);if(n)return`hint:${this.hashDedupeValue(`${t}:${n}`)}`}hashDedupeValue(e){return ve.createHash("sha256").update(e).digest("hex").slice(0,16)}buildPermissionRequestHint(e,t,i){let s=this.extractFilePathFromToolInput(e,t,i);if(this.mapToolNameForApproval(e)==="Edit"&&s)return`File: ${s}`;let n=this.firstString(t?.command,t?.cmd);return n?`Command: ${this.truncateApprovalDetail(n,80)}`:s?`File: ${s}`:`Tool: ${this.mapToolNameForApproval(e)||e}`}extractFilePathFromToolInput(e,t,i){let s=this.firstString(t?.file_path,t?.path,t?.filePath);if(s)return s;if(e==="apply_patch"){let r=this.firstString(t?.command,t?.cmd,i)?.match(/\*\*\* (?:Update|Add|Delete) File: ([^\r\n]+)/);if(r)return r[1].trim()}}stringifyToolInput(e){if(e!=null){if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return String(e)}}}buildApprovalPromptContextFromPendingCall(e){let t=this.firstString(e.parsedInput?.command,e.parsedInput?.cmd),i=Ue(e.input),s=Ae(t)||Ue(t),r=(e.name==="apply_patch"?Ae(e.input):"")||i||s,o=!!r,a=o?"apply_patch":e.name,l=o?r:e.input,p=o?e.parsedInput||{command:r}:e.parsedInput,f=o?this.extractFilePathFromToolInput("apply_patch",void 0,r):e.filePath;return{toolName:a,framedPatch:o,filePath:f,diff:o?l:e.diff,toolInput:p,rawInput:l,hint:f?`File: ${f}`:`Tool: ${this.mapToolNameForApproval(a)||a}`}}buildApprovalPromptContextFromParsedPrompt(e){let t=this.extractShellCommandFromPromptText(e.promptText);if(t)return{toolName:"Bash",toolInput:{command:t},rawInput:t,hint:`Command: ${this.truncateApprovalDetail(t,80)}`};let i=e.promptText.match(/^(?:Destination|File):\s*([^\r\n]+)$/mi)?.[1]?.trim();return i?{toolName:"apply_patch",filePath:i,toolInput:{file_path:i},hint:`File: ${i}`}:null}parsedPromptMatchesApprovalContext(e,t,i){if(t.toolName==="write_stdin"){let o=Li(t.toolName,t.toolInput);return!!o&&typeof i=="string"&&qi(i,o)}let s=this.buildApprovalPromptContextFromParsedPrompt(e),n=this.mapToolNameForApproval(t.toolName)==="Bash"?this.firstString(t.toolInput?.command,t.toolInput?.cmd):void 0;if(n){if(i&&!Mn(i,n))return!1;if(Ln(e.promptText,n,i))return!0;if(this.mapToolNameForApproval(s?.toolName)!=="Bash")return!1;let o=Ge(e.promptText);return o?Pt(o,n):!1}if(t.framedPatch!==!0)return!1;let r=t.filePath;return r?s?.toolName!=="apply_patch"||!s.filePath?!1:$.normalize(s.filePath)===$.normalize(r):!1}extractShellCommandFromPromptText(e){return us(e)}buildPromptInstructions(e){return e.kind==="yes_no"&&e.requiresFollowUpText?"Reply with 1 to approve, or 2 followed by what to change":e.kind==="yes_no"?"Reply with 1 for yes or 2 for no":e.kind==="numbered"?"Reply with the number of the option you want":"Reply with your response"}buildApprovalPromptContent(e,t){let i=e.trim(),s=i==="Codex is waiting for approval.",n=/^\$\s+/.test(i),r=t.toolName?`${t.toolName} requires approval.`:"Codex is waiting for approval.",o=[s||n||!i?r:i],a=typeof t.toolInput?.command=="string"?t.toolInput.command.trim():void 0;if(a&&!o.join(`
77
- `).includes(a))return o.push("Command:",this.truncateApprovalDetail(a,240)),o.join(`
78
+ `).trim()}hasRecentlyResolvedApprovalDedupeKey(e,t){return e?(this.pruneResolvedApprovalDedupeKeys(),this.resolvedApprovalDedupeKeys.has(`${e}::${t}`)):!1}rememberResolvedApprovalDedupeKey(e,t){!e||!t||(this.pruneResolvedApprovalDedupeKeys(),this.waitingPermissionRequests.get(t)?.ownerState.sessionId===e&&this.waitingPermissionRequests.delete(t),this.resolvedApprovalDedupeKeys.set(`${e}::${t}`,Date.now()))}pruneResolvedApprovalDedupeKeys(){let e=Date.now()-zt;for(let[t,i]of this.resolvedApprovalDedupeKeys.entries())i<e&&this.resolvedApprovalDedupeKeys.delete(t)}buildApprovalDedupeKey(e){let t=e.toolName||"Tool",i=this.firstString(e.toolInput?.command,e.toolInput?.cmd,e.rawInput);if(i)return`command:${this.hashDedupeValue(`${this.mapToolNameForApproval(t)||t}:${i}`)}`;let s=this.firstString(e.filePath,e.toolInput?.file_path,e.toolInput?.path,e.toolInput?.filePath);if(s)return`file:${this.hashDedupeValue(`${t}:${s}`)}`;let n=this.firstString(e.hint);if(n)return`hint:${this.hashDedupeValue(`${t}:${n}`)}`}hashDedupeValue(e){return Ee.createHash("sha256").update(e).digest("hex").slice(0,16)}buildPermissionRequestHint(e,t,i){let s=this.extractFilePathFromToolInput(e,t,i);if(this.mapToolNameForApproval(e)==="Edit"&&s)return`File: ${s}`;let n=this.firstString(t?.command,t?.cmd);return n?`Command: ${this.truncateApprovalDetail(n,80)}`:s?`File: ${s}`:`Tool: ${this.mapToolNameForApproval(e)||e}`}extractFilePathFromToolInput(e,t,i){let s=this.firstString(t?.file_path,t?.path,t?.filePath);if(s)return s;if(e==="apply_patch"){let r=this.firstString(t?.command,t?.cmd,i)?.match(/\*\*\* (?:Update|Add|Delete) File: ([^\r\n]+)/);if(r)return r[1].trim()}}stringifyToolInput(e){if(e!=null){if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return String(e)}}}buildApprovalPromptContextFromPendingCall(e){let t=this.firstString(e.parsedInput?.command,e.parsedInput?.cmd),i=We(e.input),s=Fe(t)||We(t),r=(e.name==="apply_patch"?Fe(e.input):"")||i||s,o=!!r,d=o?"apply_patch":e.name,l=o?r:e.input,u=o?e.parsedInput||{command:r}:e.parsedInput,h=o?this.extractFilePathFromToolInput("apply_patch",void 0,r):e.filePath;return{toolName:d,framedPatch:o,filePath:h,diff:o?l:e.diff,toolInput:u,rawInput:l,hint:h?`File: ${h}`:`Tool: ${this.mapToolNameForApproval(d)||d}`}}buildApprovalPromptContextFromParsedPrompt(e){let t=this.extractShellCommandFromPromptText(e.promptText);if(t)return{toolName:"Bash",toolInput:{command:t},rawInput:t,hint:`Command: ${this.truncateApprovalDetail(t,80)}`};let i=e.promptText.match(/^(?:Destination|File):\s*([^\r\n]+)$/mi)?.[1]?.trim();return i?{toolName:"apply_patch",filePath:i,toolInput:{file_path:i},hint:`File: ${i}`}:null}parsedPromptMatchesApprovalContext(e,t,i){if(t.toolName==="write_stdin"){let o=$i(t.toolName,t.toolInput);return!!o&&typeof i=="string"&&Wi(i,o)}let s=this.buildApprovalPromptContextFromParsedPrompt(e),n=this.mapToolNameForApproval(t.toolName)==="Bash"?this.firstString(t.toolInput?.command,t.toolInput?.cmd):void 0;if(n){if(i&&!Wn(i,n))return!1;if(zn(e.promptText,n,i))return!0;if(this.mapToolNameForApproval(s?.toolName)!=="Bash")return!1;let o=et(e.promptText);return o?Nt(o,n):!1}if(t.framedPatch!==!0)return!1;let r=t.filePath;return r?s?.toolName!=="apply_patch"||!s.filePath?!1:W.normalize(s.filePath)===W.normalize(r):!1}extractShellCommandFromPromptText(e){return bs(e)}buildPromptInstructions(e){return e.kind==="yes_no"&&e.requiresFollowUpText?"Reply with 1 to approve, or 2 followed by what to change":e.kind==="yes_no"?"Reply with 1 for yes or 2 for no":e.kind==="numbered"?"Reply with the number of the option you want":"Reply with your response"}buildApprovalPromptContent(e,t){let i=e.trim(),s=i==="Codex is waiting for approval.",n=/^\$\s+/.test(i),r=t.toolName?`${t.toolName} requires approval.`:"Codex is waiting for approval.",o=[s||n||!i?r:i],d=typeof t.toolInput?.command=="string"?t.toolInput.command.trim():void 0;if(d&&!o.join(`
79
+ `).includes(d))return o.push("Command:",this.truncateApprovalDetail(d,240)),o.join(`
78
80
  `);let l=t.filePath||t.toolInput?.file_path;return typeof l=="string"&&l.length>0&&!o.join(`
79
81
  `).includes(l)?(o.push(`File: ${l}`),o.join(`
80
82
  `)):(t.hint&&!o.join(`
81
83
  `).includes(t.hint)&&o.push(t.hint),o.join(`
82
84
  `))}truncateApprovalDetail(e,t){return e.length>t?`${e.slice(0,t-3)}...`:e}summarizePromptSnapshot(e){return e.split(`
83
85
  `).map(t=>t.trimEnd()).filter(t=>t.length>0).slice(-12).map(t=>t.slice(0,160)).join(`
84
- `)}translatePromptResponse(e,t,i=this.pendingInteractivePrompt){if(!i||t.kind!=="option")return{primaryInput:e};let s=i.submitMap[t.option];return s?t.followUpText?{primaryInput:s,followUpInput:t.followUpText}:{primaryInput:s}:{primaryInput:e}}getEventPromptId(e){let t=e.promptId??e.metadata?.promptId;return typeof t=="string"&&t.trim().length>0?t.trim():null}async emitRejectedPromptResponseNotification(e,t,i){if(!this.isExpectedSessionStateCurrent(i))return;let s=i.sessionId,n=e==="no_safe_reject_option"?"Your message was not sent because the active desktop prompt has no verified reject option. Please resolve it on the desktop and send your message again.":e==="live_prompt_unverified"?"Your response was not sent because the desktop prompt changed or could not be verified. Please reply to the prompt currently shown on your device.":e==="follow_up_delivery_failed"?"Your option was accepted, but the accompanying text could not be sent. Please send the text again.":e==="stale_preempted_queued_question"?"\u26A0\uFE0F Queued question paused \u2014 please answer the approval request first.":e==="invalid_queued_question_input"?"Your response was not recognized for this question. Please reply with the number of your choice.":this.pendingInteractivePrompt?"Response ignored because it was not tied to the current prompt. Please reply to the latest prompt again.":"Response ignored because no prompt is currently active on the desktop.",r={prompt_response_rejected:!0,reason:e,eventId:t.eventId,eventPromptId:this.getEventPromptId(t),activePromptId:this.pendingInteractivePrompt?.promptId};try{let o=(0,g.prepareEventTimestamp)({orderingKey:s}),a=await this.appSyncClient.publishCompanionNotice({sessionId:s,type:g.EventType.NOTIFICATION,source:g.EventSource.DESKTOP,content:n,metadata:r,timestamp:o},async()=>{if(!this.isExpectedSessionStateCurrent(i))return!1;let l=this.encryptForEmit(n,r,g.EventType.NOTIFICATION,s);return l?(await this.appSyncClient.createEvent({sessionId:s,type:g.EventType.NOTIFICATION,source:g.EventSource.DESKTOP,content:l.content,metadata:l.metadata,timestamp:o,...l.isEncrypted?{isEncrypted:!0}:{}}),!0):!1});c.debug("Rejected prompt response notification publication outcome",{reason:e,result:a})}catch(o){c.warn("Failed to emit rejected prompt response notification",{reason:e,error:o})}}buildToolDetailsForInteractivePrompt(e,t){let i=e.toolName,s=e.toolInput&&typeof e.toolInput=="object"?e.toolInput:void 0;if(i==="apply_patch"){let r=e.diff||e.rawInput;if(r){let{oldString:o,newString:a,oldStartLine:l,newStartLine:p}=this.extractOldNewFromPatch(r),f=t?this.extractDiffLineAnchorsFromSnapshot(t):{};return{tool_name:"Edit",tool_input:{file_path:e.filePath,content:r,diff:e.diff,raw_patch:e.rawInput,old_string:o,new_string:a,old_start_line:l??f.oldStartLine,new_start_line:p??f.newStartLine}}}}if(this.mapToolNameForApproval(i)==="Bash"){let r=this.firstString(s?.command,s?.cmd,e.rawInput,e.hint);if(r)return{tool_name:"Bash",tool_input:{command:r,output:s?.output}}}let n={};return e.filePath&&(n.file_path=e.filePath),e.diff&&(n.diff=e.diff),e.rawInput&&(n.raw_input=e.rawInput),Object.keys(n).length>0?{tool_name:i||"Tool",tool_input:n}:{}}firstString(...e){for(let t of e)if(typeof t=="string"&&t.trim().length>0)return t}buildFallbackToolInput(e){let t={};return e.filePath&&(t.file_path=e.filePath),e.diff&&(t.diff=e.diff),e.rawInput&&(t.raw_input=e.rawInput),e.toolInput&&typeof e.toolInput=="object"&&(t.parsed_input=e.toolInput),Object.keys(t).length>0?t:void 0}mapToolNameForApproval(e){return e?{exec_command:"Bash",exec:"Bash",local_shell:"Bash",Bash:"Bash",apply_patch:"Edit",shell_command:"Bash",shell:"Bash",Edit:"Edit",Write:"Write"}[e]||e:void 0}extractOldNewFromPatch(e){let t=[],i=[],s=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/,n=0,r=0,o=0,a,l;for(let p of e.split(`
85
- `)){let f=p.match(s);if(f){n+=1,r=Number.parseInt(f[1],10),o=Number.parseInt(f[2],10);continue}if(!(p.startsWith("***")||p.startsWith("---")||p.startsWith("+++")||p.startsWith("*** End Patch"))){if(p.startsWith("-"))a===void 0&&(a=r),t.push(p.slice(1)),r+=1;else if(p.startsWith("+"))l===void 0&&(l=o),i.push(p.slice(1)),o+=1;else if(p.startsWith(" ")){let u=p.slice(1);t.push(u),i.push(u),r+=1,o+=1}}}return{oldString:t.join(`
86
+ `)}translatePromptResponse(e,t,i=this.pendingInteractivePrompt){if(!i||t.kind!=="option")return{primaryInput:e};let s=i.submitMap[t.option];return s?t.followUpText?{primaryInput:s,followUpInput:t.followUpText}:{primaryInput:s}:{primaryInput:e}}getEventPromptId(e){let t=e.promptId??e.metadata?.promptId;return typeof t=="string"&&t.trim().length>0?t.trim():null}async emitRejectedPromptResponseNotification(e,t,i){if(!this.isExpectedSessionStateCurrent(i))return;let s=i.sessionId,n=e==="no_safe_reject_option"?"Your message was not sent because the active desktop prompt has no verified reject option. Please resolve it on the desktop and send your message again.":e==="live_prompt_unverified"?"Your response was not sent because the desktop prompt changed or could not be verified. Please reply to the prompt currently shown on your device.":e==="follow_up_delivery_failed"?"Your option was accepted, but the accompanying text could not be sent. Please send the text again.":e==="stale_preempted_queued_question"?"\u26A0\uFE0F Queued question paused \u2014 please answer the approval request first.":e==="invalid_queued_question_input"?"Your response was not recognized for this question. Please reply with the number of your choice.":this.pendingInteractivePrompt?"Response ignored because it was not tied to the current prompt. Please reply to the latest prompt again.":"Response ignored because no prompt is currently active on the desktop.",r={prompt_response_rejected:!0,reason:e,eventId:t.eventId,eventPromptId:this.getEventPromptId(t),activePromptId:this.pendingInteractivePrompt?.promptId};try{let o=(0,v.prepareEventTimestamp)({orderingKey:s}),d=await this.appSyncClient.publishCompanionNotice({sessionId:s,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:n,metadata:r,timestamp:o},async()=>{if(!this.isExpectedSessionStateCurrent(i))return!1;let l=this.encryptForEmit(n,r,v.EventType.NOTIFICATION,s);return l?(await this.appSyncClient.createEvent({sessionId:s,type:v.EventType.NOTIFICATION,source:v.EventSource.DESKTOP,content:l.content,metadata:l.metadata,timestamp:o,...l.isEncrypted?{isEncrypted:!0}:{}}),!0):!1});c.debug("Rejected prompt response notification publication outcome",{reason:e,result:d})}catch(o){c.warn("Failed to emit rejected prompt response notification",{reason:e,error:o})}}buildToolDetailsForInteractivePrompt(e,t){let i=e.toolName,s=e.toolInput&&typeof e.toolInput=="object"?e.toolInput:void 0;if(i==="apply_patch"){let r=e.diff||e.rawInput;if(r){let{oldString:o,newString:d,oldStartLine:l,newStartLine:u}=this.extractOldNewFromPatch(r),h=t?this.extractDiffLineAnchorsFromSnapshot(t):{};return{tool_name:"Edit",tool_input:{file_path:e.filePath,content:r,diff:e.diff,raw_patch:e.rawInput,old_string:o,new_string:d,old_start_line:l??h.oldStartLine,new_start_line:u??h.newStartLine}}}}if(this.mapToolNameForApproval(i)==="Bash"){let r=this.firstString(s?.command,s?.cmd,e.rawInput,e.hint);if(r)return{tool_name:"Bash",tool_input:{command:r,output:s?.output}}}let n={};return e.filePath&&(n.file_path=e.filePath),e.diff&&(n.diff=e.diff),e.rawInput&&(n.raw_input=e.rawInput),Object.keys(n).length>0?{tool_name:i||"Tool",tool_input:n}:{}}firstString(...e){for(let t of e)if(typeof t=="string"&&t.trim().length>0)return t}buildFallbackToolInput(e){let t={};return e.filePath&&(t.file_path=e.filePath),e.diff&&(t.diff=e.diff),e.rawInput&&(t.raw_input=e.rawInput),e.toolInput&&typeof e.toolInput=="object"&&(t.parsed_input=e.toolInput),Object.keys(t).length>0?t:void 0}mapToolNameForApproval(e){return e?{exec_command:"Bash",exec:"Bash",local_shell:"Bash",Bash:"Bash",apply_patch:"Edit",shell_command:"Bash",shell:"Bash",Edit:"Edit",Write:"Write"}[e]||e:void 0}extractOldNewFromPatch(e){let t=[],i=[],s=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/,n=0,r=0,o=0,d,l;for(let u of e.split(`
87
+ `)){let h=u.match(s);if(h){n+=1,r=Number.parseInt(h[1],10),o=Number.parseInt(h[2],10);continue}if(!(u.startsWith("***")||u.startsWith("---")||u.startsWith("+++")||u.startsWith("*** End Patch"))){if(u.startsWith("-"))d===void 0&&(d=r),t.push(u.slice(1)),r+=1;else if(u.startsWith("+"))l===void 0&&(l=o),i.push(u.slice(1)),o+=1;else if(u.startsWith(" ")){let p=u.slice(1);t.push(p),i.push(p),r+=1,o+=1}}}return{oldString:t.join(`
86
88
  `),newString:i.join(`
87
- `),oldStartLine:n===1?a:void 0,newStartLine:n===1?l:void 0}}extractDiffLineAnchorsFromSnapshot(e){let t=(0,M.normalizeSnapshot)(e),i,s;for(let n of t.split(`
88
- `)){let r=n.match(/^\s*(\d+)\s+(.*)$/);if(!r)continue;let o=Number.parseInt(r[1],10),a=r[2];if(Number.isFinite(o)){if(a.startsWith("-")){i??=o;continue}if(a.startsWith("+")){s??=o;continue}i??=o,s??=o}}return c.debug("Recovered diff line anchors from tmux snapshot",{oldStartLine:i,newStartLine:s,snapshotPreview:this.summarizePromptSnapshot(e)}),{oldStartLine:i,newStartLine:s}}subscribeToMobileEvents(e){let t=this.sessionState;if(!t||t.sessionId!==e)return c.warn("Refusing mobile subscription without matching session generation",{sessionId:e,currentSessionId:t?.sessionId}),!1;if(this.subscribedSessionId===e&&this.subscribedSessionState===t)return c.info("Already subscribed to mobile events, skipping",{sessionId:e}),!0;if(c.info("Subscribing to mobile events",{sessionId:e}),this.unsubscribe){try{this.unsubscribe()}catch(i){c.warn("Error cleaning up previous subscription (non-fatal)",{error:i})}this.subscribedSessionId=null,this.subscribedSessionState=null}try{this.unsubscribe=this.appSyncClient.subscribeToEvents(e,i=>{let s=this.handleMobileEvent(i,t);return s.catch(()=>c.warn("Mobile input retained after handler failure",{code:"NATIVE_OR_MOBILE_INPUT_FAILED"})),s},i=>{c.error("Subscription error:",i)},{onSubscribed:()=>{this.nativeAuthority&&this.maintainNativeControl().catch(()=>{})},onSessionRetired:()=>this.recoverRetiredBackendSession(e)}),this.subscribedSessionId=e,this.subscribedSessionState=t}catch(i){return c.error("Failed to subscribe to mobile events (non-fatal)",{sessionId:e,error:i}),!1}return this.isExpectedSessionStateCurrent(t)&&(t.subscriptionActive=!0),c.info("Subscribed to mobile events"),!0}async ensureOrchestrationClient(e){let{OrchestrationClient:t}=await import("@quantiya/quorum-core"),i=await g.keychainManager.getTokens((0,g.getEnvironment)());if(!i?.idToken)throw new Error("No Cognito ID token available \u2014 plugin must be logged in");let s=(0,g.getConfig)(),n=this.sessionKey??Buffer.alloc(32).toString("base64"),r=require("ws");return await t.connect({appsyncUrl:s.aws.appsyncUrl,cognitoIdToken:i.idToken,tokenProvider:async()=>(await g.keychainManager.getTokens((0,g.getEnvironment)()))?.idToken??i.idToken,sessionId:e,sessionKeyB64:n,webSocketFactory:((a,l)=>new r(a,l))})}async subscribeToOnApplyUserDecision(e){if(this.userDecisionUnsubscribe){try{this.userDecisionUnsubscribe()}catch(t){c.warn("Error invoking previous onApplyUserDecision unsubscribe (non-fatal)",{error:t})}this.userDecisionUnsubscribe=null}if(this.orchestrationClient){try{await this.orchestrationClient.destroy()}catch(t){c.warn("Error destroying previous OrchestrationClient (non-fatal)",{error:t})}this.orchestrationClient=null}try{let t=await this.ensureOrchestrationClient(e);this.orchestrationClient=t;let i=await t.onApplyUserDecision(s=>{this.handleApplyUserDecisionEvent(s)});return this.userDecisionUnsubscribe=i,c.info("[v1-bridge] Subscribed to onApplyUserDecision via OrchestrationClient",{sessionId:e}),!0}catch(t){if(c.error("Failed to subscribe to onApplyUserDecision (non-fatal)",{sessionId:e,error:t}),this.orchestrationClient){try{await this.orchestrationClient.destroy()}catch{}this.orchestrationClient=null}return!1}}handleApplyUserDecisionEvent(e){let{gateId:t,decision:i,sessionId:s,taskId:n}=e;if(this.v1Bridge.dispatch(e)==="self_echo"){c.debug("[v1-bridge] Self-origin decision echo absorbed",{gateId:t,decision:i,sessionId:s,taskId:n});return}c.info("[v1-bridge] cross-device decision recorded",{gateId:t,decision:i,sessionId:s,taskId:n});let o=String(i).toUpperCase();this.emitOrchestrationBanner(o)}async emitOrchestrationBanner(e){let t=process.env[ge];if(!t){c.warn("[v1-bridge] No tmux session set; cannot emit cross-device banner",{expectedEnv:ge});return}let s=$i(e).replace(/"/g,'\\"'),n=`tmux display-message -d 8000 -t "${t}" "${s}"`;try{await ds(n),c.info("[v1-bridge] Cross-device decision banner emitted",{decision:e})}catch(r){c.warn("[v1-bridge] tmux display-message failed (non-fatal)",{error:r instanceof Error?r.message:String(r)})}}async originateUserDecision(e){this.v1Bridge.markOriginated(e.gateId);let t=this.sessionState?.sessionId;if(!t)throw this.v1Bridge.clearOriginated(e.gateId),new Error("No active session \u2014 cannot originate user decision");let i=this.orchestrationClient,s=!1;i||(i=await this.ensureOrchestrationClient(t),s=!0);try{await i.applyUserDecision(e),c.info("[v1-bridge] originated user decision",{gateId:e.gateId,decision:e.decision,sessionId:t})}catch(n){throw this.v1Bridge.clearOriginated(e.gateId),c.error("[v1-bridge] applyUserDecision failed (rolled back originator marker)",{gateId:e.gateId,decision:e.decision,error:n instanceof Error?n.message:String(n)}),n}finally{if(s&&i)try{await i.destroy()}catch{}}}_v1BridgeStateForTest(){return this.v1Bridge}_v1BridgeHandleEventForTest(e){this.handleApplyUserDecisionEvent(e)}async downloadAttachment(e,t,i,s){try{let n=e.isEncrypted??s??!1;c.info("Downloading attachment",{id:e.id,type:e.type,filename:e.filename,s3Key:e.s3Key,attachmentIsEncrypted:e.isEncrypted,eventIsEncrypted:s,shouldDecrypt:n});let{downloadUrl:r}=await this.appSyncClient.getAttachmentDownloadUrl(e.s3Key),o=await fetch(r);if(!o.ok)throw new Error(`Failed to download attachment: ${o.status} ${o.statusText}`);let a=Buffer.from(await o.arrayBuffer());if(n&&i)try{c.info("Decrypting attachment",{id:e.id}),a=g.cryptoService.decryptData(a,i),c.info("Attachment decrypted successfully",{id:e.id,decryptedSize:a.length})}catch(m){throw c.error("Failed to decrypt attachment:",{id:e.id,error:m}),new Error("Failed to decrypt attachment")}else if(n&&!i)return c.warn("Cannot decrypt attachment - no session key available",{id:e.id}),null;let l=$.join($e.tmpdir(),"codevibe-codex",t);Ie.existsSync(l)||Ie.mkdirSync(l,{recursive:!0});let p="";if(e.filename){let m=$.extname(e.filename);m&&(p=m)}p||(p={"image/jpeg":".jpg","image/png":".png","image/gif":".gif","image/webp":".webp","image/heic":".heic","application/pdf":".pdf"}[e.type]||".bin");let f=`attachment-${e.id}${p}`,u=$.join(l,f);return Ie.writeFileSync(u,a),c.info("Attachment saved to temp file",{id:e.id,filePath:u,size:a.length}),u}catch(n){return c.error("Failed to download attachment:",{id:e.id,error:n}),null}}async handleMobileEvent(e,t=this.sessionState){if(this.nativeAuthority){this.nativeReplacementGate&&await this.retiredSessionRecoveryPromise;let o=this.nativeControlOwner;if(!o||o.state!==t)throw Error("NATIVE_SCOPE_CHANGED");await o.adapter.admit(e);return}if(e.attachments&&e.attachments.length>0&&c.info("DEBUG: Raw attachment data from subscription",{attachments:JSON.stringify(e.attachments),eventIsEncrypted:e.isEncrypted}),c.info("Received mobile event",{eventId:e.eventId,type:e.type,content:e.content?.substring(0,50),attachmentCount:e.attachments?.length||0,isEncrypted:e.isEncrypted}),!t||!this.isExpectedSessionStateCurrent(t)||e.sessionId!==t.sessionId){if(c.warn("Dropping mobile event for stale or mismatched session generation",{eventSessionId:e.sessionId,expectedSessionId:t?.sessionId,currentSessionId:this.sessionState?.sessionId}),(0,g.requiresSyncInputDeliveryReceipt)(e))throw new g.SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");return}let i=t.sessionId,{sessionKey:s}=t.encryptionSnapshot,n=e.content||"";if(e.isEncrypted){if(!s){if(c.error("Dropping encrypted mobile event without its session-pinned key",{eventId:e.eventId,sessionId:i}),(0,g.requiresSyncInputDeliveryReceipt)(e))throw new g.SyncEventClientError("SYNC_SESSION_KEY_UNAVAILABLE");return}try{n=g.cryptoService.decryptContent(e.content,s),c.debug("Event decrypted successfully",{eventId:e.eventId})}catch(o){if(c.error("Failed to decrypt event:",{eventId:e.eventId,error:o}),(0,g.requiresSyncInputDeliveryReceipt)(e))throw o;return}}let r=this.pendingInteractivePrompt;try{if(!await(0,g.acknowledgeMobileInputDelivery)(this.appSyncClient.updateEventStatus.bind(this.appSyncClient),e))return}catch(o){if(c.error("Failed to update delivery status:",o),(0,g.requiresSyncInputDeliveryReceipt)(e))throw o}if(this.isExpectedSessionStateCurrent(t)&&(e.type===g.EventType.USER_PROMPT||e.type===g.EventType.PROMPT_RESPONSE)){let o=n,a=e.attachments||[],l=e.type===g.EventType.PROMPT_RESPONSE,p=null,f=!1,u=this.getEventPromptId(e),m=r,h=(0,g.classifyMobilePromptInput)(o,m?Object.keys(m.submitMap):[]);if(m?.preemptedQueuedQuestionId&&u===m.preemptedQueuedQuestionId){c.warn("Rejecting mobile event explicitly bound to preempted queued question",{eventId:e.eventId,eventPromptId:u,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("stale_preempted_queued_question",e,t);return}let I=h.kind==="option"||/^\s*\d+(?:\s|$|[.,:])/.test(o.trim())||/^\s*(?:y|n|yes|no)\s*$/i.test(o.trim());if(u)if(m){if(u!==m.promptId){c.warn("Rejecting mobile event with mismatched promptId",{eventId:e.eventId,eventPromptId:u,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}}else{c.warn("Rejecting prompt-bound mobile event with no active prompt",{eventId:e.eventId,eventPromptId:u}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}else if(e.type===g.EventType.PROMPT_RESPONSE&&!m&&I){c.warn("Rejecting option-shaped PROMPT_RESPONSE with no active prompt",{eventId:e.eventId}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}if(m?.kind==="queued_question"){let R=o.trim();if(o.includes(",")&&/^\s*\d+(?:\s*,\s*\d+)*\s*$/.test(R)){c.warn("Rejecting multi-option input for single-choice queued question",{eventId:e.eventId,prompt:o,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("invalid_queued_question_input",e,t);return}if(e.type===g.EventType.PROMPT_RESPONSE||u){if(!u||u!==m.promptId){c.warn("Rejecting mismatched promptId for queued question",{eventId:e.eventId,eventPromptId:u,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}if(h.kind!=="option"||o.includes(",")||h.followUpText||!(R in m.submitMap)){c.warn("Rejecting invalid option for queued question",{eventId:e.eventId,prompt:o,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("invalid_queued_question_input",e,t);return}l=!0,p=m}else if(h.kind==="option"&&!o.includes(",")&&!h.followUpText&&R in m.submitMap)l=!0,p=m,c.info("Treating option-shaped unbound USER_PROMPT as queued question response",{eventId:e.eventId,activePromptId:m.promptId,promptPreview:o.slice(0,20)});else if(I){c.warn("Rejecting invalid option-shaped input beside queued question",{eventId:e.eventId,prompt:o,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("invalid_queued_question_input",e,t);return}else l=!1,f=!0,c.info("Treating mobile input as conversation continuation alongside queued question",{eventId:e.eventId,activePromptId:m.promptId,attachmentCount:a.length})}else if(h.kind==="option")if(!m)f=!0,l=!1;else if(e.type===g.EventType.PROMPT_RESPONSE){let R=m.promptId;if(!u||u!==R){c.warn("Rejecting stale or unbound PROMPT_RESPONSE",{eventId:e.eventId,eventPromptId:u,activePromptId:R}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}p=m}else{if(u&&u!==m.promptId){c.warn("Rejecting USER_PROMPT with mismatched promptId during active approval",{eventId:e.eventId,eventPromptId:u,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}let R=typeof e.timestamp=="number"?e.timestamp:(typeof e.timestamp=="string"?Date.parse(e.timestamp):0)||e.createdAt||0,_=m.preemptedQueuedQuestionAt||m.createdAt||0;if(m.preemptedQueuedQuestionId&&R>0&&_>0&&R<_){c.warn("Rejecting stale numeric USER_PROMPT composed before approval preempted queued question",{eventId:e.eventId,eventTime:R,preemptionThreshold:_,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("stale_preempted_queued_question",e,t);return}l=!0,p=m,c.info("Treating approval-shaped USER_PROMPT as active prompt response",{eventId:e.eventId,activePromptId:m.promptId,promptPreview:o.slice(0,20)})}else l=!1,f=!0,c.info("Treating mobile input as conversation continuation",{eventId:e.eventId,activePromptId:m?.promptId,attachmentCount:a.length});let y=[];if(a.length>0){c.info("Downloading attachments for prompt",{count:a.length});for(let R of a){let _=await this.downloadAttachment(R,i,s,e.isEncrypted);if(!this.isExpectedSessionStateCurrent(t))return;_&&y.push(_)}if(y.length>0){let R=y.map(_=>`[Attached file: ${_}]`).join(`
89
- `);o?o=`${R}
89
+ `),oldStartLine:n===1?d:void 0,newStartLine:n===1?l:void 0}}extractDiffLineAnchorsFromSnapshot(e){let t=(0,F.normalizeSnapshot)(e),i,s;for(let n of t.split(`
90
+ `)){let r=n.match(/^\s*(\d+)\s+(.*)$/);if(!r)continue;let o=Number.parseInt(r[1],10),d=r[2];if(Number.isFinite(o)){if(d.startsWith("-")){i??=o;continue}if(d.startsWith("+")){s??=o;continue}i??=o,s??=o}}return c.debug("Recovered diff line anchors from tmux snapshot",{oldStartLine:i,newStartLine:s,snapshotPreview:this.summarizePromptSnapshot(e)}),{oldStartLine:i,newStartLine:s}}subscribeToMobileEvents(e){let t=this.sessionState;if(!t||t.sessionId!==e)return c.warn("Refusing mobile subscription without matching session generation",{sessionId:e,currentSessionId:t?.sessionId}),!1;if(this.subscribedSessionId===e&&this.subscribedSessionState===t)return c.info("Already subscribed to mobile events, skipping",{sessionId:e}),!0;if(c.info("Subscribing to mobile events",{sessionId:e}),this.unsubscribe){try{this.unsubscribe()}catch(i){c.warn("Error cleaning up previous subscription (non-fatal)",{error:i})}this.subscribedSessionId=null,this.subscribedSessionState=null}try{this.unsubscribe=this.appSyncClient.subscribeToEvents(e,i=>{let s=this.handleMobileEvent(i,t);return s.catch(()=>c.warn("Mobile input retained after handler failure",{code:"NATIVE_OR_MOBILE_INPUT_FAILED"})),s},i=>{c.error("Subscription error:",i)},{onSubscribed:()=>{this.nativeAuthority&&this.maintainNativeControl().catch(()=>{})},onSessionRetired:()=>this.recoverRetiredBackendSession(e)}),this.subscribedSessionId=e,this.subscribedSessionState=t}catch(i){return c.error("Failed to subscribe to mobile events (non-fatal)",{sessionId:e,error:i}),!1}return this.isExpectedSessionStateCurrent(t)&&(t.subscriptionActive=!0),c.info("Subscribed to mobile events"),!0}async ensureOrchestrationClient(e){let{OrchestrationClient:t}=await import("@quantiya/quorum-core"),i=await v.keychainManager.getTokens((0,v.getEnvironment)());if(!i?.idToken)throw new Error("No Cognito ID token available \u2014 plugin must be logged in");let s=(0,v.getConfig)(),n=this.sessionKey??Buffer.alloc(32).toString("base64"),r=require("ws");return await t.connect({appsyncUrl:s.aws.appsyncUrl,cognitoIdToken:i.idToken,tokenProvider:async()=>(await v.keychainManager.getTokens((0,v.getEnvironment)()))?.idToken??i.idToken,sessionId:e,sessionKeyB64:n,webSocketFactory:((d,l)=>new r(d,l))})}async subscribeToOnApplyUserDecision(e){if(this.userDecisionUnsubscribe){try{this.userDecisionUnsubscribe()}catch(t){c.warn("Error invoking previous onApplyUserDecision unsubscribe (non-fatal)",{error:t})}this.userDecisionUnsubscribe=null}if(this.orchestrationClient){try{await this.orchestrationClient.destroy()}catch(t){c.warn("Error destroying previous OrchestrationClient (non-fatal)",{error:t})}this.orchestrationClient=null}try{let t=await this.ensureOrchestrationClient(e);this.orchestrationClient=t;let i=await t.onApplyUserDecision(s=>{this.handleApplyUserDecisionEvent(s)});return this.userDecisionUnsubscribe=i,c.info("[v1-bridge] Subscribed to onApplyUserDecision via OrchestrationClient",{sessionId:e}),!0}catch(t){if(c.error("Failed to subscribe to onApplyUserDecision (non-fatal)",{sessionId:e,error:t}),this.orchestrationClient){try{await this.orchestrationClient.destroy()}catch{}this.orchestrationClient=null}return!1}}handleApplyUserDecisionEvent(e){let{gateId:t,decision:i,sessionId:s,taskId:n}=e;if(this.v1Bridge.dispatch(e)==="self_echo"){c.debug("[v1-bridge] Self-origin decision echo absorbed",{gateId:t,decision:i,sessionId:s,taskId:n});return}c.info("[v1-bridge] cross-device decision recorded",{gateId:t,decision:i,sessionId:s,taskId:n});let o=String(i).toUpperCase();this.emitOrchestrationBanner(o)}async emitOrchestrationBanner(e){let t=process.env[we];if(!t){c.warn("[v1-bridge] No tmux session set; cannot emit cross-device banner",{expectedEnv:we});return}let s=is(e).replace(/"/g,'\\"'),n=`tmux display-message -d 8000 -t "${t}" "${s}"`;try{await ws(n),c.info("[v1-bridge] Cross-device decision banner emitted",{decision:e})}catch(r){c.warn("[v1-bridge] tmux display-message failed (non-fatal)",{error:r instanceof Error?r.message:String(r)})}}async originateUserDecision(e){this.v1Bridge.markOriginated(e.gateId);let t=this.sessionState?.sessionId;if(!t)throw this.v1Bridge.clearOriginated(e.gateId),new Error("No active session \u2014 cannot originate user decision");let i=this.orchestrationClient,s=!1;i||(i=await this.ensureOrchestrationClient(t),s=!0);try{await i.applyUserDecision(e),c.info("[v1-bridge] originated user decision",{gateId:e.gateId,decision:e.decision,sessionId:t})}catch(n){throw this.v1Bridge.clearOriginated(e.gateId),c.error("[v1-bridge] applyUserDecision failed (rolled back originator marker)",{gateId:e.gateId,decision:e.decision,error:n instanceof Error?n.message:String(n)}),n}finally{if(s&&i)try{await i.destroy()}catch{}}}_v1BridgeStateForTest(){return this.v1Bridge}_v1BridgeHandleEventForTest(e){this.handleApplyUserDecisionEvent(e)}async downloadAttachment(e,t,i,s){try{let n=e.isEncrypted??s??!1;c.info("Downloading attachment",{id:e.id,type:e.type,filename:e.filename,s3Key:e.s3Key,attachmentIsEncrypted:e.isEncrypted,eventIsEncrypted:s,shouldDecrypt:n});let{downloadUrl:r}=await this.appSyncClient.getAttachmentDownloadUrl(e.s3Key),o=await fetch(r);if(!o.ok)throw new Error(`Failed to download attachment: ${o.status} ${o.statusText}`);let d=Buffer.from(await o.arrayBuffer());if(n&&i)try{c.info("Decrypting attachment",{id:e.id}),d=v.cryptoService.decryptData(d,i),c.info("Attachment decrypted successfully",{id:e.id,decryptedSize:d.length})}catch(m){throw c.error("Failed to decrypt attachment:",{id:e.id,error:m}),new Error("Failed to decrypt attachment")}else if(n&&!i)return c.warn("Cannot decrypt attachment - no session key available",{id:e.id}),null;let l=W.join(Ze.tmpdir(),"codevibe-codex",t);Pe.existsSync(l)||Pe.mkdirSync(l,{recursive:!0});let u="";if(e.filename){let m=W.extname(e.filename);m&&(u=m)}u||(u={"image/jpeg":".jpg","image/png":".png","image/gif":".gif","image/webp":".webp","image/heic":".heic","application/pdf":".pdf"}[e.type]||".bin");let h=`attachment-${e.id}${u}`,p=W.join(l,h);return Pe.writeFileSync(p,d),c.info("Attachment saved to temp file",{id:e.id,filePath:p,size:d.length}),p}catch(n){return c.error("Failed to download attachment:",{id:e.id,error:n}),null}}async handleMobileEvent(e,t=this.sessionState){if(this.nativeAuthority){this.nativeReplacementGate&&await this.retiredSessionRecoveryPromise;let o=this.nativeControlOwner;if(!o||o.state!==t)throw Error("NATIVE_SCOPE_CHANGED");await o.adapter.admit(e);return}if(e.attachments&&e.attachments.length>0&&c.info("DEBUG: Raw attachment data from subscription",{attachments:JSON.stringify(e.attachments),eventIsEncrypted:e.isEncrypted}),c.info("Received mobile event",{eventId:e.eventId,type:e.type,content:e.content?.substring(0,50),attachmentCount:e.attachments?.length||0,isEncrypted:e.isEncrypted}),!t||!this.isExpectedSessionStateCurrent(t)||e.sessionId!==t.sessionId){if(c.warn("Dropping mobile event for stale or mismatched session generation",{eventSessionId:e.sessionId,expectedSessionId:t?.sessionId,currentSessionId:this.sessionState?.sessionId}),(0,v.requiresSyncInputDeliveryReceipt)(e))throw new v.SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");return}let i=t.sessionId,{sessionKey:s}=t.encryptionSnapshot,n=e.content||"";if(e.isEncrypted){if(!s){if(c.error("Dropping encrypted mobile event without its session-pinned key",{eventId:e.eventId,sessionId:i}),(0,v.requiresSyncInputDeliveryReceipt)(e))throw new v.SyncEventClientError("SYNC_SESSION_KEY_UNAVAILABLE");return}try{n=v.cryptoService.decryptContent(e.content,s),c.debug("Event decrypted successfully",{eventId:e.eventId})}catch(o){if(c.error("Failed to decrypt event:",{eventId:e.eventId,error:o}),(0,v.requiresSyncInputDeliveryReceipt)(e))throw o;return}}let r=this.pendingInteractivePrompt;try{if(!await(0,v.acknowledgeMobileInputDelivery)(this.appSyncClient.updateEventStatus.bind(this.appSyncClient),e))return}catch(o){if(c.error("Failed to update delivery status:",o),(0,v.requiresSyncInputDeliveryReceipt)(e))throw o}if(this.isExpectedSessionStateCurrent(t)&&(e.type===v.EventType.USER_PROMPT||e.type===v.EventType.PROMPT_RESPONSE)){let o=n,d=e.attachments||[],l=e.type===v.EventType.PROMPT_RESPONSE,u=null,h=!1,p=this.getEventPromptId(e),m=r,f=(0,v.classifyMobilePromptInput)(o,m?Object.keys(m.submitMap):[]);if(m?.preemptedQueuedQuestionId&&p===m.preemptedQueuedQuestionId){c.warn("Rejecting mobile event explicitly bound to preempted queued question",{eventId:e.eventId,eventPromptId:p,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("stale_preempted_queued_question",e,t);return}let g=f.kind==="option"||/^\s*\d+(?:\s|$|[.,:])/.test(o.trim())||/^\s*(?:y|n|yes|no)\s*$/i.test(o.trim());if(p)if(m){if(p!==m.promptId){c.warn("Rejecting mobile event with mismatched promptId",{eventId:e.eventId,eventPromptId:p,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}}else{c.warn("Rejecting prompt-bound mobile event with no active prompt",{eventId:e.eventId,eventPromptId:p}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}else if(e.type===v.EventType.PROMPT_RESPONSE&&!m&&g){c.warn("Rejecting option-shaped PROMPT_RESPONSE with no active prompt",{eventId:e.eventId}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}if(m?.kind==="queued_question"){let b=o.trim();if(o.includes(",")&&/^\s*\d+(?:\s*,\s*\d+)*\s*$/.test(b)){c.warn("Rejecting multi-option input for single-choice queued question",{eventId:e.eventId,prompt:o,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("invalid_queued_question_input",e,t);return}if(e.type===v.EventType.PROMPT_RESPONSE||p){if(!p||p!==m.promptId){c.warn("Rejecting mismatched promptId for queued question",{eventId:e.eventId,eventPromptId:p,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}if(f.kind!=="option"||o.includes(",")||f.followUpText||!(b in m.submitMap)){c.warn("Rejecting invalid option for queued question",{eventId:e.eventId,prompt:o,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("invalid_queued_question_input",e,t);return}l=!0,u=m}else if(f.kind==="option"&&!o.includes(",")&&!f.followUpText&&b in m.submitMap)l=!0,u=m,c.info("Treating option-shaped unbound USER_PROMPT as queued question response",{eventId:e.eventId,activePromptId:m.promptId,promptPreview:o.slice(0,20)});else if(g){c.warn("Rejecting invalid option-shaped input beside queued question",{eventId:e.eventId,prompt:o,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("invalid_queued_question_input",e,t);return}else l=!1,h=!0,c.info("Treating mobile input as conversation continuation alongside queued question",{eventId:e.eventId,activePromptId:m.promptId,attachmentCount:d.length})}else if(f.kind==="option")if(!m)h=!0,l=!1;else if(e.type===v.EventType.PROMPT_RESPONSE){let b=m.promptId;if(!p||p!==b){c.warn("Rejecting stale or unbound PROMPT_RESPONSE",{eventId:e.eventId,eventPromptId:p,activePromptId:b}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}u=m}else{if(p&&p!==m.promptId){c.warn("Rejecting USER_PROMPT with mismatched promptId during active approval",{eventId:e.eventId,eventPromptId:p,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("prompt_id_mismatch",e,t);return}let b=typeof e.timestamp=="number"?e.timestamp:(typeof e.timestamp=="string"?Date.parse(e.timestamp):0)||e.createdAt||0,_=m.preemptedQueuedQuestionAt||m.createdAt||0;if(m.preemptedQueuedQuestionId&&b>0&&_>0&&b<_){c.warn("Rejecting stale numeric USER_PROMPT composed before approval preempted queued question",{eventId:e.eventId,eventTime:b,preemptionThreshold:_,activePromptId:m.promptId}),await this.emitRejectedPromptResponseNotification("stale_preempted_queued_question",e,t);return}l=!0,u=m,c.info("Treating approval-shaped USER_PROMPT as active prompt response",{eventId:e.eventId,activePromptId:m.promptId,promptPreview:o.slice(0,20)})}else l=!1,h=!0,c.info("Treating mobile input as conversation continuation",{eventId:e.eventId,activePromptId:m?.promptId,attachmentCount:d.length});let y=[];if(d.length>0){c.info("Downloading attachments for prompt",{count:d.length});for(let b of d){let _=await this.downloadAttachment(b,i,s,e.isEncrypted);if(!this.isExpectedSessionStateCurrent(t))return;_&&y.push(_)}if(y.length>0){let b=y.map(_=>`[Attached file: ${_}]`).join(`
91
+ `);o?o=`${b}
90
92
 
91
- ${o}`:o=`${R}
93
+ ${o}`:o=`${b}
92
94
 
93
- Please analyze the attached file(s).`,c.info("Prompt updated with attachment paths",{attachmentCount:y.length,newPromptLength:o.length})}}if(l&&this.pendingInteractivePrompt!==p){c.info("Ignoring mobile prompt response already settled by a concurrent completion",{eventId:e.eventId,boundPromptId:p?.promptId,activePromptId:this.pendingInteractivePrompt?.promptId});return}let w=this.translatePromptResponse(o,h,p);if(!this.isExpectedSessionStateCurrent(t))return;p&&w.primaryInput!==xe&&await this.trackDurableMobileEcho(t,e,w.primaryInput,"primary");let v=()=>this.trackDurableMobileEcho(t,e,w.primaryInput,"primary");if(!this.isExpectedSessionStateCurrent(t))return;let S=p?await this.sendVerifiedPromptInput(t,p,w.primaryInput):f?await this.sendConversationContinuation(t,w.primaryInput,v):await this.sendSessionPinnedInput(t,w.primaryInput,v)?"sent":"send_failed",P=S==="sent";if(!this.isExpectedSessionStateCurrent(t))return;P&&f&&(this.approvalDetector.clear(),this.clearInteractivePromptsForAcceptedInput(t)),(S==="stale"||S==="unverified")&&await this.emitRejectedPromptResponseNotification("live_prompt_unverified",e,t),!P&&w.primaryInput!==xe&&!(0,g.requiresSyncInputDeliveryReceipt)(e)&&this.forgetMobilePrompt(i,w.primaryInput);let b=!0;if(P&&w.followUpInput){if(await new Promise(N=>setTimeout(N,200)),!this.isExpectedSessionStateCurrent(t))return;let R=w.followUpInput,_=()=>this.trackDurableMobileEcho(t,e,R,"follow_up");if(!this.isExpectedSessionStateCurrent(t)||(b=(p?await this.sendVerifiedFollowUpAfterDismissal(t,p,w.followUpInput,_):await this.sendSessionPinnedInput(t,w.followUpInput,_)?"sent":"send_failed")==="sent",!this.isExpectedSessionStateCurrent(t)))return;b||(await this.emitRejectedPromptResponseNotification("follow_up_delivery_failed",e,t),(0,g.requiresSyncInputDeliveryReceipt)(e)||this.forgetMobilePrompt(i,w.followUpInput))}if(P&&l&&p&&!p.terminalMenuIdentity&&this.pendingInteractivePrompt===p){let R=p;this.rememberResolvedApprovalDedupeKey(t.sessionId,R.dedupeKey),this.pendingInteractivePrompt=null;let _=this.beginE1PromptResolutions([R.promptId],t.sessionId);if(this.launchE1Resolutions(_),!this.isExpectedSessionStateCurrent(t)||(await this.emitNextQueuedInteractivePrompt(),!this.isExpectedSessionStateCurrent(t)))return}if(P&&b){if(!this.isExpectedSessionStateCurrent(t))return;try{await(0,g.acknowledgeMobileInputExecution)(this.appSyncClient.updateEventStatus.bind(this.appSyncClient),e)}catch(R){c.error("Failed to update executed status:",R)}}}}buildToolActivityIntegration(){return new Oe({logger:c,initialBoundary:e=>this.sessionWatcher.getToolReplayBoundary(e),selectTransport:async(e,t)=>{let i=this.sessionState;if(!i||i.sessionId!==e)throw new Error("SYNC_SOURCE_OWNER_CHANGED");let s=await this.selectNativeSourceTransport(i);return s.protocol==="LEGACY"?t:this.appSyncClient.toolActivitySyncTransport({sessionScope:s.sessionScope,getEncryptionContext:s.getEncryptionContext})},recoverPending:async(e,t,i)=>{await this.appSyncClient.recoverCompanionSyncSources({sessionId:e}),await this.appSyncClient.recoverToolActivityWindows({sessionId:e,outbox:t,ledger:i})},createEvent:e=>this.appSyncClient.createEvent(e),encryptContent:(e,t)=>g.cryptoService.encryptContent(e,t),encryptMetadata:(e,t)=>g.cryptoService.encryptMetadata(e,t),getSessionKey:()=>this.sessionKey,getSessionKeyGen:()=>this.sessionKeyGen,refreshSessionKey:e=>this.refreshToolActivitySessionKey(e)})}async refreshToolActivitySessionKey(e){try{let t=await this.appSyncClient.getSession(e);if(t&&t.status===g.SessionStatus.INACTIVE){let r=new Error(`SESSION_TERMINAL: session ${e} is ${t.status}; stop retrying`);throw r.errorType="SessionTerminal",r}if(!t||t.status!==g.SessionStatus.ACTIVE||!t.isEncrypted)return null;let i=t.sessionKeyGen??null,s=t.encryptedKeys??[];if(s.length===0)return null;let n=await g.keychainManager.getSessionKey(e,s,i);return n?(c.info("[tool-activity] refreshed session key for SessionKeyStale retry (live key untouched)",{sessionId:e,sessionKeyGen:i}),{sessionKey:n,sessionKeyGen:i}):null}catch(t){if((0,g.isTerminalSessionError)(t))throw t;return c.warn("[tool-activity] session key refresh failed after SessionKeyStale (staying retryable)",{sessionId:e,error:String(t)}),null}}getToolActivityLegacyRecorder(e){let t=this.toolActivityLegacyRecorders.get(e);return t||(t=new g.ToolActivityLedger({agent:"codex",sessionId:e,logger:c}),this.toolActivityLegacyRecorders.set(e,t)),t}async ensureToolActivityStarted(e){if(!this.sessionState||!e)return;let t=this.sessionWatcher.getActiveLogFile()||this.sessionState.codexLogFile||void 0,i=this.toolActivity;if(i){t&&i.bindTranscript(t);return}if(this.toolActivityStartPromise){await this.toolActivityStartPromise,t&&this.toolActivity?.bindTranscript(t);return}if(!this.sessionKey)return;let s=this.sessionState.sessionId;this.toolActivityStartPromise=(async()=>{let n=this.buildToolActivityIntegration();try{await n.start(s,e,t),this.toolActivity=n}catch(r){throw await n.abortStart().catch(o=>{c.warn("[tool-activity] failed candidate cleanup retained",{backendSessionId:s,rolloutId:e,error:String(o)})}),this.toolActivityStartPromise=null,r}})().catch(n=>{c.warn("[tool-activity] failed to start codex consolidator (non-fatal)",{backendSessionId:s,rolloutId:e,error:String(n)})}),await this.toolActivityStartPromise,this.toolActivity?.isActive()&&this.sessionWatcher.retryActiveRead()}startMobileEndWatcher(e){!this.sessionState||this.sessionState.sessionId!==e||(this.sessionState.mobileEndWatcher=this.appSyncClient.watchForMobileEnd(e,async()=>{if(this.nativeAuthority){this.nativeControlOwner?.adapter.stopAdmission(),this.appSyncClient.stopHeartbeat(e),this.appSyncClient.cleanupSubscription(e),process.send?.({type:"CODEVIBE_NATIVE_MOBILE_END",instanceId:this.nativeAuthority.record.instanceId});return}c.info("Mobile ended session \u2014 sending desktop quit",{sessionId:e}),this.appSyncClient.stopHeartbeat(e),this.appSyncClient.cleanupSubscription(e);try{await this.appSyncClient.updateSession({sessionId:e,status:g.SessionStatus.INACTIVE}),c.info("Marked session INACTIVE on mobile-end (before tmux terminate)",{sessionId:e})}catch(i){c.warn("Failed to mark session INACTIVE on mobile-end",{sessionId:e,error:i})}let t=process.env[ge];if(!t){c.warn("No tmux session set; skipping desktop self-terminate",{sessionId:e,expectedEnv:ge});return}await Dn(t,Cn)}))}async endActiveSession(e,t=!0){if(!this.sessionState)return;let i=e,s=t,n=this.sessionState,r=this.nativeControlOwner?.state===n?this.nativeControlOwner:null;if(r?.adapter.stopAdmission(),this.terminalInputBlockedStates.add(n),await this.terminalInputChain.catch(()=>{}),this.sessionState!==n){c.warn("Session changed while waiting for terminal-input teardown barrier",{endingSessionId:n.sessionId,currentSessionId:this.sessionState?.sessionId,reason:i});return}if(c.info("Ending active session",{sessionId:n.sessionId,codexSessionId:n.codexSessionId,reason:i}),this.sessionState.mobileEndWatcher&&(this.sessionState.mobileEndWatcher.stop(),this.sessionState.mobileEndWatcher=void 0),this.userDecisionUnsubscribe){try{this.userDecisionUnsubscribe()}catch(o){c.warn("Error invoking onApplyUserDecision unsubscribe (non-fatal)",{error:o})}this.userDecisionUnsubscribe=null}if(this.orchestrationClient){try{await this.orchestrationClient.destroy()}catch(o){c.warn("Error destroying OrchestrationClient (non-fatal)",{error:o})}this.orchestrationClient=null}this.v1Bridge.clear(),this.appSyncClient.stopHeartbeat(this.sessionState.sessionId),this.stopE1TtlRefresh(),this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null,this.subscribedSessionId=null,this.subscribedSessionState=null),this.nativeAuthority||await this.tmuxPaneObserver.stop();for(let o of this.deferredTmuxPromptCandidates.keys())o.sessionId===n.sessionId&&this.deferredTmuxPromptCandidates.delete(o);this.queuedPermissionRequestRegistrations.delete(n.sessionId),this.terminalRetirementRequested&&(i="shutdown",s=!0),i==="shutdown"&&this.sessionWatcher.stop(),this.toolActivityStartPromise&&(await this.toolActivityStartPromise.catch(()=>{}),this.toolActivityStartPromise=null),await this.logEntryChain.catch(()=>{}),await this.stopNativeSources(n),this.toolActivity&&(await this.toolActivity.stop(),this.toolActivity=null);for(let o of this.toolActivityLegacyRecorders.values())o.disposeLegacyCoordination();this.toolActivityLegacyRecorders.clear(),this.terminalRetirementRequested&&(i="shutdown",s=!0),r&&(i==="daemon-handoff"?await r.adapter.join():(await r.adapter.close(i==="backend-generation-retired"?"BACKEND_REPLACED":"TERMINAL"),i==="backend-generation-retired"&&(this.nativeReplacementToken=(0,ye.v4)(),await r.store.authorizeHandoff(r.owner,this.nativeReplacementToken,()=>r.adapter.join())))),!this.nativeAuthority&&i==="daemon-handoff"&&this.persistDaemonHandoffState(n),(i==="new-codex-session-started"||i==="shutdown")&&(await this.exactClearOpenE1ForLifecycleEnd(n.sessionId),await this.drainPendingE1ResolutionsForLifecycleEnd(),this.stopE1TtlRefresh()),i!=="backend-generation-retired"&&i!=="daemon-handoff"&&(this.permissionRequestOccurrencesByCompletionKey.clear(),this.waitingPermissionRequests.clear()),this.pendingInteractivePrompt=null,this.promptGeneration++,this.clearTmuxParseCache(),this.queuedInteractivePrompts=[],this.queuedQuestionCallIds.clear(),this.isInitializingSession=!1,this.bufferedLogEntries=[],Dt(),this.sessionKey&&(g.keychainManager.clearSessionKey(this.sessionState.sessionId),this.sessionKey=null,this.sessionKeyGen=null),this.terminalRetirementRequested&&(s=!0),s?(await this.retireHostedSession(this.sessionState.sessionId,n),r&&(await r.store.retirePayloads(r.owner,r.owner.scope,()=>r.adapter.join(),o=>this.appSyncClient.confirmDesktopSyncRetirement(o)),await r.store.pruneSettled(r.owner,r.owner.scope,o=>this.appSyncClient.confirmDesktopSyncRetirement(o)))):c.info("Preserving active backend session for daemon handoff",{sessionId:this.sessionState.sessionId}),this.sessionState=null,this.nativeControlOwner===r&&(this.nativeControlOwner=null)}async boundedTeardownStep(e,t){await Kt(async()=>{try{await t()}catch(s){c.warn(`${e} failed`,{error:String(s)})}},3e3,()=>c.warn(`${e} timed out \u2014 continuing teardown without it`,{timeoutMs:3e3}))==="timeout"&&this.teardownStepsTimedOut.push(e)}isDurableObligationSettledForExit(){return!this.retirementOwed}getTeardownStepsTimedOut(){return[...this.teardownStepsTimedOut]}async retireHostedSession(e,t){Bt("stall-retirement")&&(c.warn("[dev-fault] stall-retirement: this INACTIVE write will never settle",{sessionId:e}),await new Promise(()=>{}));let i;for(let s=1;s<=wt;s+=1)try{let n=await this.appSyncClient.updateSession({sessionId:e,status:g.SessionStatus.INACTIVE});n?.sessionGenerationId&&await this.appSyncClient.completeDesktopSyncRetirement({sessionId:e,toolOutbox:new g.ToolActivityOutbox({agent:"codex",logger:c})},n,async()=>{await this.logEntryChain.catch(()=>{}),await this.stopNativeSources(t)});return}catch(n){i=n,c.warn("Failed to retire hosted Codex session",{sessionId:e,attempt:s,maxAttempts:wt,error:n instanceof Error?n.message:String(n)}),s<wt&&await new Promise(r=>setTimeout(r,On*s))}throw new Error(`Failed to retire hosted Codex session ${e} after ${wt} attempts: ${String(i)}`)}async cleanupDetachedWrapperArtifacts(){let e=process.env.CODEVIBE_CODEX_WRAPPER_PID;if(!e||!/^\d+$/.test(e))return;let t=process.env.TMPDIR||$e.tmpdir(),i=[$.join(t,`codevibe-codex-server-${e}.pid`),$.join(t,`codevibe-codex-exit-${e}`),$.join(t,`codevibe-codex-tmux-session-${e}`)];for(let s of i)try{Ie.unlinkSync(s)}catch(n){n?.code!=="ENOENT"&&c.warn("Failed to remove detached-wrapper artifact",{ownedPath:s,error:String(n)})}}stop(e={}){return e.retireBackendSession!==!1&&(this.terminalRetirementRequested=!0),this.stopPromise?this.stopPromise:(this.stopPromise=this.doStop(),this.stopPromise)}async doStop(){c.info("Stopping CodeVibe Codex companion server"),this.stopTmuxLifecycleMonitor(),this.isStopping=!0,this.nativeControlOwner?.adapter.stopAdmission();let e=this.nativeRuntime?.close();this.nativeSourceRetryTimer&&clearTimeout(this.nativeSourceRetryTimer),this.nativeSourceRetryTimer=null,this.lifecycleGeneration+=1,this.sessionWatcher.stop();let t=this.launchSessionInitPromise,i=this.sessionStartedInitPromise,s=this.retiredSessionRecoveryPromise,n=this.hookEventChain,r=typeof this.sessionWatcher.waitForTranscriptAdmissions=="function"?this.sessionWatcher.waitForTranscriptAdmissions():Promise.resolve();this.teardownStepsTimedOut=[],await this.boundedTeardownStep("inFlightChains.join",()=>Promise.all([e?.catch(()=>{}),Promise.allSettled([...this.nativeReceiptWork?.values()??[]]),this.nativeMaintenance?.catch(()=>{}),t?.catch(()=>{}),i?.catch(()=>{}),s?.catch(()=>{}),r.catch(()=>{}),this.sessionWatcher.waitForReads().catch(()=>{}),n.catch(()=>{})]));try{let o=this.terminalRetirementRequested;this.retirementOwed=o&&this.sessionState!==null;let a,l=!1;if(await Kt(async()=>{try{await this.endActiveSession(o?"shutdown":"daemon-handoff",o),this.retirementOwed=!1}catch(f){l=!0,a=f}},1e4,()=>c.warn("endActiveSession timed out \u2014 continuing teardown without it",{timeoutMs:1e4,retirementOwed:this.retirementOwed}))==="timeout"&&this.teardownStepsTimedOut.push("endActiveSession"),l)throw a;this.sessionWatcher.stop(),this.approvalDetector?.shutdown(),Dt()}finally{this.httpApi&&await this.boundedTeardownStep("httpApi.stop",()=>this.httpApi.stop()),this.appSyncClient.cleanupSubscriptions(),this.terminalRetirementRequested&&!this.nativeAuthority&&await this.boundedTeardownStep("cleanupDetachedWrapperArtifacts",()=>this.cleanupDetachedWrapperArtifacts())}if(c.info("CodeVibe Codex companion server stopped"),this.retirementOwed)throw new Error("Session teardown timed out with the INACTIVE write still owed; the backend row may be stranded ACTIVE")}};require.main===module&&(async()=>{let d=process.env.CODEVIBE_CODEX_NATIVE_DESCRIPTOR,e=process.env.CODEVIBE_CODEX_NATIVE_INSTANCE;if(!d||!e)throw Error("Native launcher authority required;launch with codevibe --agent codex.");let t=await ei(d,e),i=new bt(t),s=!1;process.on("message",n=>{let r=n;if(r?.type==="CODEVIBE_NATIVE_RECEIPT"||r?.type==="CODEVIBE_NATIVE_RECEIPTS_UNAVAILABLE"){i.receiveNativeReceipt(n);return}if(r?.type!=="CODEVIBE_NATIVE_TERMINAL_END"||r.instanceId!==t.record.instanceId||s)return;s=!0;let o=De(a=>process.exit(a),()=>c.error("Native terminal teardown exceeded its deadline"),25e3,()=>i.isDurableObligationSettledForExit());i.stop().then(()=>{o(),process.exit(0)},()=>{o(),process.exit(1)})});for(let n of ls)process.on(n,()=>{c.info(`Received ${n}, evaluating terminal shutdown...`),(async()=>{if(i.hasNativeAuthority()){await i.stop({retireBackendSession:!1}).finally(()=>process.exit(1));return}let r;try{r=await i.shouldShutdownForTerminalSignal(n)}catch(a){c.error(`Failed to evaluate ${n} terminality; not shutting down`,{error:a instanceof Error?a.message:String(a)});return}if(!r)return;let o=De(a=>process.exit(a),()=>c.error("Shutdown watchdog fired \u2014 teardown did not complete in time; exiting anyway",{signal:n,watchdogMs:25e3,timedOutSteps:i.getTeardownStepsTimedOut(),durableObligationSettled:i.isDurableObligationSettledForExit()}),25e3,()=>i.isDurableObligationSettledForExit());try{await i.stop(),o(),process.exit(0)}catch(a){o(),c.error(`Failed to stop companion daemon after ${n}`,{error:a instanceof Error?a.message:String(a)}),process.exit(1)}})()});process.on("SIGUSR2",async()=>{c.info("Received SIGUSR2, handing off active session to replacement daemon...");let n=De(r=>process.exit(r),()=>c.error("Shutdown watchdog fired during SIGUSR2 handoff; exiting anyway",{watchdogMs:25e3,timedOutSteps:i.getTeardownStepsTimedOut()}),25e3,()=>i.isDurableObligationSettledForExit());try{await i.stop({retireBackendSession:!1})}catch(r){c.error("Handoff stop() failed; exiting anyway to free the session",{error:r instanceof Error?r.message:String(r)})}finally{n()}process.exit(0)}),(0,g.installDaemonProcessGuards)(c,{onFatal:()=>{let n=De(()=>process.exit(1),()=>c.error("Shutdown watchdog fired after a fatal guard; exiting anyway",{watchdogMs:25e3,timedOutSteps:i.getTeardownStepsTimedOut(),durableObligationSettled:i.isDurableObligationSettledForExit()}),25e3);i.stop({retireBackendSession:!i.hasNativeAuthority()}).finally(()=>{n(),process.exit(1)})}}),i.start().catch(n=>{c.error("Failed to start server:",n),process.exit(1)})})().catch(()=>{c.error("Native companion bootstrap failed"),process.exit(1)});0&&(module.exports={CodexCompanionServer,TERMINAL_SHUTDOWN_SIGNALS,TmuxPaneObserver,classifyTmuxHasSessionError,extractShellCommandFromPromptText,extractShellCommandPartsFromPromptText,restoreCodexPersistOptionCommand,shellCommandPartsMatchExpected});
95
+ Please analyze the attached file(s).`,c.info("Prompt updated with attachment paths",{attachmentCount:y.length,newPromptLength:o.length})}}if(l&&this.pendingInteractivePrompt!==u){c.info("Ignoring mobile prompt response already settled by a concurrent completion",{eventId:e.eventId,boundPromptId:u?.promptId,activePromptId:this.pendingInteractivePrompt?.promptId});return}let S=this.translatePromptResponse(o,f,u);if(!this.isExpectedSessionStateCurrent(t))return;u&&S.primaryInput!==Le&&await this.trackDurableMobileEcho(t,e,S.primaryInput,"primary");let I=()=>this.trackDurableMobileEcho(t,e,S.primaryInput,"primary");if(!this.isExpectedSessionStateCurrent(t))return;let w=u?await this.sendVerifiedPromptInput(t,u,S.primaryInput):h?await this.sendConversationContinuation(t,S.primaryInput,I):await this.sendSessionPinnedInput(t,S.primaryInput,I)?"sent":"send_failed",E=w==="sent";if(!this.isExpectedSessionStateCurrent(t))return;E&&h&&(this.approvalDetector.clear(),this.clearInteractivePromptsForAcceptedInput(t)),(w==="stale"||w==="unverified")&&await this.emitRejectedPromptResponseNotification("live_prompt_unverified",e,t),!E&&S.primaryInput!==Le&&!(0,v.requiresSyncInputDeliveryReceipt)(e)&&this.forgetMobilePrompt(i,S.primaryInput);let R=!0;if(E&&S.followUpInput){if(await new Promise(A=>setTimeout(A,200)),!this.isExpectedSessionStateCurrent(t))return;let b=S.followUpInput,_=()=>this.trackDurableMobileEcho(t,e,b,"follow_up");if(!this.isExpectedSessionStateCurrent(t)||(R=(u?await this.sendVerifiedFollowUpAfterDismissal(t,u,S.followUpInput,_):await this.sendSessionPinnedInput(t,S.followUpInput,_)?"sent":"send_failed")==="sent",!this.isExpectedSessionStateCurrent(t)))return;R||(await this.emitRejectedPromptResponseNotification("follow_up_delivery_failed",e,t),(0,v.requiresSyncInputDeliveryReceipt)(e)||this.forgetMobilePrompt(i,S.followUpInput))}if(E&&l&&u&&!u.terminalMenuIdentity&&this.pendingInteractivePrompt===u){let b=u;this.rememberResolvedApprovalDedupeKey(t.sessionId,b.dedupeKey),this.pendingInteractivePrompt=null;let _=this.beginE1PromptResolutions([b.promptId],t.sessionId);if(this.launchE1Resolutions(_),!this.isExpectedSessionStateCurrent(t)||(await this.emitNextQueuedInteractivePrompt(),!this.isExpectedSessionStateCurrent(t)))return}if(E&&R){if(!this.isExpectedSessionStateCurrent(t))return;try{await(0,v.acknowledgeMobileInputExecution)(this.appSyncClient.updateEventStatus.bind(this.appSyncClient),e)}catch(b){c.error("Failed to update executed status:",b)}}}}buildToolActivityIntegration(){return new _e({logger:c,initialBoundary:e=>this.sessionWatcher.getToolReplayBoundary(e),selectTransport:async(e,t)=>{let i=this.sessionState;if(!i||i.sessionId!==e)throw new Error("SYNC_SOURCE_OWNER_CHANGED");let s=await this.selectNativeSourceTransport(i);return s.protocol==="LEGACY"?t:this.appSyncClient.toolActivitySyncTransport({sessionScope:s.sessionScope,getEncryptionContext:s.getEncryptionContext})},recoverPending:async(e,t,i)=>{await this.appSyncClient.recoverCompanionSyncSources({sessionId:e}),await this.appSyncClient.recoverToolActivityWindows({sessionId:e,outbox:t,ledger:i})},createEvent:e=>this.appSyncClient.createEvent(e),encryptContent:(e,t)=>v.cryptoService.encryptContent(e,t),encryptMetadata:(e,t)=>v.cryptoService.encryptMetadata(e,t),getSessionKey:()=>this.sessionKey,getSessionKeyGen:()=>this.sessionKeyGen,refreshSessionKey:e=>this.refreshToolActivitySessionKey(e)})}async refreshToolActivitySessionKey(e){try{let t=await this.appSyncClient.getSession(e);if(t&&t.status===v.SessionStatus.INACTIVE){let r=new Error(`SESSION_TERMINAL: session ${e} is ${t.status}; stop retrying`);throw r.errorType="SessionTerminal",r}if(!t||t.status!==v.SessionStatus.ACTIVE||!t.isEncrypted)return null;let i=t.sessionKeyGen??null,s=t.encryptedKeys??[];if(s.length===0)return null;let n=await v.keychainManager.getSessionKey(e,s,i);return n?(c.info("[tool-activity] refreshed session key for SessionKeyStale retry (live key untouched)",{sessionId:e,sessionKeyGen:i}),{sessionKey:n,sessionKeyGen:i}):null}catch(t){if((0,v.isTerminalSessionError)(t))throw t;return c.warn("[tool-activity] session key refresh failed after SessionKeyStale (staying retryable)",{sessionId:e,error:String(t)}),null}}getToolActivityLegacyRecorder(e){let t=this.toolActivityLegacyRecorders.get(e);return t||(t=new v.ToolActivityLedger({agent:"codex",sessionId:e,logger:c}),this.toolActivityLegacyRecorders.set(e,t)),t}async ensureToolActivityStarted(e){if(!this.sessionState||!e)return;let t=this.sessionWatcher.getActiveLogFile()||this.sessionState.codexLogFile||void 0,i=this.toolActivity;if(i){t&&i.bindTranscript(t);return}if(this.toolActivityStartPromise){await this.toolActivityStartPromise,t&&this.toolActivity?.bindTranscript(t);return}if(!this.sessionKey)return;let s=this.sessionState.sessionId;this.toolActivityStartPromise=(async()=>{let n=this.buildToolActivityIntegration();try{await n.start(s,e,t),this.toolActivity=n}catch(r){throw await n.abortStart().catch(o=>{c.warn("[tool-activity] failed candidate cleanup retained",{backendSessionId:s,rolloutId:e,error:String(o)})}),this.toolActivityStartPromise=null,r}})().catch(n=>{c.warn("[tool-activity] failed to start codex consolidator (non-fatal)",{backendSessionId:s,rolloutId:e,error:String(n)})}),await this.toolActivityStartPromise,this.toolActivity?.isActive()&&this.sessionWatcher.retryActiveRead()}startMobileEndWatcher(e){!this.sessionState||this.sessionState.sessionId!==e||(this.sessionState.mobileEndWatcher=this.appSyncClient.watchForMobileEnd(e,async()=>{if(this.nativeAuthority){this.controlAdmission().invalidate(),this.nativeControlOwner?.adapter.stopAdmission(),this.appSyncClient.stopHeartbeat(e),this.appSyncClient.cleanupSubscription(e),process.send?.({type:"CODEVIBE_NATIVE_MOBILE_END",instanceId:this.nativeAuthority.record.instanceId});return}c.info("Mobile ended session \u2014 sending desktop quit",{sessionId:e}),this.appSyncClient.stopHeartbeat(e),this.appSyncClient.cleanupSubscription(e);try{await this.appSyncClient.updateSession({sessionId:e,status:v.SessionStatus.INACTIVE}),c.info("Marked session INACTIVE on mobile-end (before tmux terminate)",{sessionId:e})}catch(i){c.warn("Failed to mark session INACTIVE on mobile-end",{sessionId:e,error:i})}let t=process.env[we];if(!t){c.warn("No tmux session set; skipping desktop self-terminate",{sessionId:e,expectedEnv:we});return}await Gn(t,Un)}))}async endActiveSession(e,t=!0){if(!this.sessionState)return;let i=e,s=t,n=this.sessionState,r=this.nativeControlOwner?.state===n?this.nativeControlOwner:null;if(this.controlAdmission().invalidate(),r?.adapter.stopAdmission(),this.terminalInputBlockedStates.add(n),await this.terminalInputChain.catch(()=>{}),this.sessionState!==n){c.warn("Session changed while waiting for terminal-input teardown barrier",{endingSessionId:n.sessionId,currentSessionId:this.sessionState?.sessionId,reason:i});return}if(c.info("Ending active session",{sessionId:n.sessionId,codexSessionId:n.codexSessionId,reason:i}),this.sessionState.mobileEndWatcher&&(this.sessionState.mobileEndWatcher.stop(),this.sessionState.mobileEndWatcher=void 0),this.userDecisionUnsubscribe){try{this.userDecisionUnsubscribe()}catch(o){c.warn("Error invoking onApplyUserDecision unsubscribe (non-fatal)",{error:o})}this.userDecisionUnsubscribe=null}if(this.orchestrationClient){try{await this.orchestrationClient.destroy()}catch(o){c.warn("Error destroying OrchestrationClient (non-fatal)",{error:o})}this.orchestrationClient=null}this.v1Bridge.clear(),this.appSyncClient.stopHeartbeat(this.sessionState.sessionId),this.stopE1TtlRefresh(),this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null,this.subscribedSessionId=null,this.subscribedSessionState=null),this.nativeAuthority||await this.tmuxPaneObserver.stop();for(let o of this.deferredTmuxPromptCandidates.keys())o.sessionId===n.sessionId&&this.deferredTmuxPromptCandidates.delete(o);this.queuedPermissionRequestRegistrations.delete(n.sessionId),this.terminalRetirementRequested&&(i="shutdown",s=!0),i==="shutdown"&&this.sessionWatcher.stop(),this.toolActivityStartPromise&&(await this.toolActivityStartPromise.catch(()=>{}),this.toolActivityStartPromise=null),await this.logEntryChain.catch(()=>{}),await this.stopNativeSources(n),this.toolActivity&&(await this.toolActivity.stop(),this.toolActivity=null);for(let o of this.toolActivityLegacyRecorders.values())o.disposeLegacyCoordination();if(this.toolActivityLegacyRecorders.clear(),this.terminalRetirementRequested&&(i="shutdown",s=!0),r)if(i==="daemon-handoff")await r.adapter.join();else{let o=this.nativeRetirement?.predecessor===n;await r.adapter.close(i==="backend-generation-retired"||o?"BACKEND_REPLACED":"TERMINAL"),i==="backend-generation-retired"&&(this.nativeReplacementToken??=(0,Se.v4)(),await r.store.authorizeHandoff(r.owner,this.nativeReplacementToken,()=>r.adapter.join()))}!this.nativeAuthority&&i==="daemon-handoff"&&this.persistDaemonHandoffState(n),(i==="new-codex-session-started"||i==="shutdown")&&(await this.exactClearOpenE1ForLifecycleEnd(n.sessionId),await this.drainPendingE1ResolutionsForLifecycleEnd(),this.stopE1TtlRefresh()),i!=="backend-generation-retired"&&i!=="daemon-handoff"&&(this.permissionRequestOccurrencesByCompletionKey.clear(),this.waitingPermissionRequests.clear()),this.pendingInteractivePrompt=null,this.promptGeneration++,this.clearTmuxParseCache(),this.queuedInteractivePrompts=[],this.queuedQuestionCallIds.clear(),this.isInitializingSession=!1,this.bufferedLogEntries=[],Vt(),this.terminalRetirementRequested&&(s=!0),s?(this.retirementOwed=!0,await this.retireHostedSession(this.sessionState.sessionId,n),r&&(await r.store.retirePayloads(r.owner,r.owner.scope,()=>r.adapter.join(),o=>this.confirmNativeRetirement(o)),await r.store.pruneSettled(r.owner,r.owner.scope,o=>this.confirmNativeRetirement(o))),this.retirementOwed=!1,this.shutdownHostedRetirementUnconfirmed=!1):c.info("Preserving active backend session for daemon handoff",{sessionId:this.sessionState.sessionId}),this.sessionKey&&(v.keychainManager.clearSessionKey(this.sessionState.sessionId),this.sessionKey=null,this.sessionKeyGen=null),this.nativeRetirement?.predecessor===n&&this.nativeRetirement.stage==="retire"&&(this.nativeRetirement.stage="bootstrap"),i==="shutdown"&&(this.nativeRetirement=null),this.sessionState=null,this.nativeControlOwner===r&&(this.nativeControlOwner=null)}async boundedTeardownStep(e,t){await Gt(async()=>{try{await t()}catch(s){c.warn(`${e} failed`,{error:String(s)})}},3e3,()=>c.warn(`${e} timed out \u2014 continuing teardown without it`,{timeoutMs:3e3}))==="timeout"&&this.teardownStepsTimedOut.push(e)}isDurableObligationSettledForExit(){return!this.retirementOwed}getTeardownStepsTimedOut(){return[...this.teardownStepsTimedOut]}async confirmNativeRetirement(e){for(let t=1;t<=Ae;t+=1)try{return await this.appSyncClient.confirmDesktopSyncRetirement(e)}catch(i){if(!(i instanceof v.AppSyncGraphQLError)||i.errorType!=="SYNC_RETIREMENT_RETRY_AFTER"||t===Ae)throw i;c.warn("Native retirement proof deferred; retrying the same scope",{...Zt(i),sessionId:e.sessionId,sessionGenerationId:e.sessionGenerationId,attempt:t,maxAttempts:Ae}),await new Promise(s=>setTimeout(s,vs*t))}throw Error("NATIVE_RETIREMENT_RETRY_EXHAUSTED")}async retireHostedSession(e,t){jt("stall-retirement")&&(c.warn("[dev-fault] stall-retirement: this INACTIVE write will never settle",{sessionId:e}),await new Promise(()=>{}));let i;for(let s=1;s<=Ae;s+=1)try{let n=await this.appSyncClient.updateSession({sessionId:e,status:v.SessionStatus.INACTIVE});n?.sessionGenerationId&&await this.appSyncClient.completeDesktopSyncRetirement({sessionId:e,toolOutbox:new v.ToolActivityOutbox({agent:"codex",logger:c})},n,async()=>{await this.logEntryChain.catch(()=>{}),await this.stopNativeSources(t)});return}catch(n){i=n,c.warn("Failed to retire hosted Codex session",{sessionId:e,attempt:s,maxAttempts:Ae,error:n instanceof Error?n.message:String(n)}),s<Ae&&await new Promise(r=>setTimeout(r,vs*s))}throw new Error(`Failed to retire hosted Codex session ${e} after ${Ae} attempts: ${String(i)}`)}async cleanupDetachedWrapperArtifacts(){let e=process.env.CODEVIBE_CODEX_WRAPPER_PID;if(!e||!/^\d+$/.test(e))return;let t=process.env.TMPDIR||Ze.tmpdir(),i=[W.join(t,`codevibe-codex-server-${e}.pid`),W.join(t,`codevibe-codex-exit-${e}`),W.join(t,`codevibe-codex-tmux-session-${e}`)];for(let s of i)try{Pe.unlinkSync(s)}catch(n){n?.code!=="ENOENT"&&c.warn("Failed to remove detached-wrapper artifact",{ownedPath:s,error:String(n)})}}stop(e={}){return this.controlAdmission().invalidate(),this.nativeControlRecovery?.stop(),e.retireBackendSession!==!1&&(this.terminalRetirementRequested=!0,(this.sessionState!==null||this.shutdownHostedRetirementUnconfirmed)&&(this.retirementOwed=!0)),this.stopPromise?this.stopPromise:(this.stopPromise=this.doStop(),this.stopPromise)}async doStop(){c.info("Stopping CodeVibe Codex companion server"),this.stopTmuxLifecycleMonitor(),this.isStopping=!0,this.nativeControlOwner?.adapter.stopAdmission();let e=this.nativeRuntime?.close();this.nativeSourceRetryTimer&&clearTimeout(this.nativeSourceRetryTimer),this.nativeSourceRetryTimer=null,this.lifecycleGeneration+=1,this.sessionWatcher.stop();let t=this.launchSessionInitPromise,i=this.sessionStartedInitPromise,s=this.retiredSessionRecoveryPromise,n=this.hookEventChain,r=typeof this.sessionWatcher.waitForTranscriptAdmissions=="function"?this.sessionWatcher.waitForTranscriptAdmissions():Promise.resolve();this.teardownStepsTimedOut=[],await this.boundedTeardownStep("inFlightChains.join",()=>Promise.all([e?.catch(()=>{}),Promise.allSettled([...this.nativeReceiptWork?.values()??[]]),this.nativeMaintenance?.catch(()=>{}),t?.catch(()=>{}),i?.catch(()=>{}),s?.catch(()=>{}),r.catch(()=>{}),this.sessionWatcher.waitForReads().catch(()=>{}),n.catch(()=>{})]));try{let o=this.terminalRetirementRequested;this.shutdownHostedRetirementUnconfirmed=this.sessionState!==null,this.retirementOwed||=o&&this.shutdownHostedRetirementUnconfirmed;let d,l=!1;if(await Gt(async()=>{try{await this.endActiveSession(o?"shutdown":"daemon-handoff",o)}catch(h){l=!0,d=h}},1e4,()=>c.warn("endActiveSession timed out \u2014 continuing teardown without it",{timeoutMs:1e4,retirementOwed:this.retirementOwed}))==="timeout"&&this.teardownStepsTimedOut.push("endActiveSession"),l)throw d;this.sessionWatcher.stop(),this.approvalDetector?.shutdown(),Vt()}finally{this.httpApi&&await this.boundedTeardownStep("httpApi.stop",()=>this.httpApi.stop()),this.appSyncClient.cleanupSubscriptions(),this.terminalRetirementRequested&&!this.nativeAuthority&&await this.boundedTeardownStep("cleanupDetachedWrapperArtifacts",()=>this.cleanupDetachedWrapperArtifacts())}if(c.info("CodeVibe Codex companion server stopped"),this.retirementOwed)throw new Error("Session teardown timed out with the INACTIVE write still owed; the backend row may be stranded ACTIVE")}};require.main===module&&(async()=>{let a=process.env.CODEVIBE_CODEX_NATIVE_DESCRIPTOR,e=process.env.CODEVIBE_CODEX_NATIVE_INSTANCE;if(!a||!e)throw Error("Native launcher authority required;launch with codevibe --agent codex.");let t=await li(a,e),i=new At(t),s=!1,n=ns(r=>i.stop(r).catch(o=>{throw c.error("Native observer stop failed",Zt(o)),o}),()=>i.isDurableObligationSettledForExit(),r=>process.exit(r),()=>c.error("Native observer teardown exceeded its deadline"));process.once("disconnect",()=>n(!1)),process.on("message",r=>{let o=r;if(o?.type==="CODEVIBE_NATIVE_RECEIPT"||o?.type==="CODEVIBE_NATIVE_RECEIPTS_UNAVAILABLE"||o?.type==="CODEVIBE_NATIVE_RECEIPTS_READY"){i.receiveNativeReceipt(r);return}o?.type!=="CODEVIBE_NATIVE_TERMINAL_END"||o.instanceId!==t.record.instanceId||s||(s=!0,n(!0))});for(let r of Ss)process.on(r,()=>{c.info(`Received ${r}, evaluating terminal shutdown...`),(async()=>{if(i.hasNativeAuthority()){n(!1);return}let o;try{o=await i.shouldShutdownForTerminalSignal(r)}catch(l){c.error(`Failed to evaluate ${r} terminality; not shutting down`,{error:l instanceof Error?l.message:String(l)});return}if(!o)return;let d=Ne(l=>process.exit(l),()=>c.error("Shutdown watchdog fired \u2014 teardown did not complete in time; exiting anyway",{signal:r,watchdogMs:25e3,timedOutSteps:i.getTeardownStepsTimedOut(),durableObligationSettled:i.isDurableObligationSettledForExit()}),25e3,()=>i.isDurableObligationSettledForExit());try{await i.stop(),d(),process.exit(0)}catch(l){d(),c.error(`Failed to stop companion daemon after ${r}`,{error:l instanceof Error?l.message:String(l)}),process.exit(1)}})()});process.on("SIGUSR2",async()=>{c.info("Received SIGUSR2, handing off active session to replacement daemon...");let r=Ne(o=>process.exit(o),()=>c.error("Shutdown watchdog fired during SIGUSR2 handoff; exiting anyway",{watchdogMs:25e3,timedOutSteps:i.getTeardownStepsTimedOut()}),25e3,()=>i.isDurableObligationSettledForExit());try{await i.stop({retireBackendSession:!1})}catch(o){c.error("Handoff stop() failed; exiting anyway to free the session",{error:o instanceof Error?o.message:String(o)})}finally{r()}process.exit(0)}),(0,v.installDaemonProcessGuards)(c,{onFatal:()=>{let r=Ne(()=>process.exit(1),()=>c.error("Shutdown watchdog fired after a fatal guard; exiting anyway",{watchdogMs:25e3,timedOutSteps:i.getTeardownStepsTimedOut(),durableObligationSettled:i.isDurableObligationSettledForExit()}),25e3);i.stop({retireBackendSession:!i.hasNativeAuthority()}).finally(()=>{r(),process.exit(1)})}}),i.start().catch(r=>{c.error("Failed to start server:",r),process.exit(1)})})().catch(()=>{c.error("Native companion bootstrap failed"),process.exit(1)});0&&(module.exports={CodexCompanionServer,TERMINAL_SHUTDOWN_SIGNALS,TmuxPaneObserver,classifyTmuxHasSessionError,extractShellCommandFromPromptText,extractShellCommandPartsFromPromptText,nativeStopFailureFields,restoreCodexPersistOptionCommand,shellCommandPartsMatchExpected});