grix-connector 4.12.3 → 4.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/adapter/acp/acp-adapter.js +13 -13
  2. package/dist/adapter/acp/grok-liveness.js +3 -0
  3. package/dist/adapter/agy/agy-adapter.js +12 -12
  4. package/dist/adapter/agy/stream-parser.js +2 -0
  5. package/dist/adapter/claude/claude-adapter.js +22 -21
  6. package/dist/adapter/claude/claude-bridge-server.js +1 -1
  7. package/dist/adapter/claude/claude-tools.js +1 -1
  8. package/dist/adapter/claude/claude-worker-client.js +1 -1
  9. package/dist/adapter/claude/mcp-http-launcher.js +2 -2
  10. package/dist/adapter/claude/model-list.js +1 -1
  11. package/dist/adapter/claude/result-timeout.js +1 -1
  12. package/dist/adapter/claude/session-recovery.js +1 -0
  13. package/dist/adapter/codex/codex-bridge.js +12 -10
  14. package/dist/adapter/codex/wait-loop.js +1 -0
  15. package/dist/adapter/cursor/cursor-adapter.js +1 -1
  16. package/dist/adapter/cursor/fetch-usage.js +1 -1
  17. package/dist/adapter/cursor/index.js +1 -1
  18. package/dist/adapter/pi/pi-adapter.js +4 -4
  19. package/dist/assets/dsh-bridge/grix-dsh-bridge-4.14.0.tgz +0 -0
  20. package/dist/assets/dsh-bridge/manifest.json +5 -5
  21. package/dist/audit/adapters/codex/codex-audit-adapter.js +1 -1
  22. package/dist/bridge/adapter-pool.js +1 -1
  23. package/dist/bridge/bridge.js +2 -2
  24. package/dist/bridge/event-queue.js +1 -1
  25. package/dist/bridge/event-stop.js +1 -1
  26. package/dist/bridge/provider-quota.js +1 -1
  27. package/dist/bridge/rate-limits.js +1 -1
  28. package/dist/bridge/send-controller.js +3 -3
  29. package/dist/bridge/session-control-router.js +3 -3
  30. package/dist/bridge/tool-card-utils.js +1 -1
  31. package/dist/bridge/toolbar-meta.js +1 -1
  32. package/dist/bridge/toolbar-selection.js +1 -1
  33. package/dist/core/access/allowlist-store.js +1 -1
  34. package/dist/core/aibot/client.js +2 -2
  35. package/dist/core/config/claude-direct-env.js +1 -1
  36. package/dist/core/file-ops/list-files.js +1 -1
  37. package/dist/core/persistence/session-binding-store.js +2 -2
  38. package/dist/core/protocol/protocol-send.js +1 -0
  39. package/dist/core/provider-quota/grix-relay.js +1 -0
  40. package/dist/core/provider-quota/index.js +1 -1
  41. package/dist/core/proxy/index.js +1 -1
  42. package/dist/core/util/quoted-message-stream.js +3 -3
  43. package/dist/default-skills/grix-agent-dispatch/SKILL.md +37 -7
  44. package/dist/default-skills/grix-agent-dispatch/scripts/callback-dedupe.mjs +12 -0
  45. package/dist/grix.js +6 -6
  46. package/dist/log.js +2 -2
  47. package/dist/manager.js +1 -1
  48. package/dist/mcp/stream-http/config.js +1 -1
  49. package/dist/mcp/stream-http/connection-binding.js +1 -1
  50. package/dist/mcp/stream-http/tool-executor.js +1 -1
  51. package/dist/mcp/stream-http/tool-registry.js +1 -1
  52. package/dist/mcp/stream-http/tool-schemas.js +1 -1
  53. package/openclaw-plugin/audit-recorder-worker.js +37 -0
  54. package/openclaw-plugin/index.js +9 -3
  55. package/openclaw-plugin/skills/grix-agent-dispatch/SKILL.md +37 -7
  56. package/openclaw-plugin/skills/grix-agent-dispatch/scripts/callback-dedupe.mjs +12 -0
  57. package/package.json +1 -1
  58. package/dist/assets/dsh-bridge/grix-dsh-bridge-4.12.3.tgz +0 -0
