openclaw-code-agent 4.7.8 → 4.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,36 +1,36 @@
1
- import{$ as Yo,A as de,Aa as Ft,B as Pr,C as wr,D as br,E as Pt,F as wt,G as bt,H as Rt,I as Uo,J as Go,K as C,L as D,M as z,N as jo,O as At,P as zo,Pa as Bt,Q as Rr,R as F,S as It,T as Je,U as Tt,V as Ho,W as Qo,X as Ee,Y as oe,Z as Xe,_ as xt,a as Te,aa as H,b as xe,ba as Ar,c as vr,ca as Ir,d as Fo,da as Ze,e as Ce,ea as et,f as ue,fa as B,g as Z,ga as Ct,h as le,ha as Jo,i as Ye,ia as tt,j as Bo,ja as ie,k as _,ka as Ne,l as Ko,la as Xo,m as Y,ma as Mt,n as Me,na as nt,o as St,oa as _t,p as pe,pa as Dt,q as _e,qa as Oe,r as kt,ra as $t,s as vt,sa as Zo,t as qo,ta as Et,u as De,ua as Nt,v as $e,va as ei,w as Vo,wa as Ot,x as c,xa as Wt,y as S,ya as Lt,z as $,za as Se}from"./chunks/chunk.js";import{readdirSync as ff,statSync as gf,rmSync as hf}from"fs";import{execFileSync as yf}from"child_process";import{join as Wo}from"path";var ti={name:"openclaw-code-agent",version:"4.7.8",type:"module",packageManager:"pnpm@11.15.1",main:"dist/index.js",scripts:{"audit:prod":"pnpm audit --prod",build:"esbuild index.ts --bundle --splitting --platform=node --target=node22 --format=esm --outdir=dist --entry-names=index --chunk-names=chunks/[name] --minify --charset=utf8 --pure:console.log --pure:console.warn --pure:console.info --pure:console.debug --external:@anthropic-ai/claude-agent-sdk --external:openclaw/plugin-sdk/plugin-entry","generate:npm-shrinkwrap":"node scripts/generate-npm-shrinkwrap.mjs","check-static-guardrails":"node scripts/check-static-guardrails.mjs && node scripts/check-release-age-exceptions.mjs && node scripts/check-npm-shrinkwrap.mjs","check-plugin-security":"node scripts/check-plugin-security.mjs",test:"node scripts/run-tests.mjs","test:integ:crabbox":"node scripts/run-tests.mjs tests/oca-codex-crabbox-integ.test.ts tests/oca-plugin-workflows-integ.test.ts tests/oca-codex-telegram-proof.test.ts tests/oca-codex-proof-app-server.test.ts tests/oca-codex-proof-workflow.test.ts","test:serial":"node scripts/run-tests.mjs","test:file":"node scripts/run-tests.mjs","smoke:backend":"node scripts/run-tests.mjs tests/codex-harness.test.ts tests/plan-mode-e2e.test.ts tests/session-restore-service.test.ts","smoke:backend-parity":"node scripts/run-tests.mjs tests/backend-contract-smoke.test.ts tests/codex-harness.test.ts tests/harness-registry.test.ts","smoke:codex-worktrees":"node scripts/run-tests.mjs tests/codex-harness.test.ts tests/session-bootstrap.test.ts tests/session-restore-service.test.ts","smoke:codex-live":"OPENCLAW_RUN_LIVE_CODEX_SMOKE=1 node scripts/run-tests.mjs tests/live-codex-app-server-smoke.test.ts","proof:codex-doctor":"node --import tsx scripts/e2e/oca-codex-telegram-proof.ts doctor","proof:codex-local":"node --import tsx scripts/e2e/oca-codex-telegram-proof.ts local-smoke","proof:codex-telegram":"node scripts/e2e/run-oca-codex-telegram-proof.mjs","smoke:codex-release":"OPENCLAW_RUN_LIVE_CODEX_RELEASE_SMOKE=1 node scripts/run-tests.mjs tests/live-codex-app-server-smoke.test.ts","smoke:opencode-live":"OPENCLAW_RUN_LIVE_OPENCODE_SMOKE=1 node scripts/run-tests.mjs tests/live-opencode-server-smoke.test.ts",typecheck:"tsc -p tsconfig.typecheck.json --noEmit","validate:release-metadata":"node scripts/validate-release-metadata.mjs","verify:npm-consumer":"node scripts/check-npm-shrinkwrap-release-age.mjs && node scripts/verify-npm-consumer-install.mjs",verify:"pnpm check-static-guardrails && pnpm typecheck && pnpm build && pnpm test"},openclaw:{extensions:["./dist/index.js"],install:{npmSpec:"openclaw-code-agent",defaultChoice:"npm",minHostVersion:">=2026.7.1-2"},compat:{pluginApi:">=2026.7.1-2",minGatewayVersion:"2026.7.1-2"},build:{openclawVersion:"2026.7.1-2",pluginSdkVersion:"2026.7.1-2"}},files:["dist/","skills/","openclaw.plugin.json","npm-shrinkwrap.json","README.md","LICENSE"],dependencies:{"@anthropic-ai/claude-agent-sdk":"0.3.220","@anthropic-ai/sdk":"0.109.1","@hono/node-server":"2.0.10","@modelcontextprotocol/sdk":"1.30.0","express-rate-limit":"8.6.1","fast-uri":"3.1.5",hono:"4.12.34","ip-address":"10.3.1",zod:"4.4.3"},devDependencies:{"@types/node":"^26.0.1",esbuild:"^0.28.1",nanoid:"^6.0.0",openclaw:"2026.7.1-2",tsx:"^4.21.0",typescript:"^7.0.2"},keywords:["openclaw","plugin","claude","claude-code","opencode","coding-agent","codex","ai","anthropic","agent","code-generation","automation","cli","background-process","developer-tools"],repository:{type:"git",url:"git+https://github.com/goldmar/openclaw-code-agent.git"},homepage:"https://github.com/goldmar/openclaw-code-agent#readme",bugs:{url:"https://github.com/goldmar/openclaw-code-agent/issues"},license:"MIT",author:"Mark Goldenstein",publishConfig:{access:"public",provenance:!0},description:"An OpenClaw plugin that orchestrates coding agent sessions as managed background processes. Launch, monitor, and control coding agents (Claude Code, Codex, experimental OpenCode, and more) directly from your AI gateway.",peerDependencies:{openclaw:">=2026.7.1-2"}};import{execFile as wl}from"node:child_process";import{mkdirSync as bl,readFileSync as Rl,renameSync as Al,writeFileSync as Il}from"node:fs";import{dirname as Tl,join as xl}from"node:path";import{promisify as Cl}from"node:util";import*as di from"child_process";import{createHash as ll}from"crypto";var W="code-agent";var dl=new Set(["1","true","yes","on"]);function xr(){let n=process.env.OPENCLAW_CODE_AGENT_BUTTON_DIAGNOSTICS?.trim().toLowerCase();return!!(n&&dl.has(n))}function K(n){if(!(typeof n!="string"||n.length===0))return ll("sha256").update(n).digest("hex").slice(0,12)}function ni(n){return typeof n.callbackData=="string"?n.callbackData:typeof n.value=="string"?n.value:void 0}function E(n){let e=(n??[]).filter(r=>Array.isArray(r)&&r.length>0),t=e.flat();return{buttonRows:e.length||void 0,buttonCount:t.length||void 0,buttonLabels:t.length>0?t.map(r=>typeof r.label=="string"?r.label:void 0):void 0,callbackByteLengths:t.length>0?t.map(r=>{let o=ni(r);return o?Buffer.byteLength(o,"utf8"):void 0}):void 0,callbackHashes:t.length>0?t.map(r=>K(ni(r))):void 0,buttonStyles:t.length>0?t.map(r=>typeof r.style=="string"?r.style:void 0):void 0}}function ce(n){return n&&typeof n=="object"&&!Array.isArray(n)?n:void 0}function oi(n){let e=ce(n),t=Array.isArray(e?.blocks)?e.blocks:void 0;if(t)return t.map(r=>ce(r)?.type).filter(r=>typeof r=="string"&&r.length>0)}function ii(n){let e=ce(n),t=Array.isArray(e?.blocks)?e.blocks:void 0;if(!t)return;let r=t.map(o=>{let i=ce(o);return i?.type!=="buttons"||!Array.isArray(i.buttons)?[]:i.buttons}).filter(o=>o.length>0);return r.length>0?r:void 0}function Cr(n){let e=ii(n);return{presentationBlockTypes:oi(n),...E(e)}}function Mr(n){let e=ce(n),t=e?.interactive,r=ce(e?.channelData),o=ce(r?.telegram),i=Array.isArray(o?.buttons)?o.buttons:void 0;return{renderedPayloadKeys:e?Object.keys(e).sort():void 0,interactiveBlockTypes:oi(t),...ri("interactive",E(ii(t))),...ri("telegramChannelData",E(i)),hasPresentation:!!e?.presentation,hasInteractive:!!t,hasTelegramChannelDataButtons:!!i?.some(s=>s.length>0)}}function si(n){let e=ce(n);return e?{sendResultKeys:Object.keys(e).sort(),messageId:Tr(e.messageId),chatId:Tr(e.chatId),telegramThreadId:Tr(e.messageThreadId??e.threadId),channel:typeof e.channel=="string"?e.channel:void 0}:{sendResultType:typeof n}}function Tr(n){return typeof n=="string"||typeof n=="number"?n:void 0}function ri(n,e){let t={};for(let[r,o]of Object.entries(e))o!==void 0&&(t[`${n}${r.charAt(0).toUpperCase()}${r.slice(1)}`]=o);return t}function M(n,e){if(!xr())return;let t=Object.fromEntries(Object.entries(e).filter(([,r])=>r!==void 0));`${JSON.stringify({event:n,callbackNamespace:W,...t})}`}var ai=5e3,ui=64,ul={primary:"primary",success:"success",positive:"success",danger:"danger",destructive:"danger",negative:"danger"},pl={execFile:di.execFile},me=class extends Error{constructor(e){super(e),this.name="MissingRuntimeDirectNotificationCapabilityError"}},We=class{constructor(e=pl.execFile){this.execFile=e}execFile;async send(e,t,r){M("direct_send_started",{...J(e),messageTextLength:t.length,...E(r)});try{await this.sendViaRuntime(e,t,r),M("direct_send_succeeded",{...J(e),deliveryPath:"runtime",...E(r)});return}catch(o){if(!(o instanceof me))throw M("direct_send_failed",{...J(e),deliveryPath:"runtime",...E(r),error:_r(o)}),o;M("direct_send_runtime_capability_missing",{...J(e),deliveryPath:"runtime",...E(r),reason:o.message}),await this.sendViaBoundedCliFallback(e,t,r,o.message),M("direct_send_succeeded",{...J(e),deliveryPath:"cli-fallback",...E(r)})}}async sendViaRuntime(e,t,r){let o=xe(),i=Fo(),s=o?.channel?.outbound?.loadAdapter;if(!o)throw new me("OpenClaw plugin runtime is unavailable for direct notification delivery");if(i==null)throw new me("OpenClaw runtime config snapshot is unavailable for direct notification delivery");if(!o.channel)throw new me(`OpenClaw plugin runtime channel surface is unavailable for direct notification delivery (runtimeVersion=${Dr(o)})`);if(!o.channel.outbound)throw new me(`OpenClaw plugin runtime channel outbound surface is unavailable for direct notification delivery (runtimeVersion=${Dr(o)})`);if(!s)throw new me(`OpenClaw plugin runtime channel outbound loadAdapter is unavailable for direct notification delivery (runtimeVersion=${Dr(o)})`);let a=await s(e.channel);if(!a)throw new Error(`OpenClaw outbound adapter for channel "${e.channel}" is unavailable`);let l=Vt(r);if(M("runtime_adapter_loaded",{...J(e),adapterHasRenderPresentation:typeof a.renderPresentation=="function",adapterHasSendPayload:typeof a.sendPayload=="function",adapterHasSendText:typeof a.sendText=="function",...E(r),...l?Cr(l):{}}),l){await this.sendPresentation(a,i,e,t,l);return}if(!a.sendText)throw new Error(`OpenClaw outbound adapter for channel "${e.channel}" cannot send text`);await a.sendText({cfg:i,to:e.target,text:t,accountId:e.accountId,threadId:e.threadId})}async sendPresentation(e,t,r,o,i){let s=ml(i),a={text:o,presentation:i,interactive:s};M("presentation_render_started",{...J(r),messageTextLength:o.length,adapterHasRenderPresentation:typeof e.renderPresentation=="function",adapterHasSendPayload:typeof e.sendPayload=="function",...Cr(i)});let l={cfg:t,to:r.target,text:o,payload:a,accountId:r.accountId,threadId:r.threadId},d=e.renderPresentation?await e.renderPresentation({payload:a,presentation:i,ctx:l}):a,u=gl(d,s,r.channel);if(M("presentation_render_completed",{...J(r),adapterHasRenderPresentation:typeof e.renderPresentation=="function",adapterHasSendPayload:typeof e.sendPayload=="function",...Mr(u)}),!u||typeof u!="object"||!e.sendPayload)throw new Error(`OpenClaw outbound adapter for channel "${r.channel}" cannot preserve interactive presentation`);let f=await e.sendPayload({...l,payload:u});M("presentation_send_payload_completed",{...J(r),...Mr(u),...si(f)})}sendViaBoundedCliFallback(e,t,r,o){return new Promise((i,s)=>{let a=cl(e,t,r);M("direct_send_cli_fallback_started",{...J(e),deliveryPath:"cli-fallback",reason:o,messageTextLength:t.length,...E(r)}),this.execFile("openclaw",a,{timeout:ai,killSignal:"SIGKILL"},(l,d,u)=>{if(!l){M("direct_send_cli_fallback_completed",{...J(e),deliveryPath:"cli-fallback",...E(r)}),i();return}let f=u?.trim()?` | stderr: ${u.trim()}`:"";M("direct_send_cli_fallback_failed",{...J(e),deliveryPath:"cli-fallback",...E(r),error:_r(l),stderrLength:u?.length}),s(new Error(`${o}; bounded openclaw message send fallback failed within ${ai}ms timeout: ${_r(l)}${f}`))})})}};function J(n){return{channel:n.channel,target:n.target,accountId:n.accountId,threadId:n.threadId,sessionKey:n.sessionKey}}function cl(n,e,t){let r=Vt(t),o=["message","send","--channel",n.channel,"--target",n.target,"--message",e];return n.accountId&&o.push("--account",n.accountId),n.threadId&&o.push("--thread-id",n.threadId),r&&o.push("--presentation",JSON.stringify(r)),o}function _r(n){return n instanceof Error?n.message:String(n)}function Dr(n){if(!n||typeof n!="object")return"unknown";let e=n.version;return typeof e=="string"&&e.trim()?e:"unknown"}function Vt(n){let e=(n??[]).filter(t=>Array.isArray(t)&&t.length>0).map(t=>({type:"buttons",buttons:t.map(r=>({label:r.label,value:Pl(r.callbackData),...r.style?{style:r.style}:{}}))}));return e.length>0?{blocks:e}:void 0}function ml(n){let e=n.blocks.filter(t=>t.type==="buttons"&&t.buttons.length>0).map(t=>({type:"buttons",buttons:t.buttons.map(r=>({label:r.label,value:r.value,...r.style?{style:r.style}:{}}))}));return e.length>0?{blocks:e}:void 0}function fl(n){if(!n||typeof n!="object"||Array.isArray(n))return!1;let e=n.interactive;if(!e||typeof e!="object"||Array.isArray(e))return!1;let t=e.blocks;return Array.isArray(t)&&t.some(r=>{if(!r||typeof r!="object"||Array.isArray(r))return!1;let o=r;return o.type==="buttons"&&Array.isArray(o.buttons)&&o.buttons.length>0})}function gl(n,e,t){if(!e)return n;let r=fl(n)?n:hl(n,e);return t!=="telegram"?r:yl(r,e)}function hl(n,e){return!n||typeof n!="object"||Array.isArray(n)?n:{...n,interactive:e}}function yl(n,e){if(!n||typeof n!="object"||Array.isArray(n))return n;let t=n,r=Le(t.channelData),o=Le(r?.telegram),i=kl(o?.buttons);if(i)return{...t,channelData:{...r??{},telegram:{...o??{},buttons:i}}};let s=Sl(e);return s?{...t,channelData:{...r??{},telegram:{...o??{},buttons:s}}}:n}function Sl(n){let e=n.blocks.filter(t=>t.type==="buttons"&&t.buttons.length>0).map(t=>t.buttons.filter(r=>typeof r.value=="string"&&r.value.trim().length>0&&Buffer.byteLength(r.value,"utf8")<=ui).map(r=>({text:r.label,callback_data:r.value,...pi(r.style)}))).filter(t=>t.length>0);return e.length>0?e:void 0}function kl(n){if(!Array.isArray(n))return;let e=n.map(t=>Array.isArray(t)?t.map(r=>{if(!r||typeof r!="object"||Array.isArray(r))return;let{style:o,...i}=r;if(!(typeof i.text!="string"||i.text.trim().length===0)&&!(i.callback_data!==void 0&&(typeof i.callback_data!="string"||i.callback_data.trim().length===0||Buffer.byteLength(i.callback_data,"utf8")>ui))&&vl(i))return{...i,...pi(o)}}).filter(r=>!!r):[]).filter(t=>t.length>0);return e.length>0?e:void 0}function vl(n){return qt(n.callback_data)||qt(n.url)||Kt(n.web_app)||Kt(n.webApp)||Kt(n.login_url)||Kt(n.loginUrl)||typeof n.switch_inline_query=="string"||typeof n.switch_inline_query_current_chat=="string"||Le(n.switch_inline_query_chosen_chat)!==void 0||Le(n.callback_game)!==void 0||n.pay===!0||li(n.copy_text)||li(n.copyText)}function qt(n){return typeof n=="string"&&n.trim().length>0}function Kt(n){let e=Le(n);return qt(e?.url)}function li(n){let e=Le(n);return qt(e?.text)}function pi(n){if(typeof n!="string")return{};let e=n.trim().toLowerCase(),t=ul[e];return t?{style:t}:{}}function Le(n){return n&&typeof n=="object"&&!Array.isArray(n)?n:void 0}function Pl(n){return n.startsWith(`${W}:`)?n:`${W}:${n}`}var Ml=Cl(wl),rt="openclaw-code-agent",_l=`https://registry.npmjs.org/${encodeURIComponent(rt)}/latest`,Dl="openclaw-code-agent-auto-update.json",gi=1440*60*1e3,$l=7*gi,El=1e4,Fe="plugin:auto-update";function fe(n){return!!n&&typeof n=="object"&&!Array.isArray(n)}function $r(n){return n instanceof Error?n.message:String(n)}function te(n){return n?.trim().replace(/^v/i,"")||void 0}function ee(n,e){let t=n[e];return typeof t=="string"&&t.trim()?t.trim():void 0}function ci(n){let e=n?.trim().replace(/^npm:/,"");if(!e)return;if(e.startsWith("@")){let r=e.indexOf("@",1);return r===-1?e:e.slice(0,r)}let t=e.indexOf("@");return t===-1?e:e.slice(0,t)}function Er(n){let e=`${n.stdout}
2
- ${n.stderr}`;if(/No install record/i.test(e))throw new Error("OpenClaw reported no managed install record for OpenClaw Code Agent.");let t;try{t=JSON.parse(n.stdout)}catch{throw new Error("OpenClaw returned invalid JSON while inspecting the OpenClaw Code Agent install.")}if(!fe(t)||!fe(t.plugin)||!fe(t.install))throw new Error("OpenClaw inspection did not include the OpenClaw Code Agent plugin and managed install record.");let r=ee(t.plugin,"id"),o=te(ee(t.plugin,"version"));if(r!==rt||!o)throw new Error("OpenClaw inspection returned an unexpected OpenClaw Code Agent plugin identity or version.");let i=ee(t.install,"source"),s=te(ee(t.install,"version")),a=te(ee(t.install,"resolvedVersion"));if(i==="npm"){let l=ee(t.install,"resolvedName")??ci(ee(t.install,"spec"))??ci(ee(t.install,"resolvedSpec"));if(!l)throw new Error("The OpenClaw Code Agent npm install record does not identify its package.");return{pluginVersion:o,install:{source:i,packageName:l,recordedVersion:s,resolvedVersion:a}}}if(i==="clawhub"){let l=ee(t.install,"clawhubPackage");if(!l)throw new Error("The OpenClaw Code Agent ClawHub install record does not identify its package.");return{pluginVersion:o,install:{source:i,packageName:l,recordedVersion:s,resolvedVersion:a}}}throw new Error(`OpenClaw Code Agent self-update does not support managed install source ${i??"unknown"}.`)}function Nl(n,e){return["plugins","install",n.source==="npm"?`${n.packageName}@${e}`:`clawhub:${n.packageName}@${e}`,"--force"]}function Ol(n,e,t){if(e.install.source!==n.install.source||e.install.packageName!==n.install.packageName)throw new Error("OpenClaw Code Agent update verification found that the managed install source or package changed.");if(e.pluginVersion!==t)throw new Error(`OpenClaw Code Agent update verification found installed plugin version ${e.pluginVersion}, expected ${t}.`);let r=[e.install.recordedVersion,e.install.resolvedVersion].filter(o=>!!o);if(r.length===0||r.some(o=>o!==t))throw new Error(`OpenClaw Code Agent update verification found managed install version ${r.join("/")||"unknown"}, expected ${t}.`)}function Nr(n){let t=te(n)?.match(/^((?:0|[1-9]\d*))\.((?:0|[1-9]\d*))\.((?:0|[1-9]\d*))$/);if(!t?.[1]||!t[2]||!t[3])return;let r=[Number(t[1]),Number(t[2]),Number(t[3])];return r.every(Number.isSafeInteger)?r:void 0}function Wl(n,e){let t=Nr(n),r=Nr(e);if(!t||!r)return!1;for(let o=0;o<3;o+=1){if(t[o]>r[o])return!0;if(t[o]<r[o])return!1}return!1}function Ll(n){if(!fe(n))return{};let e={};for(let t of["lastCheckedAt","latestVersion","promptedVersion","lastPromptedAt","dismissedVersion","lastDismissedAt","updateInstalledVersion","restartPromptedVersion","lastError"]){let r=n[t];typeof r=="string"&&r.trim()&&(e[t]=r)}return e}function mi(n){if(!(!n?.provider||!n.target||n.provider==="system"||n.target==="system"))return{channel:n.provider,target:n.target,accountId:n.accountId,threadId:n.threadId,sessionKey:n.sessionKey}}function fi(){if(_.fallbackChannel)return ue(_.fallbackChannel)}async function Fl(){let{fetchNpmReleaseMetadata:n}=await import("./chunks/npm-release-client.js"),e=await n(_l,El),t=fe(e)&&typeof e.version=="string"?te(e.version):void 0;return t?{version:t}:void 0}async function Bl(n,e){let t=await n("openclaw",["plugins","search",e,"--limit","100","--json"]),r;try{r=JSON.parse(t.stdout)}catch{throw new Error("OpenClaw returned invalid JSON while checking ClawHub for OpenClaw Code Agent updates.")}let o=fe(r)&&Array.isArray(r.results)?r.results:[];for(let i of o){if(!fe(i)||!fe(i.package)||ee(i.package,"name")!==e)continue;let s=te(ee(i.package,"latestVersion"));return s?{version:s}:void 0}}async function Kl(n){let e=Er(await n("openclaw",["plugins","inspect",rt,"--json"]));return e.install.source==="npm"?Fl():Bl(n,e.install.packageName)}async function ql(n,e){let t=await Ml(n,e,{timeout:12e4,maxBuffer:1048576});return{stdout:t.stdout?.toString()??"",stderr:t.stderr?.toString()??""}}var Ut=class{constructor(e){this.options=e;this.statePath=xl(e.stateDir,Dl),this.notifier=e.notifier??new We,this.runCommand=e.runCommand??ql,this.fetchLatestRelease=e.fetchLatestRelease??(()=>Kl(this.runCommand)),this.now=e.now??Date.now}options;statePath;notifier;fetchLatestRelease;runCommand;now;checkInFlight;maybeCheckForUpdate(e={}){this.checkInFlight||(this.checkInFlight=this.checkForUpdate(e).catch(t=>{`${$r(t)}`}).finally(()=>{this.checkInFlight=void 0}))}async waitForIdle(){await this.checkInFlight}async installConfirmed(e,t){let r=te(e);if(!r||!Nr(r))return"Could not determine which stable OpenClaw Code Agent version to update to.";let o=Er(await this.runCommand("openclaw",["plugins","inspect",rt,"--json"])),i=await this.runCommand("openclaw",Nl(o.install,r));if(/No install record/i.test(`${i.stdout}
1
+ import{$ as Yo,A as de,Aa as Bt,B as Pr,C as wr,D as br,E as wt,F as bt,G as Rt,H as At,I as Uo,J as Go,K as C,L as D,M as z,N as jo,O as It,P as zo,Pa as Kt,Q as Rr,R as L,S as Tt,T as Je,U as xt,V as Ho,W as Qo,X as Ee,Y as oe,Z as Xe,_ as Ct,a as Te,aa as H,b as xe,ba as Ar,c as vr,ca as Ir,d as Lo,da as Ze,e as Ce,ea as et,f as ue,fa as B,g as Z,ga as Mt,h as le,ha as Jo,i as Ye,ia as tt,j as Bo,ja as ie,k as _,ka as Ne,l as Ko,la as Xo,m as Y,ma as _t,n as Me,na as nt,o as kt,oa as Dt,p as pe,pa as $t,q as _e,qa as Oe,r as vt,ra as Et,s as Pt,sa as Zo,t as qo,ta as Nt,u as De,ua as Ot,v as $e,va as ei,w as Vo,wa as Wt,x as c,xa as Ft,y as S,ya as Lt,z as $,za as Se}from"./chunks/chunk.js";import{readdirSync as ff,statSync as gf,rmSync as hf}from"fs";import{execFileSync as yf}from"child_process";import{join as Wo}from"path";var ti={name:"openclaw-code-agent",version:"4.7.9",type:"module",packageManager:"pnpm@11.15.1",main:"dist/index.js",scripts:{"audit:prod":"pnpm audit --prod",build:"esbuild index.ts --bundle --splitting --platform=node --target=node22 --format=esm --outdir=dist --entry-names=index --chunk-names=chunks/[name] --minify --charset=utf8 --pure:console.log --pure:console.warn --pure:console.info --pure:console.debug --external:@anthropic-ai/claude-agent-sdk --external:openclaw/plugin-sdk/plugin-entry","generate:npm-shrinkwrap":"node scripts/generate-npm-shrinkwrap.mjs","check-static-guardrails":"node scripts/check-static-guardrails.mjs && node scripts/check-release-age-exceptions.mjs && node scripts/check-npm-shrinkwrap.mjs","check-plugin-security":"node scripts/check-plugin-security.mjs",test:"node scripts/run-tests.mjs","test:integ:crabbox":"node scripts/run-tests.mjs tests/oca-codex-crabbox-integ.test.ts tests/oca-plugin-workflows-integ.test.ts tests/oca-codex-telegram-proof.test.ts tests/oca-codex-proof-app-server.test.ts tests/oca-codex-proof-workflow.test.ts","test:serial":"node scripts/run-tests.mjs","test:file":"node scripts/run-tests.mjs","smoke:backend":"node scripts/run-tests.mjs tests/codex-harness.test.ts tests/plan-mode-e2e.test.ts tests/session-restore-service.test.ts","smoke:backend-parity":"node scripts/run-tests.mjs tests/backend-contract-smoke.test.ts tests/codex-harness.test.ts tests/harness-registry.test.ts","smoke:codex-worktrees":"node scripts/run-tests.mjs tests/codex-harness.test.ts tests/session-bootstrap.test.ts tests/session-restore-service.test.ts","smoke:codex-live":"OPENCLAW_RUN_LIVE_CODEX_SMOKE=1 node scripts/run-tests.mjs tests/live-codex-app-server-smoke.test.ts","proof:codex-doctor":"node --import tsx scripts/e2e/oca-codex-telegram-proof.ts doctor","proof:codex-local":"node --import tsx scripts/e2e/oca-codex-telegram-proof.ts local-smoke","proof:codex-telegram":"node scripts/e2e/run-oca-codex-telegram-proof.mjs","smoke:codex-release":"OPENCLAW_RUN_LIVE_CODEX_RELEASE_SMOKE=1 node scripts/run-tests.mjs tests/live-codex-app-server-smoke.test.ts","smoke:opencode-live":"OPENCLAW_RUN_LIVE_OPENCODE_SMOKE=1 node scripts/run-tests.mjs tests/live-opencode-server-smoke.test.ts",typecheck:"tsc -p tsconfig.typecheck.json --noEmit","validate:release-metadata":"node scripts/validate-release-metadata.mjs","verify:npm-consumer":"node scripts/check-npm-shrinkwrap-release-age.mjs && node scripts/verify-npm-consumer-install.mjs",verify:"pnpm check-static-guardrails && pnpm typecheck && pnpm build && pnpm test"},openclaw:{extensions:["./dist/index.js"],install:{npmSpec:"openclaw-code-agent",defaultChoice:"npm",minHostVersion:">=2026.8.1"},compat:{pluginApi:">=2026.8.1",minGatewayVersion:"2026.8.1"},build:{openclawVersion:"2026.8.1",pluginSdkVersion:"2026.8.1"}},files:["dist/","skills/","openclaw.plugin.json","npm-shrinkwrap.json","README.md","LICENSE"],dependencies:{"@anthropic-ai/claude-agent-sdk":"0.3.251","@anthropic-ai/sdk":"0.122.0","@hono/node-server":"2.1.1","@modelcontextprotocol/sdk":"1.30.0","express-rate-limit":"8.7.0","fast-uri":"3.1.5",hono:"4.12.34","ip-address":"10.5.0",zod:"4.5.4"},devDependencies:{"@types/node":"^26.0.1",esbuild:"^0.28.1",nanoid:"^6.0.0",openclaw:"2026.8.1",tsx:"^4.21.0",typescript:"^7.0.2"},keywords:["openclaw","plugin","claude","claude-code","opencode","coding-agent","codex","ai","anthropic","agent","code-generation","automation","cli","background-process","developer-tools"],repository:{type:"git",url:"git+https://github.com/goldmar/openclaw-code-agent.git"},homepage:"https://github.com/goldmar/openclaw-code-agent#readme",bugs:{url:"https://github.com/goldmar/openclaw-code-agent/issues"},license:"MIT",author:"Mark Goldenstein",publishConfig:{access:"public",provenance:!0},description:"An OpenClaw plugin that orchestrates coding agent sessions as managed background processes. Launch, monitor, and control coding agents (Claude Code, Codex, experimental OpenCode, and more) directly from your AI gateway.",peerDependencies:{openclaw:">=2026.8.1"}};import{execFile as wl}from"node:child_process";import{mkdirSync as bl,readFileSync as Rl,renameSync as Al,writeFileSync as Il}from"node:fs";import{dirname as Tl,join as xl}from"node:path";import{promisify as Cl}from"node:util";import*as di from"child_process";import{createHash as ll}from"crypto";var W="code-agent";var dl=new Set(["1","true","yes","on"]);function xr(){let n=process.env.OPENCLAW_CODE_AGENT_BUTTON_DIAGNOSTICS?.trim().toLowerCase();return!!(n&&dl.has(n))}function K(n){if(!(typeof n!="string"||n.length===0))return ll("sha256").update(n).digest("hex").slice(0,12)}function ni(n){return typeof n.callbackData=="string"?n.callbackData:typeof n.value=="string"?n.value:void 0}function E(n){let e=(n??[]).filter(r=>Array.isArray(r)&&r.length>0),t=e.flat();return{buttonRows:e.length||void 0,buttonCount:t.length||void 0,buttonLabels:t.length>0?t.map(r=>typeof r.label=="string"?r.label:void 0):void 0,callbackByteLengths:t.length>0?t.map(r=>{let o=ni(r);return o?Buffer.byteLength(o,"utf8"):void 0}):void 0,callbackHashes:t.length>0?t.map(r=>K(ni(r))):void 0,buttonStyles:t.length>0?t.map(r=>typeof r.style=="string"?r.style:void 0):void 0}}function ce(n){return n&&typeof n=="object"&&!Array.isArray(n)?n:void 0}function oi(n){let e=ce(n),t=Array.isArray(e?.blocks)?e.blocks:void 0;if(t)return t.map(r=>ce(r)?.type).filter(r=>typeof r=="string"&&r.length>0)}function ii(n){let e=ce(n),t=Array.isArray(e?.blocks)?e.blocks:void 0;if(!t)return;let r=t.map(o=>{let i=ce(o);return i?.type!=="buttons"||!Array.isArray(i.buttons)?[]:i.buttons}).filter(o=>o.length>0);return r.length>0?r:void 0}function Cr(n){let e=ii(n);return{presentationBlockTypes:oi(n),...E(e)}}function Mr(n){let e=ce(n),t=e?.interactive,r=ce(e?.channelData),o=ce(r?.telegram),i=Array.isArray(o?.buttons)?o.buttons:void 0;return{renderedPayloadKeys:e?Object.keys(e).sort():void 0,interactiveBlockTypes:oi(t),...ri("interactive",E(ii(t))),...ri("telegramChannelData",E(i)),hasPresentation:!!e?.presentation,hasInteractive:!!t,hasTelegramChannelDataButtons:!!i?.some(s=>s.length>0)}}function si(n){let e=ce(n);return e?{sendResultKeys:Object.keys(e).sort(),messageId:Tr(e.messageId),chatId:Tr(e.chatId),telegramThreadId:Tr(e.messageThreadId??e.threadId),channel:typeof e.channel=="string"?e.channel:void 0}:{sendResultType:typeof n}}function Tr(n){return typeof n=="string"||typeof n=="number"?n:void 0}function ri(n,e){let t={};for(let[r,o]of Object.entries(e))o!==void 0&&(t[`${n}${r.charAt(0).toUpperCase()}${r.slice(1)}`]=o);return t}function M(n,e){if(!xr())return;let t=Object.fromEntries(Object.entries(e).filter(([,r])=>r!==void 0));`${JSON.stringify({event:n,callbackNamespace:W,...t})}`}var ai=5e3,ui=64,ul={primary:"primary",success:"success",positive:"success",danger:"danger",destructive:"danger",negative:"danger"},pl={execFile:di.execFile},me=class extends Error{constructor(e){super(e),this.name="MissingRuntimeDirectNotificationCapabilityError"}},We=class{constructor(e=pl.execFile){this.execFile=e}execFile;async send(e,t,r){M("direct_send_started",{...J(e),messageTextLength:t.length,...E(r)});try{await this.sendViaRuntime(e,t,r),M("direct_send_succeeded",{...J(e),deliveryPath:"runtime",...E(r)});return}catch(o){if(!(o instanceof me))throw M("direct_send_failed",{...J(e),deliveryPath:"runtime",...E(r),error:_r(o)}),o;M("direct_send_runtime_capability_missing",{...J(e),deliveryPath:"runtime",...E(r),reason:o.message}),await this.sendViaBoundedCliFallback(e,t,r,o.message),M("direct_send_succeeded",{...J(e),deliveryPath:"cli-fallback",...E(r)})}}async sendViaRuntime(e,t,r){let o=xe(),i=Lo(),s=o?.channel?.outbound?.loadAdapter;if(!o)throw new me("OpenClaw plugin runtime is unavailable for direct notification delivery");if(i==null)throw new me("OpenClaw runtime config snapshot is unavailable for direct notification delivery");if(!o.channel)throw new me(`OpenClaw plugin runtime channel surface is unavailable for direct notification delivery (runtimeVersion=${Dr(o)})`);if(!o.channel.outbound)throw new me(`OpenClaw plugin runtime channel outbound surface is unavailable for direct notification delivery (runtimeVersion=${Dr(o)})`);if(!s)throw new me(`OpenClaw plugin runtime channel outbound loadAdapter is unavailable for direct notification delivery (runtimeVersion=${Dr(o)})`);let a=await s(e.channel);if(!a)throw new Error(`OpenClaw outbound adapter for channel "${e.channel}" is unavailable`);let l=Ut(r);if(M("runtime_adapter_loaded",{...J(e),adapterHasRenderPresentation:typeof a.renderPresentation=="function",adapterHasSendPayload:typeof a.sendPayload=="function",adapterHasSendText:typeof a.sendText=="function",...E(r),...l?Cr(l):{}}),l){await this.sendPresentation(a,i,e,t,l);return}if(!a.sendText)throw new Error(`OpenClaw outbound adapter for channel "${e.channel}" cannot send text`);await a.sendText({cfg:i,to:e.target,text:t,accountId:e.accountId,threadId:e.threadId})}async sendPresentation(e,t,r,o,i){let s=ml(i),a={text:o,presentation:i,interactive:s};M("presentation_render_started",{...J(r),messageTextLength:o.length,adapterHasRenderPresentation:typeof e.renderPresentation=="function",adapterHasSendPayload:typeof e.sendPayload=="function",...Cr(i)});let l={cfg:t,to:r.target,text:o,payload:a,accountId:r.accountId,threadId:r.threadId},d=e.renderPresentation?await e.renderPresentation({payload:a,presentation:i,ctx:l}):a,u=gl(d,s,r.channel);if(M("presentation_render_completed",{...J(r),adapterHasRenderPresentation:typeof e.renderPresentation=="function",adapterHasSendPayload:typeof e.sendPayload=="function",...Mr(u)}),!u||typeof u!="object"||!e.sendPayload)throw new Error(`OpenClaw outbound adapter for channel "${r.channel}" cannot preserve interactive presentation`);let f=await e.sendPayload({...l,payload:u});M("presentation_send_payload_completed",{...J(r),...Mr(u),...si(f)})}sendViaBoundedCliFallback(e,t,r,o){return new Promise((i,s)=>{let a=cl(e,t,r);M("direct_send_cli_fallback_started",{...J(e),deliveryPath:"cli-fallback",reason:o,messageTextLength:t.length,...E(r)}),this.execFile("openclaw",a,{timeout:ai,killSignal:"SIGKILL"},(l,d,u)=>{if(!l){M("direct_send_cli_fallback_completed",{...J(e),deliveryPath:"cli-fallback",...E(r)}),i();return}let f=u?.trim()?` | stderr: ${u.trim()}`:"";M("direct_send_cli_fallback_failed",{...J(e),deliveryPath:"cli-fallback",...E(r),error:_r(l),stderrLength:u?.length}),s(new Error(`${o}; bounded openclaw message send fallback failed within ${ai}ms timeout: ${_r(l)}${f}`))})})}};function J(n){return{channel:n.channel,target:n.target,accountId:n.accountId,threadId:n.threadId,sessionKey:n.sessionKey}}function cl(n,e,t){let r=Ut(t),o=["message","send","--channel",n.channel,"--target",n.target,"--message",e];return n.accountId&&o.push("--account",n.accountId),n.threadId&&o.push("--thread-id",n.threadId),r&&o.push("--presentation",JSON.stringify(r)),o}function _r(n){return n instanceof Error?n.message:String(n)}function Dr(n){if(!n||typeof n!="object")return"unknown";let e=n.version;return typeof e=="string"&&e.trim()?e:"unknown"}function Ut(n){let e=(n??[]).filter(t=>Array.isArray(t)&&t.length>0).map(t=>({type:"buttons",buttons:t.map(r=>({label:r.label,value:Pl(r.callbackData),...r.style?{style:r.style}:{}}))}));return e.length>0?{blocks:e}:void 0}function ml(n){let e=n.blocks.filter(t=>t.type==="buttons"&&t.buttons.length>0).map(t=>({type:"buttons",buttons:t.buttons.map(r=>({label:r.label,value:r.value,...r.style?{style:r.style}:{}}))}));return e.length>0?{blocks:e}:void 0}function fl(n){if(!n||typeof n!="object"||Array.isArray(n))return!1;let e=n.interactive;if(!e||typeof e!="object"||Array.isArray(e))return!1;let t=e.blocks;return Array.isArray(t)&&t.some(r=>{if(!r||typeof r!="object"||Array.isArray(r))return!1;let o=r;return o.type==="buttons"&&Array.isArray(o.buttons)&&o.buttons.length>0})}function gl(n,e,t){if(!e)return n;let r=fl(n)?n:hl(n,e);return t!=="telegram"?r:yl(r,e)}function hl(n,e){return!n||typeof n!="object"||Array.isArray(n)?n:{...n,interactive:e}}function yl(n,e){if(!n||typeof n!="object"||Array.isArray(n))return n;let t=n,r=Fe(t.channelData),o=Fe(r?.telegram),i=kl(o?.buttons);if(i)return{...t,channelData:{...r??{},telegram:{...o??{},buttons:i}}};let s=Sl(e);return s?{...t,channelData:{...r??{},telegram:{...o??{},buttons:s}}}:n}function Sl(n){let e=n.blocks.filter(t=>t.type==="buttons"&&t.buttons.length>0).map(t=>t.buttons.filter(r=>typeof r.value=="string"&&r.value.trim().length>0&&Buffer.byteLength(r.value,"utf8")<=ui).map(r=>({text:r.label,callback_data:r.value,...pi(r.style)}))).filter(t=>t.length>0);return e.length>0?e:void 0}function kl(n){if(!Array.isArray(n))return;let e=n.map(t=>Array.isArray(t)?t.map(r=>{if(!r||typeof r!="object"||Array.isArray(r))return;let{style:o,...i}=r;if(!(typeof i.text!="string"||i.text.trim().length===0)&&!(i.callback_data!==void 0&&(typeof i.callback_data!="string"||i.callback_data.trim().length===0||Buffer.byteLength(i.callback_data,"utf8")>ui))&&vl(i))return{...i,...pi(o)}}).filter(r=>!!r):[]).filter(t=>t.length>0);return e.length>0?e:void 0}function vl(n){return Vt(n.callback_data)||Vt(n.url)||qt(n.web_app)||qt(n.webApp)||qt(n.login_url)||qt(n.loginUrl)||typeof n.switch_inline_query=="string"||typeof n.switch_inline_query_current_chat=="string"||Fe(n.switch_inline_query_chosen_chat)!==void 0||Fe(n.callback_game)!==void 0||n.pay===!0||li(n.copy_text)||li(n.copyText)}function Vt(n){return typeof n=="string"&&n.trim().length>0}function qt(n){let e=Fe(n);return Vt(e?.url)}function li(n){let e=Fe(n);return Vt(e?.text)}function pi(n){if(typeof n!="string")return{};let e=n.trim().toLowerCase(),t=ul[e];return t?{style:t}:{}}function Fe(n){return n&&typeof n=="object"&&!Array.isArray(n)?n:void 0}function Pl(n){return n.startsWith(`${W}:`)?n:`${W}:${n}`}var Ml=Cl(wl),rt="openclaw-code-agent",_l=`https://registry.npmjs.org/${encodeURIComponent(rt)}/latest`,Dl="openclaw-code-agent-auto-update.json",gi=1440*60*1e3,$l=7*gi,El=1e4,Le="plugin:auto-update";function fe(n){return!!n&&typeof n=="object"&&!Array.isArray(n)}function $r(n){return n instanceof Error?n.message:String(n)}function te(n){return n?.trim().replace(/^v/i,"")||void 0}function ee(n,e){let t=n[e];return typeof t=="string"&&t.trim()?t.trim():void 0}function ci(n){let e=n?.trim().replace(/^npm:/,"");if(!e)return;if(e.startsWith("@")){let r=e.indexOf("@",1);return r===-1?e:e.slice(0,r)}let t=e.indexOf("@");return t===-1?e:e.slice(0,t)}function Er(n){let e=`${n.stdout}
2
+ ${n.stderr}`;if(/No install record/i.test(e))throw new Error("OpenClaw reported no managed install record for OpenClaw Code Agent.");let t;try{t=JSON.parse(n.stdout)}catch{throw new Error("OpenClaw returned invalid JSON while inspecting the OpenClaw Code Agent install.")}if(!fe(t)||!fe(t.plugin)||!fe(t.install))throw new Error("OpenClaw inspection did not include the OpenClaw Code Agent plugin and managed install record.");let r=ee(t.plugin,"id"),o=te(ee(t.plugin,"version"));if(r!==rt||!o)throw new Error("OpenClaw inspection returned an unexpected OpenClaw Code Agent plugin identity or version.");let i=ee(t.install,"source"),s=te(ee(t.install,"version")),a=te(ee(t.install,"resolvedVersion"));if(i==="npm"){let l=ee(t.install,"resolvedName")??ci(ee(t.install,"spec"))??ci(ee(t.install,"resolvedSpec"));if(!l)throw new Error("The OpenClaw Code Agent npm install record does not identify its package.");return{pluginVersion:o,install:{source:i,packageName:l,recordedVersion:s,resolvedVersion:a}}}if(i==="clawhub"){let l=ee(t.install,"clawhubPackage");if(!l)throw new Error("The OpenClaw Code Agent ClawHub install record does not identify its package.");return{pluginVersion:o,install:{source:i,packageName:l,recordedVersion:s,resolvedVersion:a}}}throw new Error(`OpenClaw Code Agent self-update does not support managed install source ${i??"unknown"}.`)}function Nl(n,e){return["plugins","install",n.source==="npm"?`${n.packageName}@${e}`:`clawhub:${n.packageName}@${e}`,"--force"]}function Ol(n,e,t){if(e.install.source!==n.install.source||e.install.packageName!==n.install.packageName)throw new Error("OpenClaw Code Agent update verification found that the managed install source or package changed.");if(e.pluginVersion!==t)throw new Error(`OpenClaw Code Agent update verification found installed plugin version ${e.pluginVersion}, expected ${t}.`);let r=[e.install.recordedVersion,e.install.resolvedVersion].filter(o=>!!o);if(r.length===0||r.some(o=>o!==t))throw new Error(`OpenClaw Code Agent update verification found managed install version ${r.join("/")||"unknown"}, expected ${t}.`)}function Nr(n){let t=te(n)?.match(/^((?:0|[1-9]\d*))\.((?:0|[1-9]\d*))\.((?:0|[1-9]\d*))$/);if(!t?.[1]||!t[2]||!t[3])return;let r=[Number(t[1]),Number(t[2]),Number(t[3])];return r.every(Number.isSafeInteger)?r:void 0}function Wl(n,e){let t=Nr(n),r=Nr(e);if(!t||!r)return!1;for(let o=0;o<3;o+=1){if(t[o]>r[o])return!0;if(t[o]<r[o])return!1}return!1}function Fl(n){if(!fe(n))return{};let e={};for(let t of["lastCheckedAt","latestVersion","promptedVersion","lastPromptedAt","dismissedVersion","lastDismissedAt","updateInstalledVersion","restartPromptedVersion","lastError"]){let r=n[t];typeof r=="string"&&r.trim()&&(e[t]=r)}return e}function mi(n){if(!(!n?.provider||!n.target||n.provider==="system"||n.target==="system"))return{channel:n.provider,target:n.target,accountId:n.accountId,threadId:n.threadId,sessionKey:n.sessionKey}}function fi(){if(_.fallbackChannel)return ue(_.fallbackChannel)}async function Ll(){let{fetchNpmReleaseMetadata:n}=await import("./chunks/npm-release-client.js"),e=await n(_l,El),t=fe(e)&&typeof e.version=="string"?te(e.version):void 0;return t?{version:t}:void 0}async function Bl(n,e){let t=await n("openclaw",["plugins","search",e,"--limit","100","--json"]),r;try{r=JSON.parse(t.stdout)}catch{throw new Error("OpenClaw returned invalid JSON while checking ClawHub for OpenClaw Code Agent updates.")}let o=fe(r)&&Array.isArray(r.results)?r.results:[];for(let i of o){if(!fe(i)||!fe(i.package)||ee(i.package,"name")!==e)continue;let s=te(ee(i.package,"latestVersion"));return s?{version:s}:void 0}}async function Kl(n){let e=Er(await n("openclaw",["plugins","inspect",rt,"--json"]));return e.install.source==="npm"?Ll():Bl(n,e.install.packageName)}async function ql(n,e){let t=await Ml(n,e,{timeout:12e4,maxBuffer:1048576});return{stdout:t.stdout?.toString()??"",stderr:t.stderr?.toString()??""}}var Gt=class{constructor(e){this.options=e;this.statePath=xl(e.stateDir,Dl),this.notifier=e.notifier??new We,this.runCommand=e.runCommand??ql,this.fetchLatestRelease=e.fetchLatestRelease??(()=>Kl(this.runCommand)),this.now=e.now??Date.now}options;statePath;notifier;fetchLatestRelease;runCommand;now;checkInFlight;maybeCheckForUpdate(e={}){this.checkInFlight||(this.checkInFlight=this.checkForUpdate(e).catch(t=>{`${$r(t)}`}).finally(()=>{this.checkInFlight=void 0}))}async waitForIdle(){await this.checkInFlight}async installConfirmed(e,t){let r=te(e);if(!r||!Nr(r))return"Could not determine which stable OpenClaw Code Agent version to update to.";let o=Er(await this.runCommand("openclaw",["plugins","inspect",rt,"--json"])),i=await this.runCommand("openclaw",Nl(o.install,r));if(/No install record/i.test(`${i.stdout}
3
3
  ${i.stderr}`))throw new Error("OpenClaw reported no managed install record while updating OpenClaw Code Agent.");let s=Er(await this.runCommand("openclaw",["plugins","inspect",rt,"--json"]));Ol(o,s,r);let a=this.readState();this.writeState({...a,updateInstalledVersion:r});let l=mi(t?.route??fi());if(l)try{return await this.sendRestartPrompt(l,r),`OpenClaw Code Agent ${r} installation was verified. Restart confirmation was sent.`}catch(d){`${r}${$r(d)}`}return[`OpenClaw Code Agent ${r} installation was verified.`,"Restart the Gateway explicitly to load it: openclaw gateway restart"].join(`
4
4
  `)}async restartConfirmed(e){let t=te(e);return await this.runCommand("openclaw",["gateway","restart"]),t?`Gateway restart requested for OpenClaw Code Agent ${t}.`:"Gateway restart requested."}dismiss(e){return this.postpone(e,"Dismissed")}remindLater(e){return this.postpone(e,"Will remind later about")}postpone(e,t){let r=te(e),o=this.readState();return this.writeState({...o,...r?{dismissedVersion:r,lastDismissedAt:new Date(this.now()).toISOString()}:{}}),r?`${t} OpenClaw Code Agent ${r} update reminder.`:`${t} OpenClaw Code Agent update reminder.`}async checkForUpdate(e){let t=this.readState(),r=t.lastCheckedAt?Date.parse(t.lastCheckedAt):Number.NaN;if(Number.isFinite(r)&&this.now()-r<gi){await this.promptFromState(t,e);return}let o=new Date(this.now()).toISOString(),i={...t,lastCheckedAt:o};delete i.lastError,this.writeState(i);try{let s=await this.fetchLatestRelease(),a=te(s?.version),l={...this.readState(),latestVersion:a};delete l.lastError,this.writeState(l),await this.promptFromState(l,e)}catch(s){throw this.writeState({...this.readState(),lastError:$r(s)}),s}}async promptFromState(e,t){let r=te(e.latestVersion);if(!Wl(r,this.options.currentVersion)||!this.shouldPromptForVersion(e,r))return;let o=mi(t.route??fi());o&&(await this.sendUpdatePrompt(o,r),this.writeState({...this.readState(),latestVersion:r,promptedVersion:r,lastPromptedAt:new Date(this.now()).toISOString()}))}async sendUpdatePrompt(e,t){await this.notifier.send(e,[`OpenClaw Code Agent update available: ${this.options.currentVersion} -> ${t}.`,"","Update now will reinstall the exact approved version from OpenClaw Code Agent's recorded npm or ClawHub source, then verify it.","If the update succeeds, OpenClaw Code Agent will ask separately before restarting the Gateway."].join(`
5
- `),[[this.options.actionButtonFactory(Fe,"plugin-update-install","Update now",{pluginUpdateVersion:t,route:{provider:e.channel,accountId:e.accountId,target:e.target,threadId:e.threadId,sessionKey:e.sessionKey}}),this.options.actionButtonFactory(Fe,"plugin-update-remind-later","Remind later",{pluginUpdateVersion:t}),this.options.actionButtonFactory(Fe,"plugin-update-dismiss","Dismiss",{pluginUpdateVersion:t})]])}shouldPromptForVersion(e,t){let r=e.promptedVersion===t?e.lastPromptedAt:void 0,o=e.dismissedVersion===t?e.lastDismissedAt:void 0,i=[r,o].map(s=>s?Date.parse(s):Number.NaN).filter(s=>Number.isFinite(s));return i.length===0?!0:this.now()-Math.max(...i)>=$l}async sendRestartPrompt(e,t){await this.notifier.send(e,[`OpenClaw Code Agent ${t} installation was verified.`,"","Restart the Gateway now to load the updated plugin?","This will run: openclaw gateway restart"].join(`
6
- `),[[this.options.actionButtonFactory(Fe,"plugin-update-restart","Restart Gateway",{pluginUpdateVersion:t}),this.options.actionButtonFactory(Fe,"plugin-update-remind-later","Remind later",{pluginUpdateVersion:t}),this.options.actionButtonFactory(Fe,"plugin-update-dismiss","Dismiss",{pluginUpdateVersion:t})]]),this.writeState({...this.readState(),restartPromptedVersion:t})}readState(){try{return Ll(JSON.parse(Rl(this.statePath,"utf-8")))}catch{return{}}}writeState(e){bl(Tl(this.statePath),{recursive:!0});let t=`${this.statePath}.tmp`;Il(t,JSON.stringify(e,null,2),"utf-8"),Al(t,this.statePath)}};function Vl(n){return n.length>80?`${n.slice(0,80)}...`:n}function Ul(n){return n.worktreePath?!n.originalWorkdir||n.originalWorkdir===n.worktreePath?`${n.worktreePath} (worktree)`:`${n.worktreePath} (worktree of ${n.originalWorkdir})`:n.workdir}function Gl(n){let e=["Session launched successfully.",` Name: ${n.sessionName}`,` ID: ${n.sessionId}`,` Harness: ${n.harness}`,` Permission mode: ${n.permissionMode}`,` Plan approval: ${n.planApproval}`,` Worktree strategy: ${n.worktreeStrategy??"off"}`,...n.repoIntegrationPolicy?[` Repo policy: ${n.repoIntegrationPolicy}${n.repoProvider?` (${n.repoProvider})`:""}`]:[],` Resolved workdir: ${Ul(n)}`,` Model: ${n.model??"default"}`,` Prompt: "${Vl(n.prompt)}"`];if(n.reasoningEffort&&e.push(` Reasoning effort: ${n.reasoningEffort}`),n.fastMode&&e.push(" Fast mode: enabled"),n.resumeSessionId){let t=n.resumeSessionName?`${n.resumeSessionName} [${n.resumeSessionId}]`:n.resumeSessionId;e.push(` Resume: ${t}${n.forkSession?" (forked)":""}`),!n.forkSession&&n.resumeSessionName&&n.sessionName!==n.resumeSessionName&&e.push(` Follow-up label: ${n.sessionName}`)}else n.forceNewSession&&e.push(" Force new session: true");return n.clearedPersistedCodexResume&&e.push(" Thread state: historical Codex state cleared; starting a fresh thread."),e.push(" Mode: multi-turn (use agent_respond to send follow-up messages)"),e.push("","Use agent_sessions to check status, agent_output to see output."),e.join(`
7
- `)}function Gt(n,e){return Gl({...n,sessionId:e.id,sessionName:e.name,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,worktreeStrategy:e.worktreeStrategy??"off",repoIntegrationPolicy:e.repoIntegrationPolicy,repoProvider:e.repoProvider,worktreePath:e.worktreePath,originalWorkdir:e.originalWorkdir,resumeSessionName:e.resumedFromSessionName??n.resumeSessionName})}function jt(n){let e=n.resumedFromSessionName||n.sessionName,t=n.resumedFromSessionName&&n.sessionName!==n.resumedFromSessionName?` | Follow-up label: ${n.sessionName}`:"";return`▶️ [${e}] Resumed${t} | ${n.workdirLabel} | ${n.harnessLabel}`}function Be(n){let{requestedResumeSessionId:e,activeSession:t,persistedSession:r}=n;return e?t?{resumeSessionId:e,clearedPersistedCodexResume:!1}:r?.harness==="codex"&&r.backendRef?.kind!=="codex-app-server"?{resumeSessionId:void 0,clearedPersistedCodexResume:!0}:{resumeSessionId:e,clearedPersistedCodexResume:!1}:{resumeSessionId:void 0,clearedPersistedCodexResume:!1}}function zt(n){return"id"in n?n.id:n.sessionId}function ot(n){return n.status==="completed"||n.killReason==="done"}function jl(n){return!ot(n)||!C(n)?!1:n.backendRef?.kind==="codex-app-server"||n.backendRef?.kind==="opencode-server"}function zl(n){return(n.killReason==="shutdown"||n.killReason==="startup-timeout")&&!C(n)}function ke(n){if(n.status==="running")return{kind:"direct",reason:"already_running"};let e=zt(n);if(ot(n)&&!jl(n))return{kind:"unavailable",reason:"completed",stableSessionId:e};let t=C(n);if(t){let r="harnessName"in n?void 0:n,{resumeSessionId:o,clearedPersistedCodexResume:i}=Be({requestedResumeSessionId:t,activeSession:"harnessName"in n?{harnessSessionId:t}:void 0,persistedSession:r?{harness:r.harness,backendRef:r.backendRef}:void 0});return o?{kind:"resume",resumeSessionId:o,stableSessionId:e,clearedPersistedCodexResume:i}:{kind:"unavailable",reason:"legacy_non_resumable",stableSessionId:e,clearedPersistedCodexResume:i}}return zl(n)?{kind:"relaunch",stableSessionId:e}:{kind:"unavailable",reason:"missing_backend_state",stableSessionId:e}}import{existsSync as ki}from"fs";function Hl(n){return n.oneShotCliRun===!0?!0:!!n.sessionKey?.includes(":cron:")}function Ht(n){let e=Z({route:n.route});if(Ce(e))return{kind:"resolved",route:e,recovered:!1};let t=n.recoveredRouteSource?Z(n.recoveredRouteSource):void 0;return Ce(t)?{kind:"resolved",route:t,recovered:!0}:Hl(n.ctx)?{kind:"resolved",route:e??{provider:"system",target:"system",sessionKey:n.ctx.sessionKey},recovered:!1}:{kind:"error",text:[`Error: Cannot launch the asynchronous ${n.operation} because OpenClaw did not provide a trustworthy lifecycle delivery route.`,"The invocation context is missing session, delivery, and workspace identity (as occurs in the standalone deferred/nested plugin-tool bridge).","Retry from the originating chat/session or update OpenClaw so nested plugin-tool invocations preserve ToolContext routing fields. No coding session was started."].join(" ")}}function hi(n){return n==null?void 0:String(n).trim()||void 0}function Ql(n){return n.trim().replace(/^['"`](.*)['"`]$/s,"$1").trim()}function Yl(n){let e=n.split(/\n\s*\n/,1)[0]?.split(`
5
+ `),[[this.options.actionButtonFactory(Le,"plugin-update-install","Update now",{pluginUpdateVersion:t,route:{provider:e.channel,accountId:e.accountId,target:e.target,threadId:e.threadId,sessionKey:e.sessionKey}}),this.options.actionButtonFactory(Le,"plugin-update-remind-later","Remind later",{pluginUpdateVersion:t}),this.options.actionButtonFactory(Le,"plugin-update-dismiss","Dismiss",{pluginUpdateVersion:t})]])}shouldPromptForVersion(e,t){let r=e.promptedVersion===t?e.lastPromptedAt:void 0,o=e.dismissedVersion===t?e.lastDismissedAt:void 0,i=[r,o].map(s=>s?Date.parse(s):Number.NaN).filter(s=>Number.isFinite(s));return i.length===0?!0:this.now()-Math.max(...i)>=$l}async sendRestartPrompt(e,t){await this.notifier.send(e,[`OpenClaw Code Agent ${t} installation was verified.`,"","Restart the Gateway now to load the updated plugin?","This will run: openclaw gateway restart"].join(`
6
+ `),[[this.options.actionButtonFactory(Le,"plugin-update-restart","Restart Gateway",{pluginUpdateVersion:t}),this.options.actionButtonFactory(Le,"plugin-update-remind-later","Remind later",{pluginUpdateVersion:t}),this.options.actionButtonFactory(Le,"plugin-update-dismiss","Dismiss",{pluginUpdateVersion:t})]]),this.writeState({...this.readState(),restartPromptedVersion:t})}readState(){try{return Fl(JSON.parse(Rl(this.statePath,"utf-8")))}catch{return{}}}writeState(e){bl(Tl(this.statePath),{recursive:!0});let t=`${this.statePath}.tmp`;Il(t,JSON.stringify(e,null,2),"utf-8"),Al(t,this.statePath)}};function Vl(n){return n.length>80?`${n.slice(0,80)}...`:n}function Ul(n){return n.worktreePath?!n.originalWorkdir||n.originalWorkdir===n.worktreePath?`${n.worktreePath} (worktree)`:`${n.worktreePath} (worktree of ${n.originalWorkdir})`:n.workdir}function Gl(n){let e=["Session launched successfully.",` Name: ${n.sessionName}`,` ID: ${n.sessionId}`,` Harness: ${n.harness}`,` Permission mode: ${n.permissionMode}`,` Plan approval: ${n.planApproval}`,` Worktree strategy: ${n.worktreeStrategy??"off"}`,...n.repoIntegrationPolicy?[` Repo policy: ${n.repoIntegrationPolicy}${n.repoProvider?` (${n.repoProvider})`:""}`]:[],` Resolved workdir: ${Ul(n)}`,` Model: ${n.model??"default"}`,` Prompt: "${Vl(n.prompt)}"`];if(n.reasoningEffort&&e.push(` Reasoning effort: ${n.reasoningEffort}`),n.fastMode&&e.push(" Fast mode: enabled"),n.resumeSessionId){let t=n.resumeSessionName?`${n.resumeSessionName} [${n.resumeSessionId}]`:n.resumeSessionId;e.push(` Resume: ${t}${n.forkSession?" (forked)":""}`),!n.forkSession&&n.resumeSessionName&&n.sessionName!==n.resumeSessionName&&e.push(` Follow-up label: ${n.sessionName}`)}else n.forceNewSession&&e.push(" Force new session: true");return n.clearedPersistedCodexResume&&e.push(" Thread state: historical Codex state cleared; starting a fresh thread."),e.push(" Mode: multi-turn (use agent_respond to send follow-up messages)"),e.push("","Use agent_sessions to check status, agent_output to see output."),e.join(`
7
+ `)}function jt(n,e){return Gl({...n,sessionId:e.id,sessionName:e.name,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,worktreeStrategy:e.worktreeStrategy??"off",repoIntegrationPolicy:e.repoIntegrationPolicy,repoProvider:e.repoProvider,worktreePath:e.worktreePath,originalWorkdir:e.originalWorkdir,resumeSessionName:e.resumedFromSessionName??n.resumeSessionName})}function zt(n){let e=n.resumedFromSessionName||n.sessionName,t=n.resumedFromSessionName&&n.sessionName!==n.resumedFromSessionName?` | Follow-up label: ${n.sessionName}`:"";return`▶️ [${e}] Resumed${t} | ${n.workdirLabel} | ${n.harnessLabel}`}function Be(n){let{requestedResumeSessionId:e,activeSession:t,persistedSession:r}=n;return e?t?{resumeSessionId:e,clearedPersistedCodexResume:!1}:r?.harness==="codex"&&r.backendRef?.kind!=="codex-app-server"?{resumeSessionId:void 0,clearedPersistedCodexResume:!0}:{resumeSessionId:e,clearedPersistedCodexResume:!1}:{resumeSessionId:void 0,clearedPersistedCodexResume:!1}}function Ht(n){return"id"in n?n.id:n.sessionId}function ot(n){return n.status==="completed"||n.killReason==="done"}function jl(n){return!ot(n)||!C(n)?!1:n.backendRef?.kind==="codex-app-server"||n.backendRef?.kind==="opencode-server"}function zl(n){return(n.killReason==="shutdown"||n.killReason==="startup-timeout")&&!C(n)}function ke(n){if(n.status==="running")return{kind:"direct",reason:"already_running"};let e=Ht(n);if(ot(n)&&!jl(n))return{kind:"unavailable",reason:"completed",stableSessionId:e};let t=C(n);if(t){let r="harnessName"in n?void 0:n,{resumeSessionId:o,clearedPersistedCodexResume:i}=Be({requestedResumeSessionId:t,activeSession:"harnessName"in n?{harnessSessionId:t}:void 0,persistedSession:r?{harness:r.harness,backendRef:r.backendRef}:void 0});return o?{kind:"resume",resumeSessionId:o,stableSessionId:e,clearedPersistedCodexResume:i}:{kind:"unavailable",reason:"legacy_non_resumable",stableSessionId:e,clearedPersistedCodexResume:i}}return zl(n)?{kind:"relaunch",stableSessionId:e}:{kind:"unavailable",reason:"missing_backend_state",stableSessionId:e}}import{existsSync as ki}from"fs";function Hl(n){return n.oneShotCliRun===!0?!0:!!n.sessionKey?.includes(":cron:")}function Qt(n){let e=Z({route:n.route});if(Ce(e))return{kind:"resolved",route:e,recovered:!1};let t=n.recoveredRouteSource?Z(n.recoveredRouteSource):void 0;return Ce(t)?{kind:"resolved",route:t,recovered:!0}:Hl(n.ctx)?{kind:"resolved",route:e??{provider:"system",target:"system",sessionKey:n.ctx.sessionKey},recovered:!1}:{kind:"error",text:[`Error: Cannot launch the asynchronous ${n.operation} because OpenClaw did not provide a trustworthy lifecycle delivery route.`,"The invocation context is missing session, delivery, and workspace identity (as occurs in the standalone deferred/nested plugin-tool bridge).","Retry from the originating chat/session or update OpenClaw so nested plugin-tool invocations preserve ToolContext routing fields. No coding session was started."].join(" ")}}function hi(n){return n==null?void 0:String(n).trim()||void 0}function Ql(n){return n.trim().replace(/^['"`](.*)['"`]$/s,"$1").trim()}function Yl(n){let e=n.split(/\n\s*\n/,1)[0]?.split(`
8
8
  `).map(t=>t.trim()).filter(Boolean)??[];if(e.length!==0)for(let t of e){let r=t.match(/^(Workdir|Repo):\s*(.+)$/),o=Ql(r?.[2]??"");if(o.startsWith("/")&&ki(o))return o}}function yi(n,e){return n.workdir!==e.workdir?!1:e.originSessionKey&&n.originSessionKey?n.originSessionKey===e.originSessionKey:!e.originChannel||!n.originChannel?!1:n.originChannel===e.originChannel&&hi(n.originThreadId)===hi(e.originThreadId)}function Si(n){return n.slice(0,3).map(e=>` - ${e.name} [${e.ref}] | status=${e.status}${e.lifecycle?` | lifecycle=${e.lifecycle}`:""}`).join(`
9
- `)}function Jl(n,e){let t=[],r=[],o=new Set;for(let i of n.list?.("all")??[]){if(!yi(i,e))continue;let s=i.id;if(!o.has(s)){if(o.add(s),i.isExplicitlyResumable){t.push({ref:i.id,name:i.name,status:i.status,lifecycle:i.lifecycle,resumable:!0});continue}(i.status==="starting"||i.status==="running")&&r.push({ref:i.id,name:i.name,status:i.status,lifecycle:i.lifecycle,resumable:!1})}}for(let i of n.listPersistedSessions?.()??[]){if(!i.resumable||!yi(i,e))continue;let s=D(i)??i.harnessSessionId,a=i.sessionId??C(i)??i.harnessSessionId;!s||!a||o.has(a)||(o.add(a),t.push({ref:s,name:i.name,status:i.status,lifecycle:i.lifecycle,resumable:!0}))}return{resumable:t,active:r}}function Qt(n,e,t){let r=n.workdir||Yl(n.prompt)||e.workspaceDir||_.defaultWorkdir||process.cwd();if(!ki(r))return{kind:"error",text:`Error: Working directory does not exist: ${r}`};let o=n.harness??Y(),i=Me(o),s=n.model??i,a=Pt(o,s),l=n.model!==void 0,d=St(o);if(!a&&(o!=="opencode"||d&&d.length>0))return{kind:"error",text:`Error: No default model configured for harness "${o}". Set plugins.entries["openclaw-code-agent"].config.harnesses.${o}.defaultModel or pass model explicitly.`};if(a&&!bt(o,a))return{kind:"error",text:`Error: Model "${s}" is not supported for harness "${o}". Use a bare Codex model id such as "gpt-5.6-sol".`};if(a&&d&&d.length>0&&!wt(o,a,d))return{kind:"error",text:l?`Error: Model "${s}" is not allowed. Permitted models: ${d.join(", ")}`:`Error: Default model "${s||"undefined"}" is not in allowedModels (${d.join(", ")}). Update your plugin config to set a compatible defaultModel.`};let u=Rt(o,a,d),f=kt(e),h=vt(e,f||$e(r)),k=e.sessionKey||void 0,g=Vo(k)??qo(e);if(!n.resume_session_id&&!n.force_new_session){let T=Jl(t,{workdir:r,originSessionKey:k,originChannel:h,originThreadId:g});if(T.resumable.length>0||T.active.length>0){let L=T.resumable.length>0?["Linked resumable session(s) already exist for this thread/workdir:",Si(T.resumable),"","Resume the latest one with:",` agent_respond(session='${T.resumable[0].ref}', message='<next instruction>')`,"Fork from it with:",` agent_launch(prompt='<new task>', resume_session_id='${T.resumable[0].ref}', fork_session=true)`].join(`
9
+ `)}function Jl(n,e){let t=[],r=[],o=new Set;for(let i of n.list?.("all")??[]){if(!yi(i,e))continue;let s=i.id;if(!o.has(s)){if(o.add(s),i.isExplicitlyResumable){t.push({ref:i.id,name:i.name,status:i.status,lifecycle:i.lifecycle,resumable:!0});continue}(i.status==="starting"||i.status==="running")&&r.push({ref:i.id,name:i.name,status:i.status,lifecycle:i.lifecycle,resumable:!1})}}for(let i of n.listPersistedSessions?.()??[]){if(!i.resumable||!yi(i,e))continue;let s=D(i)??i.harnessSessionId,a=i.sessionId??C(i)??i.harnessSessionId;!s||!a||o.has(a)||(o.add(a),t.push({ref:s,name:i.name,status:i.status,lifecycle:i.lifecycle,resumable:!0}))}return{resumable:t,active:r}}function Yt(n,e,t){let r=n.workdir||Yl(n.prompt)||e.workspaceDir||_.defaultWorkdir||process.cwd();if(!ki(r))return{kind:"error",text:`Error: Working directory does not exist: ${r}`};let o=n.harness??Y(),i=Me(o),s=n.model??i,a=wt(o,s),l=n.model!==void 0,d=kt(o);if(!a&&(o!=="opencode"||d&&d.length>0))return{kind:"error",text:`Error: No default model configured for harness "${o}". Set plugins.entries["openclaw-code-agent"].config.harnesses.${o}.defaultModel or pass model explicitly.`};if(a&&!Rt(o,a))return{kind:"error",text:`Error: Model "${s}" is not supported for harness "${o}". Use a bare Codex model id such as "gpt-5.6-sol".`};if(a&&d&&d.length>0&&!bt(o,a,d))return{kind:"error",text:l?`Error: Model "${s}" is not allowed. Permitted models: ${d.join(", ")}`:`Error: Default model "${s||"undefined"}" is not in allowedModels (${d.join(", ")}). Update your plugin config to set a compatible defaultModel.`};let u=At(o,a,d),f=vt(e),g=Pt(e,f||$e(r)),k=e.sessionKey||void 0,h=Vo(k)??qo(e);if(!n.resume_session_id&&!n.force_new_session){let T=Jl(t,{workdir:r,originSessionKey:k,originChannel:g,originThreadId:h});if(T.resumable.length>0||T.active.length>0){let F=T.resumable.length>0?["Linked resumable session(s) already exist for this thread/workdir:",Si(T.resumable),"","Resume the latest one with:",` agent_respond(session='${T.resumable[0].ref}', message='<next instruction>')`,"Fork from it with:",` agent_launch(prompt='<new task>', resume_session_id='${T.resumable[0].ref}', fork_session=true)`].join(`
10
10
  `):"",U=T.active.length>0?[T.resumable.length>0?"Linked active session(s):":"Linked active session(s) already exist for this thread/workdir:",Si(T.active),"","Send a follow-up instead of launching a duplicate:",` agent_respond(session='${T.active[0].ref}', message='<next instruction>')`].join(`
11
- `):"";return{kind:"blocked",text:["Resume-first protection blocked a fresh launch.","",L,U,["If you intentionally want a brand-new independent session here, call:"," agent_launch(prompt='<new task>', force_new_session=true)"].join(`
11
+ `):"";return{kind:"blocked",text:["Resume-first protection blocked a fresh launch.","",F,U,["If you intentionally want a brand-new independent session here, call:"," agent_launch(prompt='<new task>', force_new_session=true)"].join(`
12
12
  `)].filter(Boolean).join(`
13
13
 
14
- `)}}}let p=n.resume_session_id,y=p?t.resolve?.(p):void 0,w=p?t.getPersistedSession?.(p):void 0;if(p){let T=t.resolveBackendConversationId?.(p)??t.resolveHarnessSessionId?.(p);if(!T)return{kind:"error",text:`Error: Could not resolve resume_session_id "${p}" to a session ID. Use agent_sessions to list available sessions.`};p=T}let{resumeSessionId:R,clearedPersistedCodexResume:A}=Be({requestedResumeSessionId:p,activeSession:y?{harnessSessionId:y.backendConversationId??y.harnessSessionId}:void 0,persistedSession:w?{harness:w.harness,backendRef:w.backendRef}:void 0}),I=n.permission_mode??_.permissionMode,b=n.plan_approval??_.planApproval,m=Ht({ctx:e,route:De(e,h,k),recoveredRouteSource:w,operation:"coding session"});if(m.kind==="error")return m;let P=m.route;return{kind:"resolved",workdir:r,harness:o,resolvedModel:u,permissionMode:I,planApproval:b,originChannel:m.recovered?P.accountId?`${P.provider}|${P.accountId}|${P.target}`:`${P.provider}|${P.target}`:h,originThreadId:m.recovered?P.threadId:g,originSessionKey:m.recovered?P.sessionKey:k,route:P,resumeSessionId:R,resolvedResumeId:p,clearedPersistedCodexResume:A,reasoningEffort:pe(o),fastMode:_e(o)}}function ge(n){let e=n.harness?.trim(),t=n.model?.trim();return e&&t?`${e} | ${t}`:e?`${e} | default`:t}function se(n){if(!Number.isFinite(n))return"0s";let e=Math.floor(n/1e3),t=Math.floor(e/60),r=e%60;return t>0?`${t}m${r}s`:`${r}s`}var Xl=new Set(["a","an","the","is","are","was","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","shall","can","need","must","i","me","my","we","our","you","your","it","its","he","she","to","of","in","for","on","with","at","by","from","as","into","through","about","that","this","these","those","and","or","but","if","then","so","not","no","please","just","also","very","all","some","any","each","make","write","create","build","implement","add","update"]);function Pi(n){let t=n.toLowerCase().replace(/[^a-z0-9\s-]/g," ").split(/\s+/).filter(r=>r.length>1&&!Xl.has(r)).slice(0,3);return t.length===0?"session":t.join("-")}var vi={starting:"🟡",running:"🟢",completed:"✅",failed:"❌",killed:"⛔",awaiting_plan_decision:"📋",awaiting_user_input:"❓",awaiting_worktree_decision:"🌿",suspended:"⏸️",terminal:"🏁"};function Zl(n){let e=n.worktreeLifecycle?.state??n.worktreeState;return n.worktreeMerged||e==="merged"?"[merged ✓]":e==="released"?"[released]":n.worktreePrUrl?`[PR: ${n.worktreePrUrl}]`:e==="pr_open"?"[PR open]":e==="dismissed"?"[dismissed]":e==="no_change"?"[no change]":"[not merged]"}function wi(n){let e=vi[n.phase]??vi[n.status]??"❓",t=se(n.duration),r=n.multiTurn?"multi-turn":"single",o=n.prompt.length>80?n.prompt.slice(0,80)+"...":n.prompt,i=n.costUsd>0?` | $${n.costUsd.toFixed(2)}`:"",s=[`${e} ${n.name} [${n.id}] (${t}${i}) — ${r}`,` 📁 ${n.workdir}`,` 📝 "${o}"`];if(n.worktreePath&&n.worktreeBranch&&s.push(` 🌿 Worktree: ${n.worktreeBranch} ${Zl(n)}`),n.phase!==n.status&&s.push(` ⚙️ Phase: ${n.phase}`),n.lifecycle&&n.lifecycle!==n.phase&&s.push(` 🔄 Lifecycle: ${n.lifecycle}`),(n.requestedPermissionMode||n.currentPermissionMode||n.approvalExecutionState)&&s.push(` 🔐 Approval: ${n.approvalExecutionState??"unknown"} (requested=${n.requestedPermissionMode??"unknown"}, effective=${n.currentPermissionMode??"unknown"})`),n.resumable&&s.push(" ↩️ Resumable: yes"),n.recovered&&n.runtimeRecovery){let l=n.runtimeRecovery?.reason?` (${n.runtimeRecovery.reason})`:"";s.push(` ♻️ Recovered: persisted metadata only; no live process to kill${l}`),s.push(` 🩺 Recovery: raw=${n.runtimeRecovery.rawStatus??"unknown"}/${n.runtimeRecovery.rawLifecycle??"unknown"}/${n.runtimeRecovery.rawRuntimeState??"unknown"} → normalized=${n.runtimeRecovery.normalizedStatus}/${n.runtimeRecovery.normalizedLifecycle??"unknown"}/${n.runtimeRecovery.normalizedRuntimeState??"unknown"}`)}else n.recovered&&s.push(" 💾 Persisted: no live runtime process in this Gateway");n.harness?s.push(` 🧰 Harness | model: ${ge({harness:n.harness,model:n.model})}`):n.model&&s.push(` 🧰 Harness | model: ${n.model}`);let a=C(n);return a&&s.push(` 🔗 Backend ID: ${a}`),n.resumeSessionId&&s.push(` ↩️ Resumed from: ${n.resumeSessionId}${n.forkSession?" (forked)":""}`),s.join(`
15
- `)}function Yt(n,e){let t=n.sessionsWithDuration>0?n.totalDurationMs/n.sessionsWithDuration:0,{completed:r,failed:o,killed:i}=n.sessionsByStatus,s=["📊 OpenClaw Code Agent Stats","","📋 Sessions",` Launched: ${n.totalLaunched}`,` Running: ${e}`,` Completed: ${r}`,` Failed: ${o}`,` Killed: ${i}`,"",`⏱️ Average duration: ${t>0?se(t):"n/a"}`];if(n.mostExpensive){let a=n.mostExpensive;s.push("","🏆 Notable session",` ${a.name} [${a.id}]`,` 📝 "${a.prompt}"`)}return s.join(`
14
+ `)}}}let p=n.resume_session_id,y=p?t.resolve?.(p):void 0,P=p?t.getPersistedSession?.(p):void 0;if(p){let T=t.resolveBackendConversationId?.(p)??t.resolveHarnessSessionId?.(p);if(!T)return{kind:"error",text:`Error: Could not resolve resume_session_id "${p}" to a session ID. Use agent_sessions to list available sessions.`};p=T}let{resumeSessionId:b,clearedPersistedCodexResume:A}=Be({requestedResumeSessionId:p,activeSession:y?{harnessSessionId:y.backendConversationId??y.harnessSessionId}:void 0,persistedSession:P?{harness:P.harness,backendRef:P.backendRef}:void 0}),I=n.permission_mode??_.permissionMode,R=n.plan_approval??_.planApproval,m=Qt({ctx:e,route:De(e,g,k),recoveredRouteSource:P,operation:"coding session"});if(m.kind==="error")return m;let w=m.route;return{kind:"resolved",workdir:r,harness:o,resolvedModel:u,permissionMode:I,planApproval:R,originChannel:m.recovered?w.accountId?`${w.provider}|${w.accountId}|${w.target}`:`${w.provider}|${w.target}`:g,originThreadId:m.recovered?w.threadId:h,originSessionKey:m.recovered?w.sessionKey:k,route:w,resumeSessionId:b,resolvedResumeId:p,clearedPersistedCodexResume:A,reasoningEffort:pe(o),fastMode:_e(o)}}function ge(n){let e=n.harness?.trim(),t=n.model?.trim();return e&&t?`${e} | ${t}`:e?`${e} | default`:t}function se(n){if(!Number.isFinite(n))return"0s";let e=Math.floor(n/1e3),t=Math.floor(e/60),r=e%60;return t>0?`${t}m${r}s`:`${r}s`}var Xl=new Set(["a","an","the","is","are","was","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","shall","can","need","must","i","me","my","we","our","you","your","it","its","he","she","to","of","in","for","on","with","at","by","from","as","into","through","about","that","this","these","those","and","or","but","if","then","so","not","no","please","just","also","very","all","some","any","each","make","write","create","build","implement","add","update"]);function Pi(n){let t=n.toLowerCase().replace(/[^a-z0-9\s-]/g," ").split(/\s+/).filter(r=>r.length>1&&!Xl.has(r)).slice(0,3);return t.length===0?"session":t.join("-")}var vi={starting:"🟡",running:"🟢",completed:"✅",failed:"❌",killed:"⛔",awaiting_plan_decision:"📋",awaiting_user_input:"❓",awaiting_worktree_decision:"🌿",suspended:"⏸️",terminal:"🏁"};function Zl(n){let e=n.worktreeLifecycle?.state??n.worktreeState;return n.worktreeMerged||e==="merged"?"[merged ✓]":e==="released"?"[released]":n.worktreePrUrl?`[PR: ${n.worktreePrUrl}]`:e==="pr_open"?"[PR open]":e==="dismissed"?"[dismissed]":e==="no_change"?"[no change]":"[not merged]"}function wi(n){let e=vi[n.phase]??vi[n.status]??"❓",t=se(n.duration),r=n.multiTurn?"multi-turn":"single",o=n.prompt.length>80?n.prompt.slice(0,80)+"...":n.prompt,i=n.costUsd>0?` | $${n.costUsd.toFixed(2)}`:"",s=[`${e} ${n.name} [${n.id}] (${t}${i}) — ${r}`,` 📁 ${n.workdir}`,` 📝 "${o}"`];if(n.worktreePath&&n.worktreeBranch&&s.push(` 🌿 Worktree: ${n.worktreeBranch} ${Zl(n)}`),n.phase!==n.status&&s.push(` ⚙️ Phase: ${n.phase}`),n.lifecycle&&n.lifecycle!==n.phase&&s.push(` 🔄 Lifecycle: ${n.lifecycle}`),(n.requestedPermissionMode||n.currentPermissionMode||n.approvalExecutionState)&&s.push(` 🔐 Approval: ${n.approvalExecutionState??"unknown"} (requested=${n.requestedPermissionMode??"unknown"}, effective=${n.currentPermissionMode??"unknown"})`),n.resumable&&s.push(" ↩️ Resumable: yes"),n.recovered&&n.runtimeRecovery){let l=n.runtimeRecovery?.reason?` (${n.runtimeRecovery.reason})`:"";s.push(` ♻️ Recovered: persisted metadata only; no live process to kill${l}`),s.push(` 🩺 Recovery: raw=${n.runtimeRecovery.rawStatus??"unknown"}/${n.runtimeRecovery.rawLifecycle??"unknown"}/${n.runtimeRecovery.rawRuntimeState??"unknown"} → normalized=${n.runtimeRecovery.normalizedStatus}/${n.runtimeRecovery.normalizedLifecycle??"unknown"}/${n.runtimeRecovery.normalizedRuntimeState??"unknown"}`)}else n.recovered&&s.push(" 💾 Persisted: no live runtime process in this Gateway");n.harness?s.push(` 🧰 Harness | model: ${ge({harness:n.harness,model:n.model})}`):n.model&&s.push(` 🧰 Harness | model: ${n.model}`);let a=C(n);return a&&s.push(` 🔗 Backend ID: ${a}`),n.resumeSessionId&&s.push(` ↩️ Resumed from: ${n.resumeSessionId}${n.forkSession?" (forked)":""}`),s.join(`
15
+ `)}function Jt(n,e){let t=n.sessionsWithDuration>0?n.totalDurationMs/n.sessionsWithDuration:0,{completed:r,failed:o,killed:i}=n.sessionsByStatus,s=["📊 OpenClaw Code Agent Stats","","📋 Sessions",` Launched: ${n.totalLaunched}`,` Running: ${e}`,` Completed: ${r}`,` Failed: ${o}`,` Killed: ${i}`,"",`⏱️ Average duration: ${t>0?se(t):"n/a"}`,`💵 Estimated API cost: $${n.totalCostUsd.toFixed(2)}`];if(n.mostExpensive){let a=n.mostExpensive;s.push("","🏆 Notable session",` ${a.name} [${a.id}]`,` 💵 $${a.costUsd.toFixed(2)}`,` 📝 "${a.prompt}"`)}return s.join(`
16
16
  `)}function q(n,e){return e<=0?"":n.length<=e?n:e<=3?".".repeat(e):n.slice(0,e-3)+"..."}function bi(n,e){let t=n.split(`
17
17
  `),r=[],o=0;for(let i=t.length-1;i>=0;i--){let s=t[i].length+(r.length>0?1:0);if(o+s>e&&r.length>0)break;r.unshift(t[i]),o+=s}return r.join(`
18
18
  `)}function Ri(n,e){let t=n.split(`
19
19
  `),r=[],o=0;for(let i=0;i<t.length;i++){let s=t[i].length+(r.length>0?1:0);if(o+s>e&&r.length>0)break;r.push(t[i]),o+=s}return r.join(`
20
- `)}var ed="openclaw-code-agent",td=160,Jt={create(){},progress(){},finalize(){}};function Xt(n,e){let t=e instanceof Error?e.message:String(e);`${n}${t}`}function Wr(n,e){if(e.applied===!1){let t=e.code?` (${e.code})`:"";`${n}${t}`}}function nd(n){let e=n.prompt.trim().replace(/\s+/g," ");return q(e||n.name,td)}function Ai(n){if(n.status==="starting"||n.lifecycle==="starting")return"Starting";if(n.lifecycle==="active")return"Running";if(n.lifecycle==="awaiting_plan_decision")return"Waiting for plan approval";if(n.lifecycle==="awaiting_user_input")return"Waiting for input";if(n.lifecycle==="awaiting_worktree_decision")return"Waiting for worktree decision";if(n.lifecycle==="suspended")return"Suspended after idle timeout"}function Ii(n){if(n.status==="completed")return"succeeded";if(n.status==="failed")return"failed";if(n.status==="killed")return n.killReason==="idle-timeout"||n.killReason==="startup-timeout"?"timed_out":"cancelled"}function Zt(n,e){return n==="completed"?"Completed":n==="failed"?"Failed":e==="idle-timeout"?"Timed out after idle timeout":e==="startup-timeout"?"Timed out during startup":e==="shutdown"?"Cancelled during shutdown":e==="user"?"Cancelled by user":"Cancelled"}function rd(n){return en(n.lifecycle)}function en(n){return n==="awaiting_plan_decision"||n==="awaiting_user_input"||n==="awaiting_worktree_decision"||n==="suspended"}function od(n){if(n.pendingPlanApproval||n.pendingWorktreeDecisionSince)return!0;if(n.runtimeRecovery?.reason==="persisted-running-without-runtime"){let e=n.runtimeRecovery.rawLifecycle;return e==="suspended"?n.runtimeRecovery.rawResumable===!0||n.resumable===!0:en(e)}return n.lifecycle==="suspended"?n.resumable===!0:en(n.lifecycle)}function id(n){if(n.runtimeRecovery?.reason==="persisted-running-without-runtime"){let e=n.runtimeRecovery.rawLifecycle;if(en(e))return e}return n.lifecycle}function Or(n,e,t){return{phase:e,integration:"phase-1-managed-task-flow",sessionId:n.id,sessionName:n.name,sessionStatus:n.status,sessionLifecycle:n.lifecycle,summary:t}}function sd(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.createManaged=="function"&&typeof e.resume=="function"&&typeof e.setWaiting=="function"&&typeof e.finish=="function"&&typeof e.fail=="function"}function tn(n,e){if(e.applied)return e.flow;let t=e.current;return t?.flowId&&typeof t.revision=="number"?t:n}var Lr=class{constructor(e){this.taskFlow=e}taskFlow;flow;finalized=!1;lastProgressKey;create(e){if(this.flow||this.finalized)return;let t="Starting",r=Date.now();try{this.flow=this.taskFlow.createManaged({controllerId:ed,goal:nd(e),status:"running",notifyPolicy:"silent",currentStep:t,stateJson:Or(e,"created",t),createdAt:e.startedAt,updatedAt:r}),e.taskFlowMirror=this.flow,this.lastProgressKey=this.progressKey(e,t)}catch(o){Xt("create",o)}}progress(e){if(!this.flow||this.finalized)return;let t=Ai(e);if(!t)return;let r=this.progressKey(e,t);if(r!==this.lastProgressKey)try{let o=Or(e,"progress",t),i=Date.now(),s=rd(e)?this.taskFlow.setWaiting({flowId:this.flow.flowId,expectedRevision:this.flow.revision,currentStep:t,stateJson:o,waitJson:{reason:t,sessionId:e.id},blockedSummary:t,updatedAt:i}):this.taskFlow.resume({flowId:this.flow.flowId,expectedRevision:this.flow.revision,status:"running",currentStep:t,stateJson:o,updatedAt:i});this.flow=tn(this.flow,s),this.flow&&(e.taskFlowMirror=this.flow),this.lastProgressKey=r}catch(o){Xt("progress",o)}}finalize(e){if(!this.flow||this.finalized)return;let t=Ii(e);if(!t)return;let r=t==="succeeded"?"Completed":t==="failed"?"Failed":Zt(e.status,e.killReason);try{let o=e.completedAt??Date.now(),i={...Or(e,"terminal",r),terminalStatus:t,terminalSummary:Zt(e.status,e.killReason),...e.status==="failed"&&e.error?{error:e.error}:{}},s=t==="succeeded"?this.taskFlow.finish({flowId:this.flow.flowId,expectedRevision:this.flow.revision,stateJson:i,updatedAt:o,endedAt:o}):this.taskFlow.fail({flowId:this.flow.flowId,expectedRevision:this.flow.revision,stateJson:i,blockedSummary:Zt(e.status,e.killReason),updatedAt:o,endedAt:o});Wr("finalize",s),this.flow=tn(this.flow,s),this.flow&&(e.taskFlowMirror=this.flow),this.finalized=!0}catch(o){Xt("finalize",o)}}progressKey(e,t){return`${e.status}:${e.lifecycle}:${t}`}};function ad(n){return n==="succeeded"||n==="failed"||n==="cancelled"||n==="lost"}function ld(n){if(!n?.trim())return;let e=vr()?.fromToolContext;if(typeof e!="function")return;let t=e({sessionKey:n});if(!t||typeof t!="object")return;let r=t;if(!(typeof r.setWaiting!="function"||typeof r.finish!="function"||typeof r.fail!="function"))return{setWaiting:r.setWaiting,finish:r.finish,fail:r.fail}}function dd(n){return n.originSessionKey??n.route?.sessionKey}function ud(n){return n.runtimeRecovery?.reason==="persisted-running-without-runtime"?"Lost after OpenClaw Code Agent restart without live process":Zt(n.status,n.killReason??"unknown")}function Ti(n){let e=n.taskFlowMirror?{...n.taskFlowMirror}:void 0;if(!e||ad(e.status))return;let t=ld(dd(n));if(!t)return;let r=Date.now();if(od(n)){let d=Ai({status:n.status,lifecycle:id(n)??"suspended"})??"Waiting",u=t.setWaiting({flowId:e.flowId,expectedRevision:e.revision,currentStep:d,stateJson:{phase:"progress",integration:"phase-1-managed-task-flow",sessionId:n.sessionId,sessionName:n.name,sessionStatus:n.status,sessionLifecycle:n.lifecycle,summary:d,reconciled:!0},waitJson:{reason:d,sessionId:n.sessionId},blockedSummary:d,updatedAt:r});return Wr("reconcile-waiting",u),tn(e,u)}let o=Ii({status:n.status,killReason:n.killReason??"unknown"})??"failed",i=ud(n),s=n.completedAt??r,a={phase:"terminal",integration:"phase-1-managed-task-flow",sessionId:n.sessionId,sessionName:n.name,sessionStatus:n.status,sessionLifecycle:n.lifecycle,summary:i,terminalStatus:n.runtimeRecovery?.reason==="persisted-running-without-runtime"?"lost":o,terminalSummary:i,reconciled:!0,runtimeRecovery:n.runtimeRecovery},l=o==="succeeded"?t.finish({flowId:e.flowId,expectedRevision:e.revision,stateJson:a,updatedAt:s,endedAt:s}):t.fail({flowId:e.flowId,expectedRevision:e.revision,stateJson:a,blockedSummary:i,updatedAt:s,endedAt:s});return Wr("reconcile-terminal",l),tn(e,l)}function nn(n){if(!n.sessionKey?.trim())return Jt;try{let e=vr()?.fromToolContext;if(typeof e!="function")return Jt;let t=e(n);return sd(t)?new Lr(t):Jt}catch(e){return Xt("resolve",e),Jt}}function pd(...n){let e;for(let t of n)t!=null&&(e=e==null?t:Math.max(e,t));return e}function Fr(n){if(n.actionablePlanDecisionVersion!=null)return n.actionablePlanDecisionVersion;let e=pd(n.approvalPromptRequiredVersion,n.approvalPromptVersion);return e??n.canonicalPlanPromptVersion??n.planDecisionVersion}function Br(n,e){return n.kind==="plan-approve"&&n.planDecisionVersion!=null&&e.approvalState==="approved"&&!e.pendingPlanApproval&&e.planDecisionVersion===n.planDecisionVersion+1}function xi(n,e){return n.worktreePath&&e&&!e.worktreePath?{...n,worktreePath:void 0,worktreeBranch:void 0,worktreeState:e.worktreeState,worktreeDisposition:e.worktreeDisposition,worktreeLifecycle:e.worktreeLifecycle,pendingWorktreeDecisionSince:e.pendingWorktreeDecisionSince,lastWorktreeReminderAt:e.lastWorktreeReminderAt,worktreeDecisionSnoozedUntil:e.worktreeDecisionSnoozedUntil,worktreeMerged:e.worktreeMerged,worktreeMergedAt:e.worktreeMergedAt,worktreeDismissedAt:e.worktreeDismissedAt,worktreeRemoteOutcome:e.worktreeRemoteOutcome}:n}function rn(n,e){let t=Fr(n);if(!n.pendingPlanApproval)return{permissionMode:e,approvalApplied:!1,patch:{}};let r={planApprovalContext:n.planApprovalContext,canonicalPlanPromptVersion:n.canonicalPlanPromptVersion,approvalPromptRequiredVersion:n.approvalPromptRequiredVersion,approvalPromptVersion:n.approvalPromptVersion,approvalPromptStatus:n.approvalPromptStatus,approvalPromptTransport:n.approvalPromptTransport,approvalPromptMessageKind:n.approvalPromptMessageKind,approvalPromptLastAttemptAt:n.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:n.approvalPromptDeliveredAt,approvalPromptFailedAt:n.approvalPromptFailedAt};return e==="bypassPermissions"&&n.actionablePlanDecisionVersion!=null&&n.actionablePlanDecisionVersion>0&&t===n.actionablePlanDecisionVersion&&n.approvalState!=="rejected"?{permissionMode:"bypassPermissions",approvalApplied:!0,decisionVersion:t,patch:{...r,pendingPlanApproval:!1,approvalState:"approved",approvalExecutionState:"approved_then_implemented",planModeApproved:!0,planDecisionVersion:t+1,actionablePlanDecisionVersion:void 0}}:{permissionMode:"plan",approvalApplied:!1,decisionVersion:t,patch:{...r,pendingPlanApproval:!0,approvalState:n.approvalState??"pending",planDecisionVersion:t??n.planDecisionVersion,actionablePlanDecisionVersion:n.actionablePlanDecisionVersion}}}function cd(n){return n instanceof Error?n.message:String(n)}function Ci(n,e){return n?("id"in n?n.id:n.sessionId)??e??"unknown-session":e??"unknown-session"}function md(n){return!n||typeof n!="object"?!1:typeof n.prompt=="string"}function fd(n){return!!n&&typeof n=="object"&&typeof n.formatLaunchResult=="function"}function gd(n){return!!n&&typeof n=="object"&&typeof n.checkRepoPolicyForLaunch=="function"&&typeof n.requestRepoPolicyForLaunch=="function"}function Mi(n){return{name:"agent_launch",description:"Launch a coding agent session in background to execute a development task. Sessions are multi-turn — they stay open for follow-up messages via agent_respond. Supports resuming previous sessions. Returns a session ID and name for tracking.",parameters:c.Object({prompt:c.String({description:"The task prompt to execute"}),name:c.Optional(c.String({description:"Short human-readable name for the session (kebab-case, e.g. 'fix-auth'). Auto-generated from prompt if omitted."})),workdir:c.Optional(c.String({description:"Working directory (defaults to cwd)"})),model:c.Optional(c.String({description:"Model name to use"})),system_prompt:c.Optional(c.String({description:"Additional system prompt"})),allowed_tools:c.Optional(c.Array(c.String(),{description:"List of allowed tools"})),resume_session_id:c.Optional(c.String({description:"Session reference to continue or fork from. Prefer the plugin session ID shown by agent_launch or agent_sessions; persisted backend conversation IDs also resolve when available."})),fork_session:c.Optional(c.Boolean({description:"When resuming, fork to a new session instead of continuing the existing one. Use with resume_session_id."})),force_new_session:c.Optional(c.Boolean({description:"Bypass resume-first protection and start a brand-new linked session even when a resumable or active linked session already exists."})),permission_mode:c.Optional(c.Union([c.Literal("default"),c.Literal("plan"),c.Literal("bypassPermissions")],{description:"Permission mode: 'default' (plugin-managed interactive execution), 'plan' (present the plan first and block implementation until approval), 'bypassPermissions' (fully autonomous execution). Defaults to plugin config ('plan' by default)."})),plan_approval:c.Optional(c.Union([c.Literal("ask"),c.Literal("delegate"),c.Literal("approve")],{description:"Plan approval policy for this session: 'ask' (send the full plan to the user with Approve/Revise/Reject buttons), 'delegate' (orchestrator must review the full plan, then either approve directly or escalate back to the user with the same buttons), 'approve' (auto-approve after verification). Overrides the plugin-level planApproval setting."})),harness:c.Optional(c.String({description:"Agent harness to use ('claude-code', 'codex', or experimental 'opencode'). Defaults to the plugin defaultHarness."})),worktree_strategy:c.Optional(c.Union([c.Literal("off"),c.Literal("manual"),c.Literal("ask"),c.Literal("delegate"),c.Literal("auto-merge"),c.Literal("auto-pr")],{description:"Worktree strategy: 'off' (no worktree), 'manual' (create worktree but no auto merge-back), 'ask' (prompt user with Merge/Open PR/Later/Discard buttons), 'delegate' (orchestrator decides), 'auto-merge' (merge automatically), 'auto-pr' (open/update a PR automatically). Defaults to the plugin config when unset."})),worktree_base_branch:c.Optional(c.String({description:"Base branch for worktree merge/PR operations (default: auto-detected or 'main')"})),worktree_pr_target_repo:c.Optional(c.String({description:"Target repository for cross-repo PRs (e.g. 'openai/codex' for fork-to-upstream workflow). If not set, auto-detected from 'upstream' remote or defaults to 'origin'."}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!md(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected at least { prompt }."}]};t.agentId&&`${t.agentId}${n.agentId}`;try{let r=Qt(t,n,S);if(r.kind!=="resolved")return{content:[{type:"text",text:r.text}]};let{workdir:o,harness:i,resolvedModel:s,permissionMode:a,planApproval:l,originChannel:d,originThreadId:u,originSessionKey:f,route:h,resumeSessionId:k,resolvedResumeId:g,clearedPersistedCodexResume:p,reasoningEffort:y,fastMode:w}=r,R=t.resume_session_id?S.resolve(t.resume_session_id)??S.getPersistedSession(t.resume_session_id):void 0,A=!t.fork_session&&R?ke(R):void 0;if(A?.kind==="direct")return{content:[{type:"text",text:`Session ${R.name} [${Ci(R,t.resume_session_id)}] is already running. Use agent_respond(session='${t.resume_session_id}', message='<next instruction>') instead of agent_launch(resume_session_id=...).`}]};if(A?.kind==="unavailable")return{content:[{type:"text",text:`Resume unavailable for session ${R.name} [${Ci(R,t.resume_session_id)}] (${A.reason}). Use agent_launch(prompt='<new task>') for a fresh session or set fork_session=true to fork from prior context.`}]};let I=R&&"resumedFromSessionName"in R?R.resumedFromSessionName:void 0,b=A?.kind==="resume"&&!t.fork_session?I??R?.name:void 0,m=b&&!t.name?b:t.name,P=t.worktree_strategy??_.defaultWorktreeStrategy??"off",T=t.fork_session?void 0:A?.kind==="resume"||A?.kind==="relaunch"?A.stableSessionId:void 0,L=A?.kind==="resume"&&!t.fork_session&&R?rn(R,a):{permissionMode:a,approvalApplied:!1,patch:{}};if(P!=="off"&&gd(S)&&S.checkRepoPolicyForLaunch(o,t.worktree_strategy).ok===!1)return{content:[{type:"text",text:S.requestRepoPolicyForLaunch({route:h,prompt:t.prompt,workdir:o,name:m,model:s,reasoningEffort:y,fastMode:w,systemPrompt:t.system_prompt,allowedTools:t.allowed_tools,resumeSessionId:A?.kind==="resume"?A.resumeSessionId:k,resumedFromSessionName:b,resumeWorktreeFrom:T??t.resume_session_id??g,sessionIdOverride:T,clearedPersistedCodexResume:p,forkSession:k?t.fork_session:!1,forceNewSession:t.force_new_session,permissionMode:a,planApproval:l,harness:i,worktreeStrategy:t.worktree_strategy,worktreeBaseBranch:t.worktree_base_branch,worktreePrTargetRepo:t.worktree_pr_target_repo,originAgentId:n.agentId||void 0})}]};let U=S.spawn({prompt:t.prompt,sessionIdOverride:T,name:m,workdir:o,model:s,reasoningEffort:y,fastMode:w,systemPrompt:t.system_prompt,allowedTools:t.allowed_tools,resumeSessionId:A?.kind==="resume"?A.resumeSessionId:k,resumedFromSessionName:b,resumeWorktreeFrom:T??t.resume_session_id??g,forkSession:k?t.fork_session:!1,multiTurn:!0,permissionMode:L.permissionMode,planApproval:l,codexApprovalPolicy:i==="codex"?"never":void 0,...L.patch,originChannel:d,originThreadId:u,originAgentId:n.agentId||void 0,originSessionKey:f,route:h,harness:i,taskLifecycle:nn(n),worktreeStrategy:t.worktree_strategy,worktreeBaseBranch:t.worktree_base_branch,worktreePrTargetRepo:t.worktree_pr_target_repo});return{content:[{type:"text",text:fd(S)?S.formatLaunchResult({prompt:t.prompt,workdir:o,harness:i,permissionMode:L.permissionMode,planApproval:l,forceNewSession:t.force_new_session,resumeSessionId:t.resume_session_id,resumeSessionName:b,forkSession:t.fork_session,clearedPersistedCodexResume:p},U):Gt({prompt:t.prompt,workdir:o,harness:i,permissionMode:L.permissionMode,planApproval:l,resumeSessionId:t.resume_session_id,resumeSessionName:b,forkSession:t.fork_session,forceNewSession:t.force_new_session,clearedPersistedCodexResume:p},{id:U.id,name:U.name,model:U.model,reasoningEffort:U.reasoningEffort??pe(i),fastMode:U.fastMode??w,worktreeStrategy:U.worktreeStrategy??t.worktree_strategy??_.defaultWorktreeStrategy??"off",repoIntegrationPolicy:U.repoIntegrationPolicy,repoProvider:U.repoProvider,worktreePath:U.worktreePath,originalWorkdir:U.originalWorkdir})}]}}catch(r){let o=cd(r),i=o.includes("Max sessions")?"":`
20
+ `)}var ed="openclaw-code-agent",td=160,Xt={create(){},progress(){},finalize(){}};function Zt(n,e){let t=e instanceof Error?e.message:String(e);`${n}${t}`}function Wr(n,e){if(e.applied===!1){let t=e.code?` (${e.code})`:"";`${n}${t}`}}function nd(n){let e=n.prompt.trim().replace(/\s+/g," ");return q(e||n.name,td)}function Ai(n){if(n.status==="starting"||n.lifecycle==="starting")return"Starting";if(n.lifecycle==="active")return"Running";if(n.lifecycle==="awaiting_plan_decision")return"Waiting for plan approval";if(n.lifecycle==="awaiting_user_input")return"Waiting for input";if(n.lifecycle==="awaiting_worktree_decision")return"Waiting for worktree decision";if(n.lifecycle==="suspended")return"Suspended after idle timeout"}function Ii(n){if(n.status==="completed")return"succeeded";if(n.status==="failed")return"failed";if(n.status==="killed")return n.killReason==="idle-timeout"||n.killReason==="startup-timeout"?"timed_out":"cancelled"}function en(n,e){return n==="completed"?"Completed":n==="failed"?"Failed":e==="idle-timeout"?"Timed out after idle timeout":e==="startup-timeout"?"Timed out during startup":e==="shutdown"?"Cancelled during shutdown":e==="user"?"Cancelled by user":"Cancelled"}function rd(n){return tn(n.lifecycle)}function tn(n){return n==="awaiting_plan_decision"||n==="awaiting_user_input"||n==="awaiting_worktree_decision"||n==="suspended"}function od(n){if(n.pendingPlanApproval||n.pendingWorktreeDecisionSince)return!0;if(n.runtimeRecovery?.reason==="persisted-running-without-runtime"){let e=n.runtimeRecovery.rawLifecycle;return e==="suspended"?n.runtimeRecovery.rawResumable===!0||n.resumable===!0:tn(e)}return n.lifecycle==="suspended"?n.resumable===!0:tn(n.lifecycle)}function id(n){if(n.runtimeRecovery?.reason==="persisted-running-without-runtime"){let e=n.runtimeRecovery.rawLifecycle;if(tn(e))return e}return n.lifecycle}function Or(n,e,t){return{phase:e,integration:"phase-1-managed-task-flow",sessionId:n.id,sessionName:n.name,sessionStatus:n.status,sessionLifecycle:n.lifecycle,summary:t}}function sd(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.createManaged=="function"&&typeof e.resume=="function"&&typeof e.setWaiting=="function"&&typeof e.finish=="function"&&typeof e.fail=="function"}function nn(n,e){if(e.applied)return e.flow;let t=e.current;return t?.flowId&&typeof t.revision=="number"?t:n}var Fr=class{constructor(e){this.taskFlow=e}taskFlow;flow;finalized=!1;lastProgressKey;create(e){if(this.flow||this.finalized)return;let t="Starting",r=Date.now();try{this.flow=this.taskFlow.createManaged({controllerId:ed,goal:nd(e),status:"running",notifyPolicy:"silent",currentStep:t,stateJson:Or(e,"created",t),createdAt:e.startedAt,updatedAt:r}),e.taskFlowMirror=this.flow,this.lastProgressKey=this.progressKey(e,t)}catch(o){Zt("create",o)}}progress(e){if(!this.flow||this.finalized)return;let t=Ai(e);if(!t)return;let r=this.progressKey(e,t);if(r!==this.lastProgressKey)try{let o=Or(e,"progress",t),i=Date.now(),s=rd(e)?this.taskFlow.setWaiting({flowId:this.flow.flowId,expectedRevision:this.flow.revision,currentStep:t,stateJson:o,waitJson:{reason:t,sessionId:e.id},blockedSummary:t,updatedAt:i}):this.taskFlow.resume({flowId:this.flow.flowId,expectedRevision:this.flow.revision,status:"running",currentStep:t,stateJson:o,updatedAt:i});this.flow=nn(this.flow,s),this.flow&&(e.taskFlowMirror=this.flow),this.lastProgressKey=r}catch(o){Zt("progress",o)}}finalize(e){if(!this.flow||this.finalized)return;let t=Ii(e);if(!t)return;let r=t==="succeeded"?"Completed":t==="failed"?"Failed":en(e.status,e.killReason);try{let o=e.completedAt??Date.now(),i={...Or(e,"terminal",r),terminalStatus:t,terminalSummary:en(e.status,e.killReason),...e.status==="failed"&&e.error?{error:e.error}:{}},s=t==="succeeded"?this.taskFlow.finish({flowId:this.flow.flowId,expectedRevision:this.flow.revision,stateJson:i,updatedAt:o,endedAt:o}):this.taskFlow.fail({flowId:this.flow.flowId,expectedRevision:this.flow.revision,stateJson:i,blockedSummary:en(e.status,e.killReason),updatedAt:o,endedAt:o});Wr("finalize",s),this.flow=nn(this.flow,s),this.flow&&(e.taskFlowMirror=this.flow),this.finalized=!0}catch(o){Zt("finalize",o)}}progressKey(e,t){return`${e.status}:${e.lifecycle}:${t}`}};function ad(n){return n==="succeeded"||n==="failed"||n==="cancelled"||n==="lost"}function ld(n){if(!n?.trim())return;let e=vr()?.fromToolContext;if(typeof e!="function")return;let t=e({sessionKey:n});if(!t||typeof t!="object")return;let r=t;if(!(typeof r.setWaiting!="function"||typeof r.finish!="function"||typeof r.fail!="function"))return{setWaiting:r.setWaiting,finish:r.finish,fail:r.fail}}function dd(n){return n.originSessionKey??n.route?.sessionKey}function ud(n){return n.runtimeRecovery?.reason==="persisted-running-without-runtime"?"Lost after OpenClaw Code Agent restart without live process":en(n.status,n.killReason??"unknown")}function Ti(n){let e=n.taskFlowMirror?{...n.taskFlowMirror}:void 0;if(!e||ad(e.status))return;let t=ld(dd(n));if(!t)return;let r=Date.now();if(od(n)){let d=Ai({status:n.status,lifecycle:id(n)??"suspended"})??"Waiting",u=t.setWaiting({flowId:e.flowId,expectedRevision:e.revision,currentStep:d,stateJson:{phase:"progress",integration:"phase-1-managed-task-flow",sessionId:n.sessionId,sessionName:n.name,sessionStatus:n.status,sessionLifecycle:n.lifecycle,summary:d,reconciled:!0},waitJson:{reason:d,sessionId:n.sessionId},blockedSummary:d,updatedAt:r});return Wr("reconcile-waiting",u),nn(e,u)}let o=Ii({status:n.status,killReason:n.killReason??"unknown"})??"failed",i=ud(n),s=n.completedAt??r,a={phase:"terminal",integration:"phase-1-managed-task-flow",sessionId:n.sessionId,sessionName:n.name,sessionStatus:n.status,sessionLifecycle:n.lifecycle,summary:i,terminalStatus:n.runtimeRecovery?.reason==="persisted-running-without-runtime"?"lost":o,terminalSummary:i,reconciled:!0,runtimeRecovery:n.runtimeRecovery},l=o==="succeeded"?t.finish({flowId:e.flowId,expectedRevision:e.revision,stateJson:a,updatedAt:s,endedAt:s}):t.fail({flowId:e.flowId,expectedRevision:e.revision,stateJson:a,blockedSummary:i,updatedAt:s,endedAt:s});return Wr("reconcile-terminal",l),nn(e,l)}function rn(n){if(!n.sessionKey?.trim())return Xt;try{let e=vr()?.fromToolContext;if(typeof e!="function")return Xt;let t=e(n);return sd(t)?new Fr(t):Xt}catch(e){return Zt("resolve",e),Xt}}function pd(...n){let e;for(let t of n)t!=null&&(e=e==null?t:Math.max(e,t));return e}function Lr(n){if(n.actionablePlanDecisionVersion!=null)return n.actionablePlanDecisionVersion;let e=pd(n.approvalPromptRequiredVersion,n.approvalPromptVersion);return e??n.canonicalPlanPromptVersion??n.planDecisionVersion}function Br(n,e){return n.kind==="plan-approve"&&n.planDecisionVersion!=null&&e.approvalState==="approved"&&!e.pendingPlanApproval&&e.planDecisionVersion===n.planDecisionVersion+1}function xi(n,e){return n.worktreePath&&e&&!e.worktreePath?{...n,worktreePath:void 0,worktreeBranch:void 0,worktreeState:e.worktreeState,worktreeDisposition:e.worktreeDisposition,worktreeLifecycle:e.worktreeLifecycle,pendingWorktreeDecisionSince:e.pendingWorktreeDecisionSince,lastWorktreeReminderAt:e.lastWorktreeReminderAt,worktreeDecisionSnoozedUntil:e.worktreeDecisionSnoozedUntil,worktreeMerged:e.worktreeMerged,worktreeMergedAt:e.worktreeMergedAt,worktreeDismissedAt:e.worktreeDismissedAt,worktreeRemoteOutcome:e.worktreeRemoteOutcome}:n}function on(n,e){let t=Lr(n);if(!n.pendingPlanApproval)return{permissionMode:e,approvalApplied:!1,patch:{}};let r={planApprovalContext:n.planApprovalContext,canonicalPlanPromptVersion:n.canonicalPlanPromptVersion,approvalPromptRequiredVersion:n.approvalPromptRequiredVersion,approvalPromptVersion:n.approvalPromptVersion,approvalPromptStatus:n.approvalPromptStatus,approvalPromptTransport:n.approvalPromptTransport,approvalPromptMessageKind:n.approvalPromptMessageKind,approvalPromptLastAttemptAt:n.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:n.approvalPromptDeliveredAt,approvalPromptFailedAt:n.approvalPromptFailedAt};return e==="bypassPermissions"&&n.actionablePlanDecisionVersion!=null&&n.actionablePlanDecisionVersion>0&&t===n.actionablePlanDecisionVersion&&n.approvalState!=="rejected"?{permissionMode:"bypassPermissions",approvalApplied:!0,decisionVersion:t,patch:{...r,pendingPlanApproval:!1,approvalState:"approved",approvalExecutionState:"awaiting_plan_output",planModeApproved:!0,planDecisionVersion:t+1,actionablePlanDecisionVersion:void 0}}:{permissionMode:"plan",approvalApplied:!1,decisionVersion:t,patch:{...r,pendingPlanApproval:!0,approvalState:n.approvalState??"pending",planDecisionVersion:t??n.planDecisionVersion,actionablePlanDecisionVersion:n.actionablePlanDecisionVersion}}}function cd(n){return n instanceof Error?n.message:String(n)}function Ci(n,e){return n?("id"in n?n.id:n.sessionId)??e??"unknown-session":e??"unknown-session"}function md(n){return!n||typeof n!="object"?!1:typeof n.prompt=="string"}function fd(n){return!!n&&typeof n=="object"&&typeof n.formatLaunchResult=="function"}function gd(n){return!!n&&typeof n=="object"&&typeof n.checkRepoPolicyForLaunch=="function"&&typeof n.requestRepoPolicyForLaunch=="function"}function Mi(n){return{name:"agent_launch",description:"Launch a coding agent session in background to execute a development task. Sessions are multi-turn — they stay open for follow-up messages via agent_respond. Supports resuming previous sessions. Returns a session ID and name for tracking.",parameters:c.Object({prompt:c.String({description:"The task prompt to execute"}),name:c.Optional(c.String({description:"Short human-readable name for the session (kebab-case, e.g. 'fix-auth'). Auto-generated from prompt if omitted."})),workdir:c.Optional(c.String({description:"Working directory (defaults to cwd)"})),model:c.Optional(c.String({description:"Model name to use"})),system_prompt:c.Optional(c.String({description:"Additional system prompt"})),allowed_tools:c.Optional(c.Array(c.String(),{description:"List of allowed tools"})),resume_session_id:c.Optional(c.String({description:"Session reference to continue or fork from. Prefer the plugin session ID shown by agent_launch or agent_sessions; persisted backend conversation IDs also resolve when available."})),fork_session:c.Optional(c.Boolean({description:"When resuming, fork to a new session instead of continuing the existing one. Use with resume_session_id."})),force_new_session:c.Optional(c.Boolean({description:"Bypass resume-first protection and start a brand-new linked session even when a resumable or active linked session already exists."})),permission_mode:c.Optional(c.Union([c.Literal("default"),c.Literal("plan"),c.Literal("bypassPermissions")],{description:"Permission mode: 'default' (plugin-managed interactive execution), 'plan' (present the plan first and block implementation until approval), 'bypassPermissions' (fully autonomous execution). Defaults to plugin config ('plan' by default)."})),plan_approval:c.Optional(c.Union([c.Literal("ask"),c.Literal("delegate"),c.Literal("approve")],{description:"Plan approval policy for this session: 'ask' (send the full plan to the user with Approve/Revise/Reject buttons), 'delegate' (orchestrator must review the full plan, then either approve directly or escalate back to the user with the same buttons), 'approve' (auto-approve after verification). Overrides the plugin-level planApproval setting."})),harness:c.Optional(c.String({description:"Agent harness to use ('claude-code', 'codex', or experimental 'opencode'). Defaults to the plugin defaultHarness."})),worktree_strategy:c.Optional(c.Union([c.Literal("off"),c.Literal("manual"),c.Literal("ask"),c.Literal("delegate"),c.Literal("auto-merge"),c.Literal("auto-pr")],{description:"Worktree strategy: 'off' (no worktree), 'manual' (create worktree but no auto merge-back), 'ask' (prompt user with Merge/Open PR/Later/Discard buttons), 'delegate' (orchestrator decides), 'auto-merge' (merge automatically), 'auto-pr' (open/update a PR automatically). Defaults to the plugin config when unset."})),worktree_base_branch:c.Optional(c.String({description:"Base branch for worktree merge/PR operations (default: auto-detected or 'main')"})),worktree_pr_target_repo:c.Optional(c.String({description:"Target repository for cross-repo PRs (e.g. 'openai/codex' for fork-to-upstream workflow). If not set, auto-detected from 'upstream' remote or defaults to 'origin'."}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!md(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected at least { prompt }."}]};t.agentId&&`${t.agentId}${n.agentId}`;try{let r=Yt(t,n,S);if(r.kind!=="resolved")return{content:[{type:"text",text:r.text}]};let{workdir:o,harness:i,resolvedModel:s,permissionMode:a,planApproval:l,originChannel:d,originThreadId:u,originSessionKey:f,route:g,resumeSessionId:k,resolvedResumeId:h,clearedPersistedCodexResume:p,reasoningEffort:y,fastMode:P}=r,b=t.resume_session_id?S.resolve(t.resume_session_id)??S.getPersistedSession(t.resume_session_id):void 0,A=!t.fork_session&&b?ke(b):void 0;if(A?.kind==="direct")return{content:[{type:"text",text:`Session ${b.name} [${Ci(b,t.resume_session_id)}] is already running. Use agent_respond(session='${t.resume_session_id}', message='<next instruction>') instead of agent_launch(resume_session_id=...).`}]};if(A?.kind==="unavailable")return{content:[{type:"text",text:`Resume unavailable for session ${b.name} [${Ci(b,t.resume_session_id)}] (${A.reason}). Use agent_launch(prompt='<new task>') for a fresh session or set fork_session=true to fork from prior context.`}]};let I=b&&"resumedFromSessionName"in b?b.resumedFromSessionName:void 0,R=A?.kind==="resume"&&!t.fork_session?I??b?.name:void 0,m=R&&!t.name?R:t.name,w=t.worktree_strategy??_.defaultWorktreeStrategy??"off",T=t.fork_session?void 0:A?.kind==="resume"||A?.kind==="relaunch"?A.stableSessionId:void 0,F=A?.kind==="resume"&&!t.fork_session&&b?on(b,a):{permissionMode:a,approvalApplied:!1,patch:{}};if(w!=="off"&&gd(S)&&S.checkRepoPolicyForLaunch(o,t.worktree_strategy).ok===!1)return{content:[{type:"text",text:S.requestRepoPolicyForLaunch({route:g,prompt:t.prompt,workdir:o,name:m,model:s,reasoningEffort:y,fastMode:P,systemPrompt:t.system_prompt,allowedTools:t.allowed_tools,resumeSessionId:A?.kind==="resume"?A.resumeSessionId:k,resumedFromSessionName:R,resumeWorktreeFrom:T??t.resume_session_id??h,sessionIdOverride:T,clearedPersistedCodexResume:p,forkSession:k?t.fork_session:!1,forceNewSession:t.force_new_session,permissionMode:a,planApproval:l,harness:i,worktreeStrategy:t.worktree_strategy,worktreeBaseBranch:t.worktree_base_branch,worktreePrTargetRepo:t.worktree_pr_target_repo,originAgentId:n.agentId||void 0})}]};let U=S.spawn({prompt:t.prompt,sessionIdOverride:T,name:m,workdir:o,model:s,reasoningEffort:y,fastMode:P,systemPrompt:t.system_prompt,allowedTools:t.allowed_tools,resumeSessionId:A?.kind==="resume"?A.resumeSessionId:k,resumedFromSessionName:R,resumeWorktreeFrom:T??t.resume_session_id??h,forkSession:k?t.fork_session:!1,multiTurn:!0,permissionMode:F.permissionMode,planApproval:l,codexApprovalPolicy:i==="codex"?"never":void 0,...F.patch,originChannel:d,originThreadId:u,originAgentId:n.agentId||void 0,originSessionKey:f,route:g,harness:i,taskLifecycle:rn(n),worktreeStrategy:t.worktree_strategy,worktreeBaseBranch:t.worktree_base_branch,worktreePrTargetRepo:t.worktree_pr_target_repo});return{content:[{type:"text",text:fd(S)?S.formatLaunchResult({prompt:t.prompt,workdir:o,harness:i,permissionMode:F.permissionMode,planApproval:l,forceNewSession:t.force_new_session,resumeSessionId:t.resume_session_id,resumeSessionName:R,forkSession:t.fork_session,clearedPersistedCodexResume:p},U):jt({prompt:t.prompt,workdir:o,harness:i,permissionMode:F.permissionMode,planApproval:l,resumeSessionId:t.resume_session_id,resumeSessionName:R,forkSession:t.fork_session,forceNewSession:t.force_new_session,clearedPersistedCodexResume:p},{id:U.id,name:U.name,model:U.model,reasoningEffort:U.reasoningEffort??pe(i),fastMode:U.fastMode??P,worktreeStrategy:U.worktreeStrategy??t.worktree_strategy??_.defaultWorktreeStrategy??"off",repoIntegrationPolicy:U.repoIntegrationPolicy,repoProvider:U.repoProvider,worktreePath:U.worktreePath,originalWorkdir:U.originalWorkdir})}]}}catch(r){let o=cd(r),i=o.includes("Max sessions")?"":`
21
21
 
22
- Use agent_sessions to see active sessions and their status.`;return{content:[{type:"text",text:`Error launching session: ${o}${i}`}]}}}}}import{existsSync as Ur,readFileSync as qi}from"fs";import{EventEmitter as Td}from"events";var _i="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var Ei=65536;function Kr(n){let e=0;for(;e<n.length;){let t=Math.min(e+Ei,n.length);crypto.getRandomValues(n.subarray(e,t)),e=t}}function Di(n){if(n|=0,n<0)throw new RangeError("Wrong ID size");let e=Buffer.allocUnsafe(n);return Kr(e),e}function $i(n,e,t){let r=256-256%n.length;if(r===256){let i=n.length-1;return(s=e)=>{if(!s)return"";let a="";for(;;){let l=t(s),d=s;for(;d--;)if(a+=n[l[d]&i],a.length>=s)return a}}}let o=Math.ceil(1.6*256*e/r);return(i=e)=>{if(!i)return"";let s="";for(;;){let a=t(o),l=o;for(;l--;)if(a[l]<r&&(s+=n[a[l]%n.length],s.length>=i))return s}}}var hd=Ei/2;function yd(n,e=21){if(typeof n!="string"||!n.length||n.length>256)return $i(n,e,Di);for(let l=0;l<n.length;l++)if(n.charCodeAt(l)>255)return $i(n,e,Di);let t=Uint8Array.from(n,l=>l.charCodeAt(0)),r=n.length,o=(2<<31-Math.clz32(r-1|1))-1,i="",s=0,a=0;return(l=e)=>{if(l|=0,l<0)throw new RangeError("Wrong ID size");if(l===0)return"";if(s+l>i.length){let d=Math.max(a,l);a=Math.min(d*16,hd);let u=Buffer.allocUnsafe(d);if(o===r-1){Kr(u);for(let f=0;f<d;f++)u[f]=t[u[f]&o]}else{let f=Buffer.allocUnsafe(Math.ceil(1.6*(o+1)*d/r)),h=0;for(;h<d;){Kr(f);for(let k=0;k<f.length;k++){let g=f[k]&o;if(g<r&&(u[h++]=t[g],h===d))break}}}i=u.toString("latin1"),s=0}return s+=l,i.substring(s-l,s)}}var on=yd(_i);var Ni={starting:["running","failed","killed"],running:["completed","failed","killed"],completed:[],failed:[],killed:[]};function O(n,e){return Object.hasOwn(n,e)}var Oi=new Set(["merged","released","pr_open","dismissed","cleanup_failed"]);function Sd(n){return n.requestedPermissionMode!=="plan"?"not_plan_gated":n.pendingPlanApproval?"awaiting_approval":n.planModeApproved?"approved_then_implemented":n.currentPermissionMode!=="plan"?"implemented_without_required_approval":"awaiting_plan_output"}function G(n){return{...n,approvalExecutionState:Sd(n)}}function qr(n,e){switch(e.type){case"initialize":return G({...n,worktreeState:e.hasWorktree&&n.worktreeState==="none"?"provisioned":n.worktreeState,lifecycle:n.status==="starting"?"starting":n.lifecycle,runtimeState:n.status==="starting"?"live":n.runtimeState});case"status.transition":return e.status==="starting"?G({...n,status:e.status,lifecycle:"starting",runtimeState:"live"}):e.status==="running"?G({...n,status:e.status,lifecycle:n.lifecycle==="starting"||n.lifecycle==="suspended"?"active":n.lifecycle,runtimeState:"live"}):G({...n,status:e.status,runtimeState:"stopped",lifecycle:n.lifecycle==="suspended"?"suspended":"terminal"});case"permission.mode_changed":return G({...n,currentPermissionMode:e.currentPermissionMode});case"turn.started":return G({...n,lifecycle:"active",runtimeState:"live"});case"input.requested":return G({...n,lifecycle:n.pendingPlanApproval?"awaiting_plan_decision":"awaiting_user_input"});case"plan.requested":if(n.planModeApproved)return n;{let t=n.pendingPlanApproval&&n.approvalState==="pending"&&n.planApprovalContext===e.context,r=n.pendingPlanApproval&&n.approvalState==="changes_requested"&&n.planApprovalContext===e.context&&n.planDecisionVersion>0,o=!n.pendingPlanApproval&&n.approvalState==="changes_requested"&&n.planApprovalContext===e.context&&n.planDecisionVersion>0,i=t||r||o?n.planDecisionVersion:n.planDecisionVersion+1;return G({...n,pendingPlanApproval:!0,planApprovalContext:e.context,approvalState:"pending",planDecisionVersion:i,actionablePlanDecisionVersion:i,canonicalPlanPromptVersion:t?n.canonicalPlanPromptVersion:void 0,approvalPromptRequiredVersion:t?n.approvalPromptRequiredVersion:void 0,approvalPromptVersion:t?n.approvalPromptVersion:void 0,approvalPromptStatus:t?n.approvalPromptStatus:"not_sent",approvalPromptTransport:t?n.approvalPromptTransport:"none",approvalPromptMessageKind:t?n.approvalPromptMessageKind:"none",approvalPromptLastAttemptAt:t?n.approvalPromptLastAttemptAt:void 0,approvalPromptDeliveredAt:t?n.approvalPromptDeliveredAt:void 0,approvalPromptFailedAt:t?n.approvalPromptFailedAt:void 0,lifecycle:"awaiting_plan_decision"})}case"plan.cleared":return G({...n,pendingPlanApproval:!1,planApprovalContext:void 0,actionablePlanDecisionVersion:void 0,approvalState:n.approvalState==="pending"?"not_required":n.approvalState});case"plan.approved":return G({...n,pendingPlanApproval:!1,planApprovalContext:void 0,actionablePlanDecisionVersion:void 0,planModeApproved:!0,approvalState:"approved",planDecisionVersion:n.planDecisionVersion+1,approvalPromptVersion:void 0,approvalPromptStatus:"not_sent",lifecycle:n.status==="running"?"active":n.lifecycle});case"plan.changes_requested":return G({...n,pendingPlanApproval:!0,approvalState:"changes_requested",planDecisionVersion:n.planDecisionVersion+1,actionablePlanDecisionVersion:void 0,canonicalPlanPromptVersion:void 0,approvalPromptRequiredVersion:void 0,approvalPromptVersion:void 0,approvalPromptStatus:"not_sent",approvalPromptTransport:"none",approvalPromptMessageKind:"none",approvalPromptLastAttemptAt:void 0,approvalPromptDeliveredAt:void 0,approvalPromptFailedAt:void 0,lifecycle:"awaiting_plan_decision"});case"terminal.entered":return G({...n,lifecycle:e.suspended?"suspended":"terminal",runtimeState:"stopped"});case"worktree.decision_requested":return G({...n,lifecycle:"awaiting_worktree_decision",worktreeState:"pending_decision"});case"worktree.state_set":return G({...n,worktreeState:e.worktreeState,lifecycle:e.worktreeState==="pending_decision"?"awaiting_worktree_decision":Oi.has(e.worktreeState)?"terminal":n.lifecycle});case"delivery.state_set":return G({...n,deliveryState:e.deliveryState})}}function Wi(n,e){let t={...n,...O(e,"lifecycle")?{lifecycle:e.lifecycle}:{},...O(e,"approvalState")?{approvalState:e.approvalState}:{},...O(e,"approvalExecutionState")?{approvalExecutionState:e.approvalExecutionState}:{},...O(e,"worktreeState")?{worktreeState:e.worktreeState}:{},...O(e,"runtimeState")?{runtimeState:e.runtimeState}:{},...O(e,"deliveryState")?{deliveryState:e.deliveryState}:{},...O(e,"requestedPermissionMode")?{requestedPermissionMode:e.requestedPermissionMode}:{},...O(e,"currentPermissionMode")?{currentPermissionMode:e.currentPermissionMode}:{},...O(e,"pendingPlanApproval")?{pendingPlanApproval:e.pendingPlanApproval}:{},...O(e,"planApprovalContext")?{planApprovalContext:e.planApprovalContext}:{},...O(e,"planDecisionVersion")?{planDecisionVersion:e.planDecisionVersion}:{},...O(e,"actionablePlanDecisionVersion")?{actionablePlanDecisionVersion:e.actionablePlanDecisionVersion}:{},...O(e,"canonicalPlanPromptVersion")?{canonicalPlanPromptVersion:e.canonicalPlanPromptVersion}:{},...O(e,"approvalPromptRequiredVersion")?{approvalPromptRequiredVersion:e.approvalPromptRequiredVersion}:{},...O(e,"approvalPromptVersion")?{approvalPromptVersion:e.approvalPromptVersion}:{},...O(e,"approvalPromptStatus")?{approvalPromptStatus:e.approvalPromptStatus}:{},...O(e,"approvalPromptTransport")?{approvalPromptTransport:e.approvalPromptTransport}:{},...O(e,"approvalPromptMessageKind")?{approvalPromptMessageKind:e.approvalPromptMessageKind}:{},...O(e,"approvalPromptLastAttemptAt")?{approvalPromptLastAttemptAt:e.approvalPromptLastAttemptAt}:{},...O(e,"approvalPromptDeliveredAt")?{approvalPromptDeliveredAt:e.approvalPromptDeliveredAt}:{},...O(e,"approvalPromptFailedAt")?{approvalPromptFailedAt:e.approvalPromptFailedAt}:{},...O(e,"planModeApproved")?{planModeApproved:e.planModeApproved}:{}};return e.approvalState==="changes_requested"&&e.pendingPlanApproval===void 0&&(t={...t,pendingPlanApproval:!1}),t.pendingPlanApproval?t={...t,approvalState:"pending",actionablePlanDecisionVersion:t.actionablePlanDecisionVersion??t.planDecisionVersion,lifecycle:"awaiting_plan_decision"}:t.approvalState==="changes_requested"&&(t={...t,actionablePlanDecisionVersion:void 0,lifecycle:"awaiting_user_input"}),O(e,"pendingWorktreeDecisionSince")&&e.pendingWorktreeDecisionSince!==void 0||t.worktreeState==="pending_decision"?t=qr(t,{type:"worktree.decision_requested"}):Oi.has(t.worktreeState)&&(t={...t,lifecycle:"terminal"}),G(t)}var sn=class{queue=[];resolve=null;done=!1;hasPending(){return this.queue.length>0}push(e){this.queue.push(e),this.resolve&&(this.resolve(),this.resolve=null)}end(){this.done=!0,this.resolve&&(this.resolve(),this.resolve=null)}async*[Symbol.asyncIterator](){for(;;){for(;this.queue.length>0;)yield this.queue.shift();if(this.done)return;await new Promise(e=>{this.resolve=e})}}};import{createHash as kd}from"crypto";import{appendFileSync as vd}from"fs";import{tmpdir as Pd}from"os";import{join as wd}from"path";var Li=2e3,bd=/^[A-Za-z0-9_.-]+$/;function Rd(n){return bd.test(n)?n:`hashed+${kd("sha256").update(n,"utf8").digest("hex")}`}function ve(n){return wd(Pd(),`openclaw-agent-${Rd(n)}.txt`)}function Ad(n,e){if(!e)return;let t=e.split(`
23
- `),[r="",...o]=t;n.length===0?n.push(r):n[n.length-1]+=r;for(let i of o)n.push(i)}function Fi(n,e,t){Ad(n,t),n.length>Li&&n.splice(0,n.length-Li);try{vd(ve(e),t,"utf-8")}catch{}return n}var an=class{timers=new Map;get size(){return this.timers.size}set(e,t,r){this.clear(e);let o=setTimeout(()=>{this.timers.get(e)===o&&this.timers.delete(e),r()},t);o.unref?.(),this.timers.set(e,o)}clear(e){let t=this.timers.get(e);t&&(clearTimeout(t),this.timers.delete(e))}clearAll(){for(let e of this.timers.values())clearTimeout(e);this.timers.clear()}};var ln=class{constructor(e){this.deps=e}deps;waitingForInputFired=!1;lastTurnHadQuestion=!1;turnInProgress=!0;currentTurnText="";currentTurnPlanArtifact;pendingInputNotificationIdentity;beginUserTurn(){this.waitingForInputFired=!1,this.turnInProgress=!0,this.currentTurnText="",this.currentTurnPlanArtifact=void 0,this.lastTurnHadQuestion=!1}noteTextDelta(e,t){this.waitingForInputFired=!1,t||(this.lastTurnHadQuestion=!1),this.deps.appendOutput(e),this.currentTurnText+=this.currentTurnText?`
24
- ${e}`:e,this.deps.emitOutput(e)}noteToolCall(e){let{name:t,input:r,currentPermissionMode:o,permissionMode:i,planModeApproved:s}=e;if(t==="Write"){let a=r;typeof a?.file_path=="string"&&a.file_path.includes("/.claude/plans/")&&this.deps.setPlanFilePath(a.file_path)}t==="AskUserQuestion"?(this.lastTurnHadQuestion=!0,this.deps.applyInputRequested(),(o==="plan"||i==="plan")&&!s&&this.deps.markPendingPlanApproval("plan-mode")):(t==="ExitPlanMode"||t==="set_permission_mode")&&!s&&(this.lastTurnHadQuestion=!0,this.deps.markPendingPlanApproval("plan-mode")),this.deps.emitToolUse(t,r)}notePendingInput(e){this.lastTurnHadQuestion=!0,this.deps.applyInputRequested();let t=e?.activeQuestionIndex??0,r=e?.questions?.[t],o=e?.requestId?`${e.requestId}:${r?.id??(e.activeQuestionIndex!=null?`q${e.activeQuestionIndex}`:"request")}`:void 0;(!this.waitingForInputFired||o&&o!==this.pendingInputNotificationIdentity)&&(this.waitingForInputFired=!0,this.pendingInputNotificationIdentity=o,this.deps.emitTurnEnd(!0))}clearResolvedPendingInput(e,t){if(!e||t?.requestId===e){this.pendingInputNotificationIdentity=void 0;return}return t}notePlanArtifact(e,t){if(this.currentTurnPlanArtifact=e,this.deps.setLatestPlanArtifact(e),!t)return;let r=e.markdown.trim();!r||this.currentTurnText.trim()===r||(this.deps.appendOutput(r),this.currentTurnText=r,this.deps.emitOutput(r))}noteSettingsChanged(e){let{oldMode:t,permissionMode:r,planModeApproved:o}=e;if(r)return r!=="plan"&&t==="plan"&&!o&&(this.deps.markPendingPlanApproval("plan-mode"),this.lastTurnHadQuestion=!0),r}finishSuccessfulTurn(e){let{currentPermissionMode:t,permissionMode:r,pendingPlanApproval:o,planModeApproved:i,pendingInputState:s,hasPendingMessages:a}=e,l=o;(t==="plan"||r==="plan")&&!l&&!i&&(this.deps.markPendingPlanApproval("plan-mode"),l=!0);let d=l||this.lastTurnHadQuestion||!!s;if(this.turnInProgress=a,d&&!this.waitingForInputFired)this.waitingForInputFired=!0,l||this.deps.markAwaitingUserInput(),this.deps.emitTurnEnd(!0);else if(!a&&!d){if(this.deps.queueWorktreeFinalizationPrompt?.()){this.turnInProgress=!0;return}this.deps.completeTurn(),this.deps.emitTurnEnd(!1)}}finishTerminalTurn(){this.turnInProgress=!1}finishInterruptedTurn(e){this.turnInProgress=e,this.waitingForInputFired=!1,this.lastTurnHadQuestion=!1,this.currentTurnText="",this.currentTurnPlanArtifact=void 0}resetAfterRun(){this.lastTurnHadQuestion=!1,this.currentTurnText="",this.currentTurnPlanArtifact=void 0}};var dn=class{constructor(e){this.deps=e}deps;applyMessage(e,t){if(e.type==="backend_ref"){this.deps.clearStartupTimer(),this.deps.assignBackendRef({...e.ref}),this.deps.transitionRunning();return}if(e.type==="run_started"){e.runId&&this.deps.noteRunStarted(e.runId);return}if(e.type==="text_delta"){this.deps.noteTextDelta(e.text,t.pendingPlanApproval);return}if(e.type==="tool_call"){this.deps.noteToolCall({name:e.name,input:e.input,currentPermissionMode:t.currentPermissionMode,permissionMode:t.permissionMode,planModeApproved:t.planModeApproved});return}if(e.type==="pending_input"){this.deps.setPendingInputState(e.state),this.deps.notePendingInput(e.state);return}if(e.type==="pending_input_resolved"){this.deps.setPendingInputState(this.deps.clearResolvedPendingInput(e.requestId,t.pendingInputState));return}if(e.type==="plan_artifact"){this.deps.notePlanArtifact(e);return}if(e.type==="settings_changed"){let r=this.deps.noteSettingsChanged({oldMode:t.currentPermissionMode,permissionMode:e.permissionMode,planModeApproved:t.planModeApproved});r&&this.deps.setCurrentPermissionMode(r);return}if(e.type==="run_completed"){this.deps.handleRunCompleted(e.data);return}e.type}};var Id=[/\bfailed to authenticate\b/i,/\binvalid bearer token\b/i,/\bapi error:\s*401\b/i,/\b401\s+unauthori[sz]ed\b/i,/\binvalid api key\b/i,/\binvalid authentication\b/i,/\bauthentication failed\b/i,/\bauth(?:orization)? error\b/i];function Vr(n){return n?.trim()?Id.some(e=>e.test(n)):!1}function Bi(n){if(!n?.trim())return;let e=n.split(/\r?\n/).map(t=>t.trim()).filter(Boolean);return e.find(t=>Vr(t))??e.at(-1)}var xd=120*1e3;function un(n){return n instanceof Error?n.message:String(n)}function Cd(n,e){JSON.stringify({component:"Session",event:n,at:new Date().toISOString(),...e})}function Md(n){return n?{backendRefKind:n.kind,hasBackendConversationId:!!n.conversationId,hasBackendRunId:!!n.runId,hasBackendWorktreeId:!!n.worktreeId,hasBackendWorktreePath:!!n.worktreePath}:{}}var pn=class extends Td{id;name;harnessSessionId;backendRef;harness;harnessHandle;prompt;workdir;model;reasoningEffort;fastMode;systemPrompt;allowedTools;permissionMode;requestedPermissionMode;planApproval;codexApprovalPolicy;currentPermissionMode;pendingModeSwitch;resumeSessionId;resumedFromSessionName;forkSession;worktreePath;originalWorkdir;worktreeBranch;worktreeParentBranch;worktreeStrategy;repoIntegrationPolicy;repoIntegrationPolicySource;repoProvider;worktreeBaseBranch;worktreePrTargetRepo;autoMergeParentSessionId;autoMergeConflictResolutionAttemptCount;autoMergeResolverSessionId;worktreePushRemote;worktreeDisposition;worktreePrUrl;worktreePrNumber;worktreeMerged;worktreeMergedAt;worktreeLifecycle;worktreeState="none";multiTurn;goalTaskId;messageStream;_status="starting";error;startedAt;completedAt;abortController;outputBuffer=[];result;costUsd=0;originChannel;originThreadId;originAgentId;originSessionKey;route;pendingInputState;lastPendingInputSubmissionRequiresMore=!1;pendingPlanApproval=!1;planApprovalContext;planDecisionVersion=0;actionablePlanDecisionVersion;canonicalPlanPromptVersion;approvalPromptRequiredVersion;approvalPromptVersion;approvalPromptStatus="not_sent";approvalPromptTransport="none";approvalPromptMessageKind="none";approvalPromptLastAttemptAt;approvalPromptDeliveredAt;approvalPromptFailedAt;planFilePath;killReason="unknown";planModeApproved=!1;turnRuntime;harnessEvents;worktreeFinalizationPromptIssued=!1;lifecycle="starting";approvalState="not_required";approvalExecutionState="not_plan_gated";approvalRationale;latestPlanArtifact;latestPlanArtifactVersion;runtimeState="live";taskFlowMirror;deliveryState="idle";canUseTool;autoRespondCount=0;timers=new an;constructor(e,t){super(),this.id=e.sessionIdOverride??on(8),this.name=t,this.harness=e.harness?Uo(e.harness):Go(),this.prompt=e.prompt,this.workdir=e.workdir,this.model=e.model??Me(this.harness.name),this.reasoningEffort=e.reasoningEffort??pe(this.harness.name),this.fastMode=this.harness.name==="codex"?e.fastMode??_e(this.harness.name):void 0,this.systemPrompt=e.systemPrompt,this.allowedTools=e.allowedTools,this.permissionMode=e.permissionMode??_.permissionMode,this.requestedPermissionMode=e.requestedPermissionMode??this.permissionMode,this.planApproval=e.planApproval??_.planApproval,this.codexApprovalPolicy=this.harness.name==="codex"?"never":void 0,this.currentPermissionMode=this.permissionMode,this.originChannel=e.originChannel,this.originThreadId=e.originThreadId,this.originAgentId=e.originAgentId,this.originSessionKey=e.originSessionKey,this.route=e.route?{...e.route}:void 0,this.backendRef=e.backendRef?{...e.backendRef}:void 0,this.resumeSessionId=e.resumeSessionId,this.resumedFromSessionName=e.resumedFromSessionName,this.forkSession=e.forkSession,this.multiTurn=e.multiTurn??!0,this.goalTaskId=e.goalTaskId,this.worktreeStrategy=e.worktreeStrategy,this.repoIntegrationPolicy=e.repoIntegrationPolicy,this.repoIntegrationPolicySource=e.repoIntegrationPolicySource,this.repoProvider=e.repoProvider,this.worktreeBaseBranch=e.worktreeBaseBranch,this.worktreeParentBranch=e.worktreeParentBranch,e.worktreePrTargetRepo&&(this.worktreePrTargetRepo=e.worktreePrTargetRepo),e.autoMergeParentSessionId&&(this.autoMergeParentSessionId=e.autoMergeParentSessionId),e.autoMergeConflictResolutionAttemptCount!==void 0&&(this.autoMergeConflictResolutionAttemptCount=e.autoMergeConflictResolutionAttemptCount),e.autoMergeResolverSessionId&&(this.autoMergeResolverSessionId=e.autoMergeResolverSessionId),this.canUseTool=e.canUseTool,this.startedAt=Date.now(),this.abortController=new AbortController,this.turnRuntime=new ln({appendOutput:r=>Fi(this.outputBuffer,this.id,r),emitOutput:r=>this.emit("output",this,r),emitToolUse:(r,o)=>this.emit("toolUse",this,r,o),emitTurnEnd:r=>this.emit("turnEnd",this,r),markPendingPlanApproval:r=>this.markPendingPlanApproval(r),markAwaitingUserInput:()=>this.markAwaitingUserInput(),applyInputRequested:()=>this.applyControlEvent({type:"input.requested"}),completeTurn:()=>{this.applyControlEvent({type:"terminal.entered"}),this.complete("done")},queueWorktreeFinalizationPrompt:()=>this.queueWorktreeFinalizationPrompt(),setPlanFilePath:r=>{this.planFilePath=r},setLatestPlanArtifact:r=>{this.latestPlanArtifact=r;let o=this.pendingPlanApproval?this.actionablePlanDecisionVersion??this.planDecisionVersion:void 0;this.latestPlanArtifactVersion=o&&o>0?o:void 0}}),this.harnessEvents=new dn({clearStartupTimer:()=>this.clearTimer("startup"),assignBackendRef:r=>{this.backendRef=r,this.harnessSessionId=r.conversationId,r.worktreePath&&(this.worktreePath=r.worktreePath,this.originalWorkdir??=this.workdir,this.worktreeBranch??=oe(r.worktreePath),this.worktreeStrategy&&this.worktreeStrategy!=="off"&&this.applyControlEvent({type:"worktree.state_set",worktreeState:"provisioned"}))},noteRunStarted:r=>{this.backendRef&&(this.backendRef={...this.backendRef,runId:r})},transitionRunning:()=>{this._status==="starting"&&this.transition("running")},noteTextDelta:(r,o)=>this.turnRuntime.noteTextDelta(r,o),noteToolCall:r=>this.turnRuntime.noteToolCall(r),setPendingInputState:r=>this.setPendingInputState(r),notePendingInput:r=>this.turnRuntime.notePendingInput(r),clearResolvedPendingInput:(r,o)=>this.turnRuntime.clearResolvedPendingInput(r,o),notePlanArtifact:r=>this.turnRuntime.notePlanArtifact(r.artifact,r.finalized),noteSettingsChanged:r=>this.turnRuntime.noteSettingsChanged(r),setCurrentPermissionMode:r=>{this.currentPermissionMode=r,this.applyControlEvent({type:"permission.mode_changed",currentPermissionMode:r})},handleRunCompleted:r=>{let o=r.outcome??(r.success?"completed":"failed"),i=r.num_turns===0?[r.result,...this.outputBuffer.slice(-5)].filter(f=>typeof f=="string").join(`
22
+ Use agent_sessions to see active sessions and their status.`;return{content:[{type:"text",text:`Error launching session: ${o}${i}`}]}}}}}import{existsSync as Ur,readFileSync as qi}from"fs";import{EventEmitter as Td}from"events";var _i="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var Ei=65536;function Kr(n){let e=0;for(;e<n.length;){let t=Math.min(e+Ei,n.length);crypto.getRandomValues(n.subarray(e,t)),e=t}}function Di(n){if(n|=0,n<0)throw new RangeError("Wrong ID size");let e=Buffer.allocUnsafe(n);return Kr(e),e}function $i(n,e,t){let r=256-256%n.length;if(r===256){let i=n.length-1;return(s=e)=>{if(!s)return"";let a="";for(;;){let l=t(s),d=s;for(;d--;)if(a+=n[l[d]&i],a.length>=s)return a}}}let o=Math.ceil(1.6*256*e/r);return(i=e)=>{if(!i)return"";let s="";for(;;){let a=t(o),l=o;for(;l--;)if(a[l]<r&&(s+=n[a[l]%n.length],s.length>=i))return s}}}var hd=Ei/2;function yd(n,e=21){if(typeof n!="string"||!n||n.length>256)return $i(n,e,Di);for(let l=0;l<n.length;l++)if(n.charCodeAt(l)>255)return $i(n,e,Di);let t=Uint8Array.from(n,l=>l.charCodeAt(0)),r=n.length,o=(2<<31-Math.clz32(r-1|1))-1,i="",s=0,a=0;return(l=e)=>{if(l|=0,l<0)throw new RangeError("Wrong ID size");if(l===0)return"";if(s+l>i.length){let d=Math.max(a,l);a=Math.min(d*16,hd);let u=Buffer.allocUnsafe(d);if(o===r-1){Kr(u);for(let f=0;f<d;f++)u[f]=t[u[f]&o]}else{let f=Buffer.allocUnsafe(Math.ceil(1.6*(o+1)*d/r)),g=0;for(;g<d;){Kr(f);for(let k=0;k<f.length;k++){let h=f[k]&o;if(h<r&&(u[g++]=t[h],g===d))break}}}i=u.toString("latin1"),s=0}return s+=l,i.substring(s-l,s)}}var sn=yd(_i);var Ni={starting:["running","failed","killed"],running:["completed","failed","killed"],completed:[],failed:[],killed:[]};function O(n,e){return Object.hasOwn(n,e)}var Oi=new Set(["merged","released","pr_open","dismissed","cleanup_failed"]);function Sd(n){return n.requestedPermissionMode!=="plan"?"not_plan_gated":n.pendingPlanApproval?"awaiting_approval":n.planModeApproved?n.status==="starting"||n.status!=="running"&&n.approvalExecutionState==="awaiting_plan_output"?"awaiting_plan_output":"approved_then_implemented":n.currentPermissionMode!=="plan"?"implemented_without_required_approval":"awaiting_plan_output"}function G(n){return{...n,approvalExecutionState:Sd(n)}}function qr(n,e){switch(e.type){case"initialize":return G({...n,worktreeState:e.hasWorktree&&n.worktreeState==="none"?"provisioned":n.worktreeState,lifecycle:n.status==="starting"?"starting":n.lifecycle,runtimeState:n.status==="starting"?"live":n.runtimeState});case"status.transition":return e.status==="starting"?G({...n,status:e.status,lifecycle:"starting",runtimeState:"live"}):e.status==="running"?G({...n,status:e.status,lifecycle:n.lifecycle==="starting"||n.lifecycle==="suspended"?"active":n.lifecycle,runtimeState:"live"}):G({...n,status:e.status,runtimeState:"stopped",lifecycle:n.lifecycle==="suspended"?"suspended":"terminal"});case"permission.mode_changed":return G({...n,currentPermissionMode:e.currentPermissionMode});case"turn.started":return G({...n,lifecycle:"active",runtimeState:"live"});case"input.requested":return G({...n,lifecycle:n.pendingPlanApproval?"awaiting_plan_decision":"awaiting_user_input"});case"plan.requested":if(n.planModeApproved)return n;{let t=n.pendingPlanApproval&&n.approvalState==="pending"&&n.planApprovalContext===e.context,r=n.pendingPlanApproval&&n.approvalState==="changes_requested"&&n.planApprovalContext===e.context&&n.planDecisionVersion>0,o=!n.pendingPlanApproval&&n.approvalState==="changes_requested"&&n.planApprovalContext===e.context&&n.planDecisionVersion>0,i=t||r||o?n.planDecisionVersion:n.planDecisionVersion+1;return G({...n,pendingPlanApproval:!0,planApprovalContext:e.context,approvalState:"pending",planDecisionVersion:i,actionablePlanDecisionVersion:i,canonicalPlanPromptVersion:t?n.canonicalPlanPromptVersion:void 0,approvalPromptRequiredVersion:t?n.approvalPromptRequiredVersion:void 0,approvalPromptVersion:t?n.approvalPromptVersion:void 0,approvalPromptStatus:t?n.approvalPromptStatus:"not_sent",approvalPromptTransport:t?n.approvalPromptTransport:"none",approvalPromptMessageKind:t?n.approvalPromptMessageKind:"none",approvalPromptLastAttemptAt:t?n.approvalPromptLastAttemptAt:void 0,approvalPromptDeliveredAt:t?n.approvalPromptDeliveredAt:void 0,approvalPromptFailedAt:t?n.approvalPromptFailedAt:void 0,lifecycle:"awaiting_plan_decision"})}case"plan.cleared":return G({...n,pendingPlanApproval:!1,planApprovalContext:void 0,actionablePlanDecisionVersion:void 0,approvalState:n.approvalState==="pending"?"not_required":n.approvalState});case"plan.approved":return G({...n,pendingPlanApproval:!1,planApprovalContext:void 0,actionablePlanDecisionVersion:void 0,planModeApproved:!0,approvalState:"approved",planDecisionVersion:n.planDecisionVersion+1,approvalPromptVersion:void 0,approvalPromptStatus:"not_sent",lifecycle:n.status==="running"?"active":n.lifecycle});case"plan.changes_requested":return G({...n,pendingPlanApproval:!0,approvalState:"changes_requested",planDecisionVersion:n.planDecisionVersion+1,actionablePlanDecisionVersion:void 0,canonicalPlanPromptVersion:void 0,approvalPromptRequiredVersion:void 0,approvalPromptVersion:void 0,approvalPromptStatus:"not_sent",approvalPromptTransport:"none",approvalPromptMessageKind:"none",approvalPromptLastAttemptAt:void 0,approvalPromptDeliveredAt:void 0,approvalPromptFailedAt:void 0,lifecycle:"awaiting_plan_decision"});case"terminal.entered":return G({...n,lifecycle:e.suspended?"suspended":"terminal",runtimeState:"stopped"});case"worktree.decision_requested":return G({...n,lifecycle:"awaiting_worktree_decision",worktreeState:"pending_decision"});case"worktree.state_set":return G({...n,worktreeState:e.worktreeState,lifecycle:e.worktreeState==="pending_decision"?"awaiting_worktree_decision":Oi.has(e.worktreeState)?"terminal":n.lifecycle});case"delivery.state_set":return G({...n,deliveryState:e.deliveryState})}}function Wi(n,e){let t={...n,...O(e,"lifecycle")?{lifecycle:e.lifecycle}:{},...O(e,"approvalState")?{approvalState:e.approvalState}:{},...O(e,"approvalExecutionState")?{approvalExecutionState:e.approvalExecutionState}:{},...O(e,"worktreeState")?{worktreeState:e.worktreeState}:{},...O(e,"runtimeState")?{runtimeState:e.runtimeState}:{},...O(e,"deliveryState")?{deliveryState:e.deliveryState}:{},...O(e,"requestedPermissionMode")?{requestedPermissionMode:e.requestedPermissionMode}:{},...O(e,"currentPermissionMode")?{currentPermissionMode:e.currentPermissionMode}:{},...O(e,"pendingPlanApproval")?{pendingPlanApproval:e.pendingPlanApproval}:{},...O(e,"planApprovalContext")?{planApprovalContext:e.planApprovalContext}:{},...O(e,"planDecisionVersion")?{planDecisionVersion:e.planDecisionVersion}:{},...O(e,"actionablePlanDecisionVersion")?{actionablePlanDecisionVersion:e.actionablePlanDecisionVersion}:{},...O(e,"canonicalPlanPromptVersion")?{canonicalPlanPromptVersion:e.canonicalPlanPromptVersion}:{},...O(e,"approvalPromptRequiredVersion")?{approvalPromptRequiredVersion:e.approvalPromptRequiredVersion}:{},...O(e,"approvalPromptVersion")?{approvalPromptVersion:e.approvalPromptVersion}:{},...O(e,"approvalPromptStatus")?{approvalPromptStatus:e.approvalPromptStatus}:{},...O(e,"approvalPromptTransport")?{approvalPromptTransport:e.approvalPromptTransport}:{},...O(e,"approvalPromptMessageKind")?{approvalPromptMessageKind:e.approvalPromptMessageKind}:{},...O(e,"approvalPromptLastAttemptAt")?{approvalPromptLastAttemptAt:e.approvalPromptLastAttemptAt}:{},...O(e,"approvalPromptDeliveredAt")?{approvalPromptDeliveredAt:e.approvalPromptDeliveredAt}:{},...O(e,"approvalPromptFailedAt")?{approvalPromptFailedAt:e.approvalPromptFailedAt}:{},...O(e,"planModeApproved")?{planModeApproved:e.planModeApproved}:{}};return e.approvalState==="changes_requested"&&e.pendingPlanApproval===void 0&&(t={...t,pendingPlanApproval:!1}),t.pendingPlanApproval?t={...t,approvalState:"pending",actionablePlanDecisionVersion:t.actionablePlanDecisionVersion??t.planDecisionVersion,lifecycle:"awaiting_plan_decision"}:t.approvalState==="changes_requested"&&(t={...t,actionablePlanDecisionVersion:void 0,lifecycle:"awaiting_user_input"}),O(e,"pendingWorktreeDecisionSince")&&e.pendingWorktreeDecisionSince!==void 0||t.worktreeState==="pending_decision"?t=qr(t,{type:"worktree.decision_requested"}):Oi.has(t.worktreeState)&&(t={...t,lifecycle:"terminal"}),G(t)}var an=class{queue=[];resolve=null;done=!1;hasPending(){return this.queue.length>0}push(e){this.queue.push(e),this.resolve&&(this.resolve(),this.resolve=null)}end(){this.done=!0,this.resolve&&(this.resolve(),this.resolve=null)}async*[Symbol.asyncIterator](){for(;;){for(;this.queue.length>0;)yield this.queue.shift();if(this.done)return;await new Promise(e=>{this.resolve=e})}}};import{createHash as kd}from"crypto";import{appendFileSync as vd}from"fs";import{tmpdir as Pd}from"os";import{join as wd}from"path";var Fi=2e3,bd=/^[A-Za-z0-9_.-]+$/;function Rd(n){return bd.test(n)?n:`hashed+${kd("sha256").update(n,"utf8").digest("hex")}`}function ve(n){return wd(Pd(),`openclaw-agent-${Rd(n)}.txt`)}function Ad(n,e){if(!e)return;let t=e.split(`
23
+ `),[r="",...o]=t;n.length===0?n.push(r):n[n.length-1]+=r;for(let i of o)n.push(i)}function Li(n,e,t){Ad(n,t),n.length>Fi&&n.splice(0,n.length-Fi);try{vd(ve(e),t,"utf-8")}catch{}return n}var ln=class{timers=new Map;get size(){return this.timers.size}set(e,t,r){this.clear(e);let o=setTimeout(()=>{this.timers.get(e)===o&&this.timers.delete(e),r()},t);o.unref?.(),this.timers.set(e,o)}clear(e){let t=this.timers.get(e);t&&(clearTimeout(t),this.timers.delete(e))}clearAll(){for(let e of this.timers.values())clearTimeout(e);this.timers.clear()}};var dn=class{constructor(e){this.deps=e}deps;waitingForInputFired=!1;lastTurnHadQuestion=!1;turnInProgress=!0;currentTurnText="";currentTurnPlanArtifact;pendingInputNotificationIdentity;beginUserTurn(){this.waitingForInputFired=!1,this.turnInProgress=!0,this.currentTurnText="",this.currentTurnPlanArtifact=void 0,this.lastTurnHadQuestion=!1}noteTextDelta(e,t){this.waitingForInputFired=!1,t||(this.lastTurnHadQuestion=!1),this.deps.appendOutput(e),this.currentTurnText+=this.currentTurnText?`
24
+ ${e}`:e,this.deps.emitOutput(e)}noteToolCall(e){let{name:t,input:r,currentPermissionMode:o,permissionMode:i,planModeApproved:s}=e;if(t==="Write"){let a=r;typeof a?.file_path=="string"&&a.file_path.includes("/.claude/plans/")&&this.deps.setPlanFilePath(a.file_path)}t==="AskUserQuestion"?(this.lastTurnHadQuestion=!0,this.deps.applyInputRequested(),(o==="plan"||i==="plan")&&!s&&this.deps.markPendingPlanApproval("plan-mode")):(t==="ExitPlanMode"||t==="set_permission_mode")&&!s&&(this.lastTurnHadQuestion=!0,this.deps.markPendingPlanApproval("plan-mode")),this.deps.emitToolUse(t,r)}notePendingInput(e){this.lastTurnHadQuestion=!0,this.deps.applyInputRequested();let t=e?.activeQuestionIndex??0,r=e?.questions?.[t],o=e?.requestId?`${e.requestId}:${r?.id??(e.activeQuestionIndex!=null?`q${e.activeQuestionIndex}`:"request")}`:void 0;(!this.waitingForInputFired||o&&o!==this.pendingInputNotificationIdentity)&&(this.waitingForInputFired=!0,this.pendingInputNotificationIdentity=o,this.deps.emitTurnEnd(!0))}clearResolvedPendingInput(e,t){if(!e||t?.requestId===e){this.pendingInputNotificationIdentity=void 0;return}return t}notePlanArtifact(e,t){if(this.currentTurnPlanArtifact=e,this.deps.setLatestPlanArtifact(e),!t)return;let r=e.markdown.trim();!r||this.currentTurnText.trim()===r||(this.deps.appendOutput(r),this.currentTurnText=r,this.deps.emitOutput(r))}noteSettingsChanged(e){let{oldMode:t,permissionMode:r,planModeApproved:o}=e;if(r)return r!=="plan"&&t==="plan"&&!o&&(this.deps.markPendingPlanApproval("plan-mode"),this.lastTurnHadQuestion=!0),r}finishSuccessfulTurn(e){let{currentPermissionMode:t,permissionMode:r,pendingPlanApproval:o,planModeApproved:i,pendingInputState:s,hasPendingMessages:a}=e,l=o;(t==="plan"||r==="plan")&&!l&&!i&&(this.deps.markPendingPlanApproval("plan-mode"),l=!0);let d=l||this.lastTurnHadQuestion||!!s;if(this.turnInProgress=a,d&&!this.waitingForInputFired)this.waitingForInputFired=!0,l||this.deps.markAwaitingUserInput(),this.deps.emitTurnEnd(!0);else if(!a&&!d){if(this.deps.queueWorktreeFinalizationPrompt?.()){this.turnInProgress=!0;return}this.deps.completeTurn(),this.deps.emitTurnEnd(!1)}}finishTerminalTurn(){this.turnInProgress=!1}finishInterruptedTurn(e){this.turnInProgress=e,this.waitingForInputFired=!1,this.lastTurnHadQuestion=!1,this.currentTurnText="",this.currentTurnPlanArtifact=void 0}resetAfterRun(){this.lastTurnHadQuestion=!1,this.currentTurnText="",this.currentTurnPlanArtifact=void 0}};var un=class{constructor(e){this.deps=e}deps;applyMessage(e,t){if(e.type==="backend_ref"){this.deps.clearStartupTimer(),this.deps.assignBackendRef({...e.ref}),this.deps.transitionRunning();return}if(e.type==="run_started"){e.runId&&this.deps.noteRunStarted(e.runId);return}if(e.type==="text_delta"){this.deps.noteTextDelta(e.text,t.pendingPlanApproval);return}if(e.type==="tool_call"){this.deps.noteToolCall({name:e.name,input:e.input,currentPermissionMode:t.currentPermissionMode,permissionMode:t.permissionMode,planModeApproved:t.planModeApproved});return}if(e.type==="pending_input"){this.deps.setPendingInputState(e.state),this.deps.notePendingInput(e.state);return}if(e.type==="pending_input_resolved"){this.deps.setPendingInputState(this.deps.clearResolvedPendingInput(e.requestId,t.pendingInputState));return}if(e.type==="plan_artifact"){this.deps.notePlanArtifact(e);return}if(e.type==="settings_changed"){let r=this.deps.noteSettingsChanged({oldMode:t.currentPermissionMode,permissionMode:e.permissionMode,planModeApproved:t.planModeApproved});r&&this.deps.setCurrentPermissionMode(r);return}if(e.type==="run_completed"){this.deps.handleRunCompleted(e.data);return}e.type}};var Id=[/\bfailed to authenticate\b/i,/\binvalid bearer token\b/i,/\bapi error:\s*401\b/i,/\b401\s+unauthori[sz]ed\b/i,/\binvalid api key\b/i,/\binvalid authentication\b/i,/\bauthentication failed\b/i,/\bauth(?:orization)? error\b/i];function Vr(n){return n?.trim()?Id.some(e=>e.test(n)):!1}function Bi(n){if(!n?.trim())return;let e=n.split(/\r?\n/).map(t=>t.trim()).filter(Boolean);return e.find(t=>Vr(t))??e.at(-1)}var xd=120*1e3;function it(n){return n instanceof Error?n.message:String(n)}function Cd(n,e){JSON.stringify({component:"Session",event:n,at:new Date().toISOString(),...e})}function Md(n){return n?{backendRefKind:n.kind,hasBackendConversationId:!!n.conversationId,hasBackendRunId:!!n.runId,hasBackendWorktreeId:!!n.worktreeId,hasBackendWorktreePath:!!n.worktreePath}:{}}var pn=class extends Td{id;name;harnessSessionId;backendRef;harness;harnessHandle;prompt;workdir;model;reasoningEffort;fastMode;systemPrompt;allowedTools;permissionMode;requestedPermissionMode;planApproval;codexApprovalPolicy;currentPermissionMode;pendingModeSwitch;resumeSessionId;resumedFromSessionName;forkSession;worktreePath;originalWorkdir;worktreeBranch;worktreeParentBranch;worktreeStrategy;repoIntegrationPolicy;repoIntegrationPolicySource;repoProvider;worktreeBaseBranch;worktreePrTargetRepo;autoMergeParentSessionId;autoMergeConflictResolutionAttemptCount;autoMergeResolverSessionId;worktreePushRemote;worktreeDisposition;worktreePrUrl;worktreePrNumber;worktreeMerged;worktreeMergedAt;worktreeLifecycle;worktreeState="none";multiTurn;goalTaskId;messageStream;_status="starting";error;startedAt;completedAt;abortController;teardownPromise;outputBuffer=[];result;costUsd=0;originChannel;originThreadId;originAgentId;originSessionKey;route;pendingInputState;lastPendingInputSubmissionRequiresMore=!1;pendingPlanApproval=!1;planApprovalContext;planDecisionVersion=0;actionablePlanDecisionVersion;canonicalPlanPromptVersion;approvalPromptRequiredVersion;approvalPromptVersion;approvalPromptStatus="not_sent";approvalPromptTransport="none";approvalPromptMessageKind="none";approvalPromptLastAttemptAt;approvalPromptDeliveredAt;approvalPromptFailedAt;planFilePath;killReason="unknown";planModeApproved=!1;turnRuntime;harnessEvents;worktreeFinalizationPromptIssued=!1;lifecycle="starting";approvalState="not_required";approvalExecutionState="not_plan_gated";approvalRationale;latestPlanArtifact;latestPlanArtifactVersion;runtimeState="live";taskFlowMirror;deliveryState="idle";canUseTool;autoRespondCount=0;timers=new ln;constructor(e,t){super(),this.id=e.sessionIdOverride??sn(8),this.name=t,this.harness=e.harness?Uo(e.harness):Go(),this.prompt=e.prompt,this.workdir=e.workdir,this.model=e.model??Me(this.harness.name),this.reasoningEffort=e.reasoningEffort??pe(this.harness.name),this.fastMode=this.harness.name==="codex"?e.fastMode??_e(this.harness.name):void 0,this.systemPrompt=e.systemPrompt,this.allowedTools=e.allowedTools,this.permissionMode=e.permissionMode??_.permissionMode,this.requestedPermissionMode=e.requestedPermissionMode??this.permissionMode,this.planApproval=e.planApproval??_.planApproval,this.codexApprovalPolicy=this.harness.name==="codex"?"never":void 0,this.currentPermissionMode=this.permissionMode,this.originChannel=e.originChannel,this.originThreadId=e.originThreadId,this.originAgentId=e.originAgentId,this.originSessionKey=e.originSessionKey,this.route=e.route?{...e.route}:void 0,this.backendRef=e.backendRef?{...e.backendRef}:void 0,this.resumeSessionId=e.resumeSessionId,this.resumedFromSessionName=e.resumedFromSessionName,this.forkSession=e.forkSession,this.multiTurn=e.multiTurn??!0,this.goalTaskId=e.goalTaskId,this.worktreeStrategy=e.worktreeStrategy,this.repoIntegrationPolicy=e.repoIntegrationPolicy,this.repoIntegrationPolicySource=e.repoIntegrationPolicySource,this.repoProvider=e.repoProvider,this.worktreeBaseBranch=e.worktreeBaseBranch,this.worktreeParentBranch=e.worktreeParentBranch,e.worktreePrTargetRepo&&(this.worktreePrTargetRepo=e.worktreePrTargetRepo),e.autoMergeParentSessionId&&(this.autoMergeParentSessionId=e.autoMergeParentSessionId),e.autoMergeConflictResolutionAttemptCount!==void 0&&(this.autoMergeConflictResolutionAttemptCount=e.autoMergeConflictResolutionAttemptCount),e.autoMergeResolverSessionId&&(this.autoMergeResolverSessionId=e.autoMergeResolverSessionId),this.canUseTool=e.canUseTool,this.startedAt=Date.now(),this.abortController=new AbortController,this.turnRuntime=new dn({appendOutput:r=>Li(this.outputBuffer,this.id,r),emitOutput:r=>this.emit("output",this,r),emitToolUse:(r,o)=>this.emit("toolUse",this,r,o),emitTurnEnd:r=>this.emit("turnEnd",this,r),markPendingPlanApproval:r=>this.markPendingPlanApproval(r),markAwaitingUserInput:()=>this.markAwaitingUserInput(),applyInputRequested:()=>this.applyControlEvent({type:"input.requested"}),completeTurn:()=>{this.applyControlEvent({type:"terminal.entered"}),this.complete("done")},queueWorktreeFinalizationPrompt:()=>this.queueWorktreeFinalizationPrompt(),setPlanFilePath:r=>{this.planFilePath=r},setLatestPlanArtifact:r=>{this.latestPlanArtifact=r;let o=this.pendingPlanApproval?this.actionablePlanDecisionVersion??this.planDecisionVersion:void 0;this.latestPlanArtifactVersion=o&&o>0?o:void 0}}),this.harnessEvents=new un({clearStartupTimer:()=>this.clearTimer("startup"),assignBackendRef:r=>{this.backendRef=r,this.harnessSessionId=r.conversationId,r.worktreePath&&(this.worktreePath=r.worktreePath,this.originalWorkdir??=this.workdir,this.worktreeBranch??=oe(r.worktreePath),this.worktreeStrategy&&this.worktreeStrategy!=="off"&&this.applyControlEvent({type:"worktree.state_set",worktreeState:"provisioned"}))},noteRunStarted:r=>{this.backendRef&&(this.backendRef={...this.backendRef,runId:r})},transitionRunning:()=>{this._status==="starting"&&this.transition("running")},noteTextDelta:(r,o)=>this.turnRuntime.noteTextDelta(r,o),noteToolCall:r=>this.turnRuntime.noteToolCall(r),setPendingInputState:r=>this.setPendingInputState(r),notePendingInput:r=>this.turnRuntime.notePendingInput(r),clearResolvedPendingInput:(r,o)=>this.turnRuntime.clearResolvedPendingInput(r,o),notePlanArtifact:r=>this.turnRuntime.notePlanArtifact(r.artifact,r.finalized),noteSettingsChanged:r=>this.turnRuntime.noteSettingsChanged(r),setCurrentPermissionMode:r=>{this.currentPermissionMode=r,this.applyControlEvent({type:"permission.mode_changed",currentPermissionMode:r})},handleRunCompleted:r=>{let o=r.outcome??(r.success?"completed":"failed"),i=r.num_turns===0?[r.result,...this.outputBuffer.slice(-5)].filter(f=>typeof f=="string").join(`
25
25
  `):"",s=o==="completed"&&Vr(i),a=s?"failed":o,l=s?Bi(i)??r.result:r.result;this.result={subtype:a==="interrupted"?"interrupted":a==="completed"?"success":"error",duration_ms:r.duration_ms,total_cost_usd:r.total_cost_usd,num_turns:r.num_turns,result:l,is_error:a==="failed",session_id:r.session_id},this.costUsd=r.total_cost_usd;let d=this.multiTurn&&this.messageStream&&a==="interrupted",u=this.multiTurn&&this.messageStream&&a==="completed";d?(this.resetIdleTimer(),this.turnRuntime.finishInterruptedTurn(this.messageStream?.hasPending()===!0)):u?(this.resetIdleTimer(),this.turnRuntime.finishSuccessfulTurn({currentPermissionMode:this.currentPermissionMode,permissionMode:this.permissionMode,pendingPlanApproval:this.pendingPlanApproval,planModeApproved:this.planModeApproved,pendingInputState:this.pendingInputState,hasPendingMessages:this.messageStream?.hasPending()===!0})):(this.turnRuntime.finishTerminalTurn(),this.transitionToTerminal(a==="completed"?"completed":"failed",{...a==="failed"&&l?{error:l}:{}})),this.turnRuntime.resetAfterRun(),this.setPendingInputState(void 0)}}),this.applyControlEvent({type:"initialize",hasWorktree:!!(this.worktreeStrategy&&this.worktreeStrategy!=="off")}),(e.planModeApproved!==void 0||e.approvalState!==void 0||e.approvalExecutionState!==void 0||e.approvalRationale!==void 0||e.pendingPlanApproval!==void 0||e.planApprovalContext!==void 0||e.planDecisionVersion!==void 0||e.actionablePlanDecisionVersion!==void 0||e.canonicalPlanPromptVersion!==void 0||e.approvalPromptRequiredVersion!==void 0||e.approvalPromptVersion!==void 0||e.approvalPromptStatus!==void 0||e.approvalPromptTransport!==void 0||e.approvalPromptMessageKind!==void 0||e.approvalPromptLastAttemptAt!==void 0||e.approvalPromptDeliveredAt!==void 0||e.approvalPromptFailedAt!==void 0)&&this.applyControlPatch({...e.planModeApproved!==void 0?{planModeApproved:e.planModeApproved}:{},...e.approvalState!==void 0?{approvalState:e.approvalState}:{},...e.approvalExecutionState!==void 0?{approvalExecutionState:e.approvalExecutionState}:{},...e.pendingPlanApproval!==void 0?{pendingPlanApproval:e.pendingPlanApproval}:{},...e.planApprovalContext!==void 0?{planApprovalContext:e.planApprovalContext}:{},...e.planDecisionVersion!==void 0?{planDecisionVersion:e.planDecisionVersion}:{},...e.actionablePlanDecisionVersion!==void 0?{actionablePlanDecisionVersion:e.actionablePlanDecisionVersion}:{},...e.canonicalPlanPromptVersion!==void 0?{canonicalPlanPromptVersion:e.canonicalPlanPromptVersion}:{},...e.approvalPromptRequiredVersion!==void 0?{approvalPromptRequiredVersion:e.approvalPromptRequiredVersion}:{},...e.approvalPromptVersion!==void 0?{approvalPromptVersion:e.approvalPromptVersion}:{},...e.approvalPromptStatus!==void 0?{approvalPromptStatus:e.approvalPromptStatus}:{},...e.approvalPromptTransport!==void 0?{approvalPromptTransport:e.approvalPromptTransport}:{},...e.approvalPromptMessageKind!==void 0?{approvalPromptMessageKind:e.approvalPromptMessageKind}:{},...e.approvalPromptLastAttemptAt!==void 0?{approvalPromptLastAttemptAt:e.approvalPromptLastAttemptAt}:{},...e.approvalPromptDeliveredAt!==void 0?{approvalPromptDeliveredAt:e.approvalPromptDeliveredAt}:{},...e.approvalPromptFailedAt!==void 0?{approvalPromptFailedAt:e.approvalPromptFailedAt}:{}}),this.approvalRationale=e.approvalRationale}get status(){return this._status}get harnessName(){return this.harness.name}get backendKind(){return this.harness.backendKind}get backendCapabilities(){return this.harness.capabilities}get backendConversationId(){return C(this)}approvalSnapshot(){return{requestedPermissionMode:this.requestedPermissionMode,currentPermissionMode:this.currentPermissionMode,approvalExecutionState:this.approvalExecutionState,approvalRationale:this.approvalRationale,planModeApproved:this.controlStateSnapshot().planModeApproved,pendingPlanApproval:this.pendingPlanApproval,planApprovalContext:this.planApprovalContext,planDecisionVersion:this.planDecisionVersion,actionablePlanDecisionVersion:this.actionablePlanDecisionVersion,canonicalPlanPromptVersion:this.canonicalPlanPromptVersion,approvalPromptRequiredVersion:this.approvalPromptRequiredVersion,approvalPromptVersion:this.approvalPromptVersion,approvalPromptStatus:this.approvalPromptStatus,approvalPromptTransport:this.approvalPromptTransport,approvalPromptMessageKind:this.approvalPromptMessageKind,approvalPromptLastAttemptAt:this.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:this.approvalPromptDeliveredAt,approvalPromptFailedAt:this.approvalPromptFailedAt,planApproval:this.planApproval,codexApprovalPolicy:this.codexApprovalPolicy}}worktreeSnapshot(){return{worktreePath:this.worktreePath,worktreeBranch:this.worktreeBranch,worktreeStrategy:this.worktreeStrategy,repoIntegrationPolicy:this.repoIntegrationPolicy,repoIntegrationPolicySource:this.repoIntegrationPolicySource,repoProvider:this.repoProvider,worktreeBaseBranch:this.worktreeBaseBranch,worktreeParentBranch:this.worktreeParentBranch,worktreePrTargetRepo:this.worktreePrTargetRepo,autoMergeParentSessionId:this.autoMergeParentSessionId,autoMergeConflictResolutionAttemptCount:this.autoMergeConflictResolutionAttemptCount,autoMergeResolverSessionId:this.autoMergeResolverSessionId,worktreeLifecycle:this.worktreeLifecycle}}backendSnapshot(){return{harnessSessionId:this.harnessSessionId,backendRef:this.backendRef,harness:this.harnessName,backendKind:this.backendKind,backendConversationId:this.backendConversationId}}routingSnapshot(){return{route:this.route,originAgentId:this.originAgentId,originChannel:this.originChannel,originThreadId:this.originThreadId,originSessionKey:this.originSessionKey}}get waitingForInputFired(){return this.turnRuntime.waitingForInputFired}set waitingForInputFired(e){this.turnRuntime.waitingForInputFired=e}get turnInProgress(){return this.turnRuntime.turnInProgress}set turnInProgress(e){this.turnRuntime.turnInProgress=e}get currentTurnPlanArtifact(){return this.turnRuntime.currentTurnPlanArtifact}set currentTurnPlanArtifact(e){this.turnRuntime.currentTurnPlanArtifact=e}get duration(){return(this.completedAt??Date.now())-this.startedAt}get phase(){return this.lifecycle}get isExplicitlyResumable(){return this.status!=="running"&&this.status!=="completed"&&this.killReason!=="done"&&!!this.backendConversationId}transition(e){if(!Ni[this._status].includes(e))throw new Error(`Session state error: cannot transition from ${this._status} to ${e}. This is an internal error — please report it.`);let t=this._status;this._status=e,this.applyControlEvent({type:"status.transition",status:e}),this.emit("statusChange",this,e,t)}setTimer(e,t,r){this.timers.set(e,t,r)}clearTimer(e){this.timers.clear(e)}clearAllTimers(){this.timers.clearAll()}markPendingPlanApproval(e){let t=this.latestPlanArtifactVersion;this.approvalRationale=void 0,this.applyControlEvent({type:"plan.requested",context:e});let r=this.actionablePlanDecisionVersion??this.planDecisionVersion;this.currentTurnPlanArtifact&&r>0?(this.latestPlanArtifact=this.currentTurnPlanArtifact,this.latestPlanArtifactVersion=r):t!==r&&(this.latestPlanArtifact=void 0,this.latestPlanArtifactVersion=void 0)}clearPendingPlanApproval(){this.applyControlEvent({type:"plan.cleared"})}markAwaitingUserInput(){this.applyControlEvent({type:"input.requested"})}queueWorktreeFinalizationPrompt(){if(!this.multiTurn||!this.messageStream||!this.worktreePath||!this.worktreeStrategy||this.worktreeStrategy==="off"||this.worktreeFinalizationPromptIssued)return!1;let e=Ze(this.worktreePath);if(e.length===0)return!1;this.worktreeFinalizationPromptIssued=!0;let t=e.slice(0,20).map(i=>`- ${i}`).join(`
26
26
  `),r=e.length>20?`
27
27
  - ...and ${e.length-20} more`:"",o=["Your worktree still has uncommitted changes, so this session cannot finish yet.","",`Worktree: ${this.worktreePath}`,`Branch: ${this.worktreeBranch??"(unknown)"}`,"","Dirty entries:",`${t}${r}`,"","Before finishing, run `git status --short` in the worktree and do exactly one of these:","1. If these are real task changes, commit them on the worktree branch with `git add` and `git commit`.","2. If these are temporary or unrelated artifacts, remove or restore them so the worktree is clean.","3. If no repository changes were intended, leave the worktree clean and say that no changes were needed.","","Do not finish again until `git status --short` is clean or all real task changes are committed."].join(`
28
- `);return this.messageStream.push(this.harness.buildUserMessage(o,this.backendConversationId??"")),!0}async start(){this.logDiagnostic("harness.launch.start",{model:this.model,hasWorkdir:!!this.workdir,hasResumeSessionId:!!this.resumeSessionId,forkSessionRequested:this.forkSession===!0,hasBackendRef:!!this.backendRef});try{let e;this.multiTurn?(this.messageStream=new sn,this.messageStream.push(this.harness.buildUserMessage(this.prompt,"")),e=this.messageStream):e=this.prompt;let t=this.harness.launch({prompt:e,cwd:this.workdir,model:this.model,reasoningEffort:this.reasoningEffort,fastMode:this.fastMode,permissionMode:this.permissionMode,codexApprovalPolicy:this.codexApprovalPolicy,systemPrompt:this.systemPrompt,allowedTools:this.allowedTools,resumeSessionId:this.resumeSessionId,forkSession:this.forkSession,backendRef:this.backendRef,worktreeStrategy:this.worktreeStrategy,originalWorkdir:this.originalWorkdir??this.workdir,abortController:this.abortController,mcpServers:Bo(),canUseTool:this.canUseTool});this.harnessHandle=t,this.logDiagnostic("harness.launch.created",{hasStreamInput:!!t.streamInput,hasInterrupt:!!t.interrupt,hasPermissionModeSwitch:!!t.setPermissionMode}),this.setTimer("startup",xd,()=>{this._status==="starting"&&this.kill("startup-timeout")})}catch(e){let t=e instanceof Error?e.message:String(e);this.logDiagnostic("harness.launch.error",{error:t}),this.transitionToTerminal("failed",{error:t});return}this.consumeMessages(this.harnessHandle.messages).catch(e=>{let t=e instanceof Error?e.message:String(e),r=e instanceof Error?e.stack:void 0;this.logDiagnostic("harness.stream.error",{error:t}),console.error(`[Session ${this.id}] consumeMessages error: ${t}`,r),this.isActive&&this.transitionToTerminal("failed",{error:t})})}async sendMessage(e){if(this._status!=="running")throw new Error(`Session is not running (status: ${this._status})`);this.resetIdleTimer(),this.turnRuntime.beginUserTurn(),this.applyControlEvent({type:"turn.started"});let t=e;if(this.pendingModeSwitch){let r=this.pendingModeSwitch,o=!1,i=!1;if(this.harnessHandle?.setPermissionMode)try{await this.harnessHandle.setPermissionMode(r),this.currentPermissionMode=r,this.applyControlEvent({type:"permission.mode_changed",currentPermissionMode:r}),this.pendingModeSwitch=void 0,i=!0,o=!0}catch(s){throw console.error(`[Session ${this.id}] setPermissionMode(${r}) FAILED: ${un(s)}`),this.markPendingPlanApproval(this.planApprovalContext??"plan-mode"),new Error(`Failed to switch permission mode to ${r}: ${un(s)}`)}else this.pendingModeSwitch=void 0,i=!0,o=!0,`${this.id}${this.currentPermissionMode}`;i&&(this.clearPendingPlanApproval(),r!=="plan"&&this.applyControlEvent({type:"plan.approved"})),o&&(t=`[SYSTEM: The user has approved your plan. Exit plan mode immediately and implement the changes with full permissions. Do not ask for further confirmation.]
28
+ `);return this.messageStream.push(this.harness.buildUserMessage(o,this.backendConversationId??"")),!0}async start(){this.logDiagnostic("harness.launch.start",{model:this.model,hasWorkdir:!!this.workdir,hasResumeSessionId:!!this.resumeSessionId,forkSessionRequested:this.forkSession===!0,hasBackendRef:!!this.backendRef});try{let e;this.multiTurn?(this.messageStream=new an,this.messageStream.push(this.harness.buildUserMessage(this.prompt,"")),e=this.messageStream):e=this.prompt;let t=this.harness.launch({prompt:e,cwd:this.workdir,model:this.model,reasoningEffort:this.reasoningEffort,fastMode:this.fastMode,permissionMode:this.permissionMode,codexApprovalPolicy:this.codexApprovalPolicy,systemPrompt:this.systemPrompt,allowedTools:this.allowedTools,resumeSessionId:this.resumeSessionId,forkSession:this.forkSession,backendRef:this.backendRef,worktreeStrategy:this.worktreeStrategy,originalWorkdir:this.originalWorkdir??this.workdir,abortController:this.abortController,mcpServers:Bo(),canUseTool:this.canUseTool});this.harnessHandle=t,this.logDiagnostic("harness.launch.created",{hasStreamInput:!!t.streamInput,hasInterrupt:!!t.interrupt,hasClose:!!t.close,hasPermissionModeSwitch:!!t.setPermissionMode}),this.setTimer("startup",xd,()=>{this._status==="starting"&&this.kill("startup-timeout")})}catch(e){let t=e instanceof Error?e.message:String(e);this.logDiagnostic("harness.launch.error",{error:t}),this.transitionToTerminal("failed",{error:t});return}this.consumeMessages(this.harnessHandle.messages).catch(e=>{let t=e instanceof Error?e.message:String(e),r=e instanceof Error?e.stack:void 0;this.logDiagnostic("harness.stream.error",{error:t}),console.error(`[Session ${this.id}] consumeMessages error: ${t}`,r),this.isActive&&this.transitionToTerminal("failed",{error:t})})}async sendMessage(e){if(this._status!=="running")throw new Error(`Session is not running (status: ${this._status})`);this.resetIdleTimer(),this.turnRuntime.beginUserTurn(),this.applyControlEvent({type:"turn.started"});let t=e;if(this.pendingModeSwitch){let r=this.pendingModeSwitch,o=!1,i=!1;if(this.harnessHandle?.setPermissionMode)try{await this.harnessHandle.setPermissionMode(r),this.currentPermissionMode=r,this.applyControlEvent({type:"permission.mode_changed",currentPermissionMode:r}),this.pendingModeSwitch=void 0,i=!0,o=!0}catch(s){throw console.error(`[Session ${this.id}] setPermissionMode(${r}) FAILED: ${it(s)}`),this.markPendingPlanApproval(this.planApprovalContext??"plan-mode"),new Error(`Failed to switch permission mode to ${r}: ${it(s)}`)}else this.pendingModeSwitch=void 0,i=!0,o=!0,`${this.id}${this.currentPermissionMode}`;i&&(this.clearPendingPlanApproval(),r!=="plan"&&this.applyControlEvent({type:"plan.approved"})),o&&(t=`[SYSTEM: The user has approved your plan. Exit plan mode immediately and implement the changes with full permissions. Do not ask for further confirmation.]
29
29
 
30
30
  ${e}`)}else if((this.pendingPlanApproval||this.approvalState==="changes_requested")&&!this.planModeApproved&&(this.approvalState!=="changes_requested"&&this.applyControlEvent({type:"plan.changes_requested"}),t=`[SYSTEM: The user wants changes to your plan. Revise the plan based on their feedback below, then re-submit your revised plan for approval. Do NOT start implementing yet.]
31
31
 
32
- ${e}`,this.harnessHandle?.setPermissionMode))try{await this.harnessHandle.setPermissionMode("plan"),this.currentPermissionMode="plan",this.applyControlEvent({type:"permission.mode_changed",currentPermissionMode:"plan"})}catch(r){`${this.id}${un(r)}`}if(this.multiTurn&&this.messageStream)this.messageStream.push(this.harness.buildUserMessage(t,this.backendConversationId??""));else if(this.harnessHandle?.streamInput){let r=this.harness.buildUserMessage(t,this.backendConversationId??"");async function*o(){yield r}await this.harnessHandle.streamInput(o())}else throw new Error("Session does not support follow-up messages (launched in single-turn mode).")}async interrupt(){return!this.turnInProgress||!this.harnessHandle?.interrupt?!1:(await this.harnessHandle.interrupt(),!0)}async submitPendingInputOption(e,t){if(!this.pendingInputState||!this.harnessHandle?.submitPendingInputOption)return!1;let r=this.pendingInputState.activeQuestionIndex,o=this.pendingInputState.questions?.length,i=await this.harnessHandle.submitPendingInputOption(e,t);return i&&(this.lastPendingInputSubmissionRequiresMore=r!=null&&o!=null&&r+1<o,this.waitingForInputFired=!1),i}canSubmitPendingInputOption(){return!!(this.pendingInputState&&this.harnessHandle?.submitPendingInputOption)}setPendingInputState(e){this.pendingInputState=e,e||(this.lastPendingInputSubmissionRequiresMore=!1)}pendingInputSubmissionRequiresMore(){return this.lastPendingInputSubmissionRequiresMore}async submitPendingInputText(e){if(!this.pendingInputState||!this.harnessHandle?.submitPendingInputText)return!1;let t=this.pendingInputState.activeQuestionIndex,r=this.pendingInputState.questions?.length,o=await this.harnessHandle.submitPendingInputText(e);return o&&(this.lastPendingInputSubmissionRequiresMore=t!=null&&r!=null&&t+1<r,this.waitingForInputFired=!1),o}switchPermissionMode(e){this.pendingModeSwitch=e}get isActive(){return this._status==="starting"||this._status==="running"}kill(e){this.transitionToTerminal("killed",{reason:e})}complete(e="done"){this.transitionToTerminal("completed",{reason:e})}incrementAutoRespond(){this.autoRespondCount++}resetAutoRespond(){this.autoRespondCount=0}getOutput(e){return e===void 0?this.outputBuffer.slice():this.outputBuffer.slice(-e)}resetIdleTimer(){if(!this.multiTurn)return;let e=(_.idleTimeoutMinutes??15)*60*1e3;this.setTimer("idle",e,()=>{this._status==="running"&&(this.logDiagnostic("idle_timeout.fire",{idleTimeoutMinutes:_.idleTimeoutMinutes??15}),this.applyControlEvent({type:"terminal.entered",suspended:!0}),this.kill("idle-timeout"))})}teardown(){this.clearAllTimers(),this.completedAt||(this.completedAt=Date.now()),this.messageStream&&this.messageStream.end(),this.harnessHandle?.interrupt&&this.harnessHandle.interrupt().catch(e=>{`${this.id}${un(e)}`}),this.abortController.abort(),this.applyControlEvent({type:"terminal.entered",suspended:this.lifecycle==="suspended"})}transitionToTerminal(e,t={}){this.isActive&&(this.logDiagnostic("terminal.transition",{nextStatus:e,reason:t.reason,error:t.error,currentStatus:this._status,lifecycle:this.lifecycle,runtimeState:this.runtimeState}),this.turnInProgress=!1,t.reason&&(this.killReason=t.reason),t.error!==void 0&&(this.error=t.error),this.completedAt=Date.now(),this.applyControlEvent({type:"terminal.entered",suspended:e==="killed"&&t.reason==="idle-timeout"}),this.transition(e),this.teardown())}async consumeMessages(e){let t=0;for await(let r of e){if(!this.isActive)break;this.resetIdleTimer(),t+=1,this.harnessEvents.applyMessage(r,{pendingPlanApproval:this.pendingPlanApproval,currentPermissionMode:this.currentPermissionMode,permissionMode:this.permissionMode,planModeApproved:this.planModeApproved,pendingInputState:this.pendingInputState})}this.logDiagnostic("harness.stream.end",{messageCount:t,activeAtEnd:this.isActive,status:this._status,lifecycle:this.lifecycle,runtimeState:this.runtimeState})}controlStateSnapshot(){return{status:this._status,lifecycle:this.lifecycle,approvalState:this.approvalState,approvalExecutionState:this.approvalExecutionState,worktreeState:this.worktreeState,runtimeState:this.runtimeState,deliveryState:this.deliveryState,requestedPermissionMode:this.requestedPermissionMode,currentPermissionMode:this.currentPermissionMode,pendingPlanApproval:this.pendingPlanApproval,planApprovalContext:this.planApprovalContext,planDecisionVersion:this.planDecisionVersion,actionablePlanDecisionVersion:this.actionablePlanDecisionVersion,canonicalPlanPromptVersion:this.canonicalPlanPromptVersion,approvalPromptRequiredVersion:this.approvalPromptRequiredVersion,approvalPromptVersion:this.approvalPromptVersion,approvalPromptStatus:this.approvalPromptStatus,approvalPromptTransport:this.approvalPromptTransport,approvalPromptMessageKind:this.approvalPromptMessageKind,approvalPromptLastAttemptAt:this.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:this.approvalPromptDeliveredAt,approvalPromptFailedAt:this.approvalPromptFailedAt,planModeApproved:this.planModeApproved}}applyControlEvent(e){let t=qr(this.controlStateSnapshot(),e);this.applyControlState(t)}applyControlPatch(e){let t=Wi(this.controlStateSnapshot(),e);this.applyControlState(t)}setControlField(e,t){this.applyControlPatch({[e]:t})}applyControlState(e){let t=this.lifecycle;this.lifecycle=e.lifecycle,this.approvalState=e.approvalState,this.approvalExecutionState=e.approvalExecutionState,this.worktreeState=e.worktreeState,this.runtimeState=e.runtimeState,this.deliveryState=e.deliveryState,this.pendingPlanApproval=e.pendingPlanApproval,this.planApprovalContext=e.planApprovalContext,this.planDecisionVersion=e.planDecisionVersion,this.actionablePlanDecisionVersion=e.actionablePlanDecisionVersion,this.canonicalPlanPromptVersion=e.canonicalPlanPromptVersion,this.approvalPromptRequiredVersion=e.approvalPromptRequiredVersion,this.approvalPromptVersion=e.approvalPromptVersion,this.approvalPromptStatus=e.approvalPromptStatus,this.approvalPromptTransport=e.approvalPromptTransport,this.approvalPromptMessageKind=e.approvalPromptMessageKind,this.approvalPromptLastAttemptAt=e.approvalPromptLastAttemptAt,this.approvalPromptDeliveredAt=e.approvalPromptDeliveredAt,this.approvalPromptFailedAt=e.approvalPromptFailedAt,this.planModeApproved=e.planModeApproved,t!==this.lifecycle&&this.emit("lifecycleChange",this,this.lifecycle,t)}logDiagnostic(e,t={}){let{backendRef:r,harnessSessionId:o,...i}=t;Cd(e,{sessionId:this.id,name:this.name,status:this._status,lifecycle:this.lifecycle,runtimeState:this.runtimeState,harness:this.harnessName,hasHarnessSessionId:!!this.harnessSessionId,...Md(this.backendRef),...i})}};var _d=50,Dd=1,$d=new Set(["starting","running","completed","failed","killed"]),Ed=5,Nd=1440*60*1e3,cn=new Set(["merged","released","dismissed","no_change"]);function Od(n){let e=Number(n);return!Number.isFinite(e)||e<Dd?_d:Math.floor(e)}function Wd(n){return typeof n=="string"&&$d.has(n)}function Ld(n){let e=n.split(`
33
- `);return e.at(-1)===""&&e.pop(),e}function Gr(n){return n.backendRef?.conversationId??n.harnessSessionId}function Fd(n,e){return e&&cn.has(e)&&(!n||!cn.has(n))?e:n??e}function Bd(n,e){return e&&cn.has(e.state)&&(!n||!cn.has(n.state))?e:n??e}function Vi(n,e,t){let r=qi(n,"utf-8"),o=Ld(r);return e.full?o:o.slice(-t)}function Kd(n,e,t){if(n.status!=="starting"&&n.status!=="running")return null;let r=ve(n.id);if(!Ur(r))return null;try{return Vi(r,e,t)}catch{return null}}function qd(n){let e=se(n.duration),t=` | Cost: $${n.costUsd.toFixed(4)}`,r=n.phase?` | Phase: ${n.phase}`:"",o=n.lifecycle&&n.lifecycle!==n.phase?` | Lifecycle: ${n.lifecycle}`:"";return[`Session: ${n.name} [${n.id}] | Status: ${n.status.toUpperCase()}${r}${o}${t} | Duration: ${e}`,`${"─".repeat(60)}`].join(`
32
+ ${e}`,this.harnessHandle?.setPermissionMode))try{await this.harnessHandle.setPermissionMode("plan"),this.currentPermissionMode="plan",this.applyControlEvent({type:"permission.mode_changed",currentPermissionMode:"plan"})}catch(r){`${this.id}${it(r)}`}if(this.multiTurn&&this.messageStream)this.messageStream.push(this.harness.buildUserMessage(t,this.backendConversationId??""));else if(this.harnessHandle?.streamInput){let r=this.harness.buildUserMessage(t,this.backendConversationId??"");async function*o(){yield r}await this.harnessHandle.streamInput(o())}else throw new Error("Session does not support follow-up messages (launched in single-turn mode).")}async interrupt(){return!this.turnInProgress||!this.harnessHandle?.interrupt?!1:(await this.harnessHandle.interrupt(),!0)}async submitPendingInputOption(e,t){if(!this.pendingInputState||!this.harnessHandle?.submitPendingInputOption)return!1;let r=this.pendingInputState.activeQuestionIndex,o=this.pendingInputState.questions?.length,i=await this.harnessHandle.submitPendingInputOption(e,t);return i&&(this.lastPendingInputSubmissionRequiresMore=r!=null&&o!=null&&r+1<o,this.waitingForInputFired=!1),i}canSubmitPendingInputOption(){return!!(this.pendingInputState&&this.harnessHandle?.submitPendingInputOption)}setPendingInputState(e){this.pendingInputState=e,e||(this.lastPendingInputSubmissionRequiresMore=!1)}pendingInputSubmissionRequiresMore(){return this.lastPendingInputSubmissionRequiresMore}async submitPendingInputText(e){if(!this.pendingInputState||!this.harnessHandle?.submitPendingInputText)return!1;let t=this.pendingInputState.activeQuestionIndex,r=this.pendingInputState.questions?.length,o=await this.harnessHandle.submitPendingInputText(e);return o&&(this.lastPendingInputSubmissionRequiresMore=t!=null&&r!=null&&t+1<r,this.waitingForInputFired=!1),o}switchPermissionMode(e){this.pendingModeSwitch=e}get isActive(){return this._status==="starting"||this._status==="running"}kill(e){this.transitionToTerminal("killed",{reason:e})}async waitForTeardown(){await(this.teardownPromise??Promise.resolve())}complete(e="done"){this.transitionToTerminal("completed",{reason:e})}incrementAutoRespond(){this.autoRespondCount++}resetAutoRespond(){this.autoRespondCount=0}getOutput(e){return e===void 0?this.outputBuffer.slice():this.outputBuffer.slice(-e)}resetIdleTimer(){if(!this.multiTurn)return;let e=(_.idleTimeoutMinutes??15)*60*1e3;this.setTimer("idle",e,()=>{this._status==="running"&&(this.logDiagnostic("idle_timeout.fire",{idleTimeoutMinutes:_.idleTimeoutMinutes??15}),this.applyControlEvent({type:"terminal.entered",suspended:!0}),this.kill("idle-timeout"))})}teardown(){if(this.teardownPromise)return;this.clearAllTimers(),this.completedAt||(this.completedAt=Date.now()),this.messageStream&&this.messageStream.end(),this.harnessHandle?.interrupt&&this.harnessHandle.interrupt().catch(t=>{`${this.id}${it(t)}`});let e=this.harnessHandle?.close?this.harnessHandle.close().catch(t=>{`${this.id}${it(t)}`}):Promise.resolve();this.teardownPromise=e,this.abortController.abort(),this.applyControlEvent({type:"terminal.entered",suspended:this.lifecycle==="suspended"})}transitionToTerminal(e,t={}){this.isActive&&(this.logDiagnostic("terminal.transition",{nextStatus:e,reason:t.reason,error:t.error,currentStatus:this._status,lifecycle:this.lifecycle,runtimeState:this.runtimeState}),this.turnInProgress=!1,t.reason&&(this.killReason=t.reason),t.error!==void 0&&(this.error=t.error),this.completedAt=Date.now(),this.applyControlEvent({type:"terminal.entered",suspended:e==="killed"&&t.reason==="idle-timeout"}),this.teardown(),this.transition(e))}async consumeMessages(e){let t=0;for await(let r of e){if(!this.isActive)break;this.resetIdleTimer(),t+=1,this.harnessEvents.applyMessage(r,{pendingPlanApproval:this.pendingPlanApproval,currentPermissionMode:this.currentPermissionMode,permissionMode:this.permissionMode,planModeApproved:this.planModeApproved,pendingInputState:this.pendingInputState})}this.logDiagnostic("harness.stream.end",{messageCount:t,activeAtEnd:this.isActive,status:this._status,lifecycle:this.lifecycle,runtimeState:this.runtimeState})}controlStateSnapshot(){return{status:this._status,lifecycle:this.lifecycle,approvalState:this.approvalState,approvalExecutionState:this.approvalExecutionState,worktreeState:this.worktreeState,runtimeState:this.runtimeState,deliveryState:this.deliveryState,requestedPermissionMode:this.requestedPermissionMode,currentPermissionMode:this.currentPermissionMode,pendingPlanApproval:this.pendingPlanApproval,planApprovalContext:this.planApprovalContext,planDecisionVersion:this.planDecisionVersion,actionablePlanDecisionVersion:this.actionablePlanDecisionVersion,canonicalPlanPromptVersion:this.canonicalPlanPromptVersion,approvalPromptRequiredVersion:this.approvalPromptRequiredVersion,approvalPromptVersion:this.approvalPromptVersion,approvalPromptStatus:this.approvalPromptStatus,approvalPromptTransport:this.approvalPromptTransport,approvalPromptMessageKind:this.approvalPromptMessageKind,approvalPromptLastAttemptAt:this.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:this.approvalPromptDeliveredAt,approvalPromptFailedAt:this.approvalPromptFailedAt,planModeApproved:this.planModeApproved}}applyControlEvent(e){let t=qr(this.controlStateSnapshot(),e);this.applyControlState(t)}applyControlPatch(e){let t=Wi(this.controlStateSnapshot(),e);this.applyControlState(t)}setControlField(e,t){this.applyControlPatch({[e]:t})}applyControlState(e){let t=this.lifecycle;this.lifecycle=e.lifecycle,this.approvalState=e.approvalState,this.approvalExecutionState=e.approvalExecutionState,this.worktreeState=e.worktreeState,this.runtimeState=e.runtimeState,this.deliveryState=e.deliveryState,this.pendingPlanApproval=e.pendingPlanApproval,this.planApprovalContext=e.planApprovalContext,this.planDecisionVersion=e.planDecisionVersion,this.actionablePlanDecisionVersion=e.actionablePlanDecisionVersion,this.canonicalPlanPromptVersion=e.canonicalPlanPromptVersion,this.approvalPromptRequiredVersion=e.approvalPromptRequiredVersion,this.approvalPromptVersion=e.approvalPromptVersion,this.approvalPromptStatus=e.approvalPromptStatus,this.approvalPromptTransport=e.approvalPromptTransport,this.approvalPromptMessageKind=e.approvalPromptMessageKind,this.approvalPromptLastAttemptAt=e.approvalPromptLastAttemptAt,this.approvalPromptDeliveredAt=e.approvalPromptDeliveredAt,this.approvalPromptFailedAt=e.approvalPromptFailedAt,this.planModeApproved=e.planModeApproved,t!==this.lifecycle&&this.emit("lifecycleChange",this,this.lifecycle,t)}logDiagnostic(e,t={}){let{backendRef:r,harnessSessionId:o,...i}=t;Cd(e,{sessionId:this.id,name:this.name,status:this._status,lifecycle:this.lifecycle,runtimeState:this.runtimeState,harness:this.harnessName,hasHarnessSessionId:!!this.harnessSessionId,...Md(this.backendRef),...i})}};var _d=50,Dd=1,$d=new Set(["starting","running","completed","failed","killed"]),Ed=5,Nd=1440*60*1e3,cn=new Set(["merged","released","dismissed","no_change"]);function Od(n){let e=Number(n);return!Number.isFinite(e)||e<Dd?_d:Math.floor(e)}function Wd(n){return typeof n=="string"&&$d.has(n)}function Fd(n){let e=n.split(`
33
+ `);return e.at(-1)===""&&e.pop(),e}function Gr(n){return n.backendRef?.conversationId??n.harnessSessionId}function Ld(n,e){return e&&cn.has(e)&&(!n||!cn.has(n))?e:n??e}function Bd(n,e){return e&&cn.has(e.state)&&(!n||!cn.has(n.state))?e:n??e}function Vi(n,e,t){let r=qi(n,"utf-8"),o=Fd(r);return e.full?o:o.slice(-t)}function Kd(n,e,t){if(n.status!=="starting"&&n.status!=="running")return null;let r=ve(n.id);if(!Ur(r))return null;try{return Vi(r,e,t)}catch{return null}}function qd(n){let e=se(n.duration),t=` | Cost: $${n.costUsd.toFixed(4)}`,r=n.phase?` | Phase: ${n.phase}`:"",o=n.lifecycle&&n.lifecycle!==n.phase?` | Lifecycle: ${n.lifecycle}`:"";return[`Session: ${n.name} [${n.id}] | Status: ${n.status.toUpperCase()}${r}${o}${t} | Duration: ${e}`,`${"─".repeat(60)}`].join(`
34
34
  `)}function Ui(n,e){let t=n.name||n.sessionId||Gr(n)||"unknown",r=n.lifecycle?` | Phase: ${n.lifecycle}`:"";return[`Session: ${t} | Status: ${n.status.toUpperCase()}${r} | Cost: $${n.costUsd.toFixed(4)}`,e,`${"─".repeat(60)}`].join(`
35
35
  `)}function Vd(n){return`(retrieved from ${n.outputPath} — evicted from runtime cache — showing persisted output)`}function Ud(n){return n.outputPath?`(persisted session metadata recovered; output file is unavailable at ${n.outputPath})`:"(persisted session metadata recovered; no output file was recorded before the runtime was interrupted)"}function Ki(n,e){let t=Ui(n,Ud(n)),r=Gr(n),o=r?`
36
36
  Backend session: ${r}`:"";return`${t}
@@ -49,50 +49,50 @@ Plan file: ${o.planFilePath}
49
49
  ${u}
50
50
  ${d}`}}catch{}return l}function fn(n,e="all",t,r={}){let o=n.listPersistedSessions()??[],s=jd(n.list("all"),o);if(e!=="all"&&(s=s.filter(a=>a.status===e)),t&&(s=s.filter(a=>a.originChannel===t)),r.full){let a=Date.now()-Nd;s=s.filter(l=>(l.startedAt??0)>=a)}else s=s.slice(0,Ed);return s.length===0?"No sessions found.":s.map(a=>wi(a)).join(`
51
51
 
52
- `)}function jd(n,e){let t=new Map;for(let r of e){if(!Wd(r.status))continue;let o=r.completedAt??Date.now(),i=r.createdAt??o,s=Gr(r),a=r.sessionId??`persisted:${s??r.harnessSessionId}`;t.set(a,{id:r.sessionId??s??r.harnessSessionId,name:r.name||r.sessionId||s||r.harnessSessionId,status:r.status,startedAt:r.createdAt??0,completedAt:r.completedAt,duration:Math.max(0,o-i),prompt:r.prompt??"",workdir:r.workdir??"(unknown)",costUsd:r.costUsd??0,multiTurn:!0,phase:r.lifecycle??r.status,lifecycle:r.lifecycle,resumable:r.resumable,harness:r.harness,model:r.model,backendRef:r.backendRef,harnessSessionId:r.harnessSessionId,requestedPermissionMode:r.requestedPermissionMode,currentPermissionMode:r.currentPermissionMode,approvalExecutionState:r.approvalExecutionState,originChannel:r.originChannel,originThreadId:r.originThreadId,worktreePath:r.worktreePath,worktreeBranch:r.worktreeBranch,worktreeStrategy:r.worktreeStrategy,worktreeState:r.worktreeState,worktreeLifecycle:r.worktreeLifecycle,worktreeMerged:r.worktreeMerged,worktreeMergedAt:r.worktreeMergedAt,worktreePrUrl:r.worktreePrUrl,recovered:!0,runtimeRecovery:r.runtimeRecovery})}for(let r of n){let o=t.get(r.id);t.set(r.id,{id:r.id,name:r.name,status:r.status,startedAt:r.startedAt,completedAt:r.completedAt,duration:r.duration,prompt:r.prompt,workdir:r.originalWorkdir??r.workdir,costUsd:r.costUsd,multiTurn:r.multiTurn,phase:r.phase,lifecycle:r.lifecycle,resumable:r.isExplicitlyResumable,harness:r.harnessName,model:r.model,backendRef:r.backendRef,harnessSessionId:r.harnessSessionId,requestedPermissionMode:r.requestedPermissionMode,currentPermissionMode:r.currentPermissionMode,approvalExecutionState:r.approvalExecutionState,originChannel:r.originChannel,originThreadId:r.originThreadId,worktreePath:r.worktreePath,worktreeBranch:r.worktreeBranch,worktreeStrategy:r.worktreeStrategy,worktreeState:Fd(r.worktreeState,o?.worktreeState),worktreeLifecycle:Bd(r.worktreeLifecycle,o?.worktreeLifecycle),worktreeMerged:r.worktreeMerged??o?.worktreeMerged,worktreeMergedAt:r.worktreeMergedAt??o?.worktreeMergedAt,worktreePrUrl:r.worktreePrUrl??o?.worktreePrUrl,recovered:!1})}return[...t.values()].sort((r,o)=>(o.startedAt??0)-(r.startedAt??0))}function zd(n){if(!n||typeof n!="object")return"all";let e=n.status;switch(e){case"running":case"completed":case"failed":case"killed":case"all":return e;default:return"all"}}function Gi(n){return{name:"agent_sessions",description:"List coding agent sessions with their status and progress. By default, shows the 5 most recent sessions; set `full` to show all sessions from the last 24 hours.",parameters:c.Object({status:c.Optional(c.Union([c.Literal("all"),c.Literal("running"),c.Literal("completed"),c.Literal("failed"),c.Literal("killed")],{description:'Filter by status (default "all")'})),full:c.Optional(c.Boolean({description:"Show all sessions from the last 24h instead of just the most recent 5"}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};let r=zd(t),o=n?.workspaceDir?$e(n.workspaceDir):void 0,i=!!(t&&typeof t=="object"&&t.full===!0);return{content:[{type:"text",text:fn(S,r,o,{full:i})}]}}}}function gn(n,e,t){let r=n.resolve(e);if(!r){let o=n.getPersistedSession(e);if(!o)return`Error: Session "${e}" not found.`;if(o.status==="killed"&&o.lifecycle==="suspended"){let i=t==="completed";if(n.updatePersistedSession(e,{status:i?"completed":"killed",lifecycle:"terminal",runtimeState:"stopped",resumable:!1,killReason:i?"done":"user"}))return i?`Recovered session ${o.name} [${o.sessionId??o.harnessSessionId}] marked as completed. No live process was running.`:`Recovered session ${o.name} [${o.sessionId??o.harnessSessionId}] dismissed. No live process was running.`}return`Session ${o.name} [${o.sessionId??o.harnessSessionId}] is a persisted ${o.status} record with no live process to kill.`}return r.status==="completed"||r.status==="failed"||r.status==="killed"?`Session ${r.name} [${r.id}] is already ${r.status}. No action needed.`:t==="completed"?(r.complete(),`Session ${r.name} [${r.id}] marked as completed.`):(n.kill(r.id),`Session ${r.name} [${r.id}] has been terminated.`)}function Hd(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.session!="string"?!1:e.reason===void 0?!0:e.reason==="completed"||e.reason==="killed"}function ji(n){return{name:"agent_kill",description:"Terminate or complete a running coding agent session by name or ID. Use reason='completed' to mark a session as successfully completed instead of killed.",parameters:c.Object({session:c.String({description:"Session name or ID to terminate"}),reason:c.Optional(c.Union([c.Literal("completed"),c.Literal("killed")],{description:"Reason for closing the session. 'completed' marks it as successfully done (sends ✅ notification). 'killed' (default) terminates it."}))}),async execute(e,t){return S?Hd(t)?{content:[{type:"text",text:gn(S,t.session,t.reason)}]}:{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, reason? }."}]}:{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]}}}}function Qd(n){return!n||typeof n!="object"?!1:typeof n.session=="string"}function hn(n){return{name:"agent_output",description:"Show recent output from a coding agent session (by name or ID).",parameters:c.Object({session:c.String({description:"Session name or ID to get output from"}),lines:c.Optional(c.Number({description:"Number of recent lines to show (default 50)"})),full:c.Optional(c.Boolean({description:"Show all available output"}))}),async execute(e,t){return S?Qd(t)?{content:[{type:"text",text:mn(S,t.session,{full:t.full,lines:t.lines})}]}:{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, lines?, full? }."}]}:{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]}}}}var Yd=10;function zr(n){return n instanceof Error?n.message:String(n)}function Pe(n){return D(n)??n.harnessSessionId??"unknown-session"}function Jd(n){if(!(!n.worktreeStrategy||n.worktreeStrategy==="off"))return zt(n)??D(n)??C(n)}function zi(n){return n.status!=="running"&&!!n.pendingPlanApproval&&!!C(n)}function Xd(n){let e=n.trim().toLowerCase().replace(/[.!?]+$/g,"").trim();if(e==="approve"||e==="approved")return"approve";if(e==="revise"||e==="request changes"||e==="changes requested")return"revise";if(e==="reject"||e==="rejected")return"reject"}function it(n,e,t){let r=e==="completed"?`This session is closed by default. Launch a fresh session, or fork from prior context with agent_launch(resume_session_id='${Pe(n)}', fork_session=true, prompt='<new task>').`:e==="legacy_non_resumable"?`Persisted historical backend state is intentionally non-resumable here. Launch fresh, or fork with agent_launch(resume_session_id='${Pe(n)}', fork_session=true, prompt='<new task>').`:e==="missing_backend_state"?`No resumable backend state is available. Launch a fresh session, or fork from prior context with agent_launch(resume_session_id='${Pe(n)}', fork_session=true, prompt='<new task>').`:`Use agent_respond(session='${Pe(n)}', message='<next instruction>') to continue the running session.`,o=t?` ${t}`:"";return{text:`Resume unavailable for session ${n.name} [${Pe(n)}] (${e}).${o} ${r}`,isError:!0}}async function Hi(n,e,t){try{let r={prompt:e.prompt,sessionIdOverride:zt(e),workdir:e.workdir,name:e.name,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,worktreeStrategy:e.worktreeStrategy,multiTurn:!0,originChannel:e.originChannel,originThreadId:e.originThreadId,originAgentId:e.originAgentId,originSessionKey:e.originSessionKey,route:e.route,permissionMode:e.currentPermissionMode,requestedPermissionMode:e.requestedPermissionMode??e.currentPermissionMode,planApproval:e.planApproval,codexApprovalPolicy:e.codexApprovalPolicy,harness:"harnessName"in e?e.harnessName:e.harness},o=await n.spawnAndAwaitRunning(r,{notifyLaunch:!1});return n.notifySession(o,`▶️ [${o.name}] Relaunched fresh`,"notification",`agent-respond-relaunched:${o.id}:${o.startedAt}`),{text:`Session ${e.name} was relaunched fresh — it was killed during startup before the harness initialized. New session: ${o.name} [${o.id}].`}}catch(r){return{text:`Error relaunching session ${e.name} [${Pe(e)}]: ${zr(r)}`,isError:!0}}}var Zd=`[SYSTEM: The user has approved your plan. Exit plan mode immediately and implement the changes with full permissions. Do not ask for further confirmation.]
52
+ `)}function jd(n,e){let t=new Map;for(let r of e){if(!Wd(r.status))continue;let o=r.completedAt??Date.now(),i=r.createdAt??o,s=Gr(r),a=r.sessionId??`persisted:${s??r.harnessSessionId}`;t.set(a,{id:r.sessionId??s??r.harnessSessionId,name:r.name||r.sessionId||s||r.harnessSessionId,status:r.status,startedAt:r.createdAt??0,completedAt:r.completedAt,duration:Math.max(0,o-i),prompt:r.prompt??"",workdir:r.workdir??"(unknown)",costUsd:r.costUsd??0,multiTurn:!0,phase:r.lifecycle??r.status,lifecycle:r.lifecycle,resumable:r.resumable,harness:r.harness,model:r.model,backendRef:r.backendRef,harnessSessionId:r.harnessSessionId,requestedPermissionMode:r.requestedPermissionMode,currentPermissionMode:r.currentPermissionMode,approvalExecutionState:r.approvalExecutionState,originChannel:r.originChannel,originThreadId:r.originThreadId,worktreePath:r.worktreePath,worktreeBranch:r.worktreeBranch,worktreeStrategy:r.worktreeStrategy,worktreeState:r.worktreeState,worktreeLifecycle:r.worktreeLifecycle,worktreeMerged:r.worktreeMerged,worktreeMergedAt:r.worktreeMergedAt,worktreePrUrl:r.worktreePrUrl,recovered:!0,runtimeRecovery:r.runtimeRecovery})}for(let r of n){let o=t.get(r.id);t.set(r.id,{id:r.id,name:r.name,status:r.status,startedAt:r.startedAt,completedAt:r.completedAt,duration:r.duration,prompt:r.prompt,workdir:r.originalWorkdir??r.workdir,costUsd:r.costUsd,multiTurn:r.multiTurn,phase:r.phase,lifecycle:r.lifecycle,resumable:r.isExplicitlyResumable,harness:r.harnessName,model:r.model,backendRef:r.backendRef,harnessSessionId:r.harnessSessionId,requestedPermissionMode:r.requestedPermissionMode,currentPermissionMode:r.currentPermissionMode,approvalExecutionState:r.approvalExecutionState,originChannel:r.originChannel,originThreadId:r.originThreadId,worktreePath:r.worktreePath,worktreeBranch:r.worktreeBranch,worktreeStrategy:r.worktreeStrategy,worktreeState:Ld(r.worktreeState,o?.worktreeState),worktreeLifecycle:Bd(r.worktreeLifecycle,o?.worktreeLifecycle),worktreeMerged:r.worktreeMerged??o?.worktreeMerged,worktreeMergedAt:r.worktreeMergedAt??o?.worktreeMergedAt,worktreePrUrl:r.worktreePrUrl??o?.worktreePrUrl,recovered:!1})}return[...t.values()].sort((r,o)=>(o.startedAt??0)-(r.startedAt??0))}function zd(n){if(!n||typeof n!="object")return"all";let e=n.status;switch(e){case"running":case"completed":case"failed":case"killed":case"all":return e;default:return"all"}}function Gi(n){return{name:"agent_sessions",description:"List coding agent sessions with their status and progress. By default, shows the 5 most recent sessions; set `full` to show all sessions from the last 24 hours.",parameters:c.Object({status:c.Optional(c.Union([c.Literal("all"),c.Literal("running"),c.Literal("completed"),c.Literal("failed"),c.Literal("killed")],{description:'Filter by status (default "all")'})),full:c.Optional(c.Boolean({description:"Show all sessions from the last 24h instead of just the most recent 5"}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};let r=zd(t),o=n?.workspaceDir?$e(n.workspaceDir):void 0,i=!!(t&&typeof t=="object"&&t.full===!0);return{content:[{type:"text",text:fn(S,r,o,{full:i})}]}}}}function gn(n,e,t){let r=n.resolve(e);if(!r){let o=n.getPersistedSession(e);if(!o)return`Error: Session "${e}" not found.`;if(o.status==="killed"&&o.lifecycle==="suspended"){let i=t==="completed";if(n.updatePersistedSession(e,{status:i?"completed":"killed",lifecycle:"terminal",runtimeState:"stopped",resumable:!1,killReason:i?"done":"user"}))return i?`Recovered session ${o.name} [${o.sessionId??o.harnessSessionId}] marked as completed. No live process was running.`:`Recovered session ${o.name} [${o.sessionId??o.harnessSessionId}] dismissed. No live process was running.`}return`Session ${o.name} [${o.sessionId??o.harnessSessionId}] is a persisted ${o.status} record with no live process to kill.`}return r.status==="completed"||r.status==="failed"||r.status==="killed"?`Session ${r.name} [${r.id}] is already ${r.status}. No action needed.`:t==="completed"?(r.complete(),`Session ${r.name} [${r.id}] marked as completed.`):(n.kill(r.id),`Session ${r.name} [${r.id}] has been terminated.`)}function Hd(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.session!="string"?!1:e.reason===void 0?!0:e.reason==="completed"||e.reason==="killed"}function ji(n){return{name:"agent_kill",description:"Terminate or complete a running coding agent session by name or ID. Use reason='completed' to mark a session as successfully completed instead of killed.",parameters:c.Object({session:c.String({description:"Session name or ID to terminate"}),reason:c.Optional(c.Union([c.Literal("completed"),c.Literal("killed")],{description:"Reason for closing the session. 'completed' marks it as successfully done (sends ✅ notification). 'killed' (default) terminates it."}))}),async execute(e,t){return S?Hd(t)?{content:[{type:"text",text:gn(S,t.session,t.reason)}]}:{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, reason? }."}]}:{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]}}}}function Qd(n){return!n||typeof n!="object"?!1:typeof n.session=="string"}function hn(n){return{name:"agent_output",description:"Show recent output from a coding agent session (by name or ID).",parameters:c.Object({session:c.String({description:"Session name or ID to get output from"}),lines:c.Optional(c.Number({description:"Number of recent lines to show (default 50)"})),full:c.Optional(c.Boolean({description:"Show all available output"}))}),async execute(e,t){return S?Qd(t)?{content:[{type:"text",text:mn(S,t.session,{full:t.full,lines:t.lines})}]}:{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, lines?, full? }."}]}:{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]}}}}var Yd=10;function zr(n){return n instanceof Error?n.message:String(n)}function Pe(n){return D(n)??n.harnessSessionId??"unknown-session"}function Jd(n){if(!(!n.worktreeStrategy||n.worktreeStrategy==="off"))return Ht(n)??D(n)??C(n)}function zi(n){return n.status!=="running"&&!!n.pendingPlanApproval&&!!C(n)}function Xd(n){let e=n.trim().toLowerCase().replace(/[.!?]+$/g,"").trim();if(e==="approve"||e==="approved")return"approve";if(e==="revise"||e==="request changes"||e==="changes requested")return"revise";if(e==="reject"||e==="rejected")return"reject"}function st(n,e,t){let r=e==="completed"?`This session is closed by default. Launch a fresh session, or fork from prior context with agent_launch(resume_session_id='${Pe(n)}', fork_session=true, prompt='<new task>').`:e==="legacy_non_resumable"?`Persisted historical backend state is intentionally non-resumable here. Launch fresh, or fork with agent_launch(resume_session_id='${Pe(n)}', fork_session=true, prompt='<new task>').`:e==="missing_backend_state"?`No resumable backend state is available. Launch a fresh session, or fork from prior context with agent_launch(resume_session_id='${Pe(n)}', fork_session=true, prompt='<new task>').`:`Use agent_respond(session='${Pe(n)}', message='<next instruction>') to continue the running session.`,o=t?` ${t}`:"";return{text:`Resume unavailable for session ${n.name} [${Pe(n)}] (${e}).${o} ${r}`,isError:!0}}async function Hi(n,e,t){try{let r={prompt:e.prompt,sessionIdOverride:Ht(e),workdir:e.workdir,name:e.name,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,worktreeStrategy:e.worktreeStrategy,multiTurn:!0,originChannel:e.originChannel,originThreadId:e.originThreadId,originAgentId:e.originAgentId,originSessionKey:e.originSessionKey,route:e.route,permissionMode:e.currentPermissionMode,requestedPermissionMode:e.requestedPermissionMode??e.currentPermissionMode,planApproval:e.planApproval,codexApprovalPolicy:e.codexApprovalPolicy,harness:"harnessName"in e?e.harnessName:e.harness},o=await n.spawnAndAwaitRunning(r,{notifyLaunch:!1});return n.notifySession(o,`▶️ [${o.name}] Relaunched fresh`,"notification",`agent-respond-relaunched:${o.id}:${o.startedAt}`),{text:`Session ${e.name} was relaunched fresh — it was killed during startup before the harness initialized. New session: ${o.name} [${o.id}].`}}catch(r){return{text:`Error relaunching session ${e.name} [${Pe(e)}]: ${zr(r)}`,isError:!0}}}var Zd=`[SYSTEM: The user has approved your plan. Exit plan mode immediately and implement the changes with full permissions. Do not ask for further confirmation.]
53
53
 
54
- `;function Qi(n){let e=n?.replace(/\s+/g," ").trim();if(e)return q(e,240)}function jr(n){if(n.approvalState==="changes_requested"&&!yn(n))return`Plan changes were already requested for session ${n.name}. Wait for the revised plan before approving.`;if(n.approvalState==="rejected")return`Plan for session ${n.name} was already rejected.`}function yn(n){return n.pendingPlanApproval?(n.approvalState==="changes_requested"?n.actionablePlanDecisionVersion:n.actionablePlanDecisionVersion??n.planDecisionVersion)>0:!1}function eu(n){return jr(n)?!1:yn(n)||n.currentPermissionMode==="plan"}function tu(n,e){let t=n.updatePersistedSession;if(typeof t!="function")return;let r=e.controlStateSnapshot();t.call(n,e.id,{lifecycle:r.lifecycle,approvalState:r.approvalState,approvalExecutionState:r.approvalExecutionState,runtimeState:r.runtimeState,requestedPermissionMode:r.requestedPermissionMode,currentPermissionMode:r.currentPermissionMode,pendingPlanApproval:r.pendingPlanApproval,planApprovalContext:r.planApprovalContext,planDecisionVersion:r.planDecisionVersion,actionablePlanDecisionVersion:r.actionablePlanDecisionVersion,planModeApproved:r.planModeApproved,approvalRationale:e.approvalRationale})}function nu(n){return(n.planDecisionVersion??0)+1}function Yi(n,e){let t={approvalState:e,lifecycle:e==="rejected"?"terminal":"awaiting_user_input",pendingPlanApproval:!1,planApprovalContext:void 0,planDecisionVersion:nu(n),actionablePlanDecisionVersion:void 0,canonicalPlanPromptVersion:void 0,approvalPromptRequiredVersion:void 0,approvalPromptVersion:void 0,approvalPromptStatus:"not_sent",approvalPromptTransport:"none",approvalPromptMessageKind:"none",approvalPromptLastAttemptAt:void 0,approvalPromptDeliveredAt:void 0,approvalPromptFailedAt:void 0};return e==="rejected"&&(t.runtimeState="stopped"),t}function Ji(n,e){let t=n;typeof t.applyControlPatch=="function"&&t.applyControlPatch(e),Object.assign(n,e)}function Hr(n,e){let t=n.resolve(e),r=t?void 0:n.getPersistedSession(e),o=t??r,i=o?.name??e;if(n.clearPlanDecisionTokens?.(e),!o)return{text:`Plan rejected for [${i}].`,isError:!1};let s=Yi(o,"rejected");return t?(Ji(t,s),n.updatePersistedSession?.(e,s),n.kill(t.id,"user"),{text:`Plan rejected for [${t.name}]. Session stopped.`}):(n.updatePersistedSession?.(e,s),{text:`Plan rejected for [${i}]. Session remains stopped.`})}function Qr(n,e){let t=n.resolve(e),r=t?void 0:n.getPersistedSession(e),o=t??r,i=o?.name??e;if(n.clearPlanDecisionTokens?.(e),o){let s=Yi(o,"changes_requested");t&&Ji(t,s),n.updatePersistedSession?.(e,s)}return{text:`Type your revision feedback for [${i}] and I'll forward it to the agent.`}}async function ru(n,e,t,r={}){let o=ke(e);if(!(o.kind==="resume"||zi(e)))return;let s=!!(r.approve&&eu(e)),a=s?Qi(r.approvalRationale):void 0;try{if(o.kind!=="resume")return o.kind==="relaunch"?Hi(n,e,t):it(e,o.reason);let l={prompt:s?Zd+t:t,sessionIdOverride:o.stableSessionId,workdir:e.workdir,name:e.name,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,resumeSessionId:o.resumeSessionId,resumeWorktreeFrom:Jd(e),worktreeStrategy:e.worktreeStrategy,worktreeBaseBranch:e.worktreeBaseBranch,worktreePrTargetRepo:e.worktreePrTargetRepo,multiTurn:!0,originChannel:e.originChannel,originThreadId:e.originThreadId,originAgentId:e.originAgentId,originSessionKey:e.originSessionKey,route:e.route,permissionMode:s?"bypassPermissions":e.currentPermissionMode,requestedPermissionMode:e.requestedPermissionMode??e.currentPermissionMode,planApproval:e.planApproval,codexApprovalPolicy:e.codexApprovalPolicy,pendingPlanApproval:s?!1:e.pendingPlanApproval,planApprovalContext:e.planApprovalContext,planDecisionVersion:s?(e.actionablePlanDecisionVersion??e.planDecisionVersion)+1:e.planDecisionVersion,actionablePlanDecisionVersion:s?void 0:e.actionablePlanDecisionVersion,canonicalPlanPromptVersion:e.canonicalPlanPromptVersion,approvalPromptRequiredVersion:e.approvalPromptRequiredVersion,approvalPromptVersion:e.approvalPromptVersion,approvalPromptStatus:e.approvalPromptStatus,approvalPromptTransport:e.approvalPromptTransport,approvalPromptMessageKind:e.approvalPromptMessageKind,approvalPromptLastAttemptAt:e.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:e.approvalPromptDeliveredAt,approvalPromptFailedAt:e.approvalPromptFailedAt,...s?{approvalState:"approved",approvalExecutionState:"approved_then_implemented",approvalRationale:a,planModeApproved:!0}:{},harness:"harnessName"in e?e.harnessName:e.harness},d=await n.spawnAndAwaitRunning(l,{notifyLaunch:!1});return s?(n.notifySession(d,`👍 [${d.name}] Plan approved (resumed)`,"plan-approved",`agent-respond-plan-approved-resumed:${d.id}:${d.startedAt}:${o.resumeSessionId}:v${e.planDecisionVersion??"unknown"}`),{text:`Plan approved for session ${d.name} [${d.id}]. Session resumed in bypassPermissions mode. Use agent_output to see the response.`}):(n.notifyResumedLaunch(d),{text:`Resume started for session ${d.name} [${d.id}]. Use agent_output to see the response.`})}catch(l){return it(e,"missing_backend_state",`Backend resume failed: ${zr(l)}`)}}async function Q(n,e){let t=n.resolve(e.session),r=t?void 0:n.getPersistedSession(e.session);if(!t&&!r)return{text:`Error: Session "${e.session}" not found.`,isError:!0};let o=t??r,i=o.status==="running"?{kind:"direct"}:ke(o),s=!e.approve&&o.lifecycle==="awaiting_plan_decision"&&o.pendingPlanApproval&&e.userInitiated?Xd(e.message):void 0;if(s==="approve")return Q(n,{...e,message:"Approved. Go ahead.",approve:!0});if(s==="revise")return Qr(n,t?.id??r?.sessionId??e.session);if(s==="reject")return Hr(n,t?.id??r?.sessionId??e.session);if(e.approve){let l=jr(o);if(l)return{text:l,isError:!0}}if(i.kind==="resume"||zi(o)){let l=await ru(n,o,e.message,{approve:e.approve,approvalRationale:e.approvalRationale});if(l)return l}else{if(i.kind==="relaunch")return Hi(n,o,e.message);if(i.kind==="unavailable")return it(o,i.reason)}if(!t)return ot(r)?it(r,"completed"):{text:`Error: Session ${r.name} [${Pe(r)}] is not running (status: ${r.status}). Cannot send a message to a non-running session.`,isError:!0};if(t.status!=="running")return ot(t)?it(t,"completed"):{text:`Error: Session ${t.name} [${t.id}] is not running (status: ${t.status}). Cannot send a message to a non-running session.`,isError:!0};let a=_.maxAutoResponds??Yd;if(e.userInitiated)t.resetAutoRespond();else if(t.autoRespondCount>=a)return{text:`⚠️ Auto-respond limit reached (${t.autoRespondCount}/${a}). Ask the user to provide the answer for session ${t.name}. Then call agent_respond with their answer and set userInitiated: true to reset the counter.`};try{if(e.approve){let y=jr(t);if(y)return{text:y,isError:!0}}let l=t.pendingInputState?.activeQuestionIndex,d=t.pendingInputState?.questions?.length;if(!e.approve&&t.pendingInputState?.allowsFreeText&&await t.submitPendingInputText?.(e.message)===!0){if(e.userInitiated){let R=q(e.message,100);n.notifySession(t,`↪️ [${t.name}] "${R}"`,"agent-respond")}e.userInitiated||t.incrementAutoRespond();let y=q(e.message,80),w=l!=null&&d!=null&&l+1<d;return{text:[w?`Pending input question answered for session ${t.name} [${t.id}]; more input is required.`:`Pending input request submitted for session ${t.name} [${t.id}].`,` Message: "${y}"`,w?"The next question is being delivered to the user.":"Use agent_output to see the response."].join(`
55
- `)}}let f=!1;e.interrupt&&(f=await t.interrupt());let h=!!(e.approve&&yn(t)),k=h?Qi(e.approvalRationale):void 0,g="";if(e.approve&&yn(t)?(t.switchPermissionMode("bypassPermissions"),t.approvalRationale=k):e.approve&&t.currentPermissionMode==="default"?t.switchPermissionMode("bypassPermissions"):e.approve&&t.currentPermissionMode==="bypassPermissions"?g=`
56
- ℹ️ approve=true was set but session is already in bypassPermissions mode.`:e.approve?g=`
57
- ⚠️ approve=true was set but session has no pending plan approval.`:(t.pendingPlanApproval||t.approvalState==="changes_requested")&&(g=`
58
- ℹ️ Session has a pending plan — sending as revision feedback. The agent will revise and re-submit. Set approve=true to approve instead.`),await t.sendMessage(e.message),h&&tu(n,t),h)n.notifySession(t,`👍 [${t.name}] Plan approved`,"plan-approved");else if(e.userInitiated){let y=q(e.message,100);n.notifySession(t,`↪️ [${t.name}] "${y}"`,"agent-respond")}e.userInitiated||t.incrementAutoRespond();let p=q(e.message,80);return h?{text:`Plan approved for session ${t.name} [${t.id}]. Use agent_output to see the response.`}:{text:[`Message sent to session ${t.name} [${t.id}].`,f?" (redirected active turn first)":e.interrupt?" (no active turn to interrupt)":"",` Message: "${p}"`,g,"Use agent_output to see the response."].filter(Boolean).join(`
59
- `)}}catch(l){return{text:`Error sending message to session ${t.name} [${t.id}]: ${zr(l)}`,isError:!0}}}function ou(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.session=="string"&&typeof e.message=="string"&&(e.approval_rationale===void 0||typeof e.approval_rationale=="string")}function Xi(n){return{name:"agent_respond",description:"Send a follow-up message to a running coding agent session. The session must be running. All sessions are multi-turn.",parameters:c.Object({session:c.String({description:"Session name or ID to respond to"}),message:c.String({description:"The message to send to the session"}),interrupt:c.Optional(c.Boolean({description:"If true, interrupt the current turn before sending the message. Useful to redirect the session mid-response."})),userInitiated:c.Optional(c.Boolean({description:"Set to true when the message comes from the user (not auto-generated). Resets the auto-respond counter and bypasses the auto-respond limit."})),approve:c.Optional(c.Boolean({description:"Set to true to escalate session permissions to bypassPermissions. Works in two scenarios: (1) approve a pending plan in plan mode, or (2) escalate a default-mode session to skip remaining OpenClaw approval checkpoints. No-op if already in bypassPermissions mode. In plan mode without a pending plan, this flag is ignored."})),approval_rationale:c.Optional(c.String({description:"Optional structured rationale for a direct delegated plan approval. Use this instead of embedding the rationale in message text when approve=true for a pending plan."}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!ou(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, message, interrupt?, userInitiated?, approve?, approval_rationale? }."}]};let r=await Q(S,{session:t.session,message:t.message,interrupt:t.interrupt,userInitiated:t.userInitiated,approve:t.approve,approvalRationale:t.approval_rationale});return{isError:r.isError??!1,content:[{type:"text",text:r.text}]}}}}function iu(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.session=="string"&&typeof e.summary=="string"}function Zi(n){return{name:"agent_request_plan_approval",description:"Send a plan-approval decision prompt to the user for a session that is already waiting on plan approval. Reuses the plugin's Approve/Revise/Reject buttons so the user can decide directly from the message.",parameters:c.Object({session:c.String({description:"Session name or ID awaiting plan approval"}),summary:c.String({description:"Concise user-facing summary of scope, risk, and any concerns that should accompany the approval buttons"})}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!iu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, summary }."}]};let r=S.requestPlanApprovalFromUser(t.session,t.summary);return{isError:r.startsWith("Error:"),content:[{type:"text",text:r}]}}}}function su(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.session=="string"&&typeof e.summary=="string"}function es(n){return{name:"agent_request_worktree_decision",description:"Send a worktree Merge/Open PR/Later/Discard decision prompt to the user for a delegated worktree session that is awaiting human choice.",parameters:c.Object({session:c.String({description:"Delegated session name or ID awaiting a worktree decision"}),summary:c.String({description:"Concise user-facing summary of scope, risk, and why human choice is needed"})}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!su(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, summary }."}]};let r=S.requestWorktreeDecisionFromUser(t.session,t.summary);return{isError:r.startsWith("Error:"),content:[{type:"text",text:r}]}}}}var Yr=["off","manual","ask","delegate","auto-merge","auto-pr"],Sn=new Set(Yr),au=["pr-required","pr-allowed","never-pr","manual"],ts=new Set(au),lu=["low","medium","high","xhigh","max"],ns=new Set(lu);function du(n){return typeof n=="string"&&Sn.has(n)}var uu=c.Union(Yr.map(n=>c.Literal(n)),{description:"Optional worktree strategy for the planning session. Use auto-pr when the follow-up should branch and open/update a PR after approved implementation."});function pu(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.offer_id=="string"&&typeof e.offer_text=="string"&&typeof e.plan_prompt=="string"&&typeof e.plan_workdir=="string"&&(e.plan_worktree_strategy==null||du(e.plan_worktree_strategy))&&(e.plan_name==null||typeof e.plan_name=="string")&&(e.target_channel==null||typeof e.target_channel=="string")&&(e.target_thread_id==null||typeof e.target_thread_id=="string"||typeof e.target_thread_id=="number")&&(e.target_session_key==null||typeof e.target_session_key=="string")}function cu(n,e){let t=De(n,e.target_channel,e.target_session_key);if(t)return e.target_thread_id!=null&&(t.threadId=String(e.target_thread_id)),t}async function mu(n,e){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};let t=cu(n,e);return!t?.provider||!t.target?{content:[{type:"text",text:"Error: Could not resolve a direct delivery route for the plan offer."}]}:(S.sendPlanOffer({offerId:e.offer_id,route:t,text:e.offer_text,planName:e.plan_name??e.offer_id,planPrompt:e.plan_prompt,planWorkdir:e.plan_workdir,planWorktreeStrategy:e.plan_worktree_strategy}),{content:[{type:"text",text:`Interactive plan offer queued for ${t.provider}|${t.target}${t.threadId?`#${t.threadId}`:""}.`}]})}function rs(n){return{name:"agent_send_plan_offer",description:"Post a user-facing message to the current or explicit chat route with human-gated Start Plan and Dismiss inline buttons. Use this when an external workflow wants the user to open a plan-only code-agent session from the message.",parameters:c.Object({offer_id:c.String({description:"Stable offer identifier, for example 'plugin-readiness-v2026.5.5'."}),offer_text:c.String({description:"Final user-facing text to deliver."}),plan_prompt:c.String({description:"Prompt to seed into the plan-only session when the user clicks Start Plan."}),plan_workdir:c.String({description:"Working directory for the planning session."}),plan_worktree_strategy:c.Optional(uu),plan_name:c.Optional(c.String({description:"Optional explicit session name for the planning session."})),target_channel:c.Optional(c.String({description:"Optional explicit route like 'telegram|<chat-id>'."})),target_thread_id:c.Optional(c.Union([c.String(),c.Number()],{description:"Optional explicit topic/thread id."})),target_session_key:c.Optional(c.String({description:"Optional explicit session key for wake routing."}))}),async execute(e,t){return pu(t)?mu(n,t):{content:[{type:"text",text:"Error: Invalid parameters. Expected { offer_id, offer_text, plan_prompt, plan_workdir }."}]}}}}function os(n){return{name:"agent_stats",description:"Show OpenClaw Code Agent usage metrics: session counts by status, average duration, and notable sessions.",parameters:c.Object({}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};let r=S.getMetrics(),o=S.list("running").length;return{content:[{type:"text",text:Yt(r,o)}]}}}}import{execFileSync as fu}from"child_process";var Xr=[{policy:"pr-required",label:"Require PR",title:"Require PR",description:"Direct merge is disabled; follow-through must use a pull request."},{policy:"pr-allowed",label:"Merge or PR",title:"Merge or PR",description:"Use the requested strategy; direct merge and pull requests are both allowed."},{policy:"never-pr",label:"No PR",title:"No PR",description:"Do not create pull requests; keep follow-through local/direct."},{policy:"manual",label:"Manual",title:"Manual",description:"Create isolated worktrees, but require an explicit human follow-up decision every time."}],gu=new Map(Xr.map(n=>[n.policy,n]));function st(n){return n?Xr:Xr.filter(e=>e.policy==="never-pr"||e.policy==="manual")}function is(n){return gu.get(n)??{policy:n,label:n,title:n,description:"Custom repo integration policy."}}function Ke(n,e){if(!(e||n!=="pr-required"&&n!=="pr-allowed"))return`Policy ${n} requires PR automation, but no supported PR provider is available. Choose never-pr or manual.`}function Zr(n){let{policy:e,prAvailable:t}=n;return{merge:e!=="pr-required"&&e!=="manual",pr:e!=="never-pr"&&e!=="manual"&&t}}function Jr(n,e){try{return fu("git",e,{cwd:n,timeout:5e3,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||void 0}catch{return}}function ss(n){if(!n)return;let e=n.trim().replace(/\/+$/,"").replace(/\.git$/i,""),t=e.match(/^git@([^:]+):(.+)$/);if(t)return`https://${t[1].toLowerCase()}/${t[2].toLowerCase()}`;let r=e.match(/^https?:\/\/([^/]+)\/(.+)$/i);return r?`https://${r[1].toLowerCase()}/${r[2].toLowerCase()}`:e.toLowerCase()}function hu(n){return ss(n)?.startsWith("https://github.com/")?"github":"unsupported"}function at(n){let e=Jr(n,["rev-parse","--show-toplevel"]);if(!e)return;let t=Jr(e,["remote","get-url","origin"])??Jr(e,["remote","get-url","upstream"]),r=ss(t),o=hu(r);return{key:r?`${e}|${r}`:e,repoRoot:e,remoteUrl:r,provider:o}}function as(n){if(n?.remoteUrl)return n.remoteUrl==="https://github.com/goldmar/openclaw-code-agent"?"pr-required":void 0}function eo(n,e,t="stored",r=new Date().toISOString()){return{key:n.key,policy:e,repoRoot:n.repoRoot,remoteUrl:n.remoteUrl,provider:n.provider,createdAt:r,updatedAt:r,source:t}}function to(n){return n.provider==="github"&&Je()}function ls(n){let e=n.requestedStrategy,t=Zr(n);return!e||e==="off"||e==="manual"?{allowedActions:t}:n.policy?n.policy==="manual"?{strategy:e==="delegate"?"delegate":"ask",reason:"Repo policy requires manual follow-through.",allowedActions:{merge:!1,pr:!1}}:n.policy==="pr-required"?e==="auto-merge"?n.prAvailable?{strategy:"auto-pr",reason:"Repo policy requires a PR; auto-merge was downgraded to auto-pr.",allowedActions:t}:{strategy:"ask",blocked:!0,reason:"Repo policy requires a PR, but no supported PR provider is available.",allowedActions:t}:e==="auto-pr"?n.prAvailable?{strategy:"auto-pr",allowedActions:t}:{strategy:"ask",blocked:!0,reason:"Repo policy requires a PR, but no supported PR provider is available.",allowedActions:t}:{strategy:e,allowedActions:t}:n.policy==="never-pr"?e==="auto-pr"?n.existingOpenPr&&n.prAvailable?{strategy:"auto-pr",reason:"Repo policy forbids new PR creation; updating the existing open PR is allowed.",allowedActions:t}:{strategy:"ask",reason:"Repo policy forbids PR creation; auto-pr was downgraded to an explicit worktree decision.",allowedActions:t}:{strategy:e,allowedActions:t}:e==="auto-pr"&&!n.prAvailable?{strategy:"ask",reason:"No supported PR provider is available; auto-pr was downgraded to an explicit worktree decision.",allowedActions:t}:{strategy:e,allowedActions:t}:{strategy:e==="auto-merge"||e==="auto-pr"?"ask":e,blocked:!0,reason:"Repo integration policy is unknown.",allowedActions:{merge:!1,pr:!1}}}function no(n,e,t=n.provider==="github"){let r=st(t);return[`Repo integration policy is not set for ${n.repoRoot}.`,"","OpenClaw Code Agent will create isolated worktrees, but it needs one repo policy before worktree follow-through can run.",`Requested worktree strategy: ${e}`,`Provider: ${n.provider}${t?"":" (PR automation unavailable)"}`,"","Choose one available policy:",...r.map(o=>`- ${o.title}: ${o.description}`),"","If buttons are unavailable, set it manually. OpenClaw Code Agent will continue the pending launch automatically when exactly one matching launch is waiting; otherwise run the intended launch again:",...r.map(o=>`- agent_repo_policy(workdir="${n.repoRoot}", policy="${o.policy}")`)].join(`
60
- `)}function yu(n){return n==="pr-required"||n==="pr-allowed"||n==="never-pr"||n==="manual"}function lt(n){return n?[`Repo policy: ${n.policy}`,`Repo: ${n.repoRoot}`,`Provider: ${n.provider}`,...n.remoteUrl?[`Remote: ${n.remoteUrl}`]:[],`Updated: ${n.updatedAt}`].join(`
54
+ `;function Qi(n){let e=n?.replace(/\s+/g," ").trim();if(e)return q(e,240)}function jr(n){if(n.approvalState==="changes_requested"&&!yn(n))return`Plan changes were already requested for session ${n.name}. Wait for the revised plan before approving.`;if(n.approvalState==="rejected")return`Plan for session ${n.name} was already rejected.`}function yn(n){return n.pendingPlanApproval?(n.approvalState==="changes_requested"?n.actionablePlanDecisionVersion:n.actionablePlanDecisionVersion??n.planDecisionVersion)>0:!1}function eu(n){return jr(n)?!1:yn(n)||n.currentPermissionMode==="plan"}function tu(n,e){let t=n.updatePersistedSession;if(typeof t!="function")return;let r=e.controlStateSnapshot();t.call(n,e.id,{lifecycle:r.lifecycle,approvalState:r.approvalState,approvalExecutionState:r.approvalExecutionState,runtimeState:r.runtimeState,requestedPermissionMode:r.requestedPermissionMode,currentPermissionMode:r.currentPermissionMode,pendingPlanApproval:r.pendingPlanApproval,planApprovalContext:r.planApprovalContext,planDecisionVersion:r.planDecisionVersion,actionablePlanDecisionVersion:r.actionablePlanDecisionVersion,planModeApproved:r.planModeApproved,approvalRationale:e.approvalRationale})}function nu(n){return(n.planDecisionVersion??0)+1}function Yi(n,e){let t={approvalState:e,lifecycle:e==="rejected"?"terminal":"awaiting_user_input",pendingPlanApproval:!1,planApprovalContext:void 0,planDecisionVersion:nu(n),actionablePlanDecisionVersion:void 0,canonicalPlanPromptVersion:void 0,approvalPromptRequiredVersion:void 0,approvalPromptVersion:void 0,approvalPromptStatus:"not_sent",approvalPromptTransport:"none",approvalPromptMessageKind:"none",approvalPromptLastAttemptAt:void 0,approvalPromptDeliveredAt:void 0,approvalPromptFailedAt:void 0};return e==="rejected"&&(t.runtimeState="stopped"),t}function Ji(n,e){let t=n;typeof t.applyControlPatch=="function"&&t.applyControlPatch(e),Object.assign(n,e)}function Hr(n,e){let t=n.resolve(e),r=t?void 0:n.getPersistedSession(e),o=t??r,i=o?.name??e;if(n.clearPlanDecisionTokens?.(e),!o)return{text:`Plan rejected for [${i}].`,isError:!1};let s=Yi(o,"rejected");return t?(Ji(t,s),n.updatePersistedSession?.(e,s),n.kill(t.id,"user"),{text:`Plan rejected for [${t.name}]. Session stopped.`}):(n.updatePersistedSession?.(e,s),{text:`Plan rejected for [${i}]. Session remains stopped.`})}function Qr(n,e){let t=n.resolve(e),r=t?void 0:n.getPersistedSession(e),o=t??r,i=o?.name??e;if(n.clearPlanDecisionTokens?.(e),o){let s=Yi(o,"changes_requested");t&&Ji(t,s),n.updatePersistedSession?.(e,s)}return{text:`Type your revision feedback for [${i}] and I'll forward it to the agent.`}}async function ru(n,e,t,r={}){let o=ke(e);if(!(o.kind==="resume"||zi(e)))return;let s=!!(r.approve&&eu(e)),a=s?Qi(r.approvalRationale):void 0;try{if(o.kind!=="resume")return o.kind==="relaunch"?Hi(n,e,t):st(e,o.reason);let l={prompt:s?Zd+t:t,sessionIdOverride:o.stableSessionId,workdir:e.workdir,name:e.name,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,resumeSessionId:o.resumeSessionId,resumeWorktreeFrom:Jd(e),worktreeStrategy:e.worktreeStrategy,worktreeBaseBranch:e.worktreeBaseBranch,worktreePrTargetRepo:e.worktreePrTargetRepo,multiTurn:!0,originChannel:e.originChannel,originThreadId:e.originThreadId,originAgentId:e.originAgentId,originSessionKey:e.originSessionKey,route:e.route,permissionMode:s?"bypassPermissions":e.currentPermissionMode,requestedPermissionMode:e.requestedPermissionMode??e.currentPermissionMode,planApproval:e.planApproval,codexApprovalPolicy:e.codexApprovalPolicy,pendingPlanApproval:s?!1:e.pendingPlanApproval,planApprovalContext:e.planApprovalContext,planDecisionVersion:s?(e.actionablePlanDecisionVersion??e.planDecisionVersion)+1:e.planDecisionVersion,actionablePlanDecisionVersion:s?void 0:e.actionablePlanDecisionVersion,canonicalPlanPromptVersion:e.canonicalPlanPromptVersion,approvalPromptRequiredVersion:e.approvalPromptRequiredVersion,approvalPromptVersion:e.approvalPromptVersion,approvalPromptStatus:e.approvalPromptStatus,approvalPromptTransport:e.approvalPromptTransport,approvalPromptMessageKind:e.approvalPromptMessageKind,approvalPromptLastAttemptAt:e.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:e.approvalPromptDeliveredAt,approvalPromptFailedAt:e.approvalPromptFailedAt,...s?{approvalState:"approved",approvalExecutionState:"awaiting_plan_output",approvalRationale:a,planModeApproved:!0}:{},harness:"harnessName"in e?e.harnessName:e.harness},d=await n.spawnAndAwaitRunning(l,{notifyLaunch:!1});return s?(n.notifySession(d,`👍 [${d.name}] Plan approved (resumed)`,"plan-approved",`agent-respond-plan-approved-resumed:${d.id}:${d.startedAt}:${o.resumeSessionId}:v${e.planDecisionVersion??"unknown"}`),{text:`Plan approved for session ${d.name} [${d.id}]. Session resumed in bypassPermissions mode. Use agent_output to see the response.`}):(n.notifyResumedLaunch(d),{text:`Resume started for session ${d.name} [${d.id}]. Use agent_output to see the response.`})}catch(l){return st(e,"missing_backend_state",`Backend resume failed: ${zr(l)}`)}}async function Q(n,e){let t=n.resolve(e.session),r=t?void 0:n.getPersistedSession(e.session);if(!t&&!r)return{text:`Error: Session "${e.session}" not found.`,isError:!0};let o=t??r,i=o.status==="running"?{kind:"direct"}:ke(o),s=!e.approve&&o.lifecycle==="awaiting_plan_decision"&&o.pendingPlanApproval&&e.userInitiated?Xd(e.message):void 0;if(s==="approve")return Q(n,{...e,message:"Approved. Go ahead.",approve:!0});if(s==="revise")return Qr(n,t?.id??r?.sessionId??e.session);if(s==="reject")return Hr(n,t?.id??r?.sessionId??e.session);if(e.approve){let l=jr(o);if(l)return{text:l,isError:!0}}if(i.kind==="resume"||zi(o)){let l=await ru(n,o,e.message,{approve:e.approve,approvalRationale:e.approvalRationale});if(l)return l}else{if(i.kind==="relaunch")return Hi(n,o,e.message);if(i.kind==="unavailable")return st(o,i.reason)}if(!t)return ot(r)?st(r,"completed"):{text:`Error: Session ${r.name} [${Pe(r)}] is not running (status: ${r.status}). Cannot send a message to a non-running session.`,isError:!0};if(t.status!=="running")return ot(t)?st(t,"completed"):{text:`Error: Session ${t.name} [${t.id}] is not running (status: ${t.status}). Cannot send a message to a non-running session.`,isError:!0};let a=_.maxAutoResponds??Yd;if(e.userInitiated)t.resetAutoRespond();else if(t.autoRespondCount>=a)return{text:`⚠️ Auto-respond limit reached (${t.autoRespondCount}/${a}). Ask the user to provide the answer for session ${t.name}. Then call agent_respond with their answer and set userInitiated: true to reset the counter.`};try{if(e.approve){let y=jr(t);if(y)return{text:y,isError:!0}}let l=t.pendingInputState?.activeQuestionIndex,d=t.pendingInputState?.questions?.length;if(!e.approve&&t.pendingInputState?.allowsFreeText&&await t.submitPendingInputText?.(e.message)===!0){if(e.userInitiated){let b=q(e.message,100);n.notifySession(t,`↪️ [${t.name}] "${b}"`,"agent-respond")}e.userInitiated||t.incrementAutoRespond();let y=q(e.message,80),P=l!=null&&d!=null&&l+1<d;return{text:[P?`Pending input question answered for session ${t.name} [${t.id}]; more input is required.`:`Pending input request submitted for session ${t.name} [${t.id}].`,` Message: "${y}"`,P?"The next question is being delivered to the user.":"Use agent_output to see the response."].join(`
55
+ `)}}let f=!1;e.interrupt&&(f=await t.interrupt());let g=!!(e.approve&&yn(t)),k=g?Qi(e.approvalRationale):void 0,h="";if(e.approve&&yn(t)?(t.switchPermissionMode("bypassPermissions"),t.approvalRationale=k):e.approve&&t.currentPermissionMode==="default"?t.switchPermissionMode("bypassPermissions"):e.approve&&t.currentPermissionMode==="bypassPermissions"?h=`
56
+ ℹ️ approve=true was set but session is already in bypassPermissions mode.`:e.approve?h=`
57
+ ⚠️ approve=true was set but session has no pending plan approval.`:(t.pendingPlanApproval||t.approvalState==="changes_requested")&&(h=`
58
+ ℹ️ Session has a pending plan — sending as revision feedback. The agent will revise and re-submit. Set approve=true to approve instead.`),await t.sendMessage(e.message),g&&tu(n,t),g)n.notifySession(t,`👍 [${t.name}] Plan approved`,"plan-approved");else if(e.userInitiated){let y=q(e.message,100);n.notifySession(t,`↪️ [${t.name}] "${y}"`,"agent-respond")}e.userInitiated||t.incrementAutoRespond();let p=q(e.message,80);return g?{text:`Plan approved for session ${t.name} [${t.id}]. Use agent_output to see the response.`}:{text:[`Message sent to session ${t.name} [${t.id}].`,f?" (redirected active turn first)":e.interrupt?" (no active turn to interrupt)":"",` Message: "${p}"`,h,"Use agent_output to see the response."].filter(Boolean).join(`
59
+ `)}}catch(l){return{text:`Error sending message to session ${t.name} [${t.id}]: ${zr(l)}`,isError:!0}}}function ou(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.session=="string"&&typeof e.message=="string"&&(e.approval_rationale===void 0||typeof e.approval_rationale=="string")}function Xi(n){return{name:"agent_respond",description:"Send a follow-up message to a running coding agent session. The session must be running. All sessions are multi-turn.",parameters:c.Object({session:c.String({description:"Session name or ID to respond to"}),message:c.String({description:"The message to send to the session"}),interrupt:c.Optional(c.Boolean({description:"If true, interrupt the current turn before sending the message. Useful to redirect the session mid-response."})),userInitiated:c.Optional(c.Boolean({description:"Set to true when the message comes from the user (not auto-generated). Resets the auto-respond counter and bypasses the auto-respond limit."})),approve:c.Optional(c.Boolean({description:"Set to true to escalate session permissions to bypassPermissions. Works in two scenarios: (1) approve a pending plan in plan mode, or (2) escalate a default-mode session to skip remaining OpenClaw approval checkpoints. No-op if already in bypassPermissions mode. In plan mode without a pending plan, this flag is ignored."})),approval_rationale:c.Optional(c.String({description:"Optional structured rationale for a direct delegated plan approval. Use this instead of embedding the rationale in message text when approve=true for a pending plan."}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!ou(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, message, interrupt?, userInitiated?, approve?, approval_rationale? }."}]};let r=await Q(S,{session:t.session,message:t.message,interrupt:t.interrupt,userInitiated:t.userInitiated,approve:t.approve,approvalRationale:t.approval_rationale});return{isError:r.isError??!1,content:[{type:"text",text:r.text}]}}}}function iu(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.session=="string"&&typeof e.summary=="string"}function Zi(n){return{name:"agent_request_plan_approval",description:"Send a plan-approval decision prompt to the user for a session that is already waiting on plan approval. Reuses the plugin's Approve/Revise/Reject buttons so the user can decide directly from the message.",parameters:c.Object({session:c.String({description:"Session name or ID awaiting plan approval"}),summary:c.String({description:"Concise user-facing summary of scope, risk, and any concerns that should accompany the approval buttons"})}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!iu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, summary }."}]};let r=S.requestPlanApprovalFromUser(t.session,t.summary);return{isError:r.startsWith("Error:"),content:[{type:"text",text:r}]}}}}function su(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.session=="string"&&typeof e.summary=="string"}function es(n){return{name:"agent_request_worktree_decision",description:"Send a worktree Merge/Open PR/Later/Discard decision prompt to the user for a delegated worktree session that is awaiting human choice.",parameters:c.Object({session:c.String({description:"Delegated session name or ID awaiting a worktree decision"}),summary:c.String({description:"Concise user-facing summary of scope, risk, and why human choice is needed"})}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!su(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, summary }."}]};let r=S.requestWorktreeDecisionFromUser(t.session,t.summary);return{isError:r.startsWith("Error:"),content:[{type:"text",text:r}]}}}}var Yr=["off","manual","ask","delegate","auto-merge","auto-pr"],Sn=new Set(Yr),au=["pr-required","pr-allowed","never-pr","manual"],ts=new Set(au),lu=["low","medium","high","xhigh","max"],ns=new Set(lu);function du(n){return typeof n=="string"&&Sn.has(n)}var uu=c.Union(Yr.map(n=>c.Literal(n)),{description:"Optional worktree strategy for the planning session. Use auto-pr when the follow-up should branch and open/update a PR after approved implementation."});function pu(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.offer_id=="string"&&typeof e.offer_text=="string"&&typeof e.plan_prompt=="string"&&typeof e.plan_workdir=="string"&&(e.plan_worktree_strategy==null||du(e.plan_worktree_strategy))&&(e.plan_name==null||typeof e.plan_name=="string")&&(e.target_channel==null||typeof e.target_channel=="string")&&(e.target_thread_id==null||typeof e.target_thread_id=="string"||typeof e.target_thread_id=="number")&&(e.target_session_key==null||typeof e.target_session_key=="string")}function cu(n,e){let t=De(n,e.target_channel,e.target_session_key);if(t)return e.target_thread_id!=null&&(t.threadId=String(e.target_thread_id)),t}async function mu(n,e){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};let t=cu(n,e);return!t?.provider||!t.target?{content:[{type:"text",text:"Error: Could not resolve a direct delivery route for the plan offer."}]}:(S.sendPlanOffer({offerId:e.offer_id,route:t,text:e.offer_text,planName:e.plan_name??e.offer_id,planPrompt:e.plan_prompt,planWorkdir:e.plan_workdir,planWorktreeStrategy:e.plan_worktree_strategy}),{content:[{type:"text",text:`Interactive plan offer queued for ${t.provider}|${t.target}${t.threadId?`#${t.threadId}`:""}.`}]})}function rs(n){return{name:"agent_send_plan_offer",description:"Post a user-facing message to the current or explicit chat route with human-gated Start Plan and Dismiss inline buttons. Use this when an external workflow wants the user to open a plan-only code-agent session from the message.",parameters:c.Object({offer_id:c.String({description:"Stable offer identifier, for example 'plugin-readiness-v2026.5.5'."}),offer_text:c.String({description:"Final user-facing text to deliver."}),plan_prompt:c.String({description:"Prompt to seed into the plan-only session when the user clicks Start Plan."}),plan_workdir:c.String({description:"Working directory for the planning session."}),plan_worktree_strategy:c.Optional(uu),plan_name:c.Optional(c.String({description:"Optional explicit session name for the planning session."})),target_channel:c.Optional(c.String({description:"Optional explicit route like 'telegram|<chat-id>'."})),target_thread_id:c.Optional(c.Union([c.String(),c.Number()],{description:"Optional explicit topic/thread id."})),target_session_key:c.Optional(c.String({description:"Optional explicit session key for wake routing."}))}),async execute(e,t){return pu(t)?mu(n,t):{content:[{type:"text",text:"Error: Invalid parameters. Expected { offer_id, offer_text, plan_prompt, plan_workdir }."}]}}}}function os(n){return{name:"agent_stats",description:"Show OpenClaw Code Agent usage metrics: session counts by status, average duration, and notable sessions.",parameters:c.Object({}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};let r=S.getMetrics(),o=S.list("running").length;return{content:[{type:"text",text:Jt(r,o)}]}}}}import{execFileSync as fu}from"child_process";var Xr=[{policy:"pr-required",label:"Require PR",title:"Require PR",description:"Direct merge is disabled; follow-through must use a pull request."},{policy:"pr-allowed",label:"Merge or PR",title:"Merge or PR",description:"Use the requested strategy; direct merge and pull requests are both allowed."},{policy:"never-pr",label:"No PR",title:"No PR",description:"Do not create pull requests; keep follow-through local/direct."},{policy:"manual",label:"Manual",title:"Manual",description:"Create isolated worktrees, but require an explicit human follow-up decision every time."}],gu=new Map(Xr.map(n=>[n.policy,n]));function at(n){return n?Xr:Xr.filter(e=>e.policy==="never-pr"||e.policy==="manual")}function is(n){return gu.get(n)??{policy:n,label:n,title:n,description:"Custom repo integration policy."}}function Ke(n,e){if(!(e||n!=="pr-required"&&n!=="pr-allowed"))return`Policy ${n} requires PR automation, but no supported PR provider is available. Choose never-pr or manual.`}function Zr(n){let{policy:e,prAvailable:t}=n;return{merge:e!=="pr-required"&&e!=="manual",pr:e!=="never-pr"&&e!=="manual"&&t}}function Jr(n,e){try{return fu("git",e,{cwd:n,timeout:5e3,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||void 0}catch{return}}function ss(n){if(!n)return;let e=n.trim().replace(/\/+$/,"").replace(/\.git$/i,""),t=e.match(/^git@([^:]+):(.+)$/);if(t)return`https://${t[1].toLowerCase()}/${t[2].toLowerCase()}`;let r=e.match(/^https?:\/\/([^/]+)\/(.+)$/i);return r?`https://${r[1].toLowerCase()}/${r[2].toLowerCase()}`:e.toLowerCase()}function hu(n){return ss(n)?.startsWith("https://github.com/")?"github":"unsupported"}function lt(n){let e=Jr(n,["rev-parse","--show-toplevel"]);if(!e)return;let t=Jr(e,["remote","get-url","origin"])??Jr(e,["remote","get-url","upstream"]),r=ss(t),o=hu(r);return{key:r?`${e}|${r}`:e,repoRoot:e,remoteUrl:r,provider:o}}function as(n){if(n?.remoteUrl)return n.remoteUrl==="https://github.com/goldmar/openclaw-code-agent"?"pr-required":void 0}function eo(n,e,t="stored",r=new Date().toISOString()){return{key:n.key,policy:e,repoRoot:n.repoRoot,remoteUrl:n.remoteUrl,provider:n.provider,createdAt:r,updatedAt:r,source:t}}function to(n){return n.provider==="github"&&Je()}function ls(n){let e=n.requestedStrategy,t=Zr(n);return!e||e==="off"||e==="manual"?{allowedActions:t}:n.policy?n.policy==="manual"?{strategy:e==="delegate"?"delegate":"ask",reason:"Repo policy requires manual follow-through.",allowedActions:{merge:!1,pr:!1}}:n.policy==="pr-required"?e==="auto-merge"?n.prAvailable?{strategy:"auto-pr",reason:"Repo policy requires a PR; auto-merge was downgraded to auto-pr.",allowedActions:t}:{strategy:"ask",blocked:!0,reason:"Repo policy requires a PR, but no supported PR provider is available.",allowedActions:t}:e==="auto-pr"?n.prAvailable?{strategy:"auto-pr",allowedActions:t}:{strategy:"ask",blocked:!0,reason:"Repo policy requires a PR, but no supported PR provider is available.",allowedActions:t}:{strategy:e,allowedActions:t}:n.policy==="never-pr"?e==="auto-pr"?n.existingOpenPr&&n.prAvailable?{strategy:"auto-pr",reason:"Repo policy forbids new PR creation; updating the existing open PR is allowed.",allowedActions:t}:{strategy:"ask",reason:"Repo policy forbids PR creation; auto-pr was downgraded to an explicit worktree decision.",allowedActions:t}:{strategy:e,allowedActions:t}:e==="auto-pr"&&!n.prAvailable?{strategy:"ask",reason:"No supported PR provider is available; auto-pr was downgraded to an explicit worktree decision.",allowedActions:t}:{strategy:e,allowedActions:t}:{strategy:e==="auto-merge"||e==="auto-pr"?"ask":e,blocked:!0,reason:"Repo integration policy is unknown.",allowedActions:{merge:!1,pr:!1}}}function no(n,e,t=n.provider==="github"){let r=at(t);return[`Repo integration policy is not set for ${n.repoRoot}.`,"","OpenClaw Code Agent will create isolated worktrees, but it needs one repo policy before worktree follow-through can run.",`Requested worktree strategy: ${e}`,`Provider: ${n.provider}${t?"":" (PR automation unavailable)"}`,"","Choose one available policy:",...r.map(o=>`- ${o.title}: ${o.description}`),"","If buttons are unavailable, set it manually. OpenClaw Code Agent will continue the pending launch automatically when exactly one matching launch is waiting; otherwise run the intended launch again:",...r.map(o=>`- agent_repo_policy(workdir="${n.repoRoot}", policy="${o.policy}")`)].join(`
60
+ `)}function yu(n){return n==="pr-required"||n==="pr-allowed"||n==="never-pr"||n==="manual"}function dt(n){return n?[`Repo policy: ${n.policy}`,`Repo: ${n.repoRoot}`,`Provider: ${n.provider}`,...n.remoteUrl?[`Remote: ${n.remoteUrl}`]:[],`Updated: ${n.updatedAt}`].join(`
61
61
  `):"No stored repo policy found."}function ds(n){return{name:"agent_repo_policy",description:"Inspect or set the repository integration policy that governs OpenClaw Code Agent worktree merge/PR follow-through.",parameters:c.Object({workdir:c.Optional(c.String({description:"Repository workdir. Defaults to the current workspace directory."})),policy:c.Optional(c.Union([c.Literal("pr-required"),c.Literal("pr-allowed"),c.Literal("never-pr"),c.Literal("manual")],{description:"Policy to set for this repo."})),reset:c.Optional(c.Boolean({description:"Remove the stored policy for this repo."})),list:c.Optional(c.Boolean({description:"List all stored repo policies."})),cleanup:c.Optional(c.Boolean({description:"Remove stored repo policies whose repoRoot no longer exists on disk."}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};let r=t&&typeof t=="object"?t:{};if(r.cleanup===!0){let a=S.cleanupRepoPolicies();return{content:[{type:"text",text:a.length===0?"No stale repo policies found.":[`Removed ${a.length} stale repo ${a.length===1?"policy":"policies"}.`,...a.map(d=>`${d.policy} | ${d.provider} | ${d.repoRoot}`)].join(`
62
62
  `)}]}}if(r.list===!0){let a=S.listRepoPolicies();return{content:[{type:"text",text:a.length===0?"No stored repo policies.":a.map(d=>`${d.policy} | ${d.provider} | ${d.repoRoot}${d.remoteUrl?` | ${d.remoteUrl}`:""}`).join(`
63
- `)}]}}let o=r.workdir??n?.workspaceDir;if(!o)return{content:[{type:"text",text:"Error: workdir is required when no workspace directory is available."}]};if(r.reset===!0)return{content:[{type:"text",text:S.resetRepoPolicy(o)?`Repo policy reset for ${o}.`:`No stored repo policy found for ${o}.`}]};if(r.policy!==void 0){if(!yu(r.policy))return{content:[{type:"text",text:"Error: policy must be one of pr-required, pr-allowed, never-pr, manual."}]};if(typeof S.resolveRepoPolicy=="function"){let d=S.resolveRepoPolicy(o);if(d.identity){let u=Ke(r.policy,d.prAvailable);if(u)return{content:[{type:"text",text:`Error: ${u}`}]}}}let a=S.setRepoPolicy(o,r.policy);if(!a)return{content:[{type:"text",text:`Error: ${o} is not a git repository.`}]};let l;try{l=typeof S.continueLaunchAfterManualRepoPolicy=="function"?S.continueLaunchAfterManualRepoPolicy(a.repoRoot,r.policy):{kind:"none"}}catch(d){let u=d instanceof Error?d.message:String(d);return{content:[{type:"text",text:[lt(a),"",`Repo policy saved, but the deferred launch failed: ${u}`,"The pending launch context was kept so you can retry the same agent_repo_policy call or run the intended launch again."].join(`
64
- `)}]}}return l.kind==="launched"?{content:[{type:"text",text:[lt(a),"",l.text].join(`
65
- `)}]}:l.kind==="ambiguous"?{content:[{type:"text",text:[lt(a),"",`Repo policy saved, but ${l.count} pending launches match this policy. Run the intended launch again to avoid starting the wrong session.`].join(`
66
- `)}]}:{content:[{type:"text",text:lt(a)}]}}let i=S.resolveRepoPolicy(o);if(!i.identity)return{content:[{type:"text",text:`No git repository found for ${o}.`}]};let s=i.record;return s?{content:[{type:"text",text:lt(s)}]}:{content:[{type:"text",text:["Repo policy: unknown",`Repo: ${i.identity.repoRoot}`,`Provider: ${i.provider}${i.prAvailable?"":" (PR automation unavailable)"}`,...i.identity.remoteUrl?[`Remote: ${i.identity.remoteUrl}`]:[]].join(`
67
- `)}]}}}}import{existsSync as kn}from"fs";function Su(n){return!n||typeof n!="object"?!1:typeof n.session=="string"}function ku(n){return n.mergeResult.stashPopConflict?[`Pre-merge stash pop conflicted; run git stash show ${n.mergeResult.stashRef??"stash@{0}"} in ${n.repoDir} to review stashed changes.`]:n.mergeResult.stashed?[`Pre-existing changes on ${n.baseBranch} were auto-stashed and restored.`]:[]}function vu(n){return n.deleteBranchRequested?n.branchDeleted&&n.worktreeCleanedUp&&!n.worktreeAlreadyAbsent?{detailLine:"Branch and worktree cleaned up.",summaryFragment:" Branch and worktree cleaned up."}:n.branchDeleted&&n.worktreeAlreadyAbsent?{detailLine:"Branch deleted; worktree was already absent.",summaryFragment:" Branch deleted; worktree was already absent."}:n.branchDeleted?{detailLine:"Branch deleted; worktree cleanup failed.",summaryFragment:" Branch deleted; worktree cleanup failed."}:n.worktreeAlreadyAbsent?{detailLine:"Worktree was already absent; branch deletion failed.",summaryFragment:" Worktree was already absent; branch deletion failed."}:n.worktreeCleanedUp?{detailLine:"Worktree cleaned up; branch deletion failed.",summaryFragment:" Worktree cleaned up; branch deletion failed."}:{detailLine:"Branch deletion and worktree cleanup failed.",summaryFragment:" Branch deletion and worktree cleanup failed."}:n.worktreeCleanedUp&&!n.worktreeAlreadyAbsent?{detailLine:"Worktree cleaned up; branch deletion was not requested.",summaryFragment:" Worktree cleaned up; branch kept."}:n.worktreeAlreadyAbsent?{detailLine:"Worktree was already absent; branch deletion was not requested.",summaryFragment:" Worktree was already absent; branch kept."}:{detailLine:"Worktree cleanup failed; branch deletion was not requested.",summaryFragment:" Worktree cleanup failed; branch kept."}}function vn(n){return{name:"agent_merge",description:"Merge a worktree branch back to the base branch. Resolves session (active or persisted), gets worktree path, and performs the merge. On conflict, spawns a conflict-resolver session using the configured default harness.",parameters:c.Object({session:c.String({description:"Session name or ID to merge"}),base_branch:c.Optional(c.String({description:"Base branch to merge into (default: main)"})),strategy:c.Optional(c.Union([c.Literal("merge"),c.Literal("squash")],{description:"Merge strategy: 'merge' (default, fast-forward if possible; merge commit if branches have diverged) or 'squash' (squashes all commits into one)"})),push:c.Optional(c.Boolean({description:"Push the base branch after successful merge (default: false)"})),delete_branch:c.Optional(c.Boolean({description:"Delete the worktree branch after successful merge (default: true)"}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!Su(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, base_branch?, strategy?, push?, delete_branch? }."}]};let r=Nt(S,t.session),o=r.activeSession,i=r.persistedSession;if(!o&&!i)return{content:[{type:"text",text:`Error: Session "${t.session}" not found.`}]};let{worktreePath:s,originalWorkdir:a,branchName:l}=r;if(!s||!a)return{content:[{type:"text",text:`Error: Session "${t.session}" does not have a worktree.`}]};if(!l)return{content:[{type:"text",text:`Error: Cannot determine branch name for worktree at ${s}. The worktree may have been removed and no persisted branch name is available.`}]};kn(s)||`${s}${a}`;let d=a;if(!kn(a))return{content:[{type:"text",text:`Error: originalWorkdir "${a}" does not exist.`}]};let u=t.base_branch??Ee(d),f=u,h=t.strategy??"merge",k=t.push===!0,g=t.delete_branch!==!1,p=S.resolveRepoPolicy(d);if(p?.policy==="pr-required")return{content:[{type:"text",text:`❌ Merge blocked: repo policy requires a pull request for ${p.identity?.repoRoot??d}. Use agent_pr if PR automation is available.`}]};if(i?.worktreeLifecycle?.state==="merged"||i?.worktreeMerged)return{content:[{type:"text",text:`ℹ️ Session "${t.session}" is already merged.`}]};if((kn(s)?Xe(d,l,f):void 0)===0&&et(s))return{content:[{type:"text",text:[`❌ Merge blocked: session "${t.session}" has uncommitted worktree changes but branch ${l} has no commits ahead of ${f}.`,`Worktree: ${s}`,"Resume or inspect the session, then commit real task changes or clean temporary files before retrying agent_merge."].join(`
68
- `)}]};let w={content:[{type:"text",text:"❌ Merge did not run (internal error)"}]};return await S.enqueueMerge(d,async()=>{let R=S.getPersistedSession(t.session);if(R?.worktreeLifecycle?.state==="merged"||R?.worktreeMerged){w={content:[{type:"text",text:`ℹ️ Session "${t.session}" was already merged while waiting in queue.`}]};return}let A=Ne(d,l,u),I=Mt(d,l,f,h,s),b=tt(I);if(I.success){let m=ku({mergeResult:I,repoDir:d,baseBranch:f});if(k&&!Xo(d,f)){let Ie=`⚠️ Merged ${l} → ${f} locally, but failed to push ${f}`;S.notifyWorktreeOutcome(r.notificationTarget,Ie,{detailLines:[`Branch ${l} was merged into ${f} in the local repository.`,`Pushing ${f} failed; remote state may not include the merge.`,"Cleanup was skipped so the branch/worktree remains available for follow-up.",...m,...b]}),w={content:[{type:"text",text:ie(Ie,I)}]};return}let P=!1,T=!1,L=!kn(s);T=L?!0:B(d,s),Ct(d),g&&(P=H(d,l));let U=vu({deleteBranchRequested:g,branchDeleted:P,worktreeCleanedUp:T,worktreeAlreadyAbsent:L});if(R){let Ie=new Date().toISOString();for(let sl of ei({...r,persistedSession:R}))S.updatePersistedSession(sl,{...Et({worktreeBaseBranch:u,worktreePrTargetRepo:R.worktreePrTargetRepo,worktreePushRemote:R.worktreePushRemote},{mergedAt:Ie,updatedAt:Ie,resolvedAt:Ie,resolutionSource:"agent_merge"}),worktreeDisposition:"merged"})}let Lo=Dt({kind:"merge",branch:l,base:u,filesChanged:A?.filesChanged,insertions:A?.insertions,deletions:A?.deletions});S.notifyWorktreeOutcome(r.notificationTarget,Lo,{detailLines:[I.fastForward?"Merge type: fast-forward.":"Merge type: merge commit.",k?`Pushed ${f}.`:`Did not push ${f}; push was not requested.`,U.detailLine,...m,...b]});let Qe=`✅ ${I.fastForward?"⚡ Fast-forward":"🔀 Merge commit"}: ${l} → ${f}.${k?" Pushed.":""}${U.summaryFragment}`;I.stashPopConflict?Qe+=`
63
+ `)}]}}let o=r.workdir??n?.workspaceDir;if(!o)return{content:[{type:"text",text:"Error: workdir is required when no workspace directory is available."}]};if(r.reset===!0)return{content:[{type:"text",text:S.resetRepoPolicy(o)?`Repo policy reset for ${o}.`:`No stored repo policy found for ${o}.`}]};if(r.policy!==void 0){if(!yu(r.policy))return{content:[{type:"text",text:"Error: policy must be one of pr-required, pr-allowed, never-pr, manual."}]};if(typeof S.resolveRepoPolicy=="function"){let d=S.resolveRepoPolicy(o);if(d.identity){let u=Ke(r.policy,d.prAvailable);if(u)return{content:[{type:"text",text:`Error: ${u}`}]}}}let a=S.setRepoPolicy(o,r.policy);if(!a)return{content:[{type:"text",text:`Error: ${o} is not a git repository.`}]};let l;try{l=typeof S.continueLaunchAfterManualRepoPolicy=="function"?S.continueLaunchAfterManualRepoPolicy(a.repoRoot,r.policy):{kind:"none"}}catch(d){let u=d instanceof Error?d.message:String(d);return{content:[{type:"text",text:[dt(a),"",`Repo policy saved, but the deferred launch failed: ${u}`,"The pending launch context was kept so you can retry the same agent_repo_policy call or run the intended launch again."].join(`
64
+ `)}]}}return l.kind==="launched"?{content:[{type:"text",text:[dt(a),"",l.text].join(`
65
+ `)}]}:l.kind==="ambiguous"?{content:[{type:"text",text:[dt(a),"",`Repo policy saved, but ${l.count} pending launches match this policy. Run the intended launch again to avoid starting the wrong session.`].join(`
66
+ `)}]}:{content:[{type:"text",text:dt(a)}]}}let i=S.resolveRepoPolicy(o);if(!i.identity)return{content:[{type:"text",text:`No git repository found for ${o}.`}]};let s=i.record;return s?{content:[{type:"text",text:dt(s)}]}:{content:[{type:"text",text:["Repo policy: unknown",`Repo: ${i.identity.repoRoot}`,`Provider: ${i.provider}${i.prAvailable?"":" (PR automation unavailable)"}`,...i.identity.remoteUrl?[`Remote: ${i.identity.remoteUrl}`]:[]].join(`
67
+ `)}]}}}}import{existsSync as kn}from"fs";function Su(n){return!n||typeof n!="object"?!1:typeof n.session=="string"}function ku(n){return n.mergeResult.stashPopConflict?[`Pre-merge stash pop conflicted; run git stash show ${n.mergeResult.stashRef??"stash@{0}"} in ${n.repoDir} to review stashed changes.`]:n.mergeResult.stashed?[`Pre-existing changes on ${n.baseBranch} were auto-stashed and restored.`]:[]}function vu(n){return n.deleteBranchRequested?n.branchDeleted&&n.worktreeCleanedUp&&!n.worktreeAlreadyAbsent?{detailLine:"Branch and worktree cleaned up.",summaryFragment:" Branch and worktree cleaned up."}:n.branchDeleted&&n.worktreeAlreadyAbsent?{detailLine:"Branch deleted; worktree was already absent.",summaryFragment:" Branch deleted; worktree was already absent."}:n.branchDeleted?{detailLine:"Branch deleted; worktree cleanup failed.",summaryFragment:" Branch deleted; worktree cleanup failed."}:n.worktreeAlreadyAbsent?{detailLine:"Worktree was already absent; branch deletion failed.",summaryFragment:" Worktree was already absent; branch deletion failed."}:n.worktreeCleanedUp?{detailLine:"Worktree cleaned up; branch deletion failed.",summaryFragment:" Worktree cleaned up; branch deletion failed."}:{detailLine:"Branch deletion and worktree cleanup failed.",summaryFragment:" Branch deletion and worktree cleanup failed."}:n.worktreeCleanedUp&&!n.worktreeAlreadyAbsent?{detailLine:"Worktree cleaned up; branch deletion was not requested.",summaryFragment:" Worktree cleaned up; branch kept."}:n.worktreeAlreadyAbsent?{detailLine:"Worktree was already absent; branch deletion was not requested.",summaryFragment:" Worktree was already absent; branch kept."}:{detailLine:"Worktree cleanup failed; branch deletion was not requested.",summaryFragment:" Worktree cleanup failed; branch kept."}}function vn(n){return{name:"agent_merge",description:"Merge a worktree branch back to the base branch. Resolves session (active or persisted), gets worktree path, and performs the merge. On conflict, spawns a conflict-resolver session using the configured default harness.",parameters:c.Object({session:c.String({description:"Session name or ID to merge"}),base_branch:c.Optional(c.String({description:"Base branch to merge into (default: main)"})),strategy:c.Optional(c.Union([c.Literal("merge"),c.Literal("squash")],{description:"Merge strategy: 'merge' (default, fast-forward if possible; merge commit if branches have diverged) or 'squash' (squashes all commits into one)"})),push:c.Optional(c.Boolean({description:"Push the base branch after successful merge (default: false)"})),delete_branch:c.Optional(c.Boolean({description:"Delete the worktree branch after successful merge (default: true)"}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!Su(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session, base_branch?, strategy?, push?, delete_branch? }."}]};let r=Ot(S,t.session),o=r.activeSession,i=r.persistedSession;if(!o&&!i)return{content:[{type:"text",text:`Error: Session "${t.session}" not found.`}]};let{worktreePath:s,originalWorkdir:a,branchName:l}=r;if(!s||!a)return{content:[{type:"text",text:`Error: Session "${t.session}" does not have a worktree.`}]};if(!l)return{content:[{type:"text",text:`Error: Cannot determine branch name for worktree at ${s}. The worktree may have been removed and no persisted branch name is available.`}]};kn(s)||`${s}${a}`;let d=a;if(!kn(a))return{content:[{type:"text",text:`Error: originalWorkdir "${a}" does not exist.`}]};let u=t.base_branch??Ee(d),f=u,g=t.strategy??"merge",k=t.push===!0,h=t.delete_branch!==!1,p=S.resolveRepoPolicy(d);if(p?.policy==="pr-required")return{content:[{type:"text",text:`❌ Merge blocked: repo policy requires a pull request for ${p.identity?.repoRoot??d}. Use agent_pr if PR automation is available.`}]};if(i?.worktreeLifecycle?.state==="merged"||i?.worktreeMerged)return{content:[{type:"text",text:`ℹ️ Session "${t.session}" is already merged.`}]};if((kn(s)?Xe(d,l,f):void 0)===0&&et(s))return{content:[{type:"text",text:[`❌ Merge blocked: session "${t.session}" has uncommitted worktree changes but branch ${l} has no commits ahead of ${f}.`,`Worktree: ${s}`,"Resume or inspect the session, then commit real task changes or clean temporary files before retrying agent_merge."].join(`
68
+ `)}]};let P={content:[{type:"text",text:"❌ Merge did not run (internal error)"}]};return await S.enqueueMerge(d,async()=>{let b=S.getPersistedSession(t.session);if(b?.worktreeLifecycle?.state==="merged"||b?.worktreeMerged){P={content:[{type:"text",text:`ℹ️ Session "${t.session}" was already merged while waiting in queue.`}]};return}let A=Ne(d,l,u),I=_t(d,l,f,g,s),R=tt(I);if(I.success){let m=ku({mergeResult:I,repoDir:d,baseBranch:f});if(k&&!Xo(d,f)){let Ie=`⚠️ Merged ${l} → ${f} locally, but failed to push ${f}`;S.notifyWorktreeOutcome(r.notificationTarget,Ie,{detailLines:[`Branch ${l} was merged into ${f} in the local repository.`,`Pushing ${f} failed; remote state may not include the merge.`,"Cleanup was skipped so the branch/worktree remains available for follow-up.",...m,...R]}),P={content:[{type:"text",text:ie(Ie,I)}]};return}let w=!1,T=!1,F=!kn(s);T=F?!0:B(d,s),Mt(d),h&&(w=H(d,l));let U=vu({deleteBranchRequested:h,branchDeleted:w,worktreeCleanedUp:T,worktreeAlreadyAbsent:F});if(b){let Ie=new Date().toISOString();for(let sl of ei({...r,persistedSession:b}))S.updatePersistedSession(sl,{...Nt({worktreeBaseBranch:u,worktreePrTargetRepo:b.worktreePrTargetRepo,worktreePushRemote:b.worktreePushRemote},{mergedAt:Ie,updatedAt:Ie,resolvedAt:Ie,resolutionSource:"agent_merge"}),worktreeDisposition:"merged"})}let Fo=$t({kind:"merge",branch:l,base:u,filesChanged:A?.filesChanged,insertions:A?.insertions,deletions:A?.deletions});S.notifyWorktreeOutcome(r.notificationTarget,Fo,{detailLines:[I.fastForward?"Merge type: fast-forward.":"Merge type: merge commit.",k?`Pushed ${f}.`:`Did not push ${f}; push was not requested.`,U.detailLine,...m,...R]});let Qe=`✅ ${I.fastForward?"⚡ Fast-forward":"🔀 Merge commit"}: ${l} → ${f}.${k?" Pushed.":""}${U.summaryFragment}`;I.stashPopConflict?Qe+=`
69
69
  ⚠️ Pre-merge stash pop conflicted — run \`git stash show ${I.stashRef??"stash@{0}"}\` in ${d} to review stashed changes.`:I.stashed&&(Qe+=`
70
- (Pre-existing changes on ${f} were auto-stashed and restored.)`),Qe=ie(Qe,I),w={content:[{type:"text",text:Qe}]}}else if(I.rebaseConflict)w={content:[{type:"text",text:ie(`⚠️ Rebase conflicts — manual resolution required:
70
+ (Pre-existing changes on ${f} were auto-stashed and restored.)`),Qe=ie(Qe,I),P={content:[{type:"text",text:Qe}]}}else if(I.rebaseConflict)P={content:[{type:"text",text:ie(`⚠️ Rebase conflicts — manual resolution required:
71
71
 
72
- ${I.error}`,I)}]};else if(I.conflictFiles&&I.conflictFiles.length>0){let m=["Resolve merge conflicts in the following files and commit the resolution:","",...I.conflictFiles.map(P=>`- ${P}`),"",`After resolving, commit with message: "Resolve merge conflicts from ${l}"`].join(`
73
- `);try{let P=S.spawn({prompt:m,workdir:d,name:`${t.session}-conflict-resolver`,harness:Y(),permissionMode:"bypassPermissions",multiTurn:!0,route:o?.route??i?.route,originChannel:o?.originChannel??i?.originChannel,originThreadId:o?.originThreadId??i?.originThreadId,originAgentId:o?.originAgentId??i?.originAgentId,originSessionKey:o?.originSessionKey??i?.originSessionKey});w={content:[{type:"text",text:ie(`⚠️ Merge conflicts in ${I.conflictFiles.length} file(s) — spawned conflict resolver session: ${P.name}`,I)}]}}catch(P){w={content:[{type:"text",text:ie(`❌ Merge conflicts detected, but failed to spawn resolver: ${P instanceof Error?P.message:String(P)}`,I)}]}}}else{let m=I.dirtyError?`❌ Merge blocked: ${I.error}`:`❌ Merge failed: ${I.error??"unknown error"}`;w={content:[{type:"text",text:ie(m,I)}]}}}),w}}}function Pu(n){return!!n&&typeof n=="object"}function us(n){return{name:"agent_worktree_cleanup",description:"Manage worktree cleanup with lifecycle-aware safety rules. Use preview_safe to list what Clean all safe would remove, clean_safe to execute it, or preview_all to see both safe and retained sandboxes with kept reasons.",parameters:c.Object({workdir:c.Optional(c.String({description:"Restrict cleanup to sessions rooted in this repository"})),base_branch:c.Optional(c.String({description:"Override base branch for lifecycle resolution"})),mode:c.Optional(c.Union([c.Literal("preview_safe"),c.Literal("clean_safe"),c.Literal("preview_all")],{description:"Cleanup mode. preview_safe shows what Clean all safe would remove, clean_safe performs that cleanup, preview_all shows both safe and retained worktrees. Defaults to preview_safe when dry_run=true, otherwise clean_safe."})),skip_session_check:c.Optional(c.Boolean({description:"Deprecated. Safe cleanup never removes live sessions."})),force:c.Optional(c.Boolean({description:"Deprecated alias for skip_session_check."})),dry_run:c.Optional(c.Boolean({description:"Show what would be cleaned without deleting anything."})),session:c.Optional(c.String({description:"Session name or ID to clean or dismiss."})),dismiss_session:c.Optional(c.Boolean({description:"When true and session is provided, permanently dismiss the worktree."}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!Pu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { workdir?, base_branch?, mode?, dry_run?, session?, dismiss_session? }."}]};let r=t.session,o=t.mode??(t.dry_run===!0?"preview_safe":"clean_safe"),i=o!=="clean_safe",s=o==="preview_all"||o==="clean_safe";if(r&&t.dismiss_session===!0)return{content:[{type:"text",text:await S.dismissWorktree(r)}]};let a=Wt(S);if(r&&(a=a.filter(k=>Lt(k,r)),a.length===0)){let k=Nt(S,r);if(!k.persistedSession&&!k.activeSession)return{content:[{type:"text",text:`Error: Session "${r}" not found.`}]}}if(t.workdir&&(a=a.filter(k=>k.workdir===t.workdir)),a.length===0)return{content:[{type:"text",text:"No managed worktrees matched the requested scope."}]};let l=[],d=[],u=[],f=[];for(let k of a){let{persistedSession:g,activeSession:p,resolvedLifecycle:y}=Ot(S,k,{baseBranch:t.base_branch});if(!y.cleanupSafe){if(s){let w=y.reasons.length>0?y.reasons.map(Ft).join(", "):Se(y.derivedState);d.push(`${k.name} [kept: ${w}]`)}continue}if(l.push(`${k.name} (${Se(y.derivedState)})`),!i)try{let w=k.workdir;if(!((g??p)&&F(g??p))&&k.worktreePath&&B(w,k.worktreePath,{destructive:!1}),k.worktreeBranch&&H(w,k.worktreeBranch),g){let A=y.derivedState==="merged"||y.derivedState==="released"?y.derivedState:y.lifecycle.state,I=new Date().toISOString(),b=A==="merged"?g.worktreeMergedAt:A==="dismissed"?g.worktreeDismissedAt:void 0;S.updatePersistedSession(k.id,{worktreePath:void 0,worktreeBranch:void 0,lifecycle:"terminal",worktreeState:"none",pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0,worktreeMerged:A==="merged"?!0:g.worktreeMerged,worktreeMergedAt:A==="merged"?g.worktreeMergedAt??I:g.worktreeMergedAt,worktreeLifecycle:{...g.worktreeLifecycle??y.lifecycle,state:A,updatedAt:I,resolvedAt:g.worktreeLifecycle?.resolvedAt??b??I,resolutionSource:g.worktreeLifecycle?.resolutionSource??"maintenance",baseBranch:t.base_branch??y.lifecycle.baseBranch??g.worktreeBaseBranch,targetRepo:g.worktreePrTargetRepo,pushRemote:g.worktreePushRemote,notes:y.reasons}})}u.push(`${k.name} (${Se(y.derivedState)})`)}catch(w){f.push(`${k.name}: ${w instanceof Error?w.message:String(w)}`)}}let h=[o==="clean_safe"?"Clean all safe:":o==="preview_all"?"Worktree lifecycle review:":"Clean all safe preview:"];return h.push(` SAFE ${i?"NOW":"FOUND"} (${l.length}): ${l.join(", ")||"(none)"}`),s&&h.push(` KEPT (${d.length}): ${d.join(", ")||"(none)"}`),i||(h.push(` CLEANED (${u.length}): ${u.join(", ")||"(none)"}`),h.push(` FAILURES (${f.length}): ${f.join(", ")||"(none)"}`)),{content:[{type:"text",text:h.join(`
74
- `)}]}}}}function wu(n){if(n==null)return!0;if(Array.isArray(n)||typeof n!="object")return!1;let e=n.session;return e===void 0||typeof e=="string"}function ps(n){return{name:"agent_worktree_status",description:"Show lifecycle-first worktree status for coding agent sessions. Displays product-facing lifecycle state, released handling, cleanup safety, and retained reasons.",parameters:c.Object({session:c.Optional(c.String({description:"Session name or ID to show status for (optional, shows all if omitted)"}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!wu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session? }."}]};let r=t&&typeof t=="object"?t.session:void 0,o=Wt(S);if(r&&(o=o.filter(s=>Lt(s,r)),o.length===0))return{content:[{type:"text",text:`Error: Session "${r}" not found or has no worktree.`}]};if(o.length===0)return{content:[{type:"text",text:"No sessions with worktrees found."}]};let i=[];for(let s of o){let{persistedSession:a,resolvedLifecycle:l}=Ot(S,s),d=l.cleanupSafe?"safe now":l.preserve?"preserve":"blocked";i.push(`Session: ${s.name} [${s.id}]`),i.push(` Branch: ${s.worktreeBranch??"(unknown)"} → ${l.lifecycle.baseBranch??a?.worktreeBaseBranch??"main"}`),i.push(` Repo: ${s.workdir}`),i.push(` Lifecycle:${Se(l.lifecycle.state)}`),l.derivedState!==l.lifecycle.state&&i.push(` Derived: ${Se(l.derivedState)}`),i.push(` Cleanup: ${d}`),l.evidence.prUrl&&i.push(` PR: ${l.evidence.prUrl} (${l.evidence.prState??"unknown"})`),(l.evidence.branchAheadCount!=null||l.evidence.baseAheadCount!=null)&&i.push(` Ahead: ${l.evidence.branchAheadCount??0} ahead / ${l.evidence.baseAheadCount??0} behind`),i.push(` Reasons: ${l.reasons.length>0?l.reasons.map(Ft).join(", "):"none"}`),i.push("")}return{content:[{type:"text",text:i.join(`
75
- `).trim()}]}}}}import{existsSync as bu}from"fs";function Ru(n=[]){return n.map((e,t)=>({label:`check-${t+1}`,command:e.trim()})).filter(e=>e.command.length>0)}function Pn(n,e){let t=n.goal.trim();if(!t)return{kind:"error",text:"Error: goal must not be empty."};let r=n.workdir||e.workspaceDir||_.defaultWorkdir||process.cwd();if(!bu(r))return{kind:"error",text:`Error: Working directory does not exist: ${r}`};let o=Ru(n.verifierCommands),i=n.goalMode??(o.length>0?"verifier":"ralph");if(i==="verifier"&&o.length===0)return{kind:"error",text:"Error: verifier mode requires at least one non-empty verifier command."};let s=n.harness??Y(),a=n.model??Me(s),l=Pt(s,a),d=St(s);if(!l&&(s!=="opencode"||d&&d.length>0))return{kind:"error",text:`Error: No default model configured for harness "${s}". Set plugins.entries["openclaw-code-agent"].config.harnesses.${s}.defaultModel or pass model explicitly.`};if(l&&!bt(s,l))return{kind:"error",text:`Error: Model "${a}" is not supported for harness "${s}". Use a bare Codex model id such as "gpt-5.6-sol".`};if(l&&!wt(s,l,d))return{kind:"error",text:`Error: Model "${a}" is not allowed. Permitted models: ${d?.join(", ")}`};let u=Rt(s,l,d),f=e.sessionKey||void 0,h=kt(e),k=vt(e,h||$e(r)),g=De(e,k,f),p=Ht({ctx:e,route:g,operation:"goal task"});if(p.kind==="error")return p;let y=p.route;return{kind:"resolved",goal:t,name:n.name,workdir:r,model:u,reasoningEffort:pe(s),fastMode:_e(s),systemPrompt:n.systemPrompt,allowedTools:n.allowedTools,maxIterations:n.maxIterations,permissionMode:n.permissionMode??"bypassPermissions",harness:s,loopMode:i,completionPromise:n.completionPromise,originChannel:k,originThreadId:g?.threadId,originAgentId:e.agentId||void 0,originSessionKey:f,route:y,verifierCommands:o}}function wn(n,e){return["Goal task launched.",` Name: ${n.name}`,` ID: ${n.id}`,` Dir: ${n.workdir}`,` Session: ${n.sessionName} [${n.sessionId}]`,` Harness: ${e.harness}`,` Model: ${e.model??"default"}`,...e.fastMode?[" Fast mode: enabled"]:[],` Loop mode: ${n.loopMode}`,` Max controller iterations: ${n.maxIterations}`,` Goal: "${e.goal.length>100?`${e.goal.slice(0,100)}...`:e.goal}"`,...n.loopMode==="ralph"?[` Completion promise: ${n.completionPromise}`]:[" Verifiers:",...e.verifierCommands.map(r=>` - ${r.command}`)],"","Controller iteration progress advances only when the goal controller starts another agent turn; internal agent review passes are reported in the completion summary.","","Use /agent_goal_status to follow progress or /agent_goal_stop to terminate the task in chat."].join(`
72
+ ${I.error}`,I)}]};else if(I.conflictFiles&&I.conflictFiles.length>0){let m=["Resolve merge conflicts in the following files and commit the resolution:","",...I.conflictFiles.map(w=>`- ${w}`),"",`After resolving, commit with message: "Resolve merge conflicts from ${l}"`].join(`
73
+ `);try{let w=S.spawn({prompt:m,workdir:d,name:`${t.session}-conflict-resolver`,harness:Y(),permissionMode:"bypassPermissions",multiTurn:!0,route:o?.route??i?.route,originChannel:o?.originChannel??i?.originChannel,originThreadId:o?.originThreadId??i?.originThreadId,originAgentId:o?.originAgentId??i?.originAgentId,originSessionKey:o?.originSessionKey??i?.originSessionKey});P={content:[{type:"text",text:ie(`⚠️ Merge conflicts in ${I.conflictFiles.length} file(s) — spawned conflict resolver session: ${w.name}`,I)}]}}catch(w){P={content:[{type:"text",text:ie(`❌ Merge conflicts detected, but failed to spawn resolver: ${w instanceof Error?w.message:String(w)}`,I)}]}}}else{let m=I.dirtyError?`❌ Merge blocked: ${I.error}`:`❌ Merge failed: ${I.error??"unknown error"}`;P={content:[{type:"text",text:ie(m,I)}]}}}),P}}}function Pu(n){return!!n&&typeof n=="object"}function us(n){return{name:"agent_worktree_cleanup",description:"Manage worktree cleanup with lifecycle-aware safety rules. Use preview_safe to list what Clean all safe would remove, clean_safe to execute it, or preview_all to see both safe and retained sandboxes with kept reasons.",parameters:c.Object({workdir:c.Optional(c.String({description:"Restrict cleanup to sessions rooted in this repository"})),base_branch:c.Optional(c.String({description:"Override base branch for lifecycle resolution"})),mode:c.Optional(c.Union([c.Literal("preview_safe"),c.Literal("clean_safe"),c.Literal("preview_all")],{description:"Cleanup mode. preview_safe shows what Clean all safe would remove, clean_safe performs that cleanup, preview_all shows both safe and retained worktrees. Defaults to preview_safe when dry_run=true, otherwise clean_safe."})),skip_session_check:c.Optional(c.Boolean({description:"Deprecated. Safe cleanup never removes live sessions."})),force:c.Optional(c.Boolean({description:"Deprecated alias for skip_session_check."})),dry_run:c.Optional(c.Boolean({description:"Show what would be cleaned without deleting anything."})),session:c.Optional(c.String({description:"Session name or ID to clean or dismiss."})),dismiss_session:c.Optional(c.Boolean({description:"When true and session is provided, permanently dismiss the worktree."}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!Pu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { workdir?, base_branch?, mode?, dry_run?, session?, dismiss_session? }."}]};let r=t.session,o=t.mode??(t.dry_run===!0?"preview_safe":"clean_safe"),i=o!=="clean_safe",s=o==="preview_all"||o==="clean_safe";if(r&&t.dismiss_session===!0)return{content:[{type:"text",text:await S.dismissWorktree(r)}]};let a=Ft(S);if(r&&(a=a.filter(k=>Lt(k,r)),a.length===0)){let k=Ot(S,r);if(!k.persistedSession&&!k.activeSession)return{content:[{type:"text",text:`Error: Session "${r}" not found.`}]}}if(t.workdir&&(a=a.filter(k=>k.workdir===t.workdir)),a.length===0)return{content:[{type:"text",text:"No managed worktrees matched the requested scope."}]};let l=[],d=[],u=[],f=[];for(let k of a){let{persistedSession:h,activeSession:p,resolvedLifecycle:y}=Wt(S,k,{baseBranch:t.base_branch});if(!y.cleanupSafe){if(s){let P=y.reasons.length>0?y.reasons.map(Bt).join(", "):Se(y.derivedState);d.push(`${k.name} [kept: ${P}]`)}continue}if(l.push(`${k.name} (${Se(y.derivedState)})`),!i)try{let P=k.workdir;if(!((h??p)&&L(h??p))&&k.worktreePath&&B(P,k.worktreePath,{destructive:!1}),k.worktreeBranch&&H(P,k.worktreeBranch),h){let A=y.derivedState==="merged"||y.derivedState==="released"?y.derivedState:y.lifecycle.state,I=new Date().toISOString(),R=A==="merged"?h.worktreeMergedAt:A==="dismissed"?h.worktreeDismissedAt:void 0;S.updatePersistedSession(k.id,{worktreePath:void 0,worktreeBranch:void 0,lifecycle:"terminal",worktreeState:"none",pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0,worktreeMerged:A==="merged"?!0:h.worktreeMerged,worktreeMergedAt:A==="merged"?h.worktreeMergedAt??I:h.worktreeMergedAt,worktreeLifecycle:{...h.worktreeLifecycle??y.lifecycle,state:A,updatedAt:I,resolvedAt:h.worktreeLifecycle?.resolvedAt??R??I,resolutionSource:h.worktreeLifecycle?.resolutionSource??"maintenance",baseBranch:t.base_branch??y.lifecycle.baseBranch??h.worktreeBaseBranch,targetRepo:h.worktreePrTargetRepo,pushRemote:h.worktreePushRemote,notes:y.reasons}})}u.push(`${k.name} (${Se(y.derivedState)})`)}catch(P){f.push(`${k.name}: ${P instanceof Error?P.message:String(P)}`)}}let g=[o==="clean_safe"?"Clean all safe:":o==="preview_all"?"Worktree lifecycle review:":"Clean all safe preview:"];return g.push(` SAFE ${i?"NOW":"FOUND"} (${l.length}): ${l.join(", ")||"(none)"}`),s&&g.push(` KEPT (${d.length}): ${d.join(", ")||"(none)"}`),i||(g.push(` CLEANED (${u.length}): ${u.join(", ")||"(none)"}`),g.push(` FAILURES (${f.length}): ${f.join(", ")||"(none)"}`)),{content:[{type:"text",text:g.join(`
74
+ `)}]}}}}function wu(n){if(n==null)return!0;if(Array.isArray(n)||typeof n!="object")return!1;let e=n.session;return e===void 0||typeof e=="string"}function ps(n){return{name:"agent_worktree_status",description:"Show lifecycle-first worktree status for coding agent sessions. Displays product-facing lifecycle state, released handling, cleanup safety, and retained reasons.",parameters:c.Object({session:c.Optional(c.String({description:"Session name or ID to show status for (optional, shows all if omitted)"}))}),async execute(e,t){if(!S)return{content:[{type:"text",text:"Error: SessionManager not initialized. The code-agent service must be running."}]};if(!wu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { session? }."}]};let r=t&&typeof t=="object"?t.session:void 0,o=Ft(S);if(r&&(o=o.filter(s=>Lt(s,r)),o.length===0))return{content:[{type:"text",text:`Error: Session "${r}" not found or has no worktree.`}]};if(o.length===0)return{content:[{type:"text",text:"No sessions with worktrees found."}]};let i=[];for(let s of o){let{persistedSession:a,resolvedLifecycle:l}=Wt(S,s),d=l.cleanupSafe?"safe now":l.preserve?"preserve":"blocked";i.push(`Session: ${s.name} [${s.id}]`),i.push(` Branch: ${s.worktreeBranch??"(unknown)"} → ${l.lifecycle.baseBranch??a?.worktreeBaseBranch??"main"}`),i.push(` Repo: ${s.workdir}`),i.push(` Lifecycle:${Se(l.lifecycle.state)}`),l.derivedState!==l.lifecycle.state&&i.push(` Derived: ${Se(l.derivedState)}`),i.push(` Cleanup: ${d}`),l.evidence.prUrl&&i.push(` PR: ${l.evidence.prUrl} (${l.evidence.prState??"unknown"})`),(l.evidence.branchAheadCount!=null||l.evidence.baseAheadCount!=null)&&i.push(` Ahead: ${l.evidence.branchAheadCount??0} ahead / ${l.evidence.baseAheadCount??0} behind`),i.push(` Reasons: ${l.reasons.length>0?l.reasons.map(Bt).join(", "):"none"}`),i.push("")}return{content:[{type:"text",text:i.join(`
75
+ `).trim()}]}}}}import{existsSync as bu}from"fs";function Ru(n=[]){return n.map((e,t)=>({label:`check-${t+1}`,command:e.trim()})).filter(e=>e.command.length>0)}function Pn(n,e){let t=n.goal.trim();if(!t)return{kind:"error",text:"Error: goal must not be empty."};let r=n.workdir||e.workspaceDir||_.defaultWorkdir||process.cwd();if(!bu(r))return{kind:"error",text:`Error: Working directory does not exist: ${r}`};let o=Ru(n.verifierCommands),i=n.goalMode??(o.length>0?"verifier":"ralph");if(i==="verifier"&&o.length===0)return{kind:"error",text:"Error: verifier mode requires at least one non-empty verifier command."};let s=n.harness??Y(),a=n.model??Me(s),l=wt(s,a),d=kt(s);if(!l&&(s!=="opencode"||d&&d.length>0))return{kind:"error",text:`Error: No default model configured for harness "${s}". Set plugins.entries["openclaw-code-agent"].config.harnesses.${s}.defaultModel or pass model explicitly.`};if(l&&!Rt(s,l))return{kind:"error",text:`Error: Model "${a}" is not supported for harness "${s}". Use a bare Codex model id such as "gpt-5.6-sol".`};if(l&&!bt(s,l,d))return{kind:"error",text:`Error: Model "${a}" is not allowed. Permitted models: ${d?.join(", ")}`};let u=At(s,l,d),f=e.sessionKey||void 0,g=vt(e),k=Pt(e,g||$e(r)),h=De(e,k,f),p=Qt({ctx:e,route:h,operation:"goal task"});if(p.kind==="error")return p;let y=p.route;return{kind:"resolved",goal:t,name:n.name,workdir:r,model:u,reasoningEffort:pe(s),fastMode:_e(s),systemPrompt:n.systemPrompt,allowedTools:n.allowedTools,maxIterations:n.maxIterations,permissionMode:n.permissionMode??"bypassPermissions",harness:s,loopMode:i,completionPromise:n.completionPromise,originChannel:k,originThreadId:h?.threadId,originAgentId:e.agentId||void 0,originSessionKey:f,route:y,verifierCommands:o}}function wn(n,e){return["Goal task launched.",` Name: ${n.name}`,` ID: ${n.id}`,` Dir: ${n.workdir}`,` Session: ${n.sessionName} [${n.sessionId}]`,` Harness: ${e.harness}`,` Model: ${e.model??"default"}`,...e.fastMode?[" Fast mode: enabled"]:[],` Loop mode: ${n.loopMode}`,` Max controller iterations: ${n.maxIterations}`,` Goal: "${e.goal.length>100?`${e.goal.slice(0,100)}...`:e.goal}"`,...n.loopMode==="ralph"?[` Completion promise: ${n.completionPromise}`]:[" Verifiers:",...e.verifierCommands.map(r=>` - ${r.command}`)],"","Controller iteration progress advances only when the goal controller starts another agent turn; internal agent review passes are reported in the completion summary.","","Use /agent_goal_status to follow progress or /agent_goal_stop to terminate the task in chat."].join(`
76
76
  `)}function Au(n){return!n||typeof n!="object"?!1:typeof n.goal=="string"}function cs(n){return{name:"agent_goal_launch",description:"Launch an explicit goal loop. Use this only when the user specifically asks for a goal task, Ralph-style autonomous loop, iterative loop, autonomous repair loop, or keep-going-until-checks-pass workflow. This is not the default session path.",parameters:c.Object({goal:c.String({description:"End goal for the autonomous task"}),verifier_commands:c.Optional(c.Array(c.String({description:"Shell command that must pass for the goal to be considered complete"}),{minItems:1,description:"Verifier commands run after each coding turn"})),name:c.Optional(c.String({description:"Short task name (kebab-case preferred)"})),workdir:c.Optional(c.String({description:"Working directory (defaults to cwd / configured workspace)"})),model:c.Optional(c.String({description:"Model name to use"})),system_prompt:c.Optional(c.String({description:"Additional system prompt"})),allowed_tools:c.Optional(c.Array(c.String(),{description:"Allowed tools for the underlying agent session"})),max_iterations:c.Optional(c.Number({description:"Maximum verifier-driven repair iterations",minimum:1})),goal_mode:c.Optional(c.Union([c.Literal("ralph"),c.Literal("verifier")],{description:"Loop strategy. 'ralph' repeats until a completion promise appears. 'verifier' repeats until verifier commands pass. Defaults to 'ralph' when no verifiers are provided, otherwise 'verifier'."})),completion_promise:c.Optional(c.String({description:"Exact completion promise for Ralph-mode loops. Defaults to 'DONE'."})),permission_mode:c.Optional(c.Union([c.Literal("default"),c.Literal("plan"),c.Literal("bypassPermissions")],{description:"Permission mode for the underlying agent session. Defaults to bypassPermissions for autonomous goal loops."})),harness:c.Optional(c.String({description:"Agent harness to use ('claude-code', 'codex', or experimental 'opencode')."}))}),async execute(e,t){if(!$)return{content:[{type:"text",text:"Error: GoalController not initialized. The code-agent service must be running."}]};if(!Au(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected at least { goal }."}]};let r=Pn({goal:t.goal,verifierCommands:t.verifier_commands,name:t.name,workdir:t.workdir,model:t.model,systemPrompt:t.system_prompt,allowedTools:t.allowed_tools,maxIterations:t.max_iterations,permissionMode:t.permission_mode,harness:t.harness,goalMode:t.goal_mode,completionPromise:t.completion_promise},n);if(r.kind!=="resolved")return{content:[{type:"text",text:r.text}]};try{let o=await $.launchTask({goal:r.goal,name:r.name,workdir:r.workdir,model:r.model,reasoningEffort:r.reasoningEffort,fastMode:r.fastMode,systemPrompt:r.systemPrompt,allowedTools:r.allowedTools,maxIterations:r.maxIterations,permissionMode:r.permissionMode,loopMode:r.loopMode,completionPromise:r.completionPromise,originChannel:r.originChannel,originThreadId:r.originThreadId,originAgentId:r.originAgentId,originSessionKey:r.originSessionKey,route:r.route,harness:r.harness,verifierCommands:r.verifierCommands});return{content:[{type:"text",text:wn(o,r)}]}}catch(o){return{content:[{type:"text",text:`Error launching goal task: ${o instanceof Error?o.message:String(o)}`}]}}}}}function ro(n,e){return n.split(`
77
77
  `).map(t=>`${e}${t}`)}function ms(n,e){return n.length<=e?n:`${n.slice(0,e-3).trimEnd()}...`}function Iu(n,e=8,t=600){let r=n.map(i=>i.trimEnd()).filter(i=>i.trim().length>0);if(r.length===0)return;let o=r.slice(-e).join(`
78
78
  `);return o.length<=t?o:`...${o.slice(-(t-3))}`}function Tu(n,e){let t=e?.trim(),r=(n??"").split(/\r?\n/).map(o=>o.trim().replace(/^[-*]\s+/,"")).filter(o=>o.length>0).filter(o=>!(t&&o===t)).filter(o=>!/^<promise>.*<\/promise>$/.test(o));return r.length===0?[]:r.slice(-3).map(o=>ms(o,180))}function xu(n){let e=(n??"").split(/\r?\n/).map(t=>t.trim()).filter(t=>t.length>0);return e.length===0?[]:e.slice(0,2).map(t=>ms(t,180))}function bn(n){let e=[],t=xu(n.verifierSummary),r=Tu(n.output,n.completionPromise);if(t.length===0&&r.length===0)return;n.completionDetected===!0&&e.push("Completion was claimed, but the loop is continuing after verification.");for(let i of t)e.push(`Verifier: ${i}`);let o=Math.max(0,3-e.length);if(o>0)for(let i of r.slice(-o))e.push(`Agent: ${i}`);return["Iteration summary:",...e.map(i=>`- ${i}`)].join(`
79
79
  `)}function oo(n){if(n)return{phase:n.phase,awaitingInput:n.isAwaitingInput??!!n.pendingInputState,latestOutput:Iu(n.getOutput(20))}}function io(n,e,t){let r=n.loopMode??"verifier",o=[`${n.name} [${n.id}]`,` Status: ${n.status}`,...r==="ralph"?[" Loop mode: ralph",` Iteration: ${n.iteration}/${n.maxIterations}`]:[` Repair iteration: ${n.iteration}/${n.maxIterations}`],` Workdir: ${n.workdir}`];return r==="ralph"&&n.completionPromise&&o.push(` Completion promise: ${n.completionPromise}`),n.sessionId&&o.push(` Session: ${n.sessionName??"(unknown)"} [${n.sessionId}]`),e?.phase&&o.push(` Phase: ${e.phase}`),e?.awaitingInput!==void 0&&o.push(` Awaiting input: ${e.awaitingInput?"yes":"no"}`),t&&o.push(...ro(t," ")),n.lastVerifierSummary&&(o.push(" Last verifier:"),o.push(...ro(n.lastVerifierSummary," "))),e?.latestOutput&&(o.push(" Latest activity:"),o.push(...ro(e.latestOutput," "))),n.waitingForUserReason&&o.push(` Waiting on user: ${n.waitingForUserReason}`),n.failureReason&&o.push(` Failure: ${n.failureReason}`),o.join(`
80
80
  `)}var X="Error: GoalController not initialized. The code-agent service must be running.";function Rn(n,e,t){let r=t?.trim();if(r){let i=n.getTask(r);if(!i)return`Error: Goal task "${r}" not found.`;let s=i.sessionId?e(i.sessionId):void 0;return io(i,oo(s))}let o=n.listTasks();return o.length===0?"No goal tasks found.":o.map(i=>{let s=i.sessionId?e(i.sessionId):void 0;return io(i,oo(s))}).join(`
81
81
 
82
- `)}function An(n,e){return n?n.action==="already_terminal"?`Task is already ${n.task.status}.`:`Task "${n.task.name}" (${n.task.id}) stopped.`:`Error: Goal task "${e}" not found.`}function In(n,e){switch(n.action){case"updated":return`Task "${n.task.name}" (${n.task.id}) goal updated.`;case"not_found":return`Error: Goal task "${e}" not found.`;case"invalid_goal":return"Error: replacement goal must not be empty.";case"not_editable":return n.task.status!=="waiting_for_user"?`Task is already ${n.task.status}.`:`Error: Goal task "${n.task.name}" is ${n.task.status} and cannot be edited.`}}function fs(n){return{name:"agent_goal_status",description:"Show status for explicit goal tasks managed by the goal controller. Use this to inspect one goal task or list all goal tasks.",parameters:c.Object({task:c.Optional(c.String({description:"Task name or ID. Omit to list all tasks."}))}),async execute(e,t){if(!$)return{content:[{type:"text",text:X}]};let r=t&&typeof t=="object"&&typeof t.task=="string"?t.task:void 0;return{content:[{type:"text",text:Rn($,o=>S?.resolve(o),r)}]}}}}function Cu(n){return!!n&&typeof n=="object"&&typeof n.task=="string"}function gs(n){return{name:"agent_goal_stop",description:"Stop an explicit goal task and kill its underlying agent session.",parameters:c.Object({task:c.String({description:"Goal task name or ID"})}),async execute(e,t){if(!$)return{content:[{type:"text",text:X}]};if(!Cu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { task }."}]};let r=$.stopTask(t.task);return{content:[{type:"text",text:An(r,t.task)}]}}}}function Mu(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.task=="string"&&typeof e.goal=="string"}function hs(n){return{name:"agent_goal_edit",description:"Edit the goal text for an active goal task without stopping or relaunching its session.",parameters:c.Object({task:c.String({description:"Goal task name or ID"}),goal:c.String({description:"Replacement goal text"})}),async execute(e,t){if(!$)return{content:[{type:"text",text:X}]};if(!Mu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { task, goal }."}]};let r=$.editTask(t.task,t.goal);return{content:[{type:"text",text:In(r,t.task)}]}}}}var so=new Set,ys="⚠️ Could not submit that answer. The question prompt is still active; try again or reply with the answer.",dt=new Map;function _u(n){return`${n.sessionId}:${n.pendingInputRequestId??n.id}`}function Du(n){return!!(n&&n.status!=="running"&&ke(n).kind==="resume")}function $u(n){return n.label?.trim()?["[SYSTEM: The gateway restarted while a user question was pending. Treat the user's selection below as the answer to that interrupted question and continue without asking it again.]","",n.pendingInputQuestionId?`Question ID: ${n.pendingInputQuestionId}`:"Question: the interrupted pending question",`Selected answer: ${n.label.trim()}`].join(`
83
- `):void 0}async function Ps(n){try{await n}catch(e){let t=e instanceof Error?e.message:String(e);`${t}`}}async function Ss(n,e,t){if(!n)return t();for(;;){let o=dt.get(n)?.operation;if(!o)break;await Ps(o)}let r=Promise.resolve().then(t);dt.set(n,{operation:r,tokenId:e});try{return await r}finally{dt.get(n)?.operation===r&&dt.delete(n)}}function Eu(n){let e=n.trim().replace(new RegExp(`^${W}:`),"");return e||null}function Nu(n){return n.trim().startsWith(`${W}:`)}async function Tn(n,e=!1){if(n.channel==="telegram")try{return(await N(n,{alreadyAcknowledged:e,forceTelegramMarkupEdit:!0})).textDelivered}catch(r){let o=r instanceof Error?r.message:String(r);return`${o}`,!1}let t=n.respond;if(typeof t.clearComponents=="function")try{return await t.clearComponents(),!1}catch(r){if(be(r))return!1;let o=r instanceof Error?r.message:String(r);`${o}`}if(typeof t.clearButtons=="function")try{await t.clearButtons()}catch(r){let o=r instanceof Error?r.message:String(r);`${o}`}else!e&&typeof t.acknowledge=="function"&&await t.acknowledge();return!1}async function ne(n,e=!1){await N(n,{alreadyAcknowledged:e,forceTelegramMarkupEdit:n.channel==="telegram"})}function Mn(n){if(n&&typeof n=="object"&&"content"in n&&Array.isArray(n.content)){let e=n.content[0];return typeof e?.text=="string"?e.text:"(done)"}return"(done)"}function ks(n){if(n&&typeof n=="object"&&"meta"in n){let e=n.meta;if(typeof e?.success=="boolean")return e.success}return uo(Mn(n))}function uo(n){return!/^\s*(?:Error\b:?|❌|⚠️)/.test(n)}function _n(n){return n==="plan-approve"||n==="plan-request-changes"||n==="plan-reject"}function Ou(n){if(_n(n.kind))return`${n.sessionId}:v${n.planDecisionVersion??"unknown"}`}function Wu(n){return n?n.approvalState==="approved"||!n.pendingPlanApproval:!1}function ao(n,e){if(!_n(n.kind))return;if(!e)return"This plan decision is stale because the session is no longer available.";let t=Fr(e);if(n.planDecisionVersion!=null&&t!=null&&n.planDecisionVersion!==t)return"This plan decision is stale because a newer plan review state already exists.";if(!e.pendingPlanApproval)return"This plan is no longer awaiting approval.";if(n.kind==="plan-approve"&&e.approvalState==="changes_requested"&&!e.pendingPlanApproval)return"Changes were already requested for this plan. Wait for the revised plan before approving.";if(n.kind==="plan-request-changes"&&e.approvalState==="changes_requested")return"Changes were already requested for this plan. Send your feedback to the agent instead."}function ws(n,...e){return e.find(t=>typeof t=="string"&&n(t))}function xn(...n){return ws(e=>e.trim().length>0,...n)}function vs(...n){return ws(Nu,...n)}function Lu(n){let e="callback"in n?vs(n.callback?.data,n.callback?.callback_data,n.callback?.callbackData):void 0;if(e)return e;let t="interaction"in n?n.interaction:void 0,r=vs(t?.data,t?.callback_data,t?.callbackData);if(r)return r;let o="callback"in n?xn(n.callback?.payload):void 0;if(o)return o;let i=xn(t?.payload);return i||(("callback"in n?xn(n.callback?.data,n.callback?.callback_data,n.callback?.callbackData):void 0)??xn(t?.data,t?.callback_data,t?.callbackData)??"")}function ut(n,e=new Set){if(n==null)return"";if(typeof n=="string")return n;if(typeof n=="number"||typeof n=="boolean"||typeof n=="bigint")return String(n);if(n instanceof Error)return[n.name,n.message,ut(n.cause,e)].filter(Boolean).join(" ");if(typeof n!="object")return String(n);if(e.has(n))return"";e.add(n);let t=n;return[t.message,t.description,t.error,t.error_description,ut(t.cause,e),ut(t.response,e),ut(t.payload,e)].filter(Boolean).join(" ")}function be(n){return/message is not modified/i.test(ut(n))}function Fu(n){let e=n instanceof Error?n.message:String(n);return/empty message/i.test(e)}async function we(n){if(typeof n.clearButtons=="function")try{await n.clearButtons()}catch(e){if(be(e))return;throw e}}async function N(n,e={}){let t=n.respond,{alreadyAcknowledged:r=!1,forceTelegramMarkupEdit:o=!1,text:i}=e;if(n.channel==="telegram"){if(typeof i=="string"&&typeof t.editMessage=="function")try{return await t.editMessage({text:i,buttons:[]}),await we(t),{textDelivered:!0}}catch(a){if(be(a))return await we(t),{textDelivered:!0};let l=a instanceof Error?a.message:String(a);`${l}`}if(o&&typeof t.editButtons=="function")try{return await t.editButtons({buttons:[]}),await we(t),{textDelivered:!1}}catch(a){if(be(a))return await we(t),{textDelivered:!1};let l=a instanceof Error?a.message:String(a);`${l}`}let s="callback"in n&&typeof n.callback?.messageText=="string"?n.callback.messageText:void 0;if(o&&typeof s=="string"&&typeof t.editMessage=="function")try{return await t.editMessage({text:s,buttons:[]}),await we(t),{textDelivered:!1}}catch(a){if(be(a))return await we(t),{textDelivered:!1};let l=a instanceof Error?a.message:String(a);`${l}`}return await we(t),{textDelivered:!1}}if(typeof t.clearComponents=="function")try{return await t.clearComponents(typeof i=="string"?{text:i}:void 0),{textDelivered:typeof i=="string"}}catch(s){if(be(s))return{textDelivered:typeof i=="string"};if(Fu(s)){if(typeof i!="string"&&r)return{textDelivered:!1};if(typeof i!="string"&&typeof t.acknowledge=="function")return await t.acknowledge(),{textDelivered:!1};typeof i!="string"&&t.acknowledge}else{if(typeof i!="string")throw s;{let a=s instanceof Error?s.message:String(s);`${a}`}}}if(typeof i=="string"&&typeof t.editMessage=="function"){try{await t.editMessage({text:i})}catch(s){if(be(s))return typeof t.clearButtons=="function"&&await t.clearButtons(),{textDelivered:!0};let a=s instanceof Error?s.message:String(s);return`${a}`,typeof t.clearButtons=="function"&&await t.clearButtons(),{textDelivered:!1}}return typeof t.clearButtons=="function"&&await t.clearButtons(),{textDelivered:!0}}return typeof t.clearButtons=="function"&&await t.clearButtons(),{textDelivered:!1}}async function Bu(n){let e=n.respond;if(typeof e.acknowledge!="function")return!1;try{return await e.acknowledge(),!0}catch(t){let r=t instanceof Error?t.message:String(t);return`${r}`,!1}}async function x(n,e){if(n.channel==="telegram"){await n.respond.reply({text:e});return}await n.respond.reply({text:e,ephemeral:!0})}var Ku="⚠️ This action is stale or has already been used.";async function qe(n,e){try{await e()}catch(t){let r=t instanceof Error?t.message:String(t);`${r}`}try{await x(n,Ku)}catch(t){let r=t instanceof Error?t.message:String(t);`${r}`}}async function Cn(n,e){try{await N(n,{alreadyAcknowledged:e,forceTelegramMarkupEdit:!0})}catch(t){let r=t instanceof Error?t.message:String(t);`${r}`}}var lo=["plan-approve","plan-request-changes","plan-reject"];function qu(n){switch(n){case"plan-approve":return"Approve";case"plan-request-changes":return"Revise";case"plan-reject":return"Reject";default:return"Continue"}}function Vu(n){switch(n){case"plan-approve":return"primary";case"plan-reject":return"danger";default:return"secondary"}}function Uu(n,e){let t=n,o=(typeof t?.listActiveActionTokens=="function"?lo.flatMap(a=>t.listActiveActionTokens?.(a)??[]):[e]).filter(a=>_n(a.kind)&&a.sessionId===e.sessionId&&(e.planDecisionVersion==null||a.planDecisionVersion==null||a.planDecisionVersion===e.planDecisionVersion)).sort((a,l)=>lo.indexOf(a.kind)-lo.indexOf(l.kind)),i=new Set,s=o.filter(a=>i.has(a.kind)?!1:(i.add(a.kind),!0)).map(a=>({label:typeof a.label=="string"&&a.label.trim()?a.label:qu(a.kind),callbackData:`${W}:${a.id}`,style:Vu(a.kind)}));return s.length>0?[s]:void 0}async function Gu(n,e,t,r){if(n.channel!=="telegram"){await x(n,e);return}let o=Uu(t,r);await n.respond.reply({text:o?`${e}
82
+ `)}function An(n,e){return n?n.action==="already_terminal"?`Task is already ${n.task.status}.`:`Task "${n.task.name}" (${n.task.id}) stopped.`:`Error: Goal task "${e}" not found.`}function In(n,e){switch(n.action){case"updated":return`Task "${n.task.name}" (${n.task.id}) goal updated.`;case"not_found":return`Error: Goal task "${e}" not found.`;case"invalid_goal":return"Error: replacement goal must not be empty.";case"not_editable":return n.task.status!=="waiting_for_user"?`Task is already ${n.task.status}.`:`Error: Goal task "${n.task.name}" is ${n.task.status} and cannot be edited.`}}function fs(n){return{name:"agent_goal_status",description:"Show status for explicit goal tasks managed by the goal controller. Use this to inspect one goal task or list all goal tasks.",parameters:c.Object({task:c.Optional(c.String({description:"Task name or ID. Omit to list all tasks."}))}),async execute(e,t){if(!$)return{content:[{type:"text",text:X}]};let r=t&&typeof t=="object"&&typeof t.task=="string"?t.task:void 0;return{content:[{type:"text",text:Rn($,o=>S?.resolve(o),r)}]}}}}function Cu(n){return!!n&&typeof n=="object"&&typeof n.task=="string"}function gs(n){return{name:"agent_goal_stop",description:"Stop an explicit goal task and kill its underlying agent session.",parameters:c.Object({task:c.String({description:"Goal task name or ID"})}),async execute(e,t){if(!$)return{content:[{type:"text",text:X}]};if(!Cu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { task }."}]};let r=$.stopTask(t.task);return{content:[{type:"text",text:An(r,t.task)}]}}}}function Mu(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.task=="string"&&typeof e.goal=="string"}function hs(n){return{name:"agent_goal_edit",description:"Edit the goal text for an active goal task without stopping or relaunching its session.",parameters:c.Object({task:c.String({description:"Goal task name or ID"}),goal:c.String({description:"Replacement goal text"})}),async execute(e,t){if(!$)return{content:[{type:"text",text:X}]};if(!Mu(t))return{content:[{type:"text",text:"Error: Invalid parameters. Expected { task, goal }."}]};let r=$.editTask(t.task,t.goal);return{content:[{type:"text",text:In(r,t.task)}]}}}}var so=new Set,ys="⚠️ Could not submit that answer. The question prompt is still active; try again or reply with the answer.",ut=new Map;function _u(n){return`${n.sessionId}:${n.pendingInputRequestId??n.id}`}function Du(n){return!!(n&&n.status!=="running"&&ke(n).kind==="resume")}function $u(n){return n.label?.trim()?["[SYSTEM: The gateway restarted while a user question was pending. Treat the user's selection below as the answer to that interrupted question and continue without asking it again.]","",n.pendingInputQuestionId?`Question ID: ${n.pendingInputQuestionId}`:"Question: the interrupted pending question",`Selected answer: ${n.label.trim()}`].join(`
83
+ `):void 0}async function Ps(n){try{await n}catch(e){let t=e instanceof Error?e.message:String(e);`${t}`}}async function Ss(n,e,t){if(!n)return t();for(;;){let o=ut.get(n)?.operation;if(!o)break;await Ps(o)}let r=Promise.resolve().then(t);ut.set(n,{operation:r,tokenId:e});try{return await r}finally{ut.get(n)?.operation===r&&ut.delete(n)}}function Eu(n){let e=n.trim().replace(new RegExp(`^${W}:`),"");return e||null}function Nu(n){return n.trim().startsWith(`${W}:`)}async function Tn(n,e=!1){if(n.channel==="telegram")try{return(await N(n,{alreadyAcknowledged:e,forceTelegramMarkupEdit:!0})).textDelivered}catch(r){let o=r instanceof Error?r.message:String(r);return`${o}`,!1}let t=n.respond;if(typeof t.clearComponents=="function")try{return await t.clearComponents(),!1}catch(r){if(be(r))return!1;let o=r instanceof Error?r.message:String(r);`${o}`}if(typeof t.clearButtons=="function")try{await t.clearButtons()}catch(r){let o=r instanceof Error?r.message:String(r);`${o}`}else!e&&typeof t.acknowledge=="function"&&await t.acknowledge();return!1}async function ne(n,e=!1){await N(n,{alreadyAcknowledged:e,forceTelegramMarkupEdit:n.channel==="telegram"})}function Mn(n){if(n&&typeof n=="object"&&"content"in n&&Array.isArray(n.content)){let e=n.content[0];return typeof e?.text=="string"?e.text:"(done)"}return"(done)"}function ks(n){if(n&&typeof n=="object"&&"meta"in n){let e=n.meta;if(typeof e?.success=="boolean")return e.success}return uo(Mn(n))}function uo(n){return!/^\s*(?:Error\b:?|❌|⚠️)/.test(n)}function _n(n){return n==="plan-approve"||n==="plan-request-changes"||n==="plan-reject"}function Ou(n){if(_n(n.kind))return`${n.sessionId}:v${n.planDecisionVersion??"unknown"}`}function Wu(n){return n?n.approvalState==="approved"||!n.pendingPlanApproval:!1}function ao(n,e){if(!_n(n.kind))return;if(!e)return"This plan decision is stale because the session is no longer available.";let t=Lr(e);if(n.planDecisionVersion!=null&&t!=null&&n.planDecisionVersion!==t)return"This plan decision is stale because a newer plan review state already exists.";if(!e.pendingPlanApproval)return"This plan is no longer awaiting approval.";if(n.kind==="plan-approve"&&e.approvalState==="changes_requested"&&!e.pendingPlanApproval)return"Changes were already requested for this plan. Wait for the revised plan before approving.";if(n.kind==="plan-request-changes"&&e.approvalState==="changes_requested")return"Changes were already requested for this plan. Send your feedback to the agent instead."}function ws(n,...e){return e.find(t=>typeof t=="string"&&n(t))}function xn(...n){return ws(e=>e.trim().length>0,...n)}function vs(...n){return ws(Nu,...n)}function Fu(n){let e="callback"in n?vs(n.callback?.data,n.callback?.callback_data,n.callback?.callbackData):void 0;if(e)return e;let t="interaction"in n?n.interaction:void 0,r=vs(t?.data,t?.callback_data,t?.callbackData);if(r)return r;let o="callback"in n?xn(n.callback?.payload):void 0;if(o)return o;let i=xn(t?.payload);return i||(("callback"in n?xn(n.callback?.data,n.callback?.callback_data,n.callback?.callbackData):void 0)??xn(t?.data,t?.callback_data,t?.callbackData)??"")}function pt(n,e=new Set){if(n==null)return"";if(typeof n=="string")return n;if(typeof n=="number"||typeof n=="boolean"||typeof n=="bigint")return String(n);if(n instanceof Error)return[n.name,n.message,pt(n.cause,e)].filter(Boolean).join(" ");if(typeof n!="object")return String(n);if(e.has(n))return"";e.add(n);let t=n;return[t.message,t.description,t.error,t.error_description,pt(t.cause,e),pt(t.response,e),pt(t.payload,e)].filter(Boolean).join(" ")}function be(n){return/message is not modified/i.test(pt(n))}function Lu(n){let e=n instanceof Error?n.message:String(n);return/empty message/i.test(e)}async function we(n){if(typeof n.clearButtons=="function")try{await n.clearButtons()}catch(e){if(be(e))return;throw e}}async function N(n,e={}){let t=n.respond,{alreadyAcknowledged:r=!1,forceTelegramMarkupEdit:o=!1,text:i}=e;if(n.channel==="telegram"){if(typeof i=="string"&&typeof t.editMessage=="function")try{return await t.editMessage({text:i,buttons:[]}),await we(t),{textDelivered:!0}}catch(a){if(be(a))return await we(t),{textDelivered:!0};let l=a instanceof Error?a.message:String(a);`${l}`}if(o&&typeof t.editButtons=="function")try{return await t.editButtons({buttons:[]}),await we(t),{textDelivered:!1}}catch(a){if(be(a))return await we(t),{textDelivered:!1};let l=a instanceof Error?a.message:String(a);`${l}`}let s="callback"in n&&typeof n.callback?.messageText=="string"?n.callback.messageText:void 0;if(o&&typeof s=="string"&&typeof t.editMessage=="function")try{return await t.editMessage({text:s,buttons:[]}),await we(t),{textDelivered:!1}}catch(a){if(be(a))return await we(t),{textDelivered:!1};let l=a instanceof Error?a.message:String(a);`${l}`}return await we(t),{textDelivered:!1}}if(typeof t.clearComponents=="function")try{return await t.clearComponents(typeof i=="string"?{text:i}:void 0),{textDelivered:typeof i=="string"}}catch(s){if(be(s))return{textDelivered:typeof i=="string"};if(Lu(s)){if(typeof i!="string"&&r)return{textDelivered:!1};if(typeof i!="string"&&typeof t.acknowledge=="function")return await t.acknowledge(),{textDelivered:!1};typeof i!="string"&&t.acknowledge}else{if(typeof i!="string")throw s;{let a=s instanceof Error?s.message:String(s);`${a}`}}}if(typeof i=="string"&&typeof t.editMessage=="function"){try{await t.editMessage({text:i})}catch(s){if(be(s))return typeof t.clearButtons=="function"&&await t.clearButtons(),{textDelivered:!0};let a=s instanceof Error?s.message:String(s);return`${a}`,typeof t.clearButtons=="function"&&await t.clearButtons(),{textDelivered:!1}}return typeof t.clearButtons=="function"&&await t.clearButtons(),{textDelivered:!0}}return typeof t.clearButtons=="function"&&await t.clearButtons(),{textDelivered:!1}}async function Bu(n){let e=n.respond;if(typeof e.acknowledge!="function")return!1;try{return await e.acknowledge(),!0}catch(t){let r=t instanceof Error?t.message:String(t);return`${r}`,!1}}async function x(n,e){if(n.channel==="telegram"){await n.respond.reply({text:e});return}await n.respond.reply({text:e,ephemeral:!0})}var Ku="⚠️ This action is stale or has already been used.";async function qe(n,e){try{await e()}catch(t){let r=t instanceof Error?t.message:String(t);`${r}`}try{await x(n,Ku)}catch(t){let r=t instanceof Error?t.message:String(t);`${r}`}}async function Cn(n,e){try{await N(n,{alreadyAcknowledged:e,forceTelegramMarkupEdit:!0})}catch(t){let r=t instanceof Error?t.message:String(t);`${r}`}}var lo=["plan-approve","plan-request-changes","plan-reject"];function qu(n){switch(n){case"plan-approve":return"Approve";case"plan-request-changes":return"Revise";case"plan-reject":return"Reject";default:return"Continue"}}function Vu(n){switch(n){case"plan-approve":return"primary";case"plan-reject":return"danger";default:return"secondary"}}function Uu(n,e){let t=n,o=(typeof t?.listActiveActionTokens=="function"?lo.flatMap(a=>t.listActiveActionTokens?.(a)??[]):[e]).filter(a=>_n(a.kind)&&a.sessionId===e.sessionId&&(e.planDecisionVersion==null||a.planDecisionVersion==null||a.planDecisionVersion===e.planDecisionVersion)).sort((a,l)=>lo.indexOf(a.kind)-lo.indexOf(l.kind)),i=new Set,s=o.filter(a=>i.has(a.kind)?!1:(i.add(a.kind),!0)).map(a=>({label:typeof a.label=="string"&&a.label.trim()?a.label:qu(a.kind),callbackData:`${W}:${a.id}`,style:Vu(a.kind)}));return s.length>0?[s]:void 0}async function Gu(n,e,t,r){if(n.channel!=="telegram"){await x(n,e);return}let o=Uu(t,r);await n.respond.reply({text:o?`${e}
84
84
 
85
- Approval is still pending. Try again below.`:e,...o?{buttons:o}:{}})}function bs(n="telegram",e={}){let t=e.makeAgentMergeTool??vn,r=e.makeAgentPrTool??Bt;return M("callback_handler_registered",{channel:n,namespace:W}),{channel:n,namespace:W,handler:async o=>{let i=await Bu(o);if(!o.auth.isAuthorizedSender)return await x(o,"⛔ Unauthorized."),{handled:!0};let s=Lu(o),a=Eu(s);if(M("callback_received",{channel:o.channel,namespace:W,payloadByteLength:Buffer.byteLength(s,"utf8"),tokenHash:K(a),isAuthorizedSender:o.auth.isAuthorizedSender}),!a)return await x(o,"⚠️ Unrecognized callback payload."),{handled:!0};if(!S)return await x(o,"⚠️ Code agent service not running."),{handled:!0};let l=S.getActionToken(a);if(M("callback_token_lookup_completed",{channel:o.channel,namespace:W,tokenHash:K(a),tokenFound:!!l,actionKind:l?.kind,sessionId:l?.sessionId,planDecisionVersion:l?.planDecisionVersion}),!l)return await qe(o,()=>N(o,{alreadyAcknowledged:i})),{handled:!0};if(l.kind==="question-answer"&&l.consumedAt!=null)return await N(o,{alreadyAcknowledged:i}),await x(o,"⚠️ That question button is no longer active. Use the latest question prompt."),{handled:!0};let d=l.sessionId,u=S.resolve?.(d)??S.getPersistedSession?.(d),f=u?.name??d;if(u&&Br(l,u))return S.consumePlanDecisionTokens?.(d,l.planDecisionVersion),await ne(o,i),await x(o,`✅ Plan v${l.planDecisionVersion} was already approved; resume is in progress or running.`),{handled:!0};let h=ao(l,u);if(M("callback_plan_validation_completed",{channel:o.channel,namespace:W,tokenHash:K(a),actionKind:l.kind,sessionId:d,sessionName:f,planDecisionVersion:l.planDecisionVersion,valid:!h}),h)return _n(l.kind)?await ne(o,i):await N(o,{alreadyAcknowledged:i}),await x(o,`⚠️ ${h}`),{handled:!0};if(l.kind==="question-answer"){if(l.optionIndex==null)return await N(o,{alreadyAcknowledged:i}),await x(o,"⚠️ Invalid question-answer action."),{handled:!0};let p=_u(l);if(so.has(p))return await x(o,"⚠️ That answer is already being submitted. If the question remains active, try again."),{handled:!0};so.add(p);let y=!1,w=!1;try{if(y=await S.resolvePendingInputOption(d,l.optionIndex,{requestId:l.pendingInputRequestId,questionId:l.pendingInputQuestionId}),!y&&!(S.canSubmitPendingInputOption?.(d)??!1)){let b=S.getPersistedSession?.(d),m=$u(l);m&&Du(b)&&(y=!(await Q(S,{session:d,message:m,userInitiated:!0})).isError,w=y)}}catch(b){let m=b instanceof Error?b.message:String(b);return`${m}`,await x(o,ys),{handled:!0}}finally{so.delete(p)}if(!y)return await x(o,ys),{handled:!0};let A=(l.pendingInputRequestId?S.consumeQuestionAnswerTokens(d,l.pendingInputRequestId,l.pendingInputQuestionId):[]).find(b=>b.id===a)??S.consumeActionToken(a);if(M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!A,actionKind:A?.kind,sessionId:A?.sessionId,planDecisionVersion:A?.planDecisionVersion}),!A){await N(o,{alreadyAcknowledged:i});let b=!w&&(S.pendingInputSubmissionRequiresMore?.(d)??!1);return await x(o,w?"✅ Answer forwarded to the resumed session.":b?"✅ Question step answered; more input is required.":"✅ Pending input request submitted."),{handled:!0}}await N(o,{alreadyAcknowledged:i});let I=!w&&(S.pendingInputSubmissionRequiresMore?.(d)??!1);return await x(o,w?"✅ Answer forwarded to the resumed session.":I?"✅ Question step answered; more input is required.":"✅ Pending input request submitted."),{handled:!0}}let k=Ou(l);if(k)for(;;){let p=dt.get(k);if(!p)break;if(p.tokenId===a)return await ne(o,i),await x(o,"⚠️ This plan decision is already being processed."),{handled:!0};await Ps(p.operation);let y=S.getActionToken(a);if(!y)return await qe(o,()=>ne(o,i)),{handled:!0};if(d=y.sessionId,u=S.resolve?.(d)??S.getPersistedSession?.(d),f=u?.name??d,u&&Br(y,u))return S.consumePlanDecisionTokens?.(d,y.planDecisionVersion),await ne(o,i),await x(o,`✅ Plan v${y.planDecisionVersion} was already approved; resume is in progress or running.`),{handled:!0};if(h=ao(y,u),M("callback_plan_validation_completed",{channel:o.channel,namespace:W,tokenHash:K(a),actionKind:y.kind,sessionId:d,sessionName:f,planDecisionVersion:y.planDecisionVersion,valid:!h,afterPlanDecisionLock:!0}),h)return await ne(o,i),await x(o,`⚠️ ${h}`),{handled:!0};l=y}if(l.kind==="plan-approve"){let p=l,y=!1,w=async(I=!1)=>{y||!I&&o.channel!=="telegram"||(await ne(o,i),y=!0)},R=await Ss(k,a,async()=>(await w(),Q(S,{session:p.sessionId,message:"Approved. Go ahead.",approve:!0,userInitiated:!0})));if(R.isError){let I=S.resolve?.(p.sessionId)??S.getPersistedSession?.(p.sessionId),b=Wu(I);if(b){let m=S.consumeActionToken(a);M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!m,actionKind:m?.kind,sessionId:m?.sessionId??p.sessionId,planDecisionVersion:m?.planDecisionVersion,approvalAppliedAfterError:!0}),await w(!0)}return b?await x(o,`⚠️ ${R.text}`):await Gu(o,`⚠️ ${R.text}`,S,p),{handled:!0}}let A=S.consumeActionToken(a);return M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!A,actionKind:A?.kind,sessionId:A?.sessionId??p.sessionId,planDecisionVersion:A?.planDecisionVersion}),A?(await w(!0),{handled:!0}):(await qe(o,()=>w(!0)),{handled:!0})}if(l.kind==="plan-reject"||l.kind==="plan-request-changes")return await Ss(k,a,async()=>{let p=S.getActionToken(a);if(!p)return await qe(o,()=>ne(o,i)),{handled:!0};d=p.sessionId,u=S.resolve?.(d)??S.getPersistedSession?.(d),f=u?.name??d;let y=ao(p,u);if(M("callback_plan_validation_completed",{channel:o.channel,namespace:W,tokenHash:K(a),actionKind:p.kind,sessionId:d,sessionName:f,planDecisionVersion:p.planDecisionVersion,valid:!y,afterPlanDecisionLock:!0}),y)return await ne(o,i),await x(o,`⚠️ ${y}`),{handled:!0};let w=S.consumeActionToken(a);if(M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!w,actionKind:w?.kind,sessionId:w?.sessionId,planDecisionVersion:w?.planDecisionVersion}),!w)return await qe(o,()=>ne(o,i)),{handled:!0};if(await ne(o,i),w.kind==="plan-reject"){let R=Hr(S,d);await x(o,`❌ ${R.text}`)}else{let R=Qr(S,d);await x(o,`✏️ ${R.text}`)}return{handled:!0}});let g=S.consumeActionToken(a);if(M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!g,actionKind:g?.kind,sessionId:g?.sessionId,planDecisionVersion:g?.planDecisionVersion}),!g)return await qe(o,()=>N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:l.kind==="plan-offer-start"||l.kind==="plan-offer-dismiss"})),{handled:!0};switch(g.kind){case"plugin-update-install":{if(await Cn(o,i),M("callback_update_action_started",{channel:o.channel,tokenHash:K(a),actionKind:g.kind,approvedVersion:g.pluginUpdateVersion}),!de){M("callback_update_action_failed",{channel:o.channel,tokenHash:K(a),reason:"service_unavailable"}),await x(o,"⚠️ OpenClaw Code Agent update service is not running.");break}let p;try{p=await de.installConfirmed(g.pluginUpdateVersion,{route:g.route})}catch(y){M("callback_update_action_failed",{channel:o.channel,tokenHash:K(a),reason:"install_failed"}),await x(o,`⚠️ OpenClaw Code Agent update failed: ${y instanceof Error?y.message:String(y)}`);break}M("callback_update_action_completed",{channel:o.channel,tokenHash:K(a),approvedVersion:g.pluginUpdateVersion});try{await x(o,`✅ ${p}`)}catch(y){M("callback_update_confirmation_failed",{channel:o.channel,tokenHash:K(a),reason:"reply_failed"}),`${y instanceof Error?y.message:String(y)}`}break}case"plugin-update-restart":{if(await Cn(o,i),!de){await x(o,"⚠️ OpenClaw Code Agent update service is not running.");break}try{let p=await de.restartConfirmed(g.pluginUpdateVersion);await x(o,`▶️ ${p}`)}catch(p){await x(o,`⚠️ Gateway restart failed: ${p instanceof Error?p.message:String(p)}`)}break}case"plugin-update-dismiss":{await Cn(o,i);let p=de?de.dismiss(g.pluginUpdateVersion):"Dismissed OpenClaw Code Agent update reminder.";await x(o,`✅ ${p}`);break}case"plugin-update-remind-later":{await Cn(o,i);let p=de?de.remindLater(g.pluginUpdateVersion):"Will remind later about OpenClaw Code Agent update reminder.";await x(o,`✅ ${p}`);break}case"worktree-merge":{let p=await t().execute("callback",{session:d}),y=Mn(p);if(ks(p)){await Tn(o,i);break}await x(o,y);break}case"worktree-decide-later":{let p=S.snoozeWorktreeDecision(d,{notifyUser:!1});if(uo(p)){let w=`⏭️ Snoozed 24h for [${f}]`;await Tn(o,i),await x(o,w)}else await x(o,p);break}case"worktree-dismiss":{let p=await S.dismissWorktree(d),y=uo(p);y&&await Tn(o,i),await x(o,y?"✅ Discarded":p);break}case"worktree-create-pr":case"worktree-update-pr":{let p=await r().execute("callback",{session:d}),y=Mn(p);if(ks(p)){await Tn(o,i);break}await x(o,y);break}case"worktree-view-pr":{await N(o,{alreadyAcknowledged:i});let p=S.getPersistedSession?.(d),y=l.targetUrl??p?.worktreePrUrl;await x(o,y?`PR: ${y}`:"⚠️ PR URL is no longer available.");break}case"plan-offer-start":{if(!g.launchPrompt||!g.launchWorkdir){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,"⚠️ This action is missing the plan launch context.");break}let p;try{p=S.launchPlanOffer({route:g.route,prompt:g.launchPrompt,workdir:g.launchWorkdir,name:g.launchName,worktreeStrategy:g.launchWorktreeStrategy})}catch(y){let w=y instanceof Error?y.message:String(y);await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`⚠️ Failed to start planning session: ${w}`);break}await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`▶️ Planning session started: ${p.name} [${p.id}]`);break}case"plan-offer-dismiss":{await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,"✅ Dismissed.");break}case"repo-policy-set":{if(!g.repoPolicy||!g.repoPolicyWorkdir){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,"⚠️ This action is missing the repo policy context.");break}if(!g.launchPrompt||!g.launchWorkdir){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,"⚠️ This action is missing the launch context.");break}if(typeof S.resolveRepoPolicy=="function"){let w=S.resolveRepoPolicy(g.repoPolicyWorkdir);if(w.identity){let R=Ke(g.repoPolicy,w.prAvailable);if(R){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`⚠️ ${R}`);break}}}let p=S.setRepoPolicy(g.repoPolicyWorkdir,g.repoPolicy);if(!p){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`⚠️ Could not resolve a git repository for ${g.repoPolicyWorkdir}.`);break}S.clearRepoPolicyChoiceTokens(g.sessionId);let y;try{y=S.launchAfterRepoPolicyChoice({route:g.route,prompt:g.launchPrompt,workdir:g.launchWorkdir,name:g.launchName,model:g.launchModel,reasoningEffort:g.launchReasoningEffort,fastMode:g.launchFastMode,systemPrompt:g.launchSystemPrompt,allowedTools:g.launchAllowedTools,resumeSessionId:g.launchResumeSessionId,resumedFromSessionName:g.launchResumedFromSessionName,resumeWorktreeFrom:g.launchResumeWorktreeFrom,sessionIdOverride:g.launchSessionIdOverride,clearedPersistedCodexResume:g.launchClearedPersistedCodexResume,forkSession:g.launchForkSession,forceNewSession:g.launchForceNewSession,permissionMode:g.launchPermissionMode,planApproval:g.launchPlanApproval,harness:g.launchHarness,worktreeStrategy:g.launchWorktreeStrategy,worktreeBaseBranch:g.launchWorktreeBaseBranch,worktreePrTargetRepo:g.launchWorktreePrTargetRepo,originAgentId:g.launchOriginAgentId}).text}catch(w){let R=w instanceof Error?w.message:String(w);await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`⚠️ Repo policy saved, but launch failed: ${R}`);break}await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,[`✅ Repo policy saved: ${is(p.policy).title}.`,"",y].join(`
86
- `));break}case"session-restart":case"session-resume":{await N(o,{alreadyAcknowledged:i});let p=await Q(S,{session:d,message:"Continue where you left off.",userInitiated:!0});await x(o,p.isError?`⚠️ ${p.text}`:`▶️ ${p.text}`);break}case"view-output":{await N(o,{alreadyAcknowledged:i});let p=await hn().execute("callback",{session:d,lines:50});await x(o,Mn(p));break}default:{await N(o,{alreadyAcknowledged:i}),await x(o,"⚠️ Unknown callback action.");break}}return{handled:!0}}}}function Ve(n){return Rs(n).map(e=>e.value)}function Rs(n){return Array.from(n.matchAll(/"[^"]*"|'[^']*'|\S+/g),e=>{let t=e[0],r=e.index??0;return{value:ju(t),raw:t,start:r,end:r+t.length}})}function Re(n){let[e]=Rs(n);if(e)return{value:e.value,rest:n.slice(e.end).trimStart()}}function ju(n){return n.length>1&&(n.startsWith('"')&&n.endsWith('"')||n.startsWith("'")&&n.endsWith("'"))?n.slice(1,-1):n}function zu(n){return n instanceof Error?n.message:String(n)}function Hu(n){let e=Ve(n),t,r=e;return e[0]==="--name"&&e[1]&&(t=e[1],r=e.slice(2)),{name:t,prompt:r.join(" ").trim()}}function As(n){n.registerCommand({name:"agent",description:"Launch a coding agent session. Usage: /agent [--name <name>] <prompt>",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let t=(e.args??"").trim();if(!t)return{text:"Usage: /agent [--name <name>] <prompt>"};let{name:r,prompt:o}=Hu(t);if(!o)return{text:"Usage: /agent [--name <name>] <prompt>"};try{let i=Qt({prompt:o,name:r},e,S);if(i.kind!=="resolved")return{text:i.text};let s=S.spawn({prompt:o,name:r,workdir:i.workdir,model:i.resolvedModel,reasoningEffort:i.reasoningEffort,fastMode:i.fastMode,codexApprovalPolicy:i.harness==="codex"?"never":void 0,originChannel:i.originChannel,originThreadId:i.originThreadId,originAgentId:e.agentId||void 0,originSessionKey:i.originSessionKey,route:i.route,harness:i.harness,permissionMode:i.permissionMode,planApproval:i.planApproval,taskLifecycle:nn(e)});return{text:S.formatLaunchResult({prompt:o,workdir:i.workdir,harness:i.harness,permissionMode:i.permissionMode??_.permissionMode,planApproval:i.planApproval},s)}}catch(i){let s=zu(i),a=s.includes("Max sessions")?"":`
85
+ Approval is still pending. Try again below.`:e,...o?{buttons:o}:{}})}function bs(n="telegram",e={}){let t=e.makeAgentMergeTool??vn,r=e.makeAgentPrTool??Kt;return M("callback_handler_registered",{channel:n,namespace:W}),{channel:n,namespace:W,handler:async o=>{let i=await Bu(o);if(!o.auth.isAuthorizedSender)return await x(o,"⛔ Unauthorized."),{handled:!0};let s=Fu(o),a=Eu(s);if(M("callback_received",{channel:o.channel,namespace:W,payloadByteLength:Buffer.byteLength(s,"utf8"),tokenHash:K(a),isAuthorizedSender:o.auth.isAuthorizedSender}),!a)return await x(o,"⚠️ Unrecognized callback payload."),{handled:!0};if(!S)return await x(o,"⚠️ Code agent service not running."),{handled:!0};let l=S.getActionToken(a);if(M("callback_token_lookup_completed",{channel:o.channel,namespace:W,tokenHash:K(a),tokenFound:!!l,actionKind:l?.kind,sessionId:l?.sessionId,planDecisionVersion:l?.planDecisionVersion}),!l)return await qe(o,()=>N(o,{alreadyAcknowledged:i})),{handled:!0};if(l.kind==="question-answer"&&l.consumedAt!=null)return await N(o,{alreadyAcknowledged:i}),await x(o,"⚠️ That question button is no longer active. Use the latest question prompt."),{handled:!0};let d=l.sessionId,u=S.resolve?.(d)??S.getPersistedSession?.(d),f=u?.name??d;if(u&&Br(l,u))return S.consumePlanDecisionTokens?.(d,l.planDecisionVersion),await ne(o,i),await x(o,`✅ Plan v${l.planDecisionVersion} was already approved; resume is in progress or running.`),{handled:!0};let g=ao(l,u);if(M("callback_plan_validation_completed",{channel:o.channel,namespace:W,tokenHash:K(a),actionKind:l.kind,sessionId:d,sessionName:f,planDecisionVersion:l.planDecisionVersion,valid:!g}),g)return _n(l.kind)?await ne(o,i):await N(o,{alreadyAcknowledged:i}),await x(o,`⚠️ ${g}`),{handled:!0};if(l.kind==="question-answer"){if(l.optionIndex==null)return await N(o,{alreadyAcknowledged:i}),await x(o,"⚠️ Invalid question-answer action."),{handled:!0};let p=_u(l);if(so.has(p))return await x(o,"⚠️ That answer is already being submitted. If the question remains active, try again."),{handled:!0};so.add(p);let y=!1,P=!1;try{if(y=await S.resolvePendingInputOption(d,l.optionIndex,{requestId:l.pendingInputRequestId,questionId:l.pendingInputQuestionId}),!y&&!(S.canSubmitPendingInputOption?.(d)??!1)){let R=S.getPersistedSession?.(d),m=$u(l);m&&Du(R)&&(y=!(await Q(S,{session:d,message:m,userInitiated:!0})).isError,P=y)}}catch(R){let m=R instanceof Error?R.message:String(R);return`${m}`,await x(o,ys),{handled:!0}}finally{so.delete(p)}if(!y)return await x(o,ys),{handled:!0};let A=(l.pendingInputRequestId?S.consumeQuestionAnswerTokens(d,l.pendingInputRequestId,l.pendingInputQuestionId):[]).find(R=>R.id===a)??S.consumeActionToken(a);if(M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!A,actionKind:A?.kind,sessionId:A?.sessionId,planDecisionVersion:A?.planDecisionVersion}),!A){await N(o,{alreadyAcknowledged:i});let R=!P&&(S.pendingInputSubmissionRequiresMore?.(d)??!1);return await x(o,P?"✅ Answer forwarded to the resumed session.":R?"✅ Question step answered; more input is required.":"✅ Pending input request submitted."),{handled:!0}}await N(o,{alreadyAcknowledged:i});let I=!P&&(S.pendingInputSubmissionRequiresMore?.(d)??!1);return await x(o,P?"✅ Answer forwarded to the resumed session.":I?"✅ Question step answered; more input is required.":"✅ Pending input request submitted."),{handled:!0}}let k=Ou(l);if(k)for(;;){let p=ut.get(k);if(!p)break;if(p.tokenId===a)return await ne(o,i),await x(o,"⚠️ This plan decision is already being processed."),{handled:!0};await Ps(p.operation);let y=S.getActionToken(a);if(!y)return await qe(o,()=>ne(o,i)),{handled:!0};if(d=y.sessionId,u=S.resolve?.(d)??S.getPersistedSession?.(d),f=u?.name??d,u&&Br(y,u))return S.consumePlanDecisionTokens?.(d,y.planDecisionVersion),await ne(o,i),await x(o,`✅ Plan v${y.planDecisionVersion} was already approved; resume is in progress or running.`),{handled:!0};if(g=ao(y,u),M("callback_plan_validation_completed",{channel:o.channel,namespace:W,tokenHash:K(a),actionKind:y.kind,sessionId:d,sessionName:f,planDecisionVersion:y.planDecisionVersion,valid:!g,afterPlanDecisionLock:!0}),g)return await ne(o,i),await x(o,`⚠️ ${g}`),{handled:!0};l=y}if(l.kind==="plan-approve"){let p=l,y=!1,P=async(I=!1)=>{y||!I&&o.channel!=="telegram"||(await ne(o,i),y=!0)},b=await Ss(k,a,async()=>(await P(),Q(S,{session:p.sessionId,message:"Approved. Go ahead.",approve:!0,userInitiated:!0})));if(b.isError){let I=S.resolve?.(p.sessionId)??S.getPersistedSession?.(p.sessionId),R=Wu(I);if(R){let m=S.consumeActionToken(a);M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!m,actionKind:m?.kind,sessionId:m?.sessionId??p.sessionId,planDecisionVersion:m?.planDecisionVersion,approvalAppliedAfterError:!0}),await P(!0)}return R?await x(o,`⚠️ ${b.text}`):await Gu(o,`⚠️ ${b.text}`,S,p),{handled:!0}}let A=S.consumeActionToken(a);return M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!A,actionKind:A?.kind,sessionId:A?.sessionId??p.sessionId,planDecisionVersion:A?.planDecisionVersion}),A?(await P(!0),{handled:!0}):(await qe(o,()=>P(!0)),{handled:!0})}if(l.kind==="plan-reject"||l.kind==="plan-request-changes")return await Ss(k,a,async()=>{let p=S.getActionToken(a);if(!p)return await qe(o,()=>ne(o,i)),{handled:!0};d=p.sessionId,u=S.resolve?.(d)??S.getPersistedSession?.(d),f=u?.name??d;let y=ao(p,u);if(M("callback_plan_validation_completed",{channel:o.channel,namespace:W,tokenHash:K(a),actionKind:p.kind,sessionId:d,sessionName:f,planDecisionVersion:p.planDecisionVersion,valid:!y,afterPlanDecisionLock:!0}),y)return await ne(o,i),await x(o,`⚠️ ${y}`),{handled:!0};let P=S.consumeActionToken(a);if(M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!P,actionKind:P?.kind,sessionId:P?.sessionId,planDecisionVersion:P?.planDecisionVersion}),!P)return await qe(o,()=>ne(o,i)),{handled:!0};if(await ne(o,i),P.kind==="plan-reject"){let b=Hr(S,d);await x(o,`❌ ${b.text}`)}else{let b=Qr(S,d);await x(o,`✏️ ${b.text}`)}return{handled:!0}});let h=S.consumeActionToken(a);if(M("callback_token_consume_completed",{channel:o.channel,namespace:W,tokenHash:K(a),consumed:!!h,actionKind:h?.kind,sessionId:h?.sessionId,planDecisionVersion:h?.planDecisionVersion}),!h)return await qe(o,()=>N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:l.kind==="plan-offer-start"||l.kind==="plan-offer-dismiss"})),{handled:!0};switch(h.kind){case"plugin-update-install":{if(await Cn(o,i),M("callback_update_action_started",{channel:o.channel,tokenHash:K(a),actionKind:h.kind,approvedVersion:h.pluginUpdateVersion}),!de){M("callback_update_action_failed",{channel:o.channel,tokenHash:K(a),reason:"service_unavailable"}),await x(o,"⚠️ OpenClaw Code Agent update service is not running.");break}let p;try{p=await de.installConfirmed(h.pluginUpdateVersion,{route:h.route})}catch(y){M("callback_update_action_failed",{channel:o.channel,tokenHash:K(a),reason:"install_failed"}),await x(o,`⚠️ OpenClaw Code Agent update failed: ${y instanceof Error?y.message:String(y)}`);break}M("callback_update_action_completed",{channel:o.channel,tokenHash:K(a),approvedVersion:h.pluginUpdateVersion});try{await x(o,`✅ ${p}`)}catch(y){M("callback_update_confirmation_failed",{channel:o.channel,tokenHash:K(a),reason:"reply_failed"}),`${y instanceof Error?y.message:String(y)}`}break}case"plugin-update-restart":{if(await Cn(o,i),!de){await x(o,"⚠️ OpenClaw Code Agent update service is not running.");break}try{let p=await de.restartConfirmed(h.pluginUpdateVersion);await x(o,`▶️ ${p}`)}catch(p){await x(o,`⚠️ Gateway restart failed: ${p instanceof Error?p.message:String(p)}`)}break}case"plugin-update-dismiss":{await Cn(o,i);let p=de?de.dismiss(h.pluginUpdateVersion):"Dismissed OpenClaw Code Agent update reminder.";await x(o,`✅ ${p}`);break}case"plugin-update-remind-later":{await Cn(o,i);let p=de?de.remindLater(h.pluginUpdateVersion):"Will remind later about OpenClaw Code Agent update reminder.";await x(o,`✅ ${p}`);break}case"worktree-merge":{let p=await t().execute("callback",{session:d}),y=Mn(p);if(ks(p)){await Tn(o,i);break}await x(o,y);break}case"worktree-decide-later":{let p=S.snoozeWorktreeDecision(d,{notifyUser:!1});if(uo(p)){let P=`⏭️ Snoozed 24h for [${f}]`;await Tn(o,i),await x(o,P)}else await x(o,p);break}case"worktree-dismiss":{let p=await S.dismissWorktree(d),y=uo(p);y&&await Tn(o,i),await x(o,y?"✅ Discarded":p);break}case"worktree-create-pr":case"worktree-update-pr":{let p=await r().execute("callback",{session:d}),y=Mn(p);if(ks(p)){await Tn(o,i);break}await x(o,y);break}case"worktree-view-pr":{await N(o,{alreadyAcknowledged:i});let p=S.getPersistedSession?.(d),y=l.targetUrl??p?.worktreePrUrl;await x(o,y?`PR: ${y}`:"⚠️ PR URL is no longer available.");break}case"plan-offer-start":{if(!h.launchPrompt||!h.launchWorkdir){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,"⚠️ This action is missing the plan launch context.");break}let p;try{p=S.launchPlanOffer({route:h.route,prompt:h.launchPrompt,workdir:h.launchWorkdir,name:h.launchName,worktreeStrategy:h.launchWorktreeStrategy})}catch(y){let P=y instanceof Error?y.message:String(y);await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`⚠️ Failed to start planning session: ${P}`);break}await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`▶️ Planning session started: ${p.name} [${p.id}]`);break}case"plan-offer-dismiss":{await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,"✅ Dismissed.");break}case"repo-policy-set":{if(!h.repoPolicy||!h.repoPolicyWorkdir){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,"⚠️ This action is missing the repo policy context.");break}if(!h.launchPrompt||!h.launchWorkdir){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,"⚠️ This action is missing the launch context.");break}if(typeof S.resolveRepoPolicy=="function"){let P=S.resolveRepoPolicy(h.repoPolicyWorkdir);if(P.identity){let b=Ke(h.repoPolicy,P.prAvailable);if(b){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`⚠️ ${b}`);break}}}let p=S.setRepoPolicy(h.repoPolicyWorkdir,h.repoPolicy);if(!p){await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`⚠️ Could not resolve a git repository for ${h.repoPolicyWorkdir}.`);break}S.clearRepoPolicyChoiceTokens(h.sessionId);let y;try{y=S.launchAfterRepoPolicyChoice({route:h.route,prompt:h.launchPrompt,workdir:h.launchWorkdir,name:h.launchName,model:h.launchModel,reasoningEffort:h.launchReasoningEffort,fastMode:h.launchFastMode,systemPrompt:h.launchSystemPrompt,allowedTools:h.launchAllowedTools,resumeSessionId:h.launchResumeSessionId,resumedFromSessionName:h.launchResumedFromSessionName,resumeWorktreeFrom:h.launchResumeWorktreeFrom,sessionIdOverride:h.launchSessionIdOverride,clearedPersistedCodexResume:h.launchClearedPersistedCodexResume,forkSession:h.launchForkSession,forceNewSession:h.launchForceNewSession,permissionMode:h.launchPermissionMode,planApproval:h.launchPlanApproval,harness:h.launchHarness,worktreeStrategy:h.launchWorktreeStrategy,worktreeBaseBranch:h.launchWorktreeBaseBranch,worktreePrTargetRepo:h.launchWorktreePrTargetRepo,originAgentId:h.launchOriginAgentId}).text}catch(P){let b=P instanceof Error?P.message:String(P);await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,`⚠️ Repo policy saved, but launch failed: ${b}`);break}await N(o,{alreadyAcknowledged:i,forceTelegramMarkupEdit:!0}),await x(o,[`✅ Repo policy saved: ${is(p.policy).title}.`,"",y].join(`
86
+ `));break}case"session-restart":case"session-resume":{await N(o,{alreadyAcknowledged:i});let p=await Q(S,{session:d,message:"Continue where you left off.",userInitiated:!0});await x(o,p.isError?`⚠️ ${p.text}`:`▶️ ${p.text}`);break}case"view-output":{await N(o,{alreadyAcknowledged:i});let p=await hn().execute("callback",{session:d,lines:50});await x(o,Mn(p));break}default:{await N(o,{alreadyAcknowledged:i}),await x(o,"⚠️ Unknown callback action.");break}}return{handled:!0}}}}function Ve(n){return Rs(n).map(e=>e.value)}function Rs(n){return Array.from(n.matchAll(/"[^"]*"|'[^']*'|\S+/g),e=>{let t=e[0],r=e.index??0;return{value:ju(t),raw:t,start:r,end:r+t.length}})}function Re(n){let[e]=Rs(n);if(e)return{value:e.value,rest:n.slice(e.end).trimStart()}}function ju(n){return n.length>1&&(n.startsWith('"')&&n.endsWith('"')||n.startsWith("'")&&n.endsWith("'"))?n.slice(1,-1):n}function zu(n){return n instanceof Error?n.message:String(n)}function Hu(n){let e=Ve(n),t,r=e;return e[0]==="--name"&&e[1]&&(t=e[1],r=e.slice(2)),{name:t,prompt:r.join(" ").trim()}}function As(n){n.registerCommand({name:"agent",description:"Launch a coding agent session. Usage: /agent [--name <name>] <prompt>",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let t=(e.args??"").trim();if(!t)return{text:"Usage: /agent [--name <name>] <prompt>"};let{name:r,prompt:o}=Hu(t);if(!o)return{text:"Usage: /agent [--name <name>] <prompt>"};try{let i=Yt({prompt:o,name:r},e,S);if(i.kind!=="resolved")return{text:i.text};let s=S.spawn({prompt:o,name:r,workdir:i.workdir,model:i.resolvedModel,reasoningEffort:i.reasoningEffort,fastMode:i.fastMode,codexApprovalPolicy:i.harness==="codex"?"never":void 0,originChannel:i.originChannel,originThreadId:i.originThreadId,originAgentId:e.agentId||void 0,originSessionKey:i.originSessionKey,route:i.route,harness:i.harness,permissionMode:i.permissionMode,planApproval:i.planApproval,taskLifecycle:rn(e)});return{text:S.formatLaunchResult({prompt:o,workdir:i.workdir,harness:i.harness,permissionMode:i.permissionMode??_.permissionMode,planApproval:i.planApproval},s)}}catch(i){let s=zu(i),a=s.includes("Max sessions")?"":`
87
87
 
88
88
  Use /agent_sessions to see active sessions.`;return{text:`Error launching session: ${s}${a}`}}}})}function Is(n){n.registerCommand({name:"agent_sessions",description:"List coding agent sessions. Usage: /agent_sessions [--full]",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let t=(e.args??"").split(/\s+/).includes("--full");return{text:fn(S,"all",void 0,{full:t})}}})}function Ts(n){n.registerCommand({name:"agent_kill",description:"Kill a coding agent session by name or ID",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let t=e.args?.trim();return t?{text:gn(S,t,"killed")}:{text:"Usage: /agent_kill <name-or-id>"}}})}function xs(n){n.registerCommand({name:"agent_respond",description:"Send a follow-up message to a running coding agent session. Usage: /agent_respond <id-or-name> <message>",acceptsArgs:!0,requireAuth:!0,handler:async e=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let t=(e.args??"").trim();if(!t)return{text:`Usage: /agent_respond <id-or-name> <message>
89
- /agent_respond --interrupt <id-or-name> <message>`};let r=!1,o=t,i=Re(o);i?.value==="--interrupt"&&(r=!0,o=i.rest);let s=Re(o);if(!s)return{text:"Error: Missing message. Usage: /agent_respond <id-or-name> <message>"};let a=s.value,l=s.rest;return l.trim()?{text:(await Q(S,{session:a,message:l,interrupt:r,userInitiated:!0})).text}:{text:"Error: Empty message. Usage: /agent_respond <id-or-name> <message>"}}})}function Cs(n){n.registerCommand({name:"agent_stats",description:"Show OpenClaw Code Agent usage metrics",acceptsArgs:!1,requireAuth:!0,handler:()=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let e=S.getMetrics(),t=S.list("running").length;return{text:Yt(e,t)}}})}function Qu(n){return n==="pr-required"||n==="pr-allowed"||n==="never-pr"||n==="manual"}function Ms(n){n.registerCommand({name:"agent_policy",description:"Inspect or set the current repo integration policy. Usage: /agent_policy [pr-required|pr-allowed|never-pr|manual|reset|list|cleanup]",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let r=Re((e.args??"").trim())?.value;if(r==="list"){let a=S.listRepoPolicies();return{text:a.length===0?"No stored repo policies.":a.map(l=>`${l.policy} | ${l.provider} | ${l.repoRoot}`).join(`
89
+ /agent_respond --interrupt <id-or-name> <message>`};let r=!1,o=t,i=Re(o);i?.value==="--interrupt"&&(r=!0,o=i.rest);let s=Re(o);if(!s)return{text:"Error: Missing message. Usage: /agent_respond <id-or-name> <message>"};let a=s.value,l=s.rest;return l.trim()?{text:(await Q(S,{session:a,message:l,interrupt:r,userInitiated:!0})).text}:{text:"Error: Empty message. Usage: /agent_respond <id-or-name> <message>"}}})}function Cs(n){n.registerCommand({name:"agent_stats",description:"Show OpenClaw Code Agent usage metrics",acceptsArgs:!1,requireAuth:!0,handler:()=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let e=S.getMetrics(),t=S.list("running").length;return{text:Jt(e,t)}}})}function Qu(n){return n==="pr-required"||n==="pr-allowed"||n==="never-pr"||n==="manual"}function Ms(n){n.registerCommand({name:"agent_policy",description:"Inspect or set the current repo integration policy. Usage: /agent_policy [pr-required|pr-allowed|never-pr|manual|reset|list|cleanup]",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let r=Re((e.args??"").trim())?.value;if(r==="list"){let a=S.listRepoPolicies();return{text:a.length===0?"No stored repo policies.":a.map(l=>`${l.policy} | ${l.provider} | ${l.repoRoot}`).join(`
90
90
  `)}}if(r==="cleanup"){let a=S.cleanupRepoPolicies();return{text:a.length===0?"No stale repo policies found.":[`Removed ${a.length} stale repo ${a.length===1?"policy":"policies"}.`,...a.map(l=>`${l.policy} | ${l.provider} | ${l.repoRoot}`)].join(`
91
91
  `)}}let o=e.workspaceDir;if(!o)return{text:"Error: workspaceDir is required."};if(r==="reset")return{text:S.resetRepoPolicy(o)?`Repo policy reset for ${o}.`:`No stored repo policy found for ${o}.`};if(r&&Qu(r)){if(typeof S.resolveRepoPolicy=="function"){let d=S.resolveRepoPolicy(o);if(d.identity){let u=Ke(r,d.prAvailable);if(u)return{text:`Error: ${u}`}}}let a=S.setRepoPolicy(o,r);if(!a)return{text:`Error: ${o} is not a git repository.`};let l=`Repo policy set to ${a.policy} for ${a.repoRoot}.`;try{if(typeof S.continueLaunchAfterManualRepoPolicy!="function")return{text:l};let d=S.continueLaunchAfterManualRepoPolicy(a.repoRoot,r);if(d.kind==="launched")return{text:[l,"",d.text].join(`
92
92
  `)};if(d.kind==="ambiguous")return{text:[l,"",`Repo policy saved, but ${d.count} pending launches match this policy. Run the intended launch again to avoid starting the wrong session.`].join(`
93
93
  `)}}catch(d){let u=d instanceof Error?d.message:String(d);return{text:[l,"",`Repo policy saved, but the deferred launch failed: ${u}`,"The pending launch context was kept so you can retry the same /agent_policy command or run the intended launch again."].join(`
94
- `)}}return{text:l}}let i=S.resolveRepoPolicy(o);if(!i.identity)return{text:`No git repository found for ${o}.`};let s=st(i.prAvailable).map(a=>a.policy).join(", ");return{text:[`Repo policy: ${i.policy??"unknown"}`,`Repo: ${i.identity.repoRoot}`,`Provider: ${i.provider}${i.prAvailable?"":" (PR automation unavailable)"}`,...i.identity.remoteUrl?[`Remote: ${i.identity.remoteUrl}`]:[],"",`Set with /agent_policy ${s}.`].join(`
95
- `)}}})}var Yu=50;function _s(n){n.registerCommand({name:"agent_output",description:"Show recent output from a coding agent session. Usage: /agent_output <id-or-name> [--full] [--lines N]",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let t=(e.args??"").trim();if(!t)return{text:"Usage: /agent_output <id-or-name> [--full] [--lines N]"};let r=Ve(t),o="",i=!1,s=Yu;for(let l=0;l<r.length;l++)if(r[l]==="--full")i=!0;else if(r[l]==="--lines"&&l+1<r.length){let d=parseInt(r[l+1],10);!isNaN(d)&&d>0&&(s=d),l++}else o||(o=r[l]);return o?{text:mn(S,o,{full:i,lines:s})}:{text:"Usage: /agent_output <id-or-name> [--full] [--lines N]"}}})}var Ds="Usage: /agent_goal [--name <name>] [--workdir <dir>] [--model <model>] [--harness <name>] [--mode <ralph|verifier>] [--completion-promise <text>] [--max-iterations N] [--verify <cmd> ...] <goal>";function $s(n){n.registerCommand({name:"agent_goal",description:"Launch an explicit goal task (Ralph-style completion loop or verifier-driven loop)",acceptsArgs:!0,requireAuth:!0,handler:async e=>{if(!$)return{text:"Error: GoalController not initialized. The code-agent service must be running."};let t=(e.args??"").trim();if(!t)return{text:Ds};let r=Ve(t),o,i,s,a,l="bypassPermissions",d,u,f,h=[],k=[];for(let y=0;y<r.length;y++){let w=r[y];if(w==="--name"&&y+1<r.length)o=r[++y];else if(w==="--workdir"&&y+1<r.length)i=r[++y];else if(w==="--model"&&y+1<r.length)s=r[++y];else if(w==="--max-iterations"&&y+1<r.length){let R=parseInt(r[++y],10);!Number.isNaN(R)&&R>0&&(a=R)}else if(w==="--permission-mode"&&y+1<r.length){let R=r[++y];if(R==="default"||R==="plan"||R==="bypassPermissions")l=R;else return{text:`Error: Invalid permission mode "${R}".`}}else if(w==="--harness"&&y+1<r.length)d=r[++y];else if(w==="--mode"&&y+1<r.length){let R=r[++y];if(R==="ralph"||R==="verifier")u=R;else return{text:`Error: Invalid goal mode "${R}". Use ralph or verifier.`}}else if(w==="--completion-promise"&&y+1<r.length)f=r[++y];else if(w==="--verify"&&y+1<r.length){let R=r[++y].trim();if(!R)return{text:"Error: --verify commands must not be empty."};h.push(R)}else k.push(w)}let g=k.join(" ").trim();if(!g)return{text:Ds};let p=Pn({goal:g,verifierCommands:h,name:o,workdir:i,model:s,maxIterations:a,permissionMode:l,harness:d,goalMode:u,completionPromise:f},e);if(p.kind!=="resolved")return{text:p.text};try{let y=await $.launchTask({goal:p.goal,name:p.name,workdir:p.workdir,model:p.model,reasoningEffort:p.reasoningEffort,fastMode:p.fastMode,maxIterations:p.maxIterations,permissionMode:p.permissionMode,harness:p.harness,loopMode:p.loopMode,completionPromise:p.completionPromise,originChannel:p.originChannel,originThreadId:p.originThreadId,originAgentId:p.originAgentId,originSessionKey:p.originSessionKey,route:p.route,verifierCommands:p.verifierCommands});return{text:wn(y,p)}}catch(y){return{text:`Error launching goal task: ${y instanceof Error?y.message:String(y)}`}}}})}function Es(n){n.registerCommand({name:"agent_goal_status",description:"Show one goal task or list all explicit goal tasks. Usage: /agent_goal_status [<task-id-or-name>]",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!$)return{text:X};let t=(e.args??"").trim();return{text:Rn($,r=>S?.resolve(r),t)}}})}function Ns(n){n.registerCommand({name:"agent_goal_stop",description:"Stop a goal task. Usage: /agent_goal_stop <task-id-or-name>",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!$)return{text:X};let t=(e.args??"").trim();if(!t)return{text:"Usage: /agent_goal_stop <task-id-or-name>"};let r=$.stopTask(t);return{text:An(r,t)}}})}var Os="Usage: /agent_goal_edit <task-id-or-name> <replacement-goal>";function Ws(n){n.registerCommand({name:"agent_goal_edit",description:"Edit a running goal task. Usage: /agent_goal_edit <task-id-or-name> <replacement-goal>",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!$)return{text:X};let t=(e.args??"").trim();if(!t)return{text:Os};let r=Re(t),o=r?.value.trim(),i=r?.rest.trim();if(!o||!i)return{text:Os};let s=$.editTask(o,i);return{text:In(s,o)}}})}import{execFile as up}from"child_process";import{createHash as Xs}from"crypto";import{existsSync as pt,mkdirSync as Ju,readFileSync as Xu,renameSync as Bs,writeFileSync as Zu}from"fs";import{homedir as ep}from"os";import{dirname as tp,join as Ks}from"path";var np=new Set(["running","waiting_for_session","waiting_for_user","succeeded","failed","stopped"]);function rp(n){let e=n.OPENCLAW_HOME?.trim();return e||Ks(ep(),".openclaw")}function op(n){let e=n.OPENCLAW_CODE_AGENT_GOAL_TASKS_PATH?.trim();return e||Ks(rp(n),"code-agent-goal-tasks.json")}function qs(n){return n instanceof Error?n.message:String(n)}function Vs(n){return!!n&&typeof n=="object"&&!Array.isArray(n)}var ip=100;function Ls(n,e,t){let r=t==null?"":`-${t}`;return`${n}.invalid-${e}${r}.json`}function sp(n){if(!pt(n))return;let e=Date.now(),t=Ls(n,e);if(!pt(t))return t;for(let r=1;r<=ip;r+=1){let o=Ls(n,e,r);if(!pt(o))return o}}function Fs(n,e){try{let t=sp(n);return t?(Bs(n,t),`${e}${t}`,!0):(pt(n),!1)}catch(t){return`${qs(t)}`,!1}}function ap(n){if(!Vs(n))return;let e=n;if(!(typeof e.provider!="string"||typeof e.target!="string"))return{provider:e.provider,target:e.target,accountId:typeof e.accountId=="string"?e.accountId:void 0,threadId:typeof e.threadId=="string"?e.threadId:void 0,sessionKey:typeof e.sessionKey=="string"?e.sessionKey:void 0}}function lp(n){if(!Vs(n))return;let e=n;if(typeof e.id!="string"||typeof e.name!="string"||typeof e.goal!="string"||typeof e.workdir!="string"||typeof e.status!="string"||!np.has(e.status))return;let t=e.status,r=t==="running"||t==="waiting_for_session"?"waiting_for_session":t;return{id:e.id,name:e.name,goal:e.goal,workdir:e.workdir,status:r,createdAt:typeof e.createdAt=="number"?e.createdAt:Date.now(),updatedAt:typeof e.updatedAt=="number"?e.updatedAt:Date.now(),iteration:typeof e.iteration=="number"?e.iteration:0,maxIterations:typeof e.maxIterations=="number"?e.maxIterations:8,sessionId:typeof e.sessionId=="string"?e.sessionId:void 0,sessionName:typeof e.sessionName=="string"?e.sessionName:void 0,harnessSessionId:typeof e.harnessSessionId=="string"?e.harnessSessionId:void 0,model:typeof e.model=="string"?e.model:void 0,reasoningEffort:typeof e.reasoningEffort=="string"?e.reasoningEffort:void 0,fastMode:e.fastMode===!0?!0:void 0,systemPrompt:typeof e.systemPrompt=="string"?e.systemPrompt:void 0,allowedTools:Array.isArray(e.allowedTools)?e.allowedTools.filter(o=>typeof o=="string"):void 0,originChannel:typeof e.originChannel=="string"?e.originChannel:void 0,originThreadId:typeof e.originThreadId=="string"||typeof e.originThreadId=="number"?e.originThreadId:void 0,originAgentId:typeof e.originAgentId=="string"?e.originAgentId:void 0,originSessionKey:typeof e.originSessionKey=="string"?e.originSessionKey:void 0,route:ap(e.route),harness:typeof e.harness=="string"?e.harness:void 0,permissionMode:typeof e.permissionMode=="string"?e.permissionMode:void 0,loopMode:e.loopMode==="ralph"?"ralph":"verifier",completionPromise:typeof e.completionPromise=="string"?e.completionPromise:void 0,verifierCommands:Array.isArray(e.verifierCommands)?e.verifierCommands.filter(o=>!!o&&typeof o=="object"&&typeof o.label=="string"&&typeof o.command=="string"):[],lastVerifierSummary:typeof e.lastVerifierSummary=="string"?e.lastVerifierSummary:void 0,lastVerifierFingerprint:typeof e.lastVerifierFingerprint=="string"?e.lastVerifierFingerprint:void 0,repeatedFailureCount:typeof e.repeatedFailureCount=="number"?e.repeatedFailureCount:0,waitingForUserReason:typeof e.waitingForUserReason=="string"?e.waitingForUserReason:void 0,failureReason:typeof e.failureReason=="string"?e.failureReason:void 0}}function dp(n){if(!Array.isArray(n))return;let e=[];for(let t of n){let r=lp(t);if(!r)return;e.push(r)}return e}var Dn=class{path;tasks=new Map;constructor(e=process.env){this.path=op(e),this.load()}load(){try{if(!pt(this.path))return;let e=Xu(this.path,"utf8"),t=JSON.parse(e),r=dp(t);if(!r){Fs(this.path,"invalid")&&this.save();return}this.tasks.clear();for(let o of r)this.tasks.set(o.id,o);this.save()}catch(e){if(e.code==="ENOENT")return;Fs(this.path,"corrupt or unreadable")&&this.save()}}save(){try{Ju(tp(this.path),{recursive:!0});let e=`${this.path}.tmp`;Zu(e,JSON.stringify([...this.tasks.values()],null,2),"utf8"),Bs(e,this.path)}catch(e){`${this.path}${qs(e)}`}}upsert(e){this.tasks.set(e.id,e),this.save()}get(e){let t=this.tasks.get(e);return t||[...this.tasks.values()].find(r=>r.name===e)}list(){return[...this.tasks.values()].sort((e,t)=>t.createdAt-e.createdAt)}};var pp=8,Zs=600*1e3,cp=4e3,po=1200,mp="DONE",fp=["BASH_ENV","ENV"];function gp(n){return n.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,48)||"goal-task"}function Ue(n,e){return n.length<=e?n:`${n.slice(0,e-3)}...`}function he(n,e=20){let t=n.split(/\r?\n/).map(r=>r.trimEnd()).filter(r=>r.trim().length>0);return t.length<=e?t.join(`
94
+ `)}}return{text:l}}let i=S.resolveRepoPolicy(o);if(!i.identity)return{text:`No git repository found for ${o}.`};let s=at(i.prAvailable).map(a=>a.policy).join(", ");return{text:[`Repo policy: ${i.policy??"unknown"}`,`Repo: ${i.identity.repoRoot}`,`Provider: ${i.provider}${i.prAvailable?"":" (PR automation unavailable)"}`,...i.identity.remoteUrl?[`Remote: ${i.identity.remoteUrl}`]:[],"",`Set with /agent_policy ${s}.`].join(`
95
+ `)}}})}var Yu=50;function _s(n){n.registerCommand({name:"agent_output",description:"Show recent output from a coding agent session. Usage: /agent_output <id-or-name> [--full] [--lines N]",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!S)return{text:"Error: SessionManager not initialized. The code-agent service must be running."};let t=(e.args??"").trim();if(!t)return{text:"Usage: /agent_output <id-or-name> [--full] [--lines N]"};let r=Ve(t),o="",i=!1,s=Yu;for(let l=0;l<r.length;l++)if(r[l]==="--full")i=!0;else if(r[l]==="--lines"&&l+1<r.length){let d=parseInt(r[l+1],10);!isNaN(d)&&d>0&&(s=d),l++}else o||(o=r[l]);return o?{text:mn(S,o,{full:i,lines:s})}:{text:"Usage: /agent_output <id-or-name> [--full] [--lines N]"}}})}var Ds="Usage: /agent_goal [--name <name>] [--workdir <dir>] [--model <model>] [--harness <name>] [--mode <ralph|verifier>] [--completion-promise <text>] [--max-iterations N] [--verify <cmd> ...] <goal>";function $s(n){n.registerCommand({name:"agent_goal",description:"Launch an explicit goal task (Ralph-style completion loop or verifier-driven loop)",acceptsArgs:!0,requireAuth:!0,handler:async e=>{if(!$)return{text:"Error: GoalController not initialized. The code-agent service must be running."};let t=(e.args??"").trim();if(!t)return{text:Ds};let r=Ve(t),o,i,s,a,l="bypassPermissions",d,u,f,g=[],k=[];for(let y=0;y<r.length;y++){let P=r[y];if(P==="--name"&&y+1<r.length)o=r[++y];else if(P==="--workdir"&&y+1<r.length)i=r[++y];else if(P==="--model"&&y+1<r.length)s=r[++y];else if(P==="--max-iterations"&&y+1<r.length){let b=parseInt(r[++y],10);!Number.isNaN(b)&&b>0&&(a=b)}else if(P==="--permission-mode"&&y+1<r.length){let b=r[++y];if(b==="default"||b==="plan"||b==="bypassPermissions")l=b;else return{text:`Error: Invalid permission mode "${b}".`}}else if(P==="--harness"&&y+1<r.length)d=r[++y];else if(P==="--mode"&&y+1<r.length){let b=r[++y];if(b==="ralph"||b==="verifier")u=b;else return{text:`Error: Invalid goal mode "${b}". Use ralph or verifier.`}}else if(P==="--completion-promise"&&y+1<r.length)f=r[++y];else if(P==="--verify"&&y+1<r.length){let b=r[++y].trim();if(!b)return{text:"Error: --verify commands must not be empty."};g.push(b)}else k.push(P)}let h=k.join(" ").trim();if(!h)return{text:Ds};let p=Pn({goal:h,verifierCommands:g,name:o,workdir:i,model:s,maxIterations:a,permissionMode:l,harness:d,goalMode:u,completionPromise:f},e);if(p.kind!=="resolved")return{text:p.text};try{let y=await $.launchTask({goal:p.goal,name:p.name,workdir:p.workdir,model:p.model,reasoningEffort:p.reasoningEffort,fastMode:p.fastMode,maxIterations:p.maxIterations,permissionMode:p.permissionMode,harness:p.harness,loopMode:p.loopMode,completionPromise:p.completionPromise,originChannel:p.originChannel,originThreadId:p.originThreadId,originAgentId:p.originAgentId,originSessionKey:p.originSessionKey,route:p.route,verifierCommands:p.verifierCommands});return{text:wn(y,p)}}catch(y){return{text:`Error launching goal task: ${y instanceof Error?y.message:String(y)}`}}}})}function Es(n){n.registerCommand({name:"agent_goal_status",description:"Show one goal task or list all explicit goal tasks. Usage: /agent_goal_status [<task-id-or-name>]",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!$)return{text:X};let t=(e.args??"").trim();return{text:Rn($,r=>S?.resolve(r),t)}}})}function Ns(n){n.registerCommand({name:"agent_goal_stop",description:"Stop a goal task. Usage: /agent_goal_stop <task-id-or-name>",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!$)return{text:X};let t=(e.args??"").trim();if(!t)return{text:"Usage: /agent_goal_stop <task-id-or-name>"};let r=$.stopTask(t);return{text:An(r,t)}}})}var Os="Usage: /agent_goal_edit <task-id-or-name> <replacement-goal>";function Ws(n){n.registerCommand({name:"agent_goal_edit",description:"Edit a running goal task. Usage: /agent_goal_edit <task-id-or-name> <replacement-goal>",acceptsArgs:!0,requireAuth:!0,handler:e=>{if(!$)return{text:X};let t=(e.args??"").trim();if(!t)return{text:Os};let r=Re(t),o=r?.value.trim(),i=r?.rest.trim();if(!o||!i)return{text:Os};let s=$.editTask(o,i);return{text:In(s,o)}}})}import{execFile as up}from"child_process";import{createHash as Xs}from"crypto";import{existsSync as ct,mkdirSync as Ju,readFileSync as Xu,renameSync as Bs,writeFileSync as Zu}from"fs";import{homedir as ep}from"os";import{dirname as tp,join as Ks}from"path";var np=new Set(["running","waiting_for_session","waiting_for_user","succeeded","failed","stopped"]);function rp(n){let e=n.OPENCLAW_HOME?.trim();return e||Ks(ep(),".openclaw")}function op(n){let e=n.OPENCLAW_CODE_AGENT_GOAL_TASKS_PATH?.trim();return e||Ks(rp(n),"code-agent-goal-tasks.json")}function qs(n){return n instanceof Error?n.message:String(n)}function Vs(n){return!!n&&typeof n=="object"&&!Array.isArray(n)}var ip=100;function Fs(n,e,t){let r=t==null?"":`-${t}`;return`${n}.invalid-${e}${r}.json`}function sp(n){if(!ct(n))return;let e=Date.now(),t=Fs(n,e);if(!ct(t))return t;for(let r=1;r<=ip;r+=1){let o=Fs(n,e,r);if(!ct(o))return o}}function Ls(n,e){try{let t=sp(n);return t?(Bs(n,t),`${e}${t}`,!0):(ct(n),!1)}catch(t){return`${qs(t)}`,!1}}function ap(n){if(!Vs(n))return;let e=n;if(!(typeof e.provider!="string"||typeof e.target!="string"))return{provider:e.provider,target:e.target,accountId:typeof e.accountId=="string"?e.accountId:void 0,threadId:typeof e.threadId=="string"?e.threadId:void 0,sessionKey:typeof e.sessionKey=="string"?e.sessionKey:void 0}}function lp(n){if(!Vs(n))return;let e=n;if(typeof e.id!="string"||typeof e.name!="string"||typeof e.goal!="string"||typeof e.workdir!="string"||typeof e.status!="string"||!np.has(e.status))return;let t=e.status,r=t==="running"||t==="waiting_for_session"?"waiting_for_session":t;return{id:e.id,name:e.name,goal:e.goal,workdir:e.workdir,status:r,createdAt:typeof e.createdAt=="number"?e.createdAt:Date.now(),updatedAt:typeof e.updatedAt=="number"?e.updatedAt:Date.now(),iteration:typeof e.iteration=="number"?e.iteration:0,maxIterations:typeof e.maxIterations=="number"?e.maxIterations:8,sessionId:typeof e.sessionId=="string"?e.sessionId:void 0,sessionName:typeof e.sessionName=="string"?e.sessionName:void 0,harnessSessionId:typeof e.harnessSessionId=="string"?e.harnessSessionId:void 0,model:typeof e.model=="string"?e.model:void 0,reasoningEffort:typeof e.reasoningEffort=="string"?e.reasoningEffort:void 0,fastMode:e.fastMode===!0?!0:void 0,systemPrompt:typeof e.systemPrompt=="string"?e.systemPrompt:void 0,allowedTools:Array.isArray(e.allowedTools)?e.allowedTools.filter(o=>typeof o=="string"):void 0,originChannel:typeof e.originChannel=="string"?e.originChannel:void 0,originThreadId:typeof e.originThreadId=="string"||typeof e.originThreadId=="number"?e.originThreadId:void 0,originAgentId:typeof e.originAgentId=="string"?e.originAgentId:void 0,originSessionKey:typeof e.originSessionKey=="string"?e.originSessionKey:void 0,route:ap(e.route),harness:typeof e.harness=="string"?e.harness:void 0,permissionMode:typeof e.permissionMode=="string"?e.permissionMode:void 0,loopMode:e.loopMode==="ralph"?"ralph":"verifier",completionPromise:typeof e.completionPromise=="string"?e.completionPromise:void 0,verifierCommands:Array.isArray(e.verifierCommands)?e.verifierCommands.filter(o=>!!o&&typeof o=="object"&&typeof o.label=="string"&&typeof o.command=="string"):[],lastVerifierSummary:typeof e.lastVerifierSummary=="string"?e.lastVerifierSummary:void 0,lastVerifierFingerprint:typeof e.lastVerifierFingerprint=="string"?e.lastVerifierFingerprint:void 0,repeatedFailureCount:typeof e.repeatedFailureCount=="number"?e.repeatedFailureCount:0,waitingForUserReason:typeof e.waitingForUserReason=="string"?e.waitingForUserReason:void 0,failureReason:typeof e.failureReason=="string"?e.failureReason:void 0}}function dp(n){if(!Array.isArray(n))return;let e=[];for(let t of n){let r=lp(t);if(!r)return;e.push(r)}return e}var Dn=class{path;tasks=new Map;constructor(e=process.env){this.path=op(e),this.load()}load(){try{if(!ct(this.path))return;let e=Xu(this.path,"utf8"),t=JSON.parse(e),r=dp(t);if(!r){Ls(this.path,"invalid")&&this.save();return}this.tasks.clear();for(let o of r)this.tasks.set(o.id,o);this.save()}catch(e){if(e.code==="ENOENT")return;Ls(this.path,"corrupt or unreadable")&&this.save()}}save(){try{Ju(tp(this.path),{recursive:!0});let e=`${this.path}.tmp`;Zu(e,JSON.stringify([...this.tasks.values()],null,2),"utf8"),Bs(e,this.path)}catch(e){`${this.path}${qs(e)}`}}upsert(e){this.tasks.set(e.id,e),this.save()}get(e){let t=this.tasks.get(e);return t||[...this.tasks.values()].find(r=>r.name===e)}list(){return[...this.tasks.values()].sort((e,t)=>t.createdAt-e.createdAt)}};var pp=8,Zs=600*1e3,cp=4e3,po=1200,mp="DONE",fp=["BASH_ENV","ENV"];function gp(n){return n.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,48)||"goal-task"}function Ue(n,e){return n.length<=e?n:`${n.slice(0,e-3)}...`}function he(n,e=20){let t=n.split(/\r?\n/).map(r=>r.trimEnd()).filter(r=>r.trim().length>0);return t.length<=e?t.join(`
96
96
  `):t.slice(-e).join(`
97
97
  `)}function hp(n){let e=(n??"").split(/\r?\n/).map(t=>t.trim()).filter(t=>t.length>0).filter(t=>!/^Iteration summary:$/i.test(t)).map(t=>t.replace(/^[-*]\s+/,""));return e.length>0?e.join(`
98
98
  `):void 0}function Us(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Gs(n){let e=n?.trim();return e&&e.length>0?e:mp}function yp(n){return n.route??ue(n.originChannel,n.originThreadId,n.originSessionKey)}function co(n){return n.map((e,t)=>({label:e.label.trim()||`check-${t+1}`,command:e.command.trim(),timeoutMs:e.timeoutMs??Zs})).filter(e=>e.command.length>0)}function Sp(n){return n.loopMode==="verifier"}function kp(n){return co(n.verifierCommands).length>0}function js(n){return Sp(n)&&!kp(n)}function $n(){return"Verifier-mode goal tasks require at least one verifier command."}function zs(n){let e=n.steps.filter(t=>!t.ok).map(t=>`${t.label}:${t.exitCode}:${he(t.output,12)}`).join(`
@@ -112,7 +112,7 @@ Use /agent_sessions to see active sessions.`;return{text:`Error launching sessio
112
112
  `);return["You emitted the completion promise, but the external verifiers did not pass.","","Goal:",n.goal,"","Verifier failures:",t,"","Instructions:","- Continue from the current repo state and fix only the remaining gaps.",`- Do not emit <promise>${n.completionPromise}</promise> again until the goal is fully complete and the failing checks are addressed.`,"- Re-run relevant checks yourself before ending the turn."].join(`
113
113
  `)}function Ap(n,e){let t=e.trim();if(!t)return!1;let r=new RegExp(`(^|\\n)\\s*${Us(t)}\\s*(\\n|$)`,"i"),o=new RegExp(`<promise>\\s*${Us(t)}\\s*<\\/promise>`,"i");return r.test(n)||o.test(n)}function Ys(n){return n.steps.map(e=>`${e.ok?"PASS":"FAIL"} ${e.label} (exit ${e.exitCode}, ${Math.round(e.durationMs)}ms)`).join(`
114
114
  `)}function Ae(n){return n instanceof Error?n.message:String(n)}function Js(n){return n==="succeeded"||n==="failed"||n==="stopped"}function Ip(n){return Ue(n.error?.trim()||"Underlying session failed.",po)}function Tp(n=process.env){let e={...n};for(let t of fp)delete e[t];return e}function xp(n,e){return new Promise(t=>{let r=Date.now();up("bash",["-lc",e.command],{cwd:n,timeout:e.timeoutMs??Zs,maxBuffer:1024*1024,env:Tp()},(o,i,s)=>{let a=Date.now()-r,l=typeof o?.code=="number"?o.code:o?1:0,d=`${i??""}${s?`
115
- ${s}`:""}`.trim();t({label:e.label,command:e.command,ok:!o,exitCode:l,durationMs:a,output:Ue(d||"(no output)",cp)})})})}var En=class{store;sessionManager;restorePromise=null;inFlight=new Set;observerDisposers=new Map;scheduledEvaluations=new Map;dirtyEvaluations=new Set;dirtyEvaluationSessionIds=new Map;started=!1;constructor(e){this.sessionManager=e,this.store=new Dn}start(){this.started||(this.started=!0,!this.restorePromise&&(this.restorePromise=this.restoreRecoverableTasks().catch(e=>{`${Ae(e)}`}).finally(()=>{this.restorePromise=null})))}stop(){this.started=!1,this.clearScheduledEvaluations(),this.detachSessionObservers(),this.captureRecoverableTasks(),this.store.save()}listTasks(){return this.store.list()}getTask(e){return this.store.get(e)}async launchTask(e){let t=e.loopMode??"verifier",r=co(e.verifierCommands);if(t==="verifier"&&r.length===0)throw new Error($n());let i={id:on(8),name:gp(e.name??e.goal),goal:e.goal.trim(),workdir:e.workdir,status:"waiting_for_session",createdAt:Date.now(),updatedAt:Date.now(),iteration:0,maxIterations:e.maxIterations??pp,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,systemPrompt:e.systemPrompt,allowedTools:e.allowedTools,originChannel:e.originChannel,originThreadId:e.originThreadId,originAgentId:e.originAgentId,originSessionKey:e.originSessionKey,route:e.route,harness:e.harness,permissionMode:e.permissionMode??"bypassPermissions",loopMode:t,completionPromise:Gs(e.completionPromise),verifierCommands:r,repeatedFailureCount:0},s=await this.spawnTaskSession(i,Pp(i));return this.attachSessionObservers(i,s),i.sessionId=s.id,i.sessionName=s.name,i.harnessSessionId=s.harnessSessionId,i.status="running",i.updatedAt=Date.now(),this.store.upsert(i),this.scheduleTaskEvaluation(i.id,"launch",s.id),this.notify(i,`🎯 [${i.name}] Goal task started
115
+ ${s}`:""}`.trim();t({label:e.label,command:e.command,ok:!o,exitCode:l,durationMs:a,output:Ue(d||"(no output)",cp)})})})}var En=class{store;sessionManager;restorePromise=null;inFlight=new Set;observerDisposers=new Map;scheduledEvaluations=new Map;dirtyEvaluations=new Set;dirtyEvaluationSessionIds=new Map;started=!1;constructor(e){this.sessionManager=e,this.store=new Dn}start(){this.started||(this.started=!0,!this.restorePromise&&(this.restorePromise=this.restoreRecoverableTasks().catch(e=>{`${Ae(e)}`}).finally(()=>{this.restorePromise=null})))}stop(){this.started=!1,this.clearScheduledEvaluations(),this.detachSessionObservers(),this.captureRecoverableTasks(),this.store.save()}listTasks(){return this.store.list()}getTask(e){return this.store.get(e)}async launchTask(e){let t=e.loopMode??"verifier",r=co(e.verifierCommands);if(t==="verifier"&&r.length===0)throw new Error($n());let i={id:sn(8),name:gp(e.name??e.goal),goal:e.goal.trim(),workdir:e.workdir,status:"waiting_for_session",createdAt:Date.now(),updatedAt:Date.now(),iteration:0,maxIterations:e.maxIterations??pp,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,systemPrompt:e.systemPrompt,allowedTools:e.allowedTools,originChannel:e.originChannel,originThreadId:e.originThreadId,originAgentId:e.originAgentId,originSessionKey:e.originSessionKey,route:e.route,harness:e.harness,permissionMode:e.permissionMode??"bypassPermissions",loopMode:t,completionPromise:Gs(e.completionPromise),verifierCommands:r,repeatedFailureCount:0},s=await this.spawnTaskSession(i,Pp(i));return this.attachSessionObservers(i,s),i.sessionId=s.id,i.sessionName=s.name,i.harnessSessionId=s.harnessSessionId,i.status="running",i.updatedAt=Date.now(),this.store.upsert(i),this.scheduleTaskEvaluation(i.id,"launch",s.id),this.notify(i,`🎯 [${i.name}] Goal task started
116
116
 
117
117
  Goal:
118
118
  ${Ue(i.goal,500)}`,"goal-task-started"),i}stopTask(e){let t=this.store.get(e);if(t)return Js(t.status)?{task:t,action:"already_terminal"}:(t.sessionId&&this.sessionManager.kill(t.sessionId,"user"),this.markTaskStopped(t,"Stopped by user."),{task:t,action:"stopped"})}editTask(e,t){let r=t.trim();if(!r)return{action:"invalid_goal"};let o=this.store.get(e);if(!o)return{action:"not_found"};if(Js(o.status)||o.status==="waiting_for_user")return{action:"not_editable",task:o};let i=o.goal;return o.goal=r,o.updatedAt=Date.now(),this.store.upsert(o),this.notify(o,`✏️ [${o.name}] Goal task edited
@@ -132,20 +132,20 @@ ${e.failureReason}`,"goal-task-stopped")}async handleRunningSession(e,t){if(t.pe
132
132
  `);if(t.pendingPlanApproval){let a=await Q(this.sessionManager,{session:t.id,message:"Approved. Implement the plan.",approve:!0,userInitiated:!1});if(a.isError){this.markTaskFailed(e,a.text);return}let l=this.sessionManager.resolve(t.id);if(!l){this.markTaskFailed(e,"Failed to resolve the resumed goal task session after idle timeout plan approval.");return}this.attachSessionObservers(e,l),this.setTaskRunningWithSession(e,l),this.notifyIterationStatus(e,`🔄 [${e.name}] Goal task resumed after idle timeout`,l),this.scheduleTaskEvaluation(e.id,"idle-timeout-plan-resume",l.id);return}if(t.pendingInputState){let a=Hs(s);if(!a){this.markTaskFailed(e,`Goal task was waiting for user input and cannot continue autonomously: ${he(s,24)||"The goal task hit idle timeout while waiting for user input."}`);return}await this.resumeAfterIdleTimeout(e,t,["The previous session hit idle timeout while waiting for a response.",`Use this response and continue the goal: ${a}`].join(`
133
133
 
134
134
  `));return}await this.resumeAfterIdleTimeout(e,t,Qs(e));return}if(t.status==="killed"&&t.killReason!=="done"){this.markTaskFailed(e,`Underlying session was killed (${t.killReason}).`);return}if(e.loopMode==="ralph"){let s=t.getOutput(200).join(`
135
- `),a=Gs(e.completionPromise);if(Ap(s,a)){if(e.verifierCommands.length===0){this.markTaskSucceeded(e,`Completion promise "${a}" detected in agent output.`);return}let h=await this.runVerifiers(e);if(e.lastVerifierSummary=h.summary,e.updatedAt=Date.now(),h.status==="pass"){this.markTaskSucceeded(e,[`Completion promise "${a}" detected.`,h.summary].join(`
136
- `));return}if(e.lastVerifierFingerprint===h.fingerprint?e.repeatedFailureCount+=1:e.repeatedFailureCount=1,e.lastVerifierFingerprint=h.fingerprint,e.iteration+1>=e.maxIterations){this.markTaskFailed(e,[`Goal task emitted completion promise but verifiers still failed before hitting the iteration budget (${e.maxIterations}).`,h.summary].join(`
137
- `));return}e.iteration+=1;let k=Rp(e,h),g=bn({output:s,verifierSummary:h.summary,completionPromise:a,completionDetected:!0});try{let p=await this.resumeTaskSession(e,k,t);this.setTaskRunningWithSession(e,p),this.notifyIterationStatus(e,`🔁 [${e.name}] Completion claimed but verifiers still failed`,void 0,g),this.scheduleTaskEvaluation(e.id,"ralph-verifier-resume",p.id)}catch(p){this.markTaskFailed(e,`Failed to resume the Ralph goal task after verifier failure: ${Ae(p)}`)}return}let d=vp(s);if(e.lastVerifierFingerprint===d?e.repeatedFailureCount+=1:e.repeatedFailureCount=1,e.lastVerifierFingerprint=d,e.iteration+1>=e.maxIterations){this.markTaskFailed(e,[`Completion promise "${a}" was not emitted before hitting the iteration budget (${e.maxIterations}).`,"Latest output:",he(s,20)||"(no output)"].join(`
138
- `));return}e.iteration+=1;let u=bp(e,s),f=bn({output:s,completionPromise:a,completionDetected:!1});try{let h=await this.resumeTaskSession(e,u,t);this.setTaskRunningWithSession(e,h),this.notifyIterationStatus(e,`🔁 [${e.name}] Continued`,void 0,f),this.scheduleTaskEvaluation(e.id,"ralph-continue",h.id)}catch(h){this.markTaskFailed(e,`Failed to continue the Ralph goal task: ${Ae(h)}`)}return}let r=await this.runVerifiers(e);if(e.lastVerifierSummary=r.summary,e.updatedAt=Date.now(),r.status==="pass"){this.markTaskSucceeded(e,r.summary);return}if(e.lastVerifierFingerprint===r.fingerprint?e.repeatedFailureCount+=1:e.repeatedFailureCount=1,e.lastVerifierFingerprint=r.fingerprint,e.iteration+1>=e.maxIterations){this.markTaskFailed(e,[`Verifier did not pass before hitting the iteration budget (${e.maxIterations}).`,r.summary].join(`
139
- `));return}e.iteration+=1;let o=wp(e,r),i=bn({verifierSummary:r.summary});try{let s=await this.resumeTaskSession(e,o,t);this.setTaskRunningWithSession(e,s),this.notifyIterationStatus(e,`🔁 [${e.name}] Repair iteration started after verifier failure`,void 0,i),this.scheduleTaskEvaluation(e.id,"repair-resume",s.id)}catch(s){this.markTaskFailed(e,`Failed to resume the goal task: ${Ae(s)}`)}}async evaluateTask(e,t,r){this.restorePromise&&await this.restorePromise;let o=this.store.get(e);o&&await this.reconcileTask(o,t,r)}async reconcileTask(e,t="manual",r){if(!(e.status==="succeeded"||e.status==="failed"||e.status==="stopped")){if(this.inFlight.has(e.id)){this.dirtyEvaluations.add(e.id),!this.dirtyEvaluationSessionIds.get(e.id)&&r?this.dirtyEvaluationSessionIds.set(e.id,r):this.dirtyEvaluationSessionIds.has(e.id)||this.dirtyEvaluationSessionIds.set(e.id,r);return}this.inFlight.add(e.id);try{if(r&&e.sessionId&&e.sessionId!==r){let i=this.sessionManager.resolve(r);if(i&&(i.status==="completed"||i.status==="failed"||i.status==="killed"))return}let o=r?this.sessionManager.resolve(r)??(e.sessionId?this.sessionManager.resolve(e.sessionId):void 0):e.sessionId?this.sessionManager.resolve(e.sessionId):void 0;if(e.status==="waiting_for_user"){this.markTaskFailed(e,"Goal task was waiting for user input and cannot continue autonomously");return}if(js(e)){this.markTaskFailed(e,$n());return}if(!o){this.markTaskFailed(e,"Underlying session could not be found.");return}if(e.sessionName=o.name,e.harnessSessionId=o.harnessSessionId,e.route=o.route??e.route,e.updatedAt=Date.now(),this.store.upsert(e),o.status==="starting"||o.status==="running"){await this.handleRunningSession(e,o);return}await this.handleTerminalSession(e,o)}finally{if(this.inFlight.delete(e.id),this.dirtyEvaluations.has(e.id)){this.dirtyEvaluations.delete(e.id);let o=this.dirtyEvaluationSessionIds.get(e.id);this.dirtyEvaluationSessionIds.delete(e.id),this.scheduleTaskEvaluation(e.id,`${t}:dirty`,o)}}}}};import{createHash as rl}from"crypto";import{existsSync as Cp,realpathSync as Mp}from"fs";import{resolve as _p}from"path";function ea(n){if(!n)return;let e=_p(n);try{if(Cp(e))return Mp.native(e)}catch{}return e}function Nn(n,e){return!n||!e?!1:ea(n)===ea(e)}import{existsSync as Dp}from"fs";function $p(n){if(!(!n.provider||!n.target))return n.accountId?`${n.provider}|${n.accountId}|${n.target}`:`${n.provider}|${n.target}`}function Ep(n){return Ce(Z({route:n.route,originChannel:n.originChannel,originThreadId:n.originThreadId,originSessionKey:n.originSessionKey}))}function Np(n,e){if(Ep(n))return;let t=[n.resumeSessionId,n.resumeWorktreeFrom].filter(r=>!!r?.trim());for(let r of t){let o=e(r);if(!o)continue;let i=Z({route:o.route,originChannel:o.originChannel,originThreadId:o.originThreadId,originSessionKey:o.originSessionKey});if(Ce(i)){n.route={...i},n.originChannel=o.originChannel??$p(i),n.originThreadId=o.originThreadId??i.threadId,n.originSessionKey=o.originSessionKey??i.sessionKey,n.originAgentId??=o.originAgentId;return}}}function ta(n){return n instanceof Error?n.message:String(n)}function Op(n){let e=n.worktreeStrategy??_.defaultWorktreeStrategy;return!!e&&e!=="off"&&zo(At({harnessName:n.harness??Y(),backendRef:n.backendRef}))}function Wp(n,e,t,r){let o=["","You are working in a git worktree.",`Worktree path: ${t}`,`Branch: ${r}`,"",`IMPORTANT: ALL file edits must be made within this worktree at ${t}.`,`Do NOT edit files directly in ${e} (the original workspace).`,`If your task references files by absolute path under ${e}, rewrite those`,"paths relative to your current working directory. For example:",` "${e}/src/file.py" → use relative path "src/file.py"`,"","Before finishing, run `git status --short` in this worktree.","If you made actual task changes, commit all of them to this branch before finishing.","Use `git add` and `git commit`. If no repository changes are needed, leave the worktree clean before finishing.","Do NOT run `git checkout`, `git switch`, or `git reset --hard` as these will detach or corrupt the worktree HEAD.","","When making changes, please note:","- Do NOT commit planning documents, investigation notes, or analysis artifacts to this branch","- Only commit actual code, configuration, tests, and documentation changes that were explicitly requested as part of the task"].join(`
140
- `);return(n??"")+o}function Lp(n,e){let t=n.resumeWorktreeFrom??n.resumeSessionId;if(!t)return{};let r=e(t);if(!r)return{};let o=!!r.harness||!!r.backendRef,i=(()=>{if(r.workdir&&r.workdir!==r.worktreePath)return r.workdir;if(r.worktreePath){let a=It(r.worktreePath);return r.workdir&&a&&Nn(r.workdir,a)?r.workdir:a??r.workdir}return r.workdir})();if(n.worktreeStrategy||(r.worktreeLifecycle?.state==="pr_open"||r.worktreePrUrl?n.worktreeStrategy="auto-pr":r.worktreeStrategy&&(n.worktreeStrategy=r.worktreeStrategy)),!n.planApproval&&r.planApproval&&(n.planApproval=r.planApproval),!r.worktreePath){let a=o&&Rr(At({persistedHarness:r.harness,backendRef:r.backendRef}));return{originalWorkdir:i,canCreateManagedWorktreeForResumeWithoutPersistedPath:a}}if(!r.worktreeBranch)throw new Error(`Cannot resume session "${t}": persisted worktree metadata is missing worktreeBranch.`);let s=Rr(At({persistedHarness:r.harness,backendRef:r.backendRef}))&&!!r.backendRef?.worktreePath;if(Dp(r.worktreePath))return`${r.worktreePath}`,{actualWorkdir:r.worktreePath,originalWorkdir:i??r.worktreePath,worktreePath:r.worktreePath,worktreeBranchName:r.worktreeBranch,worktreeParentBranch:r.worktreeParentBranch};if(!i)return`${r.worktreePath}`,{clearedResumeSessionId:!!n.resumeSessionId,clearedResumeWorktreeFrom:!!n.resumeWorktreeFrom};if(s)return`${r.worktreePath}`,{actualWorkdir:i,originalWorkdir:i,worktreeBranchName:r.worktreeBranch,worktreeParentBranch:r.worktreeParentBranch,clearedResumeWorktreeFrom:!!n.resumeWorktreeFrom,restoredMissingNativeBackendWorktree:!0};try{Ct(i);let a=Ir(i,r.worktreeBranch.replace(/^agent\//,""),{allowExistingBranch:!0});return`${r.worktreeBranch}${a}`,{actualWorkdir:a,originalWorkdir:i,worktreePath:a,worktreeBranchName:r.worktreeBranch,worktreeParentBranch:r.worktreeParentBranch}}catch(a){return`${ta(a)}`,{actualWorkdir:i,originalWorkdir:i,clearedResumeSessionId:!!n.resumeSessionId,clearedResumeWorktreeFrom:!!n.resumeWorktreeFrom,failedResumeWorktreeRestore:!0}}}function na(n,e,t){Np(n,t);let{actualWorkdir:r,originalWorkdir:o,worktreePath:i,worktreeBranchName:s,worktreeParentBranch:a,clearedResumeSessionId:l,clearedResumeWorktreeFrom:d,restoredMissingNativeBackendWorktree:u,canCreateManagedWorktreeForResumeWithoutPersistedPath:f,failedResumeWorktreeRestore:h}=Lp(n,t);l&&(n.resumeSessionId=void 0),d&&(n.resumeWorktreeFrom=void 0),r??=n.workdir,o??=n.workdir;let k=!!(n.resumeSessionId??n.resumeWorktreeFrom),g=n.worktreeStrategy??_.defaultWorktreeStrategy;g&&(n.worktreeStrategy=g),!k&&g&&g!=="off"&&Tt(o)&&(a??=oe(o));let p=Op(n),w=(!k||!!f)&&!u&&!i&&g&&g!=="off"&&!p;if(h&&g&&g!=="off")throw new Error(`Cannot launch session "${e}": worktree strategy "${g}" was requested, but no isolated worktree was prepared. Launch with worktree_strategy "off" only when running in the base checkout is intentional.`);if(p&&!Tt(o))throw new Error(`Cannot launch session "${e}": worktree strategy "${g}" requires a git worktree, but "${o}" is not a git repository.`);if(w&&Tt(o)){if(!Ho(o))throw new Error(`Cannot launch session "${e}": insufficient space for worktree creation.`);try{if(i=Ir(o,e),r=i,s=oe(i),!s)throw new Error(`created worktree at ${i} but failed to resolve branch name`);`${i}`}catch(R){throw new Error(`Cannot launch session "${e}": worktree creation failed: ${ta(R)}`)}}else if(w)throw new Error(`Cannot launch session "${e}": worktree strategy "${g}" requires a git worktree, but "${o}" is not a git repository.`);if(k&&i&&(r=i),g&&g!=="off"&&!i)throw new Error(`Cannot launch session "${e}": worktree strategy "${g}" was requested, but no isolated worktree was prepared. Launch with worktree_strategy "off" only when running in the base checkout is intentional.`);return{actualWorkdir:r,originalWorkdir:o,effectiveSystemPrompt:i&&s?Wp(n.systemPrompt,o,i,s):n.systemPrompt,worktreePath:i,worktreeBranchName:s,worktreeParentBranch:a,clearedResumeSessionId:l,clearedResumeWorktreeFrom:d,restoredMissingNativeBackendWorktree:u,failedResumeWorktreeRestore:h}}var On=class{constructor(e){this.getPersistedSession=e}getPersistedSession;prepareSpawn(e,t){return na(e,t,this.getPersistedSession)}hydrateSpawnedSession(e,t,r){r.worktreeStrategy&&r.worktreeStrategy!=="off"&&(e.originalWorkdir=t.originalWorkdir),e.worktreeParentBranch=t.worktreeParentBranch,t.worktreePath&&(e.worktreePath=t.worktreePath,e.worktreeBranch=t.worktreeBranchName,e.worktreeState="provisioned"),r.worktreePrTargetRepo&&(e.worktreePrTargetRepo=r.worktreePrTargetRepo)}};var Wn=class{constructor(e){this.deps=e}deps;applySessionPatch(e,t){let r=this.normalizeCompletionWakePatch(t),o=this.deps.store.getPersistedSession(e);o&&(Object.assign(o,r),this.deps.store.assertPersistedEntry(o));let i=this.findActiveSessionForRef(e,o);return i&&this.applyPatchToActiveSession(i,r),!o&&!i?!1:(o&&this.deps.store.saveIndex(),!0)}normalizeCompletionWakePatch(e){return"completionWakeSucceededAt"in e&&e.completionWakeSucceededAt||"completionWakeSkippedAt"in e&&e.completionWakeSkippedAt?{...e,completionWakeSummaryRequired:void 0}:e}matchesExistingSession(e,t){if(!t)return!1;let r=C(e),o=C(t);return!!(t.sessionId&&e.id===t.sessionId||o&&o===r||t?.harnessSessionId&&e.harnessSessionId===t.harnessSessionId||t?.name&&e.name===t.name)}findActiveSessionForRef(e,t){let r=this.deps.resolveSession(e);if(r)return r;for(let o of this.deps.sessions.values())if(D(o)===e||C(o)===e||o.harnessSessionId===e||this.matchesExistingSession(o,t))return o}applyPatchToActiveSession(e,t){this.applyControlStatePatch(e,t),this.applySessionMetadataPatch(e,t),this.applyWorktreeMetadataPatch(e,t)}applyControlStatePatch(e,t){let r={};if(this.copyControlPatchField(r,t,"lifecycle"),this.copyControlPatchField(r,t,"approvalState"),this.copyControlPatchField(r,t,"approvalExecutionState"),this.copyControlPatchField(r,t,"worktreeState"),this.copyControlPatchField(r,t,"runtimeState"),this.copyControlPatchField(r,t,"deliveryState"),this.copyControlPatchField(r,t,"requestedPermissionMode"),this.copyControlPatchField(r,t,"currentPermissionMode"),this.copyControlPatchField(r,t,"pendingPlanApproval"),this.copyControlPatchField(r,t,"planApprovalContext"),this.copyControlPatchField(r,t,"planDecisionVersion"),this.copyControlPatchField(r,t,"actionablePlanDecisionVersion"),this.copyControlPatchField(r,t,"canonicalPlanPromptVersion"),this.copyControlPatchField(r,t,"approvalPromptRequiredVersion"),this.copyControlPatchField(r,t,"approvalPromptVersion"),this.copyControlPatchField(r,t,"approvalPromptStatus"),this.copyControlPatchField(r,t,"approvalPromptTransport"),this.copyControlPatchField(r,t,"approvalPromptMessageKind"),this.copyControlPatchField(r,t,"approvalPromptLastAttemptAt"),this.copyControlPatchField(r,t,"approvalPromptDeliveredAt"),this.copyControlPatchField(r,t,"approvalPromptFailedAt"),this.copyControlPatchField(r,t,"planModeApproved"),this.copyControlPatchField(r,t,"pendingWorktreeDecisionSince"),typeof e.applyControlPatch=="function"){e.applyControlPatch(r);return}this.assignIfPresent(e,"lifecycle",t,"lifecycle"),this.assignIfPresent(e,"approvalState",t,"approvalState"),this.assignIfPresent(e,"approvalExecutionState",t,"approvalExecutionState"),this.assignIfPresent(e,"worktreeState",t,"worktreeState"),this.assignIfPresent(e,"runtimeState",t,"runtimeState"),this.assignIfPresent(e,"deliveryState",t,"deliveryState"),this.assignIfPresent(e,"requestedPermissionMode",t,"requestedPermissionMode"),this.assignIfPresent(e,"currentPermissionMode",t,"currentPermissionMode"),this.assignIfPresent(e,"pendingPlanApproval",t,"pendingPlanApproval"),this.assignIfPresent(e,"planApprovalContext",t,"planApprovalContext"),this.assignIfPresent(e,"planDecisionVersion",t,"planDecisionVersion"),this.assignIfPresent(e,"actionablePlanDecisionVersion",t,"actionablePlanDecisionVersion"),this.assignIfPresent(e,"canonicalPlanPromptVersion",t,"canonicalPlanPromptVersion"),this.assignIfPresent(e,"approvalPromptRequiredVersion",t,"approvalPromptRequiredVersion"),this.assignIfPresent(e,"approvalPromptVersion",t,"approvalPromptVersion"),this.assignIfPresent(e,"approvalPromptStatus",t,"approvalPromptStatus"),this.assignIfPresent(e,"approvalPromptTransport",t,"approvalPromptTransport"),this.assignIfPresent(e,"approvalPromptMessageKind",t,"approvalPromptMessageKind"),this.assignIfPresent(e,"approvalPromptLastAttemptAt",t,"approvalPromptLastAttemptAt"),this.assignIfPresent(e,"approvalPromptDeliveredAt",t,"approvalPromptDeliveredAt"),this.assignIfPresent(e,"approvalPromptFailedAt",t,"approvalPromptFailedAt"),this.setControlFieldIfPresent(e,"planModeApproved",t)}applySessionMetadataPatch(e,t){this.assignIfDefined(e,"approvalRationale",t.approvalRationale),this.assignIfDefined(e,"taskFlowMirror",t.taskFlowMirror)}applyWorktreeMetadataPatch(e,t){this.assignIfDefined(e,"worktreePath",t.worktreePath),this.assignIfDefined(e,"worktreeBranch",t.worktreeBranch),this.assignIfDefined(e,"worktreePrUrl",t.worktreePrUrl),this.assignIfDefined(e,"worktreePrNumber",t.worktreePrNumber),this.assignIfDefined(e,"worktreeMerged",t.worktreeMerged),this.assignIfDefined(e,"worktreeMergedAt",t.worktreeMergedAt),this.assignIfDefined(e,"worktreeDisposition",t.worktreeDisposition),this.assignIfDefined(e,"worktreePrTargetRepo",t.worktreePrTargetRepo),this.assignIfDefined(e,"worktreePushRemote",t.worktreePushRemote),this.assignIfDefined(e,"worktreeLifecycle",t.worktreeLifecycle),"autoMergeParentSessionId"in t&&(e.autoMergeParentSessionId=t.autoMergeParentSessionId),"autoMergeConflictResolutionAttemptCount"in t&&(e.autoMergeConflictResolutionAttemptCount=t.autoMergeConflictResolutionAttemptCount),"autoMergeResolverSessionId"in t&&(e.autoMergeResolverSessionId=t.autoMergeResolverSessionId)}assignIfDefined(e,t,r){r!==void 0&&(e[t]=r)}assignIfPresent(e,t,r,o){Object.hasOwn(r,o)&&(e[t]=r[o])}copyControlPatchField(e,t,r){Object.hasOwn(t,r)&&(e[r]=t[r])}setControlFieldIfPresent(e,t,r){Object.hasOwn(r,t)&&e.setControlField?.(t,r[t])}};var Fp=new Set(["starting","running"]),Ln=class{constructor(e,t){this.sessions=e;this.store=t}sessions;store;resolveActive(e){let t=this.sessions.get(e);return t||(this.findPreferredMatch(e,r=>r.name===e)??this.findPreferredMatch(e,r=>C(r)===e)??this.findPreferredMatch(e,r=>r.harnessSessionId===e))}getPersistedSession(e){return this.store.getPersistedSession(e)}resolveBackendConversationId(e){let t=this.resolveActive(e);return this.store.resolveBackendConversationId(e,t?C(t)??t.harnessSessionId:void 0)}findPreferredMatch(e,t){let r,o;for(let i of this.sessions.values())t(i,e)&&((!o||i.startedAt>o.startedAt)&&(o=i),Fp.has(i.status)&&(!r||i.startedAt>r.startedAt)&&(r=i));return r??o}};import{existsSync as Bp}from"fs";var ra=new Set(["merged","released","pr_open","dismissed","cleanup_failed"]),Fn=class{constructor(e){this.deps=e}deps;async plan(e){let t=D(e)??e.harnessSessionId;if(this.deps.isAlreadyMerged(t))return`${e.name}`,{kind:"skip",result:{notificationSent:!0,worktreeRemoved:!1}};let r=ra.has(e.worktreeState)?e.worktreeState:e.worktreeLifecycle?.state&&ra.has(e.worktreeLifecycle.state)?e.worktreeLifecycle.state:void 0;if(r&&!(r==="pr_open"&&e.worktreeStrategy==="auto-pr"))return`${e.name}${e.worktreeLifecycle?.state??e.worktreeState}`,{kind:"skip",result:{notificationSent:!0,worktreeRemoved:!1}};if(e.status!=="completed")return{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}};if(!this.deps.shouldRunWorktreeStrategy(e))return`${e.name}${e.phase}`,{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}};let o=e.worktreeStrategy;if(!o||o==="off"||o==="manual")return{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}};let i=e.worktreePath,s=this.deps.resolveWorktreeRepoDir(e.originalWorkdir,i),a=e.worktreeBranch;if(!s)return{kind:"notify",label:"worktree-missing-repo-dir",message:`⚠️ [${e.name}] Cannot determine the original repo for worktree ${i}. Manual inspection is required.`};if(!a)return{kind:"notify",label:"worktree-no-branch-name",message:`⚠️ [${e.name}] Cannot determine branch name for worktree ${i}. The worktree may have been removed or is in detached HEAD state. Manual cleanup may be needed.`};let l=F(e);if(l&&!Bp(i))return{kind:"no-change",repoDir:s,worktreePath:i,branchName:a,nativeBackendWorktree:l};let d=e.worktreeBaseBranch??Ee(s),u=this.deps.getWorktreeCompletionState(s,i,a,d);if(u==="no-change")return{kind:"no-change",repoDir:s,worktreePath:i,branchName:a,nativeBackendWorktree:l};if(u==="merged")return{kind:"merged",repoDir:s,worktreePath:i,branchName:a,nativeBackendWorktree:l};if(u==="released")return{kind:"released",repoDir:s,worktreePath:i,branchName:a,nativeBackendWorktree:l,reasons:["merge_noop_content_already_on_base"]};if(u==="base-advanced")return{kind:"notify",label:"worktree-no-commits-ahead",message:`⚠️ [${e.name}] Auto-merge: branch '${a}' has no commits ahead of '${d}', but '${d}' has new commits — commits likely landed outside the worktree branch. Verify that commits were not made directly to '${d}' instead of the worktree branch. Worktree: ${i}`};if(u==="dirty-uncommitted")return{kind:"dirty-uncommitted",worktreePath:i,branchName:a,baseBranch:d};let f=Ne(s,a,d);if(!f)return`${a}`,{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}};let h=e.repoIntegrationPolicy?void 0:this.deps.resolveRepoPolicy?.(s),k=e.repoIntegrationPolicy??h?.policy,g=e.repoIntegrationPolicy?this.deps.isPrAvailable(s):h?.prAvailable??this.deps.isPrAvailable(s),p=ls({requestedStrategy:o,policy:k,prAvailable:g,existingOpenPr:!1});return p.strategy?{kind:"decision",strategy:p.strategy,policy:k,policyReason:p.reason,policyBlocked:p.blocked,allowedActions:p.allowedActions,repoDir:s,worktreePath:i,branchName:a,baseBranch:d,diffSummary:f,sessionRef:t??void 0}:{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}}}};function ye(n){let e=[];typeof n.costUsd=="number"&&Number.isFinite(n.costUsd)&&e.push(`$${n.costUsd.toFixed(2)}`);let t=Kp(n);t!==void 0&&e.push(se(t));let r=ge({harness:n.harnessName??n.harness,model:n.model});return r&&e.push(...r.split(" | ")),e.length>0?` | ${e.join(" | ")}`:""}function Kp(n){if(typeof n.duration=="number"&&Number.isFinite(n.duration)&&n.duration>=0)return n.duration;if(typeof n.createdAt=="number"&&Number.isFinite(n.createdAt)&&typeof n.completedAt=="number"&&Number.isFinite(n.completedAt)&&n.completedAt>=n.createdAt)return n.completedAt-n.createdAt}function qp(n){if(n.requestedPermissionMode==="plan"){if(n.approvalExecutionState==="approved_then_implemented"){if(n.planApproval==="ask"&&n.approvalPromptStatus==="delivered"&&n.approvalPromptMessageKind==="canonical_buttons"&&n.approvalPromptDeliveredAt)return"Approval interpretation: canonical Approve/Revise/Reject buttons were delivered, and implementation after approval was expected.";if(n.approvalState==="approved")return"Approval interpretation: explicit plan approval was recorded before implementation, so leaving plan-only mode was expected."}if(n.approvalExecutionState==="implemented_without_required_approval")return"Approval interpretation: implementation left plan-only mode without a recorded approval."}}function Vp(){return/https?:\/\/github\.com\/[^\s)]+\/[^\s)]+\/pull\/(\d+)(?=[\s).,;:]|$)/gi}function Up(){return/https?:\/\/\S+/gi}function Bn(n){let e=qp(n);return[`Requested permission mode: ${n.requestedPermissionMode??"unknown"}`,`Effective permission mode: ${n.currentPermissionMode??"unknown"}`,`Deterministic approval/execution state: ${n.approvalExecutionState??"unknown"}`,...e?[e]:[]]}function mo(n){switch(n){case"user":return"Stopped by user";case"shutdown":return"Stopped by shutdown";case"startup-timeout":return"Stopped by startup timeout";case"unknown":case void 0:return"Stopped unexpectedly";default:return"Stopped"}}function Gp(){return{requiresShortFactualSummary:!0,owner:"agent",appliesToOrdinaryTerminalCompletions:!0}}function jp(){return{requiresShortFactualSummary:!0,owner:"agent",appliesToWorktreeTerminalOutcomes:!0}}function zp(){return{requiresShortFactualSummary:!0,owner:"agent",appliesToGoalTaskCompletions:!0}}function fo(n){let{sessionId:e,canonicalStatusDetail:t,canonicalStatusDelivered:r=!0,hasOriginRouteBlock:o=!1}=n,i=o?["7. Before sending that follow-up, honor the Session origin route block above. If originRoute differs from the current chat, do NOT use a plain final assistant reply; use a routed send path that preserves provider/target/threadId."]:[],s=o?8:7,a=o?9:8;return["[ACTION REQUIRED] Follow your autonomy rules for session completion:",`1. Use agent_output(session='${e}', full=true) to read the full result.`,"2. If this is part of a multi-phase pipeline, launch the next phase NOW — do not wait for user input.",`3. ${t??(r?"The plugin already sent the canonical completion status to the user.":"The plugin did not confirm delivery of the canonical completion status to the user.")}`,"4. Treat the completed session output as source material, not visible delivery. A meaningful final summary inside agent_output is not enough to skip, because the user may only have seen the plugin's terse status line.","5. If the visible result is only the plugin's terse status line, use the full output to send the user one short factual completion summary for this completed session. Do this even when agent_output already contains a good final summary.","6. This requirement applies to ordinary terminal/manual completions too, not just delegated worktree decisions.",...i,`${s}. That follow-up belongs to you alone; keep it brief, concrete, and grounded in reliable result data. Send at most one orchestrator-owned human summary for this terminal/worktree outcome.`,...r?[`${a}. Do NOT repeat the plugin's status line, and do NOT rely on the plugin to summarize the completed work for you.`]:[`${a}. Because canonical status delivery was not confirmed, account for that gap yourself when you follow up; do NOT assume the plugin already reached the user.`],`${a+1}. Send a normal concise final response after any routed follow-up is visibly sent. Do not use marker text, do not answer NO_REPLY, and do not ask the user whether they want the summary.`]}function Hp(n){let{contract:e,canonicalStatusDelivered:t}=n;return["Completion diagnostics:",`- Canonical completion status delivered to user: ${t?"yes":"no"}`,`- Plugin requested short factual follow-up summary: ${e.requiresShortFactualSummary?"yes":"no"}`,`- Contract applies to ordinary terminal/manual completions: ${e.appliesToOrdinaryTerminalCompletions?"yes":"no"}`]}function go(n){let{session:e,originThreadLine:t,preview:r}=n,o=!!t.trim(),i=Gp(),s=a=>["Coding agent session completed.",`Name: ${e.name} | ID: ${e.id}`,`Status: ${e.status}`,...o?[t]:[],...Bn(e),"","Output preview:",r,"",...Hp({contract:i,canonicalStatusDelivered:a}),"",...fo({sessionId:e.id,canonicalStatusDelivered:a,hasOriginRouteBlock:o})].join(`
135
+ `),a=Gs(e.completionPromise);if(Ap(s,a)){if(e.verifierCommands.length===0){this.markTaskSucceeded(e,`Completion promise "${a}" detected in agent output.`);return}let g=await this.runVerifiers(e);if(e.lastVerifierSummary=g.summary,e.updatedAt=Date.now(),g.status==="pass"){this.markTaskSucceeded(e,[`Completion promise "${a}" detected.`,g.summary].join(`
136
+ `));return}if(e.lastVerifierFingerprint===g.fingerprint?e.repeatedFailureCount+=1:e.repeatedFailureCount=1,e.lastVerifierFingerprint=g.fingerprint,e.iteration+1>=e.maxIterations){this.markTaskFailed(e,[`Goal task emitted completion promise but verifiers still failed before hitting the iteration budget (${e.maxIterations}).`,g.summary].join(`
137
+ `));return}e.iteration+=1;let k=Rp(e,g),h=bn({output:s,verifierSummary:g.summary,completionPromise:a,completionDetected:!0});try{let p=await this.resumeTaskSession(e,k,t);this.setTaskRunningWithSession(e,p),this.notifyIterationStatus(e,`🔁 [${e.name}] Completion claimed but verifiers still failed`,void 0,h),this.scheduleTaskEvaluation(e.id,"ralph-verifier-resume",p.id)}catch(p){this.markTaskFailed(e,`Failed to resume the Ralph goal task after verifier failure: ${Ae(p)}`)}return}let d=vp(s);if(e.lastVerifierFingerprint===d?e.repeatedFailureCount+=1:e.repeatedFailureCount=1,e.lastVerifierFingerprint=d,e.iteration+1>=e.maxIterations){this.markTaskFailed(e,[`Completion promise "${a}" was not emitted before hitting the iteration budget (${e.maxIterations}).`,"Latest output:",he(s,20)||"(no output)"].join(`
138
+ `));return}e.iteration+=1;let u=bp(e,s),f=bn({output:s,completionPromise:a,completionDetected:!1});try{let g=await this.resumeTaskSession(e,u,t);this.setTaskRunningWithSession(e,g),this.notifyIterationStatus(e,`🔁 [${e.name}] Continued`,void 0,f),this.scheduleTaskEvaluation(e.id,"ralph-continue",g.id)}catch(g){this.markTaskFailed(e,`Failed to continue the Ralph goal task: ${Ae(g)}`)}return}let r=await this.runVerifiers(e);if(e.lastVerifierSummary=r.summary,e.updatedAt=Date.now(),r.status==="pass"){this.markTaskSucceeded(e,r.summary);return}if(e.lastVerifierFingerprint===r.fingerprint?e.repeatedFailureCount+=1:e.repeatedFailureCount=1,e.lastVerifierFingerprint=r.fingerprint,e.iteration+1>=e.maxIterations){this.markTaskFailed(e,[`Verifier did not pass before hitting the iteration budget (${e.maxIterations}).`,r.summary].join(`
139
+ `));return}e.iteration+=1;let o=wp(e,r),i=bn({verifierSummary:r.summary});try{let s=await this.resumeTaskSession(e,o,t);this.setTaskRunningWithSession(e,s),this.notifyIterationStatus(e,`🔁 [${e.name}] Repair iteration started after verifier failure`,void 0,i),this.scheduleTaskEvaluation(e.id,"repair-resume",s.id)}catch(s){this.markTaskFailed(e,`Failed to resume the goal task: ${Ae(s)}`)}}async evaluateTask(e,t,r){this.restorePromise&&await this.restorePromise;let o=this.store.get(e);o&&await this.reconcileTask(o,t,r)}async reconcileTask(e,t="manual",r){if(!(e.status==="succeeded"||e.status==="failed"||e.status==="stopped")){if(this.inFlight.has(e.id)){this.dirtyEvaluations.add(e.id),!this.dirtyEvaluationSessionIds.get(e.id)&&r?this.dirtyEvaluationSessionIds.set(e.id,r):this.dirtyEvaluationSessionIds.has(e.id)||this.dirtyEvaluationSessionIds.set(e.id,r);return}this.inFlight.add(e.id);try{if(r&&e.sessionId&&e.sessionId!==r){let i=this.sessionManager.resolve(r);if(i&&(i.status==="completed"||i.status==="failed"||i.status==="killed"))return}let o=r?this.sessionManager.resolve(r)??(e.sessionId?this.sessionManager.resolve(e.sessionId):void 0):e.sessionId?this.sessionManager.resolve(e.sessionId):void 0;if(e.status==="waiting_for_user"){this.markTaskFailed(e,"Goal task was waiting for user input and cannot continue autonomously");return}if(js(e)){this.markTaskFailed(e,$n());return}if(!o){this.markTaskFailed(e,"Underlying session could not be found.");return}if(e.sessionName=o.name,e.harnessSessionId=o.harnessSessionId,e.route=o.route??e.route,e.updatedAt=Date.now(),this.store.upsert(e),o.status==="starting"||o.status==="running"){await this.handleRunningSession(e,o);return}await this.handleTerminalSession(e,o)}finally{if(this.inFlight.delete(e.id),this.dirtyEvaluations.has(e.id)){this.dirtyEvaluations.delete(e.id);let o=this.dirtyEvaluationSessionIds.get(e.id);this.dirtyEvaluationSessionIds.delete(e.id),this.scheduleTaskEvaluation(e.id,`${t}:dirty`,o)}}}}};import{createHash as rl}from"crypto";import{existsSync as Cp,realpathSync as Mp}from"fs";import{resolve as _p}from"path";function ea(n){if(!n)return;let e=_p(n);try{if(Cp(e))return Mp.native(e)}catch{}return e}function Nn(n,e){return!n||!e?!1:ea(n)===ea(e)}import{existsSync as Dp}from"fs";function $p(n){if(!(!n.provider||!n.target))return n.accountId?`${n.provider}|${n.accountId}|${n.target}`:`${n.provider}|${n.target}`}function Ep(n){return Ce(Z({route:n.route,originChannel:n.originChannel,originThreadId:n.originThreadId,originSessionKey:n.originSessionKey}))}function Np(n,e){if(Ep(n))return;let t=[n.resumeSessionId,n.resumeWorktreeFrom].filter(r=>!!r?.trim());for(let r of t){let o=e(r);if(!o)continue;let i=Z({route:o.route,originChannel:o.originChannel,originThreadId:o.originThreadId,originSessionKey:o.originSessionKey});if(Ce(i)){n.route={...i},n.originChannel=o.originChannel??$p(i),n.originThreadId=o.originThreadId??i.threadId,n.originSessionKey=o.originSessionKey??i.sessionKey,n.originAgentId??=o.originAgentId;return}}}function ta(n){return n instanceof Error?n.message:String(n)}function Op(n){let e=n.worktreeStrategy??_.defaultWorktreeStrategy;return!!e&&e!=="off"&&zo(It({harnessName:n.harness??Y(),backendRef:n.backendRef}))}function Wp(n,e,t,r){let o=["","You are working in a git worktree.",`Worktree path: ${t}`,`Branch: ${r}`,"",`IMPORTANT: ALL file edits must be made within this worktree at ${t}.`,`Do NOT edit files directly in ${e} (the original workspace).`,`If your task references files by absolute path under ${e}, rewrite those`,"paths relative to your current working directory. For example:",` "${e}/src/file.py" → use relative path "src/file.py"`,"","Before finishing, run `git status --short` in this worktree.","If you made actual task changes, commit all of them to this branch before finishing.","Use `git add` and `git commit`. If no repository changes are needed, leave the worktree clean before finishing.","Do NOT run `git checkout`, `git switch`, or `git reset --hard` as these will detach or corrupt the worktree HEAD.","","When making changes, please note:","- Do NOT commit planning documents, investigation notes, or analysis artifacts to this branch","- Only commit actual code, configuration, tests, and documentation changes that were explicitly requested as part of the task"].join(`
140
+ `);return(n??"")+o}function Fp(n,e){let t=n.resumeWorktreeFrom??n.resumeSessionId;if(!t)return{};let r=e(t);if(!r)return{};let o=!!r.harness||!!r.backendRef,i=(()=>{if(r.workdir&&r.workdir!==r.worktreePath)return r.workdir;if(r.worktreePath){let a=Tt(r.worktreePath);return r.workdir&&a&&Nn(r.workdir,a)?r.workdir:a??r.workdir}return r.workdir})();if(n.worktreeStrategy||(r.worktreeLifecycle?.state==="pr_open"||r.worktreePrUrl?n.worktreeStrategy="auto-pr":r.worktreeStrategy&&(n.worktreeStrategy=r.worktreeStrategy)),!n.planApproval&&r.planApproval&&(n.planApproval=r.planApproval),!r.worktreePath){let a=o&&Rr(It({persistedHarness:r.harness,backendRef:r.backendRef}));return{originalWorkdir:i,canCreateManagedWorktreeForResumeWithoutPersistedPath:a}}if(!r.worktreeBranch)throw new Error(`Cannot resume session "${t}": persisted worktree metadata is missing worktreeBranch.`);let s=Rr(It({persistedHarness:r.harness,backendRef:r.backendRef}))&&!!r.backendRef?.worktreePath;if(Dp(r.worktreePath))return`${r.worktreePath}`,{actualWorkdir:r.worktreePath,originalWorkdir:i??r.worktreePath,worktreePath:r.worktreePath,worktreeBranchName:r.worktreeBranch,worktreeParentBranch:r.worktreeParentBranch};if(!i)return`${r.worktreePath}`,{clearedResumeSessionId:!!n.resumeSessionId,clearedResumeWorktreeFrom:!!n.resumeWorktreeFrom};if(s)return`${r.worktreePath}`,{actualWorkdir:i,originalWorkdir:i,worktreeBranchName:r.worktreeBranch,worktreeParentBranch:r.worktreeParentBranch,clearedResumeWorktreeFrom:!!n.resumeWorktreeFrom,restoredMissingNativeBackendWorktree:!0};try{Mt(i);let a=Ir(i,r.worktreeBranch.replace(/^agent\//,""),{allowExistingBranch:!0});return`${r.worktreeBranch}${a}`,{actualWorkdir:a,originalWorkdir:i,worktreePath:a,worktreeBranchName:r.worktreeBranch,worktreeParentBranch:r.worktreeParentBranch}}catch(a){return`${ta(a)}`,{actualWorkdir:i,originalWorkdir:i,clearedResumeSessionId:!!n.resumeSessionId,clearedResumeWorktreeFrom:!!n.resumeWorktreeFrom,failedResumeWorktreeRestore:!0}}}function na(n,e,t){Np(n,t);let{actualWorkdir:r,originalWorkdir:o,worktreePath:i,worktreeBranchName:s,worktreeParentBranch:a,clearedResumeSessionId:l,clearedResumeWorktreeFrom:d,restoredMissingNativeBackendWorktree:u,canCreateManagedWorktreeForResumeWithoutPersistedPath:f,failedResumeWorktreeRestore:g}=Fp(n,t);l&&(n.resumeSessionId=void 0),d&&(n.resumeWorktreeFrom=void 0),r??=n.workdir,o??=n.workdir;let k=!!(n.resumeSessionId??n.resumeWorktreeFrom),h=n.worktreeStrategy??_.defaultWorktreeStrategy;h&&(n.worktreeStrategy=h),!k&&h&&h!=="off"&&xt(o)&&(a??=oe(o));let p=Op(n),P=(!k||!!f)&&!u&&!i&&h&&h!=="off"&&!p;if(g&&h&&h!=="off")throw new Error(`Cannot launch session "${e}": worktree strategy "${h}" was requested, but no isolated worktree was prepared. Launch with worktree_strategy "off" only when running in the base checkout is intentional.`);if(p&&!xt(o))throw new Error(`Cannot launch session "${e}": worktree strategy "${h}" requires a git worktree, but "${o}" is not a git repository.`);if(P&&xt(o)){if(!Ho(o))throw new Error(`Cannot launch session "${e}": insufficient space for worktree creation.`);try{if(i=Ir(o,e),r=i,s=oe(i),!s)throw new Error(`created worktree at ${i} but failed to resolve branch name`);`${i}`}catch(b){throw new Error(`Cannot launch session "${e}": worktree creation failed: ${ta(b)}`)}}else if(P)throw new Error(`Cannot launch session "${e}": worktree strategy "${h}" requires a git worktree, but "${o}" is not a git repository.`);if(k&&i&&(r=i),h&&h!=="off"&&!i)throw new Error(`Cannot launch session "${e}": worktree strategy "${h}" was requested, but no isolated worktree was prepared. Launch with worktree_strategy "off" only when running in the base checkout is intentional.`);return{actualWorkdir:r,originalWorkdir:o,effectiveSystemPrompt:i&&s?Wp(n.systemPrompt,o,i,s):n.systemPrompt,worktreePath:i,worktreeBranchName:s,worktreeParentBranch:a,clearedResumeSessionId:l,clearedResumeWorktreeFrom:d,restoredMissingNativeBackendWorktree:u,failedResumeWorktreeRestore:g}}var On=class{constructor(e){this.getPersistedSession=e}getPersistedSession;prepareSpawn(e,t){return na(e,t,this.getPersistedSession)}hydrateSpawnedSession(e,t,r){r.worktreeStrategy&&r.worktreeStrategy!=="off"&&(e.originalWorkdir=t.originalWorkdir),e.worktreeParentBranch=t.worktreeParentBranch,t.worktreePath&&(e.worktreePath=t.worktreePath,e.worktreeBranch=t.worktreeBranchName,e.worktreeState="provisioned"),r.worktreePrTargetRepo&&(e.worktreePrTargetRepo=r.worktreePrTargetRepo)}};var Wn=class{constructor(e){this.deps=e}deps;applySessionPatch(e,t){let r=this.normalizeCompletionWakePatch(t),o=this.deps.store.getPersistedSession(e);o&&(Object.assign(o,r),this.deps.store.assertPersistedEntry(o));let i=this.findActiveSessionForRef(e,o);return i&&this.applyPatchToActiveSession(i,r),!o&&!i?!1:(o&&this.deps.store.saveIndex(),!0)}normalizeCompletionWakePatch(e){return"completionWakeSucceededAt"in e&&e.completionWakeSucceededAt||"completionWakeSkippedAt"in e&&e.completionWakeSkippedAt?{...e,completionWakeSummaryRequired:void 0}:e}matchesExistingSession(e,t){if(!t)return!1;let r=C(e),o=C(t);return!!(t.sessionId&&e.id===t.sessionId||o&&o===r||t?.harnessSessionId&&e.harnessSessionId===t.harnessSessionId||t?.name&&e.name===t.name)}findActiveSessionForRef(e,t){let r=this.deps.resolveSession(e);if(r)return r;for(let o of this.deps.sessions.values())if(D(o)===e||C(o)===e||o.harnessSessionId===e||this.matchesExistingSession(o,t))return o}applyPatchToActiveSession(e,t){this.applyControlStatePatch(e,t),this.applySessionMetadataPatch(e,t),this.applyWorktreeMetadataPatch(e,t)}applyControlStatePatch(e,t){let r={};if(this.copyControlPatchField(r,t,"lifecycle"),this.copyControlPatchField(r,t,"approvalState"),this.copyControlPatchField(r,t,"approvalExecutionState"),this.copyControlPatchField(r,t,"worktreeState"),this.copyControlPatchField(r,t,"runtimeState"),this.copyControlPatchField(r,t,"deliveryState"),this.copyControlPatchField(r,t,"requestedPermissionMode"),this.copyControlPatchField(r,t,"currentPermissionMode"),this.copyControlPatchField(r,t,"pendingPlanApproval"),this.copyControlPatchField(r,t,"planApprovalContext"),this.copyControlPatchField(r,t,"planDecisionVersion"),this.copyControlPatchField(r,t,"actionablePlanDecisionVersion"),this.copyControlPatchField(r,t,"canonicalPlanPromptVersion"),this.copyControlPatchField(r,t,"approvalPromptRequiredVersion"),this.copyControlPatchField(r,t,"approvalPromptVersion"),this.copyControlPatchField(r,t,"approvalPromptStatus"),this.copyControlPatchField(r,t,"approvalPromptTransport"),this.copyControlPatchField(r,t,"approvalPromptMessageKind"),this.copyControlPatchField(r,t,"approvalPromptLastAttemptAt"),this.copyControlPatchField(r,t,"approvalPromptDeliveredAt"),this.copyControlPatchField(r,t,"approvalPromptFailedAt"),this.copyControlPatchField(r,t,"planModeApproved"),this.copyControlPatchField(r,t,"pendingWorktreeDecisionSince"),typeof e.applyControlPatch=="function"){e.applyControlPatch(r);return}this.assignIfPresent(e,"lifecycle",t,"lifecycle"),this.assignIfPresent(e,"approvalState",t,"approvalState"),this.assignIfPresent(e,"approvalExecutionState",t,"approvalExecutionState"),this.assignIfPresent(e,"worktreeState",t,"worktreeState"),this.assignIfPresent(e,"runtimeState",t,"runtimeState"),this.assignIfPresent(e,"deliveryState",t,"deliveryState"),this.assignIfPresent(e,"requestedPermissionMode",t,"requestedPermissionMode"),this.assignIfPresent(e,"currentPermissionMode",t,"currentPermissionMode"),this.assignIfPresent(e,"pendingPlanApproval",t,"pendingPlanApproval"),this.assignIfPresent(e,"planApprovalContext",t,"planApprovalContext"),this.assignIfPresent(e,"planDecisionVersion",t,"planDecisionVersion"),this.assignIfPresent(e,"actionablePlanDecisionVersion",t,"actionablePlanDecisionVersion"),this.assignIfPresent(e,"canonicalPlanPromptVersion",t,"canonicalPlanPromptVersion"),this.assignIfPresent(e,"approvalPromptRequiredVersion",t,"approvalPromptRequiredVersion"),this.assignIfPresent(e,"approvalPromptVersion",t,"approvalPromptVersion"),this.assignIfPresent(e,"approvalPromptStatus",t,"approvalPromptStatus"),this.assignIfPresent(e,"approvalPromptTransport",t,"approvalPromptTransport"),this.assignIfPresent(e,"approvalPromptMessageKind",t,"approvalPromptMessageKind"),this.assignIfPresent(e,"approvalPromptLastAttemptAt",t,"approvalPromptLastAttemptAt"),this.assignIfPresent(e,"approvalPromptDeliveredAt",t,"approvalPromptDeliveredAt"),this.assignIfPresent(e,"approvalPromptFailedAt",t,"approvalPromptFailedAt"),this.setControlFieldIfPresent(e,"planModeApproved",t)}applySessionMetadataPatch(e,t){this.assignIfDefined(e,"approvalRationale",t.approvalRationale),this.assignIfDefined(e,"taskFlowMirror",t.taskFlowMirror)}applyWorktreeMetadataPatch(e,t){this.assignIfDefined(e,"worktreePath",t.worktreePath),this.assignIfDefined(e,"worktreeBranch",t.worktreeBranch),this.assignIfDefined(e,"worktreePrUrl",t.worktreePrUrl),this.assignIfDefined(e,"worktreePrNumber",t.worktreePrNumber),this.assignIfDefined(e,"worktreeMerged",t.worktreeMerged),this.assignIfDefined(e,"worktreeMergedAt",t.worktreeMergedAt),this.assignIfDefined(e,"worktreeDisposition",t.worktreeDisposition),this.assignIfDefined(e,"worktreePrTargetRepo",t.worktreePrTargetRepo),this.assignIfDefined(e,"worktreePushRemote",t.worktreePushRemote),this.assignIfDefined(e,"worktreeLifecycle",t.worktreeLifecycle),"autoMergeParentSessionId"in t&&(e.autoMergeParentSessionId=t.autoMergeParentSessionId),"autoMergeConflictResolutionAttemptCount"in t&&(e.autoMergeConflictResolutionAttemptCount=t.autoMergeConflictResolutionAttemptCount),"autoMergeResolverSessionId"in t&&(e.autoMergeResolverSessionId=t.autoMergeResolverSessionId)}assignIfDefined(e,t,r){r!==void 0&&(e[t]=r)}assignIfPresent(e,t,r,o){Object.hasOwn(r,o)&&(e[t]=r[o])}copyControlPatchField(e,t,r){Object.hasOwn(t,r)&&(e[r]=t[r])}setControlFieldIfPresent(e,t,r){Object.hasOwn(r,t)&&e.setControlField?.(t,r[t])}};var Lp=new Set(["starting","running"]),Fn=class{constructor(e,t){this.sessions=e;this.store=t}sessions;store;resolveActive(e){let t=this.sessions.get(e);return t||(this.findPreferredMatch(e,r=>r.name===e)??this.findPreferredMatch(e,r=>C(r)===e)??this.findPreferredMatch(e,r=>r.harnessSessionId===e))}getPersistedSession(e){return this.store.getPersistedSession(e)}resolveBackendConversationId(e){let t=this.resolveActive(e);return this.store.resolveBackendConversationId(e,t?C(t)??t.harnessSessionId:void 0)}findPreferredMatch(e,t){let r,o;for(let i of this.sessions.values())t(i,e)&&((!o||i.startedAt>o.startedAt)&&(o=i),Lp.has(i.status)&&(!r||i.startedAt>r.startedAt)&&(r=i));return r??o}};import{existsSync as Bp}from"fs";var ra=new Set(["merged","released","pr_open","dismissed","cleanup_failed"]),Ln=class{constructor(e){this.deps=e}deps;async plan(e){let t=D(e)??e.harnessSessionId;if(this.deps.isAlreadyMerged(t))return`${e.name}`,{kind:"skip",result:{notificationSent:!0,worktreeRemoved:!1}};let r=ra.has(e.worktreeState)?e.worktreeState:e.worktreeLifecycle?.state&&ra.has(e.worktreeLifecycle.state)?e.worktreeLifecycle.state:void 0;if(r&&!(r==="pr_open"&&e.worktreeStrategy==="auto-pr"))return`${e.name}${e.worktreeLifecycle?.state??e.worktreeState}`,{kind:"skip",result:{notificationSent:!0,worktreeRemoved:!1}};if(e.status!=="completed")return{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}};if(!this.deps.shouldRunWorktreeStrategy(e))return`${e.name}${e.phase}`,{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}};let o=e.worktreeStrategy;if(!o||o==="off"||o==="manual")return{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}};let i=e.worktreePath,s=this.deps.resolveWorktreeRepoDir(e.originalWorkdir,i),a=e.worktreeBranch;if(!s)return{kind:"notify",label:"worktree-missing-repo-dir",message:`⚠️ [${e.name}] Cannot determine the original repo for worktree ${i}. Manual inspection is required.`};if(!a)return{kind:"notify",label:"worktree-no-branch-name",message:`⚠️ [${e.name}] Cannot determine branch name for worktree ${i}. The worktree may have been removed or is in detached HEAD state. Manual cleanup may be needed.`};let l=L(e);if(l&&!Bp(i))return{kind:"no-change",repoDir:s,worktreePath:i,branchName:a,nativeBackendWorktree:l};let d=e.worktreeBaseBranch??Ee(s),u=this.deps.getWorktreeCompletionState(s,i,a,d);if(u==="no-change")return{kind:"no-change",repoDir:s,worktreePath:i,branchName:a,nativeBackendWorktree:l};if(u==="merged")return{kind:"merged",repoDir:s,worktreePath:i,branchName:a,nativeBackendWorktree:l};if(u==="released")return{kind:"released",repoDir:s,worktreePath:i,branchName:a,nativeBackendWorktree:l,reasons:["merge_noop_content_already_on_base"]};if(u==="base-advanced")return{kind:"notify",label:"worktree-no-commits-ahead",message:`⚠️ [${e.name}] Auto-merge: branch '${a}' has no commits ahead of '${d}', but '${d}' has new commits — commits likely landed outside the worktree branch. Verify that commits were not made directly to '${d}' instead of the worktree branch. Worktree: ${i}`};if(u==="dirty-uncommitted")return{kind:"dirty-uncommitted",worktreePath:i,branchName:a,baseBranch:d};let f=Ne(s,a,d);if(!f)return`${a}`,{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}};let g=e.repoIntegrationPolicy?void 0:this.deps.resolveRepoPolicy?.(s),k=e.repoIntegrationPolicy??g?.policy,h=e.repoIntegrationPolicy?this.deps.isPrAvailable(s):g?.prAvailable??this.deps.isPrAvailable(s),p=ls({requestedStrategy:o,policy:k,prAvailable:h,existingOpenPr:!1});return p.strategy?{kind:"decision",strategy:p.strategy,policy:k,policyReason:p.reason,policyBlocked:p.blocked,allowedActions:p.allowedActions,repoDir:s,worktreePath:i,branchName:a,baseBranch:d,diffSummary:f,sessionRef:t??void 0}:{kind:"skip",result:{notificationSent:!1,worktreeRemoved:!1}}}};function ye(n){let e=[];typeof n.costUsd=="number"&&Number.isFinite(n.costUsd)&&e.push(`$${n.costUsd.toFixed(2)}`);let t=Kp(n);t!==void 0&&e.push(se(t));let r=ge({harness:n.harnessName??n.harness,model:n.model});return r&&e.push(...r.split(" | ")),e.length>0?` | ${e.join(" | ")}`:""}function Kp(n){if(typeof n.duration=="number"&&Number.isFinite(n.duration)&&n.duration>=0)return n.duration;if(typeof n.createdAt=="number"&&Number.isFinite(n.createdAt)&&typeof n.completedAt=="number"&&Number.isFinite(n.completedAt)&&n.completedAt>=n.createdAt)return n.completedAt-n.createdAt}function qp(n){if(n.requestedPermissionMode==="plan"){if(n.approvalExecutionState==="approved_then_implemented"){if(n.planApproval==="ask"&&n.approvalPromptStatus==="delivered"&&n.approvalPromptMessageKind==="canonical_buttons"&&n.approvalPromptDeliveredAt)return"Approval interpretation: canonical Approve/Revise/Reject buttons were delivered, and implementation after approval was expected.";if(n.approvalState==="approved")return"Approval interpretation: explicit plan approval was recorded before implementation, so leaving plan-only mode was expected."}if(n.approvalExecutionState==="implemented_without_required_approval")return"Approval interpretation: implementation left plan-only mode without a recorded approval."}}function Vp(){return/https?:\/\/github\.com\/[^\s)]+\/[^\s)]+\/pull\/(\d+)(?=[\s).,;:]|$)/gi}function Up(){return/https?:\/\/\S+/gi}function Bn(n){let e=qp(n);return[`Requested permission mode: ${n.requestedPermissionMode??"unknown"}`,`Effective permission mode: ${n.currentPermissionMode??"unknown"}`,`Deterministic approval/execution state: ${n.approvalExecutionState??"unknown"}`,...e?[e]:[]]}function mo(n){switch(n){case"user":return"Stopped by user";case"shutdown":return"Stopped by shutdown";case"startup-timeout":return"Stopped by startup timeout";case"unknown":case void 0:return"Stopped unexpectedly";default:return"Stopped"}}function Gp(){return{requiresShortFactualSummary:!0,owner:"agent",appliesToOrdinaryTerminalCompletions:!0}}function jp(){return{requiresShortFactualSummary:!0,owner:"agent",appliesToWorktreeTerminalOutcomes:!0}}function zp(){return{requiresShortFactualSummary:!0,owner:"agent",appliesToGoalTaskCompletions:!0}}function fo(n){let{sessionId:e,canonicalStatusDetail:t,canonicalStatusDelivered:r=!0,hasOriginRouteBlock:o=!1}=n,i=o?["7. Before sending that follow-up, honor the Session origin route block above. If originRoute differs from the current chat, do NOT use a plain final assistant reply; use a routed send path that preserves provider/target/threadId."]:[],s=o?8:7,a=o?9:8;return["[ACTION REQUIRED] Follow your autonomy rules for session completion:",`1. Use agent_output(session='${e}', full=true) to read the full result.`,"2. If this is part of a multi-phase pipeline, launch the next phase NOW — do not wait for user input.",`3. ${t??(r?"The plugin already sent the canonical completion status to the user.":"The plugin did not confirm delivery of the canonical completion status to the user.")}`,"4. Treat the completed session output as source material, not visible delivery. A meaningful final summary inside agent_output is not enough to skip, because the user may only have seen the plugin's terse status line.","5. If the visible result is only the plugin's terse status line, use the full output to send the user one short factual completion summary for this completed session. Do this even when agent_output already contains a good final summary.","6. This requirement applies to ordinary terminal/manual completions too, not just delegated worktree decisions.",...i,`${s}. That follow-up belongs to you alone; keep it brief, concrete, and grounded in reliable result data. Send at most one orchestrator-owned human summary for this terminal/worktree outcome.`,...r?[`${a}. Do NOT repeat the plugin's status line, and do NOT rely on the plugin to summarize the completed work for you.`]:[`${a}. Because canonical status delivery was not confirmed, account for that gap yourself when you follow up; do NOT assume the plugin already reached the user.`],`${a+1}. Send a normal concise final response after any routed follow-up is visibly sent. Do not use marker text, do not answer NO_REPLY, and do not ask the user whether they want the summary.`]}function Hp(n){let{contract:e,canonicalStatusDelivered:t}=n;return["Completion diagnostics:",`- Canonical completion status delivered to user: ${t?"yes":"no"}`,`- Plugin requested short factual follow-up summary: ${e.requiresShortFactualSummary?"yes":"no"}`,`- Contract applies to ordinary terminal/manual completions: ${e.appliesToOrdinaryTerminalCompletions?"yes":"no"}`]}function go(n){let{session:e,originThreadLine:t,preview:r}=n,o=!!t.trim(),i=Gp(),s=a=>["Coding agent session completed.",`Name: ${e.name} | ID: ${e.id}`,`Status: ${e.status}`,...o?[t]:[],...Bn(e),"","Output preview:",r,"",...Hp({contract:i,canonicalStatusDelivered:a}),"",...fo({sessionId:e.id,canonicalStatusDelivered:a,hasOriginRouteBlock:o})].join(`
141
141
  `);return{userMessage:`✅ [${e.name}] Completed${ye(e)}`,wakeMessageOnNotifySuccess:s(!0),wakeMessageOnNotifyFailed:s(!1),followupContract:i}}function Ge(n){let e=jp(),t=!!n.originThreadLine.trim(),r=(n.detailLines??[]).map(i=>oa(i).trim()).filter(i=>i.length>0),o=oa(n.outcomeLine);return["Worktree follow-through outcome recorded.",`Name: ${n.sessionName??"unknown"} | ID: ${n.sessionId}`,...t?[n.originThreadLine]:[],"","Canonical outcome status:",o,...r.length>0?["","Outcome details:",...r.map(i=>`- ${i}`)]:[],"","Completion diagnostics:",`- Canonical worktree status delivered to user: ${n.canonicalStatusDelivered?"yes":"no"}`,`- Plugin requested short factual follow-up summary: ${e.requiresShortFactualSummary?"yes":"no"}`,`- Contract applies to worktree terminal outcomes: ${e.appliesToWorktreeTerminalOutcomes?"yes":"no"}`,"","[ACTION REQUIRED] Follow your autonomy rules for worktree follow-through:",`1. Use agent_output(session='${n.sessionId}', full=true) to read the full result if output is available.`,"2. Treat the completed session output as source material, not visible delivery. A meaningful final summary inside agent_output is not enough to skip, because the user may only have seen the plugin's terse status line.","3. Use the full output plus the canonical outcome facts above to send the user one short factual outcome summary. Do this even when agent_output already contains a good final summary.","4. If full output is unavailable or not meaningful, say only what is proven by the merge/PR facts above; do not invent task details.","5. Mention blockers such as push failure when present; do not describe a local-only merge as pushed.","6. Do not include raw PR URLs in the follow-up summary. The plugin already posted the PR link in the canonical status; refer to PRs by number, repo, and branch instead.",...t?["7. Before sending that follow-up, honor the Session origin route block above. If originRoute differs from the current chat, do NOT use a plain final assistant reply; use a routed send path that preserves provider/target/threadId."]:[],`${t?8:7}. Do NOT repeat only the plugin status line; keep the follow-up brief, concrete, and non-duplicative. Send at most one human-visible summary for this terminal/worktree outcome, counting summaries already sent by the foreground assistant turn or routed message tools.`,`${t?9:8}. Send a normal concise final response after any routed follow-up is visibly sent. Do not use marker text, do not answer NO_REPLY, and do not ask the user whether they want the summary.`].join(`
142
142
  `)}function ho(n){let e=zp(),t=!!n.originThreadLine.trim();return["Goal task succeeded.",`Task: ${n.taskName}`,`Name: ${n.sessionName??n.taskName} | ID: ${n.sessionId}`,...t?[n.originThreadLine]:[],"","Canonical goal status:",n.summary,"","Completion diagnostics:",`- Canonical goal success status delivered to user: ${n.canonicalStatusDelivered?"yes":"no"}`,`- Plugin requested short factual follow-up summary: ${e.requiresShortFactualSummary?"yes":"no"}`,`- Contract applies to goal task completions: ${e.appliesToGoalTaskCompletions?"yes":"no"}`,"","[ACTION REQUIRED] Follow your autonomy rules for goal task completion:",`1. Use agent_output(session='${n.sessionId}', full=true) to read the full result if output is available.`,"2. Treat the completed session output as source material, not visible delivery. A meaningful final summary inside agent_output is not enough to skip, because the user may only have seen the plugin's terse goal status line.","3. Send the user one short factual completion summary grounded in the full output plus the canonical goal status above. Do this even when agent_output already contains a good final summary.","4. If full output is unavailable or not meaningful, say only what is proven by the goal status above; do not invent task details.",...t?["5. Before sending that follow-up, honor the Session origin route block above. If originRoute differs from the current chat, do NOT use a plain final assistant reply; use a routed send path that preserves provider/target/threadId."]:[],`${t?6:5}. Do NOT repeat only the plugin status line; keep the follow-up brief, concrete, and non-duplicative. Send at most one human-visible summary for this goal success outcome, counting summaries already sent by the foreground assistant turn or routed message tools.`,`${t?7:6}. Send a normal concise final response after any routed follow-up is visibly sent. Do not use marker text, do not answer NO_REPLY, and do not ask the user whether they want the summary.`].join(`
143
143
  `)}function oa(n){return n.replace(Vp(),"PR #$1").replace(Up(),"[link omitted]")}function yo(n){let{session:e,originThreadLine:t,errorSummary:r,preview:o,worktreeAutoCleaned:i,failedButtons:s}=n,a=o.trim()?["","Output preview:",o]:[],l=i?["","Note: Worktree and branch were auto-removed (zero cost, startup failure)."]:[];return{userMessage:[`❌ [${e.name}] Failed${ye(e)}`,` ⚠️ ${r}`].join(`
144
144
  `),wakeMessage:["Coding agent session failed.",`Name: ${e.name} | ID: ${e.id}`,`Status: ${e.status}`,t,...Bn(e),...e.harnessSessionId?[`Backend conversation ID: ${e.harnessSessionId}`]:[],"","Failure summary:",r,...a,...l,"","[ACTION REQUIRED] Follow your autonomy rules for session failure:",`1. Use agent_output(session='${e.id}', full=true) to inspect the full failure context.`,`2. Continue the same session with agent_respond(session='${e.id}', message='<next instruction>').`,` If you intentionally want to fork or switch harnesses, launch a new session with agent_launch(resume_session_id='${e.id}', fork_session=true, ...)`," If the failure is a launch/config issue, relaunch fresh with agent_launch(prompt=...).","3. Notify the user with the failure cause and the next action you are taking."].join(`
145
145
  `),buttons:s}}function So(n){let{session:e,originThreadLine:t,preview:r}=n;return{userMessage:`⏸️ [${e.name}] Turn completed${ye(e)}`,wakeMessage:["Coding agent session turn ended.",`Name: ${e.name}`,`ID: ${e.id}`,`Status: ${e.status}`,`Lifecycle: ${e.lifecycle}`,"","Last output (~20 lines):",r,...t?["",t]:[]].join(`
146
- `)}}function ko(n){let{sessionName:e,sessionId:t,branchName:r,baseBranch:o,promptSnippet:i,commitLines:s,moreNote:a,originThreadLine:l,diffSummary:d,allowedActions:u,policyReason:f}=n,h=!!l?.trim();return[`[DELEGATED WORKTREE DECISION] Session "${e}" completed with changes.`,"",`Session ID: ${t}`,`Branch: ${r} → ${o}`,`Commits: ${d.commits} | Files: ${d.filesChanged} | +${d.insertions} / -${d.deletions}`,...h?[l]:[],"",...s,...a?[a]:[],"","Original task prompt (first 500 chars):",i,"",...f?[`Policy constraint: ${f}`,""]:[],"You own the next step for this worktree.",`- First call agent_output(session='${t}', full=true) to inspect the full session output and use it as source material for your decision.`,...u?.merge===!1?["- Do not call agent_merge(); repo policy does not allow direct merge for this session."]:[`- Merge immediately with agent_merge(session="${e}", base_branch="${o}") if the changes are clearly in-scope and low-risk.`],...u?.pr===!1?["- Do not call agent_pr(); PR creation is unavailable or forbidden by repo policy."]:[`- If a PR is safer or human choice is needed, call agent_request_worktree_decision(session="${e}", summary="...") so the user gets the canonical Merge/Open PR/Later/Discard buttons.`],`- If scope or risk is unclear, call agent_request_worktree_decision(session="${e}", summary="...") with a concise risk summary instead of sending a plain-text-only question.`,"- Never call agent_pr() autonomously in delegate mode.","- After deciding, notify the user briefly with what you did and why.",...h?["- Send any human follow-up to the Session origin route above; if it differs from the current chat, do not use a plain final assistant reply."]:[]].join(`
146
+ `)}}function ko(n){let{sessionName:e,sessionId:t,branchName:r,baseBranch:o,promptSnippet:i,commitLines:s,moreNote:a,originThreadLine:l,diffSummary:d,allowedActions:u,policyReason:f}=n,g=!!l?.trim();return[`[DELEGATED WORKTREE DECISION] Session "${e}" completed with changes.`,"",`Session ID: ${t}`,`Branch: ${r} → ${o}`,`Commits: ${d.commits} | Files: ${d.filesChanged} | +${d.insertions} / -${d.deletions}`,...g?[l]:[],"",...s,...a?[a]:[],"","Original task prompt (first 500 chars):",i,"",...f?[`Policy constraint: ${f}`,""]:[],"You own the next step for this worktree.",`- First call agent_output(session='${t}', full=true) to inspect the full session output and use it as source material for your decision.`,...u?.merge===!1?["- Do not call agent_merge(); repo policy does not allow direct merge for this session."]:[`- Merge immediately with agent_merge(session="${e}", base_branch="${o}") if the changes are clearly in-scope and low-risk.`],...u?.pr===!1?["- Do not call agent_pr(); PR creation is unavailable or forbidden by repo policy."]:[`- If a PR is safer or human choice is needed, call agent_request_worktree_decision(session="${e}", summary="...") so the user gets the canonical Merge/Open PR/Later/Discard buttons.`],`- If scope or risk is unclear, call agent_request_worktree_decision(session="${e}", summary="...") with a concise risk summary instead of sending a plain-text-only question.`,"- Never call agent_pr() autonomously in delegate mode.","- After deciding, notify the user briefly with what you did and why.",...g?["- Send any human follow-up to the Session origin route above; if it differs from the current chat, do not use a plain final assistant reply."]:[]].join(`
147
147
  `)}function vo(n,e){return[`[DELEGATED WORKTREE DECISION REMINDER] Session "${n.name}" still has an unresolved worktree decision.`,"",`Session ID: ${n.sessionId??n.harnessSessionId}`,`Branch: ${n.worktreeBranch??"unknown"}`,`Pending: ${e}h`,"","Resolve it now:",`- agent_merge(session="${n.name}") if the diff is clearly safe and in scope`,"- If a PR is safer, ask the user before agent_pr()","- If scope or risk is unclear, ask the user for guidance","- Never call agent_pr() autonomously in delegate mode"].join(`
148
- `)}function Po(n){let{sessionName:e,sessionId:t,headline:r,cleanupSummary:o,preview:i,originThreadLine:s,requestedPermissionMode:a,currentPermissionMode:l,approvalExecutionState:d,approvalState:u,planApproval:f,approvalPromptStatus:h,approvalPromptMessageKind:k,approvalPromptDeliveredAt:g}=n,p=i.trim()?["","Output preview:",i]:[],y=!!s?.trim();return[r??"Coding agent session completed with no worktree changes to merge.",`Name: ${e} | ID: ${t}`,`Worktree outcome: ${o}`,...y?[s]:[],...Bn({requestedPermissionMode:a,currentPermissionMode:l,approvalExecutionState:d,approvalState:u,planApproval:f,approvalPromptStatus:h,approvalPromptMessageKind:k,approvalPromptDeliveredAt:g}),...p,"",...fo({sessionId:t,canonicalStatusDetail:"The plugin already sent the canonical completion status to the user, including the no-worktree-changes outcome.",hasOriginRouteBlock:y})].join(`
148
+ `)}function Po(n){let{sessionName:e,sessionId:t,headline:r,cleanupSummary:o,preview:i,originThreadLine:s,requestedPermissionMode:a,currentPermissionMode:l,approvalExecutionState:d,approvalState:u,planApproval:f,approvalPromptStatus:g,approvalPromptMessageKind:k,approvalPromptDeliveredAt:h}=n,p=i.trim()?["","Output preview:",i]:[],y=!!s?.trim();return[r??"Coding agent session completed with no worktree changes to merge.",`Name: ${e} | ID: ${t}`,`Worktree outcome: ${o}`,...y?[s]:[],...Bn({requestedPermissionMode:a,currentPermissionMode:l,approvalExecutionState:d,approvalState:u,planApproval:f,approvalPromptStatus:g,approvalPromptMessageKind:k,approvalPromptDeliveredAt:h}),...p,"",...fo({sessionId:t,canonicalStatusDetail:"The plugin already sent the canonical completion status to the user, including the no-worktree-changes outcome.",hasOriginRouteBlock:y})].join(`
149
149
  `)}var aa=3200,wo=3e3,Qp=2400,Yp=120,Jp=5,Xp=280,ia=1400,sa="- Additional plan details omitted for brevity.";function la(n){return n.replace(/^#{1,6}\s+/,"").replace(/^[-*+]\s+/,"").replace(/^\d+[.)]\s+/,"").replace(/^`([^`]+)`$/,"$1").trim()}function Zp(n){return n.split(`
150
150
  `).map(e=>e.trim()).filter(Boolean).map(la).map(e=>q(e,220)).filter(e=>e.length>0).filter(e=>!/^(plan|proposed plan|implementation plan|review summary|full plan)[:]?$/i.test(e)).filter(e=>!/^(should|can|could|would|will)\b.*\?$/i.test(e)).filter(e=>!/^(thinking|checking|considering|analyzing)\b/i.test(e))}function ec(n){return n.split(`
151
151
  `).map(e=>e.trim()).filter(Boolean).map(la).filter(e=>e.length>0).filter(e=>!/^(plan|proposed plan|implementation plan|review summary|summary|why this was escalated|full plan)[:]?$/i.test(e)).filter(e=>!/^(should|can|could|would|will)\b.*\?$/i.test(e)).filter(e=>!/^(thinking|checking|considering|analyzing)\b/i.test(e))}function bo(n){let e=Zp(n);return e.length===0?`Review summary:
@@ -164,9 +164,9 @@ Approval is still pending for this plan version.`:`
164
164
  Continued in next message.`}function oc(n){let{sessionName:e,actionableVersion:t,fullPlanText:r,hasButtons:o}=n,i=`📋 [${e}] Plan v${t??"?"} ready for approval:`,s=`
165
165
 
166
166
  Full plan (truncated):
167
- `,a=ua(o,!0),l=Math.max(0,wo-i.length-s.length-a.length);return`${i}${s}${q(r,l)}${a}`}function ic(n){let{sessionName:e,actionableVersion:t,fullPlanText:r,hasButtons:o}=n,i=da(e),s=Qp;for(;s>0;){let a=rc(r,s),l=a.map((f,h)=>{let k=a.length,g=[`📋 [${i}] Plan v${t??"?"} ready for approval (${h+1}/${k}):`,"",h===0?"Full plan:":""].filter(Boolean).join(`
168
- `),p=ua(o,h===k-1);return`${g}
169
- ${f}${p}`}),d=l.reduce((f,h)=>Math.max(f,h.length),0);if(d<=wo)return l;let u=d-wo;s-=Math.max(u,50)}return[oc({sessionName:i,actionableVersion:t,fullPlanText:r,hasButtons:o})]}function Ao(n){let{preview:e,artifact:t}=n,r=t?.markdown?.trim();return r&&r.length<=aa?`Full plan:
167
+ `,a=ua(o,!0),l=Math.max(0,wo-i.length-s.length-a.length);return`${i}${s}${q(r,l)}${a}`}function ic(n){let{sessionName:e,actionableVersion:t,fullPlanText:r,hasButtons:o}=n,i=da(e),s=Qp;for(;s>0;){let a=rc(r,s),l=a.map((f,g)=>{let k=a.length,h=[`📋 [${i}] Plan v${t??"?"} ready for approval (${g+1}/${k}):`,"",g===0?"Full plan:":""].filter(Boolean).join(`
168
+ `),p=ua(o,g===k-1);return`${h}
169
+ ${f}${p}`}),d=l.reduce((f,g)=>Math.max(f,g.length),0);if(d<=wo)return l;let u=d-wo;s-=Math.max(u,50)}return[oc({sessionName:i,actionableVersion:t,fullPlanText:r,hasButtons:o})]}function Ao(n){let{preview:e,artifact:t}=n,r=t?.markdown?.trim();return r&&r.length<=aa?`Full plan:
170
170
  ${r}`:bo(r||e)}function pa(n){let{sessionName:e,actionableVersion:t,preview:r,artifact:o,hasButtons:i}=n,s=o?.markdown?.trim(),a=da(e);if(s){let d=`📋 [${a}] Plan v${t??"?"} ready for approval:
171
171
 
172
172
  Full plan:
@@ -180,52 +180,52 @@ ${l}
180
180
  ${i?"Choose Approve, Revise, or Reject below.":"Approval is still pending for this plan version."}`],reviewSummary:l}}function ca(n){let e=n?.trim();return e||void 0}function sc(n){let e=ca(n.questionText)??"The session is waiting for your reply.",t=ca(n.contextSummary);return t?[`❓ [${n.sessionName}] Question waiting for reply:`,"",e,"",`Why: ${t}`].join(`
181
181
  `):`❓ [${n.sessionName}] Question waiting for reply:
182
182
 
183
- ${e}`}function ac(n,e){return e!=null&&n.approvalPromptRequiredVersion===e&&(n.approvalPromptStatus==="delivered"||n.approvalPromptStatus==="fallback_delivered")}function ct(n){let{session:e,summary:t}=n,r=e.actionablePlanDecisionVersion??e.planDecisionVersion;return[`📋 [${e.name}] Plan v${r??"?"} needs your decision.`,"","Interactive Approve / Revise / Reject buttons could not be delivered, so reply here instead:",'- Reply "approve" to approve and start implementation','- Reply "reject" to reject and stop the session',"- Any other reply will be sent back as revision feedback","","Why this was escalated:","",t].join(`
184
- `)}function Io(n){let{session:e,preview:t,questionText:r,questionContextSummary:o,planArtifact:i,originThreadLine:s,planApprovalMode:a,planApprovalButtons:l,questionButtons:d}=n,u=e.pendingPlanApproval,f=e.actionablePlanDecisionVersion??e.planDecisionVersion,h=ac(e,f),k=a??"delegate",g=u&&k==="ask"&&!h?pa({sessionName:e.name,actionableVersion:f,preview:t,artifact:i,hasButtons:!!l}):void 0,p=u?g?.reviewSummary??Ao({preview:t,artifact:i}):void 0,y=u?g&&g.userMessages.length===1?g.userMessages[0]:void 0:sc({sessionName:e.name,questionText:r??t,contextSummary:o,hasButtons:!!d}),w=u&&g&&g.userMessages.length>1?g.userMessages.map((A,I,b)=>({text:A,buttons:I===b.length-1?l:void 0})):void 0;if(u){let A=k,I="Permission mode: plan → will switch to bypassPermissions on approval";return A==="delegate"?{label:"plan-approval",userMessage:y,userMessages:w,planReviewSummary:p,wakeMessage:["[DELEGATED PLAN APPROVAL] Coding agent session has finished its plan and is requesting approval to implement.",`Name: ${e.name} | ID: ${e.id} | Plan v${f??"?"}`,s,I,"","⚠️ YOU MUST COMPLETE THESE STEPS IN ORDER. Do NOT skip any step.","","━━━ STEP 1 (MANDATORY): Read the full plan ━━━",`Call agent_output(session='${e.id}', full=true) to read the FULL plan output.`,"The preview below is truncated — you MUST read the full output before making any decision.","","Preview (truncated):",t,"","━━━ STEP 2 (MANDATORY): Review privately ━━━","You are the delegated decision-maker. Review the plan yourself before involving the user.","If you approve directly, you own the user-facing explanation of what was approved and why.","Keep it short and user-facing: one sentence is usually enough.","","━━━ STEP 3 (ONLY AFTER steps 1 and 2): Decide ━━━","Choose ONE:","","APPROVE the plan directly if ALL of the following are true:","- You have read the FULL plan (not just the preview)","- The plan scope matches the original task request","- The changes are low-risk (no destructive operations, no credential handling, no production deployments)","- The plan is clear and well-scoped (no ambiguous requirements or open design questions)","- No architectural decisions that the user should weigh in on","- The working directory and codebase are correct","","ESCALATE to the user and WAIT if ANY of the following are true:","- The plan involves destructive operations (deleting files, dropping tables, force-pushing)","- The plan involves credentials, secrets, or production environments","- The plan requires architectural decisions not covered by the original task","- The scope has expanded beyond the original request","- The requirements are ambiguous or the plan makes assumptions the user should confirm","- You are unsure — when in doubt, always escalate","",`If approving: call agent_respond(session='${e.id}', message='Approved. Go ahead.', approve=true, approval_rationale='<brief reason>').`,"That rationale should say why approval was safe: for example scope match, low risk, or no meaningful ambiguity.","After approving directly, send the user a short plain-text follow-up explaining what was approved and why.","The plugin's thumbs-up line is only the minimal approval acknowledgment, not the explanation.",`If escalating: call agent_request_plan_approval(session='${e.id}', summary='...') exactly once so the plugin posts the single canonical Approve / Revise / Reject prompt.`,"That summary must concisely explain why this was escalated, plus changed files/components, risk level and why, scope match/expansion, and any concerns or assumptions.","After the canonical prompt exists, WAIT for the user's button click or explicit response and do NOT send a second plain-text recap.",`To request changes without user escalation: call agent_respond(session='${e.id}', message='<your feedback>') and do NOT set approve=true. The agent will revise the plan.`].join(`
185
- `)}:A==="ask"?{label:"plan-approval",userMessage:y,userMessages:w,planReviewSummary:p,wakeMessage:["[USER APPROVAL REQUESTED] Coding agent session has finished its plan. The user has been notified via Telegram and must approve directly.",`Name: ${e.name} | ID: ${e.id} | Plan v${f??"?"}`,s,I,"","DO NOT approve this plan yourself. Wait for the user's explicit approval or rejection.","Once the user responds, forward their decision:",` To approve: agent_respond(session='${e.id}', message='Approved. Go ahead.', approve=true)`,` To request changes: agent_respond(session='${e.id}', message='<user feedback>')`,"","Preview (truncated):",t].join(`
186
- `),buttons:w?void 0:l}:{label:"plan-approval",userMessage:y,planReviewSummary:p,wakeMessage:["[AUTO-APPROVE] Session has a plan ready. Approve it now:",`agent_respond(session='${e.id}', message='Approved. Go ahead.', approve=true)`].join(`
187
- `)}}let R=e.multiTurn?"Multi-turn session":"Session";return{label:"waiting",userMessage:y,wakeMessage:[`[SYSTEM INSTRUCTION: Follow your auto-respond rules strictly. If this is a permission request or "should I continue?" → auto-respond. For ALL other questions → forward the agent's EXACT question to the user. Do NOT add your own analysis, commentary, or interpretation. Do NOT "nudge" or "poke" the session.]`,"",`${R} is waiting for a genuine user reply.`,`Name: ${e.name} | ID: ${e.id}`,s,"","Last output:",t,"",`Use agent_respond(session='${e.id}', message='...') to send a reply, or agent_output(session='${e.id}', full: true) to see full context before deciding.`].join(`
183
+ ${e}`}function ac(n,e){return e!=null&&n.approvalPromptRequiredVersion===e&&(n.approvalPromptStatus==="delivered"||n.approvalPromptStatus==="fallback_delivered")}function mt(n){let{session:e,summary:t}=n,r=e.actionablePlanDecisionVersion??e.planDecisionVersion;return[`📋 [${e.name}] Plan v${r??"?"} needs your decision.`,"","Interactive Approve / Revise / Reject buttons could not be delivered, so reply here instead:",'- Reply "approve" to approve and start implementation','- Reply "reject" to reject and stop the session',"- Any other reply will be sent back as revision feedback","","Why this was escalated:","",t].join(`
184
+ `)}function Io(n){let{session:e,preview:t,questionText:r,questionContextSummary:o,planArtifact:i,originThreadLine:s,planApprovalMode:a,planApprovalButtons:l,questionButtons:d}=n,u=e.pendingPlanApproval,f=e.actionablePlanDecisionVersion??e.planDecisionVersion,g=ac(e,f),k=a??"delegate",h=u&&k==="ask"&&!g?pa({sessionName:e.name,actionableVersion:f,preview:t,artifact:i,hasButtons:!!l}):void 0,p=u?h?.reviewSummary??Ao({preview:t,artifact:i}):void 0,y=u?h&&h.userMessages.length===1?h.userMessages[0]:void 0:sc({sessionName:e.name,questionText:r??t,contextSummary:o,hasButtons:!!d}),P=u&&h&&h.userMessages.length>1?h.userMessages.map((A,I,R)=>({text:A,buttons:I===R.length-1?l:void 0})):void 0;if(u){let A=k,I="Permission mode: plan → will switch to bypassPermissions on approval";return A==="delegate"?{label:"plan-approval",userMessage:y,userMessages:P,planReviewSummary:p,wakeMessage:["[DELEGATED PLAN APPROVAL] Coding agent session has finished its plan and is requesting approval to implement.",`Name: ${e.name} | ID: ${e.id} | Plan v${f??"?"}`,s,I,"","⚠️ YOU MUST COMPLETE THESE STEPS IN ORDER. Do NOT skip any step.","","━━━ STEP 1 (MANDATORY): Read the full plan ━━━",`Call agent_output(session='${e.id}', full=true) to read the FULL plan output.`,"The preview below is truncated — you MUST read the full output before making any decision.","","Preview (truncated):",t,"","━━━ STEP 2 (MANDATORY): Review privately ━━━","You are the delegated decision-maker. Review the plan yourself before involving the user.","If you approve directly, you own the user-facing explanation of what was approved and why.","Keep it short and user-facing: one sentence is usually enough.","","━━━ STEP 3 (ONLY AFTER steps 1 and 2): Decide ━━━","Choose ONE:","","APPROVE the plan directly if ALL of the following are true:","- You have read the FULL plan (not just the preview)","- The plan scope matches the original task request","- The changes are low-risk (no destructive operations, no credential handling, no production deployments)","- The plan is clear and well-scoped (no ambiguous requirements or open design questions)","- No architectural decisions that the user should weigh in on","- The working directory and codebase are correct","","ESCALATE to the user and WAIT if ANY of the following are true:","- The plan involves destructive operations (deleting files, dropping tables, force-pushing)","- The plan involves credentials, secrets, or production environments","- The plan requires architectural decisions not covered by the original task","- The scope has expanded beyond the original request","- The requirements are ambiguous or the plan makes assumptions the user should confirm","- You are unsure — when in doubt, always escalate","",`If approving: call agent_respond(session='${e.id}', message='Approved. Go ahead.', approve=true, approval_rationale='<brief reason>').`,"That rationale should say why approval was safe: for example scope match, low risk, or no meaningful ambiguity.","After approving directly, send the user a short plain-text follow-up explaining what was approved and why.","The plugin's thumbs-up line is only the minimal approval acknowledgment, not the explanation.",`If escalating: call agent_request_plan_approval(session='${e.id}', summary='...') exactly once so the plugin posts the single canonical Approve / Revise / Reject prompt.`,"That summary must concisely explain why this was escalated, plus changed files/components, risk level and why, scope match/expansion, and any concerns or assumptions.","After the canonical prompt exists, WAIT for the user's button click or explicit response and do NOT send a second plain-text recap.",`To request changes without user escalation: call agent_respond(session='${e.id}', message='<your feedback>') and do NOT set approve=true. The agent will revise the plan.`].join(`
185
+ `)}:A==="ask"?{label:"plan-approval",userMessage:y,userMessages:P,planReviewSummary:p,wakeMessage:["[USER APPROVAL REQUESTED] Coding agent session has finished its plan. The user has been notified via Telegram and must approve directly.",`Name: ${e.name} | ID: ${e.id} | Plan v${f??"?"}`,s,I,"","DO NOT approve this plan yourself. Wait for the user's explicit approval or rejection.","Once the user responds, forward their decision:",` To approve: agent_respond(session='${e.id}', message='Approved. Go ahead.', approve=true)`,` To request changes: agent_respond(session='${e.id}', message='<user feedback>')`,"","Preview (truncated):",t].join(`
186
+ `),buttons:P?void 0:l}:{label:"plan-approval",userMessage:y,planReviewSummary:p,wakeMessage:["[AUTO-APPROVE] Session has a plan ready. Approve it now:",`agent_respond(session='${e.id}', message='Approved. Go ahead.', approve=true)`].join(`
187
+ `)}}let b=e.multiTurn?"Multi-turn session":"Session";return{label:"waiting",userMessage:y,wakeMessage:[`[SYSTEM INSTRUCTION: Follow your auto-respond rules strictly. If this is a permission request or "should I continue?" → auto-respond. For ALL other questions → forward the agent's EXACT question to the user. Do NOT add your own analysis, commentary, or interpretation. Do NOT "nudge" or "poke" the session.]`,"",`${b} is waiting for a genuine user reply.`,`Name: ${e.name} | ID: ${e.id}`,s,"","Last output:",t,"",`Use agent_respond(session='${e.id}', message='...') to send a reply, or agent_output(session='${e.id}', full: true) to see full context before deciding.`].join(`
188
188
  `),buttons:d}}var Kn=3,To=180,lc=4e3,ma=32;function fa(){let n=xe(),e=hc(n);if(e)return{async generateWorktreeDecisionSummary(t){if(typeof e.generateWorktreeDecisionSummary=="function")return await e.generateWorktreeDecisionSummary(t);if(typeof e.summarizeWorktreeDecision=="function")return await e.summarizeWorktreeDecision(t);let r=yc(t);if(typeof e.generateObject=="function")return await e.generateObject({task:"openclaw-code-agent.worktree-decision-summary",prompt:r,input:t});if(typeof e.generateText=="function")return await e.generateText({task:"openclaw-code-agent.worktree-decision-summary",prompt:r});if(typeof e.complete=="function")return await e.complete({prompt:r})}}}function dc(n,e){let t=Sc(e);if(t.length>0)return t;let r=uc(n);if(r.length>0)return r;let o=[],i=n.changedFiles.slice(0,3).map(a=>`\`${a}\``);if(i.length>0){let a=n.changedFiles.length-i.length;o.push(a>0?`Touches ${i.join(", ")} and ${a} more file${a===1?"":"s"}`:`Touches ${i.join(", ")}`)}let s=[...new Set(n.commitMessages.map(a=>a.message.trim()).filter(Boolean))].slice(0,2);return s.length>0&&o.push(`Recent work: ${s.join("; ")}`),o}function uc(n){let e=new Set,t=n.commitMessages.length===1?n.changedFiles:[];return n.commitMessages.map(r=>pc(r.message,t)).filter(r=>!!r).filter(r=>{let o=r.toLowerCase();return e.has(o)?!1:(e.add(o),!0)}).slice(0,Kn)}function pc(n,e){let t=cc(n);if(!t)return;let r=e.length===1?` in \`${e[0]}\``:e.length>1&&e.length<=3?` across ${e.map(o=>`\`${o}\``).join(", ")}`:"";return xo(`${t}${r}.`,To)}function cc(n){let e=qn(Vn(n)).replace(/^(?:feat|fix|docs|style|refactor|perf|test|tests|build|ci|chore|revert)(?:\([^)]+\))?!?:\s*/i,"").replace(/\.$/,"").trim();if(!e||Co(e))return;let t=e.match(/^([a-z]+)\b(.*)$/i);if(!t)return e;let r=t[1].toLowerCase(),o=t[2]??"",s=new Map([["add","Adds"],["address","Addresses"],["block","Blocks"],["change","Changes"],["clarify","Clarifies"],["clean","Cleans"],["cover","Covers"],["create","Creates"],["deduplicate","Deduplicates"],["delete","Deletes"],["disable","Disables"],["document","Documents"],["enable","Enables"],["extract","Extracts"],["fix","Fixes"],["guard","Guards"],["harden","Hardens"],["implement","Implements"],["improve","Improves"],["init","Initializes"],["initialize","Initializes"],["migrate","Migrates"],["move","Moves"],["normalize","Normalizes"],["preserve","Preserves"],["prevent","Prevents"],["refactor","Refactors"],["remove","Removes"],["rename","Renames"],["restore","Restores"],["simplify","Simplifies"],["tighten","Tightens"],["update","Updates"],["use","Uses"],["wire","Wires"],["wrap","Wraps"]]).get(r);return s?`${s}${o}`:`${r[0].toUpperCase()}${r.slice(1)}${o}`}async function ga(n){let e=mc(n),t=dc(n.diffSummary??{changedFiles:e.changedFiles,commitMessages:e.commitSubjects.map(r=>({message:r}))},n.outputPreview);if(!n.provider)return{source:"fallback",lines:t,evidence:e,error:"LLM summary provider unavailable."};try{let r=await n.provider.generateWorktreeDecisionSummary(e),o=fc(r);return o.length>0?{source:"llm",lines:o,evidence:e}:{source:"fallback",lines:t,evidence:e,error:"LLM-generated worktree summary failed schema validation."}}catch(r){let o=r instanceof Error?r.message:String(r);return`${o}`,{source:"fallback",lines:t,evidence:e,error:"LLM summary provider failed."}}}function mc(n){let e=n.diffSummary;return{sessionName:n.sessionName,objective:Pc(n.prompt),stats:e?{commits:e.commits,filesChanged:e.filesChanged,insertions:e.insertions,deletions:e.deletions}:void 0,changedFiles:e?.changedFiles??[],commitSubjects:e?.commitMessages.map(t=>qn(t.message)).filter(Boolean).slice(0,8)??[],outputPreview:xo(Vn(n.outputPreview??""),lc)}}function fc(n){let e=gc(n),t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.summary)?e.summary:void 0;if(!t||t.length===0||t.length>Kn)return[];let r=t.map(o=>typeof o=="string"?qn(o):"").filter(Boolean);return r.length!==t.length?[]:r.some(o=>o.length>To)?[]:r.some(Co)?[]:r}function gc(n){if(typeof n!="string")return n;let e=n.trim();if(e)try{return JSON.parse(e)}catch{return{summary:e.split(`
189
189
  `).map(t=>t.replace(/^[-*•]\s+/,"").trim()).filter(Boolean).slice(0,Kn)}}}function hc(n){return[n?.worktreeDecisionSummary,n?.llm,n?.ai,n?.model,n?.models].find(t=>!!(t&&typeof t=="object"&&(typeof t.generateWorktreeDecisionSummary=="function"||typeof t.summarizeWorktreeDecision=="function"||typeof t.generateObject=="function"||typeof t.generateText=="function"||typeof t.complete=="function")))}function yc(n){return["Summarize the completed OpenClaw Code Agent work for a worktree decision notification.",'Return only JSON with shape {"summary":["..."]}.',"Write 1-3 concise, user-facing bullets that help a human choose Merge, Open PR, Later, or Discard.","Do not mention that you are summarizing. Do not invent changes not supported by the evidence.","","Evidence:",JSON.stringify(n,null,2)].join(`
190
190
  `)}function Sc(n){let e=new Set;return Vn(n??"").replace(/\r\n/g,`
191
191
  `).split(`
192
192
  `).map(r=>qn(r)).map(r=>kc(r)).filter(vc).filter(r=>{let o=r.toLowerCase();return e.has(o)?!1:(e.add(o),!0)}).slice(0,Kn)}function kc(n){return n.replace(/^(?:summary|done|completed|changes|validation|verified)\s*:\s*/i,"").trim()}function vc(n){return n.length<12||n.length>To||Co(n)||/^(```|>|command\b|exit code\b|\$|[a-z0-9_-]+@[a-z0-9_-]+:)/i.test(n)||/^(?:running|ran|pnpm|npm|node|git|tsc|vitest|jest)\b/i.test(n)||/^(?:pass|fail|ok|error)\b[:\s]/i.test(n)||/^(?:changed files?|files changed|recent commits?|commits?)\b/i.test(n)?!1:/^(?:implemented|updated|added|fixed|changed|removed|verified|covered|refactored|improved|created|documented|hardened|restored|simplified|renamed|moved|wired|handled|blocked|reduced|deduplicated|normalized|addressed|prevented)\b/i.test(n)||/\b(?:so that|coverage|validation|regression|cleanup|summary|notification|callback|button|merge|worktree|policy)\b/i.test(n)&&/\b(?:preserv(?:e|es|ed|ing)|clear(?:s|ed|ing)?|reuse(?:s|d|ing)?|cover(?:s|ed|ing)?|pass(?:es|ed|ing)?|fail(?:s|ed|ing)?|complete(?:s|d)?|fall(?:s|ing)? back)\b/i.test(n)}function Pc(n){let e=n?.replace(/\r\n/g,`
193
193
  `).split(`
194
- `).map(o=>o.trim()).filter(Boolean).join(" ");if(!e)return;let t=e.match(/^[^.!?]+[.!?]/)?.[0]??e,r=Vn(t).replace(/\s+/g," ").trim();return r?xo(r,180):void 0}function qn(n){return n.replace(/^[-*•]\s+/,"").replace(/\s+/g," ").trim()}function xo(n,e){return n.length<=e?n:`${n.slice(0,Math.max(0,e-3)).trimEnd()}...`}function Vn(n){return n.replace(/\b[A-Za-z0-9_-]*(?:api[_-]?key|token|secret|password|passwd|pwd|credential|credentials|authorization|auth)[A-Za-z0-9_-]*\b\s*[:=]\s*["']?[^"'\s,;)]+/gi,"[redacted credential]").replace(/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{16,}\b/g,"[redacted token]").replace(/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,"[redacted token]").replace(/\bsk-[A-Za-z0-9_-]{20,}\b/g,"[redacted token]").replace(/\bhttps?:\/\/\S+/gi,"[redacted link]").replace(new RegExp(`\\b[A-Za-z0-9_-]{${ma},}\\b`,"g"),"[redacted token]")}function Co(n){return/\b[A-Za-z0-9_-]*(?:api[_-]?key|token|secret|password|passwd|pwd|credential|credentials|authorization|auth)[A-Za-z0-9_-]*\b\s*[:=]\s*["']?[^"'\s,;)]+/i.test(n)||/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{16,}\b/.test(n)||/\bgithub_pat_[A-Za-z0-9_]{20,}\b/.test(n)||/\bsk-[A-Za-z0-9_-]{20,}\b/.test(n)||/\bhttps?:\/\/\S+/i.test(n)||new RegExp(`\\b[A-Za-z0-9_-]{${ma},}\\b`).test(n)}function re(n){return[n.startedAt,n.worktreeBranch??"unknown-branch",n.worktreePath??"unknown-worktree"].join(":")}var Un=class{constructor(e){this.deps=e;this.actions=new Fn({shouldRunWorktreeStrategy:e.shouldRunWorktreeStrategy,isAlreadyMerged:e.isAlreadyMerged,resolveWorktreeRepoDir:e.resolveWorktreeRepoDir,getWorktreeCompletionState:e.getWorktreeCompletionState,isPrAvailable:e.isPrAvailable??(()=>!0),resolveRepoPolicy:e.resolveRepoPolicy})}deps;actions;buildConflictResolverPrompt(e){return["Resolve the git rebase conflict for the auto-merge worktree and finish the rebase cleanly.","",`Original session: ${e.session.name} [${e.session.id}]`,`Repository root: ${e.repoDir}`,`Conflicted worktree: ${e.worktreePath}`,`Branch: ${e.branchName}`,`Base branch: ${e.baseBranch}`,"","Requirements:","- Work only inside the conflicted worktree.","- Inspect the current rebase state and resolve only the necessary conflict hunks.","- Make only minimal follow-up edits needed to keep the rebased branch correct.","- Continue the rebase until it completes successfully.","- Run relevant local verification before you finish.","- Do not broaden scope or start unrelated refactors.",`- Stop only when the branch is cleanly rebased onto ${e.baseBranch}.`,e.mergeError?"":void 0,e.mergeError?"Rebase failure details:":void 0,e.mergeError].filter(t=>typeof t=="string").join(`
194
+ `).map(o=>o.trim()).filter(Boolean).join(" ");if(!e)return;let t=e.match(/^[^.!?]+[.!?]/)?.[0]??e,r=Vn(t).replace(/\s+/g," ").trim();return r?xo(r,180):void 0}function qn(n){return n.replace(/^[-*•]\s+/,"").replace(/\s+/g," ").trim()}function xo(n,e){return n.length<=e?n:`${n.slice(0,Math.max(0,e-3)).trimEnd()}...`}function Vn(n){return n.replace(/\b[A-Za-z0-9_-]*(?:api[_-]?key|token|secret|password|passwd|pwd|credential|credentials|authorization|auth)[A-Za-z0-9_-]*\b\s*[:=]\s*["']?[^"'\s,;)]+/gi,"[redacted credential]").replace(/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{16,}\b/g,"[redacted token]").replace(/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,"[redacted token]").replace(/\bsk-[A-Za-z0-9_-]{20,}\b/g,"[redacted token]").replace(/\bhttps?:\/\/\S+/gi,"[redacted link]").replace(new RegExp(`\\b[A-Za-z0-9_-]{${ma},}\\b`,"g"),"[redacted token]")}function Co(n){return/\b[A-Za-z0-9_-]*(?:api[_-]?key|token|secret|password|passwd|pwd|credential|credentials|authorization|auth)[A-Za-z0-9_-]*\b\s*[:=]\s*["']?[^"'\s,;)]+/i.test(n)||/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{16,}\b/.test(n)||/\bgithub_pat_[A-Za-z0-9_]{20,}\b/.test(n)||/\bsk-[A-Za-z0-9_-]{20,}\b/.test(n)||/\bhttps?:\/\/\S+/i.test(n)||new RegExp(`\\b[A-Za-z0-9_-]{${ma},}\\b`).test(n)}function re(n){return[n.startedAt,n.worktreeBranch??"unknown-branch",n.worktreePath??"unknown-worktree"].join(":")}var Un=class{constructor(e){this.deps=e;this.actions=new Ln({shouldRunWorktreeStrategy:e.shouldRunWorktreeStrategy,isAlreadyMerged:e.isAlreadyMerged,resolveWorktreeRepoDir:e.resolveWorktreeRepoDir,getWorktreeCompletionState:e.getWorktreeCompletionState,isPrAvailable:e.isPrAvailable??(()=>!0),resolveRepoPolicy:e.resolveRepoPolicy})}deps;actions;buildConflictResolverPrompt(e){return["Resolve the git rebase conflict for the auto-merge worktree and finish the rebase cleanly.","",`Original session: ${e.session.name} [${e.session.id}]`,`Repository root: ${e.repoDir}`,`Conflicted worktree: ${e.worktreePath}`,`Branch: ${e.branchName}`,`Base branch: ${e.baseBranch}`,"","Requirements:","- Work only inside the conflicted worktree.","- Inspect the current rebase state and resolve only the necessary conflict hunks.","- Make only minimal follow-up edits needed to keep the rebased branch correct.","- Continue the rebase until it completes successfully.","- Run relevant local verification before you finish.","- Do not broaden scope or start unrelated refactors.",`- Stop only when the branch is cleanly rebased onto ${e.baseBranch}.`,e.mergeError?"":void 0,e.mergeError?"Rebase failure details:":void 0,e.mergeError].filter(t=>typeof t=="string").join(`
195
195
  `)}notifyAutoMergeConflictEscalation(e,t,r,o,i=[]){this.deps.dispatchSessionNotification(e,{label:"worktree-merge-conflict-escalated",idempotencyKey:`worktree-merge-conflict-escalated:${e.id}:${t}:${re(e)}`,userMessage:[`⚠️ [${e.name}] Auto-merge could not finish after one conflict-resolution attempt.`,`Branch \`${t}\` was preserved for manual follow-up.`,"",r,...i.map(s=>`⚠️ ${s}`)].join(`
196
- `),buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,o,{},[[this.deps.makeOpenPrButton(e.id)]])})}updatePersistedSessionFor(e,t){for(let r of z(e))this.deps.updatePersistedSession(r,t)}markPendingDecision(e,t={}){this.updatePersistedSessionFor(e,$t(e,t))}markAutoMergeConflictResolving(e,t,r){this.updatePersistedSessionFor(e,Zo(e,t,r,{notes:[`resolver_session:${t}`]}))}markMerged(e){this.updatePersistedSessionFor(e,Et(e,{clearResolverSessionId:!0}))}markReleased(e,t=[]){let r=new Date().toISOString();this.updatePersistedSessionFor(e,{lifecycle:"terminal",worktreeState:"released",pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0,worktreeLifecycle:{state:"released",updatedAt:r,resolvedAt:r,resolutionSource:"lifecycle_resolver",baseBranch:e.worktreeBaseBranch,targetRepo:e.worktreePrTargetRepo,pushRemote:e.worktreePushRemote,notes:t}})}async handleWorktreeStrategy(e){let t=await this.actions.plan(e);if(t.kind==="skip")return t.result;if(t.kind==="notify")return this.deps.dispatchSessionNotification(e,{label:t.label,idempotencyKey:["worktree-action",e.id,t.label,e.startedAt,e.worktreeBranch??"unknown",e.worktreePath??"unknown"].join(":"),userMessage:t.message}),{notificationSent:!0,worktreeRemoved:!1};if(t.kind==="dirty-uncommitted")return this.handleDirtyUncommittedCompletion(e,t.worktreePath,t.branchName,t.baseBranch);if(t.kind==="no-change")return this.handleNoChange(e,t.repoDir,t.worktreePath,t.branchName,t.nativeBackendWorktree);if(t.kind==="merged"){let r=t.nativeBackendWorktree?!0:B(t.repoDir,t.worktreePath);return H(t.repoDir,t.branchName),this.markMerged(e),{notificationSent:!1,worktreeRemoved:r}}if(t.kind==="released"){let r=t.nativeBackendWorktree?!0:B(t.repoDir,t.worktreePath);return H(t.repoDir,t.branchName),this.markReleased(e,t.reasons),{notificationSent:!1,worktreeRemoved:r}}return t.policyBlocked?this.shouldUpdateExistingOpenPr(e,t.repoDir,t.branchName,t.baseBranch)?this.handleAutoPrStrategy(e,t.repoDir,t.worktreePath,t.branchName,t.baseBranch,{merge:!1,pr:!0}):(this.markPendingDecision(e,{notes:t.policyReason?[t.policyReason]:void 0}),this.deps.dispatchSessionNotification(e,{label:"worktree-policy-blocked",idempotencyKey:`worktree-policy-blocked:${e.id}:${t.branchName}:${t.baseBranch}:${re(e)}`,userMessage:`⚠️ [${e.name}] ${t.policyReason??"Repo policy blocked automatic follow-through."}`,buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,t.allowedActions,{allowDelegate:!0})}),{notificationSent:!0,worktreeRemoved:!1}):t.strategy==="ask"?this.shouldUpdateExistingOpenPr(e,t.repoDir,t.branchName,t.baseBranch)?this.handleAutoPrStrategy(e,t.repoDir,t.worktreePath,t.branchName,t.baseBranch,t.allowedActions):await this.handleAskStrategy(e,t.branchName,t.baseBranch,t.diffSummary,t.allowedActions,t.policyReason):t.strategy==="delegate"?this.handleDelegateStrategy(e,t.branchName,t.baseBranch,t.diffSummary,t.allowedActions,t.policyReason):t.strategy==="auto-merge"?{notificationSent:!0,worktreeRemoved:await this.handleAutoMergeStrategy(e,t.repoDir,t.worktreePath,t.branchName,t.baseBranch,t.diffSummary,t.sessionRef,t.allowedActions)}:t.strategy==="auto-pr"?this.handleAutoPrStrategy(e,t.repoDir,t.worktreePath,t.branchName,t.baseBranch,t.allowedActions):{notificationSent:!1,worktreeRemoved:!1}}async handleNoChange(e,t,r,o,i=F(e)){if(this.hasCurrentlyOpenPrForBranch(e,t,o)){let l=new Date().toISOString();return this.updatePersistedSessionFor(e,{lifecycle:"terminal",worktreeState:"pr_open",pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0,worktreeLifecycle:{state:"pr_open",updatedAt:l,resolutionSource:e.worktreeLifecycle?.resolutionSource??"agent_pr",baseBranch:e.worktreeBaseBranch,targetRepo:e.worktreePrTargetRepo,pushRemote:e.worktreePushRemote,notes:["no_new_worktree_commits_preserved_open_pr"]}}),this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildNoChangeNotification({session:e,nativeBackendWorktree:i,cleanupSucceeded:!0,worktreePath:r,worktreeBranch:o,preview:this.deps.getOutputPreview(e),originThreadLine:this.deps.originThreadLine(e),preservedSummary:"existing PR worktree preserved until merge"})),{notificationSent:!0,worktreeRemoved:!1}}let s=this.getDeliveredRemoteOutcome(e),a=i?!0:B(t,r);return a?(e.worktreePath=void 0,this.updatePersistedSessionFor(e,{worktreePath:void 0,worktreeDisposition:"no-change-cleaned",worktreeState:"none",worktreeLifecycle:{state:"no_change",updatedAt:new Date().toISOString(),resolvedAt:new Date().toISOString(),resolutionSource:"strategy_no_change",baseBranch:e.worktreeBaseBranch,targetRepo:e.worktreePrTargetRepo,pushRemote:e.worktreePushRemote}}),this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildNoChangeNotification({session:e,nativeBackendWorktree:i,cleanupSucceeded:!0,worktreePath:r,worktreeBranch:o,preview:this.deps.getOutputPreview(e),originThreadLine:this.deps.originThreadLine(e),remoteOutcome:s}))):this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildNoChangeNotification({session:e,nativeBackendWorktree:i,cleanupSucceeded:!1,worktreePath:r,worktreeBranch:o,preview:this.deps.getOutputPreview(e),originThreadLine:this.deps.originThreadLine(e),remoteOutcome:s})),{notificationSent:!0,worktreeRemoved:a}}hasCurrentlyOpenPrForBranch(e,t,r){return this.deps.hasOpenPrForBranch?.(t,r,e.worktreePrTargetRepo)===!0}getDeliveredRemoteOutcome(e){return z(e).map(r=>this.deps.getPersistedSession?.(r)).find(r=>r?.worktreeRemoteOutcome==="pr-updated"||r?.worktreeRemoteOutcome==="pr-opened")?.worktreeRemoteOutcome}resolveExistingTargetPr(e,t,r,o){let i=Ar(t,e.worktreePrTargetRepo);if(e.worktreePrUrl){let l=this.getPrStatusForUrl(t,e.worktreePrUrl,i);if(l.exists&&l.baseRefName===o)return l}let s=e.worktreeParentBranch;if(!s||oe(t)!==s||s===r||s===o)return;let a=this.deps.getPrStatusForBranch?.(t,s,i)??nt(t,s,i);return a.exists&&a.state==="open"&&a.headRefName===s&&(!a.baseRefName||a.baseRefName===o)?a:void 0}shouldUpdateExistingOpenPr(e,t,r,o){return e.worktreeStrategy==="auto-pr"&&(this.hasCurrentlyOpenPrForBranch(e,t,r)||this.resolveExistingTargetPr(e,t,r,o)?.state==="open")}async handleAskStrategy(e,t,r,o,i,s){let a=await ga({sessionName:e.name,prompt:e.prompt,diffSummary:o,outputPreview:this.deps.getOutputPreview(e,4e3),provider:this.deps.worktreeSummaryProvider});return this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildAskNotification({session:e,branchName:t,baseBranch:r,diffSummary:o,summaryLines:a.lines,policyReason:s,buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,i)})),this.markPendingDecision(e),{notificationSent:!0,worktreeRemoved:!1}}handleDelegateStrategy(e,t,r,o,i,s){return this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildDelegateNotification({session:e,branchName:t,baseBranch:r,diffSummary:o,policyReason:s,allowedActions:i,originThreadLine:this.deps.originThreadLine(e)})),this.markPendingDecision(e),{notificationSent:!0,worktreeRemoved:!1}}getPolicyAwareWorktreeDecisionButtons(e,t,r={},o){if(this.deps.getPolicyAwareWorktreeDecisionButtons)return this.deps.getPolicyAwareWorktreeDecisionButtons(e,r,t);if(o&&t.pr)return o;if(!(o&&!t.pr&&!t.merge))return this.deps.getWorktreeDecisionButtons(e)}handleDirtyUncommittedCompletion(e,t,r,o){this.markPendingDecision(e,{notes:["dirty_uncommitted_completion"]});let i=Ze(t),s=i.slice(0,20).map(l=>`- ${l}`),a=i.length>20?[`- ...and ${i.length-20} more`]:[];return this.deps.dispatchSessionNotification(e,{label:"worktree-dirty-uncommitted",idempotencyKey:`worktree-dirty-uncommitted:${e.id}:${r}:${o}:${re(e)}`,userMessage:[`⚠️ [${e.name}] Session completed with uncommitted worktree changes.`,"",`Branch \`${r}\` has no commits ahead of \`${o}\`, so merge/PR follow-through is blocked until the worktree is fixed.`,`Worktree: ${t}`,"",...s.length>0?["Dirty entries:",...s,...a,""]:[],"Resume the session or inspect the worktree, then commit real task changes or clean temporary files. Discard only if these local changes should be permanently removed."].join(`
197
- `)}),{notificationSent:!0,worktreeRemoved:!1}}handleAutoMergeSuccess(e,t,r,o,i,s,a){let l=F(e),d=l||!Jo(r)||B(t,r);d&&(e.worktreePath=void 0,this.updatePersistedSessionFor(e,{worktreePath:void 0}),l||H(t,o)),this.markMerged(e);let u=Dt({kind:"merge",branch:o,base:i,filesChanged:s.filesChanged,insertions:s.insertions,deletions:s.deletions}),f=u;a.stashPopConflict?f+=`
196
+ `),buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,o,{},[[this.deps.makeOpenPrButton(e.id)]])})}updatePersistedSessionFor(e,t){for(let r of z(e))this.deps.updatePersistedSession(r,t)}markPendingDecision(e,t={}){this.updatePersistedSessionFor(e,Et(e,t))}markAutoMergeConflictResolving(e,t,r){this.updatePersistedSessionFor(e,Zo(e,t,r,{notes:[`resolver_session:${t}`]}))}markMerged(e){this.updatePersistedSessionFor(e,Nt(e,{clearResolverSessionId:!0}))}markReleased(e,t=[]){let r=new Date().toISOString();this.updatePersistedSessionFor(e,{lifecycle:"terminal",worktreeState:"released",pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0,worktreeLifecycle:{state:"released",updatedAt:r,resolvedAt:r,resolutionSource:"lifecycle_resolver",baseBranch:e.worktreeBaseBranch,targetRepo:e.worktreePrTargetRepo,pushRemote:e.worktreePushRemote,notes:t}})}async handleWorktreeStrategy(e){let t=await this.actions.plan(e);if(t.kind==="skip")return t.result;if(t.kind==="notify")return this.deps.dispatchSessionNotification(e,{label:t.label,idempotencyKey:["worktree-action",e.id,t.label,e.startedAt,e.worktreeBranch??"unknown",e.worktreePath??"unknown"].join(":"),userMessage:t.message}),{notificationSent:!0,worktreeRemoved:!1};if(t.kind==="dirty-uncommitted")return this.handleDirtyUncommittedCompletion(e,t.worktreePath,t.branchName,t.baseBranch);if(t.kind==="no-change")return this.handleNoChange(e,t.repoDir,t.worktreePath,t.branchName,t.nativeBackendWorktree);if(t.kind==="merged"){let r=t.nativeBackendWorktree?!0:B(t.repoDir,t.worktreePath);return H(t.repoDir,t.branchName),this.markMerged(e),{notificationSent:!1,worktreeRemoved:r}}if(t.kind==="released"){let r=t.nativeBackendWorktree?!0:B(t.repoDir,t.worktreePath);return H(t.repoDir,t.branchName),this.markReleased(e,t.reasons),{notificationSent:!1,worktreeRemoved:r}}return t.policyBlocked?this.shouldUpdateExistingOpenPr(e,t.repoDir,t.branchName,t.baseBranch)?this.handleAutoPrStrategy(e,t.repoDir,t.worktreePath,t.branchName,t.baseBranch,{merge:!1,pr:!0}):(this.markPendingDecision(e,{notes:t.policyReason?[t.policyReason]:void 0}),this.deps.dispatchSessionNotification(e,{label:"worktree-policy-blocked",idempotencyKey:`worktree-policy-blocked:${e.id}:${t.branchName}:${t.baseBranch}:${re(e)}`,userMessage:`⚠️ [${e.name}] ${t.policyReason??"Repo policy blocked automatic follow-through."}`,buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,t.allowedActions,{allowDelegate:!0})}),{notificationSent:!0,worktreeRemoved:!1}):t.strategy==="ask"?this.shouldUpdateExistingOpenPr(e,t.repoDir,t.branchName,t.baseBranch)?this.handleAutoPrStrategy(e,t.repoDir,t.worktreePath,t.branchName,t.baseBranch,t.allowedActions):await this.handleAskStrategy(e,t.branchName,t.baseBranch,t.diffSummary,t.allowedActions,t.policyReason):t.strategy==="delegate"?this.handleDelegateStrategy(e,t.branchName,t.baseBranch,t.diffSummary,t.allowedActions,t.policyReason):t.strategy==="auto-merge"?{notificationSent:!0,worktreeRemoved:await this.handleAutoMergeStrategy(e,t.repoDir,t.worktreePath,t.branchName,t.baseBranch,t.diffSummary,t.sessionRef,t.allowedActions)}:t.strategy==="auto-pr"?this.handleAutoPrStrategy(e,t.repoDir,t.worktreePath,t.branchName,t.baseBranch,t.allowedActions):{notificationSent:!1,worktreeRemoved:!1}}async handleNoChange(e,t,r,o,i=L(e)){if(this.hasCurrentlyOpenPrForBranch(e,t,o)){let l=new Date().toISOString();return this.updatePersistedSessionFor(e,{lifecycle:"terminal",worktreeState:"pr_open",pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0,worktreeLifecycle:{state:"pr_open",updatedAt:l,resolutionSource:e.worktreeLifecycle?.resolutionSource??"agent_pr",baseBranch:e.worktreeBaseBranch,targetRepo:e.worktreePrTargetRepo,pushRemote:e.worktreePushRemote,notes:["no_new_worktree_commits_preserved_open_pr"]}}),this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildNoChangeNotification({session:e,nativeBackendWorktree:i,cleanupSucceeded:!0,worktreePath:r,worktreeBranch:o,preview:this.deps.getOutputPreview(e),originThreadLine:this.deps.originThreadLine(e),preservedSummary:"existing PR worktree preserved until merge"})),{notificationSent:!0,worktreeRemoved:!1}}let s=this.getDeliveredRemoteOutcome(e),a=i?!0:B(t,r);return a?(e.worktreePath=void 0,this.updatePersistedSessionFor(e,{worktreePath:void 0,worktreeDisposition:"no-change-cleaned",worktreeState:"none",worktreeLifecycle:{state:"no_change",updatedAt:new Date().toISOString(),resolvedAt:new Date().toISOString(),resolutionSource:"strategy_no_change",baseBranch:e.worktreeBaseBranch,targetRepo:e.worktreePrTargetRepo,pushRemote:e.worktreePushRemote}}),this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildNoChangeNotification({session:e,nativeBackendWorktree:i,cleanupSucceeded:!0,worktreePath:r,worktreeBranch:o,preview:this.deps.getOutputPreview(e),originThreadLine:this.deps.originThreadLine(e),remoteOutcome:s}))):this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildNoChangeNotification({session:e,nativeBackendWorktree:i,cleanupSucceeded:!1,worktreePath:r,worktreeBranch:o,preview:this.deps.getOutputPreview(e),originThreadLine:this.deps.originThreadLine(e),remoteOutcome:s})),{notificationSent:!0,worktreeRemoved:a}}hasCurrentlyOpenPrForBranch(e,t,r){return this.deps.hasOpenPrForBranch?.(t,r,e.worktreePrTargetRepo)===!0}getDeliveredRemoteOutcome(e){return z(e).map(r=>this.deps.getPersistedSession?.(r)).find(r=>r?.worktreeRemoteOutcome==="pr-updated"||r?.worktreeRemoteOutcome==="pr-opened")?.worktreeRemoteOutcome}resolveExistingTargetPr(e,t,r,o){let i=Ar(t,e.worktreePrTargetRepo);if(e.worktreePrUrl){let l=this.getPrStatusForUrl(t,e.worktreePrUrl,i);if(l.exists&&l.baseRefName===o)return l}let s=e.worktreeParentBranch;if(!s||oe(t)!==s||s===r||s===o)return;let a=this.deps.getPrStatusForBranch?.(t,s,i)??nt(t,s,i);return a.exists&&a.state==="open"&&a.headRefName===s&&(!a.baseRefName||a.baseRefName===o)?a:void 0}shouldUpdateExistingOpenPr(e,t,r,o){return e.worktreeStrategy==="auto-pr"&&(this.hasCurrentlyOpenPrForBranch(e,t,r)||this.resolveExistingTargetPr(e,t,r,o)?.state==="open")}async handleAskStrategy(e,t,r,o,i,s){let a=await ga({sessionName:e.name,prompt:e.prompt,diffSummary:o,outputPreview:this.deps.getOutputPreview(e,4e3),provider:this.deps.worktreeSummaryProvider});return this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildAskNotification({session:e,branchName:t,baseBranch:r,diffSummary:o,summaryLines:a.lines,policyReason:s,buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,i)})),this.markPendingDecision(e),{notificationSent:!0,worktreeRemoved:!1}}handleDelegateStrategy(e,t,r,o,i,s){return this.deps.dispatchSessionNotification(e,this.deps.worktreeMessages.buildDelegateNotification({session:e,branchName:t,baseBranch:r,diffSummary:o,policyReason:s,allowedActions:i,originThreadLine:this.deps.originThreadLine(e)})),this.markPendingDecision(e),{notificationSent:!0,worktreeRemoved:!1}}getPolicyAwareWorktreeDecisionButtons(e,t,r={},o){if(this.deps.getPolicyAwareWorktreeDecisionButtons)return this.deps.getPolicyAwareWorktreeDecisionButtons(e,r,t);if(o&&t.pr)return o;if(!(o&&!t.pr&&!t.merge))return this.deps.getWorktreeDecisionButtons(e)}handleDirtyUncommittedCompletion(e,t,r,o){this.markPendingDecision(e,{notes:["dirty_uncommitted_completion"]});let i=Ze(t),s=i.slice(0,20).map(l=>`- ${l}`),a=i.length>20?[`- ...and ${i.length-20} more`]:[];return this.deps.dispatchSessionNotification(e,{label:"worktree-dirty-uncommitted",idempotencyKey:`worktree-dirty-uncommitted:${e.id}:${r}:${o}:${re(e)}`,userMessage:[`⚠️ [${e.name}] Session completed with uncommitted worktree changes.`,"",`Branch \`${r}\` has no commits ahead of \`${o}\`, so merge/PR follow-through is blocked until the worktree is fixed.`,`Worktree: ${t}`,"",...s.length>0?["Dirty entries:",...s,...a,""]:[],"Resume the session or inspect the worktree, then commit real task changes or clean temporary files. Discard only if these local changes should be permanently removed."].join(`
197
+ `)}),{notificationSent:!0,worktreeRemoved:!1}}handleAutoMergeSuccess(e,t,r,o,i,s,a){let l=L(e),d=l||!Jo(r)||B(t,r);d&&(e.worktreePath=void 0,this.updatePersistedSessionFor(e,{worktreePath:void 0}),l||H(t,o)),this.markMerged(e);let u=$t({kind:"merge",branch:o,base:i,filesChanged:s.filesChanged,insertions:s.insertions,deletions:s.deletions}),f=u;a.stashPopConflict?f+=`
198
198
  ⚠️ Pre-merge stash pop conflicted — run \`git stash show ${a.stashRef??"stash@{0}"}\` in ${t} to review stashed changes.`:a.stashed&&(f+=`
199
- (Pre-existing changes on ${i} were auto-stashed and restored.)`),f=ie(f,a);let h=tt(a),k=[a.fastForward?"Merge type: fast-forward.":"Merge type: merge commit.",`Auto-merge landed ${o} into ${i}.`,"Local worktree branch cleanup was requested.",...a.stashPopConflict?[`Pre-merge stash pop conflicted; run git stash show ${a.stashRef??"stash@{0}"} in ${t} to review stashed changes.`]:[],...!a.stashPopConflict&&a.stashed?[`Pre-existing changes on ${i} were auto-stashed and restored.`]:[],...h];return this.deps.dispatchSessionNotification(e,{label:"worktree-merge-success",idempotencyKey:`worktree-merge-success:${e.id}:${o}:${i}:${re(e)}`,userMessage:f,notifyUser:"always",completionSummary:{required:!0,producer:"worktree",outcomeKey:`worktree-merge:${e.id}:${o}:${i}:${re(e)}`},completionWakeSummaryRequired:!0,completionWakeOutcomeKey:`worktree-merge:${e.id}:${o}:${i}:${re(e)}`,deferConditionalWakeUntilNextTick:!0,wakeMessageOnNotifySuccess:Ge({sessionId:e.id,sessionName:e.name,outcomeLine:u,originThreadLine:this.deps.originThreadLine(e),detailLines:k,canonicalStatusDelivered:!0}),wakeMessageOnNotifyFailed:Ge({sessionId:e.id,sessionName:e.name,outcomeLine:u,originThreadLine:this.deps.originThreadLine(e),detailLines:k,canonicalStatusDelivered:!1})}),d}async handleInitialAutoMergeConflict(e,t,r,o,i,s,a,l){let d=l?tt(l):[],u=e.autoMergeConflictResolutionAttemptCount??0;if(u>=1){this.markPendingDecision(e,{notes:["auto_merge_conflict_retry_exhausted"],clearResolverSessionId:!0}),this.notifyAutoMergeConflictEscalation(e,o,s.pr?`The rebased branch still conflicts with \`${i}\`. Open a PR or resolve manually in ${r}.`:`The rebased branch still conflicts with \`${i}\`. Resolve manually in ${r}.`,s,d);return}let f=this.buildConflictResolverPrompt({session:e,repoDir:t,worktreePath:r,branchName:o,baseBranch:i,mergeError:a});try{let h=await this.deps.spawnConflictResolver({session:e,repoDir:t,worktreePath:r,branchName:o,baseBranch:i,prompt:f});this.markAutoMergeConflictResolving(e,h.id,u+1),this.deps.dispatchSessionNotification(e,{label:"worktree-merge-conflict-resolving",idempotencyKey:`worktree-merge-conflict-resolving:${e.id}:${o}:${h.id}`,userMessage:[`⚠️ [${e.name}] Auto-merge hit a rebase conflict. Started resolver session ${h.name} and will retry automatically if it succeeds.`,...d.map(k=>`⚠️ ${k}`)].join(`
200
- `)})}catch(h){this.markPendingDecision(e,{notes:["auto_merge_conflict_resolver_spawn_failed"]}),this.deps.dispatchSessionNotification(e,{label:"worktree-merge-conflict-spawn-failed",idempotencyKey:`worktree-merge-conflict-spawn-failed:${e.id}:${o}:${re(e)}`,userMessage:[`❌ [${e.name}] Auto-merge hit a rebase conflict and failed to start the resolver: ${h instanceof Error?h.message:String(h)}`,...d.map(k=>`⚠️ ${k}`)].join(`
199
+ (Pre-existing changes on ${i} were auto-stashed and restored.)`),f=ie(f,a);let g=tt(a),k=[a.fastForward?"Merge type: fast-forward.":"Merge type: merge commit.",`Auto-merge landed ${o} into ${i}.`,"Local worktree branch cleanup was requested.",...a.stashPopConflict?[`Pre-merge stash pop conflicted; run git stash show ${a.stashRef??"stash@{0}"} in ${t} to review stashed changes.`]:[],...!a.stashPopConflict&&a.stashed?[`Pre-existing changes on ${i} were auto-stashed and restored.`]:[],...g];return this.deps.dispatchSessionNotification(e,{label:"worktree-merge-success",idempotencyKey:`worktree-merge-success:${e.id}:${o}:${i}:${re(e)}`,userMessage:f,notifyUser:"always",completionSummary:{required:!0,producer:"worktree",outcomeKey:`worktree-merge:${e.id}:${o}:${i}:${re(e)}`},completionWakeSummaryRequired:!0,completionWakeOutcomeKey:`worktree-merge:${e.id}:${o}:${i}:${re(e)}`,deferConditionalWakeUntilNextTick:!0,wakeMessageOnNotifySuccess:Ge({sessionId:e.id,sessionName:e.name,outcomeLine:u,originThreadLine:this.deps.originThreadLine(e),detailLines:k,canonicalStatusDelivered:!0}),wakeMessageOnNotifyFailed:Ge({sessionId:e.id,sessionName:e.name,outcomeLine:u,originThreadLine:this.deps.originThreadLine(e),detailLines:k,canonicalStatusDelivered:!1})}),d}async handleInitialAutoMergeConflict(e,t,r,o,i,s,a,l){let d=l?tt(l):[],u=e.autoMergeConflictResolutionAttemptCount??0;if(u>=1){this.markPendingDecision(e,{notes:["auto_merge_conflict_retry_exhausted"],clearResolverSessionId:!0}),this.notifyAutoMergeConflictEscalation(e,o,s.pr?`The rebased branch still conflicts with \`${i}\`. Open a PR or resolve manually in ${r}.`:`The rebased branch still conflicts with \`${i}\`. Resolve manually in ${r}.`,s,d);return}let f=this.buildConflictResolverPrompt({session:e,repoDir:t,worktreePath:r,branchName:o,baseBranch:i,mergeError:a});try{let g=await this.deps.spawnConflictResolver({session:e,repoDir:t,worktreePath:r,branchName:o,baseBranch:i,prompt:f});this.markAutoMergeConflictResolving(e,g.id,u+1),this.deps.dispatchSessionNotification(e,{label:"worktree-merge-conflict-resolving",idempotencyKey:`worktree-merge-conflict-resolving:${e.id}:${o}:${g.id}`,userMessage:[`⚠️ [${e.name}] Auto-merge hit a rebase conflict. Started resolver session ${g.name} and will retry automatically if it succeeds.`,...d.map(k=>`⚠️ ${k}`)].join(`
200
+ `)})}catch(g){this.markPendingDecision(e,{notes:["auto_merge_conflict_resolver_spawn_failed"]}),this.deps.dispatchSessionNotification(e,{label:"worktree-merge-conflict-spawn-failed",idempotencyKey:`worktree-merge-conflict-spawn-failed:${e.id}:${o}:${re(e)}`,userMessage:[`❌ [${e.name}] Auto-merge hit a rebase conflict and failed to start the resolver: ${g instanceof Error?g.message:String(g)}`,...d.map(k=>`⚠️ ${k}`)].join(`
201
201
  `),buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,s,{},[[this.deps.makeOpenPrButton(e.id)]])})}}handleAutoMergeRetryFailure(e,t,r,o,i){this.markPendingDecision(e,{notes:["auto_merge_conflict_retry_failed"],clearResolverSessionId:!0}),this.deps.dispatchSessionNotification(e,{label:"worktree-merge-error",idempotencyKey:`worktree-merge-error:${e.id}:${t}:${re(e)}`,userMessage:[o,"","Auto-merge retry did not complete after conflict resolution.",`Branch \`${t}\` was preserved for manual follow-up in ${r}.`].join(`
202
- `),buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,i,{},[[this.deps.makeOpenPrButton(e.id)]])})}async handleAutoMergeStrategy(e,t,r,o,i,s,a=D(e)??e.harnessSessionId,l={merge:!0,pr:!0}){if(this.deps.isAlreadyMerged(a)||e.autoMergeResolverSessionId)return!1;let d=!1;return await this.deps.enqueueMerge(t,async()=>{if(this.deps.isAlreadyMerged(a))return;let u=this.deps.mergeBranch(t,o,i,"merge",r);if(u.success){d=this.handleAutoMergeSuccess(e,t,r,o,i,s,u);return}if(u.rebaseConflict){await this.handleInitialAutoMergeConflict(e,t,r,o,i,l,u.error,u);return}let f=ie(u.dirtyError?`❌ [${e.name}] Merge blocked: ${u.error}`:`❌ [${e.name}] Merge failed: ${u.error??"unknown error"}`,u);if(e.worktreeState==="merge_conflict_resolving"||e.worktreeLifecycle?.state==="merge_conflict_resolving"){this.handleAutoMergeRetryFailure(e,o,r,f,l);return}this.deps.dispatchSessionNotification(e,{label:"worktree-merge-error",idempotencyKey:`worktree-merge-error:${e.id}:${o}:${re(e)}`,userMessage:f})},()=>{this.deps.dispatchSessionNotification(e,{label:"worktree-merge-queued",idempotencyKey:`worktree-merge-queued:${e.id}:${o}:${re(e)}`,userMessage:`🕐 [${e.name}] Merge queued — another merge for this repo is in progress. Will notify when complete.`})}),d}async handleAutoPrStrategy(e,t,r,o,i,s={merge:!0,pr:!0}){let a=this.releaseIfRepresentedByTargetPrBranch(e,t,r,o,i);if(a)return a;if(this.updatePersistedSessionFor(e,{lifecycle:"terminal",worktreeState:"pr_in_progress"}),!(await this.deps.runAutoPr(e,i)).success){let d=this.releaseIfRepresentedByTargetPrBranch(e,t,r,o,i);if(d)return d;this.markPendingDecision(e),this.deps.dispatchSessionNotification(e,{label:"worktree-auto-pr-failed",idempotencyKey:`worktree-auto-pr-failed:${e.id}:${i}:${re(e)}`,userMessage:`⚠️ [${e.name}] Auto-PR did not complete. The worktree is preserved for an explicit merge or PR decision.`,buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,s)})}return{notificationSent:!0,worktreeRemoved:!1}}getPrStatusForUrl(e,t,r){return this.deps.getPrStatusForUrl?.(e,t,r)??_t(e,t,r)}releaseIfRepresentedByTargetPrBranch(e,t,r,o,i){if(Ze(r).length>0)return;let s=this.resolveExistingTargetPr(e,t,o,i),a=s?.headRefName;if(!a||a===o||a===i)return;let l=this.deps.fetchRemoteBranch?this.deps.fetchRemoteBranch(t,a):Qo(t,a);if(!l||!!!((s?.state==="open"||s?.state==="merged")&&s?.baseRefName===i&&xt(t,o,l)))return;let u=F(e)?!0:B(t,r);return u?(e.worktreePath=void 0,e.worktreePrUrl=s.url,e.worktreePrNumber=s.number,e.worktreePrTargetRepo=Ar(t,e.worktreePrTargetRepo),this.updatePersistedSessionFor(e,{worktreePath:void 0,worktreePrUrl:s.url,worktreePrNumber:s.number,worktreePrTargetRepo:e.worktreePrTargetRepo,worktreeRemoteOutcome:"pr-updated"}),H(t,o),this.markReleased(e,[`released_by_branch:${a}`]),{notificationSent:!1,worktreeRemoved:u}):(this.markPendingDecision(e,{notes:[`represented_by_branch:${a}`,"represented_worktree_cleanup_failed"]}),{notificationSent:!1,worktreeRemoved:!1})}};import{existsSync as sm,statSync as am,writeFileSync as lm}from"fs";import{randomUUID as wc}from"crypto";function ha(n){return n==="plan-approve"||n==="plan-request-changes"||n==="plan-reject"}var Gn=class{constructor(e,t){this.onChange=e;this.retentionMs=t}onChange;retentionMs;tokens=new Map;afterChange;replaceAll(e){this.tokens.clear();for(let t of e)this.tokens.set(t.id,t)}clear(){this.tokens.clear(),this.notifyChanged()}listForPersistence(){return[...this.tokens.values()]}createActionToken(e,t,r={}){let o={id:wc(),sessionId:e,kind:t,createdAt:Date.now(),...r};return this.tokens.set(o.id,o),this.notifyChanged(),o}getActionToken(e){let t=this.tokens.get(e);if(t){if(t.expiresAt!=null&&t.expiresAt<=Date.now()){this.tokens.delete(e),this.notifyChanged();return}return t}}listActiveActionTokens(e){let t=[];for(let r of[...this.tokens.keys()]){let o=this.getActionToken(r);!o||o.consumedAt!=null||e&&o.kind!==e||t.push(o)}return t}consumeActionToken(e){let t=this.getActionToken(e);if(!(!t||t.consumedAt!=null))return t.consumedAt=Date.now(),this.notifyChanged(),t}consumeQuestionAnswerTokens(e,t,r){let o=[],i=Date.now();for(let s of this.tokens.values())s.sessionId!==e||s.kind!=="question-answer"||s.pendingInputRequestId!==t||r!=null&&s.pendingInputQuestionId!==r||s.consumedAt!=null||(s.consumedAt=i,o.push(s));return o.length>0&&this.notifyChanged(),o}consumePlanDecisionTokens(e,t){let r=[],o=Date.now();for(let i of this.tokens.values())i.sessionId!==e||!ha(i.kind)||i.planDecisionVersion!==t||i.consumedAt!=null||(i.consumedAt=o,r.push(i));return r.length>0&&this.notifyChanged(),r}deleteActionTokensForSession(e){let t=!1;for(let[r,o]of this.tokens)o.sessionId===e&&(this.tokens.delete(r),t=!0);t&&this.notifyChanged()}deleteActionTokensForSessionByKind(e,t){let r=!1;for(let[o,i]of this.tokens)i.sessionId===e&&i.kind===t&&(this.tokens.delete(o),r=!0);r&&this.notifyChanged()}deletePlanDecisionTokensForSession(e,t){let r=!1;for(let[o,i]of this.tokens)i.sessionId!==e||!ha(i.kind)||t!=null&&i.planDecisionVersion===t||(this.tokens.delete(o),r=!0);r&&this.notifyChanged()}purgeExpiredActionTokens(e=Date.now()){let t=!1;for(let[r,o]of this.tokens){let i=o.expiresAt!=null&&o.expiresAt<=e,s=o.consumedAt!=null&&e-o.consumedAt>=this.retentionMs;(i||s)&&(this.tokens.delete(r),t=!0)}return t&&this.notifyChanged(),t}nextExpiryAt(){let e;for(let t of this.tokens.values()){let r=[t.expiresAt,t.consumedAt!=null?t.consumedAt+this.retentionMs:void 0].filter(o=>o!=null&&Number.isFinite(o));for(let o of r)(e==null||o<e)&&(e=o)}return e}setAfterChangeListener(e){this.afterChange=e}notifyChanged(){this.onChange(),this.afterChange?.()}};var jn=class{constructor(e){this.indexes=e}indexes;hasRecordedSession(e){return this.indexes.idIndex.has(e)}getLatestPersistedByName(e){let t,r=Number.NEGATIVE_INFINITY,o=Number.NEGATIVE_INFINITY,i=Number.NEGATIVE_INFINITY,s=0;for(let a of this.indexes.persisted.values()){if(a.name!==e){s++;continue}let l=a.createdAt??Number.NEGATIVE_INFINITY,d=a.completedAt??Number.NEGATIVE_INFINITY;(l>r||l===r&&d>o||l===r&&d===o&&s>i)&&(t=a,r=l,o=d,i=s),s++}return t}resolveBackendConversationId(e,t){if(t)return t;let r=this.indexes.idIndex.get(e);if(r){let s=this.indexes.persisted.get(r);return(s?C(s):void 0)??r}let o=this.getLatestPersistedByName(e);if(o)return C(o)??o.harnessSessionId;let i=this.indexes.backendIdIndex.get(e);if(i){let s=this.indexes.persisted.get(i);return(s?C(s):void 0)??i}if(this.indexes.persisted.has(e)){let s=this.indexes.persisted.get(e);return s?C(s)??e:e}if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e))return e}resolveHarnessSessionId(e,t){return this.resolveBackendConversationId(e,t)}getPersistedSession(e){let t=this.indexes.idIndex.get(e);if(t)return this.indexes.persisted.get(t);let r=this.getLatestPersistedByName(e);if(r)return r;let o=this.indexes.backendIdIndex.get(e);return o?this.indexes.persisted.get(o):this.indexes.persisted.get(e)}listPersistedSessions(){return[...this.indexes.persisted.values()].sort((e,t)=>(t.completedAt??0)-(e.completedAt??0))}};import{existsSync as Ta,mkdirSync as Yc,readFileSync as Jc,readdirSync as Xc,renameSync as xa,statSync as Ca,unlinkSync as Ma,writeFileSync as _a}from"fs";import{tmpdir as Zc}from"os";import{dirname as em,join as Da}from"path";import{homedir as bc}from"node:os";import{join as Rc}from"node:path";function zn(n){let e=n.OPENCLAW_HOME?.trim();if(e)return e;let t=n.HOME?.trim()||bc();return Rc(t,".openclaw")}var Hn=7,Ac=new Set(["running","completed","failed","killed"]),Ic=new Set(["queued","running","waiting","blocked","succeeded","failed","cancelled","lost"]);function ae(n){return!!n&&typeof n=="object"}function je(n,e=""){return typeof n=="string"&&n.trim().length>0?n:e}function v(n){return typeof n=="string"&&n.trim().length>0?n:void 0}function V(n){return typeof n=="number"&&Number.isFinite(n)?n:void 0}function Tc(n){if(!ae(n))return;let e=v(n.flowId),t=V(n.revision);if(!e||t===void 0)return;let r=typeof n.status=="string"&&Ic.has(n.status)?n.status:void 0;return{flowId:e,revision:t,...r?{status:r}:{}}}function ya(n){return typeof n=="string"&&ns.has(n)?n:void 0}function Mo(n){return n==="default"||n==="plan"||n==="bypassPermissions"?n:void 0}function xc(n){return n==="never"||n==="on-request"?"never":void 0}function Sa(n){return n==="approve"||n==="ask"||n==="delegate"?n:void 0}function Cc(n){if(n==="plan-mode"||n==="codex-first-turn-plan"||n==="soft-plan")return"plan-mode"}function ka(n){return typeof n=="string"&&Sn.has(n)?n:void 0}function _o(n){return typeof n=="string"&&ts.has(n)?n:void 0}function va(n){return n==="github"||n==="unsupported"?n:void 0}function Mc(n){return n==="stored"||n==="seeded"||n==="unknown"?n:void 0}function _c(n){return n==="user"||n==="idle-timeout"||n==="startup-timeout"||n==="shutdown"||n==="done"||n==="unknown"?n:void 0}function Pa(n){return n==="starting"||n==="active"||n==="awaiting_plan_decision"||n==="awaiting_user_input"||n==="awaiting_worktree_decision"||n==="suspended"||n==="terminal"?n:void 0}function Dc(n){return n==="not_required"||n==="pending"||n==="approved"||n==="changes_requested"||n==="rejected"?n:void 0}function $c(n){return n==="none"||n==="provisioned"||n==="pending_decision"||n==="merge_conflict_resolving"||n==="merge_in_progress"||n==="pr_in_progress"||n==="merged"||n==="released"||n==="pr_open"||n==="dismissed"||n==="cleanup_failed"?n:void 0}function Ec(n){return n==="none"||n==="provisioned"||n==="pending_decision"||n==="merge_conflict_resolving"||n==="pr_open"||n==="merged"||n==="released"||n==="dismissed"||n==="no_change"||n==="cleanup_failed"?n:void 0}function wa(n){return n==="live"||n==="stopped"?n:void 0}function Nc(n){if(!ae(n)||n.reason!=="persisted-running-without-runtime")return;let e=v(n.recoveredAt);if(!e||!Number.isFinite(Date.parse(e)))return;let t=n.normalizedStatus==="killed"?"killed":void 0;if(t)return{reason:"persisted-running-without-runtime",recoveredAt:e,rawStatus:v(n.rawStatus),rawLifecycle:v(n.rawLifecycle),rawRuntimeState:v(n.rawRuntimeState),rawResumable:typeof n.rawResumable=="boolean"?n.rawResumable:void 0,rawCompletedAt:V(n.rawCompletedAt),rawOutputPath:v(n.rawOutputPath),normalizedStatus:t,normalizedLifecycle:Pa(n.normalizedLifecycle),normalizedRuntimeState:wa(n.normalizedRuntimeState)}}function Oc(n){return{reason:"persisted-running-without-runtime",recoveredAt:new Date().toISOString(),rawStatus:v(n.status),rawLifecycle:v(n.lifecycle),rawRuntimeState:v(n.runtimeState),rawResumable:typeof n.resumable=="boolean"?n.resumable:void 0,rawCompletedAt:V(n.completedAt),rawOutputPath:v(n.outputPath),normalizedStatus:"killed",normalizedLifecycle:"suspended",normalizedRuntimeState:"stopped"}}function Wc(n){return n==="not_sent"||n==="sending"||n==="delivered"||n==="fallback_delivered"||n==="failed"?n:void 0}function Lc(n){return n==="direct-telegram"?"direct-message":n==="none"||n==="direct-message"||n==="wake-only"?n:void 0}function Fc(n){return n==="none"||n==="canonical_buttons"||n==="explicit_fallback_text"?n:void 0}function Bc(n){return n==="idle"||n==="notifying"||n==="wake_pending"||n==="failed"?n:void 0}function Kc(n){return n==="in_flight"||n==="delivered"?n:void 0}function qc(n){if(!Array.isArray(n))return;let e=n.map(t=>{if(!ae(t))return;let r=v(t.key),o=Kc(t.status),i=v(t.recordedAt);if(!(!r||!o||!i||!Number.isFinite(Date.parse(i))))return{key:r,status:o,recordedAt:i,label:v(t.label)}}).filter(t=>!!t);return e.length>0?e.slice(-64):void 0}function Vc(n){if(!Array.isArray(n))return;let e=n.map(t=>{if(!ae(t))return;let r=v(t.key),o=v(t.recordedAt);if(!r||!o||!Number.isFinite(Date.parse(o)))return;let i=Array.isArray(t.linkedKeys)?[...new Set(t.linkedKeys.map(v).filter(s=>!!(s&&s!==r)))]:void 0;return{key:r,linkedKeys:i&&i.length>0?i:void 0,recordedAt:o,label:v(t.label),skipReason:v(t.skipReason)}}).filter(t=>!!t);return e.length>0?e.slice(-1024):void 0}function Uc(n){return n==="awaiting_plan_output"||n==="awaiting_approval"||n==="approved_then_implemented"||n==="implemented_without_required_approval"||n==="not_plan_gated"?n:void 0}function Gc(n){return n==="plan-approve"||n==="plan-request-changes"||n==="plan-reject"||n==="plan-offer-start"||n==="plan-offer-dismiss"||n==="repo-policy-set"||n==="worktree-merge"||n==="worktree-create-pr"||n==="worktree-update-pr"||n==="worktree-view-pr"||n==="worktree-decide-later"||n==="worktree-dismiss"||n==="session-resume"||n==="session-restart"||n==="view-output"||n==="question-answer"?n:void 0}function ba(n){if(!ae(n))return;let e=v(n.provider),t=v(n.accountId),r=v(n.target),o=v(n.threadId),i=v(n.sessionKey);if(!(!e||!r))return{provider:e,accountId:t,target:r,threadId:o,sessionKey:i}}function jc(n,e,t){if(ae(n)){let r=v(n.kind),o=v(n.conversationId);if(o&&(r==="claude-code"||r==="codex-app-server"||r==="opencode-server"))return{kind:r,conversationId:o,runId:v(n.runId),worktreeId:v(n.worktreeId),worktreePath:v(n.worktreePath)}}if(e==="claude-code")return{kind:"claude-code",conversationId:t}}function zc(n){if(!ae(n))return;let e=Ec(n.state),t=v(n.updatedAt);if(!e||!t)return;let r=v(n.resolutionSource);return{state:e,updatedAt:t,resolvedAt:v(n.resolvedAt),resolutionSource:r==="agent_merge"||r==="agent_pr"||r==="strategy_no_change"||r==="lifecycle_resolver"||r==="dismiss"||r==="maintenance"?r:void 0,baseBranch:v(n.baseBranch),targetRepo:v(n.targetRepo),pushRemote:v(n.pushRemote),notes:Array.isArray(n.notes)?n.notes.filter(o=>typeof o=="string"&&o.length>0):void 0}}function Hc(n){let e=new Date(0).toISOString(),t=v(n.worktreeMergedAt)??v(n.worktreeDismissedAt)??v(n.pendingWorktreeDecisionSince)??e;if(n.worktreeMerged===!0||n.worktreeDisposition==="merged")return{state:"merged",updatedAt:t,resolvedAt:v(n.worktreeMergedAt)??t,resolutionSource:"agent_merge",baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.worktreeDisposition==="dismissed")return{state:"dismissed",updatedAt:t,resolvedAt:v(n.worktreeDismissedAt)??t,resolutionSource:"dismiss",baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.worktreeDisposition==="no-change-cleaned")return{state:"no_change",updatedAt:t,resolvedAt:t,resolutionSource:"strategy_no_change",baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.worktreeDisposition==="pr-opened"||n.worktreeState==="pr_open")return{state:"pr_open",updatedAt:t,baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.pendingWorktreeDecisionSince||n.worktreeState==="pending_decision")return{state:"pending_decision",updatedAt:t,baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.worktreeState==="merge_conflict_resolving")return{state:"merge_conflict_resolving",updatedAt:t,baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(v(n.worktreePath)||v(n.worktreeBranch))return{state:"provisioned",updatedAt:t,baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)}}function Qc(n){if(typeof n=="string"&&Ac.has(n))return n==="running"?"killed":n}function Ra(n){if(!ae(n))return;let e=je(n.harnessSessionId);if(!e)return;let t=Qc(n.status);if(!t)return;let r=n.status==="running",o=v(n.worktreePath),i=v(n.worktreeBranch),s=v(n.originChannel),a=typeof n.originThreadId=="string"||typeof n.originThreadId=="number"?n.originThreadId:void 0,l=v(n.originSessionKey),d=ba(n.route);if(!d)return;let u=Z({route:d,originChannel:s,originThreadId:a,originSessionKey:l});if(!u||o&&!i)return;let f=v(n.harness),h=jc(n.backendRef,f,e),k=zc(n.worktreeLifecycle)??Hc(n),g=v(n.completionWakeSucceededAt),p=v(n.completionWakeSkippedAt),y=n.completionWakeSummaryRequired===!0&&!p?!0:void 0;return{sessionId:v(n.sessionId),harnessSessionId:e,backendRef:h,name:je(n.name,e),prompt:je(n.prompt),workdir:je(n.workdir,"(unknown)"),model:v(n.model),reasoningEffort:ya(n.reasoningEffort),fastMode:n.fastMode===!0?!0:void 0,createdAt:V(n.createdAt),completedAt:V(n.completedAt),status:t,lifecycle:r?"suspended":Pa(n.lifecycle),approvalState:Dc(n.approvalState),worktreeState:$c(n.worktreeState),runtimeState:r?"stopped":wa(n.runtimeState),runtimeRecovery:r?Oc(n):Nc(n.runtimeRecovery),taskFlowMirror:Tc(n.taskFlowMirror),deliveryState:Bc(n.deliveryState),notificationDedupe:qc(n.notificationDedupe),completionSummaryDedupe:Vc(n.completionSummaryDedupe),completionWakeIssuedAt:v(n.completionWakeIssuedAt),completionWakeSucceededAt:g,completionWakeFailedAt:v(n.completionWakeFailedAt),completionWakeSkippedAt:p,completionWakeSkipReason:v(n.completionWakeSkipReason),completionWakeSummaryRequired:y,killReason:_c(n.killReason),costUsd:typeof n.costUsd=="number"&&Number.isFinite(n.costUsd)?n.costUsd:0,originAgentId:v(n.originAgentId),originChannel:s,originThreadId:a,originSessionKey:l,route:u,outputPath:v(n.outputPath),harness:f,resumedFromSessionName:v(n.resumedFromSessionName),goalTaskId:v(n.goalTaskId),requestedPermissionMode:Mo(n.requestedPermissionMode),currentPermissionMode:Mo(n.currentPermissionMode),approvalExecutionState:Uc(n.approvalExecutionState),approvalRationale:v(n.approvalRationale),planModeApproved:n.planModeApproved===!0,pendingPlanApproval:n.pendingPlanApproval===!0,planApprovalContext:Cc(n.planApprovalContext),planDecisionVersion:V(n.planDecisionVersion),actionablePlanDecisionVersion:V(n.actionablePlanDecisionVersion),canonicalPlanPromptVersion:V(n.canonicalPlanPromptVersion),approvalPromptRequiredVersion:V(n.approvalPromptRequiredVersion),approvalPromptVersion:V(n.approvalPromptVersion),approvalPromptStatus:Wc(n.approvalPromptStatus),approvalPromptTransport:Lc(n.approvalPromptTransport),approvalPromptMessageKind:Fc(n.approvalPromptMessageKind),approvalPromptLastAttemptAt:v(n.approvalPromptLastAttemptAt),approvalPromptDeliveredAt:v(n.approvalPromptDeliveredAt),approvalPromptFailedAt:v(n.approvalPromptFailedAt),planApproval:Sa(n.planApproval),codexApprovalPolicy:xc(n.codexApprovalPolicy),worktreePath:o,worktreeBranch:i,worktreeStrategy:ka(n.worktreeStrategy),repoIntegrationPolicy:_o(n.repoIntegrationPolicy),repoIntegrationPolicySource:Mc(n.repoIntegrationPolicySource),repoProvider:va(n.repoProvider),worktreeMerged:typeof n.worktreeMerged=="boolean"?n.worktreeMerged:void 0,worktreeMergedAt:v(n.worktreeMergedAt),worktreePrUrl:v(n.worktreePrUrl),worktreePrNumber:V(n.worktreePrNumber),pendingWorktreeDecisionSince:v(n.pendingWorktreeDecisionSince),lastWorktreeReminderAt:v(n.lastWorktreeReminderAt),worktreeBaseBranch:v(n.worktreeBaseBranch),worktreeParentBranch:v(n.worktreeParentBranch),worktreePrTargetRepo:v(n.worktreePrTargetRepo),autoMergeParentSessionId:v(n.autoMergeParentSessionId),autoMergeConflictResolutionAttemptCount:V(n.autoMergeConflictResolutionAttemptCount),autoMergeResolverSessionId:v(n.autoMergeResolverSessionId),worktreePushRemote:v(n.worktreePushRemote),worktreeDecisionSnoozedUntil:v(n.worktreeDecisionSnoozedUntil),worktreeDisposition:n.worktreeDisposition==="active"||n.worktreeDisposition==="pr-opened"||n.worktreeDisposition==="merged"||n.worktreeDisposition==="dismissed"||n.worktreeDisposition==="no-change-cleaned"?n.worktreeDisposition:void 0,worktreeRemoteOutcome:n.worktreeRemoteOutcome==="pr-opened"||n.worktreeRemoteOutcome==="pr-updated"?n.worktreeRemoteOutcome:void 0,worktreeDismissedAt:v(n.worktreeDismissedAt),worktreeLifecycle:k,resumable:r?!0:n.resumable===!0}}function Aa(n){if(!ae(n))return;let e=v(n.key),t=v(n.repoRoot),r=_o(n.policy),o=va(n.provider)??"unsupported",i=v(n.createdAt),s=v(n.updatedAt),a=n.source==="seeded"?"seeded":"stored";if(!(!e||!t||!r||!i||!s)&&!(!Number.isFinite(Date.parse(i))||!Number.isFinite(Date.parse(s))))return{key:e,policy:r,repoRoot:t,remoteUrl:v(n.remoteUrl),provider:o,createdAt:i,updatedAt:s,source:a}}function Ia(n){if(!ae(n))return;let e=Gc(n.kind),t=je(n.id),r=je(n.sessionId),o=V(n.createdAt);if(!(!t||!r||!e||o==null))return{id:t,sessionId:r,kind:e,createdAt:o,planDecisionVersion:V(n.planDecisionVersion),expiresAt:V(n.expiresAt),consumedAt:V(n.consumedAt),optionIndex:V(n.optionIndex),pendingInputRequestId:v(n.pendingInputRequestId),pendingInputQuestionId:v(n.pendingInputQuestionId),label:v(n.label),targetUrl:v(n.targetUrl),route:ba(n.route),launchName:v(n.launchName),launchPrompt:v(n.launchPrompt),launchWorkdir:v(n.launchWorkdir),launchModel:v(n.launchModel),launchReasoningEffort:ya(n.launchReasoningEffort),launchFastMode:n.launchFastMode===!0?!0:void 0,launchSystemPrompt:v(n.launchSystemPrompt),launchAllowedTools:Array.isArray(n.launchAllowedTools)?n.launchAllowedTools.filter(i=>typeof i=="string"):void 0,launchResumeSessionId:v(n.launchResumeSessionId),launchResumedFromSessionName:v(n.launchResumedFromSessionName),launchResumeWorktreeFrom:v(n.launchResumeWorktreeFrom),launchSessionIdOverride:v(n.launchSessionIdOverride),launchClearedPersistedCodexResume:n.launchClearedPersistedCodexResume===!0?!0:void 0,launchForkSession:typeof n.launchForkSession=="boolean"?n.launchForkSession:void 0,launchForceNewSession:typeof n.launchForceNewSession=="boolean"?n.launchForceNewSession:void 0,launchPermissionMode:Mo(n.launchPermissionMode),launchPlanApproval:Sa(n.launchPlanApproval),launchHarness:v(n.launchHarness),launchWorktreeStrategy:ka(n.launchWorktreeStrategy),launchWorktreeBaseBranch:v(n.launchWorktreeBaseBranch),launchWorktreePrTargetRepo:v(n.launchWorktreePrTargetRepo),launchOriginAgentId:v(n.launchOriginAgentId),repoPolicy:_o(n.repoPolicy),repoPolicyWorkdir:v(n.repoPolicyWorkdir)}}function Qn(n){if(!n.backendRef?.kind||!n.backendRef.conversationId)throw new Error(`Persisted session ${n.harnessSessionId} is missing required backend ref metadata.`);if(!n.route?.provider||!n.route.target)throw new Error(`Persisted session ${n.harnessSessionId} is missing required route metadata.`);if(n.worktreePath&&!n.worktreeBranch)throw new Error(`Persisted session ${n.harnessSessionId} is missing required worktreeBranch metadata.`)}function mt(n){return!!n&&typeof n=="object"}function Do(n){return n instanceof Error?n.message:String(n)}function tm(n,e){JSON.stringify({component:"SessionStore",event:n,at:new Date().toISOString(),...e})}function nm(n){return mt(n)?{backendRefKind:typeof n.kind=="string"?n.kind:void 0,hasBackendConversationId:typeof n.conversationId=="string"&&n.conversationId.length>0,hasBackendRunId:typeof n.runId=="string"&&n.runId.length>0,hasBackendWorktreeId:typeof n.worktreeId=="string"&&n.worktreeId.length>0,hasBackendWorktreePath:typeof n.worktreePath=="string"&&n.worktreePath.length>0}:{}}function $a(n,e,t=Date.now()){let r=`${n}.${e}-${t}`;for(let o=0;o<100;o+=1){let i=o===0?"":`-${o}`,s=`${r}${i}.json`;if(!Ta(s))return s}}function $o(){let n=Zc();return Xc(n).filter(e=>e.startsWith("openclaw-agent-")&&e.endsWith(".txt")).map(e=>Da(n,e))}function Ea(n){let e=n.OPENCLAW_CODE_AGENT_SESSIONS_PATH?.trim();return e||Da(zn(n),"code-agent-sessions.json")}function Na(n,e,t,r=[]){try{Yc(em(n),{recursive:!0});let o=n+".tmp";_a(o,JSON.stringify({schemaVersion:Hn,sessions:e,actionTokens:t,repoPolicies:r},null,2),"utf-8"),xa(o,n)}catch(o){`${Do(o)}`}}function rm(n,e){try{if(!Ta(n))return!1;let t=$a(n,"legacy");return t?(xa(n,t),`${e}${t}`,!0):!1}catch(t){return`${Do(t)}`,!1}}var om={archiveLegacySessionIndex:rm};function im(n,e){try{if(e.length===0)return;let t=$a(n,"codex-sdk-legacy");if(!t)return;_a(t,JSON.stringify(e,null,2),"utf-8"),`${e.length}${t}`}catch(t){`${Do(t)}`}}function Oa(n,e,t=[]){try{let r=new Set(t);for(let o of $o())if(!r.has(o))try{let i=Ca(o).mtimeMs;n-i>e&&Ma(o)}catch{}}catch{}}function Wa(n,e,t=[]){try{let r=new Set(t),o;for(let i of $o())if(!r.has(i))try{let s=Ca(i).mtimeMs+e;if(s<=n)return n;o=o==null?s:Math.min(o,s)}catch{}return o}catch{return}}function La(n){try{let e=new Set(n);for(let t of $o())if(!e.has(t))try{Ma(t)}catch{}}catch{}}function Fa(n){let{indexPath:e,clearAll:t,indexPersistedEntry:r,setActionToken:o,setRepoPolicy:i,purgeExpiredActionTokens:s,saveIndex:a}=n,l=d=>om.archiveLegacySessionIndex(e,d)?(t(),!0):!1;try{let d=Jc(e,"utf-8"),u=JSON.parse(d);if(Array.isArray(u)){if(!l("legacy array store"))return;a();return}if(!mt(u)||u.schemaVersion!==Hn&&u.schemaVersion!==6&&u.schemaVersion!==4){if(!l(`schema mismatch (expected v${Hn})`))return;a();return}let f=(b,m)=>{if(!Object.prototype.hasOwnProperty.call(u,b))return[];let P=u[b];if(Array.isArray(P))return P;l(m)&&a()},h=f("sessions","invalid sessions collection");if(h===void 0)return;let k=[],g=[],p=!1;for(let b of h){if(mt(b)&&b.harness==="codex"){let P=mt(b.backendRef)?b.backendRef:void 0;if((typeof P?.kind=="string"?P.kind:void 0)!=="codex-app-server"){k.push(b);continue}}let m=Ra(b);if(!m){if(!l("invalid v4 session entry"))return;a();return}mt(b)&&b.status==="running"&&(p=!0,tm("session.recovered_from_running_persisted_row",{sessionId:typeof b.sessionId=="string"?b.sessionId:void 0,hasHarnessSessionId:typeof b.harnessSessionId=="string"&&b.harnessSessionId.length>0,...nm(b.backendRef),rawStatus:b.status,rawLifecycle:b.lifecycle,rawRuntimeState:b.runtimeState,normalizedStatus:m.status,normalizedLifecycle:m.lifecycle,normalizedRuntimeState:m.runtimeState,reason:m.runtimeRecovery?.reason})),g.push(m)}k.length>0&&im(e,k);let y=f("actionTokens","invalid action token collection");if(y===void 0)return;let w=[];for(let b of y){let m=Ia(b);if(!m){if(!l("invalid v4 action token"))return;a();return}w.push(m)}let R=f("repoPolicies","invalid repo policy collection");if(R===void 0)return;let A=[],I=!1;for(let b of R){let m=Aa(b);if(!m){I=!0;continue}A.push(m)}for(let b of g)r(b);for(let b of w)o(b);for(let b of A)i(b);(k.length>0||p)&&a(),I&&a(),s()}catch(d){if(d.code==="ENOENT"||!l("corrupt or unreadable"))return;a()}}var dm=new Set(["completed","failed","killed"]),Eo=1440*60*1e3;function um(n){return n instanceof Error?n.message:String(n)}var pm={statSync:am};function cm(n){try{return pm.statSync(n).isDirectory()}catch(e){let t=e.code;return t!=="ENOENT"&&t!=="ENOTDIR"}}var Yn=class{persisted=new Map;repoPolicies=new Map;idIndex=new Map;nameIndex=new Map;backendIdIndex=new Map;actionTokens;actionTokenStore;indexPath;queries;constructor(e={}){let t=e.env??process.env;this.indexPath=e.indexPath??Ea(t),this.actionTokenStore=new Gn(()=>this.saveIndex(),Eo),this.actionTokens=this.actionTokenStore.tokens,this.queries=new jn({persisted:this.persisted,idIndex:this.idIndex,nameIndex:this.nameIndex,backendIdIndex:this.backendIdIndex}),t.OPENCLAW_DEBUG_SESSION_STORE==="1"&&`${this.indexPath}`,this.loadIndex()}loadIndex(){Fa({indexPath:this.indexPath,clearAll:()=>{this.persisted.clear(),this.repoPolicies.clear(),this.idIndex.clear(),this.nameIndex.clear(),this.backendIdIndex.clear(),this.actionTokenStore.clear()},indexPersistedEntry:e=>this.indexPersistedEntry(e),setActionToken:e=>{this.actionTokens.set(e.id,e)},setRepoPolicy:e=>{this.repoPolicies.set(e.key,e)},purgeExpiredActionTokens:()=>this.actionTokenStore.purgeExpiredActionTokens(),saveIndex:()=>this.saveIndex()})}saveIndex(){Na(this.indexPath,[...this.persisted.values()],this.actionTokenStore.listForPersistence(),[...this.repoPolicies.values()])}assertPersistedEntry(e){Qn(e)}getEntryStorageKey(e){return e.harnessSessionId}buildPersistedBackendRef(e){let t=jo(e),r=t==="codex"?"codex-app-server":t==="opencode"?"opencode-server":"claude-code";return e.backendRef??{kind:e.backendKind??r,conversationId:e.harnessSessionId}}getSessionApprovalSnapshot(e){if(typeof e.approvalSnapshot=="function")return e.approvalSnapshot();let t=typeof e.controlStateSnapshot=="function"?e.controlStateSnapshot():{planModeApproved:!1};return{requestedPermissionMode:e.requestedPermissionMode,currentPermissionMode:e.currentPermissionMode,approvalExecutionState:e.approvalExecutionState,approvalRationale:e.approvalRationale,planModeApproved:t.planModeApproved,pendingPlanApproval:e.pendingPlanApproval,planApprovalContext:e.planApprovalContext,planDecisionVersion:e.planDecisionVersion,actionablePlanDecisionVersion:e.actionablePlanDecisionVersion,canonicalPlanPromptVersion:e.canonicalPlanPromptVersion,approvalPromptRequiredVersion:e.approvalPromptRequiredVersion,approvalPromptVersion:e.approvalPromptVersion,approvalPromptStatus:e.approvalPromptStatus,approvalPromptTransport:e.approvalPromptTransport,approvalPromptMessageKind:e.approvalPromptMessageKind,approvalPromptLastAttemptAt:e.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:e.approvalPromptDeliveredAt,approvalPromptFailedAt:e.approvalPromptFailedAt,planApproval:e.planApproval,codexApprovalPolicy:e.codexApprovalPolicy}}getSessionRoutingSnapshot(e){return typeof e.routingSnapshot=="function"?e.routingSnapshot():{route:e.route,originAgentId:e.originAgentId,originChannel:e.originChannel,originThreadId:e.originThreadId,originSessionKey:e.originSessionKey}}getSessionWorktreeSnapshot(e){return typeof e.worktreeSnapshot=="function"?e.worktreeSnapshot():{worktreePath:e.worktreePath,worktreeBranch:e.worktreeBranch,worktreeStrategy:e.worktreeStrategy,repoIntegrationPolicy:e.repoIntegrationPolicy,repoIntegrationPolicySource:e.repoIntegrationPolicySource,repoProvider:e.repoProvider,worktreeBaseBranch:e.worktreeBaseBranch,worktreeParentBranch:e.worktreeParentBranch,worktreePrTargetRepo:e.worktreePrTargetRepo,autoMergeParentSessionId:e.autoMergeParentSessionId,autoMergeConflictResolutionAttemptCount:e.autoMergeConflictResolutionAttemptCount,autoMergeResolverSessionId:e.autoMergeResolverSessionId,worktreeLifecycle:e.worktreeLifecycle}}indexPersistedEntry(e){let t=this.getEntryStorageKey(e);if(e.sessionId){let o=this.idIndex.get(e.sessionId);if(o&&o!==t){let i=this.persisted.get(o);i&&this.removePersistedIndexes(i)}}this.persisted.set(t,e),e.sessionId&&this.idIndex.set(e.sessionId,t),e.name&&this.nameIndex.set(e.name,t);let r=C(e);r&&this.backendIdIndex.set(r,t)}removePersistedIndexes(e){let t=this.getEntryStorageKey(e);this.persisted.delete(t);for(let[r,o]of this.idIndex)o===t&&this.idIndex.delete(r);for(let[r,o]of this.nameIndex)o===t&&this.nameIndex.delete(r);for(let[r,o]of this.backendIdIndex)o===t&&this.backendIdIndex.delete(r)}markRunning(e){if(!e.harnessSessionId)return;let t=this.getSessionApprovalSnapshot(e),r=this.getSessionRoutingSnapshot(e),o=this.getSessionWorktreeSnapshot(e),i=Z({route:r.route,originChannel:r.originChannel,originThreadId:r.originThreadId,originSessionKey:r.originSessionKey});if(!i)throw new Error(`Cannot persist running session ${e.id}: canonical lifecycle route is missing.`);let s={sessionId:e.id,harnessSessionId:e.harnessSessionId,backendRef:this.buildPersistedBackendRef(e),name:e.name,prompt:e.prompt,workdir:e.originalWorkdir??e.workdir,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,createdAt:e.startedAt,status:"running",lifecycle:e.lifecycle,approvalState:e.approvalState,worktreeState:e.worktreeState,runtimeState:e.runtimeState,taskFlowMirror:e.taskFlowMirror,deliveryState:e.deliveryState,notificationDedupe:this.getExistingNotificationDedupe(e),completionSummaryDedupe:this.getExistingCompletionSummaryDedupe(e),costUsd:0,originAgentId:r.originAgentId,originChannel:r.originChannel,originThreadId:r.originThreadId,originSessionKey:r.originSessionKey,route:i,outputPath:ve(e.id),harness:e.harnessName,resumedFromSessionName:e.resumedFromSessionName,requestedPermissionMode:t.requestedPermissionMode,currentPermissionMode:t.currentPermissionMode,approvalExecutionState:t.approvalExecutionState,approvalRationale:t.approvalRationale,planModeApproved:t.planModeApproved,pendingPlanApproval:t.pendingPlanApproval,planApprovalContext:t.planApprovalContext,planDecisionVersion:t.planDecisionVersion,actionablePlanDecisionVersion:t.actionablePlanDecisionVersion,canonicalPlanPromptVersion:t.canonicalPlanPromptVersion,approvalPromptRequiredVersion:t.approvalPromptRequiredVersion,approvalPromptVersion:t.approvalPromptVersion,approvalPromptStatus:t.approvalPromptStatus,approvalPromptTransport:t.approvalPromptTransport,approvalPromptMessageKind:t.approvalPromptMessageKind,approvalPromptLastAttemptAt:t.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:t.approvalPromptDeliveredAt,approvalPromptFailedAt:t.approvalPromptFailedAt,planApproval:t.planApproval,codexApprovalPolicy:t.codexApprovalPolicy,worktreePath:o.worktreePath,worktreeBranch:o.worktreeBranch,worktreeStrategy:o.worktreeStrategy,repoIntegrationPolicy:o.repoIntegrationPolicy,repoIntegrationPolicySource:o.repoIntegrationPolicySource,repoProvider:o.repoProvider,worktreeBaseBranch:o.worktreeBaseBranch,worktreeParentBranch:o.worktreeParentBranch,worktreePrTargetRepo:o.worktreePrTargetRepo,autoMergeParentSessionId:o.autoMergeParentSessionId,autoMergeConflictResolutionAttemptCount:o.autoMergeConflictResolutionAttemptCount,autoMergeResolverSessionId:o.autoMergeResolverSessionId,worktreeLifecycle:o.worktreeLifecycle,resumable:e.isExplicitlyResumable};Qn(s),this.indexPersistedEntry(s),this.saveIndex()}hasRecordedSession(e){return this.queries.hasRecordedSession(e)}persistTerminal(e){if(!e.harnessSessionId)return;let t=this.getSessionApprovalSnapshot(e),r=this.getSessionRoutingSnapshot(e),o=this.getSessionWorktreeSnapshot(e),i=Z({route:r.route,originChannel:r.originChannel,originThreadId:r.originThreadId,originSessionKey:r.originSessionKey});if(!i)throw new Error(`Cannot persist terminal session ${e.id}: canonical lifecycle route is missing.`);let s;try{let l=ve(e.id);if(sm(l))s=l;else{let d=e.getOutput().join(`
203
- `);d.length>0&&(lm(l,d,"utf-8"),s=l)}}catch(l){`${e.id}${um(l)}`}let a={sessionId:e.id,harnessSessionId:e.harnessSessionId,backendRef:this.buildPersistedBackendRef(e),name:e.name,prompt:e.prompt,workdir:e.originalWorkdir??e.workdir,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,createdAt:e.startedAt,completedAt:e.completedAt,status:e.status,lifecycle:e.lifecycle,approvalState:e.approvalState,worktreeState:e.worktreeState,runtimeState:e.runtimeState,taskFlowMirror:e.taskFlowMirror,deliveryState:e.deliveryState,notificationDedupe:this.getExistingNotificationDedupe(e),completionSummaryDedupe:this.getExistingCompletionSummaryDedupe(e),killReason:e.killReason,costUsd:e.costUsd,originAgentId:r.originAgentId,originChannel:r.originChannel,originThreadId:r.originThreadId,originSessionKey:r.originSessionKey,route:i,outputPath:s,harness:e.harnessName,resumedFromSessionName:e.resumedFromSessionName,goalTaskId:e.goalTaskId,requestedPermissionMode:t.requestedPermissionMode,currentPermissionMode:t.currentPermissionMode,approvalExecutionState:t.approvalExecutionState,approvalRationale:t.approvalRationale,planModeApproved:t.planModeApproved,pendingPlanApproval:t.pendingPlanApproval,planApprovalContext:t.planApprovalContext,planDecisionVersion:t.planDecisionVersion,actionablePlanDecisionVersion:t.actionablePlanDecisionVersion,canonicalPlanPromptVersion:t.canonicalPlanPromptVersion,approvalPromptRequiredVersion:t.approvalPromptRequiredVersion,approvalPromptVersion:t.approvalPromptVersion,approvalPromptStatus:t.approvalPromptStatus,approvalPromptTransport:t.approvalPromptTransport,approvalPromptMessageKind:t.approvalPromptMessageKind,approvalPromptLastAttemptAt:t.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:t.approvalPromptDeliveredAt,approvalPromptFailedAt:t.approvalPromptFailedAt,planApproval:t.planApproval,codexApprovalPolicy:t.codexApprovalPolicy,worktreePath:o.worktreePath,worktreeBranch:o.worktreeBranch,worktreeStrategy:o.worktreeStrategy,worktreeBaseBranch:o.worktreeBaseBranch,worktreeParentBranch:o.worktreeParentBranch,worktreePrTargetRepo:o.worktreePrTargetRepo,autoMergeParentSessionId:o.autoMergeParentSessionId,autoMergeConflictResolutionAttemptCount:o.autoMergeConflictResolutionAttemptCount,autoMergeResolverSessionId:o.autoMergeResolverSessionId,worktreeLifecycle:o.worktreeLifecycle,resumable:e.isExplicitlyResumable};Qn(a),this.indexPersistedEntry(a),this.saveIndex()}getExistingNotificationDedupe(e){return this.getPersistedSession(e.id)?.notificationDedupe??(e.harnessSessionId?this.getPersistedSession(e.harnessSessionId)?.notificationDedupe:void 0)??(C(e)?this.getPersistedSession(C(e))?.notificationDedupe:void 0)}getExistingCompletionSummaryDedupe(e){return this.getPersistedSession(e.id)?.completionSummaryDedupe??(e.harnessSessionId?this.getPersistedSession(e.harnessSessionId)?.completionSummaryDedupe:void 0)??(C(e)?this.getPersistedSession(C(e))?.completionSummaryDedupe:void 0)}getLatestPersistedByName(e){return this.queries.getLatestPersistedByName(e)}resolveBackendConversationId(e,t){return this.queries.resolveBackendConversationId(e,t)}resolveHarnessSessionId(e,t){return this.queries.resolveHarnessSessionId(e,t)}getPersistedSession(e){return this.queries.getPersistedSession(e)}replacePersistedSession(e){let t=e.sessionId?this.getPersistedSession(e.sessionId):void 0;t&&this.removePersistedIndexes(t),this.indexPersistedEntry(e),this.saveIndex()}listPersistedSessions(){return this.queries.listPersistedSessions()}getRepoPolicy(e){return this.repoPolicies.get(e)}listRepoPolicies(){return[...this.repoPolicies.values()].sort((e,t)=>e.repoRoot.localeCompare(t.repoRoot)||e.key.localeCompare(t.key))}setRepoPolicy(e){let t=this.repoPolicies.get(e.key),r={...e,createdAt:t?.createdAt??e.createdAt,updatedAt:new Date().toISOString(),source:"stored"};return this.repoPolicies.set(r.key,r),this.saveIndex(),r}updateRepoPolicy(e,t){let r=this.repoPolicies.get(e);if(r)return this.setRepoPolicy({...r,policy:t})}resetRepoPolicy(e){let t=this.repoPolicies.delete(e);return t&&this.saveIndex(),t}removeRepoPolicies(e){let t=[];for(let r of e){let o=this.repoPolicies.get(r);o&&(this.repoPolicies.delete(r),t.push(o))}return t.length>0&&this.saveIndex(),t.sort((r,o)=>r.repoRoot.localeCompare(o.repoRoot)||r.key.localeCompare(o.key))}cleanupRepoPolicies(){let e=[];for(let[t,r]of this.repoPolicies)cm(r.repoRoot)||(this.repoPolicies.delete(t),e.push(r));return e.length>0&&this.saveIndex(),e.sort((t,r)=>t.repoRoot.localeCompare(r.repoRoot)||t.key.localeCompare(r.key))}cleanupTmpOutputFiles(e){this.actionTokenStore.purgeExpiredActionTokens(e),Oa(e,Eo,this.getReferencedOutputPaths())}getNextTmpOutputCleanupAt(e){return Wa(e,Eo,this.getReferencedOutputPaths())}evictOldestPersisted(e){let t=this.listPersistedSessions();if(t.length<=e)return[];let r=t.slice(e);for(let o of r)this.removePersistedIndexes(o);return this.saveIndex(),r}shouldGcActiveSession(e,t,r){return!e.completedAt||!dm.has(e.status)?!1:t-e.completedAt>r}getActionToken(e){return this.actionTokenStore.getActionToken(e)}consumeActionToken(e){return this.actionTokenStore.consumeActionToken(e)}deleteActionTokensForSession(e){this.actionTokenStore.deleteActionTokensForSession(e)}purgeExpiredActionTokens(e=Date.now()){return this.actionTokenStore.purgeExpiredActionTokens(e)}getNextActionTokenExpiry(){return this.actionTokenStore.nextExpiryAt()}onActionTokensChanged(e){this.actionTokenStore.setAfterChangeListener(e)}hasOutputPathReference(e){for(let t of this.persisted.values())if(t.outputPath===e)return!0;return!1}getReferencedOutputPaths(){return[...new Set([...this.persisted.values()].map(e=>e.outputPath).filter(e=>typeof e=="string"&&e.length>0))]}cleanupOrphanOutputFiles(){La(this.getReferencedOutputPaths())}};var mm=new Set(["completed","failed","killed"]),Jn=class{metrics={totalCostUsd:0,costPerDay:new Map,sessionsByStatus:{completed:0,failed:0,killed:0},totalLaunched:0,totalDurationMs:0,sessionsWithDuration:0,mostExpensive:null};incrementLaunched(){this.metrics.totalLaunched++}recordSession(e){let t=e.costUsd??0,r=e.status;this.metrics.totalCostUsd+=t;let o=new Date(e.completedAt??e.startedAt).toISOString().slice(0,10);if(this.metrics.costPerDay.set(o,(this.metrics.costPerDay.get(o)??0)+t),mm.has(r)&&this.metrics.sessionsByStatus[r]++,e.completedAt){let i=e.completedAt-e.startedAt;this.metrics.totalDurationMs+=i,this.metrics.sessionsWithDuration++}(!this.metrics.mostExpensive||t>this.metrics.mostExpensive.costUsd)&&(this.metrics.mostExpensive={id:e.id,name:e.name,costUsd:t,prompt:q(e.prompt,80)})}getMetrics(){return{totalCostUsd:this.metrics.totalCostUsd,costPerDay:new Map(this.metrics.costPerDay),sessionsByStatus:{...this.metrics.sessionsByStatus},totalLaunched:this.metrics.totalLaunched,totalDurationMs:this.metrics.totalDurationMs,sessionsWithDuration:this.metrics.sessionsWithDuration,mostExpensive:this.metrics.mostExpensive?{...this.metrics.mostExpensive}:null}}};import*as Ba from"child_process";var ze=class{tails=new Map;enqueue(e,t,r){let o=this.tails.get(e);o!==void 0&&r?.();let s=(o?.catch(()=>{})??Promise.resolve()).then(()=>t()),a=s.catch(()=>{});return this.tails.set(e,a),a.finally(()=>{this.tails.get(e)===a&&this.tails.delete(e)}),s}clear(){this.tails.clear()}};var No=3e4,fm=2e3,gm=2e4,j=4;function ft(n){return n instanceof Error?n.message:String(n)}function hm(){return new Error(`Dispatch timed out after ${No}ms`)}function ym(n){if(!(n instanceof Error))return!1;let e=n;return e.killed===!0&&e.signal==="SIGKILL"}var Sm={execFile:Ba.execFile},Xn=class{pendingRetryTimers=new Map;orderedDispatches=new ze;disposed=!1;clearPendingRetries(){for(let e of this.pendingRetryTimers.values())for(let t of e)clearTimeout(t.timer),t.onCleared?.();this.pendingRetryTimers.clear()}clearRetryTimersForSession(e){let t=this.pendingRetryTimers.get(e);if(t){for(let r of t)clearTimeout(r.timer),r.onCleared?.();this.pendingRetryTimers.delete(e)}}dispose(){this.disposed=!0,this.clearPendingRetries(),this.orderedDispatches.clear()}execute(e,t,r=1){if(!this.disposed){if(r===1&&t.orderingKey){this.enqueueOrderedDispatch(t.orderingKey,o=>this.executeNow(e,t,o,r));return}this.executeNow(e,t,void 0,r)}}executePromise(e,t,r=1){if(!this.disposed){if(r===1&&t.orderingKey){this.enqueueOrderedDispatch(t.orderingKey,o=>this.executePromiseNow(e,t,o,r));return}this.executePromiseNow(e,t,void 0,r)}}executeNow(e,t,r,o=1){if(this.disposed||t.shouldContinue?.()===!1){r?.();return}let i=Date.now();o===1&&t.onStarted?.(),this.log("info","dispatch_started",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j}),Sm.execFile("openclaw",e,{timeout:No,killSignal:"SIGKILL"},(s,a,l)=>{if(this.disposed){r?.();return}let d=Date.now()-i;if(!s){let g=t.successValidator?.(a??"");if(g?.outcome==="failure"){this.log("error","dispatch_success_validation_failed",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,error:g.reason,terminal:!0}),t.onFinalFailure?.(),r?.();return}if(g?.outcome==="skipped"){this.log("info","dispatch_skipped",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,reason:g.reason}),t.shouldContinue?.()!==!1&&t.onSkipped?.(g.reason),r?.();return}this.log("info","dispatch_succeeded",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d}),t.shouldContinue?.()!==!1&&t.onSuccess?.(),r?.();return}let u=l?.trim()?` | stderr: ${l.trim()}`:"";if(t.shouldContinue?.()===!1){r?.();return}if(t.target==="message.send"&&ym(s)){this.log("error","dispatch_failed",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,error:`${ft(s)}${u}`,terminal:!0,ambiguousResult:!0}),t.onAmbiguousResult?.(),r?.();return}if(o>=j||t.terminalOnFailure===!0){this.log("error","dispatch_failed",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,error:`${ft(s)}${u}`,terminal:!0}),t.onFinalFailure?.(),r?.();return}let h=this.retryDelayMs(o);this.log("error","dispatch_retry_scheduled",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,retryDelayMs:h,error:`${ft(s)}${u}`});let k={timer:setTimeout(()=>{let g=this.pendingRetryTimers.get(t.sessionId);if(g&&(g.delete(k),g.size===0&&this.pendingRetryTimers.delete(t.sessionId)),t.shouldContinue?.()===!1){r?.();return}this.executeNow(e,t,r,o+1)},h),onCleared:r};k.timer.unref?.(),this.pendingRetryTimers.has(t.sessionId)||this.pendingRetryTimers.set(t.sessionId,new Set),this.pendingRetryTimers.get(t.sessionId).add(k)})}executePromiseNow(e,t,r,o=1){if(this.disposed||t.shouldContinue?.()===!1){r?.();return}let i=Date.now();o===1&&t.onStarted?.(),this.log("info","dispatch_started",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j}),this.executePromiseWithTimeout(e).then(()=>{if(this.disposed){r?.();return}let s=Date.now()-i;this.log("info","dispatch_succeeded",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:s}),t.shouldContinue?.()!==!1&&t.onSuccess?.(),r?.()}).catch(s=>{if(this.disposed){r?.();return}let a=Date.now()-i;if(t.shouldContinue?.()===!1){r?.();return}if(o>=j||t.terminalOnFailure===!0){this.log("error","dispatch_failed",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:a,error:ft(s),terminal:!0,...t.terminalOnFailure===!0&&o<j?{terminalReason:"non_retryable"}:{}}),t.onFinalFailure?.(),r?.();return}let l=this.retryDelayMs(o);this.log("error","dispatch_retry_scheduled",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:a,retryDelayMs:l,error:ft(s)});let d={timer:setTimeout(()=>{let u=this.pendingRetryTimers.get(t.sessionId);if(u&&(u.delete(d),u.size===0&&this.pendingRetryTimers.delete(t.sessionId)),t.shouldContinue?.()===!1){r?.();return}this.executePromiseNow(e,t,r,o+1)},l),onCleared:r};d.timer.unref?.(),this.pendingRetryTimers.has(t.sessionId)||this.pendingRetryTimers.set(t.sessionId,new Set),this.pendingRetryTimers.get(t.sessionId).add(d)})}executePromiseWithTimeout(e){return new Promise((t,r)=>{let o=!1,i=setTimeout(()=>{o||(o=!0,r(hm()))},No);i.unref?.(),Promise.resolve().then(e).then(()=>{o||(o=!0,clearTimeout(i),t())}).catch(s=>{o||(o=!0,clearTimeout(i),r(s))})})}retryDelayMs(e){let t=Math.max(0,e-1),r=fm*2**t;return Math.min(r,gm)}enqueueOrderedDispatch(e,t){this.orderedDispatches.enqueue(e,async()=>{this.disposed||await new Promise(r=>{let o=!1;t(()=>{o||(o=!0,r())})})})}log(e,t,r){let o=`[WakeDispatcher] ${JSON.stringify({event:t,...r})}`;if(e==="error"){console.error(o);return}}};var Zn=class{resolve(e){let t=le(e);if(!(!t?.provider||!t.target))return{channel:t.provider,target:t.target,accountId:t.accountId,threadId:t.threadId,sessionKey:t.sessionKey}}summary(e){if(!e)return"system";let t=e.accountId?`|${e.accountId}`:"",r=e.threadId?`#${e.threadId}`:"";return`${e.channel}${t}|${e.target}${r}`}};import{randomUUID as km}from"crypto";var er=class{constructor(e={}){}buildChatSendArgs(e,t,r,o=km()){return["gateway","call","chat.send","--expect-final","--timeout","30000","--params",JSON.stringify({sessionKey:e,message:t,deliver:r,idempotencyKey:o})]}buildDirectNotificationArgs(e,t,r){let o=Vt(r),i=["message","send","--channel",e.channel,"--target",e.target,"--message",t];return e.accountId&&i.push("--account",e.accountId),e.threadId&&i.push("--thread-id",e.threadId),o&&i.push("--presentation",JSON.stringify(o)),i}buildSystemEventArgs(e){return["system","event","--text",e,"--mode","now"]}};function vm(n){let e=Pm(n).trim();return e?/^NO_REPLY$/i.test(e)?{outcome:"failure",reason:"completion follow-up wake ended with NO_REPLY"}:{outcome:"success"}:{outcome:"failure",reason:"completion follow-up wake produced no final response"}}function Pm(n){let e=n.trim();if(!e)return"";try{return Oo(JSON.parse(e)).trim()}catch{return e}}function Oo(n){if(typeof n=="string")return n;if(Array.isArray(n))return n.map(r=>Oo(r)).filter(Boolean).join(`
204
- `);if(!n||typeof n!="object")return"";let e=n,t=["final","finalResponse","final_response","assistantFinal","assistant_final","response","text","content"];for(let r of t){let o=e[r];if(typeof o=="string"&&o.trim())return o}for(let r of["result","message","data"]){let o=Oo(e[r]);if(o.trim())return o}return""}var tr=class{routes=new Zn;transport;directNotifications;executor=new Xn;constructor(e={}){this.transport=e.transport??new er(e.transportOptions),this.directNotifications=e.directNotifications===void 0?new We:e.directNotifications}clearPendingRetries(){this.executor.clearPendingRetries()}clearRetryTimersForSession(e){this.executor.clearRetryTimersForSession(e)}dispose(){this.executor.dispose()}buildDispatchContext(e){let t=e.buttons??[],r=t.flat();return{transportRoute:e.routeSummary,transportChannel:e.route?.channel??"system",transportTarget:e.route?.target??"system",transportAccountId:e.route?.accountId,transportThreadId:e.route?.threadId,transportSessionKey:e.route?.sessionKey,messageTextLength:e.text.length,buttonsPresent:r.length>0,buttonRows:t.length||void 0,buttonCount:r.length||void 0,buttonLabels:r.length>0?r.map(o=>o.label):void 0,maxCallbackDataLength:r.length>0?Math.max(...r.map(o=>o.callbackData.length)):void 0}}sendWake(e,t,r,o,i,s,a,l,d,u){let f=this.routes.resolve(e),h=a;if(h?.()===!1)return;let k=f?.sessionKey?.trim();if(!k){this.executor.execute(this.transport.buildSystemEventArgs(t),{label:`${r}-system`,sessionId:e.id,target:"system.event",phase:o,routeSummary:"system",messageKind:"wake",dispatchContext:this.buildDispatchContext({routeSummary:"system",text:t}),onSuccess:s,onSkipped:d,onFinalFailure:i,successValidator:l,shouldContinue:h});return}this.executor.execute(this.transport.buildChatSendArgs(k,t,!0,u),{label:r,sessionId:e.id,target:"chat.send",phase:o,routeSummary:`session:${k}`,messageKind:"wake",dispatchContext:this.buildDispatchContext({routeSummary:`session:${k}`,route:f,text:t}),onSuccess:s,onSkipped:d,successValidator:l,shouldContinue:h,onFinalFailure:()=>{h?.()!==!1&&this.executor.execute(this.transport.buildSystemEventArgs(t),{label:`${r}-fallback`,sessionId:e.id,target:"system.event",phase:o,routeSummary:"system",messageKind:"wake",dispatchContext:this.buildDispatchContext({routeSummary:"system",text:t}),onSuccess:s,onSkipped:d,onFinalFailure:i,successValidator:l,shouldContinue:h})}})}sendUserNotification(e,t,r,o,i,s,a=!1,l){if(l?.()===!1)return;let d=!!o?.some(g=>Array.isArray(g)&&g.length>0),u=this.routes.resolve(e);M("wake_notify_selected",{sessionId:e.id,sessionName:e.name,label:r,messageTextLength:t.length,requireDirectDelivery:a,hasDirectNotificationTransport:!!this.directNotifications,routeSummary:u?this.routes.summary(u):"system",channel:u?.channel,target:u?.target,accountId:u?.accountId,threadId:u?.threadId,sessionKey:u?.sessionKey,...E(o)});let f=u?`notify:${u.channel}|${u.accountId??""}|${u.target}|${u.threadId??""}`:`notify:system:${e.id}`;if(!u){if(M("wake_notify_no_direct_route",{sessionId:e.id,sessionName:e.name,label:r,requireDirectDelivery:a,hasInteractiveButtons:d,...E(o)}),a){`${r}${e.id}`,i?.();return}if(d){`${r}${e.id}`,i?.();return}this.executor.execute(this.transport.buildSystemEventArgs(t),{label:`${r}-notify-system`,sessionId:e.id,target:"system.event",phase:"notify",routeSummary:"system",messageKind:"notify",dispatchContext:this.buildDispatchContext({routeSummary:"system",text:t,buttons:o}),orderingKey:f,onSuccess:s,onFinalFailure:i,shouldContinue:l});return}let h=()=>{if(M("wake_notify_direct_failed",{sessionId:e.id,sessionName:e.name,label:r,requireDirectDelivery:a,hasInteractiveButtons:d,channel:u.channel,target:u.target,accountId:u.accountId,threadId:u.threadId,sessionKey:u.sessionKey,...E(o)}),a){`${r}${e.id}`,i?.();return}if(d){`${r}${e.id}`,i?.();return}this.executor.execute(this.transport.buildSystemEventArgs(t),{label:`${r}-notify-fallback`,sessionId:e.id,target:"system.event",phase:"notify",routeSummary:"system",messageKind:"notify",dispatchContext:this.buildDispatchContext({routeSummary:"system",text:t}),orderingKey:f,onSuccess:s,onFinalFailure:i,shouldContinue:l})},k={label:`${r}-notify`,sessionId:e.id,target:"message.send",phase:"notify",routeSummary:this.routes.summary(u),messageKind:"notify",dispatchContext:this.buildDispatchContext({routeSummary:this.routes.summary(u),route:u,text:t,buttons:o}),orderingKey:f,onSuccess:s,onAmbiguousResult:h,onFinalFailure:h,terminalOnFailure:this.directNotifications?!0:void 0,shouldContinue:l};if(this.directNotifications){M("wake_notify_dispatching_direct_runtime",{sessionId:e.id,sessionName:e.name,label:r,channel:u.channel,target:u.target,accountId:u.accountId,threadId:u.threadId,sessionKey:u.sessionKey,...E(o)}),this.executor.executePromise(()=>this.directNotifications.send(u,t,o),k);return}M("wake_notify_dispatching_cli_message_send",{sessionId:e.id,sessionName:e.name,label:r,channel:u.channel,target:u.target,accountId:u.accountId,threadId:u.threadId,sessionKey:u.sessionKey,...E(o)}),this.executor.execute(this.transport.buildDirectNotificationArgs(u,t,o),k)}sendUserNotificationSequence(e,t,r,o,i,s=!1,a){let l=t.map(u=>({text:u.text.trim(),buttons:u.buttons})).filter(u=>u.text.length>0);if(l.length===0){o?.();return}M("wake_notify_sequence_started",{sessionId:e.id,sessionName:e.name,label:r,chunkCount:l.length,buttonChunkIndexes:l.map((u,f)=>u.buttons?.some(h=>Array.isArray(h)&&h.length>0)?f+1:void 0).filter(u=>typeof u=="number"),requireDirectDelivery:s});let d=u=>{if(a?.()===!1)return;let f=l[u];if(!f){M("wake_notify_sequence_succeeded",{sessionId:e.id,sessionName:e.name,label:r,chunkCount:l.length}),i?.();return}let h=u===0?o:i;M("wake_notify_sequence_chunk_selected",{sessionId:e.id,sessionName:e.name,label:r,chunkIndex:u+1,chunkCount:l.length,messageTextLength:f.text.length,failureHandler:u===0?"all-failed":"sequence-success",...E(f.buttons)}),this.sendUserNotification(e,f.text,`${r}-part-${u+1}`,f.buttons,h,()=>d(u+1),s,a)};d(0)}dispatchSessionNotification(e,t){let r=t.hooks,o=t.wakeMessageOnNotifySuccess!=null||t.wakeMessageOnNotifyFailed!=null,i=t.notifyUser??(t.wakeMessage?"on-wake-fallback":"always"),s=(t.userMessages?.length?t.userMessages:t.userMessage?.trim()?[{text:t.userMessage.trim(),buttons:t.buttons}]:[]).map(u=>({text:u.text.trim(),buttons:u.buttons})).filter(u=>u.text.length>0),a=t.wakeMessage?.trim(),l=t.shouldDispatch,d=t.completionWakeSummaryRequired===!0?vm:void 0;if(o){let u=t.wakeMessageOnNotifySuccess?.trim(),f=t.wakeMessageOnNotifyFailed?.trim(),h=y=>{y&&l?.()!==!1&&(r?.onWakeStarted?.(),this.sendWake(e,y,`${t.label}-wake`,"wake",r?.onWakeFailed,r?.onWakeSucceeded,l,d,r?.onWakeSkipped,t.idempotencyKey))},k=y=>{if(y){if(t.deferConditionalWakeUntilNextTick===!0||t.deferConditionalWakeMs!==void 0){let w=Math.max(0,Math.floor(t.deferConditionalWakeMs??0));setTimeout(()=>h(y),w).unref?.();return}h(y)}},g=()=>{l?.()!==!1&&(r?.onNotifySucceeded?.(),u&&k(u))},p=f?()=>{l?.()!==!1&&(r?.onNotifyFailed?.(),t.onUserNotifyFailed?.(),k(f))}:()=>{l?.()!==!1&&(r?.onNotifyFailed?.(),t.onUserNotifyFailed?.())};if(s.length>0){if(l?.()===!1)return;r?.onNotifyStarted?.(),this.sendUserNotificationSequence(e,s,t.label,p,g,t.requireDirectUserNotification===!0,l)}else p();return}if(i==="always"&&s.length>0){if(l?.()===!1)return;r?.onNotifyStarted?.(),this.sendUserNotificationSequence(e,s,t.label,()=>{l?.()!==!1&&(r?.onNotifyFailed?.(),t.onUserNotifyFailed?.())},()=>{l?.()!==!1&&r?.onNotifySucceeded?.()},t.requireDirectUserNotification===!0,l)}if(a&&l?.()!==!1){if(r?.onWakeStarted?.(),i==="on-wake-fallback"&&s.length>0&&!this.routes.resolve(e)?.sessionKey){if(l?.()===!1)return;r?.onNotifyStarted?.(),this.sendUserNotificationSequence(e,s,t.label,()=>{l?.()!==!1&&(r?.onNotifyFailed?.(),t.onUserNotifyFailed?.())},()=>{l?.()!==!1&&r?.onNotifySucceeded?.()},!1,l)}this.sendWake(e,a,`${t.label}-wake`,"wake",r?.onWakeFailed,r?.onWakeSucceeded,l,d,r?.onWakeSkipped,t.idempotencyKey)}}};var Ka=36,qa=2,Va="...";function wm(n){let e=Array.from(n);return e.length<=Ka?n:`${e.slice(0,Ka-Va.length).join("")}${Va}`}var nr=class{constructor(e,t){this.actionTokens=e;this.isGitHubCliAvailable=t}actionTokens;isGitHubCliAvailable;createActionToken(e,t,r={}){return this.actionTokens.createActionToken(e,t,{expiresAt:Date.now()+10080*60*1e3,...r})}consumeActionToken(e){return this.actionTokens.consumeActionToken(e)}consumeQuestionAnswerTokens(e,t,r){return this.actionTokens.consumeQuestionAnswerTokens(e,t,r)}consumePlanDecisionTokens(e,t){return this.actionTokens.consumePlanDecisionTokens(e,t)}getActionToken(e){return this.actionTokens.getActionToken(e)}listActiveActionTokens(e){return this.actionTokens.listActiveActionTokens(e)}clearRepoPolicyChoiceTokens(e){this.actionTokens.deleteActionTokensForSessionByKind(e,"repo-policy-set")}clearPlanDecisionTokens(e,t){this.actionTokens.deletePlanDecisionTokensForSession(e,t)}makeActionButton(e,t,r,o={}){let i=this.createActionToken(e,t,{label:r,...o});return{label:r,callbackData:i.id,style:this.resolveButtonStyle(t)}}resolveButtonStyle(e){switch(e){case"plan-approve":case"worktree-create-pr":case"worktree-update-pr":case"plan-offer-start":case"repo-policy-set":return"primary";case"worktree-merge":case"session-resume":case"session-restart":case"plugin-update-install":case"plugin-update-restart":return"success";case"plugin-update-remind-later":return"secondary";case"plan-reject":case"worktree-dismiss":case"plugin-update-dismiss":return"danger";default:return"secondary"}}getWorktreeDecisionButtons(e,t,r={merge:!0,pr:!0}){if(!t)return[];let o=[],i=[];if(r.merge&&i.push(this.makeActionButton(e,"worktree-merge","Merge")),r.pr&&this.isGitHubCliAvailable())t.worktreePrUrl?(i.push(this.makeActionButton(e,"worktree-view-pr","View PR",{targetUrl:t.worktreePrUrl})),i.length>0&&o.push(i),o.push([this.makeActionButton(e,"worktree-update-pr","Sync PR"),this.makeActionButton(e,"worktree-decide-later","Later")])):(i.push(this.makeActionButton(e,"worktree-create-pr","Open PR")),i.length>0&&o.push(i),o.push([this.makeActionButton(e,"worktree-decide-later","Later"),this.makeActionButton(e,"worktree-dismiss","Discard")]));else return o.push([...i,this.makeActionButton(e,"worktree-decide-later","Later")]),o.push([this.makeActionButton(e,"worktree-dismiss","Discard")]),o;return t.worktreePrUrl&&o.push([this.makeActionButton(e,"worktree-dismiss","Discard")]),o}getPlanApprovalButtons(e,t){let r=t?.actionablePlanDecisionVersion??t?.planDecisionVersion;this.clearPlanDecisionTokens(e,r);let o=[[this.makeActionButton(e,"plan-approve","Approve",{planDecisionVersion:r}),this.makeActionButton(e,"plan-request-changes","Revise",{planDecisionVersion:r}),this.makeActionButton(e,"plan-reject","Reject",{planDecisionVersion:r})]];return M("plan_approval_buttons_created",{sessionId:e,planDecisionVersion:r,...E(o)}),o}getResumeButtons(e,t){let r=[];return t.isExplicitlyResumable&&r.push(this.makeActionButton(e,"session-resume","Resume")),r.push(this.makeActionButton(e,"view-output","View output")),[r]}getQuestionButtons(e,t,r={}){if(t.length===0)return;let o=t.map((s,a)=>{let l=this.createActionToken(e,"question-answer",{label:s.label,optionIndex:a,pendingInputRequestId:r.requestId,pendingInputQuestionId:r.questionId});return{label:wm(s.label),callbackData:l.id,style:this.resolveButtonStyle("question-answer")}}),i=[];for(let s=0;s<o.length;s+=qa)i.push(o.slice(s,s+qa));return i}getPlanOfferButtons(e){let{offerId:t,route:r,planName:o,planPrompt:i,planWorkdir:s,planWorktreeStrategy:a}=e,l=[[this.makeActionButton(t,"plan-offer-start","Start Plan",{route:r,launchName:o,launchPrompt:i,launchWorkdir:s,launchWorktreeStrategy:a}),this.makeActionButton(t,"plan-offer-dismiss","Dismiss",{route:r})]];return M("plan_offer_buttons_created",{offerId:t,planName:o,channel:r.provider,target:r.target,accountId:r.accountId,threadId:r.threadId,sessionKey:r.sessionKey,planPromptLength:i.length,planWorkdirLength:s.length,planWorktreeStrategy:a,...E(l)}),l}getRepoPolicyChoiceButtons(e){let t=st(e.prAvailable??!0),r=Array.from({length:Math.ceil(t.length/2)},(o,i)=>t.slice(i*2,i*2+2)).map(o=>o.map(i=>this.makeActionButton(e.choiceId,"repo-policy-set",i.label,{route:e.route,repoPolicy:i.policy,repoPolicyWorkdir:e.repoRoot,launchName:e.launchName,launchPrompt:e.launchPrompt,launchWorkdir:e.launchWorkdir,launchModel:e.launchModel,launchReasoningEffort:e.launchReasoningEffort,launchFastMode:e.launchFastMode,launchSystemPrompt:e.launchSystemPrompt,launchAllowedTools:e.launchAllowedTools,launchResumeSessionId:e.launchResumeSessionId,launchResumedFromSessionName:e.launchResumedFromSessionName,launchResumeWorktreeFrom:e.launchResumeWorktreeFrom,launchSessionIdOverride:e.launchSessionIdOverride,launchClearedPersistedCodexResume:e.launchClearedPersistedCodexResume,launchForkSession:e.launchForkSession,launchForceNewSession:e.launchForceNewSession,launchPermissionMode:e.launchPermissionMode,launchPlanApproval:e.launchPlanApproval,launchHarness:e.launchHarness,launchWorktreeStrategy:e.launchWorktreeStrategy,launchWorktreeBaseBranch:e.launchWorktreeBaseBranch,launchWorktreePrTargetRepo:e.launchWorktreePrTargetRepo,launchOriginAgentId:e.launchOriginAgentId})));return M("repo_policy_choice_buttons_created",{choiceId:e.choiceId,repoRoot:e.repoRoot,channel:e.route.provider,target:e.route.target,accountId:e.route.accountId,threadId:e.route.threadId,sessionKey:e.route.sessionKey,labels:t.map(o=>o.label),...E(r)}),r}};import{createHash as Im}from"crypto";var bm="duplicate notification already delivered or in flight",rr=class{maxRecords;inFlightTtlMs;now;inFlight=new Set;delivered=new Set;constructor(e={}){this.maxRecords=Math.max(1,Math.floor(e.maxRecords??64)),this.inFlightTtlMs=Math.max(1,Math.floor(e.inFlightTtlMs??6e5)),this.now=e.now??(()=>new Date)}claim(e,t,r){if(!e)return{allowed:!0};let o=this.now(),i=this.prune(t??[],o),s=i.find(a=>a.key===e);return this.delivered.has(e)||this.inFlight.has(e)||s?.status==="delivered"||s?.status==="in_flight"&&this.isFreshInFlight(s,o)?{allowed:!1,records:i,reason:bm}:(this.inFlight.add(e),this.delivered.delete(e),{allowed:!0,records:this.upsert(i,{key:e,status:"in_flight",recordedAt:o.toISOString(),label:r})})}deliveredRecords(e,t,r){if(!e)return;let o=this.now();return this.inFlight.delete(e),this.delivered.add(e),this.upsert(this.prune(t??[],o),{key:e,status:"delivered",recordedAt:o.toISOString(),label:r})}releasedRecords(e,t){if(!e)return;let r=this.now();return this.inFlight.delete(e),this.prune(t??[],r).filter(o=>!(o.key===e&&o.status==="in_flight"))}prune(e,t){let r=e.filter(o=>o.status==="delivered"?!0:this.isFreshInFlight(o,t));return r.slice(Math.max(0,r.length-this.maxRecords))}isFreshInFlight(e,t){let r=Date.parse(e.recordedAt);return Number.isFinite(r)?t.getTime()-r<this.inFlightTtlMs:!1}upsert(e,t){let o=[...e.filter(i=>i.key!==t.key),t];return o.slice(Math.max(0,o.length-this.maxRecords))}};import{createHash as Rm}from"crypto";var Am=1024,gt="duplicate completion follow-up wake already handled",or="prior human-visible summary already delivered",ir=class{inFlight=new Set;completed=new Map;claimKeysByPrimary=new Map;maxCompletedKeys;constructor(e={}){this.maxCompletedKeys=Math.max(1,Math.floor(e.maxCompletedKeys??Am))}decide(e,t,r){if(t?.required!==!0)return{required:!1,allowed:!1,explicit:!1};let o=this.buildKeySet(e,t);if(!o)return{required:!0,allowed:!0,explicit:!1};let i=this.normalizeRecords(r),s=this.buildPersistedKeyMap(i),a=o.decisionKeys.find(u=>this.inFlight.has(u)||!!this.getCompletedRecord(u)||s.has(u)),l=a?this.getCompletedRecord(a):void 0,d=a?s.get(a):void 0;return a?{required:!0,allowed:!1,explicit:o.explicit,dedupeKey:o.primary,skipReason:l?.skipReason??d?.skipReason??gt}:(this.registerClaim(o.primary,o.claimKeys),{required:!0,allowed:!0,key:o.primary,explicit:o.explicit})}recordVisibleDelivery(e,t,r,o){if(t.required!==!0)return{required:!1,allowed:!1,explicit:!1};let i=this.buildKeySet(e,t);if(!i)return{required:!0,allowed:!0,explicit:!1};let s=this.normalizeRecords(r),a=this.buildPersistedKeyMap(s),l=i.decisionKeys.find(h=>!!this.getCompletedRecord(h)||a.has(h)),d=l?this.getCompletedRecord(l):void 0,u=l?a.get(l):void 0;if(d||u)return{required:!0,allowed:!1,explicit:i.explicit,dedupeKey:i.primary,skipReason:d?.skipReason??u?.skipReason};this.finishKeys(i.primary,i.claimKeys,!0,or);let f=this.deliveredRecords(i.claimKeys,s,o,or);return{required:!0,allowed:!0,key:i.primary,explicit:i.explicit,records:f}}finish(e,t,r=gt){if(!e)return;let o=this.claimKeysByPrimary.get(e)??[e];this.finishKeys(e,o,t,r)}completionRecordsAfterDelivery(e,t,r,o=gt){if(!e)return;let i=this.claimKeysByPrimary.get(e)??[e];return this.deliveredRecords(i,t,r,o)}registerClaim(e,t){for(let r of t)this.inFlight.add(r);for(this.claimKeysByPrimary.delete(e),this.claimKeysByPrimary.set(e,t);this.claimKeysByPrimary.size>this.maxCompletedKeys;){let r=this.claimKeysByPrimary.keys().next().value;if(r===void 0)break;let o=this.claimKeysByPrimary.get(r)??[r];for(let i of o)this.inFlight.delete(i);this.claimKeysByPrimary.delete(r)}}finishKeys(e,t,r,o=gt){for(let i of t)this.inFlight.delete(i);if(this.claimKeysByPrimary.delete(e),!!r){for(let i of t)this.completed.get(i)?.skipReason===or&&o!==or||(this.completed.delete(i),this.completed.set(i,{skipReason:o,linkedKeys:t.filter(a=>a!==i)}));for(;this.completed.size>this.maxCompletedKeys;){let i=this.completed.keys().next().value;if(i===void 0)break;this.completed.delete(i)}}}buildKeySet(e,t){let r=this.getDeliveryRef(e);if(!r)return;let o=this.normalizeOutcomeKey(e,t.outcomeKey?.trim());if(o){let a=`${this.buildVisibleScope(r,e)}:outcome:${this.digest(o)}`,l=this.isGoalLike(e,t,o),d=this.buildSessionAliasKeys(r,e,"visible-summary"),u=this.buildSessionAliasKeys(r,e,"goal-summary"),f=this.isTerminalLike(t,o),h=o.startsWith("worktree-pr:")?this.normalizeWorktreePrOutcome(t.outcomeKey?.trim()):void 0,k=h?.aliases.map(g=>`${this.buildVisibleScope(r,e)}:outcome:${this.digest(g)}`)??[];return{primary:a,explicit:!0,claimKeys:[...d,...l?u:[],...k,a],decisionKeys:[a,...h?.blocksAliases?k:[],...l||f?d:[],...u]}}let i=t.fallbackFingerprint?.trim();if(!i)return;let s=`${r}:${t.producer}:${this.digest(i)}`;return{primary:s,explicit:!1,claimKeys:[s],decisionKeys:[s]}}isGoalLike(e,t,r){return!!e.goalTaskId?.trim()||t.producer==="goal"||/^goal:/i.test(r)}isTerminalLike(e,t){return e.producer==="terminal"||/^terminal:/i.test(t)}normalizeOutcomeKey(e,t){let r=e.goalTaskId?.trim();if(r)return`goal:${r}`;let o=this.normalizeWorktreePrOutcome(t);return o?o.primary:t}normalizeWorktreePrOutcome(e){if(!e)return;let t=e.split(":");if(t[0]!=="worktree-pr"||t.length<5)return;let r=t[1]?.trim().toLowerCase();if(!r||!/^(?:draft-)?(?:opened|updated)$/.test(r))return;let o=t[2]?.trim()||"default-repo",i=t[3]?.trim();if(!i)return;let s=this.normalizePrIdentity(i),a=t[4]?.trim();if(!s||!a)return;let l=["worktree-pr",o.toLowerCase(),s,a].join(":"),d=`${l}:created`;if(r.endsWith("updated")){let u=t.slice(5).join(":").trim();return{primary:u?`${l}:updated:${u}`:`${l}:updated`,aliases:[d,l],blocksAliases:!1}}return{primary:d,aliases:[l],blocksAliases:!0}}normalizePrIdentity(e){let t=e.match(/#?(\d+)$/);if(t?.[1])return`#${t[1]}`;let r=e.match(/\/pull\/(\d+)(?:\b|\/|$)/);if(r?.[1])return`#${r[1]}`;let o=e.trim();return o||void 0}buildVisibleScope(e,t){let r=le(t);return r?`route:${this.digest(JSON.stringify({provider:r.provider,accountId:r.accountId,target:r.target,threadId:r.threadId}))}`:e}buildSessionAliasKeys(e,t,r){let o=this.buildVisibleScope(e,t),i="startedAt"in t?t.startedAt:t.createdAt,s=Number.isFinite(i)?`${o}:cycle:${this.digest(String(i))}`:o,a=["id"in t?t.id:void 0,"sessionId"in t?t.sessionId:void 0,t.name,C(t),t.harnessSessionId,e].map(l=>l?.trim()).filter(l=>!!l);return[...new Set(a)].map(l=>`${s}:session:${this.digest(l)}:${r}`)}getDeliveryRef(e){return D(e)??C(e)??""}digest(e){return Rm("sha256").update(e).digest("hex").slice(0,16)}normalizeRecords(e){return e?.length?e.filter(t=>t.key.trim()&&Number.isFinite(Date.parse(t.recordedAt))).slice(-this.maxCompletedKeys):[]}buildPersistedKeyMap(e){let t=new Map;for(let r of e){t.set(r.key,r);for(let o of r.linkedKeys??[])o.trim()&&t.set(o,r)}return t}getCompletedRecord(e){let t=this.completed.get(e);if(t)return t;for(let r of this.completed.values())if(r.linkedKeys?.includes(e))return r}deliveredRecords(e,t,r,o=gt){let i=new Date().toISOString(),s=this.normalizeRecords(t),a=new Set(e),d=[...s.filter(u=>!a.has(u.key)&&!(u.linkedKeys??[]).some(f=>a.has(f))),...e.map(u=>{let f=e.filter(h=>h!==u);return{key:u,linkedKeys:f.length>0?f:void 0,recordedAt:i,label:r,skipReason:o}})];return d.slice(Math.max(0,d.length-this.maxCompletedKeys))}};var Tm=2e3,xm=new Set(["1","true","yes","on"]);function Cm(){let n=process.env.OPENCLAW_CODE_AGENT_NOTIFICATION_DIAGNOSTICS?.trim().toLowerCase();return!!(n&&xm.has(n))||xr()}function Mm(n){Cm()&&process.stderr.write(`[SessionNotification] ${JSON.stringify(n)}
205
- `)}function _m(n){let e=n?.trim().split(":")??[];if(e[0]!=="worktree-pr")return;let t=e[1]?.toLowerCase();if(t==="updated"||t==="draft-updated")return"pr-updated";if(t==="opened"||t==="draft-opened")return"pr-opened"}var sr=class{constructor(e,t,r={}){this.wakeDispatcher=e;this.applyPersistedPatch=t;this.completionSummaries=new ir({maxCompletedKeys:r.maxCompletedCompletionWakeKeys}),this.notificationDedupe=new rr({maxRecords:r.maxNotificationDedupeRecords}),this.getPersistedSession=r.getPersistedSession}wakeDispatcher;applyPersistedPatch;completionSummaries;notificationDedupe;getPersistedSession;dispatch(e,t){let r=this.getDeliveryRef(e),o=this.getPersistedSession?.(r),i=this.buildNotificationDedupeKey(e,t),s=this.notificationDedupe.claim(i,o?.notificationDedupe,t.label);if(s.records&&this.applyNotificationDedupePatch(r,s.records),!s.allowed){this.logNotificationDecision({session:e,request:t,deliveryRef:r,dedupeKey:i,decision:"skip",reason:s.reason??"duplicate notification skipped",deliveryPath:"notify"}),t.hooks?.onDuplicateSkipped?.(s.reason??"duplicate notification skipped");return}let a=this.buildCompletionSummaryFact(t),l=t.completionSummaryOwner==="foreground"&&a?.required===!0,d=l?this.completionSummaries.recordVisibleDelivery(e,a,o?.completionSummaryDedupe,t.label):this.completionSummaries.decide(e,a,o?.completionSummaryDedupe);d.records&&this.applyCompletionSummaryDedupePatch(r,d.records);let u=l?this.withoutCompletionWake(t):t;if(d.required&&!d.allowed)if(this.logNotificationDecision({session:e,request:t,deliveryRef:r,dedupeKey:d.dedupeKey??d.key,outcomeKey:a?.outcomeKey,decision:l?"skip":d.explicit?"send_without_followup":"skip",reason:d.skipReason??"completion follow-up wake suppressed",deliveryPath:l?"foreground-summary":"wake",followupKind:a?.producer}),t.hooks?.onWakeSkipped?.(d.skipReason??"completion follow-up wake suppressed"),l){this.releaseNotificationDedupe(r,i);return}else if(d.explicit)u=this.withoutCompletionWake(t);else{this.releaseNotificationDedupe(r,i);return}a?.required===!0&&this.logNotificationDecision({session:e,request:u,deliveryRef:r,dedupeKey:d.dedupeKey??d.key,outcomeKey:a.outcomeKey,decision:l?"record_visible":u.completionWakeSummaryRequired===!0?"send_with_followup":"send_without_followup",reason:l?"foreground summary owns completion follow-up":void 0,deliveryPath:l?"foreground-summary":"wake",followupKind:a.producer});let f=this.buildCompletionWakePatch(u),h=!!(u.wakeMessage?.trim()||u.wakeMessageOnNotifySuccess?.trim()),k=!!(u.wakeMessage?.trim()||u.wakeMessageOnNotifyFailed?.trim()),g=!1,p=!1,y=()=>{p||(p=!0,g||(this.releaseNotificationDedupe(r,i),g=!0),this.completionSummaries.finish(d.key,!1))},w=u.shouldDispatch?()=>{let A=u.shouldDispatch?.()!==!1;return A||y(),A}:void 0,R={onNotifyStarted:()=>{this.applyDeliveryState(r,"notifying"),u.hooks?.onNotifyStarted?.()},onNotifySucceeded:()=>{g=!0,this.markNotificationDedupeDelivered(r,i,u.label),this.applyNotifyDeliveryState(r,h?"wake_pending":"idle",h?f:void 0),h||this.completionSummaries.finish(d.key,!1),u.hooks?.onNotifySucceeded?.()},onNotifyFailed:()=>{this.applyNotifyDeliveryState(r,k?"wake_pending":"failed",k?f:void 0),k||(this.completionSummaries.finish(d.key,!1),this.releaseNotificationDedupe(r,i),g=!0),u.hooks?.onNotifyFailed?.()},onWakeStarted:()=>{this.applyPersistedPatchWithCompletionWake(r,"wake_pending",f,{completionWakeIssuedAt:new Date().toISOString(),completionWakeSucceededAt:void 0,completionWakeFailedAt:void 0,completionWakeSkippedAt:void 0,completionWakeSkipReason:void 0}),u.hooks?.onWakeStarted?.()},onWakeSucceeded:()=>{g=!0,this.markNotificationDedupeDelivered(r,i,u.label),this.markCompletionSummaryDelivered(r,d.key,u.label),this.applyPersistedPatchWithCompletionWake(r,"idle",this.buildCompletionWakeSucceededPatch(f),{completionWakeSucceededAt:new Date().toISOString(),completionWakeFailedAt:void 0,completionWakeSkippedAt:void 0,completionWakeSkipReason:void 0}),this.completionSummaries.finish(d.key,!0),u.hooks?.onWakeSucceeded?.()},onWakeSkipped:A=>{if(p){u.hooks?.onWakeSkipped?.(A);return}g=!0,this.markNotificationDedupeDelivered(r,i,u.label),this.markCompletionSummaryDelivered(r,d.key,u.label,A),this.applyPersistedPatchWithCompletionWake(r,"idle",this.buildCompletionWakeSucceededPatch(f),{completionWakeSucceededAt:void 0,completionWakeFailedAt:void 0,completionWakeSkippedAt:new Date().toISOString(),completionWakeSkipReason:A}),this.completionSummaries.finish(d.key,!0),u.hooks?.onWakeSkipped?.(A)},onWakeFailed:()=>{this.applyPersistedPatchWithCompletionWake(r,"failed",f,{completionWakeFailedAt:new Date().toISOString()}),this.completionSummaries.finish(d.key,!1),this.releaseNotificationDedupe(r,i),g=!0,u.hooks?.onWakeFailed?.()}};this.wakeDispatcher.dispatchSessionNotification(e,{...u,idempotencyKey:i??u.idempotencyKey,shouldDispatch:w,hooks:R})}notifyWorktreeOutcome(e,t,r={}){let o=this.getDeliveryRef(e),i=_m(r.completionWakeOutcomeKey);o&&i&&this.applyPersistedPatch(o,{worktreeRemoteOutcome:i});let s=Dm(t,e),a=f=>Ge({sessionId:o,sessionName:e.name,outcomeLine:s,originThreadLine:Ye(e),detailLines:r.detailLines,canonicalStatusDelivered:f}),l=r.summaryWakeRequired??!0,d={required:l,producer:"worktree-pr",outcomeKey:r.completionWakeOutcomeKey??`terminal:${o}`},u=r.completionSummaryOwner!=="foreground";if(l&&!u){let f=this.getDeliveryRef(e),h=this.completionSummaries.recordVisibleDelivery(e,d,f?this.getPersistedSession?.(f)?.completionSummaryDedupe:void 0,"worktree-outcome");h.records&&this.applyCompletionSummaryDedupePatch(f,h.records)}this.dispatch(e,{label:"worktree-outcome",userMessage:s,notifyUser:"always",requireDirectUserNotification:!0,completionSummary:{...d,required:l&&u},completionWakeSummaryRequired:l&&u,completionWakeOutcomeKey:r.completionWakeOutcomeKey??`terminal:${o}`,idempotencyKey:`worktree-outcome:${r.completionWakeOutcomeKey??t}`,deferConditionalWakeUntilNextTick:!0,deferConditionalWakeMs:Tm,wakeMessageOnNotifySuccess:l&&u?a(!0):void 0,wakeMessageOnNotifyFailed:l&&u?a(!1):void 0})}dispose(){this.wakeDispatcher.dispose()}getDeliveryRef(e){return D(e)??C(e)??""}applyDeliveryState(e,t){!e||!t||this.applyPersistedPatch(e,{deliveryState:t})}applyNotifyDeliveryState(e,t,r){!e||!t||this.applyPersistedPatch(e,r?{deliveryState:t,...r}:{deliveryState:t})}applyPersistedPatchWithCompletionWake(e,t,r,o){!e||!t||this.applyPersistedPatch(e,r?{deliveryState:t,...r,...o}:{deliveryState:t})}buildCompletionWakePatch(e){if(e.completionWakeSummaryRequired===!0)return{completionWakeSummaryRequired:!0}}buildCompletionWakeSucceededPatch(e){if(e)return{completionWakeSummaryRequired:void 0}}withoutCompletionWake(e){return{...e,completionSummary:e.completionSummary?{...e.completionSummary,required:!1}:void 0,wakeMessage:void 0,wakeMessageOnNotifySuccess:void 0,wakeMessageOnNotifyFailed:void 0,completionWakeSummaryRequired:!1}}buildCompletionSummaryFact(e){if(e.completionSummary)return e.completionSummary;if(e.completionWakeSummaryRequired!==!0)return;let t=[e.wakeMessage,e.wakeMessageOnNotifySuccess,e.wakeMessageOnNotifyFailed].map(r=>r?.trim()).filter(r=>!!r);return{required:!0,producer:"legacy",outcomeKey:e.completionWakeOutcomeKey,fallbackFingerprint:t.length>0?`${e.label}
202
+ `),buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,i,{},[[this.deps.makeOpenPrButton(e.id)]])})}async handleAutoMergeStrategy(e,t,r,o,i,s,a=D(e)??e.harnessSessionId,l={merge:!0,pr:!0}){if(this.deps.isAlreadyMerged(a)||e.autoMergeResolverSessionId)return!1;let d=!1;return await this.deps.enqueueMerge(t,async()=>{if(this.deps.isAlreadyMerged(a))return;let u=this.deps.mergeBranch(t,o,i,"merge",r);if(u.success){d=this.handleAutoMergeSuccess(e,t,r,o,i,s,u);return}if(u.rebaseConflict){await this.handleInitialAutoMergeConflict(e,t,r,o,i,l,u.error,u);return}let f=ie(u.dirtyError?`❌ [${e.name}] Merge blocked: ${u.error}`:`❌ [${e.name}] Merge failed: ${u.error??"unknown error"}`,u);if(e.worktreeState==="merge_conflict_resolving"||e.worktreeLifecycle?.state==="merge_conflict_resolving"){this.handleAutoMergeRetryFailure(e,o,r,f,l);return}this.deps.dispatchSessionNotification(e,{label:"worktree-merge-error",idempotencyKey:`worktree-merge-error:${e.id}:${o}:${re(e)}`,userMessage:f})},()=>{this.deps.dispatchSessionNotification(e,{label:"worktree-merge-queued",idempotencyKey:`worktree-merge-queued:${e.id}:${o}:${re(e)}`,userMessage:`🕐 [${e.name}] Merge queued — another merge for this repo is in progress. Will notify when complete.`})}),d}async handleAutoPrStrategy(e,t,r,o,i,s={merge:!0,pr:!0}){let a=this.releaseIfRepresentedByTargetPrBranch(e,t,r,o,i);if(a)return a;if(this.updatePersistedSessionFor(e,{lifecycle:"terminal",worktreeState:"pr_in_progress"}),!(await this.deps.runAutoPr(e,i)).success){let d=this.releaseIfRepresentedByTargetPrBranch(e,t,r,o,i);if(d)return d;this.markPendingDecision(e),this.deps.dispatchSessionNotification(e,{label:"worktree-auto-pr-failed",idempotencyKey:`worktree-auto-pr-failed:${e.id}:${i}:${re(e)}`,userMessage:`⚠️ [${e.name}] Auto-PR did not complete. The worktree is preserved for an explicit merge or PR decision.`,buttons:this.getPolicyAwareWorktreeDecisionButtons(e.id,s)})}return{notificationSent:!0,worktreeRemoved:!1}}getPrStatusForUrl(e,t,r){return this.deps.getPrStatusForUrl?.(e,t,r)??Dt(e,t,r)}releaseIfRepresentedByTargetPrBranch(e,t,r,o,i){if(Ze(r).length>0)return;let s=this.resolveExistingTargetPr(e,t,o,i),a=s?.headRefName;if(!a||a===o||a===i)return;let l=this.deps.fetchRemoteBranch?this.deps.fetchRemoteBranch(t,a):Qo(t,a);if(!l||!!!((s?.state==="open"||s?.state==="merged")&&s?.baseRefName===i&&Ct(t,o,l)))return;let u=L(e)?!0:B(t,r);return u?(e.worktreePath=void 0,e.worktreePrUrl=s.url,e.worktreePrNumber=s.number,e.worktreePrTargetRepo=Ar(t,e.worktreePrTargetRepo),this.updatePersistedSessionFor(e,{worktreePath:void 0,worktreePrUrl:s.url,worktreePrNumber:s.number,worktreePrTargetRepo:e.worktreePrTargetRepo,worktreeRemoteOutcome:"pr-updated"}),H(t,o),this.markReleased(e,[`released_by_branch:${a}`]),{notificationSent:!1,worktreeRemoved:u}):(this.markPendingDecision(e,{notes:[`represented_by_branch:${a}`,"represented_worktree_cleanup_failed"]}),{notificationSent:!1,worktreeRemoved:!1})}};import{existsSync as sm,statSync as am,writeFileSync as lm}from"fs";import{randomUUID as wc}from"crypto";function ha(n){return n==="plan-approve"||n==="plan-request-changes"||n==="plan-reject"}var Gn=class{constructor(e,t){this.onChange=e;this.retentionMs=t}onChange;retentionMs;tokens=new Map;afterChange;replaceAll(e){this.tokens.clear();for(let t of e)this.tokens.set(t.id,t)}clear(){this.tokens.clear(),this.notifyChanged()}listForPersistence(){return[...this.tokens.values()]}createActionToken(e,t,r={}){let o={id:wc(),sessionId:e,kind:t,createdAt:Date.now(),...r};return this.tokens.set(o.id,o),this.notifyChanged(),o}getActionToken(e){let t=this.tokens.get(e);if(t){if(t.expiresAt!=null&&t.expiresAt<=Date.now()){this.tokens.delete(e),this.notifyChanged();return}return t}}listActiveActionTokens(e){let t=[];for(let r of[...this.tokens.keys()]){let o=this.getActionToken(r);!o||o.consumedAt!=null||e&&o.kind!==e||t.push(o)}return t}consumeActionToken(e){let t=this.getActionToken(e);if(!(!t||t.consumedAt!=null))return t.consumedAt=Date.now(),this.notifyChanged(),t}consumeQuestionAnswerTokens(e,t,r){let o=[],i=Date.now();for(let s of this.tokens.values())s.sessionId!==e||s.kind!=="question-answer"||s.pendingInputRequestId!==t||r!=null&&s.pendingInputQuestionId!==r||s.consumedAt!=null||(s.consumedAt=i,o.push(s));return o.length>0&&this.notifyChanged(),o}consumePlanDecisionTokens(e,t){let r=[],o=Date.now();for(let i of this.tokens.values())i.sessionId!==e||!ha(i.kind)||i.planDecisionVersion!==t||i.consumedAt!=null||(i.consumedAt=o,r.push(i));return r.length>0&&this.notifyChanged(),r}deleteActionTokensForSession(e){let t=!1;for(let[r,o]of this.tokens)o.sessionId===e&&(this.tokens.delete(r),t=!0);t&&this.notifyChanged()}deleteActionTokensForSessionByKind(e,t){let r=!1;for(let[o,i]of this.tokens)i.sessionId===e&&i.kind===t&&(this.tokens.delete(o),r=!0);r&&this.notifyChanged()}deletePlanDecisionTokensForSession(e,t){let r=!1;for(let[o,i]of this.tokens)i.sessionId!==e||!ha(i.kind)||t!=null&&i.planDecisionVersion===t||(this.tokens.delete(o),r=!0);r&&this.notifyChanged()}purgeExpiredActionTokens(e=Date.now()){let t=!1;for(let[r,o]of this.tokens){let i=o.expiresAt!=null&&o.expiresAt<=e,s=o.consumedAt!=null&&e-o.consumedAt>=this.retentionMs;(i||s)&&(this.tokens.delete(r),t=!0)}return t&&this.notifyChanged(),t}nextExpiryAt(){let e;for(let t of this.tokens.values()){let r=[t.expiresAt,t.consumedAt!=null?t.consumedAt+this.retentionMs:void 0].filter(o=>o!=null&&Number.isFinite(o));for(let o of r)(e==null||o<e)&&(e=o)}return e}setAfterChangeListener(e){this.afterChange=e}notifyChanged(){this.onChange(),this.afterChange?.()}};var jn=class{constructor(e){this.indexes=e}indexes;hasRecordedSession(e){return this.indexes.idIndex.has(e)}getLatestPersistedByName(e){let t,r=Number.NEGATIVE_INFINITY,o=Number.NEGATIVE_INFINITY,i=Number.NEGATIVE_INFINITY,s=0;for(let a of this.indexes.persisted.values()){if(a.name!==e){s++;continue}let l=a.createdAt??Number.NEGATIVE_INFINITY,d=a.completedAt??Number.NEGATIVE_INFINITY;(l>r||l===r&&d>o||l===r&&d===o&&s>i)&&(t=a,r=l,o=d,i=s),s++}return t}resolveBackendConversationId(e,t){if(t)return t;let r=this.indexes.idIndex.get(e);if(r){let s=this.indexes.persisted.get(r);return(s?C(s):void 0)??r}let o=this.getLatestPersistedByName(e);if(o)return C(o)??o.harnessSessionId;let i=this.indexes.backendIdIndex.get(e);if(i){let s=this.indexes.persisted.get(i);return(s?C(s):void 0)??i}if(this.indexes.persisted.has(e)){let s=this.indexes.persisted.get(e);return s?C(s)??e:e}if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e))return e}resolveHarnessSessionId(e,t){return this.resolveBackendConversationId(e,t)}getPersistedSession(e){let t=this.indexes.idIndex.get(e);if(t)return this.indexes.persisted.get(t);let r=this.getLatestPersistedByName(e);if(r)return r;let o=this.indexes.backendIdIndex.get(e);return o?this.indexes.persisted.get(o):this.indexes.persisted.get(e)}listPersistedSessions(){return[...this.indexes.persisted.values()].sort((e,t)=>(t.completedAt??0)-(e.completedAt??0))}};import{existsSync as Ta,mkdirSync as Yc,readFileSync as Jc,readdirSync as Xc,renameSync as xa,statSync as Ca,unlinkSync as Ma,writeFileSync as _a}from"fs";import{tmpdir as Zc}from"os";import{dirname as em,join as Da}from"path";import{homedir as bc}from"node:os";import{join as Rc}from"node:path";function zn(n){let e=n.OPENCLAW_HOME?.trim();if(e)return e;let t=n.HOME?.trim()||bc();return Rc(t,".openclaw")}var Hn=7,Ac=new Set(["running","completed","failed","killed"]),Ic=new Set(["queued","running","waiting","blocked","succeeded","failed","cancelled","lost"]);function ae(n){return!!n&&typeof n=="object"}function je(n,e=""){return typeof n=="string"&&n.trim().length>0?n:e}function v(n){return typeof n=="string"&&n.trim().length>0?n:void 0}function V(n){return typeof n=="number"&&Number.isFinite(n)?n:void 0}function Tc(n){if(!ae(n))return;let e=v(n.flowId),t=V(n.revision);if(!e||t===void 0)return;let r=typeof n.status=="string"&&Ic.has(n.status)?n.status:void 0;return{flowId:e,revision:t,...r?{status:r}:{}}}function ya(n){return typeof n=="string"&&ns.has(n)?n:void 0}function Mo(n){return n==="default"||n==="plan"||n==="bypassPermissions"?n:void 0}function xc(n){return n==="never"||n==="on-request"?"never":void 0}function Sa(n){return n==="approve"||n==="ask"||n==="delegate"?n:void 0}function Cc(n){if(n==="plan-mode"||n==="codex-first-turn-plan"||n==="soft-plan")return"plan-mode"}function ka(n){return typeof n=="string"&&Sn.has(n)?n:void 0}function _o(n){return typeof n=="string"&&ts.has(n)?n:void 0}function va(n){return n==="github"||n==="unsupported"?n:void 0}function Mc(n){return n==="stored"||n==="seeded"||n==="unknown"?n:void 0}function _c(n){return n==="user"||n==="idle-timeout"||n==="startup-timeout"||n==="shutdown"||n==="done"||n==="unknown"?n:void 0}function Pa(n){return n==="starting"||n==="active"||n==="awaiting_plan_decision"||n==="awaiting_user_input"||n==="awaiting_worktree_decision"||n==="suspended"||n==="terminal"?n:void 0}function Dc(n){return n==="not_required"||n==="pending"||n==="approved"||n==="changes_requested"||n==="rejected"?n:void 0}function $c(n){return n==="none"||n==="provisioned"||n==="pending_decision"||n==="merge_conflict_resolving"||n==="merge_in_progress"||n==="pr_in_progress"||n==="merged"||n==="released"||n==="pr_open"||n==="dismissed"||n==="cleanup_failed"?n:void 0}function Ec(n){return n==="none"||n==="provisioned"||n==="pending_decision"||n==="merge_conflict_resolving"||n==="pr_open"||n==="merged"||n==="released"||n==="dismissed"||n==="no_change"||n==="cleanup_failed"?n:void 0}function wa(n){return n==="live"||n==="stopped"?n:void 0}function Nc(n){if(!ae(n)||n.reason!=="persisted-running-without-runtime")return;let e=v(n.recoveredAt);if(!e||!Number.isFinite(Date.parse(e)))return;let t=n.normalizedStatus==="killed"?"killed":void 0;if(t)return{reason:"persisted-running-without-runtime",recoveredAt:e,rawStatus:v(n.rawStatus),rawLifecycle:v(n.rawLifecycle),rawRuntimeState:v(n.rawRuntimeState),rawResumable:typeof n.rawResumable=="boolean"?n.rawResumable:void 0,rawCompletedAt:V(n.rawCompletedAt),rawOutputPath:v(n.rawOutputPath),normalizedStatus:t,normalizedLifecycle:Pa(n.normalizedLifecycle),normalizedRuntimeState:wa(n.normalizedRuntimeState)}}function Oc(n){return{reason:"persisted-running-without-runtime",recoveredAt:new Date().toISOString(),rawStatus:v(n.status),rawLifecycle:v(n.lifecycle),rawRuntimeState:v(n.runtimeState),rawResumable:typeof n.resumable=="boolean"?n.resumable:void 0,rawCompletedAt:V(n.completedAt),rawOutputPath:v(n.outputPath),normalizedStatus:"killed",normalizedLifecycle:"suspended",normalizedRuntimeState:"stopped"}}function Wc(n){return n==="not_sent"||n==="sending"||n==="delivered"||n==="fallback_delivered"||n==="failed"?n:void 0}function Fc(n){return n==="direct-telegram"?"direct-message":n==="none"||n==="direct-message"||n==="wake-only"?n:void 0}function Lc(n){return n==="none"||n==="canonical_buttons"||n==="explicit_fallback_text"?n:void 0}function Bc(n){return n==="idle"||n==="notifying"||n==="wake_pending"||n==="failed"?n:void 0}function Kc(n){return n==="in_flight"||n==="delivered"?n:void 0}function qc(n){if(!Array.isArray(n))return;let e=n.map(t=>{if(!ae(t))return;let r=v(t.key),o=Kc(t.status),i=v(t.recordedAt);if(!(!r||!o||!i||!Number.isFinite(Date.parse(i))))return{key:r,status:o,recordedAt:i,label:v(t.label)}}).filter(t=>!!t);return e.length>0?e.slice(-64):void 0}function Vc(n){if(!Array.isArray(n))return;let e=n.map(t=>{if(!ae(t))return;let r=v(t.key),o=v(t.recordedAt);if(!r||!o||!Number.isFinite(Date.parse(o)))return;let i=Array.isArray(t.linkedKeys)?[...new Set(t.linkedKeys.map(v).filter(s=>!!(s&&s!==r)))]:void 0;return{key:r,linkedKeys:i&&i.length>0?i:void 0,recordedAt:o,label:v(t.label),skipReason:v(t.skipReason)}}).filter(t=>!!t);return e.length>0?e.slice(-1024):void 0}function Uc(n){return n==="awaiting_plan_output"||n==="awaiting_approval"||n==="approved_then_implemented"||n==="implemented_without_required_approval"||n==="not_plan_gated"?n:void 0}function Gc(n){return n==="plan-approve"||n==="plan-request-changes"||n==="plan-reject"||n==="plan-offer-start"||n==="plan-offer-dismiss"||n==="repo-policy-set"||n==="worktree-merge"||n==="worktree-create-pr"||n==="worktree-update-pr"||n==="worktree-view-pr"||n==="worktree-decide-later"||n==="worktree-dismiss"||n==="session-resume"||n==="session-restart"||n==="view-output"||n==="question-answer"?n:void 0}function ba(n){if(!ae(n))return;let e=v(n.provider),t=v(n.accountId),r=v(n.target),o=v(n.threadId),i=v(n.sessionKey);if(!(!e||!r))return{provider:e,accountId:t,target:r,threadId:o,sessionKey:i}}function jc(n,e,t){if(ae(n)){let r=v(n.kind),o=v(n.conversationId);if(o&&(r==="claude-code"||r==="codex-app-server"||r==="opencode-server"))return{kind:r,conversationId:o,runId:v(n.runId),worktreeId:v(n.worktreeId),worktreePath:v(n.worktreePath)}}if(e==="claude-code")return{kind:"claude-code",conversationId:t}}function zc(n){if(!ae(n))return;let e=Ec(n.state),t=v(n.updatedAt);if(!e||!t)return;let r=v(n.resolutionSource);return{state:e,updatedAt:t,resolvedAt:v(n.resolvedAt),resolutionSource:r==="agent_merge"||r==="agent_pr"||r==="strategy_no_change"||r==="lifecycle_resolver"||r==="dismiss"||r==="maintenance"?r:void 0,baseBranch:v(n.baseBranch),targetRepo:v(n.targetRepo),pushRemote:v(n.pushRemote),notes:Array.isArray(n.notes)?n.notes.filter(o=>typeof o=="string"&&o.length>0):void 0}}function Hc(n){let e=new Date(0).toISOString(),t=v(n.worktreeMergedAt)??v(n.worktreeDismissedAt)??v(n.pendingWorktreeDecisionSince)??e;if(n.worktreeMerged===!0||n.worktreeDisposition==="merged")return{state:"merged",updatedAt:t,resolvedAt:v(n.worktreeMergedAt)??t,resolutionSource:"agent_merge",baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.worktreeDisposition==="dismissed")return{state:"dismissed",updatedAt:t,resolvedAt:v(n.worktreeDismissedAt)??t,resolutionSource:"dismiss",baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.worktreeDisposition==="no-change-cleaned")return{state:"no_change",updatedAt:t,resolvedAt:t,resolutionSource:"strategy_no_change",baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.worktreeDisposition==="pr-opened"||n.worktreeState==="pr_open")return{state:"pr_open",updatedAt:t,baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.pendingWorktreeDecisionSince||n.worktreeState==="pending_decision")return{state:"pending_decision",updatedAt:t,baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(n.worktreeState==="merge_conflict_resolving")return{state:"merge_conflict_resolving",updatedAt:t,baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)};if(v(n.worktreePath)||v(n.worktreeBranch))return{state:"provisioned",updatedAt:t,baseBranch:v(n.worktreeBaseBranch),targetRepo:v(n.worktreePrTargetRepo),pushRemote:v(n.worktreePushRemote)}}function Qc(n){if(typeof n=="string"&&Ac.has(n))return n==="running"?"killed":n}function Ra(n){if(!ae(n))return;let e=je(n.harnessSessionId);if(!e)return;let t=Qc(n.status);if(!t)return;let r=n.status==="running",o=v(n.worktreePath),i=v(n.worktreeBranch),s=v(n.originChannel),a=typeof n.originThreadId=="string"||typeof n.originThreadId=="number"?n.originThreadId:void 0,l=v(n.originSessionKey),d=ba(n.route);if(!d)return;let u=Z({route:d,originChannel:s,originThreadId:a,originSessionKey:l});if(!u||o&&!i)return;let f=v(n.harness),g=jc(n.backendRef,f,e),k=zc(n.worktreeLifecycle)??Hc(n),h=v(n.completionWakeSucceededAt),p=v(n.completionWakeSkippedAt),y=n.completionWakeSummaryRequired===!0&&!p?!0:void 0;return{sessionId:v(n.sessionId),harnessSessionId:e,backendRef:g,name:je(n.name,e),prompt:je(n.prompt),workdir:je(n.workdir,"(unknown)"),model:v(n.model),reasoningEffort:ya(n.reasoningEffort),fastMode:n.fastMode===!0?!0:void 0,createdAt:V(n.createdAt),completedAt:V(n.completedAt),status:t,lifecycle:r?"suspended":Pa(n.lifecycle),approvalState:Dc(n.approvalState),worktreeState:$c(n.worktreeState),runtimeState:r?"stopped":wa(n.runtimeState),runtimeRecovery:r?Oc(n):Nc(n.runtimeRecovery),taskFlowMirror:Tc(n.taskFlowMirror),deliveryState:Bc(n.deliveryState),notificationDedupe:qc(n.notificationDedupe),completionSummaryDedupe:Vc(n.completionSummaryDedupe),completionWakeIssuedAt:v(n.completionWakeIssuedAt),completionWakeSucceededAt:h,completionWakeFailedAt:v(n.completionWakeFailedAt),completionWakeSkippedAt:p,completionWakeSkipReason:v(n.completionWakeSkipReason),completionWakeSummaryRequired:y,killReason:_c(n.killReason),costUsd:typeof n.costUsd=="number"&&Number.isFinite(n.costUsd)?n.costUsd:0,originAgentId:v(n.originAgentId),originChannel:s,originThreadId:a,originSessionKey:l,route:u,outputPath:v(n.outputPath),harness:f,resumedFromSessionName:v(n.resumedFromSessionName),goalTaskId:v(n.goalTaskId),requestedPermissionMode:Mo(n.requestedPermissionMode),currentPermissionMode:Mo(n.currentPermissionMode),approvalExecutionState:Uc(n.approvalExecutionState),approvalRationale:v(n.approvalRationale),planModeApproved:n.planModeApproved===!0,pendingPlanApproval:n.pendingPlanApproval===!0,planApprovalContext:Cc(n.planApprovalContext),planDecisionVersion:V(n.planDecisionVersion),actionablePlanDecisionVersion:V(n.actionablePlanDecisionVersion),canonicalPlanPromptVersion:V(n.canonicalPlanPromptVersion),approvalPromptRequiredVersion:V(n.approvalPromptRequiredVersion),approvalPromptVersion:V(n.approvalPromptVersion),approvalPromptStatus:Wc(n.approvalPromptStatus),approvalPromptTransport:Fc(n.approvalPromptTransport),approvalPromptMessageKind:Lc(n.approvalPromptMessageKind),approvalPromptLastAttemptAt:v(n.approvalPromptLastAttemptAt),approvalPromptDeliveredAt:v(n.approvalPromptDeliveredAt),approvalPromptFailedAt:v(n.approvalPromptFailedAt),planApproval:Sa(n.planApproval),codexApprovalPolicy:xc(n.codexApprovalPolicy),worktreePath:o,worktreeBranch:i,worktreeStrategy:ka(n.worktreeStrategy),repoIntegrationPolicy:_o(n.repoIntegrationPolicy),repoIntegrationPolicySource:Mc(n.repoIntegrationPolicySource),repoProvider:va(n.repoProvider),worktreeMerged:typeof n.worktreeMerged=="boolean"?n.worktreeMerged:void 0,worktreeMergedAt:v(n.worktreeMergedAt),worktreePrUrl:v(n.worktreePrUrl),worktreePrNumber:V(n.worktreePrNumber),pendingWorktreeDecisionSince:v(n.pendingWorktreeDecisionSince),lastWorktreeReminderAt:v(n.lastWorktreeReminderAt),worktreeBaseBranch:v(n.worktreeBaseBranch),worktreeParentBranch:v(n.worktreeParentBranch),worktreePrTargetRepo:v(n.worktreePrTargetRepo),autoMergeParentSessionId:v(n.autoMergeParentSessionId),autoMergeConflictResolutionAttemptCount:V(n.autoMergeConflictResolutionAttemptCount),autoMergeResolverSessionId:v(n.autoMergeResolverSessionId),worktreePushRemote:v(n.worktreePushRemote),worktreeDecisionSnoozedUntil:v(n.worktreeDecisionSnoozedUntil),worktreeDisposition:n.worktreeDisposition==="active"||n.worktreeDisposition==="pr-opened"||n.worktreeDisposition==="merged"||n.worktreeDisposition==="dismissed"||n.worktreeDisposition==="no-change-cleaned"?n.worktreeDisposition:void 0,worktreeRemoteOutcome:n.worktreeRemoteOutcome==="pr-opened"||n.worktreeRemoteOutcome==="pr-updated"?n.worktreeRemoteOutcome:void 0,worktreeDismissedAt:v(n.worktreeDismissedAt),worktreeLifecycle:k,resumable:r?!0:n.resumable===!0}}function Aa(n){if(!ae(n))return;let e=v(n.key),t=v(n.repoRoot),r=_o(n.policy),o=va(n.provider)??"unsupported",i=v(n.createdAt),s=v(n.updatedAt),a=n.source==="seeded"?"seeded":"stored";if(!(!e||!t||!r||!i||!s)&&!(!Number.isFinite(Date.parse(i))||!Number.isFinite(Date.parse(s))))return{key:e,policy:r,repoRoot:t,remoteUrl:v(n.remoteUrl),provider:o,createdAt:i,updatedAt:s,source:a}}function Ia(n){if(!ae(n))return;let e=Gc(n.kind),t=je(n.id),r=je(n.sessionId),o=V(n.createdAt);if(!(!t||!r||!e||o==null))return{id:t,sessionId:r,kind:e,createdAt:o,planDecisionVersion:V(n.planDecisionVersion),expiresAt:V(n.expiresAt),consumedAt:V(n.consumedAt),optionIndex:V(n.optionIndex),pendingInputRequestId:v(n.pendingInputRequestId),pendingInputQuestionId:v(n.pendingInputQuestionId),label:v(n.label),targetUrl:v(n.targetUrl),route:ba(n.route),launchName:v(n.launchName),launchPrompt:v(n.launchPrompt),launchWorkdir:v(n.launchWorkdir),launchModel:v(n.launchModel),launchReasoningEffort:ya(n.launchReasoningEffort),launchFastMode:n.launchFastMode===!0?!0:void 0,launchSystemPrompt:v(n.launchSystemPrompt),launchAllowedTools:Array.isArray(n.launchAllowedTools)?n.launchAllowedTools.filter(i=>typeof i=="string"):void 0,launchResumeSessionId:v(n.launchResumeSessionId),launchResumedFromSessionName:v(n.launchResumedFromSessionName),launchResumeWorktreeFrom:v(n.launchResumeWorktreeFrom),launchSessionIdOverride:v(n.launchSessionIdOverride),launchClearedPersistedCodexResume:n.launchClearedPersistedCodexResume===!0?!0:void 0,launchForkSession:typeof n.launchForkSession=="boolean"?n.launchForkSession:void 0,launchForceNewSession:typeof n.launchForceNewSession=="boolean"?n.launchForceNewSession:void 0,launchPermissionMode:Mo(n.launchPermissionMode),launchPlanApproval:Sa(n.launchPlanApproval),launchHarness:v(n.launchHarness),launchWorktreeStrategy:ka(n.launchWorktreeStrategy),launchWorktreeBaseBranch:v(n.launchWorktreeBaseBranch),launchWorktreePrTargetRepo:v(n.launchWorktreePrTargetRepo),launchOriginAgentId:v(n.launchOriginAgentId),repoPolicy:_o(n.repoPolicy),repoPolicyWorkdir:v(n.repoPolicyWorkdir)}}function Qn(n){if(!n.backendRef?.kind||!n.backendRef.conversationId)throw new Error(`Persisted session ${n.harnessSessionId} is missing required backend ref metadata.`);if(!n.route?.provider||!n.route.target)throw new Error(`Persisted session ${n.harnessSessionId} is missing required route metadata.`);if(n.worktreePath&&!n.worktreeBranch)throw new Error(`Persisted session ${n.harnessSessionId} is missing required worktreeBranch metadata.`)}function ft(n){return!!n&&typeof n=="object"}function Do(n){return n instanceof Error?n.message:String(n)}function tm(n,e){JSON.stringify({component:"SessionStore",event:n,at:new Date().toISOString(),...e})}function nm(n){return ft(n)?{backendRefKind:typeof n.kind=="string"?n.kind:void 0,hasBackendConversationId:typeof n.conversationId=="string"&&n.conversationId.length>0,hasBackendRunId:typeof n.runId=="string"&&n.runId.length>0,hasBackendWorktreeId:typeof n.worktreeId=="string"&&n.worktreeId.length>0,hasBackendWorktreePath:typeof n.worktreePath=="string"&&n.worktreePath.length>0}:{}}function $a(n,e,t=Date.now()){let r=`${n}.${e}-${t}`;for(let o=0;o<100;o+=1){let i=o===0?"":`-${o}`,s=`${r}${i}.json`;if(!Ta(s))return s}}function $o(){let n=Zc();return Xc(n).filter(e=>e.startsWith("openclaw-agent-")&&e.endsWith(".txt")).map(e=>Da(n,e))}function Ea(n){let e=n.OPENCLAW_CODE_AGENT_SESSIONS_PATH?.trim();return e||Da(zn(n),"code-agent-sessions.json")}function Na(n,e,t,r=[]){try{Yc(em(n),{recursive:!0});let o=n+".tmp";_a(o,JSON.stringify({schemaVersion:Hn,sessions:e,actionTokens:t,repoPolicies:r},null,2),"utf-8"),xa(o,n)}catch(o){`${Do(o)}`}}function rm(n,e){try{if(!Ta(n))return!1;let t=$a(n,"legacy");return t?(xa(n,t),`${e}${t}`,!0):!1}catch(t){return`${Do(t)}`,!1}}var om={archiveLegacySessionIndex:rm};function im(n,e){try{if(e.length===0)return;let t=$a(n,"codex-sdk-legacy");if(!t)return;_a(t,JSON.stringify(e,null,2),"utf-8"),`${e.length}${t}`}catch(t){`${Do(t)}`}}function Oa(n,e,t=[]){try{let r=new Set(t);for(let o of $o())if(!r.has(o))try{let i=Ca(o).mtimeMs;n-i>e&&Ma(o)}catch{}}catch{}}function Wa(n,e,t=[]){try{let r=new Set(t),o;for(let i of $o())if(!r.has(i))try{let s=Ca(i).mtimeMs+e;if(s<=n)return n;o=o==null?s:Math.min(o,s)}catch{}return o}catch{return}}function Fa(n){try{let e=new Set(n);for(let t of $o())if(!e.has(t))try{Ma(t)}catch{}}catch{}}function La(n){let{indexPath:e,clearAll:t,indexPersistedEntry:r,setActionToken:o,setRepoPolicy:i,purgeExpiredActionTokens:s,saveIndex:a}=n,l=d=>om.archiveLegacySessionIndex(e,d)?(t(),!0):!1;try{let d=Jc(e,"utf-8"),u=JSON.parse(d);if(Array.isArray(u)){if(!l("legacy array store"))return;a();return}if(!ft(u)||u.schemaVersion!==Hn&&u.schemaVersion!==6&&u.schemaVersion!==4){if(!l(`schema mismatch (expected v${Hn})`))return;a();return}let f=(R,m)=>{if(!Object.prototype.hasOwnProperty.call(u,R))return[];let w=u[R];if(Array.isArray(w))return w;l(m)&&a()},g=f("sessions","invalid sessions collection");if(g===void 0)return;let k=[],h=[],p=!1;for(let R of g){if(ft(R)&&R.harness==="codex"){let w=ft(R.backendRef)?R.backendRef:void 0;if((typeof w?.kind=="string"?w.kind:void 0)!=="codex-app-server"){k.push(R);continue}}let m=Ra(R);if(!m){if(!l("invalid v4 session entry"))return;a();return}ft(R)&&R.status==="running"&&(p=!0,tm("session.recovered_from_running_persisted_row",{sessionId:typeof R.sessionId=="string"?R.sessionId:void 0,hasHarnessSessionId:typeof R.harnessSessionId=="string"&&R.harnessSessionId.length>0,...nm(R.backendRef),rawStatus:R.status,rawLifecycle:R.lifecycle,rawRuntimeState:R.runtimeState,normalizedStatus:m.status,normalizedLifecycle:m.lifecycle,normalizedRuntimeState:m.runtimeState,reason:m.runtimeRecovery?.reason})),h.push(m)}k.length>0&&im(e,k);let y=f("actionTokens","invalid action token collection");if(y===void 0)return;let P=[];for(let R of y){let m=Ia(R);if(!m){if(!l("invalid v4 action token"))return;a();return}P.push(m)}let b=f("repoPolicies","invalid repo policy collection");if(b===void 0)return;let A=[],I=!1;for(let R of b){let m=Aa(R);if(!m){I=!0;continue}A.push(m)}for(let R of h)r(R);for(let R of P)o(R);for(let R of A)i(R);(k.length>0||p)&&a(),I&&a(),s()}catch(d){if(d.code==="ENOENT"||!l("corrupt or unreadable"))return;a()}}var dm=new Set(["completed","failed","killed"]),Eo=1440*60*1e3;function um(n){return n instanceof Error?n.message:String(n)}var pm={statSync:am};function cm(n){try{return pm.statSync(n).isDirectory()}catch(e){let t=e.code;return t!=="ENOENT"&&t!=="ENOTDIR"}}var Yn=class{persisted=new Map;repoPolicies=new Map;idIndex=new Map;nameIndex=new Map;backendIdIndex=new Map;actionTokens;actionTokenStore;indexPath;queries;constructor(e={}){let t=e.env??process.env;this.indexPath=e.indexPath??Ea(t),this.actionTokenStore=new Gn(()=>this.saveIndex(),Eo),this.actionTokens=this.actionTokenStore.tokens,this.queries=new jn({persisted:this.persisted,idIndex:this.idIndex,nameIndex:this.nameIndex,backendIdIndex:this.backendIdIndex}),t.OPENCLAW_DEBUG_SESSION_STORE==="1"&&`${this.indexPath}`,this.loadIndex()}loadIndex(){La({indexPath:this.indexPath,clearAll:()=>{this.persisted.clear(),this.repoPolicies.clear(),this.idIndex.clear(),this.nameIndex.clear(),this.backendIdIndex.clear(),this.actionTokenStore.clear()},indexPersistedEntry:e=>this.indexPersistedEntry(e),setActionToken:e=>{this.actionTokens.set(e.id,e)},setRepoPolicy:e=>{this.repoPolicies.set(e.key,e)},purgeExpiredActionTokens:()=>this.actionTokenStore.purgeExpiredActionTokens(),saveIndex:()=>this.saveIndex()})}saveIndex(){Na(this.indexPath,[...this.persisted.values()],this.actionTokenStore.listForPersistence(),[...this.repoPolicies.values()])}assertPersistedEntry(e){Qn(e)}getEntryStorageKey(e){return e.harnessSessionId}buildPersistedBackendRef(e){let t=jo(e),r=t==="codex"?"codex-app-server":t==="opencode"?"opencode-server":"claude-code";return e.backendRef??{kind:e.backendKind??r,conversationId:e.harnessSessionId}}getSessionApprovalSnapshot(e){if(typeof e.approvalSnapshot=="function")return e.approvalSnapshot();let t=typeof e.controlStateSnapshot=="function"?e.controlStateSnapshot():{planModeApproved:!1};return{requestedPermissionMode:e.requestedPermissionMode,currentPermissionMode:e.currentPermissionMode,approvalExecutionState:e.approvalExecutionState,approvalRationale:e.approvalRationale,planModeApproved:t.planModeApproved,pendingPlanApproval:e.pendingPlanApproval,planApprovalContext:e.planApprovalContext,planDecisionVersion:e.planDecisionVersion,actionablePlanDecisionVersion:e.actionablePlanDecisionVersion,canonicalPlanPromptVersion:e.canonicalPlanPromptVersion,approvalPromptRequiredVersion:e.approvalPromptRequiredVersion,approvalPromptVersion:e.approvalPromptVersion,approvalPromptStatus:e.approvalPromptStatus,approvalPromptTransport:e.approvalPromptTransport,approvalPromptMessageKind:e.approvalPromptMessageKind,approvalPromptLastAttemptAt:e.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:e.approvalPromptDeliveredAt,approvalPromptFailedAt:e.approvalPromptFailedAt,planApproval:e.planApproval,codexApprovalPolicy:e.codexApprovalPolicy}}getSessionRoutingSnapshot(e){return typeof e.routingSnapshot=="function"?e.routingSnapshot():{route:e.route,originAgentId:e.originAgentId,originChannel:e.originChannel,originThreadId:e.originThreadId,originSessionKey:e.originSessionKey}}getSessionWorktreeSnapshot(e){return typeof e.worktreeSnapshot=="function"?e.worktreeSnapshot():{worktreePath:e.worktreePath,worktreeBranch:e.worktreeBranch,worktreeStrategy:e.worktreeStrategy,repoIntegrationPolicy:e.repoIntegrationPolicy,repoIntegrationPolicySource:e.repoIntegrationPolicySource,repoProvider:e.repoProvider,worktreeBaseBranch:e.worktreeBaseBranch,worktreeParentBranch:e.worktreeParentBranch,worktreePrTargetRepo:e.worktreePrTargetRepo,autoMergeParentSessionId:e.autoMergeParentSessionId,autoMergeConflictResolutionAttemptCount:e.autoMergeConflictResolutionAttemptCount,autoMergeResolverSessionId:e.autoMergeResolverSessionId,worktreeLifecycle:e.worktreeLifecycle}}indexPersistedEntry(e){let t=this.getEntryStorageKey(e);if(e.sessionId){let o=this.idIndex.get(e.sessionId);if(o&&o!==t){let i=this.persisted.get(o);i&&this.removePersistedIndexes(i)}}this.persisted.set(t,e),e.sessionId&&this.idIndex.set(e.sessionId,t),e.name&&this.nameIndex.set(e.name,t);let r=C(e);r&&this.backendIdIndex.set(r,t)}removePersistedIndexes(e){let t=this.getEntryStorageKey(e);this.persisted.delete(t);for(let[r,o]of this.idIndex)o===t&&this.idIndex.delete(r);for(let[r,o]of this.nameIndex)o===t&&this.nameIndex.delete(r);for(let[r,o]of this.backendIdIndex)o===t&&this.backendIdIndex.delete(r)}markRunning(e){if(!e.harnessSessionId)return;let t=this.getSessionApprovalSnapshot(e),r=this.getSessionRoutingSnapshot(e),o=this.getSessionWorktreeSnapshot(e),i=Z({route:r.route,originChannel:r.originChannel,originThreadId:r.originThreadId,originSessionKey:r.originSessionKey});if(!i)throw new Error(`Cannot persist running session ${e.id}: canonical lifecycle route is missing.`);let s={sessionId:e.id,harnessSessionId:e.harnessSessionId,backendRef:this.buildPersistedBackendRef(e),name:e.name,prompt:e.prompt,workdir:e.originalWorkdir??e.workdir,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,createdAt:e.startedAt,status:"running",lifecycle:e.lifecycle,approvalState:e.approvalState,worktreeState:e.worktreeState,runtimeState:e.runtimeState,taskFlowMirror:e.taskFlowMirror,deliveryState:e.deliveryState,notificationDedupe:this.getExistingNotificationDedupe(e),completionSummaryDedupe:this.getExistingCompletionSummaryDedupe(e),costUsd:0,originAgentId:r.originAgentId,originChannel:r.originChannel,originThreadId:r.originThreadId,originSessionKey:r.originSessionKey,route:i,outputPath:ve(e.id),harness:e.harnessName,resumedFromSessionName:e.resumedFromSessionName,requestedPermissionMode:t.requestedPermissionMode,currentPermissionMode:t.currentPermissionMode,approvalExecutionState:t.approvalExecutionState,approvalRationale:t.approvalRationale,planModeApproved:t.planModeApproved,pendingPlanApproval:t.pendingPlanApproval,planApprovalContext:t.planApprovalContext,planDecisionVersion:t.planDecisionVersion,actionablePlanDecisionVersion:t.actionablePlanDecisionVersion,canonicalPlanPromptVersion:t.canonicalPlanPromptVersion,approvalPromptRequiredVersion:t.approvalPromptRequiredVersion,approvalPromptVersion:t.approvalPromptVersion,approvalPromptStatus:t.approvalPromptStatus,approvalPromptTransport:t.approvalPromptTransport,approvalPromptMessageKind:t.approvalPromptMessageKind,approvalPromptLastAttemptAt:t.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:t.approvalPromptDeliveredAt,approvalPromptFailedAt:t.approvalPromptFailedAt,planApproval:t.planApproval,codexApprovalPolicy:t.codexApprovalPolicy,worktreePath:o.worktreePath,worktreeBranch:o.worktreeBranch,worktreeStrategy:o.worktreeStrategy,repoIntegrationPolicy:o.repoIntegrationPolicy,repoIntegrationPolicySource:o.repoIntegrationPolicySource,repoProvider:o.repoProvider,worktreeBaseBranch:o.worktreeBaseBranch,worktreeParentBranch:o.worktreeParentBranch,worktreePrTargetRepo:o.worktreePrTargetRepo,autoMergeParentSessionId:o.autoMergeParentSessionId,autoMergeConflictResolutionAttemptCount:o.autoMergeConflictResolutionAttemptCount,autoMergeResolverSessionId:o.autoMergeResolverSessionId,worktreeLifecycle:o.worktreeLifecycle,resumable:e.isExplicitlyResumable};Qn(s),this.indexPersistedEntry(s),this.saveIndex()}hasRecordedSession(e){return this.queries.hasRecordedSession(e)}persistTerminal(e){if(!e.harnessSessionId)return;let t=this.getSessionApprovalSnapshot(e),r=this.getSessionRoutingSnapshot(e),o=this.getSessionWorktreeSnapshot(e),i=Z({route:r.route,originChannel:r.originChannel,originThreadId:r.originThreadId,originSessionKey:r.originSessionKey});if(!i)throw new Error(`Cannot persist terminal session ${e.id}: canonical lifecycle route is missing.`);let s;try{let l=ve(e.id);if(sm(l))s=l;else{let d=e.getOutput().join(`
203
+ `);d.length>0&&(lm(l,d,"utf-8"),s=l)}}catch(l){`${e.id}${um(l)}`}let a={sessionId:e.id,harnessSessionId:e.harnessSessionId,backendRef:this.buildPersistedBackendRef(e),name:e.name,prompt:e.prompt,workdir:e.originalWorkdir??e.workdir,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,createdAt:e.startedAt,completedAt:e.completedAt,status:e.status,lifecycle:e.lifecycle,approvalState:e.approvalState,worktreeState:e.worktreeState,runtimeState:e.runtimeState,taskFlowMirror:e.taskFlowMirror,deliveryState:e.deliveryState,notificationDedupe:this.getExistingNotificationDedupe(e),completionSummaryDedupe:this.getExistingCompletionSummaryDedupe(e),killReason:e.killReason,costUsd:e.costUsd,originAgentId:r.originAgentId,originChannel:r.originChannel,originThreadId:r.originThreadId,originSessionKey:r.originSessionKey,route:i,outputPath:s,harness:e.harnessName,resumedFromSessionName:e.resumedFromSessionName,goalTaskId:e.goalTaskId,requestedPermissionMode:t.requestedPermissionMode,currentPermissionMode:t.currentPermissionMode,approvalExecutionState:t.approvalExecutionState,approvalRationale:t.approvalRationale,planModeApproved:t.planModeApproved,pendingPlanApproval:t.pendingPlanApproval,planApprovalContext:t.planApprovalContext,planDecisionVersion:t.planDecisionVersion,actionablePlanDecisionVersion:t.actionablePlanDecisionVersion,canonicalPlanPromptVersion:t.canonicalPlanPromptVersion,approvalPromptRequiredVersion:t.approvalPromptRequiredVersion,approvalPromptVersion:t.approvalPromptVersion,approvalPromptStatus:t.approvalPromptStatus,approvalPromptTransport:t.approvalPromptTransport,approvalPromptMessageKind:t.approvalPromptMessageKind,approvalPromptLastAttemptAt:t.approvalPromptLastAttemptAt,approvalPromptDeliveredAt:t.approvalPromptDeliveredAt,approvalPromptFailedAt:t.approvalPromptFailedAt,planApproval:t.planApproval,codexApprovalPolicy:t.codexApprovalPolicy,worktreePath:o.worktreePath,worktreeBranch:o.worktreeBranch,worktreeStrategy:o.worktreeStrategy,worktreeBaseBranch:o.worktreeBaseBranch,worktreeParentBranch:o.worktreeParentBranch,worktreePrTargetRepo:o.worktreePrTargetRepo,autoMergeParentSessionId:o.autoMergeParentSessionId,autoMergeConflictResolutionAttemptCount:o.autoMergeConflictResolutionAttemptCount,autoMergeResolverSessionId:o.autoMergeResolverSessionId,worktreeLifecycle:o.worktreeLifecycle,resumable:e.isExplicitlyResumable};Qn(a),this.indexPersistedEntry(a),this.saveIndex()}getExistingNotificationDedupe(e){return this.getPersistedSession(e.id)?.notificationDedupe??(e.harnessSessionId?this.getPersistedSession(e.harnessSessionId)?.notificationDedupe:void 0)??(C(e)?this.getPersistedSession(C(e))?.notificationDedupe:void 0)}getExistingCompletionSummaryDedupe(e){return this.getPersistedSession(e.id)?.completionSummaryDedupe??(e.harnessSessionId?this.getPersistedSession(e.harnessSessionId)?.completionSummaryDedupe:void 0)??(C(e)?this.getPersistedSession(C(e))?.completionSummaryDedupe:void 0)}getLatestPersistedByName(e){return this.queries.getLatestPersistedByName(e)}resolveBackendConversationId(e,t){return this.queries.resolveBackendConversationId(e,t)}resolveHarnessSessionId(e,t){return this.queries.resolveHarnessSessionId(e,t)}getPersistedSession(e){return this.queries.getPersistedSession(e)}replacePersistedSession(e){let t=e.sessionId?this.getPersistedSession(e.sessionId):void 0;t&&this.removePersistedIndexes(t),this.indexPersistedEntry(e),this.saveIndex()}listPersistedSessions(){return this.queries.listPersistedSessions()}getRepoPolicy(e){return this.repoPolicies.get(e)}listRepoPolicies(){return[...this.repoPolicies.values()].sort((e,t)=>e.repoRoot.localeCompare(t.repoRoot)||e.key.localeCompare(t.key))}setRepoPolicy(e){let t=this.repoPolicies.get(e.key),r={...e,createdAt:t?.createdAt??e.createdAt,updatedAt:new Date().toISOString(),source:"stored"};return this.repoPolicies.set(r.key,r),this.saveIndex(),r}updateRepoPolicy(e,t){let r=this.repoPolicies.get(e);if(r)return this.setRepoPolicy({...r,policy:t})}resetRepoPolicy(e){let t=this.repoPolicies.delete(e);return t&&this.saveIndex(),t}removeRepoPolicies(e){let t=[];for(let r of e){let o=this.repoPolicies.get(r);o&&(this.repoPolicies.delete(r),t.push(o))}return t.length>0&&this.saveIndex(),t.sort((r,o)=>r.repoRoot.localeCompare(o.repoRoot)||r.key.localeCompare(o.key))}cleanupRepoPolicies(){let e=[];for(let[t,r]of this.repoPolicies)cm(r.repoRoot)||(this.repoPolicies.delete(t),e.push(r));return e.length>0&&this.saveIndex(),e.sort((t,r)=>t.repoRoot.localeCompare(r.repoRoot)||t.key.localeCompare(r.key))}cleanupTmpOutputFiles(e){this.actionTokenStore.purgeExpiredActionTokens(e),Oa(e,Eo,this.getReferencedOutputPaths())}getNextTmpOutputCleanupAt(e){return Wa(e,Eo,this.getReferencedOutputPaths())}evictOldestPersisted(e){let t=this.listPersistedSessions();if(t.length<=e)return[];let r=t.slice(e);for(let o of r)this.removePersistedIndexes(o);return this.saveIndex(),r}shouldGcActiveSession(e,t,r){return!e.completedAt||!dm.has(e.status)?!1:t-e.completedAt>r}getActionToken(e){return this.actionTokenStore.getActionToken(e)}consumeActionToken(e){return this.actionTokenStore.consumeActionToken(e)}deleteActionTokensForSession(e){this.actionTokenStore.deleteActionTokensForSession(e)}purgeExpiredActionTokens(e=Date.now()){return this.actionTokenStore.purgeExpiredActionTokens(e)}getNextActionTokenExpiry(){return this.actionTokenStore.nextExpiryAt()}onActionTokensChanged(e){this.actionTokenStore.setAfterChangeListener(e)}hasOutputPathReference(e){for(let t of this.persisted.values())if(t.outputPath===e)return!0;return!1}getReferencedOutputPaths(){return[...new Set([...this.persisted.values()].map(e=>e.outputPath).filter(e=>typeof e=="string"&&e.length>0))]}cleanupOrphanOutputFiles(){Fa(this.getReferencedOutputPaths())}};var mm=new Set(["completed","failed","killed"]),Jn=class{metrics={totalCostUsd:0,costPerDay:new Map,sessionsByStatus:{completed:0,failed:0,killed:0},totalLaunched:0,totalDurationMs:0,sessionsWithDuration:0,mostExpensive:null};incrementLaunched(){this.metrics.totalLaunched++}recordSession(e){let t=e.costUsd??0,r=e.status;this.metrics.totalCostUsd+=t;let o=new Date(e.completedAt??e.startedAt).toISOString().slice(0,10);if(this.metrics.costPerDay.set(o,(this.metrics.costPerDay.get(o)??0)+t),mm.has(r)&&this.metrics.sessionsByStatus[r]++,e.completedAt){let i=e.completedAt-e.startedAt;this.metrics.totalDurationMs+=i,this.metrics.sessionsWithDuration++}(!this.metrics.mostExpensive||t>this.metrics.mostExpensive.costUsd)&&(this.metrics.mostExpensive={id:e.id,name:e.name,costUsd:t,prompt:q(e.prompt,80)})}getMetrics(){return{totalCostUsd:this.metrics.totalCostUsd,costPerDay:new Map(this.metrics.costPerDay),sessionsByStatus:{...this.metrics.sessionsByStatus},totalLaunched:this.metrics.totalLaunched,totalDurationMs:this.metrics.totalDurationMs,sessionsWithDuration:this.metrics.sessionsWithDuration,mostExpensive:this.metrics.mostExpensive?{...this.metrics.mostExpensive}:null}}};import*as Ba from"child_process";var ze=class{tails=new Map;enqueue(e,t,r){let o=this.tails.get(e);o!==void 0&&r?.();let s=(o?.catch(()=>{})??Promise.resolve()).then(()=>t()),a=s.catch(()=>{});return this.tails.set(e,a),a.finally(()=>{this.tails.get(e)===a&&this.tails.delete(e)}),s}clear(){this.tails.clear()}};var No=3e4,fm=2e3,gm=2e4,j=4;function gt(n){return n instanceof Error?n.message:String(n)}function hm(){return new Error(`Dispatch timed out after ${No}ms`)}function ym(n){if(!(n instanceof Error))return!1;let e=n;return e.killed===!0&&e.signal==="SIGKILL"}var Sm={execFile:Ba.execFile},Xn=class{pendingRetryTimers=new Map;orderedDispatches=new ze;disposed=!1;clearPendingRetries(){for(let e of this.pendingRetryTimers.values())for(let t of e)clearTimeout(t.timer),t.onCleared?.();this.pendingRetryTimers.clear()}clearRetryTimersForSession(e){let t=this.pendingRetryTimers.get(e);if(t){for(let r of t)clearTimeout(r.timer),r.onCleared?.();this.pendingRetryTimers.delete(e)}}dispose(){this.disposed=!0,this.clearPendingRetries(),this.orderedDispatches.clear()}execute(e,t,r=1){if(!this.disposed){if(r===1&&t.orderingKey){this.enqueueOrderedDispatch(t.orderingKey,o=>this.executeNow(e,t,o,r));return}this.executeNow(e,t,void 0,r)}}executePromise(e,t,r=1){if(!this.disposed){if(r===1&&t.orderingKey){this.enqueueOrderedDispatch(t.orderingKey,o=>this.executePromiseNow(e,t,o,r));return}this.executePromiseNow(e,t,void 0,r)}}executeNow(e,t,r,o=1){if(this.disposed||t.shouldContinue?.()===!1){r?.();return}let i=Date.now();o===1&&t.onStarted?.(),this.log("info","dispatch_started",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j}),Sm.execFile("openclaw",e,{timeout:No,killSignal:"SIGKILL"},(s,a,l)=>{if(this.disposed){r?.();return}let d=Date.now()-i;if(!s){let h=t.successValidator?.(a??"");if(h?.outcome==="failure"){this.log("error","dispatch_success_validation_failed",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,error:h.reason,terminal:!0}),t.onFinalFailure?.(),r?.();return}if(h?.outcome==="skipped"){this.log("info","dispatch_skipped",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,reason:h.reason}),t.shouldContinue?.()!==!1&&t.onSkipped?.(h.reason),r?.();return}this.log("info","dispatch_succeeded",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d}),t.shouldContinue?.()!==!1&&t.onSuccess?.(),r?.();return}let u=l?.trim()?` | stderr: ${l.trim()}`:"";if(t.shouldContinue?.()===!1){r?.();return}if(t.target==="message.send"&&ym(s)){this.log("error","dispatch_failed",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,error:`${gt(s)}${u}`,terminal:!0,ambiguousResult:!0}),t.onAmbiguousResult?.(),r?.();return}if(o>=j||t.terminalOnFailure===!0){this.log("error","dispatch_failed",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,error:`${gt(s)}${u}`,terminal:!0}),t.onFinalFailure?.(),r?.();return}let g=this.retryDelayMs(o);this.log("error","dispatch_retry_scheduled",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:d,retryDelayMs:g,error:`${gt(s)}${u}`});let k={timer:setTimeout(()=>{let h=this.pendingRetryTimers.get(t.sessionId);if(h&&(h.delete(k),h.size===0&&this.pendingRetryTimers.delete(t.sessionId)),t.shouldContinue?.()===!1){r?.();return}this.executeNow(e,t,r,o+1)},g),onCleared:r};k.timer.unref?.(),this.pendingRetryTimers.has(t.sessionId)||this.pendingRetryTimers.set(t.sessionId,new Set),this.pendingRetryTimers.get(t.sessionId).add(k)})}executePromiseNow(e,t,r,o=1){if(this.disposed||t.shouldContinue?.()===!1){r?.();return}let i=Date.now();o===1&&t.onStarted?.(),this.log("info","dispatch_started",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j}),this.executePromiseWithTimeout(e).then(()=>{if(this.disposed){r?.();return}let s=Date.now()-i;this.log("info","dispatch_succeeded",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:s}),t.shouldContinue?.()!==!1&&t.onSuccess?.(),r?.()}).catch(s=>{if(this.disposed){r?.();return}let a=Date.now()-i;if(t.shouldContinue?.()===!1){r?.();return}if(o>=j||t.terminalOnFailure===!0){this.log("error","dispatch_failed",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:a,error:gt(s),terminal:!0,...t.terminalOnFailure===!0&&o<j?{terminalReason:"non_retryable"}:{}}),t.onFinalFailure?.(),r?.();return}let l=this.retryDelayMs(o);this.log("error","dispatch_retry_scheduled",{label:t.label,sessionId:t.sessionId,target:t.target,phase:t.phase,messageKind:t.messageKind,route:t.routeSummary,...t.dispatchContext,attempt:o,maxAttempts:j,elapsedMs:a,retryDelayMs:l,error:gt(s)});let d={timer:setTimeout(()=>{let u=this.pendingRetryTimers.get(t.sessionId);if(u&&(u.delete(d),u.size===0&&this.pendingRetryTimers.delete(t.sessionId)),t.shouldContinue?.()===!1){r?.();return}this.executePromiseNow(e,t,r,o+1)},l),onCleared:r};d.timer.unref?.(),this.pendingRetryTimers.has(t.sessionId)||this.pendingRetryTimers.set(t.sessionId,new Set),this.pendingRetryTimers.get(t.sessionId).add(d)})}executePromiseWithTimeout(e){return new Promise((t,r)=>{let o=!1,i=setTimeout(()=>{o||(o=!0,r(hm()))},No);i.unref?.(),Promise.resolve().then(e).then(()=>{o||(o=!0,clearTimeout(i),t())}).catch(s=>{o||(o=!0,clearTimeout(i),r(s))})})}retryDelayMs(e){let t=Math.max(0,e-1),r=fm*2**t;return Math.min(r,gm)}enqueueOrderedDispatch(e,t){this.orderedDispatches.enqueue(e,async()=>{this.disposed||await new Promise(r=>{let o=!1;t(()=>{o||(o=!0,r())})})})}log(e,t,r){let o=`[WakeDispatcher] ${JSON.stringify({event:t,...r})}`;if(e==="error"){console.error(o);return}}};var Zn=class{resolve(e){let t=le(e);if(!(!t?.provider||!t.target))return{channel:t.provider,target:t.target,accountId:t.accountId,threadId:t.threadId,sessionKey:t.sessionKey}}summary(e){if(!e)return"system";let t=e.accountId?`|${e.accountId}`:"",r=e.threadId?`#${e.threadId}`:"";return`${e.channel}${t}|${e.target}${r}`}};import{randomUUID as km}from"crypto";var er=class{constructor(e={}){}buildChatSendArgs(e,t,r,o=km()){return["gateway","call","chat.send","--expect-final","--timeout","30000","--params",JSON.stringify({sessionKey:e,message:t,deliver:r,idempotencyKey:o})]}buildDirectNotificationArgs(e,t,r){let o=Ut(r),i=["message","send","--channel",e.channel,"--target",e.target,"--message",t];return e.accountId&&i.push("--account",e.accountId),e.threadId&&i.push("--thread-id",e.threadId),o&&i.push("--presentation",JSON.stringify(o)),i}buildSystemEventArgs(e){return["system","event","--text",e,"--mode","now"]}};function vm(n){let e=Pm(n).trim();return e?/^NO_REPLY$/i.test(e)?{outcome:"failure",reason:"completion follow-up wake ended with NO_REPLY"}:{outcome:"success"}:{outcome:"failure",reason:"completion follow-up wake produced no final response"}}function Pm(n){let e=n.trim();if(!e)return"";try{return Oo(JSON.parse(e)).trim()}catch{return e}}function Oo(n){if(typeof n=="string")return n;if(Array.isArray(n))return n.map(r=>Oo(r)).filter(Boolean).join(`
204
+ `);if(!n||typeof n!="object")return"";let e=n,t=["final","finalResponse","final_response","assistantFinal","assistant_final","response","text","content"];for(let r of t){let o=e[r];if(typeof o=="string"&&o.trim())return o}for(let r of["result","message","data"]){let o=Oo(e[r]);if(o.trim())return o}return""}var tr=class{routes=new Zn;transport;directNotifications;executor=new Xn;constructor(e={}){this.transport=e.transport??new er(e.transportOptions),this.directNotifications=e.directNotifications===void 0?new We:e.directNotifications}clearPendingRetries(){this.executor.clearPendingRetries()}clearRetryTimersForSession(e){this.executor.clearRetryTimersForSession(e)}dispose(){this.executor.dispose()}buildDispatchContext(e){let t=e.buttons??[],r=t.flat();return{transportRoute:e.routeSummary,transportChannel:e.route?.channel??"system",transportTarget:e.route?.target??"system",transportAccountId:e.route?.accountId,transportThreadId:e.route?.threadId,transportSessionKey:e.route?.sessionKey,messageTextLength:e.text.length,buttonsPresent:r.length>0,buttonRows:t.length||void 0,buttonCount:r.length||void 0,buttonLabels:r.length>0?r.map(o=>o.label):void 0,maxCallbackDataLength:r.length>0?Math.max(...r.map(o=>o.callbackData.length)):void 0}}sendWake(e,t,r,o,i,s,a,l,d,u){let f=this.routes.resolve(e),g=a;if(g?.()===!1)return;let k=f?.sessionKey?.trim();if(!k){this.executor.execute(this.transport.buildSystemEventArgs(t),{label:`${r}-system`,sessionId:e.id,target:"system.event",phase:o,routeSummary:"system",messageKind:"wake",dispatchContext:this.buildDispatchContext({routeSummary:"system",text:t}),onSuccess:s,onSkipped:d,onFinalFailure:i,successValidator:l,shouldContinue:g});return}this.executor.execute(this.transport.buildChatSendArgs(k,t,!0,u),{label:r,sessionId:e.id,target:"chat.send",phase:o,routeSummary:`session:${k}`,messageKind:"wake",dispatchContext:this.buildDispatchContext({routeSummary:`session:${k}`,route:f,text:t}),onSuccess:s,onSkipped:d,successValidator:l,shouldContinue:g,onFinalFailure:()=>{g?.()!==!1&&this.executor.execute(this.transport.buildSystemEventArgs(t),{label:`${r}-fallback`,sessionId:e.id,target:"system.event",phase:o,routeSummary:"system",messageKind:"wake",dispatchContext:this.buildDispatchContext({routeSummary:"system",text:t}),onSuccess:s,onSkipped:d,onFinalFailure:i,successValidator:l,shouldContinue:g})}})}sendUserNotification(e,t,r,o,i,s,a=!1,l){if(l?.()===!1)return;let d=!!o?.some(h=>Array.isArray(h)&&h.length>0),u=this.routes.resolve(e);M("wake_notify_selected",{sessionId:e.id,sessionName:e.name,label:r,messageTextLength:t.length,requireDirectDelivery:a,hasDirectNotificationTransport:!!this.directNotifications,routeSummary:u?this.routes.summary(u):"system",channel:u?.channel,target:u?.target,accountId:u?.accountId,threadId:u?.threadId,sessionKey:u?.sessionKey,...E(o)});let f=u?`notify:${u.channel}|${u.accountId??""}|${u.target}|${u.threadId??""}`:`notify:system:${e.id}`;if(!u){if(M("wake_notify_no_direct_route",{sessionId:e.id,sessionName:e.name,label:r,requireDirectDelivery:a,hasInteractiveButtons:d,...E(o)}),a){`${r}${e.id}`,i?.();return}if(d){`${r}${e.id}`,i?.();return}this.executor.execute(this.transport.buildSystemEventArgs(t),{label:`${r}-notify-system`,sessionId:e.id,target:"system.event",phase:"notify",routeSummary:"system",messageKind:"notify",dispatchContext:this.buildDispatchContext({routeSummary:"system",text:t,buttons:o}),orderingKey:f,onSuccess:s,onFinalFailure:i,shouldContinue:l});return}let g=()=>{if(M("wake_notify_direct_failed",{sessionId:e.id,sessionName:e.name,label:r,requireDirectDelivery:a,hasInteractiveButtons:d,channel:u.channel,target:u.target,accountId:u.accountId,threadId:u.threadId,sessionKey:u.sessionKey,...E(o)}),a){`${r}${e.id}`,i?.();return}if(d){`${r}${e.id}`,i?.();return}this.executor.execute(this.transport.buildSystemEventArgs(t),{label:`${r}-notify-fallback`,sessionId:e.id,target:"system.event",phase:"notify",routeSummary:"system",messageKind:"notify",dispatchContext:this.buildDispatchContext({routeSummary:"system",text:t}),orderingKey:f,onSuccess:s,onFinalFailure:i,shouldContinue:l})},k={label:`${r}-notify`,sessionId:e.id,target:"message.send",phase:"notify",routeSummary:this.routes.summary(u),messageKind:"notify",dispatchContext:this.buildDispatchContext({routeSummary:this.routes.summary(u),route:u,text:t,buttons:o}),orderingKey:f,onSuccess:s,onAmbiguousResult:g,onFinalFailure:g,terminalOnFailure:this.directNotifications?!0:void 0,shouldContinue:l};if(this.directNotifications){M("wake_notify_dispatching_direct_runtime",{sessionId:e.id,sessionName:e.name,label:r,channel:u.channel,target:u.target,accountId:u.accountId,threadId:u.threadId,sessionKey:u.sessionKey,...E(o)}),this.executor.executePromise(()=>this.directNotifications.send(u,t,o),k);return}M("wake_notify_dispatching_cli_message_send",{sessionId:e.id,sessionName:e.name,label:r,channel:u.channel,target:u.target,accountId:u.accountId,threadId:u.threadId,sessionKey:u.sessionKey,...E(o)}),this.executor.execute(this.transport.buildDirectNotificationArgs(u,t,o),k)}sendUserNotificationSequence(e,t,r,o,i,s=!1,a){let l=t.map(u=>({text:u.text.trim(),buttons:u.buttons})).filter(u=>u.text.length>0);if(l.length===0){o?.();return}M("wake_notify_sequence_started",{sessionId:e.id,sessionName:e.name,label:r,chunkCount:l.length,buttonChunkIndexes:l.map((u,f)=>u.buttons?.some(g=>Array.isArray(g)&&g.length>0)?f+1:void 0).filter(u=>typeof u=="number"),requireDirectDelivery:s});let d=u=>{if(a?.()===!1)return;let f=l[u];if(!f){M("wake_notify_sequence_succeeded",{sessionId:e.id,sessionName:e.name,label:r,chunkCount:l.length}),i?.();return}let g=u===0?o:i;M("wake_notify_sequence_chunk_selected",{sessionId:e.id,sessionName:e.name,label:r,chunkIndex:u+1,chunkCount:l.length,messageTextLength:f.text.length,failureHandler:u===0?"all-failed":"sequence-success",...E(f.buttons)}),this.sendUserNotification(e,f.text,`${r}-part-${u+1}`,f.buttons,g,()=>d(u+1),s,a)};d(0)}dispatchSessionNotification(e,t){let r=t.hooks,o=t.wakeMessageOnNotifySuccess!=null||t.wakeMessageOnNotifyFailed!=null,i=t.notifyUser??(t.wakeMessage?"on-wake-fallback":"always"),s=(t.userMessages?.length?t.userMessages:t.userMessage?.trim()?[{text:t.userMessage.trim(),buttons:t.buttons}]:[]).map(u=>({text:u.text.trim(),buttons:u.buttons})).filter(u=>u.text.length>0),a=t.wakeMessage?.trim(),l=t.shouldDispatch,d=t.completionWakeSummaryRequired===!0?vm:void 0;if(o){let u=t.wakeMessageOnNotifySuccess?.trim(),f=t.wakeMessageOnNotifyFailed?.trim(),g=y=>{y&&l?.()!==!1&&(r?.onWakeStarted?.(),this.sendWake(e,y,`${t.label}-wake`,"wake",r?.onWakeFailed,r?.onWakeSucceeded,l,d,r?.onWakeSkipped,t.idempotencyKey))},k=y=>{if(y){if(t.deferConditionalWakeUntilNextTick===!0||t.deferConditionalWakeMs!==void 0){let P=Math.max(0,Math.floor(t.deferConditionalWakeMs??0));setTimeout(()=>g(y),P).unref?.();return}g(y)}},h=()=>{l?.()!==!1&&(r?.onNotifySucceeded?.(),u&&k(u))},p=f?()=>{l?.()!==!1&&(r?.onNotifyFailed?.(),t.onUserNotifyFailed?.(),k(f))}:()=>{l?.()!==!1&&(r?.onNotifyFailed?.(),t.onUserNotifyFailed?.())};if(s.length>0){if(l?.()===!1)return;r?.onNotifyStarted?.(),this.sendUserNotificationSequence(e,s,t.label,p,h,t.requireDirectUserNotification===!0,l)}else p();return}if(i==="always"&&s.length>0){if(l?.()===!1)return;r?.onNotifyStarted?.(),this.sendUserNotificationSequence(e,s,t.label,()=>{l?.()!==!1&&(r?.onNotifyFailed?.(),t.onUserNotifyFailed?.())},()=>{l?.()!==!1&&r?.onNotifySucceeded?.()},t.requireDirectUserNotification===!0,l)}if(a&&l?.()!==!1){if(r?.onWakeStarted?.(),i==="on-wake-fallback"&&s.length>0&&!this.routes.resolve(e)?.sessionKey){if(l?.()===!1)return;r?.onNotifyStarted?.(),this.sendUserNotificationSequence(e,s,t.label,()=>{l?.()!==!1&&(r?.onNotifyFailed?.(),t.onUserNotifyFailed?.())},()=>{l?.()!==!1&&r?.onNotifySucceeded?.()},!1,l)}this.sendWake(e,a,`${t.label}-wake`,"wake",r?.onWakeFailed,r?.onWakeSucceeded,l,d,r?.onWakeSkipped,t.idempotencyKey)}}};var Ka=36,qa=2,Va="...";function wm(n){let e=Array.from(n);return e.length<=Ka?n:`${e.slice(0,Ka-Va.length).join("")}${Va}`}var nr=class{constructor(e,t){this.actionTokens=e;this.isGitHubCliAvailable=t}actionTokens;isGitHubCliAvailable;createActionToken(e,t,r={}){return this.actionTokens.createActionToken(e,t,{expiresAt:Date.now()+10080*60*1e3,...r})}consumeActionToken(e){return this.actionTokens.consumeActionToken(e)}consumeQuestionAnswerTokens(e,t,r){return this.actionTokens.consumeQuestionAnswerTokens(e,t,r)}consumePlanDecisionTokens(e,t){return this.actionTokens.consumePlanDecisionTokens(e,t)}getActionToken(e){return this.actionTokens.getActionToken(e)}listActiveActionTokens(e){return this.actionTokens.listActiveActionTokens(e)}clearRepoPolicyChoiceTokens(e){this.actionTokens.deleteActionTokensForSessionByKind(e,"repo-policy-set")}clearPlanDecisionTokens(e,t){this.actionTokens.deletePlanDecisionTokensForSession(e,t)}makeActionButton(e,t,r,o={}){let i=this.createActionToken(e,t,{label:r,...o});return{label:r,callbackData:i.id,style:this.resolveButtonStyle(t)}}resolveButtonStyle(e){switch(e){case"plan-approve":case"worktree-create-pr":case"worktree-update-pr":case"plan-offer-start":case"repo-policy-set":return"primary";case"worktree-merge":case"session-resume":case"session-restart":case"plugin-update-install":case"plugin-update-restart":return"success";case"plugin-update-remind-later":return"secondary";case"plan-reject":case"worktree-dismiss":case"plugin-update-dismiss":return"danger";default:return"secondary"}}getWorktreeDecisionButtons(e,t,r={merge:!0,pr:!0}){if(!t)return[];let o=[],i=[];if(r.merge&&i.push(this.makeActionButton(e,"worktree-merge","Merge")),r.pr&&this.isGitHubCliAvailable())t.worktreePrUrl?(i.push(this.makeActionButton(e,"worktree-view-pr","View PR",{targetUrl:t.worktreePrUrl})),i.length>0&&o.push(i),o.push([this.makeActionButton(e,"worktree-update-pr","Sync PR"),this.makeActionButton(e,"worktree-decide-later","Later")])):(i.push(this.makeActionButton(e,"worktree-create-pr","Open PR")),i.length>0&&o.push(i),o.push([this.makeActionButton(e,"worktree-decide-later","Later"),this.makeActionButton(e,"worktree-dismiss","Discard")]));else return o.push([...i,this.makeActionButton(e,"worktree-decide-later","Later")]),o.push([this.makeActionButton(e,"worktree-dismiss","Discard")]),o;return t.worktreePrUrl&&o.push([this.makeActionButton(e,"worktree-dismiss","Discard")]),o}getPlanApprovalButtons(e,t){let r=t?.actionablePlanDecisionVersion??t?.planDecisionVersion;this.clearPlanDecisionTokens(e,r);let o=[[this.makeActionButton(e,"plan-approve","Approve",{planDecisionVersion:r}),this.makeActionButton(e,"plan-request-changes","Revise",{planDecisionVersion:r}),this.makeActionButton(e,"plan-reject","Reject",{planDecisionVersion:r})]];return M("plan_approval_buttons_created",{sessionId:e,planDecisionVersion:r,...E(o)}),o}getResumeButtons(e,t){let r=[];return t.isExplicitlyResumable&&r.push(this.makeActionButton(e,"session-resume","Resume")),r.push(this.makeActionButton(e,"view-output","View output")),[r]}getQuestionButtons(e,t,r={}){if(t.length===0)return;let o=t.map((s,a)=>{let l=this.createActionToken(e,"question-answer",{label:s.label,optionIndex:a,pendingInputRequestId:r.requestId,pendingInputQuestionId:r.questionId});return{label:wm(s.label),callbackData:l.id,style:this.resolveButtonStyle("question-answer")}}),i=[];for(let s=0;s<o.length;s+=qa)i.push(o.slice(s,s+qa));return i}getPlanOfferButtons(e){let{offerId:t,route:r,planName:o,planPrompt:i,planWorkdir:s,planWorktreeStrategy:a}=e,l=[[this.makeActionButton(t,"plan-offer-start","Start Plan",{route:r,launchName:o,launchPrompt:i,launchWorkdir:s,launchWorktreeStrategy:a}),this.makeActionButton(t,"plan-offer-dismiss","Dismiss",{route:r})]];return M("plan_offer_buttons_created",{offerId:t,planName:o,channel:r.provider,target:r.target,accountId:r.accountId,threadId:r.threadId,sessionKey:r.sessionKey,planPromptLength:i.length,planWorkdirLength:s.length,planWorktreeStrategy:a,...E(l)}),l}getRepoPolicyChoiceButtons(e){let t=at(e.prAvailable??!0),r=Array.from({length:Math.ceil(t.length/2)},(o,i)=>t.slice(i*2,i*2+2)).map(o=>o.map(i=>this.makeActionButton(e.choiceId,"repo-policy-set",i.label,{route:e.route,repoPolicy:i.policy,repoPolicyWorkdir:e.repoRoot,launchName:e.launchName,launchPrompt:e.launchPrompt,launchWorkdir:e.launchWorkdir,launchModel:e.launchModel,launchReasoningEffort:e.launchReasoningEffort,launchFastMode:e.launchFastMode,launchSystemPrompt:e.launchSystemPrompt,launchAllowedTools:e.launchAllowedTools,launchResumeSessionId:e.launchResumeSessionId,launchResumedFromSessionName:e.launchResumedFromSessionName,launchResumeWorktreeFrom:e.launchResumeWorktreeFrom,launchSessionIdOverride:e.launchSessionIdOverride,launchClearedPersistedCodexResume:e.launchClearedPersistedCodexResume,launchForkSession:e.launchForkSession,launchForceNewSession:e.launchForceNewSession,launchPermissionMode:e.launchPermissionMode,launchPlanApproval:e.launchPlanApproval,launchHarness:e.launchHarness,launchWorktreeStrategy:e.launchWorktreeStrategy,launchWorktreeBaseBranch:e.launchWorktreeBaseBranch,launchWorktreePrTargetRepo:e.launchWorktreePrTargetRepo,launchOriginAgentId:e.launchOriginAgentId})));return M("repo_policy_choice_buttons_created",{choiceId:e.choiceId,repoRoot:e.repoRoot,channel:e.route.provider,target:e.route.target,accountId:e.route.accountId,threadId:e.route.threadId,sessionKey:e.route.sessionKey,labels:t.map(o=>o.label),...E(r)}),r}};import{createHash as Im}from"crypto";var bm="duplicate notification already delivered or in flight",rr=class{maxRecords;inFlightTtlMs;now;inFlight=new Set;delivered=new Set;constructor(e={}){this.maxRecords=Math.max(1,Math.floor(e.maxRecords??64)),this.inFlightTtlMs=Math.max(1,Math.floor(e.inFlightTtlMs??6e5)),this.now=e.now??(()=>new Date)}claim(e,t,r){if(!e)return{allowed:!0};let o=this.now(),i=this.prune(t??[],o),s=i.find(a=>a.key===e);return this.delivered.has(e)||this.inFlight.has(e)||s?.status==="delivered"||s?.status==="in_flight"&&this.isFreshInFlight(s,o)?{allowed:!1,records:i,reason:bm}:(this.inFlight.add(e),this.delivered.delete(e),{allowed:!0,records:this.upsert(i,{key:e,status:"in_flight",recordedAt:o.toISOString(),label:r})})}deliveredRecords(e,t,r){if(!e)return;let o=this.now();return this.inFlight.delete(e),this.delivered.add(e),this.upsert(this.prune(t??[],o),{key:e,status:"delivered",recordedAt:o.toISOString(),label:r})}releasedRecords(e,t){if(!e)return;let r=this.now();return this.inFlight.delete(e),this.prune(t??[],r).filter(o=>!(o.key===e&&o.status==="in_flight"))}prune(e,t){let r=e.filter(o=>o.status==="delivered"?!0:this.isFreshInFlight(o,t));return r.slice(Math.max(0,r.length-this.maxRecords))}isFreshInFlight(e,t){let r=Date.parse(e.recordedAt);return Number.isFinite(r)?t.getTime()-r<this.inFlightTtlMs:!1}upsert(e,t){let o=[...e.filter(i=>i.key!==t.key),t];return o.slice(Math.max(0,o.length-this.maxRecords))}};import{createHash as Rm}from"crypto";var Am=1024,ht="duplicate completion follow-up wake already handled",or="prior human-visible summary already delivered",ir=class{inFlight=new Set;completed=new Map;claimKeysByPrimary=new Map;maxCompletedKeys;constructor(e={}){this.maxCompletedKeys=Math.max(1,Math.floor(e.maxCompletedKeys??Am))}decide(e,t,r){if(t?.required!==!0)return{required:!1,allowed:!1,explicit:!1};let o=this.buildKeySet(e,t);if(!o)return{required:!0,allowed:!0,explicit:!1};let i=this.normalizeRecords(r),s=this.buildPersistedKeyMap(i),a=o.decisionKeys.find(u=>this.inFlight.has(u)||!!this.getCompletedRecord(u)||s.has(u)),l=a?this.getCompletedRecord(a):void 0,d=a?s.get(a):void 0;return a?{required:!0,allowed:!1,explicit:o.explicit,dedupeKey:o.primary,skipReason:l?.skipReason??d?.skipReason??ht}:(this.registerClaim(o.primary,o.claimKeys),{required:!0,allowed:!0,key:o.primary,explicit:o.explicit})}recordVisibleDelivery(e,t,r,o){if(t.required!==!0)return{required:!1,allowed:!1,explicit:!1};let i=this.buildKeySet(e,t);if(!i)return{required:!0,allowed:!0,explicit:!1};let s=this.normalizeRecords(r),a=this.buildPersistedKeyMap(s),l=i.decisionKeys.find(g=>!!this.getCompletedRecord(g)||a.has(g)),d=l?this.getCompletedRecord(l):void 0,u=l?a.get(l):void 0;if(d||u)return{required:!0,allowed:!1,explicit:i.explicit,dedupeKey:i.primary,skipReason:d?.skipReason??u?.skipReason};this.finishKeys(i.primary,i.claimKeys,!0,or);let f=this.deliveredRecords(i.claimKeys,s,o,or);return{required:!0,allowed:!0,key:i.primary,explicit:i.explicit,records:f}}finish(e,t,r=ht){if(!e)return;let o=this.claimKeysByPrimary.get(e)??[e];this.finishKeys(e,o,t,r)}completionRecordsAfterDelivery(e,t,r,o=ht){if(!e)return;let i=this.claimKeysByPrimary.get(e)??[e];return this.deliveredRecords(i,t,r,o)}registerClaim(e,t){for(let r of t)this.inFlight.add(r);for(this.claimKeysByPrimary.delete(e),this.claimKeysByPrimary.set(e,t);this.claimKeysByPrimary.size>this.maxCompletedKeys;){let r=this.claimKeysByPrimary.keys().next().value;if(r===void 0)break;let o=this.claimKeysByPrimary.get(r)??[r];for(let i of o)this.inFlight.delete(i);this.claimKeysByPrimary.delete(r)}}finishKeys(e,t,r,o=ht){for(let i of t)this.inFlight.delete(i);if(this.claimKeysByPrimary.delete(e),!!r){for(let i of t)this.completed.get(i)?.skipReason===or&&o!==or||(this.completed.delete(i),this.completed.set(i,{skipReason:o,linkedKeys:t.filter(a=>a!==i)}));for(;this.completed.size>this.maxCompletedKeys;){let i=this.completed.keys().next().value;if(i===void 0)break;this.completed.delete(i)}}}buildKeySet(e,t){let r=this.getDeliveryRef(e);if(!r)return;let o=this.normalizeOutcomeKey(e,t.outcomeKey?.trim());if(o){let a=`${this.buildVisibleScope(r,e)}:outcome:${this.digest(o)}`,l=this.isGoalLike(e,t,o),d=this.buildSessionAliasKeys(r,e,"visible-summary"),u=this.buildSessionAliasKeys(r,e,"goal-summary"),f=this.isTerminalLike(t,o),g=o.startsWith("worktree-pr:")?this.normalizeWorktreePrOutcome(t.outcomeKey?.trim()):void 0,k=g?.aliases.map(h=>`${this.buildVisibleScope(r,e)}:outcome:${this.digest(h)}`)??[];return{primary:a,explicit:!0,claimKeys:[...d,...l?u:[],...k,a],decisionKeys:[a,...g?.blocksAliases?k:[],...l||f?d:[],...u]}}let i=t.fallbackFingerprint?.trim();if(!i)return;let s=`${r}:${t.producer}:${this.digest(i)}`;return{primary:s,explicit:!1,claimKeys:[s],decisionKeys:[s]}}isGoalLike(e,t,r){return!!e.goalTaskId?.trim()||t.producer==="goal"||/^goal:/i.test(r)}isTerminalLike(e,t){return e.producer==="terminal"||/^terminal:/i.test(t)}normalizeOutcomeKey(e,t){let r=e.goalTaskId?.trim();if(r)return`goal:${r}`;let o=this.normalizeWorktreePrOutcome(t);return o?o.primary:t}normalizeWorktreePrOutcome(e){if(!e)return;let t=e.split(":");if(t[0]!=="worktree-pr"||t.length<5)return;let r=t[1]?.trim().toLowerCase();if(!r||!/^(?:draft-)?(?:opened|updated)$/.test(r))return;let o=t[2]?.trim()||"default-repo",i=t[3]?.trim();if(!i)return;let s=this.normalizePrIdentity(i),a=t[4]?.trim();if(!s||!a)return;let l=["worktree-pr",o.toLowerCase(),s,a].join(":"),d=`${l}:created`;if(r.endsWith("updated")){let u=t.slice(5).join(":").trim();return{primary:u?`${l}:updated:${u}`:`${l}:updated`,aliases:[d,l],blocksAliases:!1}}return{primary:d,aliases:[l],blocksAliases:!0}}normalizePrIdentity(e){let t=e.match(/#?(\d+)$/);if(t?.[1])return`#${t[1]}`;let r=e.match(/\/pull\/(\d+)(?:\b|\/|$)/);if(r?.[1])return`#${r[1]}`;let o=e.trim();return o||void 0}buildVisibleScope(e,t){let r=le(t);return r?`route:${this.digest(JSON.stringify({provider:r.provider,accountId:r.accountId,target:r.target,threadId:r.threadId}))}`:e}buildSessionAliasKeys(e,t,r){let o=this.buildVisibleScope(e,t),i="startedAt"in t?t.startedAt:t.createdAt,s=Number.isFinite(i)?`${o}:cycle:${this.digest(String(i))}`:o,a=["id"in t?t.id:void 0,"sessionId"in t?t.sessionId:void 0,t.name,C(t),t.harnessSessionId,e].map(l=>l?.trim()).filter(l=>!!l);return[...new Set(a)].map(l=>`${s}:session:${this.digest(l)}:${r}`)}getDeliveryRef(e){return D(e)??C(e)??""}digest(e){return Rm("sha256").update(e).digest("hex").slice(0,16)}normalizeRecords(e){return e?.length?e.filter(t=>t.key.trim()&&Number.isFinite(Date.parse(t.recordedAt))).slice(-this.maxCompletedKeys):[]}buildPersistedKeyMap(e){let t=new Map;for(let r of e){t.set(r.key,r);for(let o of r.linkedKeys??[])o.trim()&&t.set(o,r)}return t}getCompletedRecord(e){let t=this.completed.get(e);if(t)return t;for(let r of this.completed.values())if(r.linkedKeys?.includes(e))return r}deliveredRecords(e,t,r,o=ht){let i=new Date().toISOString(),s=this.normalizeRecords(t),a=new Set(e),d=[...s.filter(u=>!a.has(u.key)&&!(u.linkedKeys??[]).some(f=>a.has(f))),...e.map(u=>{let f=e.filter(g=>g!==u);return{key:u,linkedKeys:f.length>0?f:void 0,recordedAt:i,label:r,skipReason:o}})];return d.slice(Math.max(0,d.length-this.maxCompletedKeys))}};var Tm=2e3,xm=new Set(["1","true","yes","on"]);function Cm(){let n=process.env.OPENCLAW_CODE_AGENT_NOTIFICATION_DIAGNOSTICS?.trim().toLowerCase();return!!(n&&xm.has(n))||xr()}function Mm(n){Cm()&&process.stderr.write(`[SessionNotification] ${JSON.stringify(n)}
205
+ `)}function _m(n){let e=n?.trim().split(":")??[];if(e[0]!=="worktree-pr")return;let t=e[1]?.toLowerCase();if(t==="updated"||t==="draft-updated")return"pr-updated";if(t==="opened"||t==="draft-opened")return"pr-opened"}var sr=class{constructor(e,t,r={}){this.wakeDispatcher=e;this.applyPersistedPatch=t;this.completionSummaries=new ir({maxCompletedKeys:r.maxCompletedCompletionWakeKeys}),this.notificationDedupe=new rr({maxRecords:r.maxNotificationDedupeRecords}),this.getPersistedSession=r.getPersistedSession}wakeDispatcher;applyPersistedPatch;completionSummaries;notificationDedupe;getPersistedSession;dispatch(e,t){let r=this.getDeliveryRef(e),o=this.getPersistedSession?.(r),i=this.buildNotificationDedupeKey(e,t),s=this.notificationDedupe.claim(i,o?.notificationDedupe,t.label);if(s.records&&this.applyNotificationDedupePatch(r,s.records),!s.allowed){this.logNotificationDecision({session:e,request:t,deliveryRef:r,dedupeKey:i,decision:"skip",reason:s.reason??"duplicate notification skipped",deliveryPath:"notify"}),t.hooks?.onDuplicateSkipped?.(s.reason??"duplicate notification skipped");return}let a=this.buildCompletionSummaryFact(t),l=t.completionSummaryOwner==="foreground"&&a?.required===!0,d=l?this.completionSummaries.recordVisibleDelivery(e,a,o?.completionSummaryDedupe,t.label):this.completionSummaries.decide(e,a,o?.completionSummaryDedupe);d.records&&this.applyCompletionSummaryDedupePatch(r,d.records);let u=l?this.withoutCompletionWake(t):t;if(d.required&&!d.allowed)if(this.logNotificationDecision({session:e,request:t,deliveryRef:r,dedupeKey:d.dedupeKey??d.key,outcomeKey:a?.outcomeKey,decision:l?"skip":d.explicit?"send_without_followup":"skip",reason:d.skipReason??"completion follow-up wake suppressed",deliveryPath:l?"foreground-summary":"wake",followupKind:a?.producer}),t.hooks?.onWakeSkipped?.(d.skipReason??"completion follow-up wake suppressed"),l){this.releaseNotificationDedupe(r,i);return}else if(d.explicit)u=this.withoutCompletionWake(t);else{this.releaseNotificationDedupe(r,i);return}a?.required===!0&&this.logNotificationDecision({session:e,request:u,deliveryRef:r,dedupeKey:d.dedupeKey??d.key,outcomeKey:a.outcomeKey,decision:l?"record_visible":u.completionWakeSummaryRequired===!0?"send_with_followup":"send_without_followup",reason:l?"foreground summary owns completion follow-up":void 0,deliveryPath:l?"foreground-summary":"wake",followupKind:a.producer});let f=this.buildCompletionWakePatch(u),g=!!(u.wakeMessage?.trim()||u.wakeMessageOnNotifySuccess?.trim()),k=!!(u.wakeMessage?.trim()||u.wakeMessageOnNotifyFailed?.trim()),h=!1,p=!1,y=()=>{p||(p=!0,h||(this.releaseNotificationDedupe(r,i),h=!0),this.completionSummaries.finish(d.key,!1))},P=u.shouldDispatch?()=>{let A=u.shouldDispatch?.()!==!1;return A||y(),A}:void 0,b={onNotifyStarted:()=>{this.applyDeliveryState(r,"notifying"),u.hooks?.onNotifyStarted?.()},onNotifySucceeded:()=>{h=!0,this.markNotificationDedupeDelivered(r,i,u.label),this.applyNotifyDeliveryState(r,g?"wake_pending":"idle",g?f:void 0),g||this.completionSummaries.finish(d.key,!1),u.hooks?.onNotifySucceeded?.()},onNotifyFailed:()=>{this.applyNotifyDeliveryState(r,k?"wake_pending":"failed",k?f:void 0),k||(this.completionSummaries.finish(d.key,!1),this.releaseNotificationDedupe(r,i),h=!0),u.hooks?.onNotifyFailed?.()},onWakeStarted:()=>{this.applyPersistedPatchWithCompletionWake(r,"wake_pending",f,{completionWakeIssuedAt:new Date().toISOString(),completionWakeSucceededAt:void 0,completionWakeFailedAt:void 0,completionWakeSkippedAt:void 0,completionWakeSkipReason:void 0}),u.hooks?.onWakeStarted?.()},onWakeSucceeded:()=>{h=!0,this.markNotificationDedupeDelivered(r,i,u.label),this.markCompletionSummaryDelivered(r,d.key,u.label),this.applyPersistedPatchWithCompletionWake(r,"idle",this.buildCompletionWakeSucceededPatch(f),{completionWakeSucceededAt:new Date().toISOString(),completionWakeFailedAt:void 0,completionWakeSkippedAt:void 0,completionWakeSkipReason:void 0}),this.completionSummaries.finish(d.key,!0),u.hooks?.onWakeSucceeded?.()},onWakeSkipped:A=>{if(p){u.hooks?.onWakeSkipped?.(A);return}h=!0,this.markNotificationDedupeDelivered(r,i,u.label),this.markCompletionSummaryDelivered(r,d.key,u.label,A),this.applyPersistedPatchWithCompletionWake(r,"idle",this.buildCompletionWakeSucceededPatch(f),{completionWakeSucceededAt:void 0,completionWakeFailedAt:void 0,completionWakeSkippedAt:new Date().toISOString(),completionWakeSkipReason:A}),this.completionSummaries.finish(d.key,!0),u.hooks?.onWakeSkipped?.(A)},onWakeFailed:()=>{this.applyPersistedPatchWithCompletionWake(r,"failed",f,{completionWakeFailedAt:new Date().toISOString()}),this.completionSummaries.finish(d.key,!1),this.releaseNotificationDedupe(r,i),h=!0,u.hooks?.onWakeFailed?.()}};this.wakeDispatcher.dispatchSessionNotification(e,{...u,idempotencyKey:i??u.idempotencyKey,shouldDispatch:P,hooks:b})}notifyWorktreeOutcome(e,t,r={}){let o=this.getDeliveryRef(e),i=_m(r.completionWakeOutcomeKey);o&&i&&this.applyPersistedPatch(o,{worktreeRemoteOutcome:i});let s=Dm(t,e),a=f=>Ge({sessionId:o,sessionName:e.name,outcomeLine:s,originThreadLine:Ye(e),detailLines:r.detailLines,canonicalStatusDelivered:f}),l=r.summaryWakeRequired??!0,d={required:l,producer:"worktree-pr",outcomeKey:r.completionWakeOutcomeKey??`terminal:${o}`},u=r.completionSummaryOwner!=="foreground";if(l&&!u){let f=this.getDeliveryRef(e),g=this.completionSummaries.recordVisibleDelivery(e,d,f?this.getPersistedSession?.(f)?.completionSummaryDedupe:void 0,"worktree-outcome");g.records&&this.applyCompletionSummaryDedupePatch(f,g.records)}this.dispatch(e,{label:"worktree-outcome",userMessage:s,notifyUser:"always",requireDirectUserNotification:!0,completionSummary:{...d,required:l&&u},completionWakeSummaryRequired:l&&u,completionWakeOutcomeKey:r.completionWakeOutcomeKey??`terminal:${o}`,idempotencyKey:`worktree-outcome:${r.completionWakeOutcomeKey??t}`,deferConditionalWakeUntilNextTick:!0,deferConditionalWakeMs:Tm,wakeMessageOnNotifySuccess:l&&u?a(!0):void 0,wakeMessageOnNotifyFailed:l&&u?a(!1):void 0})}dispose(){this.wakeDispatcher.dispose()}getDeliveryRef(e){return D(e)??C(e)??""}applyDeliveryState(e,t){!e||!t||this.applyPersistedPatch(e,{deliveryState:t})}applyNotifyDeliveryState(e,t,r){!e||!t||this.applyPersistedPatch(e,r?{deliveryState:t,...r}:{deliveryState:t})}applyPersistedPatchWithCompletionWake(e,t,r,o){!e||!t||this.applyPersistedPatch(e,r?{deliveryState:t,...r,...o}:{deliveryState:t})}buildCompletionWakePatch(e){if(e.completionWakeSummaryRequired===!0)return{completionWakeSummaryRequired:!0}}buildCompletionWakeSucceededPatch(e){if(e)return{completionWakeSummaryRequired:void 0}}withoutCompletionWake(e){return{...e,completionSummary:e.completionSummary?{...e.completionSummary,required:!1}:void 0,wakeMessage:void 0,wakeMessageOnNotifySuccess:void 0,wakeMessageOnNotifyFailed:void 0,completionWakeSummaryRequired:!1}}buildCompletionSummaryFact(e){if(e.completionSummary)return e.completionSummary;if(e.completionWakeSummaryRequired!==!0)return;let t=[e.wakeMessage,e.wakeMessageOnNotifySuccess,e.wakeMessageOnNotifyFailed].map(r=>r?.trim()).filter(r=>!!r);return{required:!0,producer:"legacy",outcomeKey:e.completionWakeOutcomeKey,fallbackFingerprint:t.length>0?`${e.label}
206
206
  ${t.join(`
207
207
  ---completion-wake---
208
- `)}`:void 0}}buildNotificationDedupeKey(e,t){let r=t.idempotencyKey?.trim();if(!r)return;let o=this.getDeliveryRef(e);if(!o)return;let i=le(e),s=i?{provider:i.provider,accountId:i.accountId,target:i.target,threadId:i.threadId}:{deliveryRef:o};return`notification:${this.digest(JSON.stringify({scope:s,semanticKey:r}))}`}markNotificationDedupeDelivered(e,t,r){let o=this.notificationDedupe.deliveredRecords(t,e?this.getPersistedSession?.(e)?.notificationDedupe:void 0,r);o&&this.applyNotificationDedupePatch(e,o)}releaseNotificationDedupe(e,t){let r=this.notificationDedupe.releasedRecords(t,e?this.getPersistedSession?.(e)?.notificationDedupe:void 0);r&&this.applyNotificationDedupePatch(e,r)}applyNotificationDedupePatch(e,t){this.getPersistedSession&&e&&this.applyPersistedPatch(e,{notificationDedupe:t})}markCompletionSummaryDelivered(e,t,r,o){let i=this.completionSummaries.completionRecordsAfterDelivery(t,e?this.getPersistedSession?.(e)?.completionSummaryDedupe:void 0,r,o);i&&this.applyCompletionSummaryDedupePatch(e,i)}applyCompletionSummaryDedupePatch(e,t){this.getPersistedSession&&e&&this.applyPersistedPatch(e,{completionSummaryDedupe:t})}logNotificationDecision(e){let t=le(e.session);Mm({event:"oca_notification_decision",sessionId:"id"in e.session?e.session.id:e.session.sessionId,sessionName:e.session.name,harnessSessionId:e.session.harnessSessionId,originRoute:t?{provider:t.provider,accountId:t.accountId,target:t.target,threadId:t.threadId,sessionKey:t.sessionKey}:void 0,outcomeType:e.outcomeKey?.split(":").slice(0,2).join(":")??e.request.label,notificationKind:e.request.label,followupKind:e.followupKind,dedupeKey:e.dedupeKey,deliveryPath:e.deliveryPath,decision:e.decision,reason:e.reason,completionWakeSummaryRequired:e.request.completionWakeSummaryRequired,deliveryRef:e.deliveryRef})}digest(e){return Im("sha256").update(e).digest("hex").slice(0,16)}};function Dm(n,e){let t=ye(e);return t?`${n}${t}`:n}import{existsSync as $m}from"fs";var ar=class{getCompletionState(e,t,r,o){if(oe(t)!==r)return"has-commits";let i=Xe(e,r,o);if(i===void 0)return"has-commits";if(i===0){let s=Xe(e,o,r);return s===void 0?"has-commits":s>0?xt(e,r,o)?"merged":"base-advanced":et(t)?"dirty-uncommitted":"no-change"}return et(t)?"dirty-uncommitted":Yo(e,r,o)?"released":"has-commits"}isResolvedWorktreeEligibleForCleanup(e,t,r){if(!e.worktreePath||!e.workdir||!$m(e.worktreePath)||e.pendingWorktreeDecisionSince||e.worktreeState==="pending_decision"||e.pendingPlanApproval||e.resumable||e.worktreeBranch&&oe(e.worktreePath)!==e.worktreeBranch)return!1;let o=e.worktreeMergedAt??e.worktreeDismissedAt??e.completedAt??e.createdAt,i=typeof o=="string"?new Date(o).getTime():Number(o??0);return!!i&&t-i>=r}};import{randomUUID as Em}from"node:crypto";function Nm(n){let e=n.pendingInputState,t=e?.activeQuestionIndex??0;return e?.questions?.[t]?.id??(e?.activeQuestionIndex!=null?`q${e.activeQuestionIndex}`:void 0)}var lr=class{constructor(e,t,r,o){this.pendingQuestions=e;this.dispatchSessionNotification=t;this.clearWaitingTimestamp=r;this.getQuestionButtons=o}pendingQuestions;dispatchSessionNotification;clearWaitingTimestamp;getQuestionButtons;async handleAskUserQuestion(e,t){let i=t?.questions??[];if(i.length===0)throw new Error("AskUserQuestion: no questions in input");let s=i[0],a=s.options??[],l=`❓ [${e.name}] ${s.question}`,d=Nm(e),u=e.pendingInputState?.requestId??`legacy:${Em()}`,f=this.getQuestionButtons(e.id,a,{requestId:u,questionId:d}),h=[`[ASK USER QUESTION] Session "${e.name}" has a question requiring user input.`,"",`Question: ${s.question}`,...a.length>0?["Options:",...a.map((k,g)=>` ${g+1}. ${k.label}`)]:[],"",`Send the question to the user and call agent_respond(session="${e.id}", message="<answer>") with their answer.`].join(`
209
- `);return new Promise((k,g)=>{let p=this.pendingQuestions.get(e.id);p&&(clearTimeout(p.timeoutHandle),p.reject(new Error(`AskUserQuestion superseded by a newer question for session "${e.name}".`)));let y=setTimeout(()=>{this.pendingQuestions.delete(e.id),g(new Error(`AskUserQuestion timed out after ${6e5/1e3}s for session "${e.name}"`))},6e5);y.unref?.(),this.pendingQuestions.set(e.id,{resolve:k,reject:g,questions:i,timeoutHandle:y,requestId:u,questionId:d}),this.dispatchSessionNotification(e,{label:"ask-user-question",idempotencyKey:`ask-user-question:${e.id}:${u}`,userMessage:l,notifyUser:"always",buttons:f,wakeMessageOnNotifySuccess:["AskUserQuestion delivered to the user.",`Session: ${e.name} | ID: ${e.id}`,`Question: ${s.question}`,"Await their selection — do NOT answer this question yourself."].join(`
210
- `),wakeMessageOnNotifyFailed:h})})}resolveAskUserQuestion(e,t,r={}){let o=this.pendingQuestions.get(e);if(!o)return`${e}`,!1;if(r.requestId&&r.requestId!==o.requestId)return`${e}${o.requestId}${r.requestId}`,!1;if(r.questionId&&r.questionId!==o.questionId)return`${e}${o.questionId??""}${r.questionId}`,!1;let i=o.questions[0],s=i.options??[],a=s[t];return a?(clearTimeout(o.timeoutHandle),this.pendingQuestions.delete(e),this.clearWaitingTimestamp(e),o.resolve({behavior:"allow",updatedInput:{questions:o.questions,answers:{[i.question]:a.label}}}),!0):(`${t}${e}${s.length}`,!1)}dispose(){for(let e of this.pendingQuestions.values())clearTimeout(e.timeoutHandle),e.reject(new Error("SessionManager disposed before AskUserQuestion resolved."));this.pendingQuestions.clear()}};var Om=new Set(["merged","released","dismissed","none","cleanup_failed"]),Wm=new Set(["merged","released","dismissed","no_change","none","cleanup_failed"]),dr=class n{constructor(e,t,r,o){this.buildRoutingProxy=e;this.dispatchNotification=t;this.updatePersistedSession=r;this.getWorktreeDecisionButtons=o}buildRoutingProxy;dispatchNotification;updatePersistedSession;getWorktreeDecisionButtons;static REMINDER_THRESHOLD_MS=10800*1e3;static REMINDER_INTERVAL_MS=10800*1e3;getNextReminderAt(e){let t=new Date(e.pendingWorktreeDecisionSince).getTime();if(this.getWorktreeDecisionReminderStatus(e,t)!=="pending")return;let r=[t+n.REMINDER_THRESHOLD_MS];if(e.worktreeDecisionSnoozedUntil){let o=new Date(e.worktreeDecisionSnoozedUntil).getTime();Number.isFinite(o)&&r.push(o)}if(e.lastWorktreeReminderAt){let o=new Date(e.lastWorktreeReminderAt).getTime();Number.isFinite(o)&&r.push(o+n.REMINDER_INTERVAL_MS)}return Math.max(...r)}sendReminderIfDue(e,t=Date.now()){this.clearResolvedReminderState(e);let r=this.getNextReminderAt(e);if(r==null||r>t)return!1;let o=t-new Date(e.pendingWorktreeDecisionSince).getTime(),i=Math.floor(Math.max(0,o)/(3600*1e3));try{this.sendReminderNotification(e,i)}catch(s){return`${e.name}${s instanceof Error?s.message:String(s)}`,!1}for(let s of z(e))this.updatePersistedSession(s,{lastWorktreeReminderAt:new Date(t).toISOString()});return!0}sendReminderNotification(e,t){let r=this.buildRoutingProxy({id:e.sessionId??e.name??C(e)??e.harnessSessionId,sessionId:e.sessionId,harnessSessionId:e.harnessSessionId,backendRef:e.backendRef,route:e.route});if(e.worktreeStrategy==="delegate"){this.dispatchNotification(r,{label:`worktree-stale-reminder-${e.name}`,wakeMessage:vo(e,t),notifyUser:"never"});return}let o=[`⏰ Reminder: branch \`${e.worktreeBranch??"unknown"}\` is still waiting for a merge decision.`,`Session: ${e.name} | Pending: ${t}h`,"",`agent_merge(session="${e.name}") or agent_pr(session="${e.name}") or agent_worktree_cleanup() to resolve.`].join(`
211
- `);this.dispatchNotification(r,{label:`worktree-stale-reminder-${e.name}`,userMessage:o,notifyUser:"always",buttons:this.getWorktreeDecisionButtons(D(e)??e.harnessSessionId,e)})}clearResolvedReminderState(e){if(!e.pendingWorktreeDecisionSince&&!e.lastWorktreeReminderAt&&!e.worktreeDecisionSnoozedUntil||!this.isResolvedWorktreeDecision(e))return!1;let t=!1;for(let r of z(e))t=this.updatePersistedSession(r,{pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0})||t;return t}getWorktreeDecisionReminderStatus(e,t){if(this.hasResolvedWorktreeDecisionMarker(e))return"resolved";if(!e.pendingWorktreeDecisionSince)return"inactive";let r=t??new Date(e.pendingWorktreeDecisionSince).getTime();if(!Number.isFinite(r))return"inactive";let o=e.worktreeState==="pending_decision"||e.lifecycle==="awaiting_worktree_decision"||e.worktreeLifecycle?.state==="pending_decision",i=e.worktreeState==null&&e.lifecycle==null&&e.worktreeLifecycle?.state==null&&!e.worktreeMerged&&!e.worktreePrUrl;if(!o&&!i)return"inactive";let s=Oe(e,{activeSession:!1,includePrSync:!1});return this.isResolvedDerivedWorktreeState(s.derivedState)?"resolved":"pending"}isResolvedWorktreeDecision(e){if(this.hasResolvedWorktreeDecisionMarker(e))return!0;let t=Oe(e,{activeSession:!1,includePrSync:!1});return this.isResolvedDerivedWorktreeState(t.derivedState)}hasResolvedWorktreeDecisionMarker(e){return!!(e.worktreeMerged||e.worktreePrUrl||e.lifecycle==="terminal"||e.worktreeState&&Om.has(e.worktreeState)||e.worktreeLifecycle?.state&&Wm.has(e.worktreeLifecycle.state))}isResolvedDerivedWorktreeState(e){return e==="merged"||e==="released"||e==="no_change"||e==="cleanup_failed"}};function ht(n,e){return e!=null&&n.approvalPromptRequiredVersion===e&&Lm(n.approvalPromptStatus)}function Lm(n){return n==="delivered"||n==="fallback_delivered"}function yt(n,e){return!n||e==null?!1:!!(n.pendingPlanApproval&&n.approvalState==="pending"&&n.lifecycle==="awaiting_plan_decision"&&(n.actionablePlanDecisionVersion??n.planDecisionVersion)===e)}function He(n,e,t=!1){let r="id"in n?n.id:n.sessionId??"unknown-session";return[t?"Plan review fallback text delivered to the user because interactive buttons could not be delivered.":"Plan approval buttons delivered to the user.",`Session: ${n.name??"unknown"} | ID: ${r} | Plan v${e??"?"}`,`Wait for their ${t?"explicit reply":"button callback"} — do NOT approve or reject this plan yourself.`].join(`
208
+ `)}`:void 0}}buildNotificationDedupeKey(e,t){let r=t.idempotencyKey?.trim();if(!r)return;let o=this.getDeliveryRef(e);if(!o)return;let i=le(e),s=i?{provider:i.provider,accountId:i.accountId,target:i.target,threadId:i.threadId}:{deliveryRef:o};return`notification:${this.digest(JSON.stringify({scope:s,semanticKey:r}))}`}markNotificationDedupeDelivered(e,t,r){let o=this.notificationDedupe.deliveredRecords(t,e?this.getPersistedSession?.(e)?.notificationDedupe:void 0,r);o&&this.applyNotificationDedupePatch(e,o)}releaseNotificationDedupe(e,t){let r=this.notificationDedupe.releasedRecords(t,e?this.getPersistedSession?.(e)?.notificationDedupe:void 0);r&&this.applyNotificationDedupePatch(e,r)}applyNotificationDedupePatch(e,t){this.getPersistedSession&&e&&this.applyPersistedPatch(e,{notificationDedupe:t})}markCompletionSummaryDelivered(e,t,r,o){let i=this.completionSummaries.completionRecordsAfterDelivery(t,e?this.getPersistedSession?.(e)?.completionSummaryDedupe:void 0,r,o);i&&this.applyCompletionSummaryDedupePatch(e,i)}applyCompletionSummaryDedupePatch(e,t){this.getPersistedSession&&e&&this.applyPersistedPatch(e,{completionSummaryDedupe:t})}logNotificationDecision(e){let t=le(e.session);Mm({event:"oca_notification_decision",sessionId:"id"in e.session?e.session.id:e.session.sessionId,sessionName:e.session.name,harnessSessionId:e.session.harnessSessionId,originRoute:t?{provider:t.provider,accountId:t.accountId,target:t.target,threadId:t.threadId,sessionKey:t.sessionKey}:void 0,outcomeType:e.outcomeKey?.split(":").slice(0,2).join(":")??e.request.label,notificationKind:e.request.label,followupKind:e.followupKind,dedupeKey:e.dedupeKey,deliveryPath:e.deliveryPath,decision:e.decision,reason:e.reason,completionWakeSummaryRequired:e.request.completionWakeSummaryRequired,deliveryRef:e.deliveryRef})}digest(e){return Im("sha256").update(e).digest("hex").slice(0,16)}};function Dm(n,e){let t=ye(e);return t?`${n}${t}`:n}import{existsSync as $m}from"fs";var ar=class{getCompletionState(e,t,r,o){if(oe(t)!==r)return"has-commits";let i=Xe(e,r,o);if(i===void 0)return"has-commits";if(i===0){let s=Xe(e,o,r);return s===void 0?"has-commits":s>0?Ct(e,r,o)?"merged":"base-advanced":et(t)?"dirty-uncommitted":"no-change"}return et(t)?"dirty-uncommitted":Yo(e,r,o)?"released":"has-commits"}isResolvedWorktreeEligibleForCleanup(e,t,r){if(!e.worktreePath||!e.workdir||!$m(e.worktreePath)||e.pendingWorktreeDecisionSince||e.worktreeState==="pending_decision"||e.pendingPlanApproval||e.resumable||e.worktreeBranch&&oe(e.worktreePath)!==e.worktreeBranch)return!1;let o=e.worktreeMergedAt??e.worktreeDismissedAt??e.completedAt??e.createdAt,i=typeof o=="string"?new Date(o).getTime():Number(o??0);return!!i&&t-i>=r}};import{randomUUID as Em}from"node:crypto";function Nm(n){let e=n.pendingInputState,t=e?.activeQuestionIndex??0;return e?.questions?.[t]?.id??(e?.activeQuestionIndex!=null?`q${e.activeQuestionIndex}`:void 0)}var lr=class{constructor(e,t,r,o){this.pendingQuestions=e;this.dispatchSessionNotification=t;this.clearWaitingTimestamp=r;this.getQuestionButtons=o}pendingQuestions;dispatchSessionNotification;clearWaitingTimestamp;getQuestionButtons;async handleAskUserQuestion(e,t){let i=t?.questions??[];if(i.length===0)throw new Error("AskUserQuestion: no questions in input");let s=i[0],a=s.options??[],l=`❓ [${e.name}] ${s.question}`,d=Nm(e),u=e.pendingInputState?.requestId??`legacy:${Em()}`,f=this.getQuestionButtons(e.id,a,{requestId:u,questionId:d}),g=[`[ASK USER QUESTION] Session "${e.name}" has a question requiring user input.`,"",`Question: ${s.question}`,...a.length>0?["Options:",...a.map((k,h)=>` ${h+1}. ${k.label}`)]:[],"",`Send the question to the user and call agent_respond(session="${e.id}", message="<answer>") with their answer.`].join(`
209
+ `);return new Promise((k,h)=>{let p=this.pendingQuestions.get(e.id);p&&(clearTimeout(p.timeoutHandle),p.reject(new Error(`AskUserQuestion superseded by a newer question for session "${e.name}".`)));let y=setTimeout(()=>{this.pendingQuestions.delete(e.id),h(new Error(`AskUserQuestion timed out after ${6e5/1e3}s for session "${e.name}"`))},6e5);y.unref?.(),this.pendingQuestions.set(e.id,{resolve:k,reject:h,questions:i,timeoutHandle:y,requestId:u,questionId:d}),this.dispatchSessionNotification(e,{label:"ask-user-question",idempotencyKey:`ask-user-question:${e.id}:${u}`,userMessage:l,notifyUser:"always",buttons:f,wakeMessageOnNotifySuccess:["AskUserQuestion delivered to the user.",`Session: ${e.name} | ID: ${e.id}`,`Question: ${s.question}`,"Await their selection — do NOT answer this question yourself."].join(`
210
+ `),wakeMessageOnNotifyFailed:g})})}resolveAskUserQuestion(e,t,r={}){let o=this.pendingQuestions.get(e);if(!o)return`${e}`,!1;if(r.requestId&&r.requestId!==o.requestId)return`${e}${o.requestId}${r.requestId}`,!1;if(r.questionId&&r.questionId!==o.questionId)return`${e}${o.questionId??""}${r.questionId}`,!1;let i=o.questions[0],s=i.options??[],a=s[t];return a?(clearTimeout(o.timeoutHandle),this.pendingQuestions.delete(e),this.clearWaitingTimestamp(e),o.resolve({behavior:"allow",updatedInput:{questions:o.questions,answers:{[i.question]:a.label}}}),!0):(`${t}${e}${s.length}`,!1)}dispose(){for(let e of this.pendingQuestions.values())clearTimeout(e.timeoutHandle),e.reject(new Error("SessionManager disposed before AskUserQuestion resolved."));this.pendingQuestions.clear()}};var Om=new Set(["merged","released","dismissed","none","cleanup_failed"]),Wm=new Set(["merged","released","dismissed","no_change","none","cleanup_failed"]),dr=class n{constructor(e,t,r,o){this.buildRoutingProxy=e;this.dispatchNotification=t;this.updatePersistedSession=r;this.getWorktreeDecisionButtons=o}buildRoutingProxy;dispatchNotification;updatePersistedSession;getWorktreeDecisionButtons;static REMINDER_THRESHOLD_MS=10800*1e3;static REMINDER_INTERVAL_MS=10800*1e3;getNextReminderAt(e){let t=new Date(e.pendingWorktreeDecisionSince).getTime();if(this.getWorktreeDecisionReminderStatus(e,t)!=="pending")return;let r=[t+n.REMINDER_THRESHOLD_MS];if(e.worktreeDecisionSnoozedUntil){let o=new Date(e.worktreeDecisionSnoozedUntil).getTime();Number.isFinite(o)&&r.push(o)}if(e.lastWorktreeReminderAt){let o=new Date(e.lastWorktreeReminderAt).getTime();Number.isFinite(o)&&r.push(o+n.REMINDER_INTERVAL_MS)}return Math.max(...r)}sendReminderIfDue(e,t=Date.now()){this.clearResolvedReminderState(e);let r=this.getNextReminderAt(e);if(r==null||r>t)return!1;let o=t-new Date(e.pendingWorktreeDecisionSince).getTime(),i=Math.floor(Math.max(0,o)/(3600*1e3));try{this.sendReminderNotification(e,i)}catch(s){return`${e.name}${s instanceof Error?s.message:String(s)}`,!1}for(let s of z(e))this.updatePersistedSession(s,{lastWorktreeReminderAt:new Date(t).toISOString()});return!0}sendReminderNotification(e,t){let r=this.buildRoutingProxy({id:e.sessionId??e.name??C(e)??e.harnessSessionId,sessionId:e.sessionId,harnessSessionId:e.harnessSessionId,backendRef:e.backendRef,route:e.route});if(e.worktreeStrategy==="delegate"){this.dispatchNotification(r,{label:`worktree-stale-reminder-${e.name}`,wakeMessage:vo(e,t),notifyUser:"never"});return}let o=[`⏰ Reminder: branch \`${e.worktreeBranch??"unknown"}\` is still waiting for a merge decision.`,`Session: ${e.name} | Pending: ${t}h`,"",`agent_merge(session="${e.name}") or agent_pr(session="${e.name}") or agent_worktree_cleanup() to resolve.`].join(`
211
+ `);this.dispatchNotification(r,{label:`worktree-stale-reminder-${e.name}`,userMessage:o,notifyUser:"always",buttons:this.getWorktreeDecisionButtons(D(e)??e.harnessSessionId,e)})}clearResolvedReminderState(e){if(!e.pendingWorktreeDecisionSince&&!e.lastWorktreeReminderAt&&!e.worktreeDecisionSnoozedUntil||!this.isResolvedWorktreeDecision(e))return!1;let t=!1;for(let r of z(e))t=this.updatePersistedSession(r,{pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0})||t;return t}getWorktreeDecisionReminderStatus(e,t){if(this.hasResolvedWorktreeDecisionMarker(e))return"resolved";if(!e.pendingWorktreeDecisionSince)return"inactive";let r=t??new Date(e.pendingWorktreeDecisionSince).getTime();if(!Number.isFinite(r))return"inactive";let o=e.worktreeState==="pending_decision"||e.lifecycle==="awaiting_worktree_decision"||e.worktreeLifecycle?.state==="pending_decision",i=e.worktreeState==null&&e.lifecycle==null&&e.worktreeLifecycle?.state==null&&!e.worktreeMerged&&!e.worktreePrUrl;if(!o&&!i)return"inactive";let s=Oe(e,{activeSession:!1,includePrSync:!1});return this.isResolvedDerivedWorktreeState(s.derivedState)?"resolved":"pending"}isResolvedWorktreeDecision(e){if(this.hasResolvedWorktreeDecisionMarker(e))return!0;let t=Oe(e,{activeSession:!1,includePrSync:!1});return this.isResolvedDerivedWorktreeState(t.derivedState)}hasResolvedWorktreeDecisionMarker(e){return!!(e.worktreeMerged||e.worktreePrUrl||e.lifecycle==="terminal"||e.worktreeState&&Om.has(e.worktreeState)||e.worktreeLifecycle?.state&&Wm.has(e.worktreeLifecycle.state))}isResolvedDerivedWorktreeState(e){return e==="merged"||e==="released"||e==="no_change"||e==="cleanup_failed"}};function yt(n,e){return e!=null&&n.approvalPromptRequiredVersion===e&&Fm(n.approvalPromptStatus)}function Fm(n){return n==="delivered"||n==="fallback_delivered"}function St(n,e){return!n||e==null?!1:!!(n.pendingPlanApproval&&n.approvalState==="pending"&&n.lifecycle==="awaiting_plan_decision"&&(n.actionablePlanDecisionVersion??n.planDecisionVersion)===e)}function He(n,e,t=!1){let r="id"in n?n.id:n.sessionId??"unknown-session";return[t?"Plan review fallback text delivered to the user because interactive buttons could not be delivered.":"Plan approval buttons delivered to the user.",`Session: ${n.name??"unknown"} | ID: ${r} | Plan v${e??"?"}`,`Wait for their ${t?"explicit reply":"button callback"} — do NOT approve or reject this plan yourself.`].join(`
212
212
  `)}function ur(n){let e="id"in n.session?n.session.id:n.session.sessionId??"unknown-session",t=n.originThreadLine??(n.session.originThreadId!=null?`Origin thread: ${n.session.originThreadId}`:"");return["[PLAN APPROVAL DELIVERY FAILED] The plugin could not deliver the canonical plan review buttons or the explicit fallback text to the user.",`Name: ${n.session.name??"unknown"} | ID: ${e} | Plan v${n.planDecisionVersion??"?"}`,t,"","No user-visible actionable review prompt is confirmed for this plan version.","Intervene manually before assuming the user saw the plan review request."].filter(Boolean).join(`
213
- `)}import{existsSync as Hm,readFileSync as Qm}from"fs";var Fm=4e3,Ua=180,Bm=300;function Ga(){let n=xe(),e=Vm(n);if(e)return{async generateQuestionContextSummary(t){if(typeof e.generateQuestionContextSummary=="function")return await e.generateQuestionContextSummary(t);if(typeof e.summarizeQuestionContext=="function")return await e.summarizeQuestionContext(t);let r=Um(t);if(typeof e.generateObject=="function")return await e.generateObject({task:"openclaw-code-agent.question-context-summary",prompt:r,input:t});if(typeof e.generateText=="function")return await e.generateText({task:"openclaw-code-agent.question-context-summary",prompt:r});if(typeof e.complete=="function")return await e.complete({prompt:r})}}}async function ja(n){let e=pr(n.question??""),t=pr(Gm(e,n.context??""));if(!n.provider||!e||!t)return;let r={sessionName:n.sessionName,question:e,context:jm(t,Fm)};try{let o=await zm(n.provider.generateQuestionContextSummary(r),n.timeoutMs??Bm);return Km(o)}catch(o){let i=o instanceof Error?o.message:String(o);i!=="question-context-summary timed out"&&`${i}`;return}}function Km(n){let e=qm(n),t=typeof e=="string"?e:e&&typeof e=="object"&&typeof e.summary=="string"?e.summary:void 0,r=pr(t??"").replace(/^[-*•]\s+/,"").trim();if(!(!r||r.length>Ua)&&!(r.split(/[.!?]+/).filter(o=>o.trim()).length>1))return r}function qm(n){if(typeof n!="string")return n;let e=n.trim();if(e)try{return JSON.parse(e)}catch{return e}}function Vm(n){return[n?.questionContextSummary,n?.llm,n?.ai,n?.model,n?.models].find(t=>!!(t&&typeof t=="object"&&(typeof t.generateQuestionContextSummary=="function"||typeof t.summarizeQuestionContext=="function"||typeof t.generateObject=="function"||typeof t.generateText=="function"||typeof t.complete=="function")))}function Um(n){return["Summarize why an OpenClaw Code Agent question is being asked.",'Return only JSON with shape {"summary":"..."}.',`Write one concise user-facing sentence under ${Ua} characters.`,"Do not answer the question. Do not invent choices. Do not alter option labels or semantics.","","Evidence:",JSON.stringify(n,null,2)].join(`
213
+ `)}import{existsSync as Hm,readFileSync as Qm}from"fs";var Lm=4e3,Ua=180,Bm=300;function Ga(){let n=xe(),e=Vm(n);if(e)return{async generateQuestionContextSummary(t){if(typeof e.generateQuestionContextSummary=="function")return await e.generateQuestionContextSummary(t);if(typeof e.summarizeQuestionContext=="function")return await e.summarizeQuestionContext(t);let r=Um(t);if(typeof e.generateObject=="function")return await e.generateObject({task:"openclaw-code-agent.question-context-summary",prompt:r,input:t});if(typeof e.generateText=="function")return await e.generateText({task:"openclaw-code-agent.question-context-summary",prompt:r});if(typeof e.complete=="function")return await e.complete({prompt:r})}}}async function ja(n){let e=pr(n.question??""),t=pr(Gm(e,n.context??""));if(!n.provider||!e||!t)return;let r={sessionName:n.sessionName,question:e,context:jm(t,Lm)};try{let o=await zm(n.provider.generateQuestionContextSummary(r),n.timeoutMs??Bm);return Km(o)}catch(o){let i=o instanceof Error?o.message:String(o);i!=="question-context-summary timed out"&&`${i}`;return}}function Km(n){let e=qm(n),t=typeof e=="string"?e:e&&typeof e=="object"&&typeof e.summary=="string"?e.summary:void 0,r=pr(t??"").replace(/^[-*•]\s+/,"").trim();if(!(!r||r.length>Ua)&&!(r.split(/[.!?]+/).filter(o=>o.trim()).length>1))return r}function qm(n){if(typeof n!="string")return n;let e=n.trim();if(e)try{return JSON.parse(e)}catch{return e}}function Vm(n){return[n?.questionContextSummary,n?.llm,n?.ai,n?.model,n?.models].find(t=>!!(t&&typeof t=="object"&&(typeof t.generateQuestionContextSummary=="function"||typeof t.summarizeQuestionContext=="function"||typeof t.generateObject=="function"||typeof t.generateText=="function"||typeof t.complete=="function")))}function Um(n){return["Summarize why an OpenClaw Code Agent question is being asked.",'Return only JSON with shape {"summary":"..."}.',`Write one concise user-facing sentence under ${Ua} characters.`,"Do not answer the question. Do not invent choices. Do not alter option labels or semantics.","","Evidence:",JSON.stringify(n,null,2)].join(`
214
214
  `)}function Gm(n,e){return n?e.split(/\r?\n/).filter(t=>pr(t)!==n).join(`
215
215
  `):e}function pr(n){return n.replace(/\s+/g," ").trim()}function jm(n,e){return n.length<=e?n:`${n.slice(0,Math.max(0,e-3)).trimEnd()}...`}function zm(n,e){return new Promise((t,r)=>{let o=setTimeout(()=>r(new Error("question-context-summary timed out")),e);o.unref?.(),n.then(i=>{clearTimeout(o),t(i)},i=>{clearTimeout(o),r(i)})})}var Ym=280;function Jm(n,e){if(n.latestPlanArtifactVersion===e&&n.latestPlanArtifact)return n.latestPlanArtifact;let t=n.planFilePath?.trim();if(!(!t||!Hm(t)))try{let r=Qm(t,"utf-8").trim();return r?{markdown:r,steps:[]}:void 0}catch{return}}function Xm(n){let e=[n.total>1?`Question ${n.index+1}`:void 0,n.question.header].filter(Boolean).join(" - "),t=[...e?[e]:[],n.question.question];return n.optionDescriptions.length>0&&t.push("","Options:",...n.optionDescriptions.map(r=>`${r.label} - ${r.description}`)),t.join(`
216
- `)}function Zm(n){return n.options.map(e=>({label:e.label,description:e.description?.trim()??""})).filter(e=>e.description&&e.description.length<=Ym)}function Ha(n){let e=n?.activeQuestionIndex??0;return n?.questions?.[e]?.id??(n?.activeQuestionIndex!=null?`q${n.activeQuestionIndex}`:void 0)}function ef(n,e,t){let r=n.pendingInputState;return!!(r&&r.requestId===e&&Ha(r)===t)}function tf(n){return[n.startedAt??"unknown-started-at",n.result?.session_id??"unknown-backend-session",n.result?.num_turns??0].join(":")}function za(n){return[n.status,n.startedAt??"unknown-started-at",n.result?.session_id??"unknown-backend-session",n.result?.num_turns??0,n.killReason??"unknown"].join(":")}var cr=class{constructor(e){this.deps=e}deps;dispatchPlanApprovalFallback(e,t,r){let o=new Date().toISOString();this.deps.dispatchSessionNotification(e,{label:"plan-approval-fallback",idempotencyKey:`plan-approval:${e.id}:v${t??"unknown"}:fallback`,userMessage:ct({session:e,summary:r}),notifyUser:"always",shouldDispatch:()=>yt(e,t),hooks:{onNotifyStarted:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"sending",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o})},onNotifySucceeded:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"fallback_delivered",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o,approvalPromptDeliveredAt:new Date().toISOString(),approvalPromptFailedAt:void 0})},onNotifyFailed:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"failed",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o,approvalPromptFailedAt:new Date().toISOString()})}},wakeMessageOnNotifySuccess:He(e,t,!0),wakeMessageOnNotifyFailed:ur({session:e,planDecisionVersion:t,originThreadLine:this.deps.originThreadLine(e)})})}logCompletionWakeDiagnostic(e){JSON.stringify({event:e.event,sessionId:e.session.id,sessionName:e.session.name,canonicalStatusDelivered:e.canonicalStatusDelivered,requestedShortFactualSummary:e.followupSummaryRequired,completionKind:"terminal"})}shouldRequestCompletionFollowup(e){return e.originSessionKey?.trim()?.startsWith("agent:main:cron:")?!1:!!le(e)}async handleTurnEnd(e,t){if(e.status!=="running"){`${e.id}${e.status}`;return}if(!e.goalTaskId){if(t||e.pendingPlanApproval){await this.emitWaitingForInput(e);return}if(e.worktreeStrategy==="ask"||e.worktreeStrategy==="delegate"){`${e.id}${e.worktreeStrategy}`;return}this.deps.shouldEmitTurnCompleteWake(e)&&this.emitTurnComplete(e)}}async handleSessionTerminal(e){if(this.deps.persistSession(e),this.deps.clearWaitingTimestamp(e.id),e.goalTaskId){this.deps.clearRetryTimersForSession(e.id);return}if(e.pendingPlanApproval){e.killReason==="idle-timeout"&&e.pendingPlanApproval?this.emitIdleTimeoutPlanApproval(e):await this.emitWaitingForInput(e),this.deps.clearRetryTimersForSession(e.id);return}let t={notificationSent:!1,worktreeRemoved:!1};e.worktreePath&&e.originalWorkdir&&(t=await this.deps.handleWorktreeStrategy(e));let r=!1;if(e.worktreePath&&e.originalWorkdir&&e.status==="failed"&&e.costUsd===0&&e.duration<3e4){let a=this.deps.resolveWorktreeRepoDir(e.originalWorkdir,e.worktreePath),l=e.worktreeBranch,d=F(e);`${e.name}${e.costUsd.toFixed(2)}${e.duration}`;let u=!1;if(a&&!d&&(u=B(a,e.worktreePath)),a&&l&&!d&&u&&H(a,l),u){for(let f of z(e))this.deps.updatePersistedSession(f,{worktreePath:void 0,worktreeBranch:void 0});r=!0}}let o=e.worktreeStrategy&&e.worktreeStrategy!=="off"&&e.worktreeStrategy!=="manual";if(!r&&e.worktreePath&&e.originalWorkdir){let a=this.deps.resolveWorktreeRepoDir(e.originalWorkdir,e.worktreePath),l=F(e);t.worktreeRemoved?`${e.name}`:o?`${e.name}${e.worktreeStrategy}`:a&&!l&&B(a,e.worktreePath)}if(t.notificationSent){`${e.id}`;return}if(e.killReason==="done"){if(this.deps.hasTurnCompleteWakeMarker(e.id)||!this.deps.shouldEmitTerminalWake(e))return;this.emitCompleted(e);return}if(e.status==="completed"){if(!this.deps.shouldEmitTerminalWake(e))return;this.emitCompleted(e);return}if(e.status==="failed"){if(!this.deps.shouldEmitTerminalWake(e))return;let a=e.error||e.result?.is_error&&e.result.result||e.result?.result||this.deps.extractLastOutputLine(e)||`Session failed with no error details (session=${e.id}, subtype=${e.result?.subtype??"none"}, turns=${e.result?.num_turns??0})`;this.emitFailed(e,q(a,200),r);return}let i=`$${(e.costUsd??0).toFixed(2)}`,s=e.duration;if(e.killReason==="idle-timeout"){if(e.pendingPlanApproval){this.emitIdleTimeoutPlanApproval(e),this.deps.clearRetryTimersForSession(e.id);return}this.deps.dispatchSessionNotification(e,{label:"suspended",idempotencyKey:`suspended:${e.id}:${e.killReason??"idle-timeout"}:${e.completedAt??"unknown"}`,userMessage:`💤 [${e.name}] Suspended after idle timeout | ${i} | ${se(s)}`,notifyUser:"always",buttons:this.deps.getResumeButtons(e.id,e)}),this.deps.clearRetryTimersForSession(e.id);return}this.deps.notifySession(e,`⛔ [${e.name}] ${mo(e.killReason)} | ${i} | ${se(s)}`),this.deps.clearRetryTimersForSession(e.id)}emitIdleTimeoutPlanApproval(e){let t=this.deps.resolvePlanApprovalMode(e),r=e.actionablePlanDecisionVersion??e.planDecisionVersion,o=ht(e,r);if(t==="delegate"){this.deps.dispatchSessionNotification(e,{label:"plan-approval-timeout",idempotencyKey:`plan-approval-timeout:${e.id}:v${r??"unknown"}:delegate`,wakeMessage:["[DELEGATED PLAN APPROVAL REMINDER] Plan review is still pending after the session hit idle timeout.",`Name: ${e.name} | ID: ${e.id}`,this.deps.originThreadLine(e),"The agent already produced a plan and is waiting for a delegated decision.","Review privately first. Approve directly with agent_respond(..., approve=true, approval_rationale='...') if the plan is clearly within scope and low risk.","Escalate only if needed via agent_request_plan_approval(summary='...').","If you approve directly, follow up with a short user-facing explanation; the plugin's thumbs-up line is only the minimal approval acknowledgment.","If a canonical approval prompt was already posted for this plan version, do not restate it in plain text."].join(`
216
+ `)}function Zm(n){return n.options.map(e=>({label:e.label,description:e.description?.trim()??""})).filter(e=>e.description&&e.description.length<=Ym)}function Ha(n){let e=n?.activeQuestionIndex??0;return n?.questions?.[e]?.id??(n?.activeQuestionIndex!=null?`q${n.activeQuestionIndex}`:void 0)}function ef(n,e,t){let r=n.pendingInputState;return!!(r&&r.requestId===e&&Ha(r)===t)}function tf(n){return[n.startedAt??"unknown-started-at",n.result?.session_id??"unknown-backend-session",n.result?.num_turns??0].join(":")}function za(n){return[n.status,n.startedAt??"unknown-started-at",n.result?.session_id??"unknown-backend-session",n.result?.num_turns??0,n.killReason??"unknown"].join(":")}var cr=class{constructor(e){this.deps=e}deps;dispatchPlanApprovalFallback(e,t,r){let o=new Date().toISOString();this.deps.dispatchSessionNotification(e,{label:"plan-approval-fallback",idempotencyKey:`plan-approval:${e.id}:v${t??"unknown"}:fallback`,userMessage:mt({session:e,summary:r}),notifyUser:"always",shouldDispatch:()=>St(e,t),hooks:{onNotifyStarted:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"sending",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o})},onNotifySucceeded:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"fallback_delivered",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o,approvalPromptDeliveredAt:new Date().toISOString(),approvalPromptFailedAt:void 0})},onNotifyFailed:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"failed",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o,approvalPromptFailedAt:new Date().toISOString()})}},wakeMessageOnNotifySuccess:He(e,t,!0),wakeMessageOnNotifyFailed:ur({session:e,planDecisionVersion:t,originThreadLine:this.deps.originThreadLine(e)})})}logCompletionWakeDiagnostic(e){JSON.stringify({event:e.event,sessionId:e.session.id,sessionName:e.session.name,canonicalStatusDelivered:e.canonicalStatusDelivered,requestedShortFactualSummary:e.followupSummaryRequired,completionKind:"terminal"})}shouldRequestCompletionFollowup(e){return e.originSessionKey?.trim()?.startsWith("agent:main:cron:")?!1:!!le(e)}async handleTurnEnd(e,t){if(e.status!=="running"){`${e.id}${e.status}`;return}if(!e.goalTaskId){if(t||e.pendingPlanApproval){await this.emitWaitingForInput(e);return}if(e.worktreeStrategy==="ask"||e.worktreeStrategy==="delegate"){`${e.id}${e.worktreeStrategy}`;return}this.deps.shouldEmitTurnCompleteWake(e)&&this.emitTurnComplete(e)}}async handleSessionTerminal(e){if(this.deps.persistSession(e),this.deps.clearWaitingTimestamp(e.id),e.goalTaskId){this.deps.clearRetryTimersForSession(e.id);return}if(e.pendingPlanApproval){e.killReason==="idle-timeout"&&e.pendingPlanApproval?this.emitIdleTimeoutPlanApproval(e):await this.emitWaitingForInput(e),this.deps.clearRetryTimersForSession(e.id);return}let t={notificationSent:!1,worktreeRemoved:!1};e.worktreePath&&e.originalWorkdir&&(t=await this.deps.handleWorktreeStrategy(e));let r=!1;if(e.worktreePath&&e.originalWorkdir&&e.status==="failed"&&e.costUsd===0&&e.duration<3e4){let a=this.deps.resolveWorktreeRepoDir(e.originalWorkdir,e.worktreePath),l=e.worktreeBranch,d=L(e);`${e.name}${e.costUsd.toFixed(2)}${e.duration}`;let u=!1;if(a&&!d&&(u=B(a,e.worktreePath)),a&&l&&!d&&u&&H(a,l),u){for(let f of z(e))this.deps.updatePersistedSession(f,{worktreePath:void 0,worktreeBranch:void 0});r=!0}}let o=e.worktreeStrategy&&e.worktreeStrategy!=="off"&&e.worktreeStrategy!=="manual";if(!r&&e.worktreePath&&e.originalWorkdir){let a=this.deps.resolveWorktreeRepoDir(e.originalWorkdir,e.worktreePath),l=L(e);t.worktreeRemoved?`${e.name}`:o?`${e.name}${e.worktreeStrategy}`:a&&!l&&B(a,e.worktreePath)}if(t.notificationSent){`${e.id}`;return}if(e.killReason==="done"){if(this.deps.hasTurnCompleteWakeMarker(e.id)||!this.deps.shouldEmitTerminalWake(e))return;this.emitCompleted(e);return}if(e.status==="completed"){if(!this.deps.shouldEmitTerminalWake(e))return;this.emitCompleted(e);return}if(e.status==="failed"){if(!this.deps.shouldEmitTerminalWake(e))return;let a=e.error||e.result?.is_error&&e.result.result||e.result?.result||this.deps.extractLastOutputLine(e)||`Session failed with no error details (session=${e.id}, subtype=${e.result?.subtype??"none"}, turns=${e.result?.num_turns??0})`;this.emitFailed(e,q(a,200),r);return}let i=`$${(e.costUsd??0).toFixed(2)}`,s=e.duration;if(e.killReason==="idle-timeout"){if(e.pendingPlanApproval){this.emitIdleTimeoutPlanApproval(e),this.deps.clearRetryTimersForSession(e.id);return}this.deps.dispatchSessionNotification(e,{label:"suspended",idempotencyKey:`suspended:${e.id}:${e.killReason??"idle-timeout"}:${e.completedAt??"unknown"}`,userMessage:`💤 [${e.name}] Suspended after idle timeout | ${i} | ${se(s)}`,notifyUser:"always",buttons:this.deps.getResumeButtons(e.id,e)}),this.deps.clearRetryTimersForSession(e.id);return}this.deps.notifySession(e,`⛔ [${e.name}] ${mo(e.killReason)} | ${i} | ${se(s)}`),this.deps.clearRetryTimersForSession(e.id)}emitIdleTimeoutPlanApproval(e){let t=this.deps.resolvePlanApprovalMode(e),r=e.actionablePlanDecisionVersion??e.planDecisionVersion,o=yt(e,r);if(t==="delegate"){this.deps.dispatchSessionNotification(e,{label:"plan-approval-timeout",idempotencyKey:`plan-approval-timeout:${e.id}:v${r??"unknown"}:delegate`,wakeMessage:["[DELEGATED PLAN APPROVAL REMINDER] Plan review is still pending after the session hit idle timeout.",`Name: ${e.name} | ID: ${e.id}`,this.deps.originThreadLine(e),"The agent already produced a plan and is waiting for a delegated decision.","Review privately first. Approve directly with agent_respond(..., approve=true, approval_rationale='...') if the plan is clearly within scope and low risk.","Escalate only if needed via agent_request_plan_approval(summary='...').","If you approve directly, follow up with a short user-facing explanation; the plugin's thumbs-up line is only the minimal approval acknowledgment.","If a canonical approval prompt was already posted for this plan version, do not restate it in plain text."].join(`
217
217
  `),notifyUser:"never"});return}if(t==="ask"&&o){this.deps.dispatchSessionNotification(e,{label:"plan-approval-timeout",idempotencyKey:`plan-approval-timeout:${e.id}:v${r??"unknown"}:already-delivered`,notifyUser:"never",wakeMessage:["[PLAN APPROVAL REMINDER] The user already has an actionable plan review prompt for this plan version.",`Name: ${e.name} | ID: ${e.id} | Plan v${r??"?"}`,this.deps.originThreadLine(e),"Do NOT post another approval summary unless canonical delivery is known to be missing."].join(`
218
218
  `)});return}this.deps.dispatchSessionNotification(e,{label:"plan-approval-timeout",idempotencyKey:`plan-approval-timeout:${e.id}:v${r??"unknown"}:user-prompt`,userMessage:[`📋 [${e.name}] Plan v${r??"?"} still awaiting approval after idle timeout | $${(e.costUsd??0).toFixed(2)} | ${se(e.duration)}`,"","The agent already produced a plan and is waiting for your decision.","Approve resumes the session and starts implementation.","Revise resumes it in plan mode so it can update the plan first.","Reject keeps the session stopped."].join(`
219
- `),notifyUser:"always",buttons:t==="ask"&&!o?this.deps.getPlanApprovalButtons(e.id,{...e,planDecisionVersion:r}):void 0})}async emitWaitingForInput(e){let t=e.pendingInputState?.questions,r=t?.[e.pendingInputState?.activeQuestionIndex??0],o=e.pendingInputState?.requestId,i=Ha(e.pendingInputState),s=o?[o,i].filter(Boolean).join(":"):void 0,a=s?`pending-input:${s}`:void 0;if(!this.deps.debounceWaitingEvent(e.id,a))return;let l=e.pendingPlanApproval?this.deps.resolvePlanApprovalMode(e):void 0,d=e.actionablePlanDecisionVersion??e.planDecisionVersion,u=e.pendingPlanApproval&&l==="ask"&&ht(e,d),f=e.pendingInputState?.promptText?.trim()||void 0,h=e.pendingPlanApproval?void 0:this.deps.getOutputPreview(e),k=!e.pendingPlanApproval&&f?f:!e.pendingPlanApproval&&h!==void 0?h:this.deps.getOutputPreview(e,e.pendingPlanApproval&&l!=="delegate"?Number.POSITIVE_INFINITY:void 0),g=e.pendingInputState?.options.map(P=>({label:P}))??[],p=!t||t.length===0?g:r&&r.options.length>0&&r.options.length<=6&&!r.options.some(P=>P.isOther)&&!r.multiSelect?r.options:t.length===1&&r&&r.options.length===0?g:[],y=e.pendingPlanApproval&&l==="ask"&&!u?this.deps.getPlanApprovalButtons(e.id,{...e,planDecisionVersion:d}):!e.pendingPlanApproval&&p.length?this.deps.getQuestionButtons(e.id,p,{requestId:e.pendingInputState?.requestId,questionId:r?.id}):void 0,w=Jm(e,d),R=r?Zm(r):[],A=r?Xm({question:r,index:e.pendingInputState?.activeQuestionIndex??0,total:t?.length??1,optionDescriptions:R}):f,I=!e.pendingPlanApproval&&this.deps.questionContextSummaryProvider?await ja({sessionName:e.name,question:A??k,context:h,provider:this.deps.questionContextSummaryProvider}):void 0,b=Io({session:e,preview:k,questionText:e.pendingPlanApproval?void 0:A,questionContextPreview:h,questionContextSummary:I,planArtifact:w,originThreadLine:this.deps.originThreadLine(e),planApprovalMode:l,planApprovalButtons:y,questionButtons:e.pendingPlanApproval?void 0:y}),m=b.planReviewSummary??k;if(b.label==="plan-approval"&&l==="ask"&&u){this.deps.dispatchSessionNotification(e,{label:b.label,idempotencyKey:`plan-approval:${e.id}:v${d??"unknown"}:canonical`,userMessage:b.userMessage,userMessages:b.userMessages,notifyUser:"never",buttons:b.buttons,wakeMessage:b.wakeMessage});return}if(b.label==="plan-approval"&&l==="ask"){this.deps.dispatchSessionNotification(e,{label:b.label,idempotencyKey:`plan-approval:${e.id}:v${d??"unknown"}:canonical`,userMessage:b.userMessage,userMessages:b.userMessages,notifyUser:"always",buttons:b.buttons,hooks:{onNotifyStarted:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"sending",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptLastAttemptAt:new Date().toISOString()})},onNotifySucceeded:()=>{this.deps.updatePersistedSession(e.id,{canonicalPlanPromptVersion:d,approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"delivered",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptDeliveredAt:new Date().toISOString(),approvalPromptFailedAt:void 0})},onNotifyFailed:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"failed",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptFailedAt:new Date().toISOString()})}},shouldDispatch:()=>yt(e,d),onUserNotifyFailed:()=>this.dispatchPlanApprovalFallback(e,d,m),wakeMessageOnNotifySuccess:He(e,d)});return}if(b.label==="plan-approval"){this.deps.dispatchSessionNotification(e,{label:b.label,idempotencyKey:`plan-approval:${e.id}:v${d??"unknown"}:wake-only`,userMessage:b.userMessage,wakeMessage:b.wakeMessage,notifyUser:"never",buttons:b.buttons});return}this.deps.dispatchSessionNotification(e,{label:b.label,idempotencyKey:`waiting:${e.id}:${s??`${b.label}:${b.userMessage}`}`,userMessage:b.userMessage,notifyUser:"always",buttons:b.buttons,shouldDispatch:o?()=>ef(e,o,i):void 0,wakeMessageOnNotifyFailed:b.wakeMessage})}emitTurnComplete(e){`${e.id}${e.result?.num_turns??0}${e.worktreeStrategy??"none"}`;let t=So({session:e,originThreadLine:this.deps.originThreadLine(e),preview:this.deps.getOutputPreview(e)});this.deps.dispatchSessionNotification(e,{label:"turn-complete",idempotencyKey:`turn-complete:${e.id}:${tf(e)}`,userMessage:t.userMessage,wakeMessage:t.wakeMessage,notifyUser:"always",onUserNotifyFailed:()=>{`${e.id}`,this.deps.shouldEmitTerminalWake(e)&&this.emitCompleted(e)}})}emitCompleted(e){let t=this.deps.getOutputPreview(e),r=this.shouldRequestCompletionFollowup(e),o=go({session:e,originThreadLine:this.deps.originThreadLine(e),preview:t}),i=za(e),s=`terminal:${e.id}:${i}`,a;this.deps.dispatchSessionNotification(e,{label:"completed",idempotencyKey:`terminal-completed:${e.id}:${i}`,userMessage:o.userMessage,notifyUser:"always",completionSummary:{required:r,producer:"terminal",outcomeKey:s},completionWakeSummaryRequired:r,completionWakeOutcomeKey:s,requireDirectUserNotification:!0,wakeMessageOnNotifySuccess:r?o.wakeMessageOnNotifySuccess:void 0,wakeMessageOnNotifyFailed:r?o.wakeMessageOnNotifyFailed:void 0,hooks:{onNotifySucceeded:()=>{a=!0,this.logCompletionWakeDiagnostic({session:e,event:"completion_notify_succeeded",canonicalStatusDelivered:a,followupSummaryRequired:r})},onNotifyFailed:()=>{a=!1,this.logCompletionWakeDiagnostic({session:e,event:"completion_notify_failed",canonicalStatusDelivered:a,followupSummaryRequired:r})},onWakeSucceeded:()=>{this.logCompletionWakeDiagnostic({session:e,event:"completion_wake_succeeded",canonicalStatusDelivered:a,followupSummaryRequired:r})}}})}emitFailed(e,t,r){let o=yo({session:e,originThreadLine:this.deps.originThreadLine(e),errorSummary:t,preview:this.deps.getOutputPreview(e),worktreeAutoCleaned:r,failedButtons:this.deps.getResumeButtons(e.id,e)});this.deps.dispatchSessionNotification(e,{label:"failed",idempotencyKey:`terminal-failed:${e.id}:${za(e)}:${t}`,userMessage:o.userMessage,wakeMessage:o.wakeMessage,notifyUser:"always",buttons:o.buttons})}};import{existsSync as nf}from"fs";var mr=class{constructor(e){this.deps=e}deps;async dismissWorktree(e){let t=this.deps.getPersistedSession(e),r=this.deps.resolveActiveSession(e),o=r??t;if(!o)return`Error: Session "${e}" not found.`;let i=r?.worktreePath??t?.worktreePath,s=this.deps.resolveWorktreeRepoDir(r?.originalWorkdir??t?.workdir,i),a=r?.worktreeBranch??t?.worktreeBranch,l=r?.name??t?.name??e;if(!s)return`Error: No workdir found for session "${e}".`;let d=F(o);!d&&i&&nf(i)&&B(s,i,{destructive:!0}),a&&H(s,a);for(let f of z(r??t))this.deps.updatePersistedSession(f,{worktreeDisposition:"dismissed",worktreeDismissedAt:new Date().toISOString(),pendingWorktreeDecisionSince:void 0,worktreeState:"dismissed",lifecycle:"terminal",worktreePath:void 0,worktreeBranch:void 0,worktreeLifecycle:{state:"dismissed",updatedAt:new Date().toISOString(),resolvedAt:new Date().toISOString(),resolutionSource:"dismiss",baseBranch:t?.worktreeLifecycle?.baseBranch,targetRepo:t?.worktreePrTargetRepo,pushRemote:t?.worktreePushRemote}});let u=d?`🗑️ [${l}] Branch \`${a??"unknown"}\` dismissed. Native backend worktree released for backend cleanup.`:`🗑️ [${l}] Branch \`${a??"unknown"}\` dismissed and permanently deleted.`;return this.deps.dispatchNotification(this.deps.buildRoutingProxy({id:D(r??t??{id:e})??e,sessionId:t?.sessionId,harnessSessionId:r?.harnessSessionId??t?.harnessSessionId,backendRef:r?.backendRef??t?.backendRef,route:r?.route??t?.route}),{label:"worktree-dismissed",idempotencyKey:`worktree-dismissed:${D(r??t??{id:e})??e}:${a??"unknown"}`,userMessage:u,notifyUser:"always"}),u}snoozeWorktreeDecision(e,t={}){let r=this.deps.getPersistedSession(e);if(!r)return`Error: Session "${e}" not found.`;let o=Date.now(),i=new Date(o+1440*60*1e3).toISOString();for(let l of z(r))this.deps.updatePersistedSession(l,{worktreeDecisionSnoozedUntil:i,lastWorktreeReminderAt:new Date(o).toISOString()});let a=`⏭️ Reminder snoozed 24h for \`${r.worktreeBranch??"unknown"}\` (session: ${r.name})`;return t.notifyUser!==!1&&this.deps.dispatchNotification(this.deps.buildRoutingProxy({id:D(r)??C(r)??r.harnessSessionId,sessionId:r.sessionId,harnessSessionId:r.harnessSessionId,backendRef:r.backendRef,route:r.route}),{label:"worktree-snoozed",idempotencyKey:`worktree-snoozed:${D(r)??C(r)??r.harnessSessionId}:${i}`,userMessage:a,notifyUser:"always"}),a}};var Qa=new Set(["starting","running"]);function Ya(n,e){JSON.stringify({component:"SessionRuntimeRegistry",event:n,at:new Date().toISOString(),...e})}function Ja(n){return{sessionId:n.id,name:n.name,status:n.status,lifecycle:n.lifecycle,runtimeState:n.runtimeState,harness:n.harnessName,hasHarnessSessionId:!!n.harnessSessionId,backendRefKind:n.backendRef?.kind,hasBackendConversationId:!!n.backendRef?.conversationId,hasBackendRunId:!!n.backendRef?.runId,hasBackendWorktreeId:!!n.backendRef?.worktreeId,hasBackendWorktreePath:!!n.backendRef?.worktreePath}}var fr=class{sessions=new Map;activeSessionCount(){return[...this.sessions.values()].filter(e=>Qa.has(e.status)).length}uniqueName(e){let t=new Set([...this.sessions.values()].filter(o=>Qa.has(o.status)).map(o=>o.name));if(!t.has(e))return e;let r=2;for(;t.has(`${e}-${r}`);)r+=1;return`${e}-${r}`}add(e,t="spawn"){Ya("runtime.add",{reason:t,...Ja(e),activeCountBefore:this.activeSessionCount()}),this.sessions.set(e.id,e)}remove(e,t="unknown"){let r=this.sessions.get(e);Ya("runtime.remove",{reason:t,sessionId:e,existed:!!r,...r?Ja(r):{},activeCountBefore:this.activeSessionCount()}),this.sessions.delete(e)}get(e){return this.sessions.get(e)}list(){return[...this.sessions.values()]}};var gr=class{constructor(e){this.deps=e}deps;initializeSession(e,t,r,o={}){if(this.deps.hydrateSpawnedSession(e,t,r),r.taskLifecycle?.create(e),e.on("statusChange",(i,s)=>{s==="running"?(e.harnessSessionId&&this.deps.markRunning(e),r.taskLifecycle?.progress(e)):(s==="completed"||s==="failed"||s==="killed")&&(r.taskLifecycle?.finalize(e),this.deps.handleTerminal(e).catch(a=>{console.error(`[SessionRuntimeBootstrap] handleTerminal threw for session ${e.id}:`,a)}))}),e.on("lifecycleChange",(i,s)=>{r.taskLifecycle?.progress(e)}),e.on("turnEnd",(i,s)=>{this.deps.handleTurnEnd(e,s).catch(a=>{console.error(`[SessionRuntimeBootstrap] handleTurnEnd threw for session ${e.id}:`,a)})}),e.start(),o.notifyLaunch!==!1){let i=this.buildLaunchNotification(e);this.deps.notifySession(e,i.text,i.label,i.idempotencyKey)}return e}buildLaunchNotification(e){let t=this.deps.formatLaunchWorkdirLabel(e),r=ge({harness:e.harnessName,model:e.model})??"default";return e.resumeSessionId?{text:jt({sessionName:e.name,resumedFromSessionName:e.resumedFromSessionName,workdirLabel:t,harnessLabel:r}),label:"resumed-launch",idempotencyKey:`resumed-launch:${e.id}:${e.startedAt}:${e.resumeSessionId}`}:{text:`🚀 [${e.name}] Launched | ${t} | ${r}`,label:"launch"}}};var hr=class{buildNoChangeNotification(e){let{session:t,nativeBackendWorktree:r,cleanupSucceeded:o,worktreePath:i,worktreeBranch:s,preview:a,originThreadLine:l,preservedSummary:d,remoteOutcome:u}=e,f=d?"preserved":o?"cleaned":"cleanup-failed",h=[s?.trim()||"unknown-branch",i.trim()||"unknown-worktree",t.startedAt].join(":"),k=d??(o?r?"native backend worktree released for backend cleanup":"worktree cleaned up":`cleanup failed; worktree still exists at ${i}`),g=ye({costUsd:t.costUsd,duration:typeof t.completedAt=="number"?t.completedAt-t.startedAt:void 0,harnessName:t.harnessName,model:t.model}),p=u==="pr-updated"?"PR updated; no local worktree changes remained to merge":u==="pr-opened"?"PR opened; no local worktree changes remained to merge":"Session completed with no worktree changes to merge",y=u==="pr-updated"?`PR updated; no local worktree changes remained to merge — ${k}`:u==="pr-opened"?`PR opened; no local worktree changes remained to merge — ${k}`:void 0,w=u==="pr-updated"?"PR updated; no local worktree changes remained to merge":u==="pr-opened"?"PR opened; no local worktree changes remained to merge":"Session completed with no worktree changes to merge",R=u==="pr-updated"?"Coding agent session updated a PR; no local worktree changes remained to merge.":u==="pr-opened"?"Coding agent session opened a PR; no local worktree changes remained to merge.":void 0;return{label:d?"worktree-no-changes-preserved":o?"worktree-no-changes":"worktree-no-changes-cleanup-failed",idempotencyKey:`worktree-no-change:${t.id}:${f}:${h}`,userMessage:d?`ℹ️ [${t.name}] ${p} — ${d}${g}`:o?r?`ℹ️ [${t.name}] ${p} — native backend worktree released for backend cleanup${g}`:`ℹ️ [${t.name}] ${p} — worktree cleaned up${g}`:`⚠️ [${t.name}] ${w}, but worktree cleanup failed. Worktree still exists at ${i}${g}`,wakeMessage:Po({sessionName:t.name,sessionId:t.id,headline:R,cleanupSummary:y??k,preview:a,originThreadLine:l,requestedPermissionMode:t.requestedPermissionMode,currentPermissionMode:t.currentPermissionMode,approvalExecutionState:t.approvalExecutionState,approvalState:t.approvalState,planApproval:t.planApproval,approvalPromptStatus:t.approvalPromptStatus,approvalPromptMessageKind:t.approvalPromptMessageKind,approvalPromptDeliveredAt:t.approvalPromptDeliveredAt}),notifyUser:"always"}}buildAskNotification(e){let{session:t,branchName:r,baseBranch:o,diffSummary:i,buttons:s,summaryLines:a=[],policyReason:l}=e,d=i.commitMessages.slice(0,5).map(h=>`• ${h.hash} ${h.message} (${h.author})`),u=i.commits>5?`...and ${i.commits-5} more`:"",f=t.worktreePrTargetRepo?`Branch: \`${r}\` → \`${o}\` | PR target: ${t.worktreePrTargetRepo}`:`Branch: \`${r}\` → \`${o}\``;return{label:"worktree-merge-ask",idempotencyKey:["worktree-decision",t.id,r,o,i.commits,i.commitMessages.map(h=>h.hash).join(",")].join(":"),userMessage:[`🔀 Worktree decision required for session \`${t.name}\``,"",f,`Commits: ${i.commits} | Files: ${i.filesChanged} | +${i.insertions} / -${i.deletions}`,"",...a.length>0?["Summary:",...a.map(h=>`- ${h}`),""]:[],...l?[`Policy: ${l}`,""]:[],"Recent commits:",...d,...u?[u]:[],"",`⚠️ Discard will permanently delete branch \`${r}\` and all local changes. This cannot be undone.`].join(`
219
+ `),notifyUser:"always",buttons:t==="ask"&&!o?this.deps.getPlanApprovalButtons(e.id,{...e,planDecisionVersion:r}):void 0})}async emitWaitingForInput(e){let t=e.pendingInputState?.questions,r=t?.[e.pendingInputState?.activeQuestionIndex??0],o=e.pendingInputState?.requestId,i=Ha(e.pendingInputState),s=o?[o,i].filter(Boolean).join(":"):void 0,a=s?`pending-input:${s}`:void 0;if(!this.deps.debounceWaitingEvent(e.id,a))return;let l=e.pendingPlanApproval?this.deps.resolvePlanApprovalMode(e):void 0,d=e.actionablePlanDecisionVersion??e.planDecisionVersion,u=e.pendingPlanApproval&&l==="ask"&&yt(e,d),f=e.pendingInputState?.promptText?.trim()||void 0,g=e.pendingPlanApproval?void 0:this.deps.getOutputPreview(e),k=!e.pendingPlanApproval&&f?f:!e.pendingPlanApproval&&g!==void 0?g:this.deps.getOutputPreview(e,e.pendingPlanApproval&&l!=="delegate"?Number.POSITIVE_INFINITY:void 0),h=e.pendingInputState?.options.map(w=>({label:w}))??[],p=!t||t.length===0?h:r&&r.options.length>0&&r.options.length<=6&&!r.options.some(w=>w.isOther)&&!r.multiSelect?r.options:t.length===1&&r&&r.options.length===0?h:[],y=e.pendingPlanApproval&&l==="ask"&&!u?this.deps.getPlanApprovalButtons(e.id,{...e,planDecisionVersion:d}):!e.pendingPlanApproval&&p.length?this.deps.getQuestionButtons(e.id,p,{requestId:e.pendingInputState?.requestId,questionId:r?.id}):void 0,P=Jm(e,d),b=r?Zm(r):[],A=r?Xm({question:r,index:e.pendingInputState?.activeQuestionIndex??0,total:t?.length??1,optionDescriptions:b}):f,I=!e.pendingPlanApproval&&this.deps.questionContextSummaryProvider?await ja({sessionName:e.name,question:A??k,context:g,provider:this.deps.questionContextSummaryProvider}):void 0,R=Io({session:e,preview:k,questionText:e.pendingPlanApproval?void 0:A,questionContextPreview:g,questionContextSummary:I,planArtifact:P,originThreadLine:this.deps.originThreadLine(e),planApprovalMode:l,planApprovalButtons:y,questionButtons:e.pendingPlanApproval?void 0:y}),m=R.planReviewSummary??k;if(R.label==="plan-approval"&&l==="ask"&&u){this.deps.dispatchSessionNotification(e,{label:R.label,idempotencyKey:`plan-approval:${e.id}:v${d??"unknown"}:canonical`,userMessage:R.userMessage,userMessages:R.userMessages,notifyUser:"never",buttons:R.buttons,wakeMessage:R.wakeMessage});return}if(R.label==="plan-approval"&&l==="ask"){this.deps.dispatchSessionNotification(e,{label:R.label,idempotencyKey:`plan-approval:${e.id}:v${d??"unknown"}:canonical`,userMessage:R.userMessage,userMessages:R.userMessages,notifyUser:"always",buttons:R.buttons,hooks:{onNotifyStarted:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"sending",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptLastAttemptAt:new Date().toISOString()})},onNotifySucceeded:()=>{this.deps.updatePersistedSession(e.id,{canonicalPlanPromptVersion:d,approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"delivered",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptDeliveredAt:new Date().toISOString(),approvalPromptFailedAt:void 0})},onNotifyFailed:()=>{this.deps.updatePersistedSession(e.id,{approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"failed",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptFailedAt:new Date().toISOString()})}},shouldDispatch:()=>St(e,d),onUserNotifyFailed:()=>this.dispatchPlanApprovalFallback(e,d,m),wakeMessageOnNotifySuccess:He(e,d)});return}if(R.label==="plan-approval"){this.deps.dispatchSessionNotification(e,{label:R.label,idempotencyKey:`plan-approval:${e.id}:v${d??"unknown"}:wake-only`,userMessage:R.userMessage,wakeMessage:R.wakeMessage,notifyUser:"never",buttons:R.buttons});return}this.deps.dispatchSessionNotification(e,{label:R.label,idempotencyKey:`waiting:${e.id}:${s??`${R.label}:${R.userMessage}`}`,userMessage:R.userMessage,notifyUser:"always",buttons:R.buttons,shouldDispatch:o?()=>ef(e,o,i):void 0,wakeMessageOnNotifyFailed:R.wakeMessage})}emitTurnComplete(e){`${e.id}${e.result?.num_turns??0}${e.worktreeStrategy??"none"}`;let t=So({session:e,originThreadLine:this.deps.originThreadLine(e),preview:this.deps.getOutputPreview(e)});this.deps.dispatchSessionNotification(e,{label:"turn-complete",idempotencyKey:`turn-complete:${e.id}:${tf(e)}`,userMessage:t.userMessage,wakeMessage:t.wakeMessage,notifyUser:"always",onUserNotifyFailed:()=>{`${e.id}`,this.deps.shouldEmitTerminalWake(e)&&this.emitCompleted(e)}})}emitCompleted(e){let t=this.deps.getOutputPreview(e),r=this.shouldRequestCompletionFollowup(e),o=go({session:e,originThreadLine:this.deps.originThreadLine(e),preview:t}),i=za(e),s=`terminal:${e.id}:${i}`,a;this.deps.dispatchSessionNotification(e,{label:"completed",idempotencyKey:`terminal-completed:${e.id}:${i}`,userMessage:o.userMessage,notifyUser:"always",completionSummary:{required:r,producer:"terminal",outcomeKey:s},completionWakeSummaryRequired:r,completionWakeOutcomeKey:s,requireDirectUserNotification:!0,wakeMessageOnNotifySuccess:r?o.wakeMessageOnNotifySuccess:void 0,wakeMessageOnNotifyFailed:r?o.wakeMessageOnNotifyFailed:void 0,hooks:{onNotifySucceeded:()=>{a=!0,this.logCompletionWakeDiagnostic({session:e,event:"completion_notify_succeeded",canonicalStatusDelivered:a,followupSummaryRequired:r})},onNotifyFailed:()=>{a=!1,this.logCompletionWakeDiagnostic({session:e,event:"completion_notify_failed",canonicalStatusDelivered:a,followupSummaryRequired:r})},onWakeSucceeded:()=>{this.logCompletionWakeDiagnostic({session:e,event:"completion_wake_succeeded",canonicalStatusDelivered:a,followupSummaryRequired:r})}}})}emitFailed(e,t,r){let o=yo({session:e,originThreadLine:this.deps.originThreadLine(e),errorSummary:t,preview:this.deps.getOutputPreview(e),worktreeAutoCleaned:r,failedButtons:this.deps.getResumeButtons(e.id,e)});this.deps.dispatchSessionNotification(e,{label:"failed",idempotencyKey:`terminal-failed:${e.id}:${za(e)}:${t}`,userMessage:o.userMessage,wakeMessage:o.wakeMessage,notifyUser:"always",buttons:o.buttons})}};import{existsSync as nf}from"fs";var mr=class{constructor(e){this.deps=e}deps;async dismissWorktree(e){let t=this.deps.getPersistedSession(e),r=this.deps.resolveActiveSession(e),o=r??t;if(!o)return`Error: Session "${e}" not found.`;let i=r?.worktreePath??t?.worktreePath,s=this.deps.resolveWorktreeRepoDir(r?.originalWorkdir??t?.workdir,i),a=r?.worktreeBranch??t?.worktreeBranch,l=r?.name??t?.name??e;if(!s)return`Error: No workdir found for session "${e}".`;let d=L(o);!d&&i&&nf(i)&&B(s,i,{destructive:!0}),a&&H(s,a);for(let f of z(r??t))this.deps.updatePersistedSession(f,{worktreeDisposition:"dismissed",worktreeDismissedAt:new Date().toISOString(),pendingWorktreeDecisionSince:void 0,worktreeState:"dismissed",lifecycle:"terminal",worktreePath:void 0,worktreeBranch:void 0,worktreeLifecycle:{state:"dismissed",updatedAt:new Date().toISOString(),resolvedAt:new Date().toISOString(),resolutionSource:"dismiss",baseBranch:t?.worktreeLifecycle?.baseBranch,targetRepo:t?.worktreePrTargetRepo,pushRemote:t?.worktreePushRemote}});let u=d?`🗑️ [${l}] Branch \`${a??"unknown"}\` dismissed. Native backend worktree released for backend cleanup.`:`🗑️ [${l}] Branch \`${a??"unknown"}\` dismissed and permanently deleted.`;return this.deps.dispatchNotification(this.deps.buildRoutingProxy({id:D(r??t??{id:e})??e,sessionId:t?.sessionId,harnessSessionId:r?.harnessSessionId??t?.harnessSessionId,backendRef:r?.backendRef??t?.backendRef,route:r?.route??t?.route}),{label:"worktree-dismissed",idempotencyKey:`worktree-dismissed:${D(r??t??{id:e})??e}:${a??"unknown"}`,userMessage:u,notifyUser:"always"}),u}snoozeWorktreeDecision(e,t={}){let r=this.deps.getPersistedSession(e);if(!r)return`Error: Session "${e}" not found.`;let o=Date.now(),i=new Date(o+1440*60*1e3).toISOString();for(let l of z(r))this.deps.updatePersistedSession(l,{worktreeDecisionSnoozedUntil:i,lastWorktreeReminderAt:new Date(o).toISOString()});let a=`⏭️ Reminder snoozed 24h for \`${r.worktreeBranch??"unknown"}\` (session: ${r.name})`;return t.notifyUser!==!1&&this.deps.dispatchNotification(this.deps.buildRoutingProxy({id:D(r)??C(r)??r.harnessSessionId,sessionId:r.sessionId,harnessSessionId:r.harnessSessionId,backendRef:r.backendRef,route:r.route}),{label:"worktree-snoozed",idempotencyKey:`worktree-snoozed:${D(r)??C(r)??r.harnessSessionId}:${i}`,userMessage:a,notifyUser:"always"}),a}};var Qa=new Set(["starting","running"]);function Ya(n,e){JSON.stringify({component:"SessionRuntimeRegistry",event:n,at:new Date().toISOString(),...e})}function Ja(n){return{sessionId:n.id,name:n.name,status:n.status,lifecycle:n.lifecycle,runtimeState:n.runtimeState,harness:n.harnessName,hasHarnessSessionId:!!n.harnessSessionId,backendRefKind:n.backendRef?.kind,hasBackendConversationId:!!n.backendRef?.conversationId,hasBackendRunId:!!n.backendRef?.runId,hasBackendWorktreeId:!!n.backendRef?.worktreeId,hasBackendWorktreePath:!!n.backendRef?.worktreePath}}var fr=class{sessions=new Map;activeSessionCount(){return[...this.sessions.values()].filter(e=>Qa.has(e.status)).length}uniqueName(e){let t=new Set([...this.sessions.values()].filter(o=>Qa.has(o.status)).map(o=>o.name));if(!t.has(e))return e;let r=2;for(;t.has(`${e}-${r}`);)r+=1;return`${e}-${r}`}add(e,t="spawn"){Ya("runtime.add",{reason:t,...Ja(e),activeCountBefore:this.activeSessionCount()}),this.sessions.set(e.id,e)}remove(e,t="unknown"){let r=this.sessions.get(e);Ya("runtime.remove",{reason:t,sessionId:e,existed:!!r,...r?Ja(r):{},activeCountBefore:this.activeSessionCount()}),this.sessions.delete(e)}get(e){return this.sessions.get(e)}list(){return[...this.sessions.values()]}};var gr=class{constructor(e){this.deps=e}deps;initializeSession(e,t,r,o={}){if(this.deps.hydrateSpawnedSession(e,t,r),r.taskLifecycle?.create(e),e.on("statusChange",(i,s)=>{s==="running"?(e.harnessSessionId&&this.deps.markRunning(e),r.taskLifecycle?.progress(e)):(s==="completed"||s==="failed"||s==="killed")&&(r.taskLifecycle?.finalize(e),this.deps.handleTerminal(e).catch(a=>{console.error(`[SessionRuntimeBootstrap] handleTerminal threw for session ${e.id}:`,a)}))}),e.on("lifecycleChange",(i,s)=>{r.taskLifecycle?.progress(e)}),e.on("turnEnd",(i,s)=>{this.deps.handleTurnEnd(e,s).catch(a=>{console.error(`[SessionRuntimeBootstrap] handleTurnEnd threw for session ${e.id}:`,a)})}),o.startAfter?o.startAfter.then(()=>e.start()).catch(i=>{console.error(`[SessionRuntimeBootstrap] deferred start threw for session ${e.id}:`,i)}):e.start(),o.notifyLaunch!==!1){let i=this.buildLaunchNotification(e);this.deps.notifySession(e,i.text,i.label,i.idempotencyKey)}return e}buildLaunchNotification(e){let t=this.deps.formatLaunchWorkdirLabel(e),r=ge({harness:e.harnessName,model:e.model})??"default";return e.resumeSessionId?{text:zt({sessionName:e.name,resumedFromSessionName:e.resumedFromSessionName,workdirLabel:t,harnessLabel:r}),label:"resumed-launch",idempotencyKey:`resumed-launch:${e.id}:${e.startedAt}:${e.resumeSessionId}`}:{text:`🚀 [${e.name}] Launched | ${t} | ${r}`,label:"launch"}}};var hr=class{buildNoChangeNotification(e){let{session:t,nativeBackendWorktree:r,cleanupSucceeded:o,worktreePath:i,worktreeBranch:s,preview:a,originThreadLine:l,preservedSummary:d,remoteOutcome:u}=e,f=d?"preserved":o?"cleaned":"cleanup-failed",g=[s?.trim()||"unknown-branch",i.trim()||"unknown-worktree",t.startedAt].join(":"),k=d??(o?r?"native backend worktree released for backend cleanup":"worktree cleaned up":`cleanup failed; worktree still exists at ${i}`),h=ye({costUsd:t.costUsd,duration:typeof t.completedAt=="number"?t.completedAt-t.startedAt:void 0,harnessName:t.harnessName,model:t.model}),p=u==="pr-updated"?"PR updated; no local worktree changes remained to merge":u==="pr-opened"?"PR opened; no local worktree changes remained to merge":"Session completed with no worktree changes to merge",y=u==="pr-updated"?`PR updated; no local worktree changes remained to merge — ${k}`:u==="pr-opened"?`PR opened; no local worktree changes remained to merge — ${k}`:void 0,P=u==="pr-updated"?"PR updated; no local worktree changes remained to merge":u==="pr-opened"?"PR opened; no local worktree changes remained to merge":"Session completed with no worktree changes to merge",b=u==="pr-updated"?"Coding agent session updated a PR; no local worktree changes remained to merge.":u==="pr-opened"?"Coding agent session opened a PR; no local worktree changes remained to merge.":void 0;return{label:d?"worktree-no-changes-preserved":o?"worktree-no-changes":"worktree-no-changes-cleanup-failed",idempotencyKey:`worktree-no-change:${t.id}:${f}:${g}`,userMessage:d?`ℹ️ [${t.name}] ${p} — ${d}${h}`:o?r?`ℹ️ [${t.name}] ${p} — native backend worktree released for backend cleanup${h}`:`ℹ️ [${t.name}] ${p} — worktree cleaned up${h}`:`⚠️ [${t.name}] ${P}, but worktree cleanup failed. Worktree still exists at ${i}${h}`,wakeMessage:Po({sessionName:t.name,sessionId:t.id,headline:b,cleanupSummary:y??k,preview:a,originThreadLine:l,requestedPermissionMode:t.requestedPermissionMode,currentPermissionMode:t.currentPermissionMode,approvalExecutionState:t.approvalExecutionState,approvalState:t.approvalState,planApproval:t.planApproval,approvalPromptStatus:t.approvalPromptStatus,approvalPromptMessageKind:t.approvalPromptMessageKind,approvalPromptDeliveredAt:t.approvalPromptDeliveredAt}),notifyUser:"always"}}buildAskNotification(e){let{session:t,branchName:r,baseBranch:o,diffSummary:i,buttons:s,summaryLines:a=[],policyReason:l}=e,d=i.commitMessages.slice(0,5).map(g=>`• ${g.hash} ${g.message} (${g.author})`),u=i.commits>5?`...and ${i.commits-5} more`:"",f=t.worktreePrTargetRepo?`Branch: \`${r}\` → \`${o}\` | PR target: ${t.worktreePrTargetRepo}`:`Branch: \`${r}\` → \`${o}\``;return{label:"worktree-merge-ask",idempotencyKey:["worktree-decision",t.id,r,o,i.commits,i.commitMessages.map(g=>g.hash).join(",")].join(":"),userMessage:[`🔀 Worktree decision required for session \`${t.name}\``,"",f,`Commits: ${i.commits} | Files: ${i.filesChanged} | +${i.insertions} / -${i.deletions}`,"",...a.length>0?["Summary:",...a.map(g=>`- ${g}`),""]:[],...l?[`Policy: ${l}`,""]:[],"Recent commits:",...d,...u?[u]:[],"",`⚠️ Discard will permanently delete branch \`${r}\` and all local changes. This cannot be undone.`].join(`
220
220
  `),notifyUser:"always",buttons:s,wakeMessageOnNotifySuccess:["Worktree decision buttons delivered to the user.",`Session: ${t.name} | ID: ${t.id}`,f,"Wait for their button callback — do NOT act on this worktree yourself."].join(`
221
221
  `),wakeMessageOnNotifyFailed:[`🔀 Worktree decision required for session \`${t.name}\``,"",f,`Commits: ${i.commits} | Files: ${i.filesChanged} | +${i.insertions} / -${i.deletions}`].join(`
222
- `)}}buildDelegateNotification(e){let{session:t,branchName:r,baseBranch:o,diffSummary:i,policyReason:s,allowedActions:a,originThreadLine:l}=e,d=i.commitMessages.slice(0,5).map(h=>`• ${h.hash} ${h.message} (${h.author})`),u=i.commits>5?`...and ${i.commits-5} more`:void 0,f=t.prompt?t.prompt.slice(0,500):"(no prompt)";return{label:"worktree-delegate",idempotencyKey:["worktree-delegate",t.id,r,o,i.commits,i.commitMessages.map(h=>h.hash).join(",")].join(":"),wakeMessage:ko({sessionName:t.name,sessionId:t.id,branchName:r,baseBranch:o,promptSnippet:f,commitLines:d,moreNote:u,originThreadLine:l,diffSummary:i,allowedActions:a,policyReason:s}),notifyUser:"never"}}};function Xa(n,e=1e3){let t=!Number.isFinite(e),r=typeof n.getOutput=="function"?n.getOutput():[],o=t?r.join(`
222
+ `)}}buildDelegateNotification(e){let{session:t,branchName:r,baseBranch:o,diffSummary:i,policyReason:s,allowedActions:a,originThreadLine:l}=e,d=i.commitMessages.slice(0,5).map(g=>`• ${g.hash} ${g.message} (${g.author})`),u=i.commits>5?`...and ${i.commits-5} more`:void 0,f=t.prompt?t.prompt.slice(0,500):"(no prompt)";return{label:"worktree-delegate",idempotencyKey:["worktree-delegate",t.id,r,o,i.commits,i.commitMessages.map(g=>g.hash).join(",")].join(":"),wakeMessage:ko({sessionName:t.name,sessionId:t.id,branchName:r,baseBranch:o,promptSnippet:f,commitLines:d,moreNote:u,originThreadLine:l,diffSummary:i,allowedActions:a,policyReason:s}),notifyUser:"never"}}};function Xa(n,e=1e3){let t=!Number.isFinite(e),r=typeof n.getOutput=="function"?n.getOutput():[],o=t?r.join(`
223
223
  `):rf(n);return t?o:o.length>e?Za(n)?bi(o,e):Ri(o,e):o}function rf(n){let e=typeof n.getOutput=="function"?n.getOutput():[],t=e.join(`
224
224
  `).trim();return t?Za(n)?of(t)??t:e.slice(-20).join(`
225
225
  `):""}function Za(n){if(n.status==="completed"||n.killReason==="done")return!0;let e=n;return e.approvalState==="approved"||e.planModeApproved===!0||(e.planDecisionVersion??0)>0}function of(n){let t=n.split(/\n\s*\n+/).map(r=>r.trim()).filter(r=>/[A-Za-z0-9]/.test(r)).at(-1);if(t)return t.length>=120||t.includes(`
226
- `)?t:void 0}import{unlinkSync as sf}from"fs";var yr=class n{timers=new Map;disposed=!1;static MAX_DELAY_MS=2147483647;schedule(e,t,r){if(this.disposed||(this.cancel(e),!Number.isFinite(t)))return;let o=Math.max(0,t-Date.now()),i=setTimeout(()=>{if(this.timers.delete(e),!this.disposed){if(t-Date.now()>0){this.schedule(e,t,r);return}r()}},Math.min(o,n.MAX_DELAY_MS));i.unref?.(),this.timers.set(e,i)}cancel(e){let t=this.timers.get(e);t&&(clearTimeout(t),this.timers.delete(e))}cancelPrefix(e){for(let t of this.timers.keys())t.startsWith(e)&&this.cancel(t)}dispose(){this.disposed=!0;for(let e of this.timers.values())clearTimeout(e);this.timers.clear()}};var el=10080*60*1e3,af=300*1e3,tl="tmp-output:cleanup",lf=60*1e3;function df(n){return n instanceof Error?n.message:String(n)}var Sr=class{constructor(e){this.deps=e}deps;scheduler=new yr;lastTmpOutputCleanupAttemptAt;schedule(e,t,r){this.scheduler.schedule(e,t,r)}cancel(e){this.scheduler.cancel(e)}cancelPrefix(e){this.scheduler.cancelPrefix(e)}bootstrapMaintenanceSchedules(){let e=Date.now();this.runTmpOutputCleanup(e);for(let t of this.deps.store.listPersistedSessions())this.syncPersistedSessionMaintenance(t);this.syncActionTokenExpiryDeadline(),this.deps.store.cleanupOrphanOutputFiles(),this.syncTmpOutputCleanupDeadline(e)}syncRuntimeGcDeadline(e){if(!e.completedAt)return;let t=this.runtimeGcKey(e.id);this.schedule(t,e.completedAt+this.runtimeGcMaxAgeMs(),()=>{let r=this.deps.sessions.get(e.id);if(!r||!r.completedAt)return;let o=this.runtimeGcMaxAgeMs();if(!this.deps.store.shouldGcActiveSession(r,Date.now(),o)){this.syncRuntimeGcDeadline(r);return}this.deps.removeRuntimeSession(e.id,"runtime-gc"),this.deps.persistSession(r,{scheduleRuntimeGc:!1}),this.deps.clearRuntimeSessionState(e.id)})}cancelRuntimeGc(e){this.cancel(this.runtimeGcKey(e))}cancelPersistedMaintenance(e){let t=this.persistedMaintenanceRef(e);t&&this.cancelPrefix(`persisted:${t}:`)}syncPersistedSessionMaintenance(e){let t=this.persistedMaintenanceRef(e);if(!t)return;this.cancel(this.persistedMaintenanceKey(t,"worktree-reminder"));let r=this.deps.reminders.getNextReminderAt(e);r!=null?this.schedulePersistedWorktreeReminder(t,r):this.deps.reminders.clearResolvedReminderState(e),this.cancel(this.persistedMaintenanceKey(t,"worktree-retention"));let o=Oe(e,{activeSession:!1,includePrSync:e.worktreeLifecycle?.state==="pr_open"||!!e.worktreePrUrl}),i=this.resolvedAtIso(e),s=this.isLegacyResolvedWorktree(e);if((o.cleanupSafe||s)&&typeof i=="string"){let a=new Date(i).getTime();Number.isFinite(a)&&this.schedule(this.persistedMaintenanceKey(t,"worktree-retention"),a+el,()=>{let l=this.deps.store.getPersistedSession(t);l&&this.reconcileResolvedWorktreeRetention(l,Date.now())})}}reconcileResolvedWorktreeRetention(e,t){let r=Oe(e,{activeSession:!1,includePrSync:e.worktreeLifecycle?.state==="pr_open"||!!e.worktreePrUrl}),o=this.resolvedAtIso(e),i=o?new Date(o).getTime():0,s=this.legacyResolvedWorktreeState(e);if(!(!r.cleanupSafe&&!s||!o||!Number.isFinite(i)||t-i<el))try{if(!e.worktreePath&&!F(e))return;let a=this.deps.resolveWorktreeRepoDir(e.workdir,e.worktreePath);if(!a)return;let l=F(e)?!1:B(a,e.worktreePath);if(!F(e)&&!l)return;for(let d of z(e))this.deps.updatePersistedSession(d,{worktreePath:void 0,worktreeBranch:void 0,worktreeState:"none",pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0,worktreeLifecycle:{...e.worktreeLifecycle??r.lifecycle,state:r.cleanupSafe?r.derivedState:s??r.derivedState,updatedAt:new Date(t).toISOString(),resolvedAt:e.worktreeLifecycle?.resolvedAt??o,resolutionSource:e.worktreeLifecycle?.resolutionSource??"maintenance",notes:r.reasons}})}catch(a){`${e.worktreePath}${df(a)}`}}syncActionTokenExpiryDeadline(){let e="tokens:expiry";this.cancel(e);let t=this.deps.store.getNextActionTokenExpiry();t!=null&&this.schedule(e,t,()=>{this.deps.store.purgeExpiredActionTokens(Date.now())||this.syncActionTokenExpiryDeadline()})}syncTmpOutputCleanupDeadline(e=Date.now()){this.cancel(tl);let t=this.deps.store.getNextTmpOutputCleanupAt(e);if(t==null){this.lastTmpOutputCleanupAttemptAt=void 0;return}t>e&&(this.lastTmpOutputCleanupAttemptAt=void 0),this.schedule(tl,this.getTmpOutputCleanupScheduleAt(t,e),()=>{let r=Date.now();this.runTmpOutputCleanup(r),this.syncTmpOutputCleanupDeadline(r)})}enforcePersistedRetention(){let e=this.deps.store.evictOldestPersisted(this.deps.getMaxPersistedSessions());for(let t of e)this.cancelPersistedMaintenance(t),t.sessionId&&this.cancelRuntimeGc(t.sessionId),this.cleanupOutputPathIfUnreferenced(t.outputPath)}dispose(){this.scheduler.dispose()}persistedMaintenanceRef(e){return e.sessionId??C(e)??e.harnessSessionId}runtimeGcKey(e){return`runtime-gc:${e}`}persistedMaintenanceKey(e,t){return`persisted:${e}:${t}`}runtimeGcMaxAgeMs(){return(_.sessionGcAgeMinutes??1440)*6e4}runTmpOutputCleanup(e){this.lastTmpOutputCleanupAttemptAt=e,this.deps.store.cleanupTmpOutputFiles(e)}getTmpOutputCleanupScheduleAt(e,t){if(e>t||this.lastTmpOutputCleanupAttemptAt==null)return e;let r=this.lastTmpOutputCleanupAttemptAt+lf;return r>t?r:e}schedulePersistedWorktreeReminder(e,t){let r=this.persistedMaintenanceKey(e,"worktree-reminder");this.schedule(r,t,()=>{let o=this.deps.store.getPersistedSession(e);if(!o||this.deps.reminders.sendReminderIfDue(o,Date.now()))return;let s=this.deps.reminders.getNextReminderAt(o);s!=null&&this.schedulePersistedWorktreeReminder(e,Math.max(s,Date.now()+af))})}cleanupOutputPathIfUnreferenced(e){if(!(!e||this.deps.store.hasOutputPathReference(e)))try{sf(e)}catch{}}resolvedAtIso(e){return e.worktreeLifecycle?.resolvedAt??e.worktreeMergedAt??e.worktreeDismissedAt??(e.completedAt?new Date(e.completedAt).toISOString():void 0)}isLegacyResolvedWorktree(e){return this.legacyResolvedWorktreeState(e)!=null}legacyResolvedWorktreeState(e){if(e.worktreeMerged===!0||e.worktreeDisposition==="merged"||e.worktreeState==="merged")return"merged";if(e.worktreeDisposition==="dismissed"||e.worktreeState==="dismissed")return"dismissed";if(e.worktreeDisposition==="no-change-cleaned")return"no_change"}};var nl=new Set(["completed","failed","killed"]),uf=new Set(["starting","running"]),pf=5e3;function cf(n,e){return rl("sha256").update(JSON.stringify({route:n.route?{provider:n.route.provider,target:n.route.target,accountId:n.route.accountId,threadId:n.route.threadId,sessionKey:n.route.sessionKey}:void 0,prompt:n.prompt,workdir:n.workdir,name:n.name,model:n.model,reasoningEffort:n.reasoningEffort,fastMode:n.fastMode,systemPrompt:n.systemPrompt,allowedTools:n.allowedTools?[...n.allowedTools].sort():n.allowedTools,resumeSessionId:n.resumeSessionId,resumedFromSessionName:n.resumedFromSessionName,resumeWorktreeFrom:n.resumeWorktreeFrom,sessionIdOverride:n.sessionIdOverride,clearedPersistedCodexResume:n.clearedPersistedCodexResume,forkSession:n.forkSession,forceNewSession:n.forceNewSession,permissionMode:n.permissionMode,planApproval:n.planApproval,harness:n.harness,worktreeStrategy:n.worktreeStrategy,effectiveWorktreeStrategy:e,worktreeBaseBranch:n.worktreeBaseBranch,worktreePrTargetRepo:n.worktreePrTargetRepo,originAgentId:n.originAgentId})).digest("hex").slice(0,16)}function mf(n){return rl("sha256").update(JSON.stringify({route:n.route?{provider:n.route.provider,target:n.route.target,accountId:n.route.accountId,threadId:n.route.threadId,sessionKey:n.route.sessionKey}:void 0,prompt:n.launchPrompt,workdir:n.launchWorkdir,name:n.launchName,model:n.launchModel,reasoningEffort:n.launchReasoningEffort,fastMode:n.launchFastMode,systemPrompt:n.launchSystemPrompt,allowedTools:n.launchAllowedTools?[...n.launchAllowedTools].sort():n.launchAllowedTools,resumeSessionId:n.launchResumeSessionId,resumedFromSessionName:n.launchResumedFromSessionName,resumeWorktreeFrom:n.launchResumeWorktreeFrom,sessionIdOverride:n.launchSessionIdOverride,clearedPersistedCodexResume:n.launchClearedPersistedCodexResume,forkSession:n.launchForkSession,forceNewSession:n.launchForceNewSession,permissionMode:n.launchPermissionMode,planApproval:n.launchPlanApproval,harness:n.launchHarness,worktreeStrategy:n.launchWorktreeStrategy,worktreeBaseBranch:n.launchWorktreeBaseBranch,worktreePrTargetRepo:n.launchWorktreePrTargetRepo,originAgentId:n.launchOriginAgentId})).digest("hex").slice(0,16)}var kr=class n{registry;sessions;maxSessions;maxPersistedSessions;lastWaitingEventTimestamps=new Map;lastTurnCompleteMarkers=new Map;lastTerminalWakeMarkers=new Map;mergeQueue=new ze;pendingAskUserQuestions=new Map;store;metrics;wakeDispatcher;interactions;notifications;worktrees;questions;lifecycle;restore;stateSync;references;worktreeStrategy;worktreeDecisions;runtimeBootstrap;worktreeMessages;maintenance;pendingPlanResumeClaims=new Map;constructor(e=20,t=50,r={}){this.maxSessions=e,this.maxPersistedSessions=t;let o=n.createServiceBundle(this,r);this.registry=o.registry,this.sessions=o.sessions,this.store=o.store,this.metrics=o.metrics,this.wakeDispatcher=o.wakeDispatcher,this.interactions=o.interactions,this.notifications=o.notifications,this.worktrees=o.worktrees,this.questions=o.questions,this.lifecycle=o.lifecycle,this.restore=o.restore,this.stateSync=o.stateSync,this.references=o.references,this.worktreeStrategy=o.worktreeStrategy,this.worktreeDecisions=o.worktreeDecisions,this.runtimeBootstrap=o.runtimeBootstrap,this.worktreeMessages=o.worktreeMessages,this.maintenance=o.maintenance,this.reconcilePersistedTaskFlowMirrors()}static createServiceBundle(e,t){let r=new fr,o=r.sessions,i=new Yn(t.store),s=new Jn,a=new tr,l=new nr(i.actionTokenStore,Je),d=new Ln(o,i),u=new Wn({store:i,sessions:o,resolveSession:m=>d.resolveActive(m)}),f=new sr(a,(m,P)=>u.applySessionPatch(m,P),{getPersistedSession:m=>i.getPersistedSession(m)}),h=new ar,k=new On(m=>i.getPersistedSession(m)),g=new hr,p=new Un({shouldRunWorktreeStrategy:m=>e.shouldRunWorktreeStrategy(m),isAlreadyMerged:m=>e.isAlreadyMerged(m),resolveWorktreeRepoDir:(m,P)=>e.resolveWorktreeRepoDir(m,P),getWorktreeCompletionState:(m,P,T,L)=>e.getWorktreeCompletionState(m,P,T,L),updatePersistedSession:(m,P)=>e.updatePersistedSession(m,P),getPersistedSession:m=>i.getPersistedSession(m),dispatchSessionNotification:(m,P)=>e.dispatchSessionNotification(m,P),getOutputPreview:(m,P)=>e.getOutputPreview(m,P),originThreadLine:m=>e.originThreadLine(m),getWorktreeDecisionButtons:m=>e.getWorktreeDecisionButtons(m),getPolicyAwareWorktreeDecisionButtons:(m,P,T)=>e.getWorktreeDecisionButtons(m,P,T),makeOpenPrButton:m=>e.makeActionButton(m,"worktree-create-pr","Open PR"),isPrAvailable:m=>e.resolveRepoPolicy(m).prAvailable,hasOpenPrForBranch:(m,P,T)=>{let L=nt(m,P,T);return L.exists&&L.state==="open"},getPrStatusForBranch:(m,P,T)=>nt(m,P,T),getPrStatusForUrl:(m,P,T)=>_t(m,P,T),resolveRepoPolicy:m=>e.resolveRepoPolicy(m),worktreeSummaryProvider:t.worktreeSummaryProvider,worktreeMessages:g,enqueueMerge:(m,P,T)=>e.enqueueMerge(m,P,T),mergeBranch:Mt,spawnConflictResolver:async({session:m,worktreePath:P,prompt:T})=>e.spawn({prompt:T,workdir:P,name:`${m.name}-conflict-resolver`,harness:m.harnessName||Y(),model:m.model,reasoningEffort:m.reasoningEffort,fastMode:m.fastMode,permissionMode:"bypassPermissions",multiTurn:!0,worktreeStrategy:"off",autoMergeParentSessionId:m.id,route:m.route,originChannel:m.originChannel,originThreadId:m.originThreadId,originAgentId:m.originAgentId,originSessionKey:m.originSessionKey},{notifyLaunch:!1}),runAutoPr:async(m,P)=>{let{makeAgentPrTool:T}=await import("./chunks/agent-pr.js");return{success:(await T().execute("auto-pr",{session:m.id,base_branch:P}))?.meta?.success===!0}}}),y=new lr(e.pendingAskUserQuestions,(m,P)=>e.dispatchSessionNotification(m,P),m=>{e.clearWaitingTimestampsForSession(m)},(m,P,T)=>l.getQuestionButtons(m,P,T)),w=new dr(m=>e.buildRoutingProxy(m),(m,P)=>f.dispatch(m,P),(m,P)=>e.updatePersistedSession(m,P),(m,P)=>e.getPolicyAwareWorktreeDecisionButtons(m,{},void 0,P)),R=new Sr({store:i,sessions:o,reminders:w,removeRuntimeSession:(m,P)=>r.remove(m,P),persistSession:(m,P)=>e.persistSession(m,P),clearRuntimeSessionState:m=>{e.clearWaitingTimestampsForSession(m),e.lastTurnCompleteMarkers.delete(m),e.lastTerminalWakeMarkers.delete(m)},resolveWorktreeRepoDir:(m,P)=>e.resolveWorktreeRepoDir(m,P),updatePersistedSession:(m,P)=>e.updatePersistedSession(m,P),getMaxPersistedSessions:()=>e.maxPersistedSessions});i.onActionTokensChanged(()=>e.syncActionTokenExpiryDeadline());let A=new cr({persistSession:m=>e.persistSession(m),clearWaitingTimestamp:m=>{e.clearWaitingTimestampsForSession(m)},handleWorktreeStrategy:m=>e.handleWorktreeStrategy(m),resolveWorktreeRepoDir:(m,P)=>e.resolveWorktreeRepoDir(m,P),updatePersistedSession:(m,P)=>e.updatePersistedSession(m,P),dispatchSessionNotification:(m,P)=>e.dispatchSessionNotification(m,P),notifySession:(m,P,T,L)=>e.notifySession(m,P,T,L),clearRetryTimersForSession:m=>a.clearRetryTimersForSession(m),hasTurnCompleteWakeMarker:m=>e.lastTurnCompleteMarkers.has(m),shouldEmitTurnCompleteWake:m=>e.shouldEmitTurnCompleteWake(m),shouldEmitTerminalWake:m=>e.shouldEmitTerminalWake(m),resolvePlanApprovalMode:m=>e.resolvePlanApprovalMode(m),getPlanApprovalButtons:(m,P)=>l.getPlanApprovalButtons(m,P),getResumeButtons:(m,P)=>l.getResumeButtons(m,P),getQuestionButtons:(m,P,T)=>l.getQuestionButtons(m,P,T),extractLastOutputLine:m=>e.extractLastOutputLine(m),getOutputPreview:(m,P)=>e.getOutputPreview(m,P),originThreadLine:m=>e.originThreadLine(m),debounceWaitingEvent:(m,P)=>e.debounceWaitingEvent(m,P),isAlreadyMerged:m=>e.isAlreadyMerged(m),questionContextSummaryProvider:t.questionContextSummaryProvider??Ga()}),I=new mr({getPersistedSession:m=>i.getPersistedSession(m),resolveActiveSession:m=>d.resolveActive(m),resolveWorktreeRepoDir:(m,P)=>e.resolveWorktreeRepoDir(m,P),updatePersistedSession:(m,P)=>e.updatePersistedSession(m,P),dispatchNotification:(m,P)=>f.dispatch(m,P),buildRoutingProxy:m=>e.buildRoutingProxy(m)}),b=new gr({hydrateSpawnedSession:(m,P,T)=>{k.hydrateSpawnedSession(m,P,T)},markRunning:m=>{i.markRunning(m),m.approvalState==="approved"&&m.planDecisionVersion>0&&l.consumePlanDecisionTokens(m.id,m.planDecisionVersion-1),e.pendingPlanResumeClaims.delete(m.id),e.onPersistedSessionChanged(i.getPersistedSession(m.id))},handleTerminal:async m=>{let P=e.pendingPlanResumeClaims.get(m.id);try{await e.onSessionTerminal(m)}finally{if(P){let T=xi(P,i.getPersistedSession(m.id));i.replacePersistedSession(T),e.pendingPlanResumeClaims.delete(m.id),e.onPersistedSessionChanged(T)}}},handleTurnEnd:(m,P)=>A.handleTurnEnd(m,P),formatLaunchWorkdirLabel:m=>e.formatLaunchWorkdirLabel(m),notifySession:(m,P,T,L)=>e.notifySession(m,P,T,L)});return{registry:r,sessions:o,store:i,metrics:s,wakeDispatcher:a,interactions:l,notifications:f,worktrees:h,questions:y,lifecycle:A,restore:k,stateSync:u,references:d,worktreeStrategy:p,worktreeDecisions:I,runtimeBootstrap:b,worktreeMessages:g,maintenance:R}}get persisted(){return this.store.persisted}get idIndex(){return this.store.idIndex}get nameIndex(){return this.store.nameIndex}uniqueName(e){return this.registry.uniqueName(e)}syncRuntimeGcDeadline(e){this.maintenance.syncRuntimeGcDeadline(e)}onPersistedSessionChanged(e){e&&(this.syncPersistedSessionMaintenance(e),this.enforcePersistedRetention())}syncPersistedSessionMaintenance(e){this.maintenance.syncPersistedSessionMaintenance(e)}syncActionTokenExpiryDeadline(){this.maintenance.syncActionTokenExpiryDeadline()}syncTmpOutputCleanupDeadline(e=Date.now()){this.maintenance.syncTmpOutputCleanupDeadline(e)}enforcePersistedRetention(){this.maintenance.enforcePersistedRetention()}bootstrapMaintenanceSchedules(){this.maintenance.bootstrapMaintenanceSchedules()}disposeMaintenance(){this.maintenance.dispose()}spawn(e,t={}){if(this.registry.activeSessionCount()>=this.maxSessions)throw new Error(`Max sessions reached (${this.maxSessions}). Use agent_sessions to list active sessions and agent_kill to end one.`);let o;if(e.sessionIdOverride){let g=this.getPersistedSession(e.sessionIdOverride);if(e.resumeSessionId&&g?.pendingPlanApproval){let y=rn(g,e.permissionMode??_.permissionMode);e={...e,permissionMode:y.permissionMode,...y.patch},y.approvalApplied&&(o=g)}let p=this.registry.get(e.sessionIdOverride);if(p?.status==="starting"||p?.status==="running")throw new Error(`Cannot reuse session ID ${e.sessionIdOverride}: that session is still ${p.status}.`);p&&this.registry.remove(p.id,"session-id-override-replacement"),this.clearWaitingTimestampsForSession(e.sessionIdOverride),this.lastTurnCompleteMarkers.delete(e.sessionIdOverride),this.lastTerminalWakeMarkers.delete(e.sessionIdOverride),this.maintenance.cancelRuntimeGc(e.sessionIdOverride)}let i=e.name||Pi(e.prompt),s=this.uniqueName(i);s!==i&&`${i}${s}`;let a=this.checkRepoPolicyForLaunch(e.workdir,e.worktreeStrategy);if(!a.ok){let g=a;throw new Error(g.text)}e.repoIntegrationPolicy=a.resolution.policy,e.repoIntegrationPolicySource=a.resolution.source==="none"?void 0:a.resolution.source,e.repoProvider=a.resolution.provider;let l=this.restore.prepareSpawn(e,s);if(!e.route?.provider||!e.route.target)throw new Error(`Cannot launch session "${s}": missing explicit route metadata.`);let d=e.harness??"claude-code",u=this,f,h=d==="claude-code"&&!e.canUseTool?async(g,p)=>{if(!f)throw new Error("canUseTool called before session ID was set");return u.handleAskUserQuestion(f,p)}:e.canUseTool,k=new pn({...e,workdir:l.actualWorkdir,systemPrompt:l.effectiveSystemPrompt,canUseTool:h},s);f=k.id,o&&this.pendingPlanResumeClaims.set(k.id,o),this.registry.add(k),this.metrics.incrementLaunched();try{return this.runtimeBootstrap.initializeSession(k,l,e,t)}catch(g){throw this.pendingPlanResumeClaims.delete(k.id),g}}async spawnAndAwaitRunning(e,t={}){let r=this.spawn(e,t);return await this.waitForRunningSession(r),r}async waitForRunningSession(e){if(e.status==="running")return;if(nl.has(e.status))throw new Error(this.describeLaunchFailure(e));let t=e.on?.bind(e),r=e.off?.bind(e)??e.removeListener?.bind(e);if(!t||!r)throw new Error(`Session ${e.name} [${e.id}] did not expose lifecycle events during startup.`);await new Promise((o,i)=>{let s=(l,d)=>{if(d==="running"){a(),o();return}nl.has(d)&&(a(),i(new Error(this.describeLaunchFailure(e))))},a=()=>{r("statusChange",s)};t("statusChange",s)})}describeLaunchFailure(e){let t=e.killReason?` (reason: ${e.killReason})`:"",r=e.error||e.result?.result||`status=${e.status}${t}`;return`Session ${e.name} [${e.id}] failed to start: ${r}`}formatLaunchResult(e,t){return Gt({prompt:e.prompt,workdir:e.workdir,harness:e.harness,permissionMode:e.permissionMode??_.permissionMode,planApproval:e.planApproval,resumeSessionId:e.resumeSessionId,resumeSessionName:e.resumeSessionName,forkSession:e.forkSession,forceNewSession:e.forceNewSession,clearedPersistedCodexResume:e.clearedPersistedCodexResume},t)}shouldRunWorktreeStrategy(e){let t=e.lifecycle;return!(t==="starting"||t==="awaiting_plan_decision"||t==="awaiting_user_input"||e.pendingPlanApproval)}resolveRepoPolicy(e){let t=at(e);if(!t)return{source:"none",provider:"unsupported",prAvailable:!1};let r=this.store.getRepoPolicy(t.key);if(r)return{identity:t,policy:r.policy,source:"stored",provider:t.provider,prAvailable:t.provider==="github"&&Je(),record:r};let o=as(t);if(o){let i=eo(t,o,"seeded");return{identity:t,policy:o,source:"seeded",provider:t.provider,prAvailable:to({provider:t.provider}),record:i}}return{identity:t,source:"unknown",provider:t.provider,prAvailable:to({provider:t.provider})}}checkRepoPolicyForLaunch(e,t){let r=t??_.defaultWorktreeStrategy??"off",o=this.resolveRepoPolicy(e);return r==="off"?{ok:!0,resolution:o}:o.source==="none"?{ok:!0,resolution:o}:o.source==="unknown"&&o.identity?{ok:!1,text:no(o.identity,r,o.prAvailable)}:{ok:!0,resolution:o}}getRepoPolicyRecordForWorkdir(e){return this.resolveRepoPolicy(e).record}listRepoPolicies(){return this.store.listRepoPolicies()}cleanupRepoPolicies(){let e=[...this.store.cleanupRepoPolicies()],t=[];for(let r of this.store.listRepoPolicies()){let o=at(r.repoRoot);!o||o.key===r.key||t.push(r.key)}return e.push(...this.store.removeRepoPolicies(t)),e.sort((r,o)=>r.repoRoot.localeCompare(o.repoRoot)||r.key.localeCompare(o.key))}setRepoPolicy(e,t){let r=at(e);if(r)return this.store.setRepoPolicy(eo(r,t,"stored"))}resetRepoPolicy(e){let t=at(e);return t?this.store.resetRepoPolicy(t.key):!1}requestRepoPolicyForLaunch(e){let t=e.worktreeStrategy??_.defaultWorktreeStrategy??"off",r=this.resolveRepoPolicy(e.workdir);if(!r.identity)return`Error: ${e.workdir} is not a git repository.`;let o=no(r.identity,t,r.prAvailable);if(!e.route?.provider||!e.route.target)return o;let i=`repo-policy:${r.identity.key}`,s=this.interactions.getRepoPolicyChoiceButtons({choiceId:i,route:e.route,repoRoot:r.identity.repoRoot,launchPrompt:e.prompt,launchWorkdir:e.workdir,launchName:e.name,launchModel:e.model,launchReasoningEffort:e.reasoningEffort,launchFastMode:e.fastMode,launchSystemPrompt:e.systemPrompt,launchAllowedTools:e.allowedTools,launchResumeSessionId:e.resumeSessionId,launchResumedFromSessionName:e.resumedFromSessionName,launchResumeWorktreeFrom:e.resumeWorktreeFrom,launchSessionIdOverride:e.sessionIdOverride,launchClearedPersistedCodexResume:e.clearedPersistedCodexResume,launchForkSession:e.forkSession,launchForceNewSession:e.forceNewSession,launchPermissionMode:e.permissionMode,launchPlanApproval:e.planApproval,launchHarness:e.harness,launchWorktreeStrategy:t,launchWorktreeBaseBranch:e.worktreeBaseBranch,launchWorktreePrTargetRepo:e.worktreePrTargetRepo,launchOriginAgentId:e.originAgentId,prAvailable:r.prAvailable}),a=cf(e,t);return this.notifications.dispatch(this.buildRoutingProxy({id:i,name:"repo-policy",route:e.route}),{label:"repo-policy-choice",idempotencyKey:`repo-policy-choice:${r.identity.key}:${t}:${a}`,userMessage:[o,"","After you choose a policy, OpenClaw Code Agent will continue this launch automatically."].join(`
226
+ `)?t:void 0}import{unlinkSync as sf}from"fs";var yr=class n{timers=new Map;disposed=!1;static MAX_DELAY_MS=2147483647;schedule(e,t,r){if(this.disposed||(this.cancel(e),!Number.isFinite(t)))return;let o=Math.max(0,t-Date.now()),i=setTimeout(()=>{if(this.timers.delete(e),!this.disposed){if(t-Date.now()>0){this.schedule(e,t,r);return}r()}},Math.min(o,n.MAX_DELAY_MS));i.unref?.(),this.timers.set(e,i)}cancel(e){let t=this.timers.get(e);t&&(clearTimeout(t),this.timers.delete(e))}cancelPrefix(e){for(let t of this.timers.keys())t.startsWith(e)&&this.cancel(t)}dispose(){this.disposed=!0;for(let e of this.timers.values())clearTimeout(e);this.timers.clear()}};var el=10080*60*1e3,af=300*1e3,tl="tmp-output:cleanup",lf=60*1e3;function df(n){return n instanceof Error?n.message:String(n)}var Sr=class{constructor(e){this.deps=e}deps;scheduler=new yr;lastTmpOutputCleanupAttemptAt;schedule(e,t,r){this.scheduler.schedule(e,t,r)}cancel(e){this.scheduler.cancel(e)}cancelPrefix(e){this.scheduler.cancelPrefix(e)}bootstrapMaintenanceSchedules(){let e=Date.now();this.runTmpOutputCleanup(e);for(let t of this.deps.store.listPersistedSessions())this.syncPersistedSessionMaintenance(t);this.syncActionTokenExpiryDeadline(),this.deps.store.cleanupOrphanOutputFiles(),this.syncTmpOutputCleanupDeadline(e)}syncRuntimeGcDeadline(e){if(!e.completedAt)return;let t=this.runtimeGcKey(e.id);this.schedule(t,e.completedAt+this.runtimeGcMaxAgeMs(),()=>{let r=this.deps.sessions.get(e.id);if(!r||!r.completedAt)return;let o=this.runtimeGcMaxAgeMs();if(!this.deps.store.shouldGcActiveSession(r,Date.now(),o)){this.syncRuntimeGcDeadline(r);return}this.deps.removeRuntimeSession(e.id,"runtime-gc"),this.deps.persistSession(r,{scheduleRuntimeGc:!1}),this.deps.clearRuntimeSessionState(e.id)})}cancelRuntimeGc(e){this.cancel(this.runtimeGcKey(e))}cancelPersistedMaintenance(e){let t=this.persistedMaintenanceRef(e);t&&this.cancelPrefix(`persisted:${t}:`)}syncPersistedSessionMaintenance(e){let t=this.persistedMaintenanceRef(e);if(!t)return;this.cancel(this.persistedMaintenanceKey(t,"worktree-reminder"));let r=this.deps.reminders.getNextReminderAt(e);r!=null?this.schedulePersistedWorktreeReminder(t,r):this.deps.reminders.clearResolvedReminderState(e),this.cancel(this.persistedMaintenanceKey(t,"worktree-retention"));let o=Oe(e,{activeSession:!1,includePrSync:e.worktreeLifecycle?.state==="pr_open"||!!e.worktreePrUrl}),i=this.resolvedAtIso(e),s=this.isLegacyResolvedWorktree(e);if((o.cleanupSafe||s)&&typeof i=="string"){let a=new Date(i).getTime();Number.isFinite(a)&&this.schedule(this.persistedMaintenanceKey(t,"worktree-retention"),a+el,()=>{let l=this.deps.store.getPersistedSession(t);l&&this.reconcileResolvedWorktreeRetention(l,Date.now())})}}reconcileResolvedWorktreeRetention(e,t){let r=Oe(e,{activeSession:!1,includePrSync:e.worktreeLifecycle?.state==="pr_open"||!!e.worktreePrUrl}),o=this.resolvedAtIso(e),i=o?new Date(o).getTime():0,s=this.legacyResolvedWorktreeState(e);if(!(!r.cleanupSafe&&!s||!o||!Number.isFinite(i)||t-i<el))try{if(!e.worktreePath&&!L(e))return;let a=this.deps.resolveWorktreeRepoDir(e.workdir,e.worktreePath);if(!a)return;let l=L(e)?!1:B(a,e.worktreePath);if(!L(e)&&!l)return;for(let d of z(e))this.deps.updatePersistedSession(d,{worktreePath:void 0,worktreeBranch:void 0,worktreeState:"none",pendingWorktreeDecisionSince:void 0,lastWorktreeReminderAt:void 0,worktreeDecisionSnoozedUntil:void 0,worktreeLifecycle:{...e.worktreeLifecycle??r.lifecycle,state:r.cleanupSafe?r.derivedState:s??r.derivedState,updatedAt:new Date(t).toISOString(),resolvedAt:e.worktreeLifecycle?.resolvedAt??o,resolutionSource:e.worktreeLifecycle?.resolutionSource??"maintenance",notes:r.reasons}})}catch(a){`${e.worktreePath}${df(a)}`}}syncActionTokenExpiryDeadline(){let e="tokens:expiry";this.cancel(e);let t=this.deps.store.getNextActionTokenExpiry();t!=null&&this.schedule(e,t,()=>{this.deps.store.purgeExpiredActionTokens(Date.now())||this.syncActionTokenExpiryDeadline()})}syncTmpOutputCleanupDeadline(e=Date.now()){this.cancel(tl);let t=this.deps.store.getNextTmpOutputCleanupAt(e);if(t==null){this.lastTmpOutputCleanupAttemptAt=void 0;return}t>e&&(this.lastTmpOutputCleanupAttemptAt=void 0),this.schedule(tl,this.getTmpOutputCleanupScheduleAt(t,e),()=>{let r=Date.now();this.runTmpOutputCleanup(r),this.syncTmpOutputCleanupDeadline(r)})}enforcePersistedRetention(){let e=this.deps.store.evictOldestPersisted(this.deps.getMaxPersistedSessions());for(let t of e)this.cancelPersistedMaintenance(t),t.sessionId&&this.cancelRuntimeGc(t.sessionId),this.cleanupOutputPathIfUnreferenced(t.outputPath)}dispose(){this.scheduler.dispose()}persistedMaintenanceRef(e){return e.sessionId??C(e)??e.harnessSessionId}runtimeGcKey(e){return`runtime-gc:${e}`}persistedMaintenanceKey(e,t){return`persisted:${e}:${t}`}runtimeGcMaxAgeMs(){return(_.sessionGcAgeMinutes??1440)*6e4}runTmpOutputCleanup(e){this.lastTmpOutputCleanupAttemptAt=e,this.deps.store.cleanupTmpOutputFiles(e)}getTmpOutputCleanupScheduleAt(e,t){if(e>t||this.lastTmpOutputCleanupAttemptAt==null)return e;let r=this.lastTmpOutputCleanupAttemptAt+lf;return r>t?r:e}schedulePersistedWorktreeReminder(e,t){let r=this.persistedMaintenanceKey(e,"worktree-reminder");this.schedule(r,t,()=>{let o=this.deps.store.getPersistedSession(e);if(!o||this.deps.reminders.sendReminderIfDue(o,Date.now()))return;let s=this.deps.reminders.getNextReminderAt(o);s!=null&&this.schedulePersistedWorktreeReminder(e,Math.max(s,Date.now()+af))})}cleanupOutputPathIfUnreferenced(e){if(!(!e||this.deps.store.hasOutputPathReference(e)))try{sf(e)}catch{}}resolvedAtIso(e){return e.worktreeLifecycle?.resolvedAt??e.worktreeMergedAt??e.worktreeDismissedAt??(e.completedAt?new Date(e.completedAt).toISOString():void 0)}isLegacyResolvedWorktree(e){return this.legacyResolvedWorktreeState(e)!=null}legacyResolvedWorktreeState(e){if(e.worktreeMerged===!0||e.worktreeDisposition==="merged"||e.worktreeState==="merged")return"merged";if(e.worktreeDisposition==="dismissed"||e.worktreeState==="dismissed")return"dismissed";if(e.worktreeDisposition==="no-change-cleaned")return"no_change"}};var nl=new Set(["completed","failed","killed"]),uf=new Set(["starting","running"]),pf=5e3;function cf(n,e){return rl("sha256").update(JSON.stringify({route:n.route?{provider:n.route.provider,target:n.route.target,accountId:n.route.accountId,threadId:n.route.threadId,sessionKey:n.route.sessionKey}:void 0,prompt:n.prompt,workdir:n.workdir,name:n.name,model:n.model,reasoningEffort:n.reasoningEffort,fastMode:n.fastMode,systemPrompt:n.systemPrompt,allowedTools:n.allowedTools?[...n.allowedTools].sort():n.allowedTools,resumeSessionId:n.resumeSessionId,resumedFromSessionName:n.resumedFromSessionName,resumeWorktreeFrom:n.resumeWorktreeFrom,sessionIdOverride:n.sessionIdOverride,clearedPersistedCodexResume:n.clearedPersistedCodexResume,forkSession:n.forkSession,forceNewSession:n.forceNewSession,permissionMode:n.permissionMode,planApproval:n.planApproval,harness:n.harness,worktreeStrategy:n.worktreeStrategy,effectiveWorktreeStrategy:e,worktreeBaseBranch:n.worktreeBaseBranch,worktreePrTargetRepo:n.worktreePrTargetRepo,originAgentId:n.originAgentId})).digest("hex").slice(0,16)}function mf(n){return rl("sha256").update(JSON.stringify({route:n.route?{provider:n.route.provider,target:n.route.target,accountId:n.route.accountId,threadId:n.route.threadId,sessionKey:n.route.sessionKey}:void 0,prompt:n.launchPrompt,workdir:n.launchWorkdir,name:n.launchName,model:n.launchModel,reasoningEffort:n.launchReasoningEffort,fastMode:n.launchFastMode,systemPrompt:n.launchSystemPrompt,allowedTools:n.launchAllowedTools?[...n.launchAllowedTools].sort():n.launchAllowedTools,resumeSessionId:n.launchResumeSessionId,resumedFromSessionName:n.launchResumedFromSessionName,resumeWorktreeFrom:n.launchResumeWorktreeFrom,sessionIdOverride:n.launchSessionIdOverride,clearedPersistedCodexResume:n.launchClearedPersistedCodexResume,forkSession:n.launchForkSession,forceNewSession:n.launchForceNewSession,permissionMode:n.launchPermissionMode,planApproval:n.launchPlanApproval,harness:n.launchHarness,worktreeStrategy:n.launchWorktreeStrategy,worktreeBaseBranch:n.launchWorktreeBaseBranch,worktreePrTargetRepo:n.launchWorktreePrTargetRepo,originAgentId:n.launchOriginAgentId})).digest("hex").slice(0,16)}var kr=class n{registry;sessions;maxSessions;maxPersistedSessions;lastWaitingEventTimestamps=new Map;lastTurnCompleteMarkers=new Map;lastTerminalWakeMarkers=new Map;mergeQueue=new ze;pendingAskUserQuestions=new Map;store;metrics;wakeDispatcher;interactions;notifications;worktrees;questions;lifecycle;restore;stateSync;references;worktreeStrategy;worktreeDecisions;runtimeBootstrap;worktreeMessages;maintenance;pendingPlanResumeClaims=new Map;constructor(e=20,t=50,r={}){this.maxSessions=e,this.maxPersistedSessions=t;let o=n.createServiceBundle(this,r);this.registry=o.registry,this.sessions=o.sessions,this.store=o.store,this.metrics=o.metrics,this.wakeDispatcher=o.wakeDispatcher,this.interactions=o.interactions,this.notifications=o.notifications,this.worktrees=o.worktrees,this.questions=o.questions,this.lifecycle=o.lifecycle,this.restore=o.restore,this.stateSync=o.stateSync,this.references=o.references,this.worktreeStrategy=o.worktreeStrategy,this.worktreeDecisions=o.worktreeDecisions,this.runtimeBootstrap=o.runtimeBootstrap,this.worktreeMessages=o.worktreeMessages,this.maintenance=o.maintenance,this.reconcilePersistedTaskFlowMirrors()}static createServiceBundle(e,t){let r=new fr,o=r.sessions,i=new Yn(t.store),s=new Jn,a=new tr,l=new nr(i.actionTokenStore,Je),d=new Fn(o,i),u=new Wn({store:i,sessions:o,resolveSession:m=>d.resolveActive(m)}),f=new sr(a,(m,w)=>u.applySessionPatch(m,w),{getPersistedSession:m=>i.getPersistedSession(m)}),g=new ar,k=new On(m=>i.getPersistedSession(m)),h=new hr,p=new Un({shouldRunWorktreeStrategy:m=>e.shouldRunWorktreeStrategy(m),isAlreadyMerged:m=>e.isAlreadyMerged(m),resolveWorktreeRepoDir:(m,w)=>e.resolveWorktreeRepoDir(m,w),getWorktreeCompletionState:(m,w,T,F)=>e.getWorktreeCompletionState(m,w,T,F),updatePersistedSession:(m,w)=>e.updatePersistedSession(m,w),getPersistedSession:m=>i.getPersistedSession(m),dispatchSessionNotification:(m,w)=>e.dispatchSessionNotification(m,w),getOutputPreview:(m,w)=>e.getOutputPreview(m,w),originThreadLine:m=>e.originThreadLine(m),getWorktreeDecisionButtons:m=>e.getWorktreeDecisionButtons(m),getPolicyAwareWorktreeDecisionButtons:(m,w,T)=>e.getWorktreeDecisionButtons(m,w,T),makeOpenPrButton:m=>e.makeActionButton(m,"worktree-create-pr","Open PR"),isPrAvailable:m=>e.resolveRepoPolicy(m).prAvailable,hasOpenPrForBranch:(m,w,T)=>{let F=nt(m,w,T);return F.exists&&F.state==="open"},getPrStatusForBranch:(m,w,T)=>nt(m,w,T),getPrStatusForUrl:(m,w,T)=>Dt(m,w,T),resolveRepoPolicy:m=>e.resolveRepoPolicy(m),worktreeSummaryProvider:t.worktreeSummaryProvider,worktreeMessages:h,enqueueMerge:(m,w,T)=>e.enqueueMerge(m,w,T),mergeBranch:_t,spawnConflictResolver:async({session:m,worktreePath:w,prompt:T})=>e.spawn({prompt:T,workdir:w,name:`${m.name}-conflict-resolver`,harness:m.harnessName||Y(),model:m.model,reasoningEffort:m.reasoningEffort,fastMode:m.fastMode,permissionMode:"bypassPermissions",multiTurn:!0,worktreeStrategy:"off",autoMergeParentSessionId:m.id,route:m.route,originChannel:m.originChannel,originThreadId:m.originThreadId,originAgentId:m.originAgentId,originSessionKey:m.originSessionKey},{notifyLaunch:!1}),runAutoPr:async(m,w)=>{let{makeAgentPrTool:T}=await import("./chunks/agent-pr.js");return{success:(await T().execute("auto-pr",{session:m.id,base_branch:w}))?.meta?.success===!0}}}),y=new lr(e.pendingAskUserQuestions,(m,w)=>e.dispatchSessionNotification(m,w),m=>{e.clearWaitingTimestampsForSession(m)},(m,w,T)=>l.getQuestionButtons(m,w,T)),P=new dr(m=>e.buildRoutingProxy(m),(m,w)=>f.dispatch(m,w),(m,w)=>e.updatePersistedSession(m,w),(m,w)=>e.getPolicyAwareWorktreeDecisionButtons(m,{},void 0,w)),b=new Sr({store:i,sessions:o,reminders:P,removeRuntimeSession:(m,w)=>r.remove(m,w),persistSession:(m,w)=>e.persistSession(m,w),clearRuntimeSessionState:m=>{e.clearWaitingTimestampsForSession(m),e.lastTurnCompleteMarkers.delete(m),e.lastTerminalWakeMarkers.delete(m)},resolveWorktreeRepoDir:(m,w)=>e.resolveWorktreeRepoDir(m,w),updatePersistedSession:(m,w)=>e.updatePersistedSession(m,w),getMaxPersistedSessions:()=>e.maxPersistedSessions});i.onActionTokensChanged(()=>e.syncActionTokenExpiryDeadline());let A=new cr({persistSession:m=>e.persistSession(m),clearWaitingTimestamp:m=>{e.clearWaitingTimestampsForSession(m)},handleWorktreeStrategy:m=>e.handleWorktreeStrategy(m),resolveWorktreeRepoDir:(m,w)=>e.resolveWorktreeRepoDir(m,w),updatePersistedSession:(m,w)=>e.updatePersistedSession(m,w),dispatchSessionNotification:(m,w)=>e.dispatchSessionNotification(m,w),notifySession:(m,w,T,F)=>e.notifySession(m,w,T,F),clearRetryTimersForSession:m=>a.clearRetryTimersForSession(m),hasTurnCompleteWakeMarker:m=>e.lastTurnCompleteMarkers.has(m),shouldEmitTurnCompleteWake:m=>e.shouldEmitTurnCompleteWake(m),shouldEmitTerminalWake:m=>e.shouldEmitTerminalWake(m),resolvePlanApprovalMode:m=>e.resolvePlanApprovalMode(m),getPlanApprovalButtons:(m,w)=>l.getPlanApprovalButtons(m,w),getResumeButtons:(m,w)=>l.getResumeButtons(m,w),getQuestionButtons:(m,w,T)=>l.getQuestionButtons(m,w,T),extractLastOutputLine:m=>e.extractLastOutputLine(m),getOutputPreview:(m,w)=>e.getOutputPreview(m,w),originThreadLine:m=>e.originThreadLine(m),debounceWaitingEvent:(m,w)=>e.debounceWaitingEvent(m,w),isAlreadyMerged:m=>e.isAlreadyMerged(m),questionContextSummaryProvider:t.questionContextSummaryProvider??Ga()}),I=new mr({getPersistedSession:m=>i.getPersistedSession(m),resolveActiveSession:m=>d.resolveActive(m),resolveWorktreeRepoDir:(m,w)=>e.resolveWorktreeRepoDir(m,w),updatePersistedSession:(m,w)=>e.updatePersistedSession(m,w),dispatchNotification:(m,w)=>f.dispatch(m,w),buildRoutingProxy:m=>e.buildRoutingProxy(m)}),R=new gr({hydrateSpawnedSession:(m,w,T)=>{k.hydrateSpawnedSession(m,w,T)},markRunning:m=>{i.markRunning(m),m.approvalState==="approved"&&m.planDecisionVersion>0&&l.consumePlanDecisionTokens(m.id,m.planDecisionVersion-1),e.pendingPlanResumeClaims.delete(m.id),e.onPersistedSessionChanged(i.getPersistedSession(m.id))},handleTerminal:async m=>{let w=e.pendingPlanResumeClaims.get(m.id);try{await e.onSessionTerminal(m)}finally{if(w){let T=xi(w,i.getPersistedSession(m.id));i.replacePersistedSession(T),e.pendingPlanResumeClaims.delete(m.id),e.onPersistedSessionChanged(T)}}},handleTurnEnd:(m,w)=>A.handleTurnEnd(m,w),formatLaunchWorkdirLabel:m=>e.formatLaunchWorkdirLabel(m),notifySession:(m,w,T,F)=>e.notifySession(m,w,T,F)});return{registry:r,sessions:o,store:i,metrics:s,wakeDispatcher:a,interactions:l,notifications:f,worktrees:g,questions:y,lifecycle:A,restore:k,stateSync:u,references:d,worktreeStrategy:p,worktreeDecisions:I,runtimeBootstrap:R,worktreeMessages:h,maintenance:b}}get persisted(){return this.store.persisted}get idIndex(){return this.store.idIndex}get nameIndex(){return this.store.nameIndex}uniqueName(e){return this.registry.uniqueName(e)}syncRuntimeGcDeadline(e){this.maintenance.syncRuntimeGcDeadline(e)}onPersistedSessionChanged(e){e&&(this.syncPersistedSessionMaintenance(e),this.enforcePersistedRetention())}syncPersistedSessionMaintenance(e){this.maintenance.syncPersistedSessionMaintenance(e)}syncActionTokenExpiryDeadline(){this.maintenance.syncActionTokenExpiryDeadline()}syncTmpOutputCleanupDeadline(e=Date.now()){this.maintenance.syncTmpOutputCleanupDeadline(e)}enforcePersistedRetention(){this.maintenance.enforcePersistedRetention()}bootstrapMaintenanceSchedules(){this.maintenance.bootstrapMaintenanceSchedules()}disposeMaintenance(){this.maintenance.dispose()}spawn(e,t={}){if(this.registry.activeSessionCount()>=this.maxSessions)throw new Error(`Max sessions reached (${this.maxSessions}). Use agent_sessions to list active sessions and agent_kill to end one.`);let o,i,s=y=>{i=i?Promise.all([i,y]).then(()=>{}):y};if(e.resumeSessionId&&!e.forkSession){let y=this.registry.list().filter(b=>b.backendKind==="codex-app-server"&&(b.harnessSessionId===e.resumeSessionId||b.backendRef?.conversationId===e.resumeSessionId||!b.harnessSessionId&&!b.backendRef?.conversationId&&b.resumeSessionId===e.resumeSessionId)),P=y.find(b=>b.status==="starting"||b.status==="running");if(P)throw new Error(`Cannot resume backend thread ${e.resumeSessionId}: session ${P.id} still owns its active writer.`);for(let b of y)typeof b.waitForTeardown=="function"&&s(b.waitForTeardown())}if(e.sessionIdOverride){let y=this.getPersistedSession(e.sessionIdOverride);if(e.resumeSessionId&&y?.pendingPlanApproval){let b=on(y,e.permissionMode??_.permissionMode);e={...e,permissionMode:b.permissionMode,...b.patch},b.approvalApplied&&(o=y)}let P=this.registry.get(e.sessionIdOverride);if(P?.status==="starting"||P?.status==="running")throw new Error(`Cannot reuse session ID ${e.sessionIdOverride}: that session is still ${P.status}.`);P&&(typeof P.waitForTeardown=="function"&&s(P.waitForTeardown()),this.registry.remove(P.id,"session-id-override-replacement")),this.clearWaitingTimestampsForSession(e.sessionIdOverride),this.lastTurnCompleteMarkers.delete(e.sessionIdOverride),this.lastTerminalWakeMarkers.delete(e.sessionIdOverride),this.maintenance.cancelRuntimeGc(e.sessionIdOverride)}let a=e.name||Pi(e.prompt),l=this.uniqueName(a);l!==a&&`${a}${l}`;let d=this.checkRepoPolicyForLaunch(e.workdir,e.worktreeStrategy);if(!d.ok){let y=d;throw new Error(y.text)}e.repoIntegrationPolicy=d.resolution.policy,e.repoIntegrationPolicySource=d.resolution.source==="none"?void 0:d.resolution.source,e.repoProvider=d.resolution.provider;let u=this.restore.prepareSpawn(e,l);if(!e.route?.provider||!e.route.target)throw new Error(`Cannot launch session "${l}": missing explicit route metadata.`);let f=e.harness??"claude-code",g=this,k,h=f==="claude-code"&&!e.canUseTool?async(y,P)=>{if(!k)throw new Error("canUseTool called before session ID was set");return g.handleAskUserQuestion(k,P)}:e.canUseTool,p=new pn({...e,workdir:u.actualWorkdir,systemPrompt:u.effectiveSystemPrompt,canUseTool:h},l);k=p.id,o&&this.pendingPlanResumeClaims.set(p.id,o),this.registry.add(p),this.metrics.incrementLaunched();try{return this.runtimeBootstrap.initializeSession(p,u,e,{...t,startAfter:i})}catch(y){throw this.pendingPlanResumeClaims.delete(p.id),y}}async spawnAndAwaitRunning(e,t={}){let r=this.spawn(e,t);return await this.waitForRunningSession(r),r}async waitForRunningSession(e){if(e.status==="running")return;if(nl.has(e.status))throw new Error(this.describeLaunchFailure(e));let t=e.on?.bind(e),r=e.off?.bind(e)??e.removeListener?.bind(e);if(!t||!r)throw new Error(`Session ${e.name} [${e.id}] did not expose lifecycle events during startup.`);await new Promise((o,i)=>{let s=(l,d)=>{if(d==="running"){a(),o();return}nl.has(d)&&(a(),i(new Error(this.describeLaunchFailure(e))))},a=()=>{r("statusChange",s)};t("statusChange",s)})}describeLaunchFailure(e){let t=e.killReason?` (reason: ${e.killReason})`:"",r=e.error||e.result?.result||`status=${e.status}${t}`;return`Session ${e.name} [${e.id}] failed to start: ${r}`}formatLaunchResult(e,t){return jt({prompt:e.prompt,workdir:e.workdir,harness:e.harness,permissionMode:e.permissionMode??_.permissionMode,planApproval:e.planApproval,resumeSessionId:e.resumeSessionId,resumeSessionName:e.resumeSessionName,forkSession:e.forkSession,forceNewSession:e.forceNewSession,clearedPersistedCodexResume:e.clearedPersistedCodexResume},t)}shouldRunWorktreeStrategy(e){let t=e.lifecycle;return!(t==="starting"||t==="awaiting_plan_decision"||t==="awaiting_user_input"||e.pendingPlanApproval)}resolveRepoPolicy(e){let t=lt(e);if(!t)return{source:"none",provider:"unsupported",prAvailable:!1};let r=this.store.getRepoPolicy(t.key);if(r)return{identity:t,policy:r.policy,source:"stored",provider:t.provider,prAvailable:t.provider==="github"&&Je(),record:r};let o=as(t);if(o){let i=eo(t,o,"seeded");return{identity:t,policy:o,source:"seeded",provider:t.provider,prAvailable:to({provider:t.provider}),record:i}}return{identity:t,source:"unknown",provider:t.provider,prAvailable:to({provider:t.provider})}}checkRepoPolicyForLaunch(e,t){let r=t??_.defaultWorktreeStrategy??"off",o=this.resolveRepoPolicy(e);return r==="off"?{ok:!0,resolution:o}:o.source==="none"?{ok:!0,resolution:o}:o.source==="unknown"&&o.identity?{ok:!1,text:no(o.identity,r,o.prAvailable)}:{ok:!0,resolution:o}}getRepoPolicyRecordForWorkdir(e){return this.resolveRepoPolicy(e).record}listRepoPolicies(){return this.store.listRepoPolicies()}cleanupRepoPolicies(){let e=[...this.store.cleanupRepoPolicies()],t=[];for(let r of this.store.listRepoPolicies()){let o=lt(r.repoRoot);!o||o.key===r.key||t.push(r.key)}return e.push(...this.store.removeRepoPolicies(t)),e.sort((r,o)=>r.repoRoot.localeCompare(o.repoRoot)||r.key.localeCompare(o.key))}setRepoPolicy(e,t){let r=lt(e);if(r)return this.store.setRepoPolicy(eo(r,t,"stored"))}resetRepoPolicy(e){let t=lt(e);return t?this.store.resetRepoPolicy(t.key):!1}requestRepoPolicyForLaunch(e){let t=e.worktreeStrategy??_.defaultWorktreeStrategy??"off",r=this.resolveRepoPolicy(e.workdir);if(!r.identity)return`Error: ${e.workdir} is not a git repository.`;let o=no(r.identity,t,r.prAvailable);if(!e.route?.provider||!e.route.target)return o;let i=`repo-policy:${r.identity.key}`,s=this.interactions.getRepoPolicyChoiceButtons({choiceId:i,route:e.route,repoRoot:r.identity.repoRoot,launchPrompt:e.prompt,launchWorkdir:e.workdir,launchName:e.name,launchModel:e.model,launchReasoningEffort:e.reasoningEffort,launchFastMode:e.fastMode,launchSystemPrompt:e.systemPrompt,launchAllowedTools:e.allowedTools,launchResumeSessionId:e.resumeSessionId,launchResumedFromSessionName:e.resumedFromSessionName,launchResumeWorktreeFrom:e.resumeWorktreeFrom,launchSessionIdOverride:e.sessionIdOverride,launchClearedPersistedCodexResume:e.clearedPersistedCodexResume,launchForkSession:e.forkSession,launchForceNewSession:e.forceNewSession,launchPermissionMode:e.permissionMode,launchPlanApproval:e.planApproval,launchHarness:e.harness,launchWorktreeStrategy:t,launchWorktreeBaseBranch:e.worktreeBaseBranch,launchWorktreePrTargetRepo:e.worktreePrTargetRepo,launchOriginAgentId:e.originAgentId,prAvailable:r.prAvailable}),a=cf(e,t);return this.notifications.dispatch(this.buildRoutingProxy({id:i,name:"repo-policy",route:e.route}),{label:"repo-policy-choice",idempotencyKey:`repo-policy-choice:${r.identity.key}:${t}:${a}`,userMessage:[o,"","After you choose a policy, OpenClaw Code Agent will continue this launch automatically."].join(`
227
227
  `),notifyUser:"always",requireDirectUserNotification:!0,buttons:s,wakeMessageOnNotifySuccess:["Repo policy choice buttons delivered to the user.",`Repo: ${r.identity.repoRoot}`,"Wait for their policy choice; do not set the policy or relaunch separately."].join(`
228
- `),wakeMessageOnNotifyFailed:o}),[`Repo policy choice prompt sent for ${r.identity.repoRoot}.`,r.prAvailable?"Wait for the user's Require PR, Merge or PR, No PR, or Manual response.":"Wait for the user's No PR or Manual response.","Do not send a separate plain-text policy question."].join(" ")}launchAfterRepoPolicyChoice(e){let t=e.route;if(!t?.provider||!t.target)throw new Error("missing route metadata for stored launch");let r=e.harness??Y(),o=e.permissionMode??_.permissionMode,i=e.planApproval??_.planApproval,s=this.spawn({prompt:e.prompt,workdir:e.workdir,sessionIdOverride:e.sessionIdOverride,name:e.name,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,systemPrompt:e.systemPrompt,allowedTools:e.allowedTools,resumeSessionId:e.resumeSessionId,resumedFromSessionName:e.resumedFromSessionName,resumeWorktreeFrom:e.resumeWorktreeFrom,forkSession:e.resumeSessionId?e.forkSession:!1,multiTurn:!0,permissionMode:o,planApproval:i,codexApprovalPolicy:r==="codex"?"never":void 0,originChannel:this.originChannelFromRoute(t),originThreadId:t.threadId,originAgentId:e.originAgentId,originSessionKey:t.sessionKey,route:t,harness:r,worktreeStrategy:e.worktreeStrategy,worktreeBaseBranch:e.worktreeBaseBranch,worktreePrTargetRepo:e.worktreePrTargetRepo});return{session:s,text:this.formatLaunchResult({prompt:e.prompt,workdir:e.workdir,harness:r,permissionMode:o,planApproval:i,forceNewSession:e.forceNewSession,resumeSessionId:e.resumeSessionId,resumeSessionName:e.resumedFromSessionName,forkSession:e.forkSession,clearedPersistedCodexResume:e.clearedPersistedCodexResume},s)}}continueLaunchAfterManualRepoPolicy(e,t){let r=this.resolveRepoPolicy(e);if(!r.identity)return{kind:"none"};let o=this.interactions.listActiveActionTokens("repo-policy-set").filter(u=>u.repoPolicyWorkdir===r.identity?.repoRoot),i=()=>{for(let u of new Set(o.map(f=>f.sessionId)))this.clearRepoPolicyChoiceTokens(u)},s=o.filter(u=>u.repoPolicy===t&&!!u.launchPrompt&&!!u.launchWorkdir&&!!u.route?.provider&&!!u.route?.target);if(s.length===0)return i(),{kind:"none"};let a=new Map;for(let u of s){let f=mf(u);a.has(f)||a.set(f,u)}if(a.size>1)return i(),{kind:"ambiguous",count:a.size};let l=[...a.values()][0];if(!l.launchPrompt||!l.launchWorkdir)return{kind:"none"};let d=this.launchAfterRepoPolicyChoice({route:l.route,prompt:l.launchPrompt,workdir:l.launchWorkdir,name:l.launchName,model:l.launchModel,reasoningEffort:l.launchReasoningEffort,fastMode:l.launchFastMode,systemPrompt:l.launchSystemPrompt,allowedTools:l.launchAllowedTools,resumeSessionId:l.launchResumeSessionId,resumedFromSessionName:l.launchResumedFromSessionName,resumeWorktreeFrom:l.launchResumeWorktreeFrom,sessionIdOverride:l.launchSessionIdOverride,clearedPersistedCodexResume:l.launchClearedPersistedCodexResume,forkSession:l.launchForkSession,forceNewSession:l.launchForceNewSession,permissionMode:l.launchPermissionMode,planApproval:l.launchPlanApproval,harness:l.launchHarness,worktreeStrategy:l.launchWorktreeStrategy,worktreeBaseBranch:l.launchWorktreeBaseBranch,worktreePrTargetRepo:l.launchWorktreePrTargetRepo,originAgentId:l.launchOriginAgentId});return this.consumeActionToken(l.id),this.clearRepoPolicyChoiceTokens(l.sessionId),{kind:"launched",...d}}makeActionButton(e,t,r,o={}){return this.interactions.makeActionButton(e,t,r,o)}makePluginActionButton(e,t,r,o={}){return this.makeActionButton(e,t,r,o)}consumeActionToken(e){return this.interactions.consumeActionToken(e)}getActionToken(e){return this.interactions.getActionToken(e)}clearRepoPolicyChoiceTokens(e){this.interactions.clearRepoPolicyChoiceTokens(e)}clearPlanDecisionTokens(e,t){this.interactions.clearPlanDecisionTokens(e,t)}isCurrentPendingPlanDecision(e,t){let r=this.resolve(e)??this.getPersistedSession(e);return yt(r,t)}dispatchPlanApprovalFallback(e,t,r){let o=new Date().toISOString();this.notifications.dispatch(e,{label:"plan-approval-fallback",idempotencyKey:`plan-approval:${e.id}:v${t??"unknown"}:fallback`,userMessage:ct({session:e,summary:r}),notifyUser:"always",shouldDispatch:()=>this.isCurrentPendingPlanDecision(e.id,t),hooks:{onNotifyStarted:()=>{this.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"sending",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o})},onNotifySucceeded:()=>{this.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"fallback_delivered",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o,approvalPromptDeliveredAt:new Date().toISOString(),approvalPromptFailedAt:void 0})},onNotifyFailed:()=>{this.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"failed",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o,approvalPromptFailedAt:new Date().toISOString()})}},wakeMessageOnNotifySuccess:He(e,t,!0),wakeMessageOnNotifyFailed:ur({session:e,planDecisionVersion:t})})}getWorktreeDecisionButtons(e,t={},r={merge:!0,pr:!0}){let o=this.resolve(e)??this.getPersistedSession(e);if(!(!o||o.worktreeStrategy==="delegate"&&t.allowDelegate!==!0))return this.interactions.getWorktreeDecisionButtons(e,o,r)}getPolicyAwareWorktreeDecisionButtons(e,t={},r,o){let i=r??this.resolve(e),s=o??this.getPersistedSession(e),a=this.resolveWorktreeRepoDir(i?.originalWorkdir??s?.workdir,i?.worktreePath??s?.worktreePath),l=a?this.resolveRepoPolicy(a):void 0,d=i?.repoIntegrationPolicy??s?.repoIntegrationPolicy,u=d??l?.policy,f=l?.prAvailable??!!(d&&d!=="never-pr"&&d!=="manual"),h=u?Zr({policy:u,prAvailable:f}):{merge:!0,pr:!0};return this.getWorktreeDecisionButtons(e,t,h)}getWorktreeCompletionState(e,t,r,o){return this.worktrees.getCompletionState(e,t,r,o)}notifyWorktreeOutcome(e,t,r){this.notifications.notifyWorktreeOutcome(e,t,r)}requestPlanApprovalFromUser(e,t){let r=t.trim();if(!r)return"Error: summary must not be empty.";let o=Ro(r),i=this.resolve(e),s=i?void 0:this.getPersistedSession(e),a=i??s;if(!a)return`Error: Session "${e}" not found.`;if(!a.pendingPlanApproval)return`Error: Session "${e}" is not awaiting plan approval.`;let l=D(i??s??{id:e})??e;if(this.resolvePlanApprovalMode(a)!=="delegate")return`Error: Session "${e}" already uses direct user plan approval. Do not send a duplicate approval prompt.`;let d=a.actionablePlanDecisionVersion??a.planDecisionVersion;if(ht(a,d))return[`An actionable plan review prompt already exists for session ${a.name} [${l}].`,"Wait for the user's Approve, Revise, or Reject response.","Do not send a separate plain-text approval message."].join(" ");if(a.deliveryState==="notifying")return[`A plan approval prompt is already being delivered for session ${a.name} [${l}].`,"Wait for delivery to finish before retrying."].join(" ");let u=this.interactions.getPlanApprovalButtons(l,{...a,planDecisionVersion:d}),f=[`📋 [${a.name}] Plan v${d??"?"} needs your decision:`,"","Why this was escalated:","",o,"","Choose Approve, Revise, or Reject below."].join(`
229
- `);return this.notifications.dispatch(this.buildRoutingProxy({id:l,name:a.name,sessionId:s?.sessionId,harnessSessionId:i?.harnessSessionId??s?.harnessSessionId,backendRef:i?.backendRef??s?.backendRef,route:i?.route??s?.route}),{label:"plan-approval",idempotencyKey:`plan-approval:${l}:v${d??"unknown"}:canonical`,userMessage:f,notifyUser:"always",buttons:u,hooks:{onNotifyStarted:()=>{this.updatePersistedSession(l,{approvalPromptRequiredVersion:d,approvalPromptStatus:"sending",approvalPromptVersion:d,approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptLastAttemptAt:new Date().toISOString()})},onNotifySucceeded:()=>{this.updatePersistedSession(l,{canonicalPlanPromptVersion:d,approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"delivered",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptDeliveredAt:new Date().toISOString(),approvalPromptFailedAt:void 0})},onNotifyFailed:()=>{this.updatePersistedSession(l,{approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"failed",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptFailedAt:new Date().toISOString()})}},shouldDispatch:()=>this.isCurrentPendingPlanDecision(l,d),onUserNotifyFailed:()=>this.dispatchPlanApprovalFallback(this.buildRoutingProxy({id:l,name:a.name,sessionId:s?.sessionId,harnessSessionId:i?.harnessSessionId??s?.harnessSessionId,backendRef:i?.backendRef??s?.backendRef,route:i?.route??s?.route}),d,o),wakeMessageOnNotifySuccess:He({id:l,name:a.name},d)}),[`Canonical plan approval prompt sent for session ${a.name} [${l}].`,"Wait for the user's Approve, Revise, or Reject response.","Do not send a separate plain-text approval message."].join(" ")}requestWorktreeDecisionFromUser(e,t){let r=t.trim();if(!r)return"Error: summary must not be empty.";let o=this.resolve(e),i=this.getPersistedSession(e),s=o??i;if(!s)return`Error: Session "${e}" not found.`;if(s.worktreeStrategy!=="delegate")return`Error: Session "${e}" already uses direct user worktree decisions. Do not send a duplicate decision prompt.`;if(!(!!("pendingWorktreeDecisionSince"in s?s.pendingWorktreeDecisionSince:void 0)||s.worktreeState==="pending_decision"||s.worktreeLifecycle?.state==="pending_decision"))return`Error: Session "${e}" is not awaiting a delegated worktree decision.`;let d=D(o??i??{id:e})??e,u=o?.worktreePath??i?.worktreePath,f=o?.worktreeBranch??i?.worktreeBranch,h=this.resolveWorktreeRepoDir(o?.originalWorkdir??i?.workdir,u);if(!u)return`Error: Session "${e}" has no managed worktree path.`;if(!f)return`Error: Session "${e}" has no managed worktree branch.`;if(!h)return`Error: Session "${e}" has no resolvable repository root for worktree ${u}.`;let k=o?.worktreeBaseBranch??i?.worktreeBaseBranch??Ee(h),g=Ne(h,f,k);if(!g)return`Error: Could not compute worktree diff summary for session "${e}".`;let p=this.getPolicyAwareWorktreeDecisionButtons(d,{allowDelegate:!0},o,i);if(!p||p.length===0)return`Error: Could not create worktree decision buttons for session "${e}".`;let y=r.split(/\r?\n/).map(w=>w.replace(/^[-*]\s+/,"").trim()).filter(w=>w.length>0);return this.notifications.dispatch(this.buildRoutingProxy({id:d,name:s.name,sessionId:i?.sessionId,harnessSessionId:o?.harnessSessionId??i?.harnessSessionId,backendRef:o?.backendRef??i?.backendRef,route:o?.route??i?.route}),this.worktreeMessages.buildAskNotification({session:{id:d,name:s.name,worktreePrTargetRepo:o?.worktreePrTargetRepo??i?.worktreePrTargetRepo},branchName:f,baseBranch:k,diffSummary:g,summaryLines:y,buttons:p})),[`Canonical worktree decision prompt sent for session ${s.name} [${d}].`,"Wait for the user's Merge, Open PR, Later, or Discard response.","Do not send a separate plain-text worktree decision message."].join(" ")}buildRoutingProxy(e){return{id:D(e)??C(e)??e.harnessSessionId??"unknown-session",name:e.name,harnessSessionId:e.harnessSessionId,backendRef:e.backendRef?{...e.backendRef}:void 0,route:e.route}}resolveWorktreeRepoDir(e,t){return e&&(!t||!Nn(e,t))||!t?e:It(t)??e}formatLaunchWorkdirLabel(e){if(!e.worktreePath)return e.workdir;let t=this.resolveWorktreeRepoDir(e.originalWorkdir,e.worktreePath);return!t||t===e.worktreePath?e.worktreePath:`${e.worktreePath} (worktree of ${t})`}async dismissWorktree(e){return this.worktreeDecisions.dismissWorktree(e)}snoozeWorktreeDecision(e,t){return this.worktreeDecisions.snoozeWorktreeDecision(e,t)}async handleWorktreeStrategy(e){return this.worktreeStrategy.handleWorktreeStrategy(e)}async onSessionTerminal(e){if(e.autoMergeParentSessionId){await this.handleAutoMergeResolverTerminal(e);return}return this.lifecycle.handleSessionTerminal(e)}async handleAutoMergeResolverTerminal(e){this.persistSession(e),this.clearWaitingTimestampsForSession(e.id),this.wakeDispatcher.clearRetryTimersForSession(e.id);let t=e.autoMergeParentSessionId;if(!t)return;let r=this.resolve(t),o=this.getPersistedSession(t),i=r??(o?this.buildRoutingProxy({id:o.sessionId,name:o.name,sessionId:o.sessionId,harnessSessionId:o.harnessSessionId,backendRef:o.backendRef,route:o.route}):void 0);if(!i){`${e.id}${t}`;return}if(e.status==="completed"&&r){this.updatePersistedSession(t,{autoMergeResolverSessionId:void 0}),await this.handleWorktreeStrategy(r);return}let s=r?.worktreeBranch??o?.worktreeBranch??"unknown",a=r?.worktreePath??o?.worktreePath??"(unknown worktree)",l=r?.worktreeBaseBranch??o?.worktreeBaseBranch,d=r?.worktreePrTargetRepo??o?.worktreePrTargetRepo,u=r?.worktreePushRemote??o?.worktreePushRemote;this.updatePersistedSession(t,$t({worktreeBaseBranch:l,worktreePrTargetRepo:d,worktreePushRemote:u},{clearResolverSessionId:!0,notes:[e.status==="completed"?"auto_merge_conflict_resolver_completed_without_retry_target":"auto_merge_conflict_resolver_failed"]})),this.dispatchSessionNotification(i,{label:"worktree-merge-conflict-resolver-failed",idempotencyKey:`worktree-merge-conflict-resolver-failed:${t}:${e.id}`,userMessage:[`⚠️ [${i.name}] Auto-merge conflict resolution did not complete successfully.`,`Branch \`${s}\` was preserved for manual follow-up in ${a}.`,e.status==="completed"?"The resolver finished, but the original session could not be resumed for the merge retry.":`Resolver session ${e.name} ended with status=${e.status}.`].join(`
230
- `),buttons:this.getPolicyAwareWorktreeDecisionButtons(t,{allowDelegate:!0},r,o)})}persistSession(e,t={}){let r=t.scheduleRuntimeGc??!0;this.store.hasRecordedSession(e.id)||this.metrics.recordSession(e),this.store.persistTerminal(e),r&&this.syncRuntimeGcDeadline(e),this.onPersistedSessionChanged(this.store.getPersistedSession(e.id)),this.syncTmpOutputCleanupDeadline()}reconcilePersistedTaskFlowMirrors(){let e=!1;for(let t of this.store.listPersistedSessions()){let r=Ti(t);r&&(t.taskFlowMirror=r,e=!0)}e&&this.store.saveIndex()}getMetrics(){return this.metrics.getMetrics()}notifySession(e,t,r="notification",o){this.dispatchSessionNotification(e,{label:r,idempotencyKey:r==="agent-respond"?void 0:o??`notify:${e.id}:${r}:${t}`,userMessage:t,notifyUser:"always"})}notifyResumedLaunch(e){if(!e.resumeSessionId)return;let t=this.formatLaunchWorkdirLabel(e),r=ge({harness:e.harnessName,model:e.model})??"default";this.notifySession(e,jt({sessionName:e.name,resumedFromSessionName:e.resumedFromSessionName,workdirLabel:t,harnessLabel:r}),"resumed-launch",`resumed-launch:${e.id}:${e.startedAt}:${e.resumeSessionId}`)}sendPlanOffer(e){let t=this.interactions.getPlanOfferButtons({offerId:e.offerId,route:e.route,planName:e.planName,planPrompt:e.planPrompt,planWorkdir:e.planWorkdir,planWorktreeStrategy:e.planWorktreeStrategy});this.dispatchSessionNotification(this.buildRoutingProxy({id:e.offerId,route:e.route}),{label:"plan-offer",idempotencyKey:`plan-offer:${e.offerId}`,userMessage:e.text,notifyUser:"always",buttons:t})}emitGoalTaskUpdate(e,t,r="goal-task"){let o=e.sessionId??e.id,i=this.buildRoutingProxy({id:o,name:e.sessionName??e.name,route:e.route});i.originChannel=e.originChannel,i.originThreadId=e.originThreadId,i.originSessionKey=e.originSessionKey;let s=r==="goal-task-succeeded",a=[`✅ [${e.name}] Goal task succeeded`,e.sessionId?`Session: ${e.sessionName??e.name} [${e.sessionId}]`:void 0].filter(d=>!!d).join(`
231
- `),l=d=>ho({sessionId:o,sessionName:e.sessionName,taskName:e.name,summary:t,originThreadLine:Ye(i),canonicalStatusDelivered:d});this.dispatchSessionNotification(i,{label:r,idempotencyKey:`goal:${e.id}:${r}:${s?"success":t}`,userMessage:s?a:t,notifyUser:"always",completionSummary:s?{required:!0,producer:"goal",outcomeKey:`goal:${e.id}`}:void 0,completionWakeSummaryRequired:s,completionWakeOutcomeKey:s?`goal:${e.id}`:void 0,wakeMessageOnNotifySuccess:s?l(!0):void 0,wakeMessageOnNotifyFailed:s?l(!1):void 0})}launchPlanOffer(e){let t=e.route??{provider:"system",target:"system"};return this.spawn({prompt:e.prompt,workdir:e.workdir,name:e.name,harness:Y(),permissionMode:"plan",planApproval:"ask",worktreeStrategy:e.worktreeStrategy??"off",multiTurn:!0,route:t,originChannel:this.originChannelFromRoute(t),originThreadId:t.threadId,originSessionKey:t.sessionKey})}dispatchSessionNotification(e,t){this.notifications.dispatch(e,t)}originChannelFromRoute(e){return e.accountId?`${e.provider}|${e.accountId}|${e.target}`:`${e.provider}|${e.target}`}debounceWaitingEvent(e,t){let r=Date.now(),o=t?`${e}:${t}`:e,i=this.lastWaitingEventTimestamps.get(o);return i&&r-i<pf?!1:(this.lastWaitingEventTimestamps.set(o,r),!0)}clearWaitingTimestampsForSession(e){this.lastWaitingEventTimestamps.delete(e);let t=`${e}:`;for(let r of this.lastWaitingEventTimestamps.keys())r.startsWith(t)&&this.lastWaitingEventTimestamps.delete(r)}originThreadLine(e){return Ye(e)}extractLastOutputLine(e){return e.getOutput(3).filter(o=>o.trim()).pop()?.trim()||void 0}getOutputPreview(e,t=1e3){return Xa(e,t)}resolvePlanApprovalMode(e){return e.planApproval??_.planApproval??"delegate"}shouldEmitTurnCompleteWake(e){let t=`${e.startedAt??0}|${e.result?.session_id??""}|${e.result?.num_turns??0}`;return this.lastTurnCompleteMarkers.get(e.id)===t?(`${e.id}${t}`,!1):(this.lastTurnCompleteMarkers.set(e.id,t),!0)}shouldEmitTerminalWake(e){let t=`${e.status}|${e.startedAt??0}|${e.result?.session_id??""}|${e.result?.num_turns??0}|${e.killReason}`;return this.lastTerminalWakeMarkers.get(e.id)===t?!1:(this.lastTerminalWakeMarkers.set(e.id,t),!0)}resolve(e){return this.references.resolveActive(e)}get(e){return this.registry.get(e)}list(e){let t=this.registry.list();return e&&e!=="all"&&(t=t.filter(r=>r.status===e)),t.sort((r,o)=>o.startedAt-r.startedAt)}kill(e,t){let r=this.registry.get(e);if(!r)return!1;if(r.pendingPlanApproval){this.clearPlanDecisionTokens(r.id);let o={lifecycle:"terminal",runtimeState:"stopped",pendingPlanApproval:!1,planApprovalContext:void 0,approvalState:r.approvalState==="pending"?"rejected":r.approvalState,planDecisionVersion:(r.planDecisionVersion??0)+1,actionablePlanDecisionVersion:void 0,canonicalPlanPromptVersion:void 0,approvalPromptRequiredVersion:void 0,approvalPromptVersion:void 0,approvalPromptStatus:"not_sent",approvalPromptTransport:"none",approvalPromptMessageKind:"none",approvalPromptLastAttemptAt:void 0,approvalPromptDeliveredAt:void 0,approvalPromptFailedAt:void 0};r.applyControlPatch(o),Object.assign(r,o),this.updatePersistedSession(r.id,o)}return r.kill(t??"user"),!0}killAll(e="user"){for(let t of this.sessions.values())uf.has(t.status)&&this.kill(t.id,e)}resolveBackendConversationId(e){return this.references.resolveBackendConversationId(e)}resolveHarnessSessionId(e){return this.resolveBackendConversationId(e)}getPersistedSession(e){return this.references.getPersistedSession(e)}isAlreadyMerged(e){if(!e)return!1;let t=this.store.getPersistedSession(e);return t?.worktreeMerged===!0||t?.worktreeLifecycle?.state==="merged"||t?.worktreeLifecycle?.state==="released"}async enqueueMerge(e,t,r){return this.mergeQueue.enqueue(e,t,r)}updatePersistedSession(e,t){let r=this.stateSync.applySessionPatch(e,t);return r&&this.onPersistedSessionChanged(this.store.getPersistedSession(e)),r}listPersistedSessions(){return this.store.listPersistedSessions()}async handleAskUserQuestion(e,t){let r=this.sessions.get(e);if(!r)throw new Error(`Session "${e}" not found for AskUserQuestion intercept`);return this.questions.handleAskUserQuestion(r,t)}resolveAskUserQuestion(e,t,r={}){return this.questions.resolveAskUserQuestion(e,t,r)}async resolvePendingInputOption(e,t,r={}){let o=this.sessions.get(e);return o?.canSubmitPendingInputOption?.()?await o.submitPendingInputOption(t,r)?(this.clearWaitingTimestampsForSession(e),!0):!1:this.questions.resolveAskUserQuestion(e,t,r)}canSubmitPendingInputOption(e){return this.sessions.get(e)?.canSubmitPendingInputOption?.()===!0}pendingInputSubmissionRequiresMore(e){return this.sessions.get(e)?.pendingInputSubmissionRequiresMore()===!0}consumeQuestionAnswerTokens(e,t,r){return this.interactions.consumeQuestionAnswerTokens(e,t,r)}consumePlanDecisionTokens(e,t){return this.interactions.consumePlanDecisionTokens(e,t)}dispose(){this.disposeMaintenance(),this.questions.dispose(),this.notifications.dispose()}};import{definePluginEntry as ol}from"openclaw/plugin-sdk/plugin-entry";function Sf(n){let e=parseInt(process.env.OPENCLAW_WORKTREE_CLEANUP_AGE_HOURS??"168",10)||168,t=e*60*60*1e3,r=Date.now()-t,o=new Set(n.listPersistedSessions().map(l=>l.worktreePath).filter(l=>typeof l=="string"&&l.length>0)),i=new Set,s=process.env.OPENCLAW_WORKTREE_DIR??_.worktreeDir;if(s)i.add(s);else for(let l of n.listPersistedSessions())if(l.workdir)try{let d=yf("git",["rev-parse","--show-toplevel"],{cwd:l.workdir,timeout:5e3,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim();d&&i.add(Wo(d,".worktrees"))}catch{}if(i.size===0)return;let a=0;for(let l of i)try{let d=ff(l);for(let u of d){if(!u.startsWith("openclaw-worktree-"))continue;let f=Wo(l,u);try{let h=gf(f);if(!h.isDirectory()||h.mtimeMs>r||o.has(f))continue;hf(f,{recursive:!0,force:!0}),a++}catch(h){`${f}${h instanceof Error?h.message:String(h)}`}}}catch{}a>0&&`${a}${e}`}function kf(n){if(!n||typeof n!="object")return;let e=n,t=e.channel?.trim().toLowerCase();if(!t)return;let r=t==="telegram"?e.callback?.chatId??e.parentConversationId??e.conversationId:e.parentConversationId??e.conversationId??e.callback?.chatId;if(r)return ue(e.accountId?`${t}|${e.accountId}|${r}`:`${t}|${r}`,e.threadId,e.sessionKey)}function vf(n){let e=null,t=null,r=null,o=!1,i=!1,s=n.registerTool;Te(n.runtime);let a=()=>Wo(zn(process.env),"plugin-state","openclaw-code-agent"),l=p=>{let y=p.deliveryContext;return y?.channel&&y.to?ue(y.accountId?`${y.channel}|${y.accountId}|${y.to}`:`${y.channel}|${y.to}`,y.threadId,p.sessionKey):ue(p.messageChannel,void 0,p.sessionKey)},d=p=>{r?.maybeCheckForUpdate({route:p})},u=p=>{if(o){p&&!i&&(Te(n.runtime,p.config),i=!0);return}let y=n.pluginConfig??{};Ko(y),p?(Te(n.runtime,p.config),i=!0):(Te(n.runtime),i=!1),e=new kr(_.maxSessions,_.maxPersistedSessions,{worktreeSummaryProvider:fa()}),t=new En(e),r=new Ut({stateDir:p?.stateDir??a(),currentVersion:n.version??ti.version??"0.0.0",actionButtonFactory:(w,R,A,I)=>e.makePluginActionButton(w,R,A,I)}),Pr(e),wr(t),br(r),t.start(),Sf(e),e.bootstrapMaintenanceSchedules(),o=!0,d()},f=()=>{t&&t.stop(),e&&e.killAll("shutdown"),e&&e.dispose(),t=null,e=null,r=null,o=!1,i=!1,Te(void 0),wr(null),Pr(null),br(null)},h=(p,y)=>{s(w=>(u(),d(l(w)),p(w)),y)},k={...n,registerCommand(p){n.registerCommand({...p,handler:y=>(u(),d(l(y)),p.handler(y))})}},g=p=>{let y=bs(p);n.registerInteractiveHandler({...y,handler:async w=>(u(),d(kf(w)),y.handler(w))})};h(p=>Mi(p),{optional:!1,name:"agent_launch"}),h(p=>Gi(p),{optional:!1,name:"agent_sessions"}),h(p=>ji(p),{optional:!1,name:"agent_kill"}),h(p=>hn(p),{optional:!1,name:"agent_output"}),h(p=>Xi(p),{optional:!1,name:"agent_respond"}),h(p=>Zi(p),{optional:!1,name:"agent_request_plan_approval"}),h(p=>es(p),{optional:!1,name:"agent_request_worktree_decision"}),h(p=>rs(p),{optional:!1,name:"agent_send_plan_offer"}),h(p=>os(p),{optional:!1,name:"agent_stats"}),h(p=>ds(p),{optional:!1,name:"agent_repo_policy"}),h(p=>vn(p),{optional:!1,name:"agent_merge"}),h(p=>Bt(p),{optional:!1,name:"agent_pr"}),h(p=>us(p),{optional:!1,name:"agent_worktree_cleanup"}),h(p=>ps(p),{optional:!1,name:"agent_worktree_status"}),h(p=>cs(p),{optional:!1,name:"agent_goal_launch"}),h(p=>fs(p),{optional:!1,name:"agent_goal_status"}),h(p=>gs(p),{optional:!1,name:"agent_goal_stop"}),h(p=>hs(p),{optional:!1,name:"agent_goal_edit"}),g("telegram"),g("discord"),As(k),Is(k),Ts(k),xs(k),Cs(k),Ms(k),_s(k),$s(k),Es(k),Ns(k),Ws(k),n.registerService({id:"openclaw-code-agent",start:u,stop:f})}var ub=ol({id:"openclaw-code-agent",name:"Code Agent",description:"Multi-session coding-agent orchestration from OpenClaw chat",register:vf});export{ub as default,vf as register,kf as routeFromInteractiveContext};
228
+ `),wakeMessageOnNotifyFailed:o}),[`Repo policy choice prompt sent for ${r.identity.repoRoot}.`,r.prAvailable?"Wait for the user's Require PR, Merge or PR, No PR, or Manual response.":"Wait for the user's No PR or Manual response.","Do not send a separate plain-text policy question."].join(" ")}launchAfterRepoPolicyChoice(e){let t=e.route;if(!t?.provider||!t.target)throw new Error("missing route metadata for stored launch");let r=e.harness??Y(),o=e.permissionMode??_.permissionMode,i=e.planApproval??_.planApproval,s=this.spawn({prompt:e.prompt,workdir:e.workdir,sessionIdOverride:e.sessionIdOverride,name:e.name,model:e.model,reasoningEffort:e.reasoningEffort,fastMode:e.fastMode,systemPrompt:e.systemPrompt,allowedTools:e.allowedTools,resumeSessionId:e.resumeSessionId,resumedFromSessionName:e.resumedFromSessionName,resumeWorktreeFrom:e.resumeWorktreeFrom,forkSession:e.resumeSessionId?e.forkSession:!1,multiTurn:!0,permissionMode:o,planApproval:i,codexApprovalPolicy:r==="codex"?"never":void 0,originChannel:this.originChannelFromRoute(t),originThreadId:t.threadId,originAgentId:e.originAgentId,originSessionKey:t.sessionKey,route:t,harness:r,worktreeStrategy:e.worktreeStrategy,worktreeBaseBranch:e.worktreeBaseBranch,worktreePrTargetRepo:e.worktreePrTargetRepo});return{session:s,text:this.formatLaunchResult({prompt:e.prompt,workdir:e.workdir,harness:r,permissionMode:o,planApproval:i,forceNewSession:e.forceNewSession,resumeSessionId:e.resumeSessionId,resumeSessionName:e.resumedFromSessionName,forkSession:e.forkSession,clearedPersistedCodexResume:e.clearedPersistedCodexResume},s)}}continueLaunchAfterManualRepoPolicy(e,t){let r=this.resolveRepoPolicy(e);if(!r.identity)return{kind:"none"};let o=this.interactions.listActiveActionTokens("repo-policy-set").filter(u=>u.repoPolicyWorkdir===r.identity?.repoRoot),i=()=>{for(let u of new Set(o.map(f=>f.sessionId)))this.clearRepoPolicyChoiceTokens(u)},s=o.filter(u=>u.repoPolicy===t&&!!u.launchPrompt&&!!u.launchWorkdir&&!!u.route?.provider&&!!u.route?.target);if(s.length===0)return i(),{kind:"none"};let a=new Map;for(let u of s){let f=mf(u);a.has(f)||a.set(f,u)}if(a.size>1)return i(),{kind:"ambiguous",count:a.size};let l=[...a.values()][0];if(!l.launchPrompt||!l.launchWorkdir)return{kind:"none"};let d=this.launchAfterRepoPolicyChoice({route:l.route,prompt:l.launchPrompt,workdir:l.launchWorkdir,name:l.launchName,model:l.launchModel,reasoningEffort:l.launchReasoningEffort,fastMode:l.launchFastMode,systemPrompt:l.launchSystemPrompt,allowedTools:l.launchAllowedTools,resumeSessionId:l.launchResumeSessionId,resumedFromSessionName:l.launchResumedFromSessionName,resumeWorktreeFrom:l.launchResumeWorktreeFrom,sessionIdOverride:l.launchSessionIdOverride,clearedPersistedCodexResume:l.launchClearedPersistedCodexResume,forkSession:l.launchForkSession,forceNewSession:l.launchForceNewSession,permissionMode:l.launchPermissionMode,planApproval:l.launchPlanApproval,harness:l.launchHarness,worktreeStrategy:l.launchWorktreeStrategy,worktreeBaseBranch:l.launchWorktreeBaseBranch,worktreePrTargetRepo:l.launchWorktreePrTargetRepo,originAgentId:l.launchOriginAgentId});return this.consumeActionToken(l.id),this.clearRepoPolicyChoiceTokens(l.sessionId),{kind:"launched",...d}}makeActionButton(e,t,r,o={}){return this.interactions.makeActionButton(e,t,r,o)}makePluginActionButton(e,t,r,o={}){return this.makeActionButton(e,t,r,o)}consumeActionToken(e){return this.interactions.consumeActionToken(e)}getActionToken(e){return this.interactions.getActionToken(e)}clearRepoPolicyChoiceTokens(e){this.interactions.clearRepoPolicyChoiceTokens(e)}clearPlanDecisionTokens(e,t){this.interactions.clearPlanDecisionTokens(e,t)}isCurrentPendingPlanDecision(e,t){let r=this.resolve(e)??this.getPersistedSession(e);return St(r,t)}dispatchPlanApprovalFallback(e,t,r){let o=new Date().toISOString();this.notifications.dispatch(e,{label:"plan-approval-fallback",idempotencyKey:`plan-approval:${e.id}:v${t??"unknown"}:fallback`,userMessage:mt({session:e,summary:r}),notifyUser:"always",shouldDispatch:()=>this.isCurrentPendingPlanDecision(e.id,t),hooks:{onNotifyStarted:()=>{this.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"sending",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o})},onNotifySucceeded:()=>{this.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"fallback_delivered",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o,approvalPromptDeliveredAt:new Date().toISOString(),approvalPromptFailedAt:void 0})},onNotifyFailed:()=>{this.updatePersistedSession(e.id,{approvalPromptRequiredVersion:t,approvalPromptVersion:t,approvalPromptStatus:"failed",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"explicit_fallback_text",approvalPromptLastAttemptAt:o,approvalPromptFailedAt:new Date().toISOString()})}},wakeMessageOnNotifySuccess:He(e,t,!0),wakeMessageOnNotifyFailed:ur({session:e,planDecisionVersion:t})})}getWorktreeDecisionButtons(e,t={},r={merge:!0,pr:!0}){let o=this.resolve(e)??this.getPersistedSession(e);if(!(!o||o.worktreeStrategy==="delegate"&&t.allowDelegate!==!0))return this.interactions.getWorktreeDecisionButtons(e,o,r)}getPolicyAwareWorktreeDecisionButtons(e,t={},r,o){let i=r??this.resolve(e),s=o??this.getPersistedSession(e),a=this.resolveWorktreeRepoDir(i?.originalWorkdir??s?.workdir,i?.worktreePath??s?.worktreePath),l=a?this.resolveRepoPolicy(a):void 0,d=i?.repoIntegrationPolicy??s?.repoIntegrationPolicy,u=d??l?.policy,f=l?.prAvailable??!!(d&&d!=="never-pr"&&d!=="manual"),g=u?Zr({policy:u,prAvailable:f}):{merge:!0,pr:!0};return this.getWorktreeDecisionButtons(e,t,g)}getWorktreeCompletionState(e,t,r,o){return this.worktrees.getCompletionState(e,t,r,o)}notifyWorktreeOutcome(e,t,r){this.notifications.notifyWorktreeOutcome(e,t,r)}requestPlanApprovalFromUser(e,t){let r=t.trim();if(!r)return"Error: summary must not be empty.";let o=Ro(r),i=this.resolve(e),s=i?void 0:this.getPersistedSession(e),a=i??s;if(!a)return`Error: Session "${e}" not found.`;if(!a.pendingPlanApproval)return`Error: Session "${e}" is not awaiting plan approval.`;let l=D(i??s??{id:e})??e;if(this.resolvePlanApprovalMode(a)!=="delegate")return`Error: Session "${e}" already uses direct user plan approval. Do not send a duplicate approval prompt.`;let d=a.actionablePlanDecisionVersion??a.planDecisionVersion;if(yt(a,d))return[`An actionable plan review prompt already exists for session ${a.name} [${l}].`,"Wait for the user's Approve, Revise, or Reject response.","Do not send a separate plain-text approval message."].join(" ");if(a.deliveryState==="notifying")return[`A plan approval prompt is already being delivered for session ${a.name} [${l}].`,"Wait for delivery to finish before retrying."].join(" ");let u=this.interactions.getPlanApprovalButtons(l,{...a,planDecisionVersion:d}),f=[`📋 [${a.name}] Plan v${d??"?"} needs your decision:`,"","Why this was escalated:","",o,"","Choose Approve, Revise, or Reject below."].join(`
229
+ `);return this.notifications.dispatch(this.buildRoutingProxy({id:l,name:a.name,sessionId:s?.sessionId,harnessSessionId:i?.harnessSessionId??s?.harnessSessionId,backendRef:i?.backendRef??s?.backendRef,route:i?.route??s?.route}),{label:"plan-approval",idempotencyKey:`plan-approval:${l}:v${d??"unknown"}:canonical`,userMessage:f,notifyUser:"always",buttons:u,hooks:{onNotifyStarted:()=>{this.updatePersistedSession(l,{approvalPromptRequiredVersion:d,approvalPromptStatus:"sending",approvalPromptVersion:d,approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptLastAttemptAt:new Date().toISOString()})},onNotifySucceeded:()=>{this.updatePersistedSession(l,{canonicalPlanPromptVersion:d,approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"delivered",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptDeliveredAt:new Date().toISOString(),approvalPromptFailedAt:void 0})},onNotifyFailed:()=>{this.updatePersistedSession(l,{approvalPromptRequiredVersion:d,approvalPromptVersion:d,approvalPromptStatus:"failed",approvalPromptTransport:"direct-message",approvalPromptMessageKind:"canonical_buttons",approvalPromptFailedAt:new Date().toISOString()})}},shouldDispatch:()=>this.isCurrentPendingPlanDecision(l,d),onUserNotifyFailed:()=>this.dispatchPlanApprovalFallback(this.buildRoutingProxy({id:l,name:a.name,sessionId:s?.sessionId,harnessSessionId:i?.harnessSessionId??s?.harnessSessionId,backendRef:i?.backendRef??s?.backendRef,route:i?.route??s?.route}),d,o),wakeMessageOnNotifySuccess:He({id:l,name:a.name},d)}),[`Canonical plan approval prompt sent for session ${a.name} [${l}].`,"Wait for the user's Approve, Revise, or Reject response.","Do not send a separate plain-text approval message."].join(" ")}requestWorktreeDecisionFromUser(e,t){let r=t.trim();if(!r)return"Error: summary must not be empty.";let o=this.resolve(e),i=this.getPersistedSession(e),s=o??i;if(!s)return`Error: Session "${e}" not found.`;if(s.worktreeStrategy!=="delegate")return`Error: Session "${e}" already uses direct user worktree decisions. Do not send a duplicate decision prompt.`;if(!(!!("pendingWorktreeDecisionSince"in s?s.pendingWorktreeDecisionSince:void 0)||s.worktreeState==="pending_decision"||s.worktreeLifecycle?.state==="pending_decision"))return`Error: Session "${e}" is not awaiting a delegated worktree decision.`;let d=D(o??i??{id:e})??e,u=o?.worktreePath??i?.worktreePath,f=o?.worktreeBranch??i?.worktreeBranch,g=this.resolveWorktreeRepoDir(o?.originalWorkdir??i?.workdir,u);if(!u)return`Error: Session "${e}" has no managed worktree path.`;if(!f)return`Error: Session "${e}" has no managed worktree branch.`;if(!g)return`Error: Session "${e}" has no resolvable repository root for worktree ${u}.`;let k=o?.worktreeBaseBranch??i?.worktreeBaseBranch??Ee(g),h=Ne(g,f,k);if(!h)return`Error: Could not compute worktree diff summary for session "${e}".`;let p=this.getPolicyAwareWorktreeDecisionButtons(d,{allowDelegate:!0},o,i);if(!p||p.length===0)return`Error: Could not create worktree decision buttons for session "${e}".`;let y=r.split(/\r?\n/).map(P=>P.replace(/^[-*]\s+/,"").trim()).filter(P=>P.length>0);return this.notifications.dispatch(this.buildRoutingProxy({id:d,name:s.name,sessionId:i?.sessionId,harnessSessionId:o?.harnessSessionId??i?.harnessSessionId,backendRef:o?.backendRef??i?.backendRef,route:o?.route??i?.route}),this.worktreeMessages.buildAskNotification({session:{id:d,name:s.name,worktreePrTargetRepo:o?.worktreePrTargetRepo??i?.worktreePrTargetRepo},branchName:f,baseBranch:k,diffSummary:h,summaryLines:y,buttons:p})),[`Canonical worktree decision prompt sent for session ${s.name} [${d}].`,"Wait for the user's Merge, Open PR, Later, or Discard response.","Do not send a separate plain-text worktree decision message."].join(" ")}buildRoutingProxy(e){return{id:D(e)??C(e)??e.harnessSessionId??"unknown-session",name:e.name,harnessSessionId:e.harnessSessionId,backendRef:e.backendRef?{...e.backendRef}:void 0,route:e.route}}resolveWorktreeRepoDir(e,t){return e&&(!t||!Nn(e,t))||!t?e:Tt(t)??e}formatLaunchWorkdirLabel(e){if(!e.worktreePath)return e.workdir;let t=this.resolveWorktreeRepoDir(e.originalWorkdir,e.worktreePath);return!t||t===e.worktreePath?e.worktreePath:`${e.worktreePath} (worktree of ${t})`}async dismissWorktree(e){return this.worktreeDecisions.dismissWorktree(e)}snoozeWorktreeDecision(e,t){return this.worktreeDecisions.snoozeWorktreeDecision(e,t)}async handleWorktreeStrategy(e){return this.worktreeStrategy.handleWorktreeStrategy(e)}async onSessionTerminal(e){if(e.autoMergeParentSessionId){await this.handleAutoMergeResolverTerminal(e);return}return this.lifecycle.handleSessionTerminal(e)}async handleAutoMergeResolverTerminal(e){this.persistSession(e),this.clearWaitingTimestampsForSession(e.id),this.wakeDispatcher.clearRetryTimersForSession(e.id);let t=e.autoMergeParentSessionId;if(!t)return;let r=this.resolve(t),o=this.getPersistedSession(t),i=r??(o?this.buildRoutingProxy({id:o.sessionId,name:o.name,sessionId:o.sessionId,harnessSessionId:o.harnessSessionId,backendRef:o.backendRef,route:o.route}):void 0);if(!i){`${e.id}${t}`;return}if(e.status==="completed"&&r){this.updatePersistedSession(t,{autoMergeResolverSessionId:void 0}),await this.handleWorktreeStrategy(r);return}let s=r?.worktreeBranch??o?.worktreeBranch??"unknown",a=r?.worktreePath??o?.worktreePath??"(unknown worktree)",l=r?.worktreeBaseBranch??o?.worktreeBaseBranch,d=r?.worktreePrTargetRepo??o?.worktreePrTargetRepo,u=r?.worktreePushRemote??o?.worktreePushRemote;this.updatePersistedSession(t,Et({worktreeBaseBranch:l,worktreePrTargetRepo:d,worktreePushRemote:u},{clearResolverSessionId:!0,notes:[e.status==="completed"?"auto_merge_conflict_resolver_completed_without_retry_target":"auto_merge_conflict_resolver_failed"]})),this.dispatchSessionNotification(i,{label:"worktree-merge-conflict-resolver-failed",idempotencyKey:`worktree-merge-conflict-resolver-failed:${t}:${e.id}`,userMessage:[`⚠️ [${i.name}] Auto-merge conflict resolution did not complete successfully.`,`Branch \`${s}\` was preserved for manual follow-up in ${a}.`,e.status==="completed"?"The resolver finished, but the original session could not be resumed for the merge retry.":`Resolver session ${e.name} ended with status=${e.status}.`].join(`
230
+ `),buttons:this.getPolicyAwareWorktreeDecisionButtons(t,{allowDelegate:!0},r,o)})}persistSession(e,t={}){let r=t.scheduleRuntimeGc??!0;this.store.hasRecordedSession(e.id)||this.metrics.recordSession(e),this.store.persistTerminal(e),r&&this.syncRuntimeGcDeadline(e),this.onPersistedSessionChanged(this.store.getPersistedSession(e.id)),this.syncTmpOutputCleanupDeadline()}reconcilePersistedTaskFlowMirrors(){let e=!1;for(let t of this.store.listPersistedSessions()){let r=Ti(t);r&&(t.taskFlowMirror=r,e=!0)}e&&this.store.saveIndex()}getMetrics(){return this.metrics.getMetrics()}notifySession(e,t,r="notification",o){this.dispatchSessionNotification(e,{label:r,idempotencyKey:r==="agent-respond"?void 0:o??`notify:${e.id}:${r}:${t}`,userMessage:t,notifyUser:"always"})}notifyResumedLaunch(e){if(!e.resumeSessionId)return;let t=this.formatLaunchWorkdirLabel(e),r=ge({harness:e.harnessName,model:e.model})??"default";this.notifySession(e,zt({sessionName:e.name,resumedFromSessionName:e.resumedFromSessionName,workdirLabel:t,harnessLabel:r}),"resumed-launch",`resumed-launch:${e.id}:${e.startedAt}:${e.resumeSessionId}`)}sendPlanOffer(e){let t=this.interactions.getPlanOfferButtons({offerId:e.offerId,route:e.route,planName:e.planName,planPrompt:e.planPrompt,planWorkdir:e.planWorkdir,planWorktreeStrategy:e.planWorktreeStrategy});this.dispatchSessionNotification(this.buildRoutingProxy({id:e.offerId,route:e.route}),{label:"plan-offer",idempotencyKey:`plan-offer:${e.offerId}`,userMessage:e.text,notifyUser:"always",buttons:t})}emitGoalTaskUpdate(e,t,r="goal-task"){let o=e.sessionId??e.id,i=this.buildRoutingProxy({id:o,name:e.sessionName??e.name,route:e.route});i.originChannel=e.originChannel,i.originThreadId=e.originThreadId,i.originSessionKey=e.originSessionKey;let s=r==="goal-task-succeeded",a=[`✅ [${e.name}] Goal task succeeded`,e.sessionId?`Session: ${e.sessionName??e.name} [${e.sessionId}]`:void 0].filter(d=>!!d).join(`
231
+ `),l=d=>ho({sessionId:o,sessionName:e.sessionName,taskName:e.name,summary:t,originThreadLine:Ye(i),canonicalStatusDelivered:d});this.dispatchSessionNotification(i,{label:r,idempotencyKey:`goal:${e.id}:${r}:${s?"success":t}`,userMessage:s?a:t,notifyUser:"always",completionSummary:s?{required:!0,producer:"goal",outcomeKey:`goal:${e.id}`}:void 0,completionWakeSummaryRequired:s,completionWakeOutcomeKey:s?`goal:${e.id}`:void 0,wakeMessageOnNotifySuccess:s?l(!0):void 0,wakeMessageOnNotifyFailed:s?l(!1):void 0})}launchPlanOffer(e){let t=e.route??{provider:"system",target:"system"};return this.spawn({prompt:e.prompt,workdir:e.workdir,name:e.name,harness:Y(),permissionMode:"plan",planApproval:"ask",worktreeStrategy:e.worktreeStrategy??"off",multiTurn:!0,route:t,originChannel:this.originChannelFromRoute(t),originThreadId:t.threadId,originSessionKey:t.sessionKey})}dispatchSessionNotification(e,t){this.notifications.dispatch(e,t)}originChannelFromRoute(e){return e.accountId?`${e.provider}|${e.accountId}|${e.target}`:`${e.provider}|${e.target}`}debounceWaitingEvent(e,t){let r=Date.now(),o=t?`${e}:${t}`:e,i=this.lastWaitingEventTimestamps.get(o);return i&&r-i<pf?!1:(this.lastWaitingEventTimestamps.set(o,r),!0)}clearWaitingTimestampsForSession(e){this.lastWaitingEventTimestamps.delete(e);let t=`${e}:`;for(let r of this.lastWaitingEventTimestamps.keys())r.startsWith(t)&&this.lastWaitingEventTimestamps.delete(r)}originThreadLine(e){return Ye(e)}extractLastOutputLine(e){return e.getOutput(3).filter(o=>o.trim()).pop()?.trim()||void 0}getOutputPreview(e,t=1e3){return Xa(e,t)}resolvePlanApprovalMode(e){return e.planApproval??_.planApproval??"delegate"}shouldEmitTurnCompleteWake(e){let t=`${e.startedAt??0}|${e.result?.session_id??""}|${e.result?.num_turns??0}`;return this.lastTurnCompleteMarkers.get(e.id)===t?(`${e.id}${t}`,!1):(this.lastTurnCompleteMarkers.set(e.id,t),!0)}shouldEmitTerminalWake(e){let t=`${e.status}|${e.startedAt??0}|${e.result?.session_id??""}|${e.result?.num_turns??0}|${e.killReason}`;return this.lastTerminalWakeMarkers.get(e.id)===t?!1:(this.lastTerminalWakeMarkers.set(e.id,t),!0)}resolve(e){return this.references.resolveActive(e)}get(e){return this.registry.get(e)}list(e){let t=this.registry.list();return e&&e!=="all"&&(t=t.filter(r=>r.status===e)),t.sort((r,o)=>o.startedAt-r.startedAt)}kill(e,t){let r=this.registry.get(e);if(!r)return!1;if(r.pendingPlanApproval){this.clearPlanDecisionTokens(r.id);let o={lifecycle:"terminal",runtimeState:"stopped",pendingPlanApproval:!1,planApprovalContext:void 0,approvalState:r.approvalState==="pending"?"rejected":r.approvalState,planDecisionVersion:(r.planDecisionVersion??0)+1,actionablePlanDecisionVersion:void 0,canonicalPlanPromptVersion:void 0,approvalPromptRequiredVersion:void 0,approvalPromptVersion:void 0,approvalPromptStatus:"not_sent",approvalPromptTransport:"none",approvalPromptMessageKind:"none",approvalPromptLastAttemptAt:void 0,approvalPromptDeliveredAt:void 0,approvalPromptFailedAt:void 0};r.applyControlPatch(o),Object.assign(r,o),this.updatePersistedSession(r.id,o)}return r.kill(t??"user"),!0}killAll(e="user"){for(let t of this.sessions.values())uf.has(t.status)&&this.kill(t.id,e)}resolveBackendConversationId(e){return this.references.resolveBackendConversationId(e)}resolveHarnessSessionId(e){return this.resolveBackendConversationId(e)}getPersistedSession(e){return this.references.getPersistedSession(e)}isAlreadyMerged(e){if(!e)return!1;let t=this.store.getPersistedSession(e);return t?.worktreeMerged===!0||t?.worktreeLifecycle?.state==="merged"||t?.worktreeLifecycle?.state==="released"}async enqueueMerge(e,t,r){return this.mergeQueue.enqueue(e,t,r)}updatePersistedSession(e,t){let r=this.stateSync.applySessionPatch(e,t);return r&&this.onPersistedSessionChanged(this.store.getPersistedSession(e)),r}listPersistedSessions(){return this.store.listPersistedSessions()}async handleAskUserQuestion(e,t){let r=this.sessions.get(e);if(!r)throw new Error(`Session "${e}" not found for AskUserQuestion intercept`);return this.questions.handleAskUserQuestion(r,t)}resolveAskUserQuestion(e,t,r={}){return this.questions.resolveAskUserQuestion(e,t,r)}async resolvePendingInputOption(e,t,r={}){let o=this.sessions.get(e);return o?.canSubmitPendingInputOption?.()?await o.submitPendingInputOption(t,r)?(this.clearWaitingTimestampsForSession(e),!0):!1:this.questions.resolveAskUserQuestion(e,t,r)}canSubmitPendingInputOption(e){return this.sessions.get(e)?.canSubmitPendingInputOption?.()===!0}pendingInputSubmissionRequiresMore(e){return this.sessions.get(e)?.pendingInputSubmissionRequiresMore()===!0}consumeQuestionAnswerTokens(e,t,r){return this.interactions.consumeQuestionAnswerTokens(e,t,r)}consumePlanDecisionTokens(e,t){return this.interactions.consumePlanDecisionTokens(e,t)}dispose(){this.disposeMaintenance(),this.questions.dispose(),this.notifications.dispose()}};import{definePluginEntry as ol}from"openclaw/plugin-sdk/plugin-entry";function Sf(n){let e=parseInt(process.env.OPENCLAW_WORKTREE_CLEANUP_AGE_HOURS??"168",10)||168,t=e*60*60*1e3,r=Date.now()-t,o=new Set(n.listPersistedSessions().map(l=>l.worktreePath).filter(l=>typeof l=="string"&&l.length>0)),i=new Set,s=process.env.OPENCLAW_WORKTREE_DIR??_.worktreeDir;if(s)i.add(s);else for(let l of n.listPersistedSessions())if(l.workdir)try{let d=yf("git",["rev-parse","--show-toplevel"],{cwd:l.workdir,timeout:5e3,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim();d&&i.add(Wo(d,".worktrees"))}catch{}if(i.size===0)return;let a=0;for(let l of i)try{let d=ff(l);for(let u of d){if(!u.startsWith("openclaw-worktree-"))continue;let f=Wo(l,u);try{let g=gf(f);if(!g.isDirectory()||g.mtimeMs>r||o.has(f))continue;hf(f,{recursive:!0,force:!0}),a++}catch(g){`${f}${g instanceof Error?g.message:String(g)}`}}}catch{}a>0&&`${a}${e}`}function kf(n){if(!n||typeof n!="object")return;let e=n,t=e.channel?.trim().toLowerCase();if(!t)return;let r=t==="telegram"?e.callback?.chatId??e.parentConversationId??e.conversationId:e.parentConversationId??e.conversationId??e.callback?.chatId;if(r)return ue(e.accountId?`${t}|${e.accountId}|${r}`:`${t}|${r}`,e.threadId,e.sessionKey)}function vf(n){let e=null,t=null,r=null,o=!1,i=!1,s=n.registerTool;Te(n.runtime);let a=()=>Wo(zn(process.env),"plugin-state","openclaw-code-agent"),l=p=>{let y=p.deliveryContext;return y?.channel&&y.to?ue(y.accountId?`${y.channel}|${y.accountId}|${y.to}`:`${y.channel}|${y.to}`,y.threadId,p.sessionKey):ue(p.messageChannel,void 0,p.sessionKey)},d=p=>{r?.maybeCheckForUpdate({route:p})},u=p=>{if(o){p&&!i&&(Te(n.runtime,p.config),i=!0);return}let y=n.pluginConfig??{};Ko(y),p?(Te(n.runtime,p.config),i=!0):(Te(n.runtime),i=!1),e=new kr(_.maxSessions,_.maxPersistedSessions,{worktreeSummaryProvider:fa()}),t=new En(e),r=new Gt({stateDir:p?.stateDir??a(),currentVersion:n.version??ti.version??"0.0.0",actionButtonFactory:(P,b,A,I)=>e.makePluginActionButton(P,b,A,I)}),Pr(e),wr(t),br(r),t.start(),Sf(e),e.bootstrapMaintenanceSchedules(),o=!0,d()},f=()=>{t&&t.stop(),e&&e.killAll("shutdown"),e&&e.dispose(),t=null,e=null,r=null,o=!1,i=!1,Te(void 0),wr(null),Pr(null),br(null)},g=(p,y)=>{s(P=>(u(),d(l(P)),p(P)),y)},k={...n,registerCommand(p){n.registerCommand({...p,handler:y=>(u(),d(l(y)),p.handler(y))})}},h=p=>{let y=bs(p);n.registerInteractiveHandler({...y,handler:async P=>(u(),d(kf(P)),y.handler(P))})};g(p=>Mi(p),{optional:!1,name:"agent_launch"}),g(p=>Gi(p),{optional:!1,name:"agent_sessions"}),g(p=>ji(p),{optional:!1,name:"agent_kill"}),g(p=>hn(p),{optional:!1,name:"agent_output"}),g(p=>Xi(p),{optional:!1,name:"agent_respond"}),g(p=>Zi(p),{optional:!1,name:"agent_request_plan_approval"}),g(p=>es(p),{optional:!1,name:"agent_request_worktree_decision"}),g(p=>rs(p),{optional:!1,name:"agent_send_plan_offer"}),g(p=>os(p),{optional:!1,name:"agent_stats"}),g(p=>ds(p),{optional:!1,name:"agent_repo_policy"}),g(p=>vn(p),{optional:!1,name:"agent_merge"}),g(p=>Kt(p),{optional:!1,name:"agent_pr"}),g(p=>us(p),{optional:!1,name:"agent_worktree_cleanup"}),g(p=>ps(p),{optional:!1,name:"agent_worktree_status"}),g(p=>cs(p),{optional:!1,name:"agent_goal_launch"}),g(p=>fs(p),{optional:!1,name:"agent_goal_status"}),g(p=>gs(p),{optional:!1,name:"agent_goal_stop"}),g(p=>hs(p),{optional:!1,name:"agent_goal_edit"}),h("telegram"),h("discord"),As(k),Is(k),Ts(k),xs(k),Cs(k),Ms(k),_s(k),$s(k),Es(k),Ns(k),Ws(k),n.registerService({id:"openclaw-code-agent",start:u,stop:f})}var ub=ol({id:"openclaw-code-agent",name:"Code Agent",description:"Multi-session coding-agent orchestration from OpenClaw chat",register:vf});export{ub as default,vf as register,kf as routeFromInteractiveContext};