@@ -1,14 +1,16 @@
1
- import{execFileSync as me}from"node:child_process";import{createInterface as ge}from"node:readline";import{EventEmitter as K}from"node:events";import{stat as Z}from"node:fs/promises";import{join as P,resolve as ve}from"node:path";import{fileURLToPath as Ie}from"node:url";import{syncDefaultSkillsToDir as xe}from"../../default-skills/index.js";import{resolveCommandPath as ye,resolveShimInvocation as we,spawnCommand as Te,killProcessGroup as Q,hasChildProcesses as _e}from"../../core/runtime/spawn.js";import{InternalApiServer as Ce}from"../../core/mcp/internal-api-server.js";import{resolveMcpServerName as be,LEGACY_MCP_SERVER_NAMES as Ae}from"../../core/mcp/server-name.js";import{formatInboundMessageReferenceText as Ee}from"../../core/protocol/message-reference.js";import{INBOUND_MESSAGE_ID_PROTOCOL_INSTRUCTION as L}from"../shared/inbound-message-id-injector.js";import{log as d}from"../../core/log/index.js";import{resolveClientVersion as Se}from"../../core/util/client-version.js";import{isThinkingAgentMessagePhase as N,isUserVisibleAgentMessagePhase as F}from"../../core/util/codex-output-policy.js";import{SessionBindingStore as Re}from"../../core/persistence/session-binding-store.js";import{ensureCodexProjectTrusted as Me,isCodexCommand as ke,readCodexProviderSettings as j,resolveCodexHome as Pe}from"./codex-trust.js";import{prepareCodexDirectHome as De}from"./direct-home.js";import{checkCodexSessionActivity as Oe,inspectCodexTurnProgress as $e}from"./session-activity.js";import{findRolloutFile as Le}from"./rollout-locator.js";import{checkCodexLock as ee}from"./lock-monitor.js";import{resolveCliPath as te,getCliVersion as Ne}from"../../core/util/cli-probe.js";import{scanSkills as Fe}from"../claude/skill-scanner.js";import{normalizeCodexConfigOverrides as ie}from"./config-overrides.js";import{buildCodexOpenAiCompatibleProviderOverrides as je,CODEX_RELAY_OPENAI_PROVIDER_ID as He,prepareCodexRawCapture as Ue,resolveCodexProviderName as qe,resolveCodexRawCaptureTarget as Be,resolveCodexProviderSupportsWebsocketsConfigKey as We}from"./raw-capture-hook.js";import{unavailableRawApiCaptureBoundary as ze}from"../../audit/raw-capture/capture-relay.js";const Ve=60*1e3,Ge=600*1e3,Xe="GRIX_RELAY_PROXY",Je=5*1e3,Ye=15*1e3,se=3;function H(a,e){const t=Number(process.env[a]);return Number.isFinite(t)&&t>0?t:e}function Ke(a){const e=Number(process.env[a]);return Number.isFinite(e)&&e>0?e:null}function Ze(a){if(!a||typeof a!="object"||Array.isArray(a))return;const e=a,t=typeof e.auditId=="string"?e.auditId.trim():"",i=typeof e.sessionId=="string"?e.sessionId.trim():"",s=typeof e.spoolRootDir=="string"?e.spoolRootDir.trim():"";return t&&i&&s?{auditId:t,sessionId:i,spoolRootDir:s}:void 0}const U=H("GRIX_CODEX_PREFLIGHT_STALL_TIMEOUT_MS",120*1e3),Qe=20,et=8e3,ne=2*1024,re=`
2
- \u2026(truncated)`,oe=80,tt=120*1e3,it=60*1e3,st=300*1e3,nt=H("GRIX_CODEX_DELTA_COALESCE_MS",1e3),rt=H("GRIX_CODEX_DELTA_COALESCE_CHARS",4096),ot=[{id:"gpt-5.3-codex",displayName:"GPT-5.3 Codex",defaultReasoningEffort:null,supportedReasoningEfforts:[],defaultServiceTier:null,serviceTiers:[],isDefault:!0}],ae=[{id:"default",displayName:"Default"},{id:"plan",displayName:"Plan"}],at=new Set(["rawResponse/completed","codex/rawResponse/completed","rawResponseItem/completed","codex/rawResponseItem/completed","thread/tokenUsage/updated","codex/thread/tokenUsage/updated","thread/compacted","codex/thread/compacted","turn/started","codex/turn/started","turn/completed","codex/turn/completed","item/started","codex/item/started","item/completed","codex/item/completed","error","codex/error"]);async function de(a,e){const t=String(a??"").trim()||"codex",i=ye(t,e);if(i!==t)return i;if(t==="codex"){const n=process.platform==="win32"?[]:["/opt/homebrew/bin/codex","/usr/local/bin/codex","/usr/bin/codex"],r=process.platform!=="win32"?[]:[P(process.env.LOCALAPPDATA??"","npm","codex.cmd"),P(process.env.APPDATA??"","npm","codex.cmd"),P(process.env.LOCALAPPDATA??"","Programs","codex","codex.exe")];for(const o of[...n,...r])try{return require("node:fs").accessSync(o,require("node:fs").constants.X_OK),o}catch{continue}}const s=await te(t);return s||(d.warn("codex-adapter",`resolveCodexCommandPath: failed to resolve "${t}" via PATH, codex fallbacks, or resolveCliPath. envPath=${e?"provided":"missing (using process.env.PATH)"}`),t)}class D extends K{type="codex";config;callbacks;process=null;alive=!1;stopped=!1;internalApi=null;bridgeStatus="starting";pendingRequests=new Map;requestId=0;threadId=null;initialized=!1;cwd;approvalPolicy;sandboxMode;model;collaborationMode;reasoningEffort;serviceTier;idleTimer=null;orphanTurnTimer=null;orphanTurnSince=0;lastProgressAt=0;lastIdleCheckAt=0;activityGeneration=0;lastIdleCheckGeneration=0;idleNoProgressCount=0;inFlightToolOps=0;consecutivePingFailures=0;currentTurnStartedAt=0;preflightCheckComplete=!1;turnInactivityTimeoutMs=Ke("GRIX_CODEX_TURN_INACTIVITY_TIMEOUT_MS");pendingApprovals=new Map;needsHistoryInjection=!1;lastInjectedSessionId=null;identityInputInjectedThreadId=null;protocolInstructionInputInjectedThreadId=null;legacyDeveloperInstructionsUnsupported=!1;profileIdentityRefreshPending=!1;bindingStore=null;aibotSessionId="";threadResumePending=!1;autoTrustProject="auto";codexHome;codexDirect=null;directEnv={};configOverrideArgs=[];rawCaptureOptions;rawCaptureRelay;rawCaptureConfigOverrides=[];rawCaptureUnavailableReason;codexModelOptions=[];codexModelOptionsCachedAt=0;static MODEL_CACHE_TTL_MS=3600*1e3;rateLimitSnapshot=null;lastNonDefaultLimitRefreshAt=0;static NON_DEFAULT_LIMIT_REFRESH_INTERVAL_MS=6e4;currentThreadTokenUsage=null;currentModelContextWindow=null;auditCaptureByEventId=new Map;constructor(e,t){super(),this.config=e,this.callbacks=t;const i=e.options??{};this.approvalPolicy=i.approvalPolicy??"never",this.sandboxMode=typeof i.sandboxMode=="string"&&i.sandboxMode.trim()&&i.sandboxMode.trim()!=="default"?i.sandboxMode.trim():void 0,this.aibotSessionId=String(i.aibotSessionId??"").trim(),this.bindingStore=i.bindingStore instanceof Re?i.bindingStore:null,this.model=i.model,this.collaborationMode=i.collaborationMode,this.reasoningEffort=i.reasoningEffort,this.serviceTier=i.serviceTier,this.bindingStore&&this.aibotSessionId&&(this.model=this.model??this.bindingStore.getCodexModelId(this.aibotSessionId),this.collaborationMode=this.collaborationMode??this.bindingStore.getCodexModeId(this.aibotSessionId),this.reasoningEffort=this.reasoningEffort??this.bindingStore.getCodexReasoningEffort(this.aibotSessionId),this.serviceTier=this.serviceTier??this.bindingStore.getCodexServiceTier(this.aibotSessionId),this.sandboxMode=this.sandboxMode??this.bindingStore.getCodexSandboxMode(this.aibotSessionId)),this.autoTrustProject=typeof i.autoTrustProject=="boolean"?i.autoTrustProject:"auto",this.codexHome=typeof i.codexHome=="string"&&i.codexHome.trim()?i.codexHome.trim():void 0;const s=i.codexDirect;if(this.codexDirect=s&&typeof s=="object"&&!Array.isArray(s)?s:null,this.configOverrideArgs=ie(i.codexConfigOverrides,"codexConfigOverrides"),this.rawCaptureOptions=Ze(i.rawApiCapture),this.cwd=this.resolveCwd(),this.bindingStore&&this.aibotSessionId){const n=this.bindingStore.getCodexThreadId(this.aibotSessionId);n&&(this.threadId=n,this.threadResumePending=!0)}}resolveCwd(){if(this.bindingStore&&this.aibotSessionId){const e=this.bindingStore.get(this.aibotSessionId);if(e?.cwd)return e.cwd}return process.cwd()}async start(){await this.prepareDirectHome(),await this.ensureProjectTrusted(),await this.prepareRawApiCapture();try{await this.startInternalApiAndRegisterMcp(),await this.spawnCodex(),await this.initializeHandshake(),await this.notifyBindingReadyWithContext(),d.info("codex-adapter",`Ready (pid=${this.process?.pid})`)}catch(e){throw await this.stopRawApiCapture(),e}}async prepareRawApiCapture(){if(this.rawCaptureOptions)try{const e=await Ue(this.rawCaptureOptions,{adapterType:"codex",sessionId:this.rawCaptureOptions.sessionId,cwd:this.cwd,env:this.resolveChildEnv(),configOverrides:this.configOverrideArgs,codexHome:this.codexHome});this.rawCaptureRelay=e.relay,this.rawCaptureConfigOverrides=e.overlay.configOverrides??[],this.rawCaptureUnavailableReason=void 0,d.info("codex-adapter","Raw API audit capture relay is ready")}catch(e){this.rawCaptureRelay=void 0,this.rawCaptureConfigOverrides=[],this.rawCaptureUnavailableReason=e instanceof Error?e.message:String(e),d.warn("codex-adapter",`Raw API audit capture unavailable: ${this.rawCaptureUnavailableReason}`)}}async stopRawApiCapture(){const e=this.rawCaptureRelay;this.rawCaptureRelay=void 0,this.rawCaptureConfigOverrides=[],e&&await e.stop()}async prepareDirectHome(){if(!this.codexDirect)return;const e=await De(this.codexDirect);this.codexHome=e.codexHome,this.directEnv=e.env;const t=ie(e.configOverrides,"codexDirect.configOverrides");this.configOverrideArgs=[...this.configOverrideArgs,...t],d.info("codex-adapter",`Codex direct home ready: ${e.codexHome} (catalog=${e.catalogVersion??"none"}, token=${e.tokenDigest?`present sha256:${e.tokenDigest}`:"absent"})`)}resolveChildEnv(){const e={...process.env,...this.config.env};return this.codexHome&&(e.CODEX_HOME=this.codexHome),e}async ensureProjectTrusted(){if(this.shouldAutoTrustProject())try{const e=await Me(this.cwd,{codexHome:this.codexHome});e.changed&&d.info("codex-adapter",`Trusted Codex project ${this.cwd} in ${e.configPath}`)}catch(e){const t=e instanceof Error?e.message:String(e);throw d.error("codex-adapter",`Failed to trust Codex project ${this.cwd}: ${t}`),e}}async startInternalApiAndRegisterMcp(){try{this.internalApi=new Ce,this.internalApi.setInvokeHandler(async(c,h,p,f)=>this.callbacks.agentInvoke(c,h,f)),await this.internalApi.start(0),d.info("codex-adapter",`Internal API started at ${this.internalApi.url}`);const e=this.getMcpConfig(),t=this.resolveChildEnv(),i=typeof t.PATH=="string"?t.PATH:void 0,s=await de(this.config.command||"codex",i),n=c=>{const h=we(s,c);me(h.command,h.args,{env:t,timeout:1e4,stdio:"ignore",windowsHide:!0,windowsVerbatimArguments:h.windowsVerbatimArguments})};for(const c of[...Ae,e.name])try{n(["mcp","remove",c])}catch{}n(["mcp","add",e.name,"--",e.command,...e.args]),d.info("codex-adapter",`Registered MCP server: ${e.name}`);const r=P(Pe(this.codexHome),"skills"),o=xe(r);o.length>0&&d.info("codex-adapter",`Synced connector skills to ${r}: [${o.join(", ")}]`)}catch(e){d.warn("codex-adapter",`Failed to register MCP tools (non-fatal): ${e instanceof Error?e.message:String(e)}`)}}shouldAutoTrustProject(){return this.autoTrustProject===!1?!1:this.autoTrustProject===!0?!0:ke(this.config.command)}notifyBindingReady(){!this.aibotSessionId||!this.cwd||this.callbacks.sendUpdateBindingCard(this.aibotSessionId,"ready",this.cwd)}async notifyBindingReadyWithContext(){if(!(!this.aibotSessionId||!this.cwd))try{this.callbacks.sendUpdateBindingCard(this.aibotSessionId,"ready",this.cwd,await this.buildToolbarContextResult("binding_ready"))}catch(e){d.warn("codex-adapter",`Failed to attach toolbar context to binding update: ${e instanceof Error?e.message:String(e)}`),this.notifyBindingReady()}}scheduleToolbarContextPush(){this.notifyBindingReadyWithContext()}externalProviderCheckedAt=0;externalProviderCached=!1;static EXTERNAL_PROVIDER_CACHE_TTL_MS=60*1e3;isExternalProvider(){const e=Date.now();if(e-this.externalProviderCheckedAt<D.EXTERNAL_PROVIDER_CACHE_TTL_MS)return this.externalProviderCached;const t=j(this.codexHome);return this.externalProviderCached=!!(t.baseUrl&&ue(t.baseUrl)),this.externalProviderCheckedAt=e,this.externalProviderCached}effectiveServiceTier(){if(!this.serviceTier||this.serviceTier.trim().toLowerCase()==="default"||this.isExternalProvider())return;const e=this.getModelOption(this.currentModelId());if(!(e&&!e.serviceTiers.some(t=>t.id===this.serviceTier)))return this.serviceTier}resolveReasoningEffortForModel(e,t,i={}){const s=String(e??"").trim();if(!s||this.isExternalProvider())return;const n=this.getModelOption(t),r=n?.supportedReasoningEfforts??[];if(r.length===0)return;const o=r.find(c=>c.trim().toLowerCase()===s.toLowerCase());if(o)return o;if(!i.strict&&["max","ultra"].includes(s.toLowerCase())){const c=r.find(h=>h.trim().toLowerCase()==="xhigh");if(c)return c}return i.strict?void 0:n?.defaultReasoningEffort??void 0}effectiveReasoningEffort(){return this.resolveReasoningEffortForModel(this.reasoningEffort,this.currentModelId())}getEffortMeta(){if(this.isExternalProvider())return{};const e=this.currentModelId(),t=this.getModelOption(e),i={},s=t?.supportedReasoningEfforts??[];s.length>0&&(i.available_efforts=s,i.reasoning_effort=this.effectiveReasoningEffort()??t?.defaultReasoningEffort??null);const n=t?.serviceTiers??[];return n.length>0&&(i.available_service_tiers=n,i.service_tier=this.effectiveServiceTier()??t?.defaultServiceTier??null),i}async stop(){this.stopped=!0,this.alive=!1,this.stopComposing(),this.clearIdleTimer(),this.stopOrphanTurnWatch(),this.currentTurnId=null,this.rejectAllPending("adapter stopped"),this.pendingAutoCompact=!1,this.compacting=!1,this.compactingTimer&&(clearTimeout(this.compactingTimer),this.compactingTimer=null);for(const t of this.compactionDeferred.splice(0))this.sendEventResultAfterFlushing(t.event_id,"failed","adapter stopped");for(const t of this.steerDeferred.splice(0))this.sendEventResultAfterFlushing(t.event_id,"failed","adapter stopped");this.internalApi&&(await this.internalApi.stop(),this.internalApi=null);const e=this.process;if(this.process=null,e?.pid&&typeof e.once=="function")Q(e,"SIGTERM"),await Promise.race([new Promise(i=>{e.once("exit",()=>i(!0))}),new Promise(i=>{setTimeout(()=>i(!1),5e3)})])||Q(e,"SIGKILL");else if(e)try{e.kill("SIGTERM")}catch{}await this.stopRawApiCapture()}isAlive(){return this.alive}async createSession(e){if(this.initialized||await this.initializeHandshake(),this.threadId||await this.startNewThread(),!this.threadId)throw new Error("Failed to create session: thread ID is missing");return await this.notifyBindingReadyWithContext(),this.threadId}async resumeSession(e,t){await this.ensureThreadResumed()}async destroySession(e){this.threadId=null,this.threadResumePending=!1,this.persistThreadId(void 0),this.protocolInstructionInputInjectedThreadId=null}sendPrompt(e){const t=new z(e.adapterSessionId);return this.runTurn(e,t).catch(i=>{t.emitError(i instanceof Error?i:new Error(String(i)))}),t}async cancel(e){if(this.threadId)try{await this.sendRequest("turn/interrupt",{threadId:this.threadId,turnId:this.currentTurnId??""},5e3)}catch{}}setPermissionHandler(e){this.permissionHandler=e}permissionHandler=null;async ping(e){if(!this.alive||!this.process)return!1;if(!this.process.pid){const t=!!(this.process.stdin&&!this.process.stdin.destroyed),i=!!(this.process.stdout&&!this.process.stdout.destroyed);return t&&i}if(!this.process.stdin||this.process.stdin.destroyed)return!!(this.process.stdout&&!this.process.stdout.destroyed);try{const t=++this.requestId,i={jsonrpc:"2.0",id:t,method:"ping",params:{}};return await new Promise(s=>{const n=setTimeout(()=>{this.pendingRequests.delete(String(t)),s(!1)},e);this.pendingRequests.set(String(t),{resolve:()=>s(!0),reject:()=>s(!1),timer:n}),this.process.stdin.write(`${JSON.stringify(i)}
3
- `)})}catch{return!1}}getStatus(){return{alive:this.alive,busy:this.currentTurnId!==null||this.compacting,sessions:this.threadId?1:0}}getActiveEventIds(){return this.activeEventId?[this.activeEventId]:[]}clearActiveEventForShutdown(){this.clearIdleTimer(),this.clearCodexDeltaBuffer(),this.activeEventId=null}setModel(e){this.model=e,this.reasoningEffort=this.resolveReasoningEffortForModel(this.reasoningEffort,this.currentModelId()),this.persistCodexContext(),d.info("codex-adapter",`Model set to: ${e}`),this.scheduleToolbarContextPush()}setMode(e){const t=k(e);if(!t){d.info("codex-adapter",`Ignoring unsupported mode: ${e}`);return}this.collaborationMode=t,this.persistCodexContext(),d.info("codex-adapter",`Mode set to: ${t}`),this.scheduleToolbarContextPush()}setReasoningEffort(e){const t=this.resolveReasoningEffortForModel(e,this.currentModelId(),{strict:!0});if(!t){d.info("codex-adapter",`Ignoring unsupported reasoning effort for ${this.currentModelId()}: ${e}`);return}this.reasoningEffort=t,this.persistCodexContext(),d.info("codex-adapter",`Reasoning effort set to: ${t}`)}setServiceTier(e){const t=e.trim();this.serviceTier=t.toLowerCase()==="default"?"default":t,this.persistCodexContext(),d.info("codex-adapter",`Service tier set to: ${this.serviceTier}`)}setSandboxMode(e){this.sandboxMode=e,this.persistCodexContext(),d.info("codex-adapter",`Sandbox mode set to: ${e} (applied on next restart)`)}async threadCompact(){if(!this.threadId)throw new Error("No active thread");return this.sendRequest("thread/compact/start",{threadId:this.threadId},12e4)}async threadRollback(e){if(!this.threadId)throw new Error("No active thread");return this.sendRequest("thread/rollback",{threadId:this.threadId,numTurns:e},1e4)}getThreadId(){return this.threadId}hasRawApiCaptureRelay(){return!!this.rawCaptureRelay}enableAuditCapture(e,t={}){const i=e.trim();if(!i||this.auditCaptureByEventId.has(i))return;const s=t.rawProviderBody??!!this.rawCaptureOptions;this.auditCaptureByEventId.set(i,{threadId:this.threadId??void 0,modelId:this.currentModelId()??void 0,rawProviderBody:s,sequence:0,events:[]}),s&&this.rawCaptureRelay?.beginEvent(i,t.auditId)}takeAuditBoundary(e){const t=this.auditCaptureByEventId.get(e);if(t)return this.auditCaptureByEventId.delete(e),{adapterType:this.type,providerTurnId:t.providerTurnId,threadId:t.threadId??this.threadId??void 0,codexEvidence:{events:t.events,...t.modelId?{modelId:t.modelId}:{},...t.rawProviderBody?{rawApiCapture:this.rawCaptureRelay?this.rawCaptureRelay.takeEvent(e):ze(this.rawCaptureUnavailableReason??"raw_capture_relay_not_prepared_before_adapter_start")}:{}}}}getMcpConfig(){if(!this.internalApi)return null;const e=ve(Ie(import.meta.url),"../../../mcp/acp-mcp-server.js");return{name:be(this.callbacks.getAgentId?.()),command:process.execPath,args:[e,"--api-url",this.internalApi.url]}}async hasBackgroundWork(){const e=this.process?.pid;return e?_e(e,[e]):!1}onAgentProfileChanged(){this.threadId&&(this.profileIdentityRefreshPending=!0,this.identityInputInjectedThreadId=null,d.info("codex-adapter",`agent profile changed; scheduling identity refresh for thread=${this.threadId}`))}async probe(e){const t=this.config.command||"codex",i=await te(t),s=i!==null;let n=null,r;if(s){const v=await Ne(t);n=v.version,v.error&&(r=v.error)}else r={code:"cli_not_found",message:`command not found: ${t}`};const c=j(this.codexHome).baseUrl??null,h=this.currentModelId()||null,p=this.getStatus(),f=e?.conversation?{attempted:!0,ok:!1,latency_ms:null,error:{code:"unsupported",message:"codex does not support minimal prompt probe"}}:{attempted:!1,ok:!1,latency_ms:null},g=await this.probeSessionRecord(),y=ee({codexHome:this.codexHome});return{cli:{command:t,installed:s,path:i,version:n,...r?{error:r}:{}},conversation:f,config:{model:h,base_url:c,source:{model:h?"runtime":"unknown",base_url:c?"file":"unknown"}},process:{started:!!this.process,alive:p.alive,busy:p.busy},session:g,lock:{present:y.present,locked:y.locked,stale:y.stale,path:y.path}}}async probeSessionRecord(){const e=this.threadId?Le(this.threadId,this.codexHome):null;if(!e)return{recordPath:null,lastActivityMs:null,freshMs:null};try{const t=await Z(e);return{recordPath:e,lastActivityMs:t.mtimeMs,freshMs:Date.now()-t.mtimeMs}}catch{return{recordPath:e,lastActivityMs:null,freshMs:null}}}getSupportedCommands(){return[{name:"compact",description:"Compact thread to reduce context size"},{name:"model",description:"List or set model",args:"[model_id]"},{name:"mode",description:"List or set collaboration mode",args:"[default|plan]"},{name:"rollback",description:"Roll back thread turns",args:"[num_turns]"},{name:"interrupt",description:"Interrupt current turn"},{name:"rate_limits",description:"Show current rate limits"},{name:"status",description:"Show thread and session status"},{name:"skills",description:"List available skills"}]}async execCommand(e,t,i){try{switch(e){case"compact":{if(!this.threadId)return{status:"failed",message:"No active thread"};if(this.compacting)return{status:"failed",message:"Compaction already in progress"};if(this.currentTurnId&&(await this.cancel(this.threadId).catch(()=>{}),this.activeEventId&&this.sendEventResultAfterFlushing(this.activeEventId,"canceled","compacting"),this.clearActive()),await this.ensureThreadResumed(),this.currentTurnId)return{status:"failed",message:"agent busy"};if(this.needsHistoryInjection)return{status:"failed",message:"The session has expired and there is no history to compact. Please send a new message and try again."};this.compacting=!0;const s=new Promise(n=>{this.compactionDoneResolver=n});try{return await this.threadCompact(),this.armCompactionFallback(),await s,{status:"ok",message:"Thread compacted"}}catch(n){this.finishCompaction("compact-error");const r=n instanceof Error?n.message:String(n);if(/thread.*(not found|not exist|unknown|invalid)/i.test(r)||/not found.*thread/i.test(r))return this.threadId=null,this.persistThreadId(void 0),{status:"failed",message:"The session has expired and there is no history to compact. Please send a new message and try again."};throw n}}case"model":{const s=t.trim();return s?this.getModelOptions().some(r=>r.id===s)?(this.setModel(s),{status:"ok",message:`Model set to ${s}`}):{status:"failed",message:`Unknown model: ${s}`}:{status:"ok",message:`Current: ${this.currentModelId()}`,data:{models:this.getModelOptions()}}}case"mode":{const s=t.trim();if(s){const n=k(s);return n?(this.setMode(n),{status:"ok",message:`Mode set to ${n}`}):{status:"failed",message:`Unknown mode: ${s}. Supported: default, plan`}}return{status:"ok",message:`Current: ${this.collaborationMode??"default"}`,data:{modes:ae}}}case"rollback":{if(!this.threadId)return{status:"failed",message:"No active thread"};const s=Math.max(1,parseInt(t.trim(),10)||1);return this.currentTurnId&&(await this.cancel(this.threadId).catch(()=>{}),this.activeEventId&&this.sendEventResultAfterFlushing(this.activeEventId,"canceled","rolled back"),this.clearActive()),await this.threadRollback(s),{status:"ok",message:`Rolled back ${s} turn(s)`}}case"interrupt":return this.threadId?(await this.cancel(this.threadId),this.activeEventId&&this.sendEventResultAfterFlushing(this.activeEventId,"canceled","interrupted"),this.clearActive(),{status:"ok",message:"Turn interrupted"}):{status:"failed",message:"No active thread"};case"rate_limits":return{status:"ok",message:this.rateLimitSnapshot?`Primary: ${this.rateLimitSnapshot.primary.usedPercent.toFixed(1)}%, Secondary: ${this.rateLimitSnapshot.secondary.usedPercent.toFixed(1)}%`:"Rate limits not available",data:{rateLimits:this.rateLimitSnapshot}};case"status":return{status:"ok",message:`Thread: ${this.threadId??"none"}, Model: ${this.currentModelId()}, Mode: ${this.collaborationMode??"default"}`,data:{threadId:this.threadId,model:this.currentModelId(),mode:this.collaborationMode??"default",cwd:this.cwd,alive:this.alive}};case"skills":{const s=Fe({mode:"codex",projectDir:this.cwd}),n=s.map(r=>`- ${r.name}${r.trigger?` (${r.trigger})`:""}: ${r.description}`);return{status:"ok",message:n.length>0?n.join(`
4
- `):"No skills found",data:s}}default:return{status:"unsupported",message:`Unknown command: ${e}`}}}catch(s){return{status:"failed",message:s instanceof Error?s.message:String(s)}}}async handleLocalAction(e){const t=e.action_type??"",i=e.params??{};switch(d.info("codex-adapter",`handleLocalAction action_type=${t} action_id=${e.action_id} session_id=${i.session_id??""}`),t){case"set_model":{const s=x(u(i.model_id),u(i.modelId),u(i.value));return s&&this.setModel(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("model_set")),{handled:!0,kind:"set_model"}}case"set_mode":{const s=i.mode_id;return s&&this.setMode(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("mode_set")),{handled:!0,kind:"set_mode"}}case"set_reasoning_effort":{const s=x(u(i.reasoning_effort),u(i.reasoning_eff),u(i.effort)),n=this.resolveReasoningEffortForModel(s,this.currentModelId(),{strict:!0});if(!n){const r=this.getModelOption(this.currentModelId())?.supportedReasoningEfforts??[];return this.callbacks.sendLocalActionResult(e.action_id,"failed",{outcome:"effort_rejected",model_id:this.currentModelId(),available_efforts:r},"unsupported_reasoning_effort",r.length>0?`reasoning_effort must be one of: ${r.join(", ")}`:`reasoning_effort is not supported by model ${this.currentModelId()}`),{handled:!0,kind:"set_reasoning_effort_rejected"}}return this.setReasoningEffort(n),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("effort_set",!1)),{handled:!0,kind:"set_reasoning_effort"}}case"set_service_tier":{const s=x(u(i.service_tier),u(i.serviceTier),u(i.value));return s&&this.setServiceTier(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("service_tier_set",!1)),{handled:!0,kind:"set_service_tier"}}case"set_sandbox_mode":{const s=x(u(i.sandbox_mode),u(i.sandboxMode),u(i.value));return s&&this.setSandboxMode(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("sandbox_mode_set",!1)),{handled:!0,kind:"set_sandbox_mode"}}case"thread_compact":{d.info("codex-adapter",`thread_compact start action_id=${e.action_id} threadId=${this.threadId}`),this.currentTurnId&&(await this.cancel(this.threadId).catch(()=>{}),this.activeEventId&&this.sendEventResultAfterFlushing(this.activeEventId,"canceled","compacting"),this.clearActive());try{if(await this.ensureThreadResumed(),this.needsHistoryInjection)return d.info("codex-adapter",`thread_compact aborted: thread expired, new thread created action_id=${e.action_id}`),this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"thread_expired","The session has expired and there is no history to compact. Please send a new message and try again."),{handled:!0,kind:"thread_compact"};this.compacting=!0;const s=new Promise(n=>{this.compactionDoneResolver=n});await this.threadCompact(),this.armCompactionFallback(),await s,d.info("codex-adapter",`thread_compact done action_id=${e.action_id}`),this.callbacks.sendLocalActionResult(e.action_id,"ok")}catch(s){this.finishCompaction("compact-error");const n=s instanceof Error?s.message:String(s);/thread.*(not found|not exist|unknown|invalid)/i.test(n)||/not found.*thread/i.test(n)?(d.warn("codex-adapter",`thread_compact thread expired, resetting threadId action_id=${e.action_id} err=${n}`),this.threadId=null,this.persistThreadId(void 0),this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"thread_expired","The session has expired and there is no history to compact. Please send a new message and try again.")):(d.info("codex-adapter",`thread_compact failed action_id=${e.action_id} err=${n}`),this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,void 0,n))}return{handled:!0,kind:"thread_compact"}}case"get_context":return this.callbacks.sendLocalActionResult(e.action_id,"ok",{threadId:this.threadId,model:this.model,mode:this.collaborationMode,approvalPolicy:this.approvalPolicy,cwd:this.cwd,...await this.buildToolbarContextResult("context")}),{handled:!0,kind:"get_context"};case"exec_approve":case"file_approve":{const s=this.resolvePendingApproval(e);if(!s)return this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"unknown_or_expired_approval_id","That approval request is no longer pending."),{handled:!0,kind:t};const n=i.decision||"allow-once",r=ce[n]??"accept";return this.sendApprovalDecision(s.requestId,r),this.pendingApprovals.delete(s.approvalId),this.callbacks.sendLocalActionResult(e.action_id,"ok",{approval_id:s.approvalId,approval_command_id:s.approvalCommandId,decision:n}),this.resumeAfterApproval(e,i,s),{handled:!0,kind:t}}case"exec_reject":case"file_reject":{const s=this.resolvePendingApproval(e);return s?(this.sendApprovalDecision(s.requestId,"deny"),this.pendingApprovals.delete(s.approvalId),this.callbacks.sendLocalActionResult(e.action_id,"ok",{approval_id:s.approvalId,approval_command_id:s.approvalCommandId,decision:"deny"}),this.resumeAfterApproval(e,i,s),{handled:!0,kind:t}):(this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"unknown_or_expired_approval_id","That approval request is no longer pending."),{handled:!0,kind:t})}case"permission_approve":{const s=this.resolvePendingApproval(e);return!s||s.kind!=="permission"?(this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"unknown_or_expired_approval_id","That permission approval request is no longer pending."),{handled:!0,kind:t}):(this.sendApprovalDecision(s.requestId,"accept"),this.pendingApprovals.delete(s.approvalId),this.callbacks.sendLocalActionResult(e.action_id,"ok",{approval_id:s.approvalId,decision:"approve"}),this.resumeAfterApproval(e,i,s),{handled:!0,kind:t})}case"permission_reject":{const s=this.resolvePendingApproval(e);return!s||s.kind!=="permission"?(this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"unknown_or_expired_approval_id","That permission approval request is no longer pending."),{handled:!0,kind:t}):(this.sendApprovalDecision(s.requestId,"deny"),this.pendingApprovals.delete(s.approvalId),this.callbacks.sendLocalActionResult(e.action_id,"ok",{approval_id:s.approvalId,decision:"deny"}),this.resumeAfterApproval(e,i,s),{handled:!0,kind:t})}case"turn_interrupt":{try{await this.cancel(this.threadId??""),this.callbacks.sendLocalActionResult(e.action_id,"ok")}catch(s){this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,void 0,s instanceof Error?s.message:String(s))}return{handled:!0,kind:"turn_interrupt"}}case"thread_rollback":{const s=Number(i.numTurns??i.num_turns??1);if(!this.threadId)return this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"no_thread","No active thread"),{handled:!0,kind:"thread_rollback"};this.currentTurnId&&(await this.cancel(this.threadId).catch(()=>{}),this.activeEventId&&this.sendEventResultAfterFlushing(this.activeEventId,"canceled","rolled back"),this.clearActive());try{await this.threadRollback(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",{numTurns:s})}catch(n){this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,void 0,n instanceof Error?n.message:String(n))}return{handled:!0,kind:"thread_rollback"}}case"get_rate_limits":{const s=this.rateLimitSnapshot,n=this.buildContextWindowSnapshot(),r=Date.now(),o=this.currentThreadTokenUsage;return s?d.info("codex-adapter",`[rate-limits] responding: primary=${s.primary.usedPercent.toFixed(1)}% window=${s.primary.windowMinutes}min resetsAt=${s.primary.resetsAt} secondary=${s.secondary.usedPercent.toFixed(1)}% window=${s.secondary.windowMinutes}min resetsAt=${s.secondary.resetsAt}`):d.info("codex-adapter","[rate-limits] responding: no rateLimitSnapshot available"),d.debug("codex-adapter",`[cp-diagnose] get_rate_limits: threadId=${this.threadId??"-"} contextWindow=${JSON.stringify(n)} tokenUsage=${JSON.stringify(o)}`),this.callbacks.sendLocalActionResult(e.action_id,"ok",{adapterType:"codex",available:s!==null,cached:!1,sampledAt:r,rateLimits:s,contextWindow:n,tokenUsage:o}),{handled:!0,kind:"get_rate_limits"}}default:return{handled:!1,kind:""}}}async buildToolbarContextResult(e,t=!0){t&&await this.refreshCodexModelOptions();const i=k(this.collaborationMode)??"default",s=this.currentModelId(),n=this.getModelOption(s),r=this.getModelOptions(),o=ae,c=this.effectiveReasoningEffort()??n?.defaultReasoningEffort??null,h=n?.supportedReasoningEfforts??[],p=this.effectiveServiceTier()??n?.defaultServiceTier??null,f=n?.serviceTiers??[],g=this.isExternalProvider(),y=g?[]:h,v=g?null:c,w=g?[]:f,R=g?null:p,C={outcome:e,session_context:{modelId:s,modeId:i,reasoningEffort:v,serviceTier:R,approvalPolicy:this.approvalPolicy,sandboxMode:this.sandboxMode??null},model_id:s,mode_id:i,currentModelId:s,currentModeId:i,available_models:r,available_modes:o,available_efforts:y,availableModels:r,availableModes:o,reasoning_effort:v,available_service_tiers:w,service_tier:R,sandbox_mode:this.sandboxMode??null,models:r.map(T=>({modelId:T.id,name:T.displayName})),modes:o.map(T=>({id:T.id,name:T.displayName}))};return this.rateLimitSnapshot&&(C.rate_limit_primary_percent=this.rateLimitSnapshot.primary.usedPercent,C.rate_limit_secondary_percent=this.rateLimitSnapshot.secondary.usedPercent,C.rate_limit_primary_window_min=this.rateLimitSnapshot.primary.windowMinutes,C.rate_limit_secondary_window_min=this.rateLimitSnapshot.secondary.windowMinutes),C}currentModelId(){const e=String(this.model??"").trim();if(e)return e;const t=this.getModelOptions();return t.find(i=>i.isDefault)?.id??t[0]?.id??""}getModelOption(e){const t=e.trim().toLowerCase();return this.getModelOptions().find(i=>i.id.trim().toLowerCase()===t)}getModelOptions(){const e=this.config.options??{},t=e.available_models??e.availableModels??e.models,i=ft(t),s=this.codexModelOptions,n=[],r=String(this.model??"").trim(),o=r&&!s.some(f=>f.id.trim().toLowerCase()===r.toLowerCase()),c=s.length>0?s:o?[]:ot;if(r){const f=[...s,...i].find(g=>g.id.trim().toLowerCase()===r.toLowerCase());n.push({id:r,displayName:f?.displayName??S(r),defaultReasoningEffort:f?.defaultReasoningEffort??null,supportedReasoningEfforts:f?.supportedReasoningEfforts??[],defaultServiceTier:f?.defaultServiceTier??null,serviceTiers:f?.serviceTiers??[],isDefault:f?.isDefault??!1})}n.push(...i),n.push(...c);const h=[],p=new Set;for(const f of n){const g=f.id.trim(),y=g.toLowerCase();!g||p.has(y)||(p.add(y),h.push({id:g,displayName:f.displayName.trim()||g,defaultReasoningEffort:f.defaultReasoningEffort,supportedReasoningEfforts:[...f.supportedReasoningEfforts],defaultServiceTier:f.defaultServiceTier,serviceTiers:[...f.serviceTiers],isDefault:f.isDefault}))}return h}async refreshCodexModelOptions(){if(!this.initialized||!this.alive||!this.process?.stdin||Date.now()-this.codexModelOptionsCachedAt<D.MODEL_CACHE_TTL_MS)return;const e=j(this.codexHome);if(e.baseUrl&&ue(e.baseUrl)){try{const t=await gt(e.baseUrl,e.apiKey);if(t.length>0){this.codexModelOptions=he(t),this.codexModelOptionsCachedAt=Date.now(),d.info("codex-adapter",`Loaded ${t.length} models from external provider ${e.baseUrl}`);return}}catch(t){d.warn("codex-adapter",`External provider /v1/models failed (${t instanceof Error?t.message:String(t)})`)}if(!mt(e.baseUrl)){this.codexModelOptions=[],this.codexModelOptionsCachedAt=Date.now();return}d.info("codex-adapter",`External provider ${e.baseUrl} returned no models; falling back to Codex model/list`)}try{const t=[];let i;do{const s=await this.sendRequest("model/list",{cursor:i??null,includeHidden:!1,limit:100},15e3),n=It(s);t.push(...n.models),i=n.nextCursor}while(i);t.length>0&&(this.codexModelOptions=he(t),this.codexModelOptionsCachedAt=Date.now())}catch(t){d.warn("codex-adapter",`Failed to load Codex model list: ${t instanceof Error?t.message:String(t)}`)}}currentTurnId=null;compacting=!1;pendingAutoCompact=!1;compactionDeferred=[];steerDeferred=[];compactingTimer=null;compactionDoneResolver=null;activeEventId=null;activeSessionId=null;visibleAgentMessageIds=new Set;hiddenAgentMessageIds=new Set;agentMessagePhases=new Map;deliveredAgentMessageIds=new Set;deliveredThinkingAgentMessageIds=new Set;codexSequence=0;pendingCodexDeltaFlush=null;turnError=null;turnErrorIsRetryableOnly=!0;turnHasVisibleOutput=!1;turnSawVisibleFinalAnswer=!1;turnHasDeliveredFinalAnswer=!1;deliverInboundEvent(e){if(this.compacting){d.info("codex-adapter",`Event ${e.event_id} deferred: compaction in progress`),this.compactionDeferred.push(e);return}const t=Ee(e.content,{messageId:e.msg_id});if(this.currentTurnId&&t.trim()){d.info("codex-adapter",`Event ${e.event_id}: steering active turn ${this.currentTurnId}`),this.steerTurn(t).catch(i=>{const s=i instanceof Error?i.message:String(i);if(d.info("codex-adapter",`Steer failed, falling through: ${s}`),!this.currentTurnId){this.startNewTurn(e,t);return}if(wt(s)){d.info("codex-adapter","Unsteerable turn detected, clearing active state and starting new turn"),this.clearActive(),this.startNewTurn(e,t);return}d.info("codex-adapter",`Steer failed but turn still active; deferring event ${e.event_id} for replay after turn ends`),this.steerDeferred.push(e)});return}if(this.currentTurnId){d.info("codex-adapter",`Event ${e.event_id} rejected: busy and empty content`),this.sendEventResultAfterFlushing(e.event_id,"failed","agent busy");return}this.startNewTurn(e,t)}startNewTurn(e,t){this.activeEventId=e.event_id,this.activeSessionId=e.session_id,e.audit?.enabled===!0&&this.enableAuditCapture(e.event_id,{auditId:e.audit.auditId,rawProviderBody:e.audit.rawProviderBody}),this.visibleAgentMessageIds.clear(),this.hiddenAgentMessageIds.clear(),this.agentMessagePhases.clear(),this.deliveredAgentMessageIds.clear(),this.deliveredThinkingAgentMessageIds.clear(),this.turnSawVisibleFinalAnswer=!1,this.turnHasDeliveredFinalAnswer=!1,this.codexSequence=0,this.startComposing();const i=this.threadId??"",s=new z(i),n={adapterSessionId:i,text:t,contextMessages:e.context_messages_json?JSON.parse(e.context_messages_json).map(r=>({senderId:r.sender_id??"unknown",content:r.content})):void 0};this.runTurn(n,s,e.event_id,e.session_id).catch(r=>{d.error("codex-adapter",`Turn failed: ${r}`),this.sendEventResultAfterFlushing(e.event_id,"failed",r instanceof Error?r.message:String(r)),this.clearActive()}),this.resetIdleTimer(e.event_id)}deliverStopEvent(e,t){this.activeEventId===e&&(this.cancel(this.threadId??"").catch(()=>{}),this.sendEventResultAfterFlushing(e,"canceled","stopped by user"),this.clearActive())}async spawnCodex(){const e={...this.resolveChildEnv(),...this.directEnv},t=typeof e.PATH=="string"?e.PATH:void 0;t||d.warn("codex-adapter",`spawnCodex: env.PATH is missing! process.env.PATH=${process.env.PATH?"set":"missing"}, config.env=${JSON.stringify(this.config.env)}`);const i=await de(this.config.command||"codex",t),s=lt(this.config.args);for(const o of this.configOverrideArgs)s.push("-c",o);for(const o of this.resolveRelayTransportConfigOverrides())s.push("-c",o);for(const o of this.rawCaptureConfigOverrides)s.push("-c",o);this.sandboxMode&&s.push("-c",`sandbox_mode="${this.sandboxMode}"`);const n=s.map(o=>this.rawCaptureConfigOverrides.includes(o)?"<raw-api-capture-overlay>":o);d.info("codex-adapter",`Spawning: ${i} ${n.join(" ")}`);try{if(!(await Z(this.cwd)).isDirectory())throw new Error(`Bound path is not a directory: ${this.cwd}`)}catch(o){throw String(o?.code??"")==="ENOENT"?new Error(`Bound directory does not exist: ${this.cwd}. Please rebind with /grix open <valid-directory>.`):o}const r=ee({codexHome:this.codexHome});if(r.locked&&!r.stale)throw new Error(`Codex session appears locked by another process: ${r.path}`);r.stale&&d.warn("codex-adapter",`Ignoring stale Codex lock: ${r.path}`);try{this.process=Te(i,s,{env:e,cwd:this.cwd}).process}catch(o){throw d.error("codex-adapter",`Codex spawn threw: ${o}`),this.process=null,this.alive=!1,this.bridgeStatus="closed",o}this.process.on("error",o=>{d.error("codex-adapter",`Codex process spawn error: ${o}`),this.process=null,this.alive=!1,this.bridgeStatus="closed",this.clearIdleTimer(),this.currentTurnId=null,this.rejectAllPending("spawn failed: "+(o instanceof Error?o.message:String(o))),this.stopComposing(),this.activeEventId?(this.flushCodexDeltaBuffer(),this.sendEventResultAfterFlushing(this.activeEventId,"failed","Codex process spawn failed"),this.activeEventId=null):this.clearCodexDeltaBuffer(),this.emit("exit",1)}),this.process.on("exit",o=>{d.info("codex-adapter",`Codex process exited (code=${o})`),this.alive=!1,this.bridgeStatus="closed",this.clearIdleTimer(),this.currentTurnId=null,this.rejectAllPending("process exited"),this.stopComposing(),this.activeEventId?this.flushCodexDeltaBuffer():this.clearCodexDeltaBuffer(),this.emit("exit",o)}),this.process.stderr?.on("data",o=>{const c=o.toString().trim();c&&d.info("codex-adapter",`[codex stderr] ${c}`)}),this.bindStdout(),this.alive=!0,this.startOrphanTurnWatch()}resolveRelayTransportConfigOverrides(){if(this.config.env?.[Xe]!=="1")return[];const e=qe(this.codexHome,this.configOverrideArgs);if(e==="openai"){const i=Be(this.codexHome,this.configOverrideArgs);return je(He,"Grix OpenAI Relay",i.targetBaseUrl)}const t=We(e);return t?[`${t}=false`]:[]}bindStdout(){if(!this.process?.stdout)return;this.process.stdout.setEncoding("utf8"),ge({input:this.process.stdout}).on("line",t=>{if(!t.trim())return;let i;try{i=JSON.parse(t)}catch{d.error("codex-adapter",`Invalid JSON from Codex: ${t.slice(0,200)}`);return}if(this.bridgeStatus==="starting"&&(this.bridgeStatus="ready"),i.id!=null){const s=String(i.id),n=this.pendingRequests.get(s);if(n){clearTimeout(n.timer),this.pendingRequests.delete(s),n.resolve(i);return}}this.handleNotification(i)})}handleNotification(e){const t=e.method,i=e.params??{};if(this.shouldIgnoreOutOfScopeNotification(e,t,i)){this.activeEventId&&this.resetIdleTimer(this.activeEventId);return}switch(this.captureAuditNotification(t,i),this.captureContextWindowFromPayload(t,i),this.activeEventId&&t&&t.startsWith("item/")&&!t.endsWith("/requestApproval")&&this.startComposing(),t){case"item/started":{const n=i.item,r=n?.id,o=n?.type,c=this.normalizeAgentMessagePhase(n?.phase);if(this.isLongRunningToolItemType(o)&&(this.inFlightToolOps+=1),o==="agentMessage"&&r){c?this.agentMessagePhases.set(r,c):this.agentMessagePhases.delete(r);const h=F(c),p=N(c);h?(this.visibleAgentMessageIds.add(r),this.hiddenAgentMessageIds.delete(r)):p?(this.visibleAgentMessageIds.delete(r),this.hiddenAgentMessageIds.delete(r)):(this.hiddenAgentMessageIds.add(r),this.visibleAgentMessageIds.delete(r)),c==="final_answer"&&h&&(this.turnSawVisibleFinalAnswer=!0)}break}case"item/agentMessage/delta":{const n=i.delta,r=i.itemId,o=this.resolveAgentMessagePhase(r,i.phase),c=(!r||!this.hiddenAgentMessageIds.has(r))&&F(o),h=(!r||!this.hiddenAgentMessageIds.has(r))&&N(o);if(o==="final_answer"&&c&&(this.turnSawVisibleFinalAnswer=!0),n&&this.activeEventId&&h){this.recordDeliveredThinkingAgentMessage(r),this.callbacks.sendThinking?.(this.activeEventId,this.activeSessionId??"",n);break}n&&this.activeEventId&&c&&!this.shouldSuppressAgentMessageDeltaDuringToolRun(r,o)&&(this.recordDeliveredAgentMessage(r,o),this.queueCodexDeltaEvent({...e,params:{...i,...o?{phase:o}:{}}}));break}case"item/completed":{const n=i.item,r=n?.id,o=n?.type;if(this.isLongRunningToolItemType(o)&&(this.inFlightToolOps=Math.max(0,this.inFlightToolOps-1)),this.activeEventId&&o==="commandExecution"&&(this.turnHasVisibleOutput=!0,this.emitCodexEvent("item/completed",e)),o==="agentMessage"){const c=this.resolveAgentMessagePhase(r,n?.phase),h=(!r||!this.hiddenAgentMessageIds.has(r))&&F(c);if(c==="final_answer"&&h){this.turnSawVisibleFinalAnswer=!0;const p=this.extractAgentMessageText(n),f=r?this.deliveredAgentMessageIds.has(r):!1;this.activeEventId&&p&&!f&&(d.warn("codex-adapter",`Recovering final_answer from item/completed item_id=${r??"unknown"}`),this.recordDeliveredAgentMessage(r,c),this.queueCodexDeltaEvent({method:"item/agentMessage/delta",params:{...r?{itemId:r}:{},delta:p,phase:c}}))}else if(N(c)){const p=this.extractAgentMessageText(n),f=r?this.deliveredThinkingAgentMessageIds.has(r):!1;this.activeEventId&&p&&!f&&(this.recordDeliveredThinkingAgentMessage(r),this.callbacks.sendThinking?.(this.activeEventId,this.activeSessionId??"",p))}r&&(this.visibleAgentMessageIds.delete(r),this.hiddenAgentMessageIds.delete(r),this.agentMessagePhases.delete(r))}break}case"turn/started":{const r=i.turn?.id;r&&(this.currentTurnId=r,this.turnError=null,this.turnErrorIsRetryableOnly=!0,this.turnHasVisibleOutput=!1,this.turnSawVisibleFinalAnswer=!1,this.turnHasDeliveredFinalAnswer=!1,this.deliveredAgentMessageIds.clear(),this.deliveredThinkingAgentMessageIds.clear(),this.currentTurnStartedAt=Date.now(),this.preflightCheckComplete=!1,d.info("codex-adapter",`Turn started: ${r}`),this.startComposing());break}case"item/fileChange/requestApproval":{this.handleApprovalRequest(e,"file");break}case"item/commandExecution/requestApproval":{this.handleApprovalRequest(e,"exec");break}case"item/permissions/requestApproval":{this.handleApprovalRequest(e,"permission");break}case"turn/completed":{this.handleTurnCompleted(i);break}case"error":{const n=i.error,r=i.message??n?.message??JSON.stringify(i);d.error("codex-adapter",`Codex error: ${r}`);const o=i.willRetry===!0;r&&(this.turnError=r,o||(this.turnErrorIsRetryableOnly=!1)),this.activeEventId&&!o&&(this.flushCodexDeltaBuffer(),this.callbacks.sendRunError(this.activeEventId,this.activeSessionId??"",r));break}case"account/rateLimits/updated":{const n=this.extractRateLimitPushLimitId(i),r=this.parseRateLimitSnapshot(i,this.rateLimitSnapshot);r&&(this.rateLimitSnapshot=r,d.info("codex-adapter",`Rate limits updated: primary=${r.primary.usedPercent.toFixed(1)}% secondary=${r.secondary.usedPercent.toFixed(1)}% extras=${r.extras?.length??0}`),this.callbacks.onRateLimitsUpdated?.(r)),n&&n!=="codex"&&this.refreshMainRateLimitsThrottled();break}case"thread/tokenUsage/updated":{const n=i.threadId,r=i.tokenUsage,o=r?.last;(!n||!r||!o)&&d.info("codex-adapter",`[cp-diagnose] token_usage payload_incomplete: method=thread/tokenUsage/updated hasThreadId=${String(!!n)} hasTokenUsage=${String(!!r)} hasLast=${String(!!o)} params=${JSON.stringify(i)}`),n&&r&&o&&(this.currentThreadTokenUsage={inputTokens:o.inputTokens??0,outputTokens:o.outputTokens??0,cacheReadInputTokens:o.cachedInputTokens??0,cacheCreationInputTokens:0},d.info("codex-adapter",`[cp-diagnose] token_usage raw thread=${n}: ${JSON.stringify(r)}`),d.info("codex-adapter",`[cp-diagnose] token_usage parsed thread=${n}: ${JSON.stringify(this.currentThreadTokenUsage)}`),this.callbacks.onTokenUsageUpdated?.(this.currentThreadTokenUsage),this.publishContextWindowSnapshot());break}default:break}const s=t?.endsWith("/requestApproval")===!0;t&&t!=="turn/started"&&(t.startsWith("item/")||t==="error"||t==="turn/completed")&&(this.preflightCheckComplete=!0),this.activeEventId&&(!s||this.pendingApprovals.size===0)&&this.resetIdleTimer(this.activeEventId)}shouldIgnoreOutOfScopeNotification(e,t,i){if(!t||e.id!=null)return!1;const s=x(u(i.threadId),u(i.threadID));if(s&&this.threadId&&s!==this.threadId)return this.logIgnoredNotificationScope(t,s,this.readNotificationTurnId(i)),!0;const n=this.readNotificationTurnId(i);return n&&this.currentTurnId&&n!==this.currentTurnId?(this.logIgnoredNotificationScope(t,s,n),!0):!1}readNotificationTurnId(e){const t=e.turn&&typeof e.turn=="object"?e.turn:void 0;return x(u(e.turnId),u(e.turnID),u(t?.id))}logIgnoredNotificationScope(e,t,i){e!=="error"&&!e.startsWith("turn/")||d.info("codex-adapter",`[scope] ignored ${e} thread=${t??"<none>"} turn=${i??"<none>"} active_thread=${this.threadId??"<none>"} active_turn=${this.currentTurnId??"<none>"}`)}captureAuditNotification(e,t){const i=this.activeEventId;if(!e||!i)return;const s=this.auditCaptureByEventId.get(i);if(!s)return;const n=t.turn,r=typeof t.turnId=="string"&&t.turnId?t.turnId:typeof t.turn_id=="string"&&t.turn_id?t.turn_id:typeof n?.id=="string"&&n.id?n.id:this.currentTurnId;r&&(s.providerTurnId=r);const o=typeof t.threadId=="string"&&t.threadId?t.threadId:typeof t.thread_id=="string"&&t.thread_id?t.thread_id:this.threadId;if(o&&(s.threadId=o),!!at.has(e))try{const c=JSON.parse(JSON.stringify(t));s.events.push({sequence:++s.sequence,method:e,params:c,observedAt:new Date().toISOString()})}catch(c){const h=c instanceof Error?c.message:String(c);d.warn("codex-adapter",`Audit evidence capture skipped event=${i} method=${e}: ${h}`)}}captureContextWindowFromPayload(e,t){const i=["model_context_window","modelContextWindow","context_window_size","contextWindowSize"],s=this.findNumericField(t,i);if(s==null||s<=0){const n=this.probeContextWindowFields(t,i);n.foundAnyCandidateField&&d.info("codex-adapter",`[cp-diagnose] context_window missing_or_invalid: method=${e??"-"} matchedFields=${n.matchedFields.join(",")||"-"} raw=${n.rawValues.join(",")||"-"} extracted=${String(s)}`);return}this.currentModelContextWindow!==s&&(this.currentModelContextWindow=s,d.info("codex-adapter",`[cp-diagnose] context_window updated: method=${e??"-"} size=${s}`),this.publishContextWindowSnapshot())}probeContextWindowFields(e,t){const i=[],s=[],n=r=>{if(!r||typeof r!="object")return;if(Array.isArray(r)){for(const c of r)n(c);return}const o=r;for(const c of t)Object.prototype.hasOwnProperty.call(o,c)&&(i.push(c),s.push(String(o[c])));for(const c of Object.values(o))n(c)};return n(e),{foundAnyCandidateField:i.length>0,matchedFields:i,rawValues:s}}findNumericField(e,t){if(!e||typeof e!="object")return null;const i=e;for(const s of t){const n=i[s];if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"){const r=Number(n);if(Number.isFinite(r))return r}}for(const s of Object.values(i)){if(Array.isArray(s)){for(const r of s){const o=this.findNumericField(r,t);if(o!=null)return o}continue}const n=this.findNumericField(s,t);if(n!=null)return n}return null}buildContextWindowSnapshot(){const e=this.currentModelContextWindow;if(!e||e<=0)return d.debug("codex-adapter",`[cp-diagnose] context_window snapshot skipped: invalid size=${String(e)}`),null;const t=this.currentThreadTokenUsage,i=t?t.inputTokens+t.outputTokens:null,s=i==null?null:Math.max(0,e-i),n=i==null?null:Math.min(100,i/e*100),r=i==null?null:Math.max(0,100-(n??0));return d.info("codex-adapter",`[cp-diagnose] context_window computed: threadId=${this.threadId??"-"} size=${e} usedTokens=${String(i)} usedPercentage=${String(n)}`),{sizeTokens:e,usedTokens:i,remainingTokens:s,usedPercentage:n,remainingPercentage:r,source:"codex:model_context_window"}}publishContextWindowSnapshot(){const e=this.buildContextWindowSnapshot();this.callbacks.onContextWindowUpdated?.(e),this.maybeScheduleAutoCompact(e)}maybeScheduleAutoCompact(e){const t=e?.usedPercentage;typeof t!="number"||t<oe||this.pendingAutoCompact||this.compacting||(this.pendingAutoCompact=!0,d.info("codex-adapter",`[auto-compact] context_window usedPercentage=${t.toFixed(1)}% >= ${oe}%, scheduling compact`),this.tryRunPendingAutoCompact())}tryRunPendingAutoCompact(){this.pendingAutoCompact&&(this.stopped||!this.alive||this.currentTurnId||this.compacting||(this.pendingAutoCompact=!1,this.execCommand("compact","",this.activeSessionId??"").then(e=>{d.info("codex-adapter",`[auto-compact] compact done status=${e.status} msg=${e.message??""}`),e.status==="failed"&&/agent busy/i.test(e.message??"")&&(this.pendingAutoCompact=!0)}).catch(e=>{d.warn("codex-adapter",`[auto-compact] compact error: ${e instanceof Error?e.message:e}`)})))}parseRateLimitSnapshot(e,t=null){try{const i=e.rateLimitsByLimitId,s=this.extractRateLimitPushLimitId(e),n=!i?.codex&&!!s&&s!=="codex",r=i?.codex??(n?{}:e.rateLimits??e),o=r.primary,c=r.secondary,h=r.credits,p=l=>{if(typeof l=="number"&&Number.isFinite(l))return l;if(typeof l=="string"){const m=Number(l);if(Number.isFinite(m))return m}return 0},f=l=>typeof l=="boolean"?l:typeof l=="string"?l.toLowerCase()==="true":!1,g=l=>{if(l==null)return null;if(typeof l=="string"){const m=l.trim();if(!m)return null;const I=Number(m);return Number.isFinite(I)&&I>1e9?new Date(I*1e3).toISOString():m}if(typeof l=="number"&&Number.isFinite(l)&&l>0){const m=l>1e12?l/1e3:l;return new Date(m*1e3).toISOString()}return null},y=l=>{const m=l.resets_in_seconds??l.resetsInSeconds,I=typeof m=="number"||typeof m=="string"?Number(m):NaN;return!Number.isFinite(I)||I<=0?null:new Date(Date.now()+I*1e3).toISOString()},v=l=>({usedPercent:p(l.used_percent??l.usedPercent),windowMinutes:p(l.window_minutes??l.windowDurationMins??l.windowMinutes),resetsAt:g(l.resets_at??l.resetsAt)??y(l)}),w=()=>({usedPercent:0,windowMinutes:0,resetsAt:null}),R=(l,m)=>l??m??w(),C=()=>{const l=[];if(o&&l.push(o),c&&l.push(c),Array.isArray(r.windows))for(const m of r.windows)m&&typeof m=="object"&&l.push(m);return l.map(v).filter(m=>m.windowMinutes>0)},T=(l,m,I)=>{const b=l.filter(A=>I(A.windowMinutes));return b.length===0?null:b.reduce((A,E)=>Math.abs(E.windowMinutes-m)<Math.abs(A.windowMinutes-m)?E:A)},O=C(),$=n?t?{primary:t.primary,secondary:t.secondary}:null:O.length>0?{primary:R(T(O,300,l=>l<1440),t?.primary),secondary:R(T(O,10080,l=>l>=1440),t?.secondary)}:o||c?{primary:o?v(o):t?.primary??w(),secondary:c?v(c):t?.secondary??w()}:null;if(!$)return null;const V=(l,m)=>{if(!m||typeof m!="object"||Array.isArray(m))return null;const I=m,b=I.limitName??I.limit_name,A=typeof b=="string"&&b.trim()?b.trim():l,E=[],G=I.primary,X=I.secondary;G&&E.push(G),X&&E.push(X);const J=E.map(v).filter(M=>M.windowMinutes>0),Y=T(J,10080,M=>M>=1440)??T(J,300,M=>M<1440);return Y?{id:l,label:A,...Y}:null};let _;if(i&&typeof i=="object"){_=[];for(const[l,m]of Object.entries(i)){if(l==="codex")continue;const I=V(l,m);I&&_.push(I)}}else if(_=t?.extras?[...t.extras]:[],n&&s){const l=V(s,e.rateLimits??e);if(l){const m=_.findIndex(I=>I.id===l.id);m>=0?_[m]=l:_.push(l)}}return{primary:$.primary,secondary:$.secondary,credits:h?{hasCredits:f(h.has_credits??h.hasCredits),unlimited:f(h.unlimited),balance:h.balance==null?null:p(h.balance)}:t?.credits??{hasCredits:!1,unlimited:!1,balance:null},..._.length>0?{extras:_}:{}}}catch{return null}}handleApprovalRequest(e,t){const i=e.id;if(i==null)return;const s=e.method,n=`${i}`.trim(),r=`codex_${pe(this.activeSessionId??"")}_${pe(n)}`;if(this.approvalPolicy==="never"){this.sendApprovalDecision(i,"accept");return}this.activeEventId&&this.emitCodexEvent(s,e),this.pendingApprovals.set(r,{approvalId:r,approvalCommandId:n,sourceEventId:this.activeEventId??"",requestId:i,kind:t}),d.info("codex-adapter",`Pending approval stored: ${r} (kind=${t})`),this.clearIdleTimer(),this.stopComposing()}resolvePendingApproval(e){const t=e.params??{},i=x(t.approval_id,t.approvalId);if(i)return this.pendingApprovals.get(i)??null;const s=x(t.approval_command_id,t.approvalCommandId);if(s){for(const[,n]of this.pendingApprovals)if(n.approvalCommandId===s)return n}return null}async handleExecApprovalEvent(e){const t={approval_id:e.approval_id,approval_command_id:e.approval_command_id,session_id:e.session_id},i={action_id:"exec_approval_event",action_type:e.decision==="deny"?"exec_reject":"exec_approve",params:t},s=this.resolvePendingApproval(i);if(!s)return{delivered:!1,errorCode:"approval_not_found",errorMsg:"That approval request is no longer pending."};const n=ce[e.decision]??"accept";return this.sendApprovalDecision(s.requestId,n),this.pendingApprovals.delete(s.approvalId),this.resumeAfterApproval({...i,event_id:s.sourceEventId},t,s),{delivered:!0}}sendApprovalDecision(e,t){if(e==null||!this.process?.stdin)return;const i={jsonrpc:"2.0",id:e,result:{decision:t}};this.process.stdin.write(`${JSON.stringify(i)}
5
- `)}armCompactionFallback(){this.compacting&&(this.compactingTimer&&clearTimeout(this.compactingTimer),this.compactingTimer=setTimeout(()=>{d.warn("codex-adapter","Compaction fallback fired: turn/completed not received within timeout, treating as stuck and releasing deferred events"),this.currentTurnId=null,this.finishCompaction("fallback-timeout")},tt),this.compactingTimer.unref?.())}startOrphanTurnWatch(){this.orphanTurnTimer||(this.orphanTurnTimer=setInterval(()=>this.checkOrphanTurn(),it),this.orphanTurnTimer.unref?.())}stopOrphanTurnWatch(){this.orphanTurnTimer&&(clearInterval(this.orphanTurnTimer),this.orphanTurnTimer=null),this.orphanTurnSince=0}checkOrphanTurn(){if(!(this.currentTurnId!==null&&this.activeEventId===null&&!this.compacting)){this.orphanTurnSince=0;return}const t=Date.now();if(this.orphanTurnSince===0){this.orphanTurnSince=t;return}if(t-this.orphanTurnSince<st)return;const i=this.currentTurnId,s=t-this.orphanTurnSince;this.currentTurnId=null,this.orphanTurnSince=0,d.warn("codex-adapter",`Orphan turn ${i} cleared after ${Math.round(s/1e3)}s with no active event: turn/completed never arrived. Adapter was reporting busy the whole time, which blocks upgrade/restart idle waits.`)}finishCompaction(e){if(!this.compacting)return;this.compacting=!1,this.compactingTimer&&(clearTimeout(this.compactingTimer),this.compactingTimer=null);const t=this.compactionDeferred.splice(0);d.info("codex-adapter",`Compaction finished (${e}); replaying ${t.length} deferred events`);for(const s of t)this.deliverInboundEvent(s);const i=this.compactionDoneResolver;this.compactionDoneResolver=null,i?.()}handleTurnCompleted(e){if(this.currentTurnId=null,this.stopComposing(),this.activeEventId){this.flushCodexDeltaBuffer();const t=this.activeEventId,i={event_id:t,session_id:this.activeSessionId??"",thread_id:this.threadId??void 0,codex_event_type:"codex",codex_method:"turn/completed",codex_sequence:++this.codexSequence},s=this.turnError,n=this.turnErrorIsRetryableOnly,r=this.turnHasVisibleOutput,o=this.turnSawVisibleFinalAnswer&&!this.turnHasDeliveredFinalAnswer;this.turnError=null,this.turnErrorIsRetryableOnly=!0,this.turnHasVisibleOutput=!1,this.turnSawVisibleFinalAnswer=!1,this.turnHasDeliveredFinalAnswer=!1;const h=(s&&!(n&&r)?s:null)??(o?"Codex final answer was observed but not delivered":null)??(r?null:"Codex completed without producing any visible output"),p=h!==null;this.callbacks.sendCodexEvent(i),this.sendEventResultAfterFlushing(t,p?"failed":"responded",h??void 0),this.clearActive()}this.compacting&&this.finishCompaction("turn-completed")}emitCodexEvent(e,t){if(!this.activeEventId)return;this.flushCodexDeltaBuffer();const i=fe(e,t);if(i===void 0&&e==="item/completed")return;const s={event_id:this.activeEventId,session_id:this.activeSessionId??"",thread_id:this.threadId??void 0,codex_event_type:"codex",codex_method:e,codex_sequence:++this.codexSequence};i!==void 0&&(s.codex_payload=i),this.callbacks.sendCodexEvent(s)}queueCodexDeltaEvent(e){if(!this.activeEventId)return;const t=fe("item/agentMessage/delta",e),i=t?.params?.delta;if(typeof i!="string"||i.length===0)return;const s=typeof t?.params?.phase=="string"?t.params.phase:void 0,n=this.activeEventId,r=this.activeSessionId??"",o=this.threadId??void 0,c=this.pendingCodexDeltaFlush;if(c&&(c.eventId!==n||c.sessionId!==r||c.threadId!==o||c.phase!==s)&&this.flushCodexDeltaBuffer(),this.pendingCodexDeltaFlush||(this.pendingCodexDeltaFlush={eventId:n,sessionId:r,threadId:o,delta:"",phase:s,timer:null}),this.pendingCodexDeltaFlush.delta+=i,this.pendingCodexDeltaFlush.delta.length>=rt){this.flushCodexDeltaBuffer();return}this.pendingCodexDeltaFlush.timer||(this.pendingCodexDeltaFlush.timer=setTimeout(()=>{if(this.activeEventId!==n){this.clearCodexDeltaBuffer();return}this.flushCodexDeltaBuffer()},nt))}flushCodexDeltaBuffer(){const e=this.pendingCodexDeltaFlush;if(!e||(this.pendingCodexDeltaFlush=null,e.timer&&clearTimeout(e.timer),!e.delta))return;const t={event_id:e.eventId,session_id:e.sessionId,thread_id:e.threadId,codex_event_type:"codex",codex_method:"item/agentMessage/delta",codex_sequence:++this.codexSequence,codex_payload:{params:{delta:e.delta,...e.phase?{phase:e.phase}:{}}}};this.callbacks.sendCodexEvent(t)}clearCodexDeltaBuffer(){const e=this.pendingCodexDeltaFlush;this.pendingCodexDeltaFlush=null,e?.timer&&clearTimeout(e.timer)}sendEventResultAfterFlushing(e,t,i){this.pendingCodexDeltaFlush?.eventId===e&&this.flushCodexDeltaBuffer(),this.callbacks.sendEventResult(e,t,i)}startComposing(){}stopComposing(){}async sendRequest(e,t,i=3e4){return new Promise((s,n)=>{if(!this.process?.stdin){n(new Error("Codex process not available"));return}const r=++this.requestId,o={jsonrpc:"2.0",id:r,method:e,params:t??{}},c=setTimeout(()=>{this.pendingRequests.delete(String(r)),n(new Error(`Request timeout: ${e}`))},i);this.pendingRequests.set(String(r),{resolve:p=>{p.error?n(new Error(`JSON-RPC error: ${p.error.message}`)):s(p.result)},reject:n,timer:c});const h=JSON.stringify(o);this.process.stdin.write(`${h}
1
+ import{execFileSync as Te}from"node:child_process";import{createInterface as xe}from"node:readline";import{EventEmitter as ee}from"node:events";import{stat as te}from"node:fs/promises";import{join as P,resolve as ye}from"node:path";import{fileURLToPath as Ce}from"node:url";import{syncDefaultSkillsToDir as _e}from"../../default-skills/index.js";import{resolveCommandPath as Ae,resolveShimInvocation as Se,spawnCommand as be,killProcessGroup as $,hasChildProcesses as Ee}from"../../core/runtime/spawn.js";import{InternalApiServer as Re}from"../../core/mcp/internal-api-server.js";import{resolveMcpServerName as ke,LEGACY_MCP_SERVER_NAMES as Me}from"../../core/mcp/server-name.js";import{formatInboundMessageReferenceText as F}from"../../core/protocol/message-reference.js";import{INBOUND_MESSAGE_ID_PROTOCOL_INSTRUCTION as j}from"../shared/inbound-message-id-injector.js";import{log as c}from"../../core/log/index.js";import{resolveClientVersion as Pe}from"../../core/util/client-version.js";import{isThinkingAgentMessagePhase as H,isUserVisibleAgentMessagePhase as D}from"../../core/util/codex-output-policy.js";import{SessionBindingStore as De}from"../../core/persistence/session-binding-store.js";import{ensureCodexProjectTrusted as Oe,isCodexCommand as Ne,readCodexProviderSettings as U,resolveCodexHome as Le}from"./codex-trust.js";import{prepareCodexDirectHome as $e}from"./direct-home.js";import{checkCodexSessionActivity as Fe,inspectCodexTurnProgress as je}from"./session-activity.js";import{CodexWaitLoopTracker as ie}from"./wait-loop.js";import{findRolloutFile as He}from"./rollout-locator.js";import{checkCodexLock as se}from"./lock-monitor.js";import{resolveCliPath as ne,getCliVersion as Ue}from"../../core/util/cli-probe.js";import{scanSkills as qe}from"../claude/skill-scanner.js";import{normalizeCodexConfigOverrides as re}from"./config-overrides.js";import{buildCodexOpenAiCompatibleProviderOverrides as We,CODEX_RELAY_OPENAI_PROVIDER_ID as Be,prepareCodexRawCapture as ze,resolveCodexProviderName as Ge,resolveCodexRawCaptureTarget as Ve,resolveCodexProviderSupportsWebsocketsConfigKey as Xe}from"./raw-capture-hook.js";import{unavailableRawApiCaptureBoundary as Je}from"../../audit/raw-capture/capture-relay.js";const oe=60*1e3,Ye=600*1e3,Ke=300*1e3,Ze="GRIX_RELAY_PROXY",Qe=5*1e3,et=15*1e3,ae=3;function q(a,e){const t=Number(process.env[a]);return Number.isFinite(t)&&t>0?t:e}function tt(a){const e=Number(process.env[a]);return Number.isFinite(e)&&e>0?e:null}function it(a){if(!a||typeof a!="object"||Array.isArray(a))return;const e=a,t=typeof e.auditId=="string"?e.auditId.trim():"",i=typeof e.sessionId=="string"?e.sessionId.trim():"",s=typeof e.spoolRootDir=="string"?e.spoolRootDir.trim():"";return t&&i&&s?{auditId:t,sessionId:i,spoolRootDir:s}:void 0}const W=q("GRIX_CODEX_PREFLIGHT_STALL_TIMEOUT_MS",120*1e3),st=20,nt=8e3,de=2*1024,ce=`
2
+ \u2026(truncated)`,le=80,ue=120*1e3,B=600*1e3,rt=60*1e3,ot=300*1e3,at=q("GRIX_CODEX_DELTA_COALESCE_MS",1e3),dt=q("GRIX_CODEX_DELTA_COALESCE_CHARS",4096),ct=[{id:"gpt-5.3-codex",displayName:"GPT-5.3 Codex",defaultReasoningEffort:null,supportedReasoningEfforts:[],defaultServiceTier:null,serviceTiers:[],isDefault:!0}],he=[{id:"default",displayName:"Default"},{id:"plan",displayName:"Plan"}],lt=new Set(["rawResponse/completed","codex/rawResponse/completed","rawResponseItem/completed","codex/rawResponseItem/completed","thread/tokenUsage/updated","codex/thread/tokenUsage/updated","thread/compacted","codex/thread/compacted","turn/started","codex/turn/started","turn/completed","codex/turn/completed","item/started","codex/item/started","item/completed","codex/item/completed","error","codex/error"]);async function pe(a,e){const t=String(a??"").trim()||"codex",i=Ae(t,e);if(i!==t)return i;if(t==="codex"){const n=process.platform==="win32"?[]:["/opt/homebrew/bin/codex","/usr/local/bin/codex","/usr/bin/codex"],r=process.platform!=="win32"?[]:[P(process.env.LOCALAPPDATA??"","npm","codex.cmd"),P(process.env.APPDATA??"","npm","codex.cmd"),P(process.env.LOCALAPPDATA??"","Programs","codex","codex.exe")];for(const o of[...n,...r])try{return require("node:fs").accessSync(o,require("node:fs").constants.X_OK),o}catch{continue}}const s=await ne(t);return s||(c.warn("codex-adapter",`resolveCodexCommandPath: failed to resolve "${t}" via PATH, codex fallbacks, or resolveCliPath. envPath=${e?"provided":"missing (using process.env.PATH)"}`),t)}class O extends ee{type="codex";config;callbacks;process=null;alive=!1;stopped=!1;internalApi=null;bridgeStatus="starting";pendingRequests=new Map;requestId=0;threadId=null;initialized=!1;cwd;approvalPolicy;sandboxMode;model;collaborationMode;reasoningEffort;serviceTier;idleTimer=null;waitLoopTimer=null;waitLoopCheckRunning=!1;waitLoopTracker=new ie;waitLoopProgressGeneration=0;waitLoopChildTools=new Set;rejectedTurnStarts=new Set;startingEventId=null;rejectedNativeOwner=null;rejectedNativeTimer=null;orphanTurnTimer=null;orphanTurnSince=0;lastProgressAt=0;lastIdleCheckAt=0;activityGeneration=0;lastIdleCheckGeneration=0;idleNoProgressCount=0;inFlightToolOps=0;consecutivePingFailures=0;currentTurnStartedAt=0;preflightCheckComplete=!1;turnInactivityTimeoutMs=tt("GRIX_CODEX_TURN_INACTIVITY_TIMEOUT_MS");pendingApprovals=new Map;needsHistoryInjection=!1;lastInjectedSessionId=null;identityInputInjectedThreadId=null;protocolInstructionInputInjectedThreadId=null;legacyDeveloperInstructionsUnsupported=!1;profileIdentityRefreshPending=!1;bindingStore=null;aibotSessionId="";threadResumePending=!1;autoTrustProject="auto";codexHome;codexDirect=null;directEnv={};configOverrideArgs=[];rawCaptureOptions;rawCaptureRelay;rawCaptureConfigOverrides=[];rawCaptureUnavailableReason;codexModelOptions=[];codexModelOptionsCachedAt=0;static MODEL_CACHE_TTL_MS=3600*1e3;rateLimitSnapshot=null;lastNonDefaultLimitRefreshAt=0;static NON_DEFAULT_LIMIT_REFRESH_INTERVAL_MS=6e4;currentThreadTokenUsage=null;currentModelContextWindow=null;auditCaptureByEventId=new Map;constructor(e,t){super(),this.config=e,this.callbacks=t;const i=e.options??{};this.approvalPolicy=i.approvalPolicy??"never",this.sandboxMode=typeof i.sandboxMode=="string"&&i.sandboxMode.trim()&&i.sandboxMode.trim()!=="default"?i.sandboxMode.trim():void 0,this.aibotSessionId=String(i.aibotSessionId??"").trim(),this.bindingStore=i.bindingStore instanceof De?i.bindingStore:null,this.model=i.model,this.collaborationMode=i.collaborationMode,this.reasoningEffort=i.reasoningEffort,this.serviceTier=i.serviceTier,this.bindingStore&&this.aibotSessionId&&(this.model=this.model??this.bindingStore.getCodexModelId(this.aibotSessionId),this.collaborationMode=this.collaborationMode??this.bindingStore.getCodexModeId(this.aibotSessionId),this.reasoningEffort=this.reasoningEffort??this.bindingStore.getCodexReasoningEffort(this.aibotSessionId),this.serviceTier=this.serviceTier??this.bindingStore.getCodexServiceTier(this.aibotSessionId),this.sandboxMode=this.sandboxMode??this.bindingStore.getCodexSandboxMode(this.aibotSessionId)),this.autoTrustProject=typeof i.autoTrustProject=="boolean"?i.autoTrustProject:"auto",this.codexHome=typeof i.codexHome=="string"&&i.codexHome.trim()?i.codexHome.trim():void 0;const s=i.codexDirect;if(this.codexDirect=s&&typeof s=="object"&&!Array.isArray(s)?s:null,this.configOverrideArgs=re(i.codexConfigOverrides,"codexConfigOverrides"),this.rawCaptureOptions=it(i.rawApiCapture),this.cwd=this.resolveCwd(),this.bindingStore&&this.aibotSessionId){const n=this.bindingStore.getCodexThreadId(this.aibotSessionId);n&&(this.threadId=n,this.threadResumePending=!0)}}resolveCwd(){if(this.bindingStore&&this.aibotSessionId){const e=this.bindingStore.get(this.aibotSessionId);if(e?.cwd)return e.cwd}return process.cwd()}async start(){await this.prepareDirectHome(),await this.ensureProjectTrusted(),await this.prepareRawApiCapture();try{await this.startInternalApiAndRegisterMcp(),await this.spawnCodex(),await this.initializeHandshake(),await this.notifyBindingReadyWithContext(),c.info("codex-adapter",`Ready (pid=${this.process?.pid})`)}catch(e){throw await this.stopRawApiCapture(),e}}async prepareRawApiCapture(){if(this.rawCaptureOptions)try{const e=await ze(this.rawCaptureOptions,{adapterType:"codex",sessionId:this.rawCaptureOptions.sessionId,cwd:this.cwd,env:this.resolveChildEnv(),configOverrides:this.configOverrideArgs,codexHome:this.codexHome});this.rawCaptureRelay=e.relay,this.rawCaptureConfigOverrides=e.overlay.configOverrides??[],this.rawCaptureUnavailableReason=void 0,c.info("codex-adapter","Raw API audit capture relay is ready")}catch(e){this.rawCaptureRelay=void 0,this.rawCaptureConfigOverrides=[],this.rawCaptureUnavailableReason=e instanceof Error?e.message:String(e),c.warn("codex-adapter",`Raw API audit capture unavailable: ${this.rawCaptureUnavailableReason}`)}}async stopRawApiCapture(){const e=this.rawCaptureRelay;this.rawCaptureRelay=void 0,this.rawCaptureConfigOverrides=[],e&&await e.stop()}async prepareDirectHome(){if(!this.codexDirect)return;const e=await $e(this.codexDirect);this.codexHome=e.codexHome,this.directEnv=e.env;const t=re(e.configOverrides,"codexDirect.configOverrides");this.configOverrideArgs=[...this.configOverrideArgs,...t],c.info("codex-adapter",`Codex direct home ready: ${e.codexHome} (catalog=${e.catalogVersion??"none"}, token=${e.tokenDigest?`present sha256:${e.tokenDigest}`:"absent"})`)}resolveChildEnv(){const e={...process.env,...this.config.env};return this.codexHome&&(e.CODEX_HOME=this.codexHome),e}async ensureProjectTrusted(){if(this.shouldAutoTrustProject())try{const e=await Oe(this.cwd,{codexHome:this.codexHome});e.changed&&c.info("codex-adapter",`Trusted Codex project ${this.cwd} in ${e.configPath}`)}catch(e){const t=e instanceof Error?e.message:String(e);throw c.error("codex-adapter",`Failed to trust Codex project ${this.cwd}: ${t}`),e}}async startInternalApiAndRegisterMcp(){try{this.internalApi=new Re,this.internalApi.setInvokeHandler(async(d,h,f,p)=>this.callbacks.agentInvoke(d,h,p)),await this.internalApi.start(0),c.info("codex-adapter",`Internal API started at ${this.internalApi.url}`);const e=this.getMcpConfig(),t=this.resolveChildEnv(),i=typeof t.PATH=="string"?t.PATH:void 0,s=await pe(this.config.command||"codex",i),n=d=>{const h=Se(s,d);Te(h.command,h.args,{env:t,timeout:1e4,stdio:"ignore",windowsHide:!0,windowsVerbatimArguments:h.windowsVerbatimArguments})};for(const d of[...Me,e.name])try{n(["mcp","remove",d])}catch{}n(["mcp","add",e.name,"--",e.command,...e.args]),c.info("codex-adapter",`Registered MCP server: ${e.name}`);const r=P(Le(this.codexHome),"skills"),o=_e(r);o.length>0&&c.info("codex-adapter",`Synced connector skills to ${r}: [${o.join(", ")}]`)}catch(e){c.warn("codex-adapter",`Failed to register MCP tools (non-fatal): ${e instanceof Error?e.message:String(e)}`)}}shouldAutoTrustProject(){return this.autoTrustProject===!1?!1:this.autoTrustProject===!0?!0:Ne(this.config.command)}notifyBindingReady(){!this.aibotSessionId||!this.cwd||this.callbacks.sendUpdateBindingCard(this.aibotSessionId,"ready",this.cwd)}async notifyBindingReadyWithContext(){if(!(!this.aibotSessionId||!this.cwd))try{this.callbacks.sendUpdateBindingCard(this.aibotSessionId,"ready",this.cwd,await this.buildToolbarContextResult("binding_ready"))}catch(e){c.warn("codex-adapter",`Failed to attach toolbar context to binding update: ${e instanceof Error?e.message:String(e)}`),this.notifyBindingReady()}}scheduleToolbarContextPush(){this.notifyBindingReadyWithContext()}externalProviderCheckedAt=0;externalProviderCached=!1;static EXTERNAL_PROVIDER_CACHE_TTL_MS=60*1e3;isExternalProvider(){const e=Date.now();if(e-this.externalProviderCheckedAt<O.EXTERNAL_PROVIDER_CACHE_TTL_MS)return this.externalProviderCached;const t=U(this.codexHome);return this.externalProviderCached=!!(t.baseUrl&&ge(t.baseUrl)),this.externalProviderCheckedAt=e,this.externalProviderCached}effectiveServiceTier(){if(!this.serviceTier||this.serviceTier.trim().toLowerCase()==="default"||this.isExternalProvider())return;const e=this.getModelOption(this.currentModelId());if(!(e&&!e.serviceTiers.some(t=>t.id===this.serviceTier)))return this.serviceTier}resolveReasoningEffortForModel(e,t,i={}){const s=String(e??"").trim();if(!s||this.isExternalProvider())return;const n=this.getModelOption(t),r=n?.supportedReasoningEfforts??[];if(r.length===0)return;const o=r.find(d=>d.trim().toLowerCase()===s.toLowerCase());if(o)return o;if(!i.strict&&["max","ultra"].includes(s.toLowerCase())){const d=r.find(h=>h.trim().toLowerCase()==="xhigh");if(d)return d}return i.strict?void 0:n?.defaultReasoningEffort??void 0}effectiveReasoningEffort(){return this.resolveReasoningEffortForModel(this.reasoningEffort,this.currentModelId())}getEffortMeta(){if(this.isExternalProvider())return{};const e=this.currentModelId(),t=this.getModelOption(e),i={},s=t?.supportedReasoningEfforts??[];s.length>0&&(i.available_efforts=s,i.reasoning_effort=this.effectiveReasoningEffort()??t?.defaultReasoningEffort??null);const n=t?.serviceTiers??[];return n.length>0&&(i.available_service_tiers=n,i.service_tier=this.effectiveServiceTier()??t?.defaultServiceTier??null),i}async stop(){this.stopped=!0,this.alive=!1,this.stopComposing(),this.clearIdleTimer(),this.clearWaitLoopWatch(),this.rejectedTurnStarts.clear(),this.stopOrphanTurnWatch(),this.currentTurnId=null,this.finishActiveInputs("canceled","adapter stopped"),this.rejectAllPending("adapter stopped"),this.pendingAutoCompact=!1,this.clearNativeSettlement("adapter stopped"),this.finishCompaction({status:"failed",message:"adapter stopped"});for(const t of this.steerDeferred.splice(0))this.sendEventResultAfterFlushing(t.event_id,"failed","adapter stopped");this.internalApi&&(await this.internalApi.stop(),this.internalApi=null);const e=this.process;if(this.process=null,e?.pid&&typeof e.once=="function")$(e,"SIGTERM"),await Promise.race([new Promise(i=>{e.once("exit",()=>i(!0))}),new Promise(i=>{setTimeout(()=>i(!1),5e3)})])||$(e,"SIGKILL");else if(e)try{e.kill("SIGTERM")}catch{}await this.stopRawApiCapture()}isAlive(){return this.alive}async createSession(e){if(this.initialized||await this.initializeHandshake(),this.threadId||await this.startNewThread(),!this.threadId)throw new Error("Failed to create session: thread ID is missing");return await this.notifyBindingReadyWithContext(),this.threadId}async resumeSession(e,t){await this.ensureThreadResumed()}async destroySession(e){this.threadId=null,this.threadResumePending=!1,this.persistThreadId(void 0),this.protocolInstructionInputInjectedThreadId=null}sendPrompt(e){const t=new X(e.adapterSessionId);return this.runTurn(e,t).catch(i=>{t.emitError(i instanceof Error?i:new Error(String(i)))}),t}async cancel(e){if(this.compacting&&this.finishCompaction({status:"failed",message:"Compaction interrupted"},!1),this.threadId)try{await this.sendRequest("turn/interrupt",{threadId:this.threadId,turnId:this.currentTurnId??""},5e3)}catch{}}setPermissionHandler(e){this.permissionHandler=e}permissionHandler=null;async ping(e){if(!this.alive||!this.process)return!1;if(!this.process.pid){const t=!!(this.process.stdin&&!this.process.stdin.destroyed),i=!!(this.process.stdout&&!this.process.stdout.destroyed);return t&&i}if(!this.process.stdin||this.process.stdin.destroyed)return!!(this.process.stdout&&!this.process.stdout.destroyed);try{const t=++this.requestId,i={jsonrpc:"2.0",id:t,method:"ping",params:{}};return await new Promise(s=>{const n=setTimeout(()=>{this.pendingRequests.delete(String(t)),s(!1)},e);this.pendingRequests.set(String(t),{resolve:()=>s(!0),reject:()=>s(!1),timer:n}),this.process.stdin.write(`${JSON.stringify(i)}
3
+ `)})}catch{return!1}}getStatus(){return{alive:this.alive,busy:this.currentTurnId!==null||this.compacting,sessions:this.threadId?1:0}}getActiveEventIds(){return this.activeEventId?[this.activeEventId]:[]}clearActiveEventForShutdown(){this.activeInputs.clear(),this.clearIdleTimer(),this.clearWaitLoopWatch(),this.clearCodexDeltaBuffer(),this.activeEventId=null}rejectEventOutput(e){if(this.compactionDeferred=this.compactionDeferred.filter(t=>t.event_id!==e),this.steerDeferred=this.steerDeferred.filter(t=>t.event_id!==e),this.activeInputs.delete(e)){this.emit("eventDone",e);return}this.activeEventId===e&&(this.clearCodexDeltaBuffer(),this.pendingAutoCompact=!1,this.currentTurnId?this.threadId&&this.interruptRejectedTurn(e,this.threadId,this.currentTurnId):this.startingEventId===e&&(this.rejectedTurnStarts.add(e),this.emit("pauseIntake","barrier")),this.clearActive({runPendingAutoCompact:!1}))}interruptRejectedTurn(e,t,i){const s=this.rejectedNativeOwner;if(s?.eventId===e&&s.threadId===t&&s.turnId===i&&s.process===this.process)return;this.rejectedNativeTimer&&clearTimeout(this.rejectedNativeTimer);const n={eventId:e,threadId:t,turnId:i,process:this.process,terminationAttempted:!1};this.rejectedNativeOwner=n,this.rejectedNativeTimer=setTimeout(()=>{this.rejectedNativeOwner===n&&(this.rejectedNativeTimer=null,this.terminateRejectedNativeOwner(n))},B),this.rejectedNativeTimer.unref?.(),this.sendRequest("turn/interrupt",{threadId:t,turnId:i},5e3).catch(()=>{this.terminateRejectedNativeOwner(n)})}terminateRejectedNativeOwner(e){if(!(this.rejectedNativeOwner!==e||e.terminationAttempted||!e.process||this.process!==e.process||this.threadId!==e.threadId||this.currentTurnId!==e.turnId||this.activeEventId||this.stopped||!this.alive)){e.terminationAttempted=!0,this.rejectedNativeTimer&&clearTimeout(this.rejectedNativeTimer),this.rejectedNativeTimer=null;try{$(e.process,"SIGTERM")}catch(t){c.error("codex-adapter",`Rejected producer termination failed; retaining native barrier: ${t instanceof Error?t.message:String(t)}`)}}}setModel(e){this.model=e,this.reasoningEffort=this.resolveReasoningEffortForModel(this.reasoningEffort,this.currentModelId()),this.persistCodexContext(),c.info("codex-adapter",`Model set to: ${e}`),this.scheduleToolbarContextPush()}setMode(e){const t=M(e);if(!t){c.info("codex-adapter",`Ignoring unsupported mode: ${e}`);return}this.collaborationMode=t,this.persistCodexContext(),c.info("codex-adapter",`Mode set to: ${t}`),this.scheduleToolbarContextPush()}setReasoningEffort(e){const t=this.resolveReasoningEffortForModel(e,this.currentModelId(),{strict:!0});if(!t){c.info("codex-adapter",`Ignoring unsupported reasoning effort for ${this.currentModelId()}: ${e}`);return}this.reasoningEffort=t,this.persistCodexContext(),c.info("codex-adapter",`Reasoning effort set to: ${t}`)}setServiceTier(e){const t=e.trim();this.serviceTier=t.toLowerCase()==="default"?"default":t,this.persistCodexContext(),c.info("codex-adapter",`Service tier set to: ${this.serviceTier}`)}setSandboxMode(e){this.sandboxMode=e,this.persistCodexContext(),c.info("codex-adapter",`Sandbox mode set to: ${e} (applied on next restart)`)}async threadCompact(){if(!this.threadId)throw new Error("No active thread");return this.sendRequest("thread/compact/start",{threadId:this.threadId},12e4)}async threadRollback(e){if(!this.threadId)throw new Error("No active thread");return this.sendRequest("thread/rollback",{threadId:this.threadId,numTurns:e},1e4)}getThreadId(){return this.threadId}hasRawApiCaptureRelay(){return!!this.rawCaptureRelay}enableAuditCapture(e,t={}){const i=e.trim();if(!i||this.auditCaptureByEventId.has(i))return;const s=t.rawProviderBody??!!this.rawCaptureOptions;this.auditCaptureByEventId.set(i,{auditId:t.auditId,threadId:this.threadId??void 0,modelId:this.currentModelId()??void 0,rawProviderBody:s,sequence:0,events:[]}),s&&this.rawCaptureRelay?.beginEvent(i,t.auditId)}takeAuditBoundary(e){const t=this.auditCaptureByEventId.get(e);if(t)return this.auditCaptureByEventId.delete(e),{adapterType:this.type,providerTurnId:t.providerTurnId,threadId:t.threadId??this.threadId??void 0,...t.sharedTurnOwner?{sharedTurnOwner:t.sharedTurnOwner}:{},codexEvidence:{events:t.events,...t.modelId?{modelId:t.modelId}:{},...t.rawProviderBody?{rawApiCapture:this.rawCaptureRelay?this.rawCaptureRelay.takeEvent(e):Je(this.rawCaptureUnavailableReason??"raw_capture_relay_not_prepared_before_adapter_start")}:{}}}}getMcpConfig(){if(!this.internalApi)return null;const e=ye(Ce(import.meta.url),"../../../mcp/acp-mcp-server.js");return{name:ke(this.callbacks.getAgentId?.()),command:process.execPath,args:[e,"--api-url",this.internalApi.url]}}async hasBackgroundWork(){const e=this.process?.pid;return e?Ee(e,[e]):!1}onAgentProfileChanged(){this.threadId&&(this.profileIdentityRefreshPending=!0,this.identityInputInjectedThreadId=null,c.info("codex-adapter",`agent profile changed; scheduling identity refresh for thread=${this.threadId}`))}async probe(e){const t=this.config.command||"codex",i=await ne(t),s=i!==null;let n=null,r;if(s){const v=await Ue(t);n=v.version,v.error&&(r=v.error)}else r={code:"cli_not_found",message:`command not found: ${t}`};const d=U(this.codexHome).baseUrl??null,h=this.currentModelId()||null,f=this.getStatus(),p=e?.conversation?{attempted:!0,ok:!1,latency_ms:null,error:{code:"unsupported",message:"codex does not support minimal prompt probe"}}:{attempted:!1,ok:!1,latency_ms:null},g=await this.probeSessionRecord(),T=se({codexHome:this.codexHome});return{cli:{command:t,installed:s,path:i,version:n,...r?{error:r}:{}},conversation:p,config:{model:h,base_url:d,source:{model:h?"runtime":"unknown",base_url:d?"file":"unknown"}},process:{started:!!this.process,alive:f.alive,busy:f.busy},session:g,lock:{present:T.present,locked:T.locked,stale:T.stale,path:T.path}}}async probeSessionRecord(){const e=this.threadId?He(this.threadId,this.codexHome):null;if(!e)return{recordPath:null,lastActivityMs:null,freshMs:null};try{const t=await te(e);return{recordPath:e,lastActivityMs:t.mtimeMs,freshMs:Date.now()-t.mtimeMs}}catch{return{recordPath:e,lastActivityMs:null,freshMs:null}}}getSupportedCommands(){return[{name:"compact",description:"Compact thread to reduce context size"},{name:"model",description:"List or set model",args:"[model_id]"},{name:"mode",description:"List or set collaboration mode",args:"[default|plan]"},{name:"rollback",description:"Roll back thread turns",args:"[num_turns]"},{name:"interrupt",description:"Interrupt current turn"},{name:"rate_limits",description:"Show current rate limits"},{name:"status",description:"Show thread and session status"},{name:"skills",description:"List available skills"}]}async execCommand(e,t,i){try{switch(e){case"compact":{if(!this.threadId)return{status:"failed",message:"No active thread"};if(this.compacting)return{status:"failed",message:"Compaction already in progress"};if(this.activeEventId&&!this.currentTurnId)return{status:"failed",message:"agent busy"};if(this.currentTurnId&&await this.cancelActiveTurnForCompaction(),await this.ensureThreadResumed(),this.currentTurnId||this.activeEventId)return{status:"failed",message:"agent busy"};if(this.needsHistoryInjection)return{status:"failed",message:"The session has expired and there is no history to compact. Please send a new message and try again."};if(this.compacting)return{status:"failed",message:"Compaction already in progress"};try{const s=await this.runCompaction();if(s.status!=="ok")throw new Error(s.message);return s}catch(s){const n=s instanceof Error?s.message:String(s);if(/thread.*(not found|not exist|unknown|invalid)/i.test(n)||/not found.*thread/i.test(n))return this.threadId=null,this.persistThreadId(void 0),{status:"failed",message:"The session has expired and there is no history to compact. Please send a new message and try again."};throw s}}case"model":{const s=t.trim();return s?this.getModelOptions().some(r=>r.id===s)?(this.setModel(s),{status:"ok",message:`Model set to ${s}`}):{status:"failed",message:`Unknown model: ${s}`}:{status:"ok",message:`Current: ${this.currentModelId()}`,data:{models:this.getModelOptions()}}}case"mode":{const s=t.trim();if(s){const n=M(s);return n?(this.setMode(n),{status:"ok",message:`Mode set to ${n}`}):{status:"failed",message:`Unknown mode: ${s}. Supported: default, plan`}}return{status:"ok",message:`Current: ${this.collaborationMode??"default"}`,data:{modes:he}}}case"rollback":{if(!this.threadId)return{status:"failed",message:"No active thread"};const s=Math.max(1,parseInt(t.trim(),10)||1);return this.currentTurnId&&(await this.cancel(this.threadId).catch(()=>{}),this.activeEventId&&this.sendEventResultAfterFlushing(this.activeEventId,"canceled","rolled back"),this.clearActive()),await this.threadRollback(s),{status:"ok",message:`Rolled back ${s} turn(s)`}}case"interrupt":{if(!this.threadId)return{status:"failed",message:"No active thread"};const s=this.compacting;return await this.cancel(this.threadId),this.activeEventId&&this.sendEventResultAfterFlushing(this.activeEventId,"canceled","interrupted"),s||this.clearActive(),{status:"ok",message:"Turn interrupted"}}case"rate_limits":return{status:"ok",message:this.rateLimitSnapshot?`Primary: ${this.rateLimitSnapshot.primary.usedPercent.toFixed(1)}%, Secondary: ${this.rateLimitSnapshot.secondary.usedPercent.toFixed(1)}%`:"Rate limits not available",data:{rateLimits:this.rateLimitSnapshot}};case"status":return{status:"ok",message:`Thread: ${this.threadId??"none"}, Model: ${this.currentModelId()}, Mode: ${this.collaborationMode??"default"}`,data:{threadId:this.threadId,model:this.currentModelId(),mode:this.collaborationMode??"default",cwd:this.cwd,alive:this.alive}};case"skills":{const s=qe({mode:"codex",projectDir:this.cwd}),n=s.map(r=>`- ${r.name}${r.trigger?` (${r.trigger})`:""}: ${r.description}`);return{status:"ok",message:n.length>0?n.join(`
4
+ `):"No skills found",data:s}}default:return{status:"unsupported",message:`Unknown command: ${e}`}}}catch(s){return{status:"failed",message:s instanceof Error?s.message:String(s)}}}async handleLocalAction(e){const t=e.action_type??"",i=e.params??{};switch(c.info("codex-adapter",`handleLocalAction action_type=${t} action_id=${e.action_id} session_id=${i.session_id??""}`),t){case"set_model":{const s=w(u(i.model_id),u(i.modelId),u(i.value));return s&&this.setModel(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("model_set")),{handled:!0,kind:"set_model"}}case"set_mode":{const s=i.mode_id;return s&&this.setMode(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("mode_set")),{handled:!0,kind:"set_mode"}}case"set_reasoning_effort":{const s=w(u(i.reasoning_effort),u(i.reasoning_eff),u(i.effort)),n=this.resolveReasoningEffortForModel(s,this.currentModelId(),{strict:!0});if(!n){const r=this.getModelOption(this.currentModelId())?.supportedReasoningEfforts??[];return this.callbacks.sendLocalActionResult(e.action_id,"failed",{outcome:"effort_rejected",model_id:this.currentModelId(),available_efforts:r},"unsupported_reasoning_effort",r.length>0?`reasoning_effort must be one of: ${r.join(", ")}`:`reasoning_effort is not supported by model ${this.currentModelId()}`),{handled:!0,kind:"set_reasoning_effort_rejected"}}return this.setReasoningEffort(n),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("effort_set",!1)),{handled:!0,kind:"set_reasoning_effort"}}case"set_service_tier":{const s=w(u(i.service_tier),u(i.serviceTier),u(i.value));return s&&this.setServiceTier(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("service_tier_set",!1)),{handled:!0,kind:"set_service_tier"}}case"set_sandbox_mode":{const s=w(u(i.sandbox_mode),u(i.sandboxMode),u(i.value));return s&&this.setSandboxMode(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",await this.buildToolbarContextResult("sandbox_mode_set",!1)),{handled:!0,kind:"set_sandbox_mode"}}case"thread_compact":{if(c.info("codex-adapter",`thread_compact start action_id=${e.action_id} threadId=${this.threadId}`),this.compacting)return this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,void 0,"Compaction already in progress"),{handled:!0,kind:"thread_compact"};if(this.activeEventId&&!this.currentTurnId)return this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,void 0,"agent busy"),{handled:!0,kind:"thread_compact"};this.currentTurnId&&await this.cancelActiveTurnForCompaction();try{if(await this.ensureThreadResumed(),this.needsHistoryInjection)return c.info("codex-adapter",`thread_compact aborted: thread expired, new thread created action_id=${e.action_id}`),this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"thread_expired","The session has expired and there is no history to compact. Please send a new message and try again."),{handled:!0,kind:"thread_compact"};if(this.currentTurnId||this.activeEventId||this.compacting)throw new Error("agent busy");const s=await this.runCompaction();if(s.status!=="ok")throw new Error(s.message);c.info("codex-adapter",`thread_compact done action_id=${e.action_id}`),this.callbacks.sendLocalActionResult(e.action_id,"ok")}catch(s){const n=s instanceof Error?s.message:String(s);/thread.*(not found|not exist|unknown|invalid)/i.test(n)||/not found.*thread/i.test(n)?(c.warn("codex-adapter",`thread_compact thread expired, resetting threadId action_id=${e.action_id} err=${n}`),this.threadId=null,this.persistThreadId(void 0),this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"thread_expired","The session has expired and there is no history to compact. Please send a new message and try again.")):(c.info("codex-adapter",`thread_compact failed action_id=${e.action_id} err=${n}`),this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,void 0,n))}return{handled:!0,kind:"thread_compact"}}case"get_context":return this.callbacks.sendLocalActionResult(e.action_id,"ok",{threadId:this.threadId,model:this.model,mode:this.collaborationMode,approvalPolicy:this.approvalPolicy,cwd:this.cwd,...await this.buildToolbarContextResult("context")}),{handled:!0,kind:"get_context"};case"exec_approve":case"file_approve":{const s=this.resolvePendingApproval(e);if(!s)return this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"unknown_or_expired_approval_id","That approval request is no longer pending."),{handled:!0,kind:t};const n=i.decision||"allow-once",r=fe[n]??"accept";return this.sendApprovalDecision(s.requestId,r),this.pendingApprovals.delete(s.approvalId),this.callbacks.sendLocalActionResult(e.action_id,"ok",{approval_id:s.approvalId,approval_command_id:s.approvalCommandId,decision:n}),this.resumeAfterApproval(e,i,s),{handled:!0,kind:t}}case"exec_reject":case"file_reject":{const s=this.resolvePendingApproval(e);return s?(this.sendApprovalDecision(s.requestId,"deny"),this.pendingApprovals.delete(s.approvalId),this.callbacks.sendLocalActionResult(e.action_id,"ok",{approval_id:s.approvalId,approval_command_id:s.approvalCommandId,decision:"deny"}),this.resumeAfterApproval(e,i,s),{handled:!0,kind:t}):(this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"unknown_or_expired_approval_id","That approval request is no longer pending."),{handled:!0,kind:t})}case"permission_approve":{const s=this.resolvePendingApproval(e);return!s||s.kind!=="permission"?(this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"unknown_or_expired_approval_id","That permission approval request is no longer pending."),{handled:!0,kind:t}):(this.sendApprovalDecision(s.requestId,"accept"),this.pendingApprovals.delete(s.approvalId),this.callbacks.sendLocalActionResult(e.action_id,"ok",{approval_id:s.approvalId,decision:"approve"}),this.resumeAfterApproval(e,i,s),{handled:!0,kind:t})}case"permission_reject":{const s=this.resolvePendingApproval(e);return!s||s.kind!=="permission"?(this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"unknown_or_expired_approval_id","That permission approval request is no longer pending."),{handled:!0,kind:t}):(this.sendApprovalDecision(s.requestId,"deny"),this.pendingApprovals.delete(s.approvalId),this.callbacks.sendLocalActionResult(e.action_id,"ok",{approval_id:s.approvalId,decision:"deny"}),this.resumeAfterApproval(e,i,s),{handled:!0,kind:t})}case"turn_interrupt":{try{await this.cancel(this.threadId??""),this.callbacks.sendLocalActionResult(e.action_id,"ok")}catch(s){this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,void 0,s instanceof Error?s.message:String(s))}return{handled:!0,kind:"turn_interrupt"}}case"thread_rollback":{const s=Number(i.numTurns??i.num_turns??1);if(!this.threadId)return this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,"no_thread","No active thread"),{handled:!0,kind:"thread_rollback"};this.currentTurnId&&(await this.cancel(this.threadId).catch(()=>{}),this.activeEventId&&this.sendEventResultAfterFlushing(this.activeEventId,"canceled","rolled back"),this.clearActive());try{await this.threadRollback(s),this.callbacks.sendLocalActionResult(e.action_id,"ok",{numTurns:s})}catch(n){this.callbacks.sendLocalActionResult(e.action_id,"failed",void 0,void 0,n instanceof Error?n.message:String(n))}return{handled:!0,kind:"thread_rollback"}}case"get_rate_limits":{const s=this.rateLimitSnapshot,n=this.buildContextWindowSnapshot(),r=Date.now(),o=this.currentThreadTokenUsage;return s?c.info("codex-adapter",`[rate-limits] responding: primary=${s.primary.usedPercent.toFixed(1)}% window=${s.primary.windowMinutes}min resetsAt=${s.primary.resetsAt} secondary=${s.secondary.usedPercent.toFixed(1)}% window=${s.secondary.windowMinutes}min resetsAt=${s.secondary.resetsAt}`):c.info("codex-adapter","[rate-limits] responding: no rateLimitSnapshot available"),c.debug("codex-adapter",`[cp-diagnose] get_rate_limits: threadId=${this.threadId??"-"} contextWindow=${JSON.stringify(n)} tokenUsage=${JSON.stringify(o)}`),this.callbacks.sendLocalActionResult(e.action_id,"ok",{adapterType:"codex",available:s!==null,cached:!1,sampledAt:r,rateLimits:s,contextWindow:n,tokenUsage:o}),{handled:!0,kind:"get_rate_limits"}}default:return{handled:!1,kind:""}}}async buildToolbarContextResult(e,t=!0){t&&await this.refreshCodexModelOptions();const i=M(this.collaborationMode)??"default",s=this.currentModelId(),n=this.getModelOption(s),r=this.getModelOptions(),o=he,d=this.effectiveReasoningEffort()??n?.defaultReasoningEffort??null,h=n?.supportedReasoningEfforts??[],f=this.effectiveServiceTier()??n?.defaultServiceTier??null,p=n?.serviceTiers??[],g=this.isExternalProvider(),T=g?[]:h,v=g?null:d,x=g?[]:p,y=g?null:f,A={outcome:e,session_context:{modelId:s,modeId:i,reasoningEffort:v,serviceTier:y,approvalPolicy:this.approvalPolicy,sandboxMode:this.sandboxMode??null},model_id:s,mode_id:i,currentModelId:s,currentModeId:i,available_models:r,available_modes:o,available_efforts:T,availableModels:r,availableModes:o,reasoning_effort:v,available_service_tiers:x,service_tier:y,sandbox_mode:this.sandboxMode??null,models:r.map(C=>({modelId:C.id,name:C.displayName})),modes:o.map(C=>({id:C.id,name:C.displayName}))};return this.rateLimitSnapshot&&(A.rate_limit_primary_percent=this.rateLimitSnapshot.primary.usedPercent,A.rate_limit_secondary_percent=this.rateLimitSnapshot.secondary.usedPercent,A.rate_limit_primary_window_min=this.rateLimitSnapshot.primary.windowMinutes,A.rate_limit_secondary_window_min=this.rateLimitSnapshot.secondary.windowMinutes),A}currentModelId(){const e=String(this.model??"").trim();if(e)return e;const t=this.getModelOptions();return t.find(i=>i.isDefault)?.id??t[0]?.id??""}getModelOption(e){const t=e.trim().toLowerCase();return this.getModelOptions().find(i=>i.id.trim().toLowerCase()===t)}getModelOptions(){const e=this.config.options??{},t=e.available_models??e.availableModels??e.models,i=vt(t),s=this.codexModelOptions,n=[],r=String(this.model??"").trim(),o=r&&!s.some(p=>p.id.trim().toLowerCase()===r.toLowerCase()),d=s.length>0?s:o?[]:ct;if(r){const p=[...s,...i].find(g=>g.id.trim().toLowerCase()===r.toLowerCase());n.push({id:r,displayName:p?.displayName??R(r),defaultReasoningEffort:p?.defaultReasoningEffort??null,supportedReasoningEfforts:p?.supportedReasoningEfforts??[],defaultServiceTier:p?.defaultServiceTier??null,serviceTiers:p?.serviceTiers??[],isDefault:p?.isDefault??!1})}n.push(...i),n.push(...d);const h=[],f=new Set;for(const p of n){const g=p.id.trim(),T=g.toLowerCase();!g||f.has(T)||(f.add(T),h.push({id:g,displayName:p.displayName.trim()||g,defaultReasoningEffort:p.defaultReasoningEffort,supportedReasoningEfforts:[...p.supportedReasoningEfforts],defaultServiceTier:p.defaultServiceTier,serviceTiers:[...p.serviceTiers],isDefault:p.isDefault}))}return h}async refreshCodexModelOptions(){if(!this.initialized||!this.alive||!this.process?.stdin||Date.now()-this.codexModelOptionsCachedAt<O.MODEL_CACHE_TTL_MS)return;const e=U(this.codexHome);if(e.baseUrl&&ge(e.baseUrl)){try{const t=await wt(e.baseUrl,e.apiKey);if(t.length>0){this.codexModelOptions=ve(t),this.codexModelOptionsCachedAt=Date.now(),c.info("codex-adapter",`Loaded ${t.length} models from external provider ${e.baseUrl}`);return}}catch(t){c.warn("codex-adapter",`External provider /v1/models failed (${t instanceof Error?t.message:String(t)})`)}if(!It(e.baseUrl)){this.codexModelOptions=[],this.codexModelOptionsCachedAt=Date.now();return}c.info("codex-adapter",`External provider ${e.baseUrl} returned no models; falling back to Codex model/list`)}try{const t=[];let i;do{const s=await this.sendRequest("model/list",{cursor:i??null,includeHidden:!1,limit:100},15e3),n=xt(s);t.push(...n.models),i=n.nextCursor}while(i);t.length>0&&(this.codexModelOptions=ve(t),this.codexModelOptionsCachedAt=Date.now())}catch(t){c.warn("codex-adapter",`Failed to load Codex model list: ${t instanceof Error?t.message:String(t)}`)}}currentTurnId=null;compacting=!1;pendingAutoCompact=!1;compactionDeferred=[];steerDeferred=[];compactingTimer=null;compactionState=null;retiredTurnIds=new Set;nativeSettlement=null;nativeSettlementTimer=null;activeEventId=null;activeSessionId=null;visibleAgentMessageIds=new Set;hiddenAgentMessageIds=new Set;agentMessagePhases=new Map;deliveredAgentMessageIds=new Set;deliveredThinkingAgentMessageIds=new Set;codexSequence=0;pendingCodexDeltaFlush=null;turnError=null;turnErrorIsRetryableOnly=!0;turnHasVisibleOutput=!1;turnSawVisibleFinalAnswer=!1;turnSawNonEmptyFinalAnswer=!1;completedEmptyFinalAnswerItems=new Map;turnHasDeliveredFinalAnswer=!1;activeInputs=new Map;canAcceptActiveInput(e){const t=this.activeEventId?this.auditCaptureByEventId.get(this.activeEventId):void 0;return(e.audit?.enabled!==!0||!!t&&(!(e.audit.rawProviderBody??!!this.rawCaptureOptions)||t.rawProviderBody))&&this.alive&&!this.stopped&&this.initialized&&!!this.threadId&&!!this.currentTurnId&&!!this.activeEventId&&e.session_id===this.activeSessionId&&e.msg_type===1&&e.content.trim().length>0&&!this.compacting&&!this.nativeSettlement&&this.rejectedTurnStarts.size===0&&this.compactionDeferred.length===0&&this.steerDeferred.length===0}deliverActiveInput(e){if(this.activeInputs.has(e.event_id)||this.activeEventId===e.event_id)return;if(!this.canAcceptActiveInput(e)){this.sendEventResultAfterFlushing(e.event_id,"failed","Active Codex turn no longer accepts input; input was not submitted"),this.emit("eventDone",e.event_id);return}const t={accepted:!1};if(e.audit?.enabled===!0){this.enableAuditCapture(e.event_id,{auditId:e.audit.auditId,rawProviderBody:!1});const r=this.auditCaptureByEventId.get(e.event_id);r.providerTurnId=this.currentTurnId,r.sharedTurnOwner={eventId:this.activeEventId,auditId:this.auditCaptureByEventId.get(this.activeEventId)?.auditId}}this.activeInputs.set(e.event_id,t),this.emit("eventStarted",e.event_id,e.session_id);const i=F(e.content,{messageId:e.msg_id}),s={threadId:this.threadId,turnId:this.currentTurnId,inputEventId:e.event_id};this.captureActiveInputAudit(e.event_id,"turn/steer",s);const n=()=>{t.accepted=!0,this.captureActiveInputAudit(e.event_id,"turn/steer/accepted",s)};this.steerTurn(i,e.context_messages_json,n).then(()=>{this.activeInputs.get(e.event_id)===t&&(this.waitLoopTracker.noteProgress(),this.waitLoopProgressGeneration++)}).catch(r=>{this.activeInputs.get(e.event_id)===t&&(this.activeInputs.delete(e.event_id),this.sendEventResultAfterFlushing(e.event_id,"failed",`Codex input delivery unconfirmed: ${r instanceof Error?r.message:String(r)}`),this.emit("eventDone",e.event_id))})}captureActiveInputAudit(e,t,i){const s=this.auditCaptureByEventId.get(e);s?.sharedTurnOwner&&s.events.push({sequence:++s.sequence,method:t,params:JSON.parse(JSON.stringify(i)),observedAt:new Date().toISOString()})}finishActiveInputs(e,t){const i=[...this.activeInputs];this.activeInputs.clear();for(const[s,n]of i){const r=e==="responded"&&!n.accepted;this.callbacks.sendEventResult(s,r?"failed":e,r?"Codex turn ended before input delivery was confirmed; check native history before retrying":t),this.emit("eventDone",s)}}deliverInboundEvent(e){if(this.stopped){this.sendEventResultAfterFlushing(e.event_id,"failed","adapter stopped");return}if(this.rejectedTurnStarts.size>0&&!this.nativeSettlement){this.compactionDeferred.push(e);return}if(this.nativeSettlement){this.nativeSettlement.waiting?this.compactionDeferred.push(e):(this.sendEventResultAfterFlushing(e.event_id,"failed","Native turn completion is unconfirmed; input was not submitted. Retry after native completion to recheck status."),this.checkNativeSettlement());return}if(this.compacting&&!this.compactionState?.resolve){this.sendEventResultAfterFlushing(e.event_id,"failed","Compaction completion is unconfirmed; input was not submitted. Retry after native completion to recheck status."),this.checkCompactionCompletion();return}if(this.compacting||this.compactionDeferred.length>0||this.activeEventId&&!this.currentTurnId){c.info("codex-adapter",`Event ${e.event_id} deferred: compaction in progress or inputs draining`),this.compactionDeferred.push(e);return}const t=F(e.content,{messageId:e.msg_id});if(this.currentTurnId&&t.trim()){c.info("codex-adapter",`Event ${e.event_id}: steering active turn ${this.currentTurnId}`);const i=this.activeEventId,s=this.currentTurnId;this.steerTurn(t).catch(n=>{if(this.nativeSettlement||this.compacting||this.activeEventId!==i||this.currentTurnId!==s){this.deliverInboundEvent(e);return}const r=n instanceof Error?n.message:String(n);if(c.info("codex-adapter",`Steer failed, falling through: ${r}`),_t(r)){c.info("codex-adapter","Unsteerable turn detected, closing local ownership and retaining native barrier"),i&&this.sendEventResultAfterFlushing(i,"failed",r),this.clearActive(),this.deliverInboundEvent(e);return}c.info("codex-adapter",`Steer failed but turn still active; deferring event ${e.event_id} for replay after turn ends`),this.steerDeferred.push(e)});return}if(this.currentTurnId){c.info("codex-adapter",`Event ${e.event_id} rejected: busy and empty content`),this.sendEventResultAfterFlushing(e.event_id,"failed","agent busy");return}this.startNewTurn(e,t)}startNewTurn(e,t){this.activeEventId=e.event_id,this.activeSessionId=e.session_id,this.turnError=null,this.turnErrorIsRetryableOnly=!0,this.turnHasVisibleOutput=!1,e.audit?.enabled===!0&&this.enableAuditCapture(e.event_id,{auditId:e.audit.auditId,rawProviderBody:e.audit.rawProviderBody}),this.visibleAgentMessageIds.clear(),this.hiddenAgentMessageIds.clear(),this.agentMessagePhases.clear(),this.deliveredAgentMessageIds.clear(),this.deliveredThinkingAgentMessageIds.clear(),this.turnSawVisibleFinalAnswer=!1,this.turnSawNonEmptyFinalAnswer=!1,this.completedEmptyFinalAnswerItems.clear(),this.turnHasDeliveredFinalAnswer=!1,this.codexSequence=0,this.startComposing();const i=this.threadId??"",s=new X(i),n={adapterSessionId:i,text:t,contextMessages:e.context_messages_json?JSON.parse(e.context_messages_json).map(r=>({senderId:r.sender_id??"unknown",content:r.content})):void 0};this.runTurn(n,s,e.event_id,e.session_id).catch(r=>{this.activeEventId!==e.event_id||this.compacting||(c.error("codex-adapter",`Turn failed: ${r}`),this.sendEventResultAfterFlushing(e.event_id,"failed",r instanceof Error?r.message:String(r)),this.clearActive())}),this.resetIdleTimer(e.event_id)}deliverStopEvent(e,t){const i=this.compactionDeferred.findIndex(s=>s.event_id===e);if(i>=0){this.compactionDeferred.splice(i,1),this.sendEventResultAfterFlushing(e,"canceled","stopped by user");return}this.activeEventId&&(this.activeEventId===e||this.activeInputs.has(e))&&(this.cancel(this.threadId??"").catch(()=>{}),this.sendEventResultAfterFlushing(this.activeEventId,"canceled","stopped by user"),this.clearActive())}async spawnCodex(){const e={...this.resolveChildEnv(),...this.directEnv},t=typeof e.PATH=="string"?e.PATH:void 0;t||c.warn("codex-adapter",`spawnCodex: env.PATH is missing! process.env.PATH=${process.env.PATH?"set":"missing"}, config.env=${JSON.stringify(this.config.env)}`);const i=await pe(this.config.command||"codex",t),s=pt(this.config.args);for(const o of this.configOverrideArgs)s.push("-c",o);for(const o of this.resolveRelayTransportConfigOverrides())s.push("-c",o);for(const o of this.rawCaptureConfigOverrides)s.push("-c",o);this.sandboxMode&&s.push("-c",`sandbox_mode="${this.sandboxMode}"`);const n=s.map(o=>this.rawCaptureConfigOverrides.includes(o)?"<raw-api-capture-overlay>":o);c.info("codex-adapter",`Spawning: ${i} ${n.join(" ")}`);try{if(!(await te(this.cwd)).isDirectory())throw new Error(`Bound path is not a directory: ${this.cwd}`)}catch(o){throw String(o?.code??"")==="ENOENT"?new Error(`Bound directory does not exist: ${this.cwd}. Please rebind with /grix open <valid-directory>.`):o}const r=se({codexHome:this.codexHome});if(r.locked&&!r.stale)throw new Error(`Codex session appears locked by another process: ${r.path}`);r.stale&&c.warn("codex-adapter",`Ignoring stale Codex lock: ${r.path}`);try{this.process=be(i,s,{env:e,cwd:this.cwd}).process}catch(o){throw c.error("codex-adapter",`Codex spawn threw: ${o}`),this.process=null,this.alive=!1,this.bridgeStatus="closed",o}this.process.on("error",o=>{c.error("codex-adapter",`Codex process spawn error: ${o}`),this.process=null,this.alive=!1,this.bridgeStatus="closed",this.clearIdleTimer(),this.clearWaitLoopWatch(),this.rejectedTurnStarts.clear(),this.currentTurnId=null,this.clearNativeSettlement("Codex process spawn failed"),this.finishCompaction({status:"failed",message:"Codex process spawn failed"}),this.rejectAllPending("spawn failed: "+(o instanceof Error?o.message:String(o))),this.stopComposing(),this.activeEventId?(this.flushCodexDeltaBuffer(),this.sendEventResultAfterFlushing(this.activeEventId,"failed","Codex process spawn failed"),this.activeEventId=null):this.clearCodexDeltaBuffer(),this.emit("exit",1)}),this.process.on("exit",o=>{c.info("codex-adapter",`Codex process exited (code=${o})`),this.alive=!1,this.bridgeStatus="closed",this.clearIdleTimer(),this.clearWaitLoopWatch(),this.rejectedTurnStarts.clear(),this.currentTurnId=null,this.clearNativeSettlement("Codex process exited"),this.finishCompaction({status:"failed",message:"Codex process exited"}),this.rejectAllPending("process exited"),this.stopComposing(),this.activeEventId?this.flushCodexDeltaBuffer():this.clearCodexDeltaBuffer(),this.emit("exit",o)}),this.process.stderr?.on("data",o=>{const d=o.toString().trim();d&&c.info("codex-adapter",`[codex stderr] ${d}`)}),this.bridgeStatus="starting",this.bindStdout(),this.alive=!0,this.startOrphanTurnWatch()}resolveRelayTransportConfigOverrides(){if(this.config.env?.[Ze]!=="1")return[];const e=Ge(this.codexHome,this.configOverrideArgs);if(e==="openai"){const i=Ve(this.codexHome,this.configOverrideArgs);return We(Be,"Grix OpenAI Relay",i.targetBaseUrl)}const t=Xe(e);return t?[`${t}=false`]:[]}bindStdout(){if(!this.process?.stdout)return;this.process.stdout.setEncoding("utf8"),xe({input:this.process.stdout}).on("line",t=>{if(!t.trim())return;let i;try{i=JSON.parse(t)}catch{c.error("codex-adapter",`Invalid JSON from Codex: ${t.slice(0,200)}`);return}this.bridgeStatus==="starting"&&(this.bridgeStatus="ready");const s=Object.prototype.hasOwnProperty.call(i,"result"),n=Object.prototype.hasOwnProperty.call(i,"error"),r=!Object.prototype.hasOwnProperty.call(i,"method")&&s!==n&&(s||typeof i.error?.code=="number"&&typeof i.error.message=="string");if(i.id!=null&&r){const o=String(i.id),d=this.pendingRequests.get(o);if(d){clearTimeout(d.timer),this.pendingRequests.delete(o),d.resolve(i);return}}this.handleNotification(i)})}handleNotification(e){const t=e.method,i=e.params??{};if(this.stopped||this.bridgeStatus==="closed")return;if(this.shouldIgnoreOutOfScopeNotification(e,t,i)){const n=w(u(i.threadId),u(i.threadID)),r=i.item;if(n&&n!==this.threadId&&r?.id&&this.isLongRunningToolItemType(r.type)){const o=`${n}:${r.id}`;t==="item/started"&&this.waitLoopChildTools.add(o),t==="item/completed"&&this.waitLoopChildTools.delete(o),this.waitLoopTracker.noteProgress(),this.waitLoopProgressGeneration++}this.activeEventId&&this.resetIdleTimer(this.activeEventId);return}switch(this.captureAuditNotification(t,i),this.captureContextWindowFromPayload(t,i),this.activeEventId&&t&&t.startsWith("item/")&&!t.endsWith("/requestApproval")&&this.startComposing(),t){case"thread/status/changed":{const n=i.status;this.nativeSettlement&&i.threadId===this.nativeSettlement.threadId&&n?.type==="idle"&&this.checkNativeSettlement(),this.compactionState&&!this.compactionState.resolve&&i.threadId===this.compactionState.threadId&&n?.type==="idle"&&this.checkCompactionCompletion();break}case"item/started":{const n=i.item,r=n?.id,o=n?.type,d=this.normalizeAgentMessagePhase(n?.phase);if(this.isLongRunningToolItemType(o)&&(this.waitLoopTracker.noteProgress(),this.waitLoopProgressGeneration++,this.inFlightToolOps+=1),o==="agentMessage"&&d==="final_answer"&&D(d)&&this.recordFinalAnswerEvidence(r,this.extractAgentMessageText(n)),o==="agentMessage"&&r){d?this.agentMessagePhases.set(r,d):this.agentMessagePhases.delete(r);const h=D(d),f=H(d);h?(this.visibleAgentMessageIds.add(r),this.hiddenAgentMessageIds.delete(r)):f?(this.visibleAgentMessageIds.delete(r),this.hiddenAgentMessageIds.delete(r)):(this.hiddenAgentMessageIds.add(r),this.visibleAgentMessageIds.delete(r))}break}case"item/agentMessage/delta":{const n=i.delta;n&&(this.waitLoopTracker.noteProgress(),this.waitLoopProgressGeneration++);const r=i.itemId,o=this.resolveAgentMessagePhase(r,i.phase),d=(!r||!this.hiddenAgentMessageIds.has(r))&&D(o),h=(!r||!this.hiddenAgentMessageIds.has(r))&&H(o);if(o==="final_answer"&&d&&this.recordFinalAnswerEvidence(r,n),n&&this.activeEventId&&h){this.recordDeliveredThinkingAgentMessage(r),this.callbacks.sendThinking?.(this.activeEventId,this.activeSessionId??"",n);break}n&&this.activeEventId&&d&&!this.shouldSuppressAgentMessageDeltaDuringToolRun(r,o)&&(this.recordDeliveredAgentMessage(r,o),this.queueCodexDeltaEvent({...e,params:{...i,...o?{phase:o}:{}}}));break}case"item/completed":{const n=i.item,r=n?.id,o=n?.type;if(this.isLongRunningToolItemType(o)&&(this.inFlightToolOps=Math.max(0,this.inFlightToolOps-1)),this.activeEventId&&o==="commandExecution"&&(this.turnHasVisibleOutput=!0,this.emitCodexEvent("item/completed",e)),o==="agentMessage"){const d=this.resolveAgentMessagePhase(r,n?.phase),h=(!r||!this.hiddenAgentMessageIds.has(r))&&D(d);if(d==="final_answer"&&h){const f=this.extractAgentMessageText(n);this.recordFinalAnswerEvidence(r,f,!0);const p=r?this.deliveredAgentMessageIds.has(r):!1;this.activeEventId&&f&&!p&&(c.warn("codex-adapter",`Recovering final_answer from item/completed item_id=${r??"unknown"}`),this.recordDeliveredAgentMessage(r,d),this.queueCodexDeltaEvent({method:"item/agentMessage/delta",params:{...r?{itemId:r}:{},delta:f,phase:d}}))}else if(H(d)){const f=this.extractAgentMessageText(n),p=r?this.deliveredThinkingAgentMessageIds.has(r):!1;this.activeEventId&&f&&!p&&(this.recordDeliveredThinkingAgentMessage(r),this.callbacks.sendThinking?.(this.activeEventId,this.activeSessionId??"",f))}r&&(this.visibleAgentMessageIds.delete(r),this.hiddenAgentMessageIds.delete(r),this.agentMessagePhases.delete(r))}break}case"turn/started":{const r=i.turn?.id;if(r){if(this.compactionState&&(this.compactionState.turnId=r),this.currentTurnId=r,this.rejectedTurnStarts.size>0&&!this.activeEventId){this.retainUnconfirmedNativeTurn();const o=this.rejectedTurnStarts.values().next().value;this.threadId&&o&&this.interruptRejectedTurn(o,this.threadId,r);break}this.turnError=null,this.turnErrorIsRetryableOnly=!0,this.turnHasVisibleOutput=!1,this.turnSawVisibleFinalAnswer=!1,this.turnSawNonEmptyFinalAnswer=!1,this.completedEmptyFinalAnswerItems.clear(),this.turnHasDeliveredFinalAnswer=!1,this.deliveredAgentMessageIds.clear(),this.deliveredThinkingAgentMessageIds.clear(),this.currentTurnStartedAt=Date.now(),this.preflightCheckComplete=!1,c.info("codex-adapter",`Turn started: ${r}`),this.startComposing(),this.emit("activeInputReady")}break}case"item/fileChange/requestApproval":{this.handleApprovalRequest(e,"file");break}case"item/commandExecution/requestApproval":{this.handleApprovalRequest(e,"exec");break}case"item/permissions/requestApproval":{this.handleApprovalRequest(e,"permission");break}case"turn/completed":{this.handleTurnCompleted(i);break}case"error":{const n=i.error,r=i.message??n?.message??JSON.stringify(i);c.error("codex-adapter",`Codex error: ${r}`);const o=i.willRetry===!0;r&&(this.turnError=r,o||(this.turnErrorIsRetryableOnly=!1)),this.activeEventId&&!o&&(this.flushCodexDeltaBuffer(),this.callbacks.sendRunError(this.activeEventId,this.activeSessionId??"",r));break}case"account/rateLimits/updated":{const n=this.extractRateLimitPushLimitId(i),r=this.parseRateLimitSnapshot(i,this.rateLimitSnapshot);r&&(this.rateLimitSnapshot=r,c.info("codex-adapter",`Rate limits updated: primary=${r.primary.usedPercent.toFixed(1)}% secondary=${r.secondary.usedPercent.toFixed(1)}% extras=${r.extras?.length??0}`),this.callbacks.onRateLimitsUpdated?.(r)),n&&n!=="codex"&&this.refreshMainRateLimitsThrottled();break}case"thread/tokenUsage/updated":{const n=i.threadId,r=i.tokenUsage,o=r?.last;(!n||!r||!o)&&c.info("codex-adapter",`[cp-diagnose] token_usage payload_incomplete: method=thread/tokenUsage/updated hasThreadId=${String(!!n)} hasTokenUsage=${String(!!r)} hasLast=${String(!!o)} params=${JSON.stringify(i)}`),n&&r&&o&&(this.currentThreadTokenUsage={inputTokens:o.inputTokens??0,outputTokens:o.outputTokens??0,cacheReadInputTokens:o.cachedInputTokens??0,cacheCreationInputTokens:0},c.info("codex-adapter",`[cp-diagnose] token_usage raw thread=${n}: ${JSON.stringify(r)}`),c.info("codex-adapter",`[cp-diagnose] token_usage parsed thread=${n}: ${JSON.stringify(this.currentThreadTokenUsage)}`),this.callbacks.onTokenUsageUpdated?.(this.currentThreadTokenUsage),this.publishContextWindowSnapshot());break}default:break}const s=t?.endsWith("/requestApproval")===!0;t&&t!=="turn/started"&&(t.startsWith("item/")||t==="error"||t==="turn/completed")&&(this.preflightCheckComplete=!0),this.activeEventId&&(!s||this.pendingApprovals.size===0)&&this.resetIdleTimer(this.activeEventId)}shouldIgnoreOutOfScopeNotification(e,t,i){if(!t||e.id!=null)return!1;const s=w(u(i.threadId),u(i.threadID));if(s&&this.threadId&&s!==this.threadId)return this.logIgnoredNotificationScope(t,s,this.readNotificationTurnId(i)),!0;if(this.nativeSettlement&&(t.startsWith("turn/")||t.startsWith("item/")||t==="error")){const r=i.turn;return t!=="turn/completed"||s!==this.nativeSettlement.threadId||this.readNotificationTurnId(i)!==this.nativeSettlement.turnId||!["completed","failed","interrupted"].includes(String(r?.status))}if(this.compactionState&&t.startsWith("turn/")){if(s!==this.compactionState.threadId)return!0;const r=this.readNotificationTurnId(i);if(!r||this.retiredTurnIds.has(r)||t==="turn/completed"&&r!==this.compactionState.turnId)return!0}const n=this.readNotificationTurnId(i);return n&&this.retiredTurnIds.has(n)?!0:n&&this.currentTurnId&&n!==this.currentTurnId?(this.logIgnoredNotificationScope(t,s,n),!0):!1}readNotificationTurnId(e){const t=e.turn&&typeof e.turn=="object"?e.turn:void 0;return w(u(e.turnId),u(e.turnID),u(t?.id))}logIgnoredNotificationScope(e,t,i){e!=="error"&&!e.startsWith("turn/")||c.info("codex-adapter",`[scope] ignored ${e} thread=${t??"<none>"} turn=${i??"<none>"} active_thread=${this.threadId??"<none>"} active_turn=${this.currentTurnId??"<none>"}`)}captureAuditNotification(e,t){const i=this.activeEventId;if(!e||!i)return;const s=this.auditCaptureByEventId.get(i);if(!s)return;const n=t.turn,r=typeof t.turnId=="string"&&t.turnId?t.turnId:typeof t.turn_id=="string"&&t.turn_id?t.turn_id:typeof n?.id=="string"&&n.id?n.id:this.currentTurnId;r&&(s.providerTurnId=r);const o=typeof t.threadId=="string"&&t.threadId?t.threadId:typeof t.thread_id=="string"&&t.thread_id?t.thread_id:this.threadId;if(o&&(s.threadId=o),!!lt.has(e)){try{const d=JSON.parse(JSON.stringify(t));s.events.push({sequence:++s.sequence,method:e,params:d,observedAt:new Date().toISOString()})}catch(d){const h=d instanceof Error?d.message:String(d);c.warn("codex-adapter",`Audit evidence capture skipped event=${i} method=${e}: ${h}`)}if(e==="turn/completed"||e==="codex/turn/completed")for(const d of this.activeInputs.keys())this.captureActiveInputAudit(d,e,{threadId:o,turnId:r,turn:n?{id:n.id,status:n.status,error:n.error}:void 0})}}captureContextWindowFromPayload(e,t){const i=["model_context_window","modelContextWindow","context_window_size","contextWindowSize"],s=this.findNumericField(t,i);if(s==null||s<=0){const n=this.probeContextWindowFields(t,i);n.foundAnyCandidateField&&c.info("codex-adapter",`[cp-diagnose] context_window missing_or_invalid: method=${e??"-"} matchedFields=${n.matchedFields.join(",")||"-"} raw=${n.rawValues.join(",")||"-"} extracted=${String(s)}`);return}this.currentModelContextWindow!==s&&(this.currentModelContextWindow=s,c.info("codex-adapter",`[cp-diagnose] context_window updated: method=${e??"-"} size=${s}`),this.publishContextWindowSnapshot())}probeContextWindowFields(e,t){const i=[],s=[],n=r=>{if(!r||typeof r!="object")return;if(Array.isArray(r)){for(const d of r)n(d);return}const o=r;for(const d of t)Object.prototype.hasOwnProperty.call(o,d)&&(i.push(d),s.push(String(o[d])));for(const d of Object.values(o))n(d)};return n(e),{foundAnyCandidateField:i.length>0,matchedFields:i,rawValues:s}}findNumericField(e,t){if(!e||typeof e!="object")return null;const i=e;for(const s of t){const n=i[s];if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"){const r=Number(n);if(Number.isFinite(r))return r}}for(const s of Object.values(i)){if(Array.isArray(s)){for(const r of s){const o=this.findNumericField(r,t);if(o!=null)return o}continue}const n=this.findNumericField(s,t);if(n!=null)return n}return null}buildContextWindowSnapshot(){const e=this.currentModelContextWindow;if(!e||e<=0)return c.debug("codex-adapter",`[cp-diagnose] context_window snapshot skipped: invalid size=${String(e)}`),null;const t=this.currentThreadTokenUsage,i=t?t.inputTokens+t.outputTokens:null,s=i==null?null:Math.max(0,e-i),n=i==null?null:Math.min(100,i/e*100),r=i==null?null:Math.max(0,100-(n??0));return c.info("codex-adapter",`[cp-diagnose] context_window computed: threadId=${this.threadId??"-"} size=${e} usedTokens=${String(i)} usedPercentage=${String(n)}`),{sizeTokens:e,usedTokens:i,remainingTokens:s,usedPercentage:n,remainingPercentage:r,source:"codex:model_context_window"}}publishContextWindowSnapshot(){const e=this.buildContextWindowSnapshot();this.callbacks.onContextWindowUpdated?.(e),this.maybeScheduleAutoCompact(e)}maybeScheduleAutoCompact(e){const t=e?.usedPercentage;typeof t!="number"||t<le||this.pendingAutoCompact||this.compacting||(this.pendingAutoCompact=!0,c.info("codex-adapter",`[auto-compact] context_window usedPercentage=${t.toFixed(1)}% >= ${le}%, scheduling compact`),this.tryRunPendingAutoCompact())}tryRunPendingAutoCompact(){this.pendingAutoCompact&&(this.stopped||this.bridgeStatus==="closed"||this.currentTurnId||this.activeEventId||this.compacting||(this.pendingAutoCompact=!1,this.execCommand("compact","",this.activeSessionId??"").then(e=>{c.info("codex-adapter",`[auto-compact] compact done status=${e.status} msg=${e.message??""}`),e.status==="failed"&&/agent busy/i.test(e.message??"")&&(this.pendingAutoCompact=!0)}).catch(e=>{c.warn("codex-adapter",`[auto-compact] compact error: ${e instanceof Error?e.message:e}`)})))}parseRateLimitSnapshot(e,t=null){try{const i=e.rateLimitsByLimitId,s=this.extractRateLimitPushLimitId(e),n=!i?.codex&&!!s&&s!=="codex",r=i?.codex??(n?{}:e.rateLimits??e),o=r.primary,d=r.secondary,h=r.credits,f=l=>{if(typeof l=="number"&&Number.isFinite(l))return l;if(typeof l=="string"){const m=Number(l);if(Number.isFinite(m))return m}return 0},p=l=>typeof l=="boolean"?l:typeof l=="string"?l.toLowerCase()==="true":!1,g=l=>{if(l==null)return null;if(typeof l=="string"){const m=l.trim();if(!m)return null;const I=Number(m);return Number.isFinite(I)&&I>1e9?new Date(I*1e3).toISOString():m}if(typeof l=="number"&&Number.isFinite(l)&&l>0){const m=l>1e12?l/1e3:l;return new Date(m*1e3).toISOString()}return null},T=l=>{const m=l.resets_in_seconds??l.resetsInSeconds,I=typeof m=="number"||typeof m=="string"?Number(m):NaN;return!Number.isFinite(I)||I<=0?null:new Date(Date.now()+I*1e3).toISOString()},v=l=>({usedPercent:f(l.used_percent??l.usedPercent),windowMinutes:f(l.window_minutes??l.windowDurationMins??l.windowMinutes),resetsAt:g(l.resets_at??l.resetsAt)??T(l)}),x=()=>({usedPercent:0,windowMinutes:0,resetsAt:null}),y=(l,m)=>l??m??x(),A=()=>{const l=[];if(o&&l.push(o),d&&l.push(d),Array.isArray(r.windows))for(const m of r.windows)m&&typeof m=="object"&&l.push(m);return l.map(v).filter(m=>m.windowMinutes>0)},C=(l,m,I)=>{const S=l.filter(b=>I(b.windowMinutes));return S.length===0?null:S.reduce((b,E)=>Math.abs(E.windowMinutes-m)<Math.abs(b.windowMinutes-m)?E:b)},N=A(),L=n?t?{primary:t.primary,secondary:t.secondary}:null:N.length>0?{primary:y(C(N,300,l=>l<1440),t?.primary),secondary:y(C(N,10080,l=>l>=1440),t?.secondary)}:o||d?{primary:o?v(o):t?.primary??x(),secondary:d?v(d):t?.secondary??x()}:null;if(!L)return null;const J=(l,m)=>{if(!m||typeof m!="object"||Array.isArray(m))return null;const I=m,S=I.limitName??I.limit_name,b=typeof S=="string"&&S.trim()?S.trim():l,E=[],Y=I.primary,K=I.secondary;Y&&E.push(Y),K&&E.push(K);const Z=E.map(v).filter(k=>k.windowMinutes>0),Q=C(Z,10080,k=>k>=1440)??C(Z,300,k=>k<1440);return Q?{id:l,label:b,...Q}:null};let _;if(i&&typeof i=="object"){_=[];for(const[l,m]of Object.entries(i)){if(l==="codex")continue;const I=J(l,m);I&&_.push(I)}}else if(_=t?.extras?[...t.extras]:[],n&&s){const l=J(s,e.rateLimits??e);if(l){const m=_.findIndex(I=>I.id===l.id);m>=0?_[m]=l:_.push(l)}}return{primary:L.primary,secondary:L.secondary,credits:h?{hasCredits:p(h.has_credits??h.hasCredits),unlimited:p(h.unlimited),balance:h.balance==null?null:f(h.balance)}:t?.credits??{hasCredits:!1,unlimited:!1,balance:null},..._.length>0?{extras:_}:{}}}catch{return null}}handleApprovalRequest(e,t){const i=e.id;if(i==null)return;const s=e.method,n=`${i}`.trim(),r=`codex_${Ie(this.activeSessionId??"")}_${Ie(n)}`;if(this.approvalPolicy==="never"){this.sendApprovalDecision(i,"accept");return}this.activeEventId&&this.emitCodexEvent(s,e),this.pendingApprovals.set(r,{approvalId:r,approvalCommandId:n,sourceEventId:this.activeEventId??"",requestId:i,kind:t}),c.info("codex-adapter",`Pending approval stored: ${r} (kind=${t})`),this.clearIdleTimer(),this.stopComposing()}resolvePendingApproval(e){const t=e.params??{},i=w(t.approval_id,t.approvalId);if(i)return this.pendingApprovals.get(i)??null;const s=w(t.approval_command_id,t.approvalCommandId);if(s){for(const[,n]of this.pendingApprovals)if(n.approvalCommandId===s)return n}return null}async handleExecApprovalEvent(e){const t={approval_id:e.approval_id,approval_command_id:e.approval_command_id,session_id:e.session_id},i={action_id:"exec_approval_event",action_type:e.decision==="deny"?"exec_reject":"exec_approve",params:t},s=this.resolvePendingApproval(i);if(!s)return{delivered:!1,errorCode:"approval_not_found",errorMsg:"That approval request is no longer pending."};const n=fe[e.decision]??"accept";return this.sendApprovalDecision(s.requestId,n),this.pendingApprovals.delete(s.approvalId),this.resumeAfterApproval({...i,event_id:s.sourceEventId},t,s),{delivered:!0}}sendApprovalDecision(e,t){if(e==null||!this.process?.stdin)return;const i={jsonrpc:"2.0",id:e,result:{decision:t}};this.process.stdin.write(`${JSON.stringify(i)}
5
+ `)}async cancelActiveTurnForCompaction(){const e=this.threadId,t=this.currentTurnId,i=this.activeEventId;await this.cancel(e??"").catch(()=>{}),!(this.threadId!==e||this.currentTurnId!==t||this.activeEventId!==i||this.compacting)&&(i&&this.sendEventResultAfterFlushing(i,"canceled","compacting"),this.clearActive())}runCompaction(){if(this.currentTurnId||this.activeEventId||this.compacting)return Promise.resolve({status:"failed",message:"agent busy"});this.compacting=!0;const e=new Promise(i=>{this.compactionState={threadId:this.threadId,turnId:null,deadline:Date.now()+B,checking:!1,resolve:i}}),t=this.compactionState;return this.armCompactionCheck(),this.threadCompact().catch(i=>{if(this.compactionState!==t)return;const s=i instanceof Error?i.message:String(i),n=!t?.turnId&&(/thread.*(not found|not exist|unknown|invalid)/i.test(s)||/not found.*thread/i.test(s));this.finishCompaction({status:"failed",message:s},n)}),e}armCompactionCheck(){this.compactingTimer&&clearTimeout(this.compactingTimer);const e=this.compactionState;e?.resolve&&(this.compactingTimer=setTimeout(()=>{this.compactingTimer=null,this.checkCompactionCompletion()},Math.min(ue,Math.max(0,e.deadline-Date.now()))),this.compactingTimer.unref?.())}async checkCompactionCompletion(){const e=this.compactionState;if(!e||e.checking||this.stopped||!this.alive||this.threadId!==e.threadId||!e.resolve&&!e.turnId)return;const t=i=>{this.compactionState===e&&this.finishCompaction({status:"failed",message:i},!1)};if(e.resolve&&Date.now()>=e.deadline){t("Compaction completion was not confirmed within 10 minutes; input was not submitted");return}e.checking=!0;try{const i=await this.sendRequest("thread/read",{threadId:e.threadId,includeTurns:!0},5e3);if(this.compactionState!==e||this.stopped||!this.alive||this.threadId!==e.threadId)return;const s=i.thread?.id===e.threadId&&e.turnId?i.thread.turns?.find(n=>n.id===e.turnId):void 0;i.thread?.status?.type==="idle"&&s&&["completed","failed","interrupted"].includes(String(s.status))?this.handleTurnCompleted({threadId:e.threadId,turn:s}):s?.status==="inProgress"||i.thread?.id===e.threadId&&i.thread.status?.type==="active"?(c.info("codex-adapter","Compaction still in progress; retaining input barrier"),this.armCompactionCheck()):t("Compaction native state could not be confirmed; input was not submitted")}catch(i){t(`Compaction status check failed; input was not submitted: ${i instanceof Error?i.message:String(i)}`)}finally{e.checking=!1}}retainUnconfirmedNativeTurn(){this.compacting||this.nativeSettlement||!this.currentTurnId||!this.threadId||!this.alive||this.stopped||(this.nativeSettlement={threadId:this.threadId,turnId:this.currentTurnId,deadline:Date.now()+B,checking:!1,waiting:!0},this.armNativeSettlementCheck())}clearNativeSettlement(e){if(this.nativeSettlementTimer&&clearTimeout(this.nativeSettlementTimer),this.nativeSettlementTimer=null,this.nativeSettlement=null,this.rejectedNativeTimer&&clearTimeout(this.rejectedNativeTimer),this.rejectedNativeTimer=null,this.rejectedNativeOwner=null,e){this.failCompactionDeferred(e);for(const t of this.steerDeferred.splice(0))this.sendEventResultAfterFlushing(t.event_id,"failed",e)}}armNativeSettlementCheck(){this.nativeSettlementTimer&&clearTimeout(this.nativeSettlementTimer);const e=this.nativeSettlement;e?.waiting&&(this.nativeSettlementTimer=setTimeout(()=>{this.nativeSettlementTimer=null,this.checkNativeSettlement()},Math.min(ue,Math.max(0,e.deadline-Date.now()))),this.nativeSettlementTimer.unref?.())}async checkNativeSettlement(){const e=this.nativeSettlement;if(!e||e.checking||this.stopped||!this.alive||this.threadId!==e.threadId)return;const t=i=>{if(this.nativeSettlement===e){e.waiting=!1,this.nativeSettlementTimer&&clearTimeout(this.nativeSettlementTimer),this.nativeSettlementTimer=null,this.failCompactionDeferred(i);for(const s of this.steerDeferred.splice(0))this.sendEventResultAfterFlushing(s.event_id,"failed",i)}};if(e.waiting&&Date.now()>=e.deadline){t("Native turn completion was not confirmed within 10 minutes; input was not submitted");return}e.checking=!0;try{const i=await this.sendRequest("thread/read",{threadId:e.threadId,includeTurns:!0},5e3);if(this.nativeSettlement!==e||this.stopped||!this.alive||this.threadId!==e.threadId)return;const s=i.thread?.id===e.threadId?i.thread.turns?.find(n=>n.id===e.turnId):void 0;i.thread?.status?.type==="idle"&&s&&["completed","failed","interrupted"].includes(String(s.status))?this.handleTurnCompleted({threadId:e.threadId,turn:s}):s?.status==="inProgress"||i.thread?.id===e.threadId&&i.thread.status?.type==="active"?this.armNativeSettlementCheck():t("Native turn state could not be confirmed; input was not submitted")}catch(i){t(`Native turn status check failed; input was not submitted: ${i instanceof Error?i.message:String(i)}`)}finally{e.checking=!1}}startOrphanTurnWatch(){this.orphanTurnTimer||(this.orphanTurnTimer=setInterval(()=>this.checkOrphanTurn(),rt),this.orphanTurnTimer.unref?.())}stopOrphanTurnWatch(){this.orphanTurnTimer&&(clearInterval(this.orphanTurnTimer),this.orphanTurnTimer=null),this.orphanTurnSince=0}checkOrphanTurn(){if(!(this.currentTurnId!==null&&this.activeEventId===null&&!this.compacting&&!this.nativeSettlement)){this.orphanTurnSince=0;return}const t=Date.now();if(this.orphanTurnSince===0){this.orphanTurnSince=t;return}if(t-this.orphanTurnSince<ot)return;const i=this.currentTurnId,s=t-this.orphanTurnSince;this.currentTurnId=null,this.orphanTurnSince=0,c.warn("codex-adapter",`Orphan turn ${i} cleared after ${Math.round(s/1e3)}s with no active event: turn/completed never arrived. Adapter was reporting busy the whole time, which blocks upgrade/restart idle waits.`)}finishCompaction(e,t=!0){const i=this.compactionState;if(!i){this.failCompactionDeferred(e.message??"Compaction failed");return}this.compactingTimer&&(clearTimeout(this.compactingTimer),this.compactingTimer=null);const s=i.resolve;i.resolve=null,t&&(i.turnId&&this.retiredTurnIds.add(i.turnId),this.compactionState=null,this.compacting=!1,this.currentTurnId=null,this.stopComposing()),c.info("codex-adapter",`Compaction settled status=${e.status} nativeSettled=${t}`),s?.(e),e.status==="ok"&&t&&s?this.replayCompactionDeferred():this.failCompactionDeferred(e.message??"Compaction failed")}failCompactionDeferred(e){for(const t of this.compactionDeferred.splice(0))this.sendEventResultAfterFlushing(t.event_id,"failed",e)}replayCompactionDeferred(){if(this.compacting||this.activeEventId||this.currentTurnId||this.stopped||!this.alive)return;const e=this.compactionDeferred.shift();e&&this.startNewTurn(e,F(e.content,{messageId:e.msg_id}))}handleTurnCompleted(e){if(this.nativeSettlement){const s=this.nativeSettlement,n=e.turn;if(e.threadId!==s.threadId&&e.threadID!==s.threadId||n?.id!==s.turnId||!["completed","failed","interrupted"].includes(String(n.status)))return;this.retiredTurnIds.add(s.turnId),this.clearNativeSettlement(),this.currentTurnId=null,this.rejectedTurnStarts.size>0&&(this.rejectedTurnStarts.clear(),this.emit("resumeIntake","barrier")),this.replayCompactionDeferred(),this.replaySteerDeferred(),this.tryRunPendingAutoCompact();return}if(this.compactionState){const s=e.turn;if(e.threadId!==this.compactionState.threadId||s?.id!==this.compactionState.turnId)return;const n=s?.status;if(!["completed","failed","interrupted"].includes(String(n)))return;const r=s?.error,o=n==="completed"&&!(this.turnError&&!this.turnErrorIsRetryableOnly);this.finishCompaction({status:o?"ok":"failed",message:o?"Thread compacted":r?.message??this.turnError??`Compaction ${n}`});return}const t=this.readNotificationTurnId(e),i=e.turn;if(!(!i||!t||e.threadId!==this.threadId&&e.threadID!==this.threadId||!["completed","failed","interrupted"].includes(String(i.status))||this.currentTurnId&&t!==this.currentTurnId)&&(this.retiredTurnIds.add(t),this.currentTurnId=null,this.stopComposing(),this.activeEventId)){this.flushCodexDeltaBuffer();const s=this.activeEventId,n={event_id:s,session_id:this.activeSessionId??"",thread_id:this.threadId??void 0,codex_event_type:"codex",codex_method:"turn/completed",codex_sequence:++this.codexSequence},r=this.turnError,o=this.turnErrorIsRetryableOnly,d=this.turnHasVisibleOutput,h=i.status==="completed"&&this.completedEmptyFinalAnswerItems.size>0&&[...this.completedEmptyFinalAnswerItems.values()].every(x=>x)&&!this.turnSawNonEmptyFinalAnswer,f=this.turnSawVisibleFinalAnswer&&!this.turnHasDeliveredFinalAnswer&&!h;this.turnError=null,this.turnErrorIsRetryableOnly=!0,this.turnHasVisibleOutput=!1,this.turnSawVisibleFinalAnswer=!1,this.turnSawNonEmptyFinalAnswer=!1,this.completedEmptyFinalAnswerItems.clear(),this.turnHasDeliveredFinalAnswer=!1;const T=i.error?.message??(i.status!=="completed"?r??`Codex turn ${i.status}`:null)??(r&&!(o&&d)?r:null)??(f?"Codex final answer was observed but not delivered":null)??(!d&&!h?"Codex completed without producing any visible output":null),v=T!==null;this.callbacks.sendCodexEvent(n),this.sendEventResultAfterFlushing(s,v?"failed":"responded",T??void 0),this.clearActive()}}emitCodexEvent(e,t){if(!this.activeEventId)return;this.flushCodexDeltaBuffer();const i=we(e,t);if(i===void 0&&e==="item/completed")return;const s={event_id:this.activeEventId,session_id:this.activeSessionId??"",thread_id:this.threadId??void 0,codex_event_type:"codex",codex_method:e,codex_sequence:++this.codexSequence};i!==void 0&&(s.codex_payload=i),this.callbacks.sendCodexEvent(s)}queueCodexDeltaEvent(e){if(!this.activeEventId)return;const t=we("item/agentMessage/delta",e),i=t?.params?.delta;if(typeof i!="string"||i.length===0)return;const s=typeof t?.params?.phase=="string"?t.params.phase:void 0,n=this.activeEventId,r=this.activeSessionId??"",o=this.threadId??void 0,d=this.pendingCodexDeltaFlush;if(d&&(d.eventId!==n||d.sessionId!==r||d.threadId!==o||d.phase!==s)&&this.flushCodexDeltaBuffer(),this.pendingCodexDeltaFlush||(this.pendingCodexDeltaFlush={eventId:n,sessionId:r,threadId:o,delta:"",phase:s,timer:null}),this.pendingCodexDeltaFlush.delta+=i,this.pendingCodexDeltaFlush.delta.length>=dt){this.flushCodexDeltaBuffer();return}this.pendingCodexDeltaFlush.timer||(this.pendingCodexDeltaFlush.timer=setTimeout(()=>{if(this.activeEventId!==n){this.clearCodexDeltaBuffer();return}this.flushCodexDeltaBuffer()},at))}flushCodexDeltaBuffer(){const e=this.pendingCodexDeltaFlush;if(!e||(this.pendingCodexDeltaFlush=null,e.timer&&clearTimeout(e.timer),!e.delta))return;const t={event_id:e.eventId,session_id:e.sessionId,thread_id:e.threadId,codex_event_type:"codex",codex_method:"item/agentMessage/delta",codex_sequence:++this.codexSequence,codex_payload:{params:{delta:e.delta,...e.phase?{phase:e.phase}:{}}}};this.callbacks.sendCodexEvent(t)}clearCodexDeltaBuffer(){const e=this.pendingCodexDeltaFlush;this.pendingCodexDeltaFlush=null,e?.timer&&clearTimeout(e.timer)}sendEventResultAfterFlushing(e,t,i){e===this.activeEventId&&t!=="responded"&&this.retainUnconfirmedNativeTurn(),this.pendingCodexDeltaFlush?.eventId===e&&this.flushCodexDeltaBuffer(),e===this.activeEventId&&this.finishActiveInputs(t,i),this.callbacks.sendEventResult(e,t,i)}startComposing(){}stopComposing(){}async sendRequest(e,t,i=3e4,s){return new Promise((n,r)=>{if(!this.process?.stdin){r(new Error("Codex process not available"));return}const o=++this.requestId,d={jsonrpc:"2.0",id:o,method:e,params:t??{}},h=setTimeout(()=>{this.pendingRequests.delete(String(o)),r(new Error(`Request timeout: ${e}`))},i);this.pendingRequests.set(String(o),{resolve:p=>{p.error?r(new Error(`JSON-RPC error: ${p.error.message}`)):(s?.(),n(p.result))},reject:r,timer:h});const f=JSON.stringify(d);this.process.stdin.write(`${f}
6
6
  `)})}sendNotification(e,t){if(!this.process?.stdin)return;const i={jsonrpc:"2.0",method:e,params:t??{}};this.process.stdin.write(`${JSON.stringify(i)}
7
- `)}async initializeHandshake(){if(this.initialized)return;const e=Se(),t=await this.sendRequest("initialize",{clientInfo:{name:"grix-connector",title:"Grix Connector",version:e},capabilities:{experimentalApi:!0}},15e3);d.info("codex-adapter",`Initialized: ${JSON.stringify(t)}`),this.sendNotification("initialized"),this.initialized=!0,await this.refreshCodexModelOptions(),this.fetchRateLimits()}extractRateLimitPushLimitId(e){const t=s=>{if(!s||typeof s!="object"||Array.isArray(s))return null;const n=s.limitId??s.limit_id;return typeof n=="string"&&n.trim()?n.trim():null},i=e.rateLimitsByLimitId;if(i&&typeof i=="object"&&!Array.isArray(i)){const s=i;return s.codex?"codex":t(Object.values(s)[0])}return t(e.rateLimits??e)}refreshMainRateLimitsThrottled(){const e=Date.now();e-this.lastNonDefaultLimitRefreshAt<D.NON_DEFAULT_LIMIT_REFRESH_INTERVAL_MS||(this.lastNonDefaultLimitRefreshAt=e,this.fetchRateLimits())}fetchRateLimits(){Promise.resolve(this.sendRequest("account/rateLimits/read",void 0,1e4)).then(e=>{const t=this.parseRateLimitSnapshot(e);t&&(this.rateLimitSnapshot=t,d.info("codex-adapter",`Initial rate limits: primary=${t.primary.usedPercent.toFixed(1)}% secondary=${t.secondary.usedPercent.toFixed(1)}% credits=${t.credits.balance??"N/A"}`),this.callbacks.onRateLimitsUpdated?.(t))}).catch(e=>{d.warn("codex-adapter",`Failed to fetch rate limits: ${e instanceof Error?e.message:e}`)})}async runTurn(e,t,i,s){this.threadId||await this.createSession({cwd:this.cwd}),await this.ensureThreadResumed();const n=[],r=[],o=this.legacyDeveloperInstructionsUnsupported&&this.protocolInstructionInputInjectedThreadId!==this.threadId;o&&r.push(L);const h=(this.legacyDeveloperInstructionsUnsupported||this.profileIdentityRefreshPending)&&this.identityInputInjectedThreadId!==this.threadId;if(h){const v=le(this.callbacks.getAgentProfile?.());v&&(r.push(v.instructions),d.info("codex-adapter",`Injected agent identity through compatibility input for thread=${this.threadId} name="${v.agentName}"`))}if(this.needsHistoryInjection&&s){this.needsHistoryInjection=!1;const v=await this.loadHistoryForInjection(s);for(const w of v)n.push(w);v.length>0&&d.info("codex-adapter",`Injected ${v.length} history items`)}if(n.push({type:"text",text:e.text,text_elements:[]}),e.contextMessages&&e.contextMessages.length>0){const v=e.contextMessages.map(w=>`[${w.senderId??"unknown"}]: ${w.content}`).join(`
7
+ `)}async initializeHandshake(){if(this.initialized)return;const e=Pe(),t=await this.sendRequest("initialize",{clientInfo:{name:"grix-connector",title:"Grix Connector",version:e},capabilities:{experimentalApi:!0}},15e3);c.info("codex-adapter",`Initialized: ${JSON.stringify(t)}`),this.sendNotification("initialized"),this.initialized=!0,await this.refreshCodexModelOptions(),this.fetchRateLimits()}extractRateLimitPushLimitId(e){const t=s=>{if(!s||typeof s!="object"||Array.isArray(s))return null;const n=s.limitId??s.limit_id;return typeof n=="string"&&n.trim()?n.trim():null},i=e.rateLimitsByLimitId;if(i&&typeof i=="object"&&!Array.isArray(i)){const s=i;return s.codex?"codex":t(Object.values(s)[0])}return t(e.rateLimits??e)}refreshMainRateLimitsThrottled(){const e=Date.now();e-this.lastNonDefaultLimitRefreshAt<O.NON_DEFAULT_LIMIT_REFRESH_INTERVAL_MS||(this.lastNonDefaultLimitRefreshAt=e,this.fetchRateLimits())}fetchRateLimits(){Promise.resolve(this.sendRequest("account/rateLimits/read",void 0,1e4)).then(e=>{const t=this.parseRateLimitSnapshot(e);t&&(this.rateLimitSnapshot=t,c.info("codex-adapter",`Initial rate limits: primary=${t.primary.usedPercent.toFixed(1)}% secondary=${t.secondary.usedPercent.toFixed(1)}% credits=${t.credits.balance??"N/A"}`),this.callbacks.onRateLimitsUpdated?.(t))}).catch(e=>{c.warn("codex-adapter",`Failed to fetch rate limits: ${e instanceof Error?e.message:e}`)})}async runTurn(e,t,i,s){this.threadId||await this.createSession({cwd:this.cwd}),await this.ensureThreadResumed();const n=[],r=[],o=this.legacyDeveloperInstructionsUnsupported&&this.protocolInstructionInputInjectedThreadId!==this.threadId;o&&r.push(j);const h=(this.legacyDeveloperInstructionsUnsupported||this.profileIdentityRefreshPending)&&this.identityInputInjectedThreadId!==this.threadId;if(h){const x=me(this.callbacks.getAgentProfile?.());x&&(r.push(x.instructions),c.info("codex-adapter",`Injected agent identity through compatibility input for thread=${this.threadId} name="${x.agentName}"`))}if(this.needsHistoryInjection&&s){this.needsHistoryInjection=!1;const x=await this.loadHistoryForInjection(s);for(const y of x)n.push(y);x.length>0&&c.info("codex-adapter",`Injected ${x.length} history items`)}if(n.push({type:"text",text:e.text,text_elements:[]}),e.contextMessages&&e.contextMessages.length>0){const x=e.contextMessages.map(y=>`[${y.senderId??"unknown"}]: ${y.content}`).join(`
8
8
  `);n.push({type:"text",text:`Conversation context:
9
- ${v}`,text_elements:[]})}r.length>0&&n.push({type:"text",text:r.join(`
9
+ ${x}`,text_elements:[]})}r.length>0&&n.push({type:"text",text:r.join(`
10
10
 
11
- `),text_elements:[]});const p={threadId:this.threadId,approvalPolicy:this.approvalPolicy,input:n,model:this.model},f=pt(this.collaborationMode,this.model);f&&(p.collaborationMode=f);const g=this.effectiveReasoningEffort();g&&(p.effort=g);const y=this.effectiveServiceTier();y&&(p.serviceTier=y),await this.sendRequest("turn/start",p),o&&(this.protocolInstructionInputInjectedThreadId=this.threadId),h&&(this.identityInputInjectedThreadId=this.threadId,this.profileIdentityRefreshPending=!1),t.emitDone({status:"completed"})}async ensureThreadResumed(){if(!(!this.threadId||!this.threadResumePending))try{const e=this.effectiveReasoningEffort(),t=this.effectiveServiceTier(),i=await this.sendRequest("thread/resume",{threadId:this.threadId,approvalPolicy:this.approvalPolicy,model:this.model,excludeTurns:!0,persistExtendedHistory:!1,...e?{effort:e}:{},...t?{serviceTier:t}:{}});this.updateModelFromThreadResult(i),this.threadResumePending=!1}catch{this.threadId=null,this.needsHistoryInjection=!0,await this.startNewThread(),this.threadResumePending=!1}}async startNewThread(){const e=le(this.callbacks.getAgentProfile?.()),t=dt(e),i=this.effectiveReasoningEffort(),s=this.effectiveServiceTier(),n={approvalPolicy:this.approvalPolicy,model:this.model,cwd:this.cwd,experimentalRawEvents:!1,persistExtendedHistory:!1,...i?{effort:i}:{},...s?{serviceTier:s}:{}};try{let r;if(this.legacyDeveloperInstructionsUnsupported)r=await this.sendRequest("thread/start",n);else try{r=await this.sendRequest("thread/start",{...n,developerInstructions:t})}catch(c){if(!ct(c))throw c;this.legacyDeveloperInstructionsUnsupported=!0,d.warn("codex-adapter","Codex app-server does not support thread/start.developerInstructions; falling back to first-turn compatibility input"),r=await this.sendRequest("thread/start",n)}const o=ut(r);if(!o)throw new Error("Codex thread id is missing in thread/start result");this.threadId=o,this.identityInputInjectedThreadId=null,this.protocolInstructionInputInjectedThreadId=null,this.profileIdentityRefreshPending=!1,this.updateModelFromThreadResult(r),this.threadResumePending=!1,this.persistThreadId(o)}catch(r){const o=r instanceof Error?r.message:String(r);throw new Error(`Failed to start Codex thread: ${o}`)}}updateModelFromThreadResult(e){if(this.model)return;const t=ht(e);t&&(this.model=t,this.persistCodexContext())}persistThreadId(e){!this.bindingStore||!this.aibotSessionId||this.bindingStore.setCodexThreadId(this.aibotSessionId,e)}persistCodexContext(){!this.bindingStore||!this.aibotSessionId||this.bindingStore.setCodexContext(this.aibotSessionId,{modelId:this.model,modeId:k(this.collaborationMode)??void 0,reasoningEffort:this.effectiveReasoningEffort(),serviceTier:this.serviceTier,sandboxMode:this.sandboxMode})}async loadHistoryForInjection(e){const t=this.callbacks.getConversationLog();if(!t)return[];try{const i=await t.readHistory(e,Qe),s=[];for(const n of i){const r=(n.content??"").slice(0,et);n.direction==="inbound"?s.push({type:"text",text:r,text_elements:[]}):n.direction==="outbound"&&s.push({type:"assistant",text:r,text_elements:[]})}return s}catch(i){return d.error("codex-adapter",`Failed to load history: ${i}`),[]}}async steerTurn(e){if(!this.threadId||!this.currentTurnId)throw new Error("No active turn to steer");await this.sendRequest("turn/steer",{threadId:this.threadId,expectedTurnId:this.currentTurnId,input:[{type:"text",text:e,text_elements:[]}]})}resumeAfterApproval(e,t,i){if(!this.threadId)return;const s=e.event_id?.trim()||`local_action_${e.action_id.trim()}`,n=x(t.session_id,t.sessionId)??this.activeSessionId??"";if(!n)return;const r=this.threadId,o=new z(r),c={adapterSessionId:r,text:""};this.activeEventId=s,this.activeSessionId=n,this.visibleAgentMessageIds.clear(),this.hiddenAgentMessageIds.clear(),this.agentMessagePhases.clear(),this.deliveredAgentMessageIds.clear(),this.deliveredThinkingAgentMessageIds.clear(),this.turnSawVisibleFinalAnswer=!1,this.turnHasDeliveredFinalAnswer=!1,this.codexSequence=0,this.runTurn(c,o,s,n).catch(h=>{d.error("codex-adapter",`Post-approval turn failed: ${h}`),this.sendEventResultAfterFlushing(s,"failed",h instanceof Error?h.message:String(h)),this.clearActive()}),this.resetIdleTimer(s)}clearActive(e){const t=this.activeEventId;if(this.flushCodexDeltaBuffer(),this.stopComposing(),this.activeEventId=null,this.activeSessionId=null,this.currentTurnId=null,this.visibleAgentMessageIds.clear(),this.hiddenAgentMessageIds.clear(),this.agentMessagePhases.clear(),this.deliveredAgentMessageIds.clear(),this.deliveredThinkingAgentMessageIds.clear(),this.turnSawVisibleFinalAnswer=!1,this.turnHasDeliveredFinalAnswer=!1,this.inFlightToolOps=0,this.consecutivePingFailures=0,this.currentTurnStartedAt=0,this.preflightCheckComplete=!1,this.clearIdleTimer(),this.pendingApprovals.clear(),t&&e?.emitEventDone!==!1){const i=this.rawCaptureRelay;i?i.completeEvent(t).catch(s=>{d.warn("codex-adapter",`Raw API audit capture did not settle cleanly: ${s instanceof Error?s.message:String(s)}`)}).finally(()=>this.emit("eventDone",t)):this.emit("eventDone",t)}this.replaySteerDeferred(),e?.runPendingAutoCompact!==!1&&this.tryRunPendingAutoCompact()}replaySteerDeferred(){if(this.steerDeferred.length===0)return;const e=this.steerDeferred.splice(0);d.info("codex-adapter",`Replaying ${e.length} steer-deferred event(s) after turn ended`);for(const t of e)this.deliverInboundEvent(t)}resetIdleTimer(e){const t=Date.now();this.lastProgressAt=t,this.lastIdleCheckAt=t,this.activityGeneration+=1,this.lastIdleCheckGeneration=this.activityGeneration,this.idleNoProgressCount=0,this.consecutivePingFailures=0,this.armIdleTimer(e)}armIdleTimer(e,t=Number.POSITIVE_INFINITY){this.clearIdleTimer();const i=Date.now(),s=this.inFlightToolOps>0?Ge:Ve,n=this.turnInactivityTimeoutMs===null?Number.POSITIVE_INFINITY:this.lastProgressAt+this.turnInactivityTimeoutMs-i,r=this.currentTurnStartedAt>0&&!this.preflightCheckComplete?this.currentTurnStartedAt+U-i:Number.POSITIVE_INFINITY,o=Math.max(0,Math.min(s,n,r,t));this.idleTimer=setTimeout(()=>{this.onIdleTimeout(e,o)},o)}async onIdleTimeout(e,t){if(this.activeEventId!==e)return;const i=this.lastIdleCheckAt,s=this.lastIdleCheckGeneration,n=this.ping(Je).catch(()=>!1),r=this.checkSessionActivitySince(i),[o,c]=await Promise.all([n,r]);if(this.activeEventId!==e)return;const h=this.activityGeneration>s;if(this.lastIdleCheckAt=Date.now(),this.lastIdleCheckGeneration=this.activityGeneration,!this.preflightCheckComplete&&this.currentTurnStartedAt>0&&Date.now()-this.currentTurnStartedAt>=U){const f=this.activityGeneration,g=await this.inspectCurrentTurnProgress();if(this.activeEventId!==e)return;if(this.activityGeneration>f)this.preflightCheckComplete=!0;else if(g==="task_started_only"){this.declareRecoverablePreflightStuck(e,`Codex preflight stalled for ${Math.round(U/1e3)}s before model execution`);return}else g==="unknown"?this.currentTurnStartedAt=Date.now():this.preflightCheckComplete=!0}if(h||c){c&&(d.info("codex-adapter",`Idle timer: no stream output but rollout still being written, continuing: ${e}`),this.lastProgressAt=Date.now()),this.idleNoProgressCount=0,this.consecutivePingFailures=0,this.armIdleTimer(e);return}const p=Date.now()-this.lastProgressAt;if(this.turnInactivityTimeoutMs!==null&&p>=this.turnInactivityTimeoutMs){d.error("codex-adapter",`Turn inactive ${Math.round(p/1e3)}s \u2265 cap ${Math.round(this.turnInactivityTimeoutMs/1e3)}s, declaring stuck: ${e}`),this.declareStuck(e,`turn inactivity timeout after ${Math.round(p/1e3)}s with no Codex activity`);return}if(!o){if(this.consecutivePingFailures+=1,this.consecutivePingFailures<se){d.warn("codex-adapter",`Agent idle ${t/1e3}s and ping failed (${this.consecutivePingFailures}/${se}); retrying liveness probe: ${e}`),this.armIdleTimer(e,Ye);return}d.error("codex-adapter",`Agent idle ${t/1e3}s and ping failed ${this.consecutivePingFailures}x, declaring stuck: ${e}`),this.declareStuck(e,`agent idle ${t/1e3}s, ping failed ${this.consecutivePingFailures}x`);return}this.consecutivePingFailures=0,this.idleNoProgressCount++,d.info("codex-adapter",`Idle timer: ping ok, no stream progress (cycle=${this.idleNoProgressCount}), keeping active turn alive${this.turnInactivityTimeoutMs===null?"":` until inactivity cap (${Math.round(this.turnInactivityTimeoutMs/6e4)}min)`}: ${e}`),this.armIdleTimer(e)}declareStuck(e,t){this.sendEventResultAfterFlushing(e,"failed",t),this.clearActive(),this.emit("stuck")}declareRecoverablePreflightStuck(e,t){const i=this.activeSessionId??"";d.error("codex-adapter",`${t}; restarting adapter and replaying event: ${e}`),this.clearActive({runPendingAutoCompact:!1,emitEventDone:!1}),this.emit("internalError",{eventId:e,sessionId:i,errorMsg:t})}async inspectCurrentTurnProgress(){if(!this.threadId||!this.currentTurnId)return"unknown";try{return await $e(this.threadId,this.currentTurnId,this.codexHome)}catch{return"unknown"}}async checkSessionActivitySince(e){if(!this.threadId)return!1;try{return await Oe(this.threadId,e,this.codexHome)}catch{return!1}}isLongRunningToolItemType(e){if(!e)return!1;const t=e.toLowerCase();return t==="commandexecution"||t==="command_execution"||t==="item/commandexecution"||t==="filechange"||t==="file_change"||t==="item/filechange"}normalizeAgentMessagePhase(e){return typeof e!="string"?void 0:e.trim().toLowerCase()||void 0}resolveAgentMessagePhase(e,t){return this.normalizeAgentMessagePhase(t)??(e?this.agentMessagePhases.get(e):void 0)}extractAgentMessageText(e){return e?typeof e.text=="string"&&e.text.length>0?e.text:typeof e.message=="string"&&e.message.length>0?e.message:Array.isArray(e.content)&&e.content.map(i=>{if(typeof i=="string")return i;if(!i||typeof i!="object"||Array.isArray(i))return"";const s=i;return typeof s.text=="string"?s.text:""}).join("")||void 0:void 0}recordDeliveredAgentMessage(e,t){this.turnHasVisibleOutput=!0,e&&this.deliveredAgentMessageIds.add(e),t==="final_answer"&&(this.turnSawVisibleFinalAnswer=!0,this.turnHasDeliveredFinalAnswer=!0)}recordDeliveredThinkingAgentMessage(e){e&&this.deliveredThinkingAgentMessageIds.add(e)}shouldSuppressAgentMessageDeltaDuringToolRun(e,t){return t==="final_answer"||this.inFlightToolOps<=0?!1:(d.info("codex-adapter",`Suppressing agentMessage delta during tool run item_id=${e??"unknown"}`),!0)}clearIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null)}rejectAllPending(e){for(const[,t]of this.pendingRequests)clearTimeout(t.timer),t.reject(new Error(`Request canceled: ${e}`));this.pendingRequests.clear(),this.pendingApprovals.clear()}}const ce={allow:"accept","allow-once":"accept","allow-always":"acceptForSession",deny:"deny"};function le(a){const e=a?.agentName?.trim()??"",t=a?.introduction?.trim()??"";if(!e&&!t)return;const i=["[system-identity]"];return e&&i.push(`Your name is "${e}".`),t&&i.push(`Your self-introduction: ${t}`),i.push("Treat this as an out-of-band instruction; do not echo or repeat it in your replies."),i.push("[/system-identity]"),{agentName:e,instructions:i.join(`
12
- `)}}function dt(a){return a?`${a.instructions}
11
+ `),text_elements:[]});const f={threadId:this.threadId,approvalPolicy:this.approvalPolicy,input:n,model:this.model},p=gt(this.collaborationMode,this.model);p&&(f.collaborationMode=p);const g=this.effectiveReasoningEffort();g&&(f.effort=g);const T=this.effectiveServiceTier();if(T&&(f.serviceTier=T),i&&this.activeEventId!==i)return;if(i){try{await this.waitLoopTracker.prepare(this.threadId,this.codexHome)}catch{}if(this.activeEventId!==i)return}this.startingEventId=i??null;let v;try{v=await this.sendRequest("turn/start",f)}finally{this.startingEventId===i&&(this.startingEventId=null)}if(i&&this.rejectedTurnStarts.has(i)){v.turn?.id&&(this.rejectedTurnStarts.delete(i),this.nativeSettlement||(this.currentTurnId=v.turn.id,this.retainUnconfirmedNativeTurn(),this.threadId&&this.interruptRejectedTurn(i,this.threadId,v.turn.id)),this.emit("resumeIntake","barrier"));return}i&&this.activeEventId===i&&!this.compacting&&!this.nativeSettlement&&!this.currentTurnId&&v.turn?.id&&!this.retiredTurnIds.has(v.turn.id)&&(this.currentTurnId=v.turn.id,this.emit("activeInputReady")),o&&(this.protocolInstructionInputInjectedThreadId=this.threadId),h&&(this.identityInputInjectedThreadId=this.threadId,this.profileIdentityRefreshPending=!1),t.emitDone({status:"completed"})}async ensureThreadResumed(){if(!(!this.threadId||!this.threadResumePending))try{const e=this.effectiveReasoningEffort(),t=this.effectiveServiceTier(),i=await this.sendRequest("thread/resume",{threadId:this.threadId,approvalPolicy:this.approvalPolicy,model:this.model,excludeTurns:!0,persistExtendedHistory:!1,...e?{effort:e}:{},...t?{serviceTier:t}:{}});this.updateModelFromThreadResult(i),this.threadResumePending=!1}catch{this.threadId=null,this.needsHistoryInjection=!0,await this.startNewThread(),this.threadResumePending=!1}}async startNewThread(){const e=me(this.callbacks.getAgentProfile?.()),t=ut(e),i=this.effectiveReasoningEffort(),s=this.effectiveServiceTier(),n={approvalPolicy:this.approvalPolicy,model:this.model,cwd:this.cwd,experimentalRawEvents:!1,persistExtendedHistory:!1,...i?{effort:i}:{},...s?{serviceTier:s}:{}};try{let r;if(this.legacyDeveloperInstructionsUnsupported)r=await this.sendRequest("thread/start",n);else try{r=await this.sendRequest("thread/start",{...n,developerInstructions:t})}catch(d){if(!ht(d))throw d;this.legacyDeveloperInstructionsUnsupported=!0,c.warn("codex-adapter","Codex app-server does not support thread/start.developerInstructions; falling back to first-turn compatibility input"),r=await this.sendRequest("thread/start",n)}const o=ft(r);if(!o)throw new Error("Codex thread id is missing in thread/start result");this.threadId=o,this.identityInputInjectedThreadId=null,this.protocolInstructionInputInjectedThreadId=null,this.profileIdentityRefreshPending=!1,this.updateModelFromThreadResult(r),this.threadResumePending=!1,this.persistThreadId(o)}catch(r){const o=r instanceof Error?r.message:String(r);throw new Error(`Failed to start Codex thread: ${o}`)}}updateModelFromThreadResult(e){if(this.model)return;const t=mt(e);t&&(this.model=t,this.persistCodexContext())}persistThreadId(e){!this.bindingStore||!this.aibotSessionId||this.bindingStore.setCodexThreadId(this.aibotSessionId,e)}persistCodexContext(){!this.bindingStore||!this.aibotSessionId||this.bindingStore.setCodexContext(this.aibotSessionId,{modelId:this.model,modeId:M(this.collaborationMode)??void 0,reasoningEffort:this.effectiveReasoningEffort(),serviceTier:this.serviceTier,sandboxMode:this.sandboxMode})}async loadHistoryForInjection(e){const t=this.callbacks.getConversationLog();if(!t)return[];try{const i=await t.readHistory(e,st),s=[];for(const n of i){const r=(n.content??"").slice(0,nt);n.direction==="inbound"?s.push({type:"text",text:r,text_elements:[]}):n.direction==="outbound"&&s.push({type:"assistant",text:r,text_elements:[]})}return s}catch(i){return c.error("codex-adapter",`Failed to load history: ${i}`),[]}}async steerTurn(e,t,i){if(!this.threadId||!this.currentTurnId)throw new Error("No active turn to steer");const s=[{type:"text",text:e,text_elements:[]}];if(t){const n=JSON.parse(t);n.length>0&&s.push({type:"text",text:`Conversation context:
12
+ ${n.map(r=>`[${r.sender_id??"unknown"}]: ${r.content}`).join(`
13
+ `)}`,text_elements:[]})}await this.sendRequest("turn/steer",{threadId:this.threadId,expectedTurnId:this.currentTurnId,input:s},3e4,i)}resumeAfterApproval(e,t,i){if(!this.threadId)return;const s=e.event_id?.trim()||`local_action_${e.action_id.trim()}`,n=w(t.session_id,t.sessionId)??this.activeSessionId??"";if(!n)return;const r=this.threadId,o=new X(r),d={adapterSessionId:r,text:""};this.activeEventId=s,this.activeSessionId=n,this.visibleAgentMessageIds.clear(),this.hiddenAgentMessageIds.clear(),this.agentMessagePhases.clear(),this.deliveredAgentMessageIds.clear(),this.deliveredThinkingAgentMessageIds.clear(),this.turnSawVisibleFinalAnswer=!1,this.turnSawNonEmptyFinalAnswer=!1,this.completedEmptyFinalAnswerItems.clear(),this.turnHasDeliveredFinalAnswer=!1,this.codexSequence=0,this.runTurn(d,o,s,n).catch(h=>{c.error("codex-adapter",`Post-approval turn failed: ${h}`),this.sendEventResultAfterFlushing(s,"failed",h instanceof Error?h.message:String(h)),this.clearActive()}),this.resetIdleTimer(s)}clearActive(e){const t=this.activeEventId;if(this.finishActiveInputs("failed","Codex turn ownership ended before input completion"),this.flushCodexDeltaBuffer(),this.stopComposing(),this.activeEventId=null,this.activeSessionId=null,this.compacting||(this.retainUnconfirmedNativeTurn(),this.nativeSettlement||(this.currentTurnId=null)),this.visibleAgentMessageIds.clear(),this.hiddenAgentMessageIds.clear(),this.agentMessagePhases.clear(),this.deliveredAgentMessageIds.clear(),this.deliveredThinkingAgentMessageIds.clear(),this.turnSawVisibleFinalAnswer=!1,this.turnSawNonEmptyFinalAnswer=!1,this.completedEmptyFinalAnswerItems.clear(),this.turnHasDeliveredFinalAnswer=!1,this.inFlightToolOps=0,this.consecutivePingFailures=0,this.currentTurnStartedAt=0,this.preflightCheckComplete=!1,this.clearIdleTimer(),this.clearWaitLoopWatch(),this.pendingApprovals.clear(),t&&e?.emitEventDone!==!1){const i=this.rawCaptureRelay;i?i.completeEvent(t).catch(s=>{c.warn("codex-adapter",`Raw API audit capture did not settle cleanly: ${s instanceof Error?s.message:String(s)}`)}).finally(()=>this.emit("eventDone",t)):this.emit("eventDone",t)}this.nativeSettlement||(this.replayCompactionDeferred(),this.replaySteerDeferred(),e?.runPendingAutoCompact!==!1&&this.tryRunPendingAutoCompact())}replaySteerDeferred(){if(this.steerDeferred.length===0)return;const e=this.steerDeferred.splice(0);c.info("codex-adapter",`Replaying ${e.length} steer-deferred event(s) after turn ended`);for(const t of e)this.deliverInboundEvent(t)}resetIdleTimer(e){const t=Date.now();this.waitLoopTracker.pureWait||(this.lastProgressAt=t),this.lastIdleCheckAt=t,this.activityGeneration+=1,this.lastIdleCheckGeneration=this.activityGeneration,this.idleNoProgressCount=0,this.consecutivePingFailures=0,this.waitLoopTimer||(this.waitLoopTimer=setInterval(()=>{this.checkWaitLoop(e)},oe),this.waitLoopTimer.unref?.()),this.armIdleTimer(e)}clearWaitLoopWatch(){this.waitLoopTimer&&clearInterval(this.waitLoopTimer),this.waitLoopTimer=null,this.waitLoopTracker=new ie,this.waitLoopChildTools.clear()}async checkWaitLoop(e){if(this.waitLoopCheckRunning||this.activeEventId!==e||!this.threadId||!this.currentTurnId||this.compacting||this.pendingApprovals.size>0)return;const t=this.waitLoopTracker,i=this.currentTurnId,s=this.waitLoopProgressGeneration;this.waitLoopCheckRunning=!0;try{const n=await t.inspect(this.threadId,i,this.codexHome,Date.now());if(this.activeEventId!==e||this.currentTurnId!==i||t!==this.waitLoopTracker)return;if(this.waitLoopProgressGeneration!==s||this.waitLoopChildTools.size>0||this.inFlightToolOps>0){t.noteProgress();return}if(n!==null&&Date.now()-n>=Ke){const r="repeated clock.sleep without useful progress for 5 minutes; end this turn and resume on owner input";this.rejectEventOutput(e),this.callbacks.sendEventResult(e,"failed",r)}}catch{t.reset()}finally{this.waitLoopCheckRunning=!1}}armIdleTimer(e,t=Number.POSITIVE_INFINITY){this.clearIdleTimer();const i=Date.now(),s=this.inFlightToolOps>0?Ye:oe,n=this.turnInactivityTimeoutMs===null||this.waitLoopTracker.pureWait?Number.POSITIVE_INFINITY:this.lastProgressAt+this.turnInactivityTimeoutMs-i,r=this.currentTurnStartedAt>0&&!this.preflightCheckComplete?this.currentTurnStartedAt+W-i:Number.POSITIVE_INFINITY,o=Math.max(0,Math.min(s,n,r,t));this.idleTimer=setTimeout(()=>{this.onIdleTimeout(e,o)},o)}async onIdleTimeout(e,t){if(this.activeEventId!==e)return;const i=this.lastIdleCheckAt,s=this.lastIdleCheckGeneration,n=this.ping(Qe).catch(()=>!1),r=this.checkSessionActivitySince(i),[o,d]=await Promise.all([n,r]);if(this.activeEventId!==e)return;const h=this.activityGeneration>s;if(this.lastIdleCheckAt=Date.now(),this.lastIdleCheckGeneration=this.activityGeneration,!this.preflightCheckComplete&&this.currentTurnStartedAt>0&&Date.now()-this.currentTurnStartedAt>=W){const p=this.activityGeneration,g=await this.inspectCurrentTurnProgress();if(this.activeEventId!==e)return;if(this.activityGeneration>p)this.preflightCheckComplete=!0;else if(g==="task_started_only"){this.declareRecoverablePreflightStuck(e,`Codex preflight stalled for ${Math.round(W/1e3)}s before model execution`);return}else g==="unknown"?this.currentTurnStartedAt=Date.now():this.preflightCheckComplete=!0}if(h||d){d&&(c.info("codex-adapter",`Idle timer: no stream output but rollout still being written, continuing: ${e}`),this.waitLoopTracker.pureWait||(this.lastProgressAt=Date.now())),this.idleNoProgressCount=0,this.consecutivePingFailures=0,this.armIdleTimer(e);return}const f=Date.now()-this.lastProgressAt;if(this.turnInactivityTimeoutMs!==null&&f>=this.turnInactivityTimeoutMs){c.error("codex-adapter",`Turn inactive ${Math.round(f/1e3)}s \u2265 cap ${Math.round(this.turnInactivityTimeoutMs/1e3)}s, declaring stuck: ${e}`),this.declareStuck(e,`turn inactivity timeout after ${Math.round(f/1e3)}s with no Codex activity`);return}if(!o){if(this.consecutivePingFailures+=1,this.consecutivePingFailures<ae){c.warn("codex-adapter",`Agent idle ${t/1e3}s and ping failed (${this.consecutivePingFailures}/${ae}); retrying liveness probe: ${e}`),this.armIdleTimer(e,et);return}c.error("codex-adapter",`Agent idle ${t/1e3}s and ping failed ${this.consecutivePingFailures}x, declaring stuck: ${e}`),this.declareStuck(e,`agent idle ${t/1e3}s, ping failed ${this.consecutivePingFailures}x`);return}this.consecutivePingFailures=0,this.idleNoProgressCount++,c.info("codex-adapter",`Idle timer: ping ok, no stream progress (cycle=${this.idleNoProgressCount}), keeping active turn alive${this.turnInactivityTimeoutMs===null?"":` until inactivity cap (${Math.round(this.turnInactivityTimeoutMs/6e4)}min)`}: ${e}`),this.armIdleTimer(e)}declareStuck(e,t){this.sendEventResultAfterFlushing(e,"failed",t),this.clearActive(),this.emit("stuck")}declareRecoverablePreflightStuck(e,t){const i=this.activeSessionId??"";c.error("codex-adapter",`${t}; restarting adapter and replaying event: ${e}`),this.clearActive({runPendingAutoCompact:!1,emitEventDone:!1}),this.emit("internalError",{eventId:e,sessionId:i,errorMsg:t})}async inspectCurrentTurnProgress(){if(!this.threadId||!this.currentTurnId)return"unknown";try{return await je(this.threadId,this.currentTurnId,this.codexHome)}catch{return"unknown"}}async checkSessionActivitySince(e){if(!this.threadId)return!1;try{return await Fe(this.threadId,e,this.codexHome)}catch{return!1}}isLongRunningToolItemType(e){if(!e)return!1;const t=e.toLowerCase();return t==="commandexecution"||t==="command_execution"||t==="item/commandexecution"||t==="filechange"||t==="file_change"||t==="item/filechange"}normalizeAgentMessagePhase(e){return typeof e!="string"?void 0:e.trim().toLowerCase()||void 0}resolveAgentMessagePhase(e,t){return this.normalizeAgentMessagePhase(t)??(e?this.agentMessagePhases.get(e):void 0)}extractAgentMessageText(e){if(!e)return;if(typeof e.text=="string"&&e.text.length>0)return e.text;if(typeof e.message=="string"&&e.message.length>0)return e.message;if(!Array.isArray(e.content))return e.text===""||e.message===""?"":void 0;const t=e.content.map(i=>{if(typeof i=="string")return i;if(!i||typeof i!="object"||Array.isArray(i))return;const s=i;return typeof s.text=="string"?s.text:void 0});return t.join("")||(t.every(i=>i!==void 0)?"":void 0)}recordFinalAnswerEvidence(e,t,i=!1){this.turnSawVisibleFinalAnswer=!0,t&&(this.turnSawNonEmptyFinalAnswer=!0);const s=typeof e=="string"&&e?e:void 0;(i||!this.completedEmptyFinalAnswerItems.has(s))&&this.completedEmptyFinalAnswerItems.set(s,s!==void 0&&i&&t==="")}recordDeliveredAgentMessage(e,t){this.turnHasVisibleOutput=!0,e&&this.deliveredAgentMessageIds.add(e),t==="final_answer"&&(this.turnSawVisibleFinalAnswer=!0,this.turnSawNonEmptyFinalAnswer=!0,this.turnHasDeliveredFinalAnswer=!0)}recordDeliveredThinkingAgentMessage(e){e&&this.deliveredThinkingAgentMessageIds.add(e)}shouldSuppressAgentMessageDeltaDuringToolRun(e,t){return t==="final_answer"||this.inFlightToolOps<=0?!1:(c.info("codex-adapter",`Suppressing agentMessage delta during tool run item_id=${e??"unknown"}`),!0)}clearIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null)}rejectAllPending(e){for(const[,t]of this.pendingRequests)clearTimeout(t.timer),t.reject(new Error(`Request canceled: ${e}`));this.pendingRequests.clear(),this.pendingApprovals.clear()}}const fe={allow:"accept","allow-once":"accept","allow-always":"acceptForSession",deny:"deny"};function me(a){const e=a?.agentName?.trim()??"",t=a?.introduction?.trim()??"";if(!e&&!t)return;const i=["[system-identity]"];return e&&i.push(`Your name is "${e}".`),t&&i.push(`Your self-introduction: ${t}`),i.push("Treat this as an out-of-band instruction; do not echo or repeat it in your replies."),i.push("[/system-identity]"),{agentName:e,instructions:i.join(`
14
+ `)}}function ut(a){return a?`${a.instructions}
13
15
 
14
- ${L}`:L}function ct(a){return a instanceof Error?/unknown\s+(?:field|parameter|property)[^\n]*(?:developerInstructions|developer_instructions)/i.test(a.message):!1}function lt(a){return a&&a.length>0?[...a]:["app-server"]}function u(a){if(typeof a!="string")return;const e=a.trim();return e||void 0}function ut(a){if(!a||typeof a!="object")return null;const e=a,t=e.thread&&typeof e.thread=="object"?e.thread:void 0;return x(u(e.threadId),u(e.threadID),u(t?.id))??null}function ht(a){return!a||typeof a!="object"?null:u(a.model)??null}function k(a){const e=a?.trim().toLowerCase();return e==="default"||e==="plan"?e:null}function pt(a,e){const t=k(a),i=u(e);if(!(!t||!i))return{mode:t,settings:{model:i}}}function ft(a){if(!Array.isArray(a))return[];const e=[];for(const t of a){if(typeof t=="string"){const r=t.trim();r&&e.push(xt(r,S(r)));continue}if(!t||typeof t!="object")continue;const i=t,s=x(u(i.id),u(i.model_id),u(i.modelId),u(i.value));if(!s)continue;const n=x(u(i.displayName),u(i.display_name),u(i.name),u(i.label))??S(s);e.push({id:s,displayName:n,defaultReasoningEffort:u(i.defaultReasoningEffort)??null,supportedReasoningEfforts:q(i.supportedReasoningEfforts),defaultServiceTier:u(i.defaultServiceTier)??null,serviceTiers:B(i.serviceTiers),isDefault:i.isDefault===!0})}return e}function ue(a){const e=a.toLowerCase().replace(/\/+$/,"");return!(e==="https://api.openai.com"||e==="https://api.openai.com/v1"||e.endsWith(".openai.com"))}function mt(a){try{const e=new URL(a).hostname.toLowerCase();return e==="localhost"||e==="127.0.0.1"||e==="::1"}catch{return!1}}async function gt(a,e){const i=`${a.replace(/\/+$/,"")}/models`,s={Accept:"application/json"};e&&(s.Authorization=`Bearer ${e}`);const n=new AbortController,r=setTimeout(()=>n.abort(),1e4);try{const o=await fetch(i,{headers:s,signal:n.signal});if(!o.ok)return[];const c=await o.json();return vt(c)}finally{clearTimeout(r)}}function vt(a){if(!a||typeof a!="object")return[];const e=a,t=Array.isArray(e.data)?e.data:[],i=Array.isArray(e.models)?e.models:[],s=t.length>0?t:i,n=[];for(const r of s){if(typeof r=="string"){const p=r.trim();if(!p)continue;n.push({id:p,displayName:S(p),defaultReasoningEffort:null,supportedReasoningEfforts:[],defaultServiceTier:null,serviceTiers:[],isDefault:!1});continue}if(!r||typeof r!="object")continue;const o=r,c=x(u(o.id),u(o.model));if(!c)continue;const h=x(u(o.displayName),u(o.display_name),u(o.name))??S(c);n.push({id:c,displayName:h,defaultReasoningEffort:u(o.defaultReasoningEffort)??null,supportedReasoningEfforts:q(o.supportedReasoningEfforts),defaultServiceTier:u(o.defaultServiceTier)??null,serviceTiers:B(o.serviceTiers),isDefault:o.isDefault===!0})}return n}function It(a){if(!a||typeof a!="object")return{models:[],nextCursor:null};const e=a,t=Array.isArray(e.data)?e.data:[],i=[];for(const s of t){if(!s||typeof s!="object")continue;const n=s;if(n.hidden===!0)continue;const r=x(u(n.id),u(n.model));if(!r)continue;const o=x(u(n.displayName),u(n.display_name),u(n.name))??S(r);i.push({id:r,displayName:o,defaultReasoningEffort:u(n.defaultReasoningEffort)??null,supportedReasoningEfforts:q(n.supportedReasoningEfforts),defaultServiceTier:u(n.defaultServiceTier)??null,serviceTiers:B(n.serviceTiers),isDefault:n.isDefault===!0})}return{models:i,nextCursor:u(e.nextCursor)??null}}function he(a){const e=[],t=new Set;for(const i of a){const s=i.id.trim(),n=s.toLowerCase();!s||t.has(n)||(t.add(n),e.push({id:s,displayName:i.displayName.trim()||s,defaultReasoningEffort:i.defaultReasoningEffort,supportedReasoningEfforts:[...i.supportedReasoningEfforts],defaultServiceTier:i.defaultServiceTier,serviceTiers:[...i.serviceTiers],isDefault:i.isDefault}))}return e}function xt(a,e){return{id:a,displayName:e,defaultReasoningEffort:null,supportedReasoningEfforts:[],defaultServiceTier:null,serviceTiers:[],isDefault:!1}}function q(a){if(!Array.isArray(a))return[];const e=[];for(const t of a){if(typeof t=="string"){const s=t.trim();s&&e.push(s);continue}if(!t||typeof t!="object")continue;const i=u(t.reasoningEffort);i&&e.push(i)}return e}function B(a){if(!Array.isArray(a))return[];const e=[];for(const t of a){if(typeof t=="string"){const n=t.trim();n&&e.push({id:n,displayName:n,description:null});continue}if(!t||typeof t!="object")continue;const i=t,s=u(i.id);s&&e.push({id:s,displayName:x(u(i.name),u(i.displayName),u(i.display_name))??s,description:u(i.description)??null})}return e}function S(a){return a.split(/[-_\s]+/).filter(Boolean).map(e=>/^(gpt|codex|o\d+)$/i.test(e)?e.toUpperCase():e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}function x(...a){for(const e of a)if(e!=null){if(typeof e=="string"&&!e.trim())continue;return e}}function pe(a){return a.trim().replace(/[^a-zA-Z0-9._:-]+/g,"_")}function fe(a,e){switch(a){case"turn/completed":return;case"item/agentMessage/delta":{const t=e?.params??{};if(typeof t.delta!="string"||t.delta.length===0)return;const i=typeof t.phase=="string"&&t.phase.trim()?t.phase.trim().toLowerCase():void 0;return{params:{delta:t.delta,...i?{phase:i}:{}}}}case"item/completed":{const i=(e?.params??{}).item;if(!i||typeof i!="object"||i.type!=="commandExecution")return;const s=yt(i.command);return{params:{item:{type:"commandExecution",...s!==void 0?{command:s}:{},...i.exitCode!==void 0?{exitCode:i.exitCode}:{},...i.durationMs!==void 0?{durationMs:i.durationMs}:{}}}}}case"item/permissions/requestApproval":return W(e,"permission");case"item/commandExecution/requestApproval":return W(e,"exec");case"item/fileChange/requestApproval":return W(e,"file");default:return}}function W(a,e){if(a==null||typeof a!="object")return;const t=a.params??{};if(t==null||typeof t!="object"||Array.isArray(t))return;const i={},s=(...r)=>{for(const o of r)t[o]!==void 0&&(i[o]=t[o])};e==="permission"?s("threadId","turnId","itemId","reason","permissions"):e==="exec"?s("command","commandLine","command_line","argv","args","availableDecisions","cwd","workingDirectory","working_directory"):s("path","filePath","file_path","targetPath","target_path","paths","files","availableDecisions","cwd","workingDirectory","working_directory");const n={params:i};return a.id!==void 0&&(n.id=a.id),typeof a.method=="string"&&a.method&&(n.method=a.method),n}function yt(a){if(typeof a!="string")return;const e=a.trim();if(e)return e.length<=ne?e:e.slice(0,ne-re.length)+re}class z extends K{adapterSessionId;constructor(e){super(),this.adapterSessionId=e}emitDone(e){this.emit("done",e)}emitError(e){if(this.listenerCount("error")===0){d.warn("codex-adapter",`Prompt handle error (no listeners): ${e.message}`);return}this.emit("error",e)}async cancel(){}}function wt(a){return["cannot steer a compact turn","turn not found","turn already completed","no active turn"].some(t=>a.includes(t))}export{D as CodexAdapter,de as resolveCodexCommandPath,fe as trimCodexPayloadForWire};
16
+ ${j}`:j}function ht(a){return a instanceof Error?/unknown\s+(?:field|parameter|property)[^\n]*(?:developerInstructions|developer_instructions)/i.test(a.message):!1}function pt(a){return a&&a.length>0?[...a]:["app-server"]}function u(a){if(typeof a!="string")return;const e=a.trim();return e||void 0}function ft(a){if(!a||typeof a!="object")return null;const e=a,t=e.thread&&typeof e.thread=="object"?e.thread:void 0;return w(u(e.threadId),u(e.threadID),u(t?.id))??null}function mt(a){return!a||typeof a!="object"?null:u(a.model)??null}function M(a){const e=a?.trim().toLowerCase();return e==="default"||e==="plan"?e:null}function gt(a,e){const t=M(a),i=u(e);if(!(!t||!i))return{mode:t,settings:{model:i}}}function vt(a){if(!Array.isArray(a))return[];const e=[];for(const t of a){if(typeof t=="string"){const r=t.trim();r&&e.push(yt(r,R(r)));continue}if(!t||typeof t!="object")continue;const i=t,s=w(u(i.id),u(i.model_id),u(i.modelId),u(i.value));if(!s)continue;const n=w(u(i.displayName),u(i.display_name),u(i.name),u(i.label))??R(s);e.push({id:s,displayName:n,defaultReasoningEffort:u(i.defaultReasoningEffort)??null,supportedReasoningEfforts:z(i.supportedReasoningEfforts),defaultServiceTier:u(i.defaultServiceTier)??null,serviceTiers:G(i.serviceTiers),isDefault:i.isDefault===!0})}return e}function ge(a){const e=a.toLowerCase().replace(/\/+$/,"");return!(e==="https://api.openai.com"||e==="https://api.openai.com/v1"||e.endsWith(".openai.com"))}function It(a){try{const e=new URL(a).hostname.toLowerCase();return e==="localhost"||e==="127.0.0.1"||e==="::1"}catch{return!1}}async function wt(a,e){const i=`${a.replace(/\/+$/,"")}/models`,s={Accept:"application/json"};e&&(s.Authorization=`Bearer ${e}`);const n=new AbortController,r=setTimeout(()=>n.abort(),1e4);try{const o=await fetch(i,{headers:s,signal:n.signal});if(!o.ok)return[];const d=await o.json();return Tt(d)}finally{clearTimeout(r)}}function Tt(a){if(!a||typeof a!="object")return[];const e=a,t=Array.isArray(e.data)?e.data:[],i=Array.isArray(e.models)?e.models:[],s=t.length>0?t:i,n=[];for(const r of s){if(typeof r=="string"){const f=r.trim();if(!f)continue;n.push({id:f,displayName:R(f),defaultReasoningEffort:null,supportedReasoningEfforts:[],defaultServiceTier:null,serviceTiers:[],isDefault:!1});continue}if(!r||typeof r!="object")continue;const o=r,d=w(u(o.id),u(o.model));if(!d)continue;const h=w(u(o.displayName),u(o.display_name),u(o.name))??R(d);n.push({id:d,displayName:h,defaultReasoningEffort:u(o.defaultReasoningEffort)??null,supportedReasoningEfforts:z(o.supportedReasoningEfforts),defaultServiceTier:u(o.defaultServiceTier)??null,serviceTiers:G(o.serviceTiers),isDefault:o.isDefault===!0})}return n}function xt(a){if(!a||typeof a!="object")return{models:[],nextCursor:null};const e=a,t=Array.isArray(e.data)?e.data:[],i=[];for(const s of t){if(!s||typeof s!="object")continue;const n=s;if(n.hidden===!0)continue;const r=w(u(n.id),u(n.model));if(!r)continue;const o=w(u(n.displayName),u(n.display_name),u(n.name))??R(r);i.push({id:r,displayName:o,defaultReasoningEffort:u(n.defaultReasoningEffort)??null,supportedReasoningEfforts:z(n.supportedReasoningEfforts),defaultServiceTier:u(n.defaultServiceTier)??null,serviceTiers:G(n.serviceTiers),isDefault:n.isDefault===!0})}return{models:i,nextCursor:u(e.nextCursor)??null}}function ve(a){const e=[],t=new Set;for(const i of a){const s=i.id.trim(),n=s.toLowerCase();!s||t.has(n)||(t.add(n),e.push({id:s,displayName:i.displayName.trim()||s,defaultReasoningEffort:i.defaultReasoningEffort,supportedReasoningEfforts:[...i.supportedReasoningEfforts],defaultServiceTier:i.defaultServiceTier,serviceTiers:[...i.serviceTiers],isDefault:i.isDefault}))}return e}function yt(a,e){return{id:a,displayName:e,defaultReasoningEffort:null,supportedReasoningEfforts:[],defaultServiceTier:null,serviceTiers:[],isDefault:!1}}function z(a){if(!Array.isArray(a))return[];const e=[];for(const t of a){if(typeof t=="string"){const s=t.trim();s&&e.push(s);continue}if(!t||typeof t!="object")continue;const i=u(t.reasoningEffort);i&&e.push(i)}return e}function G(a){if(!Array.isArray(a))return[];const e=[];for(const t of a){if(typeof t=="string"){const n=t.trim();n&&e.push({id:n,displayName:n,description:null});continue}if(!t||typeof t!="object")continue;const i=t,s=u(i.id);s&&e.push({id:s,displayName:w(u(i.name),u(i.displayName),u(i.display_name))??s,description:u(i.description)??null})}return e}function R(a){return a.split(/[-_\s]+/).filter(Boolean).map(e=>/^(gpt|codex|o\d+)$/i.test(e)?e.toUpperCase():e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}function w(...a){for(const e of a)if(e!=null){if(typeof e=="string"&&!e.trim())continue;return e}}function Ie(a){return a.trim().replace(/[^a-zA-Z0-9._:-]+/g,"_")}function we(a,e){switch(a){case"turn/completed":return;case"item/agentMessage/delta":{const t=e?.params??{};if(typeof t.delta!="string"||t.delta.length===0)return;const i=typeof t.phase=="string"&&t.phase.trim()?t.phase.trim().toLowerCase():void 0;return{params:{delta:t.delta,...i?{phase:i}:{}}}}case"item/completed":{const i=(e?.params??{}).item;if(!i||typeof i!="object"||i.type!=="commandExecution")return;const s=Ct(i.command);return{params:{item:{type:"commandExecution",...s!==void 0?{command:s}:{},...i.exitCode!==void 0?{exitCode:i.exitCode}:{},...i.durationMs!==void 0?{durationMs:i.durationMs}:{}}}}}case"item/permissions/requestApproval":return V(e,"permission");case"item/commandExecution/requestApproval":return V(e,"exec");case"item/fileChange/requestApproval":return V(e,"file");default:return}}function V(a,e){if(a==null||typeof a!="object")return;const t=a.params??{};if(t==null||typeof t!="object"||Array.isArray(t))return;const i={},s=(...r)=>{for(const o of r)t[o]!==void 0&&(i[o]=t[o])};e==="permission"?s("threadId","turnId","itemId","reason","permissions"):e==="exec"?s("command","commandLine","command_line","argv","args","availableDecisions","cwd","workingDirectory","working_directory"):s("path","filePath","file_path","targetPath","target_path","paths","files","availableDecisions","cwd","workingDirectory","working_directory");const n={params:i};return a.id!==void 0&&(n.id=a.id),typeof a.method=="string"&&a.method&&(n.method=a.method),n}function Ct(a){if(typeof a!="string")return;const e=a.trim();if(e)return e.length<=de?e:e.slice(0,de-ce.length)+ce}class X extends ee{adapterSessionId;constructor(e){super(),this.adapterSessionId=e}emitDone(e){this.emit("done",e)}emitError(e){if(this.listenerCount("error")===0){c.warn("codex-adapter",`Prompt handle error (no listeners): ${e.message}`);return}this.emit("error",e)}async cancel(){}}function _t(a){return["cannot steer a compact turn","turn not found","turn already completed","no active turn"].some(t=>a.includes(t))}export{O as CodexAdapter,pe as resolveCodexCommandPath,we as trimCodexPayloadForWire};
@@ -0,0 +1 @@
1
+ import{open as g,stat as y}from"node:fs/promises";import{findRolloutFile as m}from"./rollout-locator.js";const p=512*1024;class b{identity="";preparedThread=null;offset=0;partial=Buffer.alloc(0);checkpoint=Buffer.alloc(0);scopeAnchor=null;droppingRecord=!1;complete=!1;scoped=!1;pendingTools=new Set;waitCalls=new Set;waitSince=null;reset(){this.identity="",this.preparedThread=null,this.offset=0,this.partial=Buffer.alloc(0),this.checkpoint=Buffer.alloc(0),this.scopeAnchor=null,this.droppingRecord=!1,this.complete=!1,this.scoped=!1,this.pendingTools.clear(),this.noteProgress()}noteProgress(){this.waitCalls.clear(),this.waitSince=null}get pureWait(){return this.complete&&this.scoped&&this.pendingTools.size===0&&this.waitCalls.size>=3}async prepare(o,n){this.reset();const a=m(o,n);if(!a)return;const r=await g(a,"r");try{const e=await r.stat(),t=Buffer.alloc(Math.min(64,e.size)),{bytesRead:s}=await r.read(t,0,t.length,e.size-t.length),i=await y(a);if(s!==t.length||i.size!==e.size||i.ino!==e.ino||i.dev!==e.dev||i.mtimeMs!==e.mtimeMs||i.ctimeMs!==e.ctimeMs)return;this.identity=`${a}\0${e.dev}:${e.ino}`,this.preparedThread=o,this.offset=e.size,this.checkpoint=t,this.droppingRecord=t.length>0&&t.at(-1)!==10}finally{await r.close()}}async inspect(o,n,a,r){if(!o||!n)return null;const e=m(o,a);if(!e)return this.reset(),null;const t=await g(e,"r");try{this.complete=!1;const s=await t.stat(),i=`${e}\0${s.dev}:${s.ino}`,l=`${i}\0${n}`;this.preparedThread===o&&this.identity===i&&(this.identity=l,this.preparedThread=null);const h=Buffer.alloc(this.checkpoint.length);this.checkpoint.length&&s.size>=this.offset&&await t.read(h,0,h.length,this.offset-h.length),(this.identity!==l||s.size<this.offset||!h.equals(this.checkpoint)||!await this.anchorMatches(t))&&(this.reset(),this.identity=l);const f=Buffer.alloc(Math.min(p,s.size-this.offset)),{bytesRead:d}=await t.read(f,0,f.length,this.offset);this.offset+=d;const u=f.subarray(0,d);this.checkpoint=Buffer.from(Buffer.concat([this.checkpoint,u]).subarray(-64)),this.consumePage(u,n,r);const c=await y(e);return c.ino!==s.ino||c.dev!==s.dev||c.size<this.offset||c.size===s.size&&(c.mtimeMs!==s.mtimeMs||c.ctimeMs!==s.ctimeMs)||!await this.anchorMatches(t)?(this.reset(),null):this.partial.length||this.droppingRecord||c.size!==this.offset?null:(this.complete=!0,this.pureWait?this.waitSince:null)}catch{return this.reset(),null}finally{await t.close()}}unknown(){this.scoped=!1,this.scopeAnchor=null,this.pendingTools.clear(),this.noteProgress()}async anchorMatches(o){if(!this.scopeAnchor)return!0;const n=Buffer.alloc(this.scopeAnchor.bytes.length);return(await o.read(n,0,n.length,this.scopeAnchor.offset)).bytesRead===n.length&&n.equals(this.scopeAnchor.bytes)}consumePage(o,n,a){const r=this.offset-o.length-this.partial.length,e=Buffer.concat([this.partial,o]);this.partial=Buffer.alloc(0);let t=0;for(let s=e.indexOf(10);s!==-1;s=e.indexOf(10,t)){if(!this.droppingRecord)if(s-t>p)this.unknown();else try{const i=e.subarray(t,s),l=JSON.parse(i.toString("utf8"));this.consume(l,n,a),l.type==="event_msg"&&l.payload?.type==="task_started"&&(this.scoped&&i.length<=4096?this.scopeAnchor={offset:r+t,bytes:Buffer.from(i)}:this.unknown())}catch{this.unknown()}this.droppingRecord=!1,t=s+1}e.length-t>p?(this.unknown(),this.droppingRecord=!0):this.droppingRecord||(this.partial=Buffer.from(e.subarray(t)))}consume(o,n,a){if(!o||typeof o!="object"||Array.isArray(o))throw new Error("Invalid rollout record");const r=o,e=r.payload;if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Invalid rollout payload");const t=e;if(r.type==="event_msg"&&t.type==="task_started"){this.scoped=t.turn_id===n,this.pendingTools.clear(),this.noteProgress();return}if(this.scoped){if(r.type==="compacted"){this.noteProgress();return}if(r.type==="event_msg"&&(t.type==="task_complete"||t.type==="task_completed")||r.type==="turn_context"&&t.turn_id!==n){this.scoped=!1,this.scopeAnchor=null,this.pendingTools.clear(),this.noteProgress();return}if(r.type==="response_item")if(t.type==="function_call"||t.type==="custom_tool_call"){if(typeof t.call_id!="string")throw new Error("Missing tool ownership");let s={};if(t.type==="function_call"){if(typeof t.arguments!="string")throw new Error("Invalid tool arguments");const i=JSON.parse(t.arguments);if(!i||typeof i!="object"||Array.isArray(i))throw new Error("Invalid tool arguments");s=i}t.type==="function_call"&&t.namespace==="clock"&&t.name==="sleep"&&typeof s.duration_ms=="number"&&s.duration_ms>0?(this.waitSince===null&&(this.waitSince=a),this.waitCalls.add(t.call_id),this.waitCalls.size>128&&this.waitCalls.delete(this.waitCalls.values().next().value)):(this.pendingTools.add(t.call_id),this.pendingTools.size>256&&this.unknown(),this.noteProgress())}else if(t.type==="function_call_output"||t.type==="custom_tool_call_output"){if(typeof t.call_id!="string")throw new Error("Missing tool ownership");this.pendingTools.delete(t.call_id)?this.noteProgress():this.waitCalls.has(t.call_id)||this.noteProgress()}else t.type!=="reasoning"&&this.noteProgress();else r.type==="event_msg"&&(t.type==="agent_message"||t.type==="user_message")&&this.noteProgress()}}}export{b as CodexWaitLoopTracker};