@leviyuan/lodestar 0.17.2 → 0.17.3
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/README.md +29 -29
- package/dist/lodestar-setup.js +13 -10
- package/dist/lodestar-update.js +10 -7
- package/dist/lodestar-version.js +1 -1
- package/dist/lodestar.js +168 -165
- package/docs/AGENTS.md +7 -4
- package/docs/claude-agent-backend.md +29 -43
- package/docs/configuration.md +29 -5
- package/docs/models.md +38 -30
- package/docs/usage.md +29 -31
- package/package.json +1 -1
- package/scripts/postinstall.cjs +2 -1
- package/docs/dsh-testing-report.md +0 -189
package/dist/lodestar.js
CHANGED
|
@@ -1,46 +1,49 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`),Y=parseInt((J[0]??"").trim(),10),Q=(J[1]??"").trim();if(!Number.isFinite(Y)||Y<=0)return{state:"continue"};if(!Q)try{return process.kill(Y,0),{state:"exit",pid:Y}}catch{return{state:"continue"}}if(
|
|
4
|
-
${
|
|
5
|
-
`)}var
|
|
6
|
-
${H}`));else
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
`))}
|
|
10
|
-
|
|
2
|
+
var bV=Object.defineProperty;var yV=($)=>$;function wV($,Z){this[$]=yV.bind(null,Z)}var n$=($,Z)=>{for(var J in Z)bV($,J,{get:Z[J],enumerable:!0,configurable:!0,set:wV.bind(Z,J)})};var S=($,Z)=>()=>($&&(Z=$($=0)),Z);import{homedir as fV}from"node:os";import{join as i}from"node:path";function LZ($,Z,J){if($)return $;if(Z)return i(Z,"lodestar");return J}function vV(){if(BZ)return i(process.env.APPDATA??i(y4,"AppData","Roaming"),"Lodestar");return i(y4,".config","lodestar")}function hV(){if(BZ)return i(process.env.LOCALAPPDATA??i(y4,"AppData","Local"),"Lodestar");return i(y4,".local","share","lodestar")}var y4,BZ,d6,o,M0,v0,x1,n6,a6,o6,r6,t6,w4,a$,f4,o$,k1,s6,qZ,DZ,e6,$7,r$,v4;var Y0=S(()=>{y4=fV(),BZ=process.platform==="win32";d6=LZ(process.env.LODESTAR_CONFIG_DIR,process.env.XDG_CONFIG_HOME,vV()),o=LZ(process.env.LODESTAR_DATA_DIR,process.env.XDG_DATA_HOME,hV()),M0=process.env.LODESTAR_CONFIG??i(d6,"config.toml"),v0=i(o,"daemon.pid"),x1=i(o,"daemon.log"),n6=i(o,"session-chat-map.json"),a6=i(o,"session-resume-map.json"),o6=i(o,"session-turns-map.json"),r6=i(o,"session-model-map.json"),t6=i(o,"temp-session-leases.json"),w4=i(o,"tasklist-map.json"),a$=i(o,"agent-runs"),f4=i(o,"agent-session-ids.json"),o$=i(o,"managed-claude-plugin"),k1=i(o,"dsh"),s6=i(o,"agent-runtimes"),qZ=i(o,"context-window-cache.json"),DZ=i(o,"notify-callbacks.json"),e6=i(o,"alive-on-shutdown.json"),$7=i(o,"inbox"),r$=i(o,"debug.sock"),v4=i(o,"debug-context.json")});import{execSync as PZ}from"node:child_process";import{readFileSync as jZ,writeFileSync as IV}from"node:fs";function gV(){return process.argv[1]??`pid:${process.pid}`}function cV($){try{if(process.platform==="linux")return jZ(`/proc/${$}/cmdline`,"utf8").replace(/\0/g," ").trim();if(process.platform==="darwin")return PZ(`ps -p ${$} -o args=`,{encoding:"utf8",timeout:2000}).trim();if(process.platform==="win32")return PZ(`powershell -NoProfile -Command "(Get-CimInstance Win32_Process -Filter 'ProcessId=${$}').CommandLine"`,{encoding:"utf8",timeout:5000}).trim()||null;return null}catch{return null}}function mV($,Z){if(!Number.isFinite($)||$<=0||!Z)return!1;let J=cV($);if(!J)return!1;if(process.platform==="win32")return J.toLowerCase().includes(Z.toLowerCase());return J.includes(Z)}function h4($){let Z="";try{Z=jZ($,"utf8")}catch{return{state:"continue"}}let J=Z.split(`
|
|
3
|
+
`),Y=parseInt((J[0]??"").trim(),10),Q=(J[1]??"").trim();if(!Number.isFinite(Y)||Y<=0)return{state:"continue"};if(!Q)try{return process.kill(Y,0),{state:"exit",pid:Y}}catch{return{state:"continue"}}if(mV(Y,Q))return{state:"exit",pid:Y};return{state:"continue"}}function FZ($){IV($,`${process.pid}
|
|
4
|
+
${gV()}`)}var Z7=()=>{};import{chmodSync as uV,closeSync as J7,fsyncSync as MZ,mkdirSync as pV,openSync as RZ,renameSync as lV,unlinkSync as iV,writeFileSync as dV}from"node:fs";import{randomUUID as nV}from"node:crypto";import{dirname as UZ}from"node:path";function tV($){let Z=UZ($);pV(Z,{recursive:!0,mode:rV})}function OZ($,Z,J){tV($);let Y=`${$}.${process.pid}.${nV()}.tmp`,Q=null;try{Q=RZ(Y,"wx",J),dV(Q,Z),MZ(Q),J7(Q),Q=null,lV(Y,$);try{uV($,J)}catch{}if(process.platform!=="win32"){let H=null;try{H=RZ(UZ($),"r"),MZ(H)}catch{}finally{if(H!==null)try{J7(H)}catch{}}}}catch(H){if(Q!==null)try{J7(Q)}catch{}try{iV(Y)}catch{}throw H}}function d0($,Z){OZ($,Z,aV)}function TZ($,Z){OZ($,Z,oV)}function A0($,Z){d0($,JSON.stringify(Z,null,2)+`
|
|
5
|
+
`)}var aV=384,oV=448,rV=448;var n0=()=>{};import{execFile as sV}from"node:child_process";import{spawn as eV}from"cross-spawn";function Zz($){if(!Number.isSafeInteger($)||$<=0)return Promise.reject(Error(`Invalid npm installer PID: ${$}`));return new Promise((Z,J)=>{sV("taskkill",["/PID",String($),"/T","/F"],{windowsHide:!0,timeout:1e4},(Y,Q,H)=>{if(Y)J(Error(`taskkill npm installer PID ${$} failed: ${Y.message}
|
|
6
|
+
${Q}${H}`));else Z()})})}async function Y7($,Z,J={}){Z?.throwIfAborted();let Y=J.platform??process.platform,Q=J.timeoutMs??300000,H=J.terminationTimeoutMs??1e4;return await new Promise((W,X)=>{let V=(J.spawn??eV)("npm",["install","--prefix",$,"--include=optional","--no-fund","--no-audit",`--registry=${$z}`],{cwd:$,stdio:["ignore","pipe","pipe"],shell:!1,windowsHide:!0}),z="",G,A,K=!1,L=!1,D,q=(k)=>{z=(z+k.toString()).slice(-16384)};V.stdout.on("data",q),V.stderr.on("data",q);let P=(k)=>{if(K)return;if(K=!0,clearTimeout(j),D)clearTimeout(D);if(Z?.removeEventListener("abort",M),k)X(k);else W()},x=(k)=>new I4(`${G?.message??"Agent runtime install failed"}; npm installer PID ${V.pid??"MISS"} termination unconfirmed: ${k}; partial directory retained: ${$}
|
|
7
|
+
${z}`),F=(k)=>{if(K||L||A)return;G??=Error(k),D=setTimeout(()=>P(x(`stdio did not close within ${H}ms`)),H),A=Promise.resolve().then(async()=>{if(L)throw Error("installer closed before process-tree termination started");if(!V.pid)throw Error("installer PID unavailable");if(Y==="win32")await(J.terminateWindows??Zz)(V.pid);else if(!V.kill("SIGTERM"))throw Error("npm installer rejected SIGTERM")}),A.catch((C)=>P(x(C instanceof Error?C.message:String(C))))},M=()=>F("Agent runtime install aborted"),j=setTimeout(()=>F(`Agent runtime install timed out after ${Q}ms`),Q);if(Z?.addEventListener("abort",M,{once:!0}),V.on("error",(k)=>{if(G??=k,!V.pid)P(Error(`${k.message}
|
|
8
|
+
${z}`))}),V.once("close",async(k,C)=>{L=!0,clearTimeout(j),Z?.removeEventListener("abort",M);try{await A}catch(c){P(x(c instanceof Error?c.message:String(c)));return}if(G||k!==0)P(Error(`${G?.message??`npm install exited code=${k} signal=${C}`}
|
|
9
|
+
${z}`));else P()}),Z?.aborted)M()})}var $z="https://registry.npmjs.org",I4;var Q7=S(()=>{I4=class I4 extends Error{}});import{createHash as Jz,randomUUID as Yz}from"node:crypto";import{createRequire as Qz}from"node:module";import{existsSync as H7,readFileSync as NZ}from"node:fs";import{mkdir as SZ,mkdtemp as Hz,readFile as xZ,rename as kZ,rm as g4,writeFile as W7}from"node:fs/promises";import{join as S0,isAbsolute as Wz}from"node:path";import{fileURLToPath as Xz,pathToFileURL as Vz}from"node:url";function CZ($,Z=s6){let J=S0(Z,$,"current.json");if(!H7(J))return null;let Y=JSON.parse(NZ(J,"utf8"));if(!Number.isFinite(Y.checkedAt)||Y.directory!==void 0&&!Wz(Y.directory))throw Error(`Invalid ${$} runtime state: ${J}`);return Y}function c4($){let Z=CZ($);if(Z?.error)throw Error(`${$} 更新失败: ${Z.error}`);if(!Z?.directory)throw Error(`${$} runtime 未安装,请运行 lodestar-update --agents-only`);return Z.directory}function X7($,Z){return Qz(S0(c4($),"package.json")).resolve(Z)}function U2($,Z){let J=S0(c4($),"node_modules",".bin",`${Z}${process.platform==="win32"?".cmd":""}`);if(!H7(J))throw Error(`${$} executable missing: ${J}`);return J}async function bZ(){return import(Vz(X7("claude","@anthropic-ai/claude-agent-sdk")).href)}async function Az($,Z,J){let Y=new AbortController,Q=()=>Y.abort(J?.reason);if(J?.addEventListener("abort",Q,{once:!0}),J?.aborted)Q();let H=setTimeout(()=>Y.abort(Error("npm registry request timed out")),30000);try{let W=await fetch(`${_z}/${encodeURIComponent($)}/${encodeURIComponent(Z)}`,{signal:Y.signal});if(!W.ok)throw Error(`${$}@${Z}: npm HTTP ${W.status}`);let X=await W.json();if(X.name!==$||typeof X.version!=="string"||!X.version)throw Error(`Invalid npm manifest: ${$}@${Z}`);return X}finally{clearTimeout(H),J?.removeEventListener("abort",Q)}}async function Kz($,Z){let J={};if($!=="dsh"){let W=await Promise.all(R2[$].map((X)=>Z(X,"latest")));for(let X of W)J[X.name]=X.version;return J}let Y=await Z("@deepseek-ai/dsh","latest"),Q=new Set(R2.dsh),H=new Set;while(Q.size){let W=[...Q].slice(0,12);for(let V of W)Q.delete(V),H.add(V);let X=await Promise.all(W.map((V)=>V===Y.name?Y:Z(V,Y.version)));for(let V of X){if(V.version!==Y.version)throw Error(`DSH release package mismatch: ${V.name}@${V.version}, expected ${Y.version}`);J[V.name]=V.version;for(let z of Object.keys({...V.dependencies,...V.peerDependencies,...V.optionalDependencies}))if(z.startsWith("@deepseek-ai/dsh")&&!H.has(z))Q.add(z)}}return J}async function C1($,Z=process.platform){for(let J=0;;J++)try{return await $()}catch(Y){let Q=Y.code;if(Z!=="win32"||!["EPERM","EACCES","EBUSY","ENOTEMPTY"].includes(Q??"")||J>=5)throw Y;await new Promise((H)=>setTimeout(H,100*(J+1)))}}async function EZ($,Z){let J=S0($,`current-${Yz()}.json`),Y;try{await W7(J,JSON.stringify(Z)+`
|
|
10
|
+
`,{mode:384}),await C1(()=>kZ(J,S0($,"current.json")))}catch(Q){throw Y=Q,Q}finally{try{await C1(()=>g4(J,{force:!0}))}catch(Q){if(Y)throw AggregateError([Y,Q],`${t$(Y)}; state temporary file cleanup failed: ${t$(Q)}`);throw Q}}}async function Bz($,Z){let J=S0($,"update.lock"),Y=Date.now()+360000;for(;;){Z?.throwIfAborted();try{return await SZ(J),await W7(S0(J,"pid"),String(process.pid)),()=>C1(()=>g4(J,{recursive:!0}))}catch(Q){if(Q.code!=="EEXIST")throw Q;try{let H=Number(await xZ(S0(J,"pid"),"utf8"));if(!Number.isSafeInteger(H)||H<=0)throw Error(`Invalid runtime update lock: ${J}`);try{process.kill(H,0)}catch(W){if(W.code!=="ESRCH")throw W;await C1(()=>g4(J,{recursive:!0}));continue}}catch(H){if(H.code!=="ENOENT")throw H}if(Date.now()>=Y)throw Error(`Timed out waiting for runtime update lock: ${J}`);await new Promise((H)=>setTimeout(H,200))}}}async function m4($,Z={}){let J=Z.root??s6,Y=S0(J,$);await SZ(Y,{recursive:!0,mode:448});let Q=await Bz(Y,Z.signal),H,W,X=!1;try{Z.report?.(`${$}: 检查 upstream latest`);let V=CZ($,J),z=await Kz($,Z.metadata??((D,q)=>Az(D,q,Z.signal)));Z.signal?.throwIfAborted();let G=JSON.parse(NZ(Xz(new URL("../package.json",import.meta.url)),"utf8")).overrides??{},A=Jz("sha256").update(JSON.stringify({installFormat:2,versions:Object.entries(z).sort(),security:G,platform:process.platform,arch:process.arch})).digest("hex").slice(0,20),K=S0(Y,A);if(!H7(K)){H=await Hz(S0(Y,".install-")),await W7(S0(H,"package.json"),JSON.stringify({name:`lodestar-runtime-${$}`,version:z[R2[$][0]],private:!0,type:"module",dependencies:z,overrides:{...G,...$==="dsh"?z:{}}})+`
|
|
11
|
+
`,{mode:384}),await(Z.install??Y7)(H,Z.signal);for(let[q,P]of Object.entries(z)){let x=JSON.parse(await xZ(S0(H,"node_modules",q,"package.json"),"utf8"));if(x.version!==P)throw Error(`npm installed ${q}@${x.version}, expected ${P}`)}Z.signal?.throwIfAborted();let D=H;await C1(()=>kZ(D,K)),H=void 0}let L={directory:K,versions:z,checkedAt:Date.now()};return await EZ(Y,L),Z.report?.(`${$}: ${R2[$][0]}@${z[R2[$][0]]}${V?.directory===K?" 已是 latest":" 已更新,新进程使用新版"}`),L}catch(V){W=V,X=V instanceof I4;try{await EZ(Y,{checkedAt:Date.now(),error:t$(V)})}catch(z){throw W=AggregateError([V,z],`${t$(V)}; recording update failure also failed: ${t$(z)}`),W}throw V}finally{let V=[];if(H&&!X){let z=H;try{await C1(()=>g4(z,{recursive:!0}))}catch(G){V.push(G)}}try{await Q()}catch(z){V.push(z)}if(V.length){let z=W?[W,...V]:V;throw AggregateError(z,z.map(t$).join("; "))}}}function yZ($,Z={}){let J=zz.filter((Y)=>Z.enabled?.[Y]===!0).map((Y)=>{let Q=new AbortController,H,W=setInterval(()=>{if(H)return;H=(Z.update??m4)(Y,{report:$,signal:Q.signal}).catch((X)=>$(`${Y} 自动更新未完成: ${t$(X)}`)).finally(()=>{H=void 0})},Gz);return W.unref(),()=>{clearInterval(W),Q.abort()}});return()=>{for(let Y of J)Y()}}var zz,Gz=21600000,_z="https://registry.npmjs.org",R2,t$=($)=>$ instanceof Error?$.message:String($);var b1=S(()=>{Y0();Q7();Q7();zz=["codex","claude","dsh"],R2={codex:["@openai/codex"],claude:["@anthropic-ai/claude-code","@anthropic-ai/claude-agent-sdk","@anthropic-ai/sdk"],dsh:["@deepseek-ai/dsh","@deepseek-ai/dsh-llm-pi-ai","@deepseek-ai/dsh-tool-ask-user"]}});var vZ={};n$(vZ,{runSetup:()=>kz});import{execFileSync as Lz,spawn as p4}from"node:child_process";import{spawn as qz}from"cross-spawn";import{existsSync as z7,mkdirSync as fZ,readFileSync as Dz}from"node:fs";import{createInterface as Pz}from"node:readline/promises";import{dirname as jz,join as G7}from"node:path";import{homedir as Fz}from"node:os";import{fileURLToPath as Mz}from"node:url";async function s$($,Z={}){while(!0){let J=Z.default?`${B.dim} [${Z.default}]${B.reset}`:"",Y=(await O2.question(`${B.cyan}? ${B.reset}${$}${J}
|
|
12
|
+
${B.green}>${B.reset} `)).trim();if(!Y&&Z.default!==void 0)return Z.default;if(!Y&&Z.required){console.log(`${B.red}必填,请重新输入${B.reset}`);continue}return Y}}function Rz($){let Z="═".repeat(58);console.log(`
|
|
11
13
|
${B.bold}${B.cyan}╔${Z}╗${B.reset}`),console.log(`${B.bold}${B.cyan}║ ${$.padEnd(54)} ║${B.reset}`),console.log(`${B.bold}${B.cyan}╚${Z}╝${B.reset}
|
|
12
|
-
`)}function
|
|
14
|
+
`)}function u4($,Z,J){console.log(`
|
|
13
15
|
${B.bold}${B.yellow}[${$}/${Z}] ${J}${B.reset}
|
|
14
|
-
`)}function
|
|
15
|
-
`),{path:J}}catch(Z){return{error:Z?.message??String(Z)}}}function
|
|
16
|
+
`)}function V7($){return $.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}function wZ($){try{let Z=Lz($,["login","status"],{timeout:1e4,shell:process.platform==="win32"}).toString();return/Logged in using ChatGPT/i.test(Z)}catch{return!1}}async function Uz($){return new Promise((Z)=>{let J=qz($,["login"],{stdio:"inherit",shell:!1});J.on("exit",(Y)=>Z(Y===0)),J.on("error",()=>Z(!1))})}function Oz(){return process.env.CLAUDE_CONFIG_DIR||G7(Fz(),".claude")}async function Tz($){try{let Z=await fetch("https://open.bigmodel.cn/api/anthropic/v1/models",{headers:{Authorization:`Bearer ${$}`},signal:AbortSignal.timeout(1e4)});if(!Z.ok)return null;let J=await Z.json(),Y=(Array.isArray(J?.data)?J.data:[]).map((A)=>typeof A?.display_name==="string"&&A.display_name?A.display_name:String(A?.id??"")).filter(Boolean);if(!Y.length)return null;let Q=(A)=>{let K=A.match(/(\d+(?:\.\d+)?)/);return K?Number(K[1]):-1},H=(A)=>A.replace(/-Turbo|-Air$/i,""),X=[...Y.filter((A)=>!/-Turbo|-Air/i.test(A))].sort((A,K)=>Q(K)-Q(A)),V=X[0],z=X[X.length-1],G={};if(V)G.ANTHROPIC_DEFAULT_OPUS_MODEL=`${V}[1m]`,G.ANTHROPIC_DEFAULT_SONNET_MODEL=`${V}[1m]`;if(z&&H(z)!==H(V))G.ANTHROPIC_DEFAULT_HAIKU_MODEL=z;return Object.keys(G).length?G:null}catch{return null}}async function Ez($){try{let Z=Oz();fZ(Z,{recursive:!0});let J=G7(Z,"settings.json"),Y={};if(z7(J)){let X=Dz(J,"utf8");try{let V=JSON.parse(X);if(!V||typeof V!=="object"||Array.isArray(V))return{error:`${J} 内容不是 JSON 对象, 拒绝覆盖, 请手动检查`};Y=V}catch{return{error:`${J} 解析失败 (JSON 语法错), 拒绝覆盖, 请手动修复后重跑`}}}let Q=Y.env&&typeof Y.env==="object"&&!Array.isArray(Y.env)?Y.env:{},H={ANTHROPIC_AUTH_TOKEN:$,ANTHROPIC_BASE_URL:"https://open.bigmodel.cn/api/anthropic",API_TIMEOUT_MS:"3000000",CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:"1"},W=await Tz($);if(W)Object.assign(H,W);return Y.env={...Q,...H},d0(J,JSON.stringify(Y,null,2)+`
|
|
17
|
+
`),{path:J}}catch(Z){return{error:Z?.message??String(Z)}}}function Nz($){try{if(process.platform==="win32")p4(process.env.ComSpec??"cmd.exe",["/c","start",'""',$],{detached:!0,stdio:"ignore",windowsHide:!0}).unref();else if(process.platform==="darwin")p4("open",[$],{detached:!0,stdio:"ignore"}).unref();else p4("xdg-open",[$],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function Sz($,Z){try{let Y=await(await fetch("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({app_id:$,app_secret:Z}),signal:AbortSignal.timeout(15000)})).json();if(Y.tenant_access_token)return{ok:!0};return{ok:!1,error:`飞书拒绝: code=${Y.code} msg=${Y.msg??"(no msg)"}`}}catch(J){return{ok:!1,error:`网络错误: ${J?.message??String(J)}`}}}function xz(){try{let $=jz(Mz(import.meta.url)),Z=G7($,"lodestar.js");if(!z7(Z))return{error:`找不到 daemon bundle: ${Z}`};let J=p4(process.execPath,[Z],{detached:!0,stdio:"ignore",windowsHide:!0});return J.unref(),{pid:J.pid}}catch($){return{error:$?.message??String($)}}}async function kz(){if(!process.stdin.isTTY)console.error(`${B.red}lodestar-setup: stdin 不是 TTY,无法交互式输入。${B.reset}`),console.error("请直接在 cmd / PowerShell / Terminal 里跑,不要 pipe 或重定向 stdin。"),process.exit(1);if(z7(M0)){if(console.log(`${B.yellow}发现已有配置: ${M0}${B.reset}`),(await s$("覆盖? (y/N)",{default:"n"})).toLowerCase()!=="y"){console.log("已取消"),O2.close();return}}Rz("Lodestar 安装向导"),console.log("Lodestar 把 Feishu (飞书) 群聊接到 AI agent。"),console.log("默认后端是 Claude Code; Codex 是可选第二后端, 群里发 model 一键切换。"),console.log("每个群对应一个项目目录, agent 在那里跑、能读写文件。"),console.log(),console.log(`${B.yellow}⚠ Claude 官方限制:${B.reset}`),console.log(` ${B.bold}Claude 订阅 (Pro/Max OAuth 登录) 不支持本项目${B.reset},`),console.log(" 必须走 API 方式 —— 推荐 GLM Coding Plan, 或自备 Anthropic API key。"),console.log(),console.log("本向导依次做 4 件事:"),console.log(` ${B.dim}1) 确保 Claude Code CLI 已装好${B.reset}`),console.log(` ${B.dim}2) GLM Coding Plan API key (推荐, 可选) + Codex (可选)${B.reset}`),console.log(` ${B.dim}3) Feishu 自建应用 (含权限 / 事件 / 发版 + 凭据测试)${B.reset}`),console.log(` ${B.dim}4) 工作目录, 自动启动 daemon${B.reset}`),console.log(),await O2.question(`${B.dim}按 Enter 开始 (Ctrl+C 退出)...${B.reset}`),u4(1,4,"准备 Claude Code CLI"),await m4("claude",{report:(A)=>console.log(A)}),console.log(`${B.green}✓ Claude Code / SDK 已更新${B.reset}: ${B.dim}${U2("claude","claude")}${B.reset}`),console.log(),console.log(`${B.dim}下一步可选配 GLM Coding Plan 自动写入路由; 不配则用本机 Claude Code 现有配置。${B.reset}`),console.log(`${B.dim}记住: 别用 \`claude\` 走订阅 OAuth 登录 —— 订阅不支持本项目, 要用 API key。${B.reset}`),u4(2,4,"GLM Coding Plan (推荐, 可选)"),console.log("GLM Coding Plan 给 Claude Code 接 GLM 系列模型 (支持 1M token 上下文, 中文友好)。"),console.log("订阅后在智谱开放平台拿一个 API key, 粘到下面 —— 向导自动写进 ~/.claude/settings.json。"),console.log(` ${B.dim}拿 key: https://open.bigmodel.cn → 控制台 → API Keys${B.reset}`),console.log(` ${B.dim}不给也行: 以本机 Claude Code 现有配置启动 (确保是 API key 方式, 非订阅)。${B.reset}`),console.log();let $=await s$("GLM API key (直接回车跳过)",{});if($){let A=await Ez($);if("path"in A)console.log(`${B.green}✓ GLM 路由已写入${B.reset}: ${B.dim}${A.path}${B.reset}`),console.log(`${B.dim}模型 slots 按端点当前列表自动选取(最新一代 opus/sonnet, 1M ctx)${B.reset}`);else console.log(`${B.red}✗ 写入失败:${B.reset} ${A.error}`),console.log(`${B.dim}跳过 GLM 配置, 以本机 Claude Code 现有配置启动。${B.reset}`)}else console.log(`${B.dim}已跳过 GLM, 以本机 Claude Code 现有配置启动。${B.reset}`);if(console.log(),console.log(`${B.bold}Codex (可选第二后端)${B.reset}`),console.log(` ${B.dim}想用 Codex 的话, 登录 ChatGPT 订阅即可, 模型/effort 走 ~/.codex/config.toml, 群里发 model 切换。${B.reset}`),(await s$("现在顺便配置 Codex 后端吗?",{default:"n"})).toLowerCase()==="y"){await m4("codex",{report:(K)=>console.log(K)});let A=U2("codex","codex");if(wZ(A))console.log(`${B.green}✓ Codex 已登录 ChatGPT${B.reset}`);else if(console.log(`${B.dim}启动 \`codex login\`...${B.reset}`),await Uz(A)&&wZ(A))console.log(`${B.green}✓ Codex 已登录 ChatGPT${B.reset}`);else console.log(`${B.yellow}Codex 登录未完成 — 不影响默认 Claude 后端; 需要时随时跑 codex login。${B.reset}`)}else console.log(`${B.dim}已跳过 Codex (需要时随时跑 codex login, 群里发 model 切)。${B.reset}`);u4(3,4,"Feishu 自建应用");let J="https://open.feishu.cn/app";console.log("打开飞书开放平台 (浏览器):"),console.log(` ${B.cyan}${J}${B.reset}`),Nz(J),console.log(`${B.dim}(如果浏览器没自动开, 复制上面 URL 粘到浏览器)${B.reset}`),console.log(),console.log(`${B.bold}详细操作步骤:${B.reset}`),console.log(),console.log(` ${B.bold}① 创建应用${B.reset}`),console.log(` 点 "创建企业自建应用", 填名字 (如 ${B.dim}Lodestar${B.reset}), logo 随意。`),console.log(),console.log(` ${B.bold}② 添加机器人能力${B.reset}`),console.log(` 左侧菜单 "${B.cyan}添加应用能力${B.reset}" → 找到 "机器人" → 点 "${B.bold}添加${B.reset}" 按钮。`),console.log(),console.log(` ${B.bold}③ 申请权限 (左侧 "${B.cyan}权限管理${B.reset}" → "${B.bold}开通权限${B.reset}")${B.reset}`),console.log(` ${B.yellow}缺一个都会让 daemon 启动后默默丢消息, 一定要全开。${B.reset}`),console.log(` ${B.dim}消息类:${B.reset}`),console.log(` • ${B.bold}im:message:send_as_bot${B.reset} ${B.dim}# 以机器人身份发消息${B.reset}`),console.log(` • ${B.bold}im:message${B.reset} ${B.dim}# 接收/操作消息 (核心)${B.reset}`),console.log(` • ${B.bold}im:chat${B.reset} ${B.dim}# 读/写群信息 (匹配群名 ↔ 项目目录)${B.reset}`),console.log(` • ${B.bold}im:chat:create${B.reset} ${B.dim}# wt: 自动创建 worktree 群${B.reset}`),console.log(` • ${B.bold}im:chat:delete${B.reset} ${B.dim}# wt: 解散 worktree 群${B.reset}`),console.log(` • ${B.bold}im:chat.members:read${B.reset} ${B.dim}# wt: 判断发起人是否已在群内${B.reset}`),console.log(` • ${B.bold}im:chat.members:write_only${B.reset} ${B.dim}# wt: 把发起人拉进已有 worktree 群${B.reset}`),console.log(` • ${B.bold}im:resource${B.reset} ${B.dim}# 上传/下载附件 (图文双向)${B.reset}`),console.log(` • ${B.bold}im:message.urgent${B.reset} ${B.dim}# 加急推送 (锁屏通知 / Ask)${B.reset}`),console.log(` • ${B.bold}im:message.group_msg${B.reset} ${B.dim}# 敏感: 接收群里所有消息${B.reset}`),console.log(` ${B.dim}└ 关键: 没它机器人只收 @ 自己的消息, 拿不到群里其他对话, 一定要开${B.reset}`),console.log(` ${B.dim}└ 敏感权限要走审批: 申请时填用途, 个人开发者通常秒过${B.reset}`),console.log(` • ${B.bold}im:message.group_at_msg:readonly${B.reset} ${B.dim}# 读 @ 机器人消息 (兜底)${B.reset}`),console.log(` ${B.dim}卡片类 (Card Kit):${B.reset}`),console.log(` • ${B.bold}cardkit:card:read${B.reset} ${B.dim}# 读卡片状态${B.reset}`),console.log(` • ${B.bold}cardkit:card:write${B.reset} ${B.dim}# 创建/更新卡片 (流式渲染核心)${B.reset}`),console.log(),console.log(` ${B.bold}④ 订阅事件 (左侧 "${B.cyan}事件与回调${B.reset}", 拆两个子页:)${B.reset}`),console.log(` ${B.dim}a)${B.reset} ${B.bold}事件配置${B.reset} 页:`),console.log(` ${B.yellow}• "订阅方式" → 选 "长连接" → 点保存${B.reset}`),console.log(` • 添加事件: ${B.bold}im.message.receive_v1${B.reset} ${B.dim}# 收群消息${B.reset}`),console.log(` ${B.dim}b)${B.reset} ${B.bold}回调配置${B.reset} 页:`),console.log(` ${B.yellow}• "订阅方式" → 选 "长连接" → 点保存${B.reset}`),console.log(` • 添加事件: ${B.bold}card.action.trigger${B.reset} ${B.dim}# 卡片按钮点击回调${B.reset}`),console.log(),console.log(` ${B.bold}⑤ 发布版本${B.reset}`),console.log(` 页面顶部 "${B.bold}创建版本${B.reset}" → 滚到底点 "${B.bold}保存${B.reset}" → 弹框点 "${B.bold}发布${B.reset}"。`),console.log(` ${B.yellow}没发版的应用收不到任何事件 — 这步九成新手会忘!${B.reset}`),console.log(),console.log(` ${B.bold}⑥ 拿凭据${B.reset}`),console.log(` 左侧 "凭证与基础信息" → 顶部 ${B.bold}App ID${B.reset} (${B.dim}cli_...${B.reset}) 和 ${B.bold}App Secret${B.reset}, 待会粘到下面。`),console.log(),console.log(` ${B.bold}⑦ 把机器人拉进群${B.reset}`),console.log(" 想用的飞书群 → 群设置 → 群机器人 → 添加机器人 → 选你的应用。"),console.log(` ${B.yellow}群名要等于 projects_root 下的项目目录名${B.reset} (下一步设, 默认是用户主目录)。`),console.log();let Y="",Q="";while(!0){Y=await s$("App ID (以 cli_ 开头)",{required:!0}),Q=await s$("App Secret",{required:!0}),console.log(`${B.dim}测试中... (调 tenant_access_token endpoint)${B.reset}`);let A=await Sz(Y,Q);if(A.ok){console.log(`${B.green}✓ Feishu 凭据测试通过${B.reset}`);break}if(console.log(`${B.red}✗ 测试失败:${B.reset} ${A.error}`),console.log(`${B.dim}最常见原因: app_id / app_secret 抄错, 或应用还没 "发布上线" (步骤 ⑤)。${B.reset}`),console.log(),(await s$("重新填? (Y/n)",{default:"y"})).toLowerCase()==="n")console.log(`${B.yellow}已取消, 配置未写盘。${B.reset}`),O2.close(),process.exit(1)}u4(4,4,"工作目录 + 启动"),console.log("每个 Feishu 群对应 projects_root 下同名的目录。"),console.log();let H=process.platform==="win32"?process.env.USERPROFILE??"C:\\Users\\Default":process.env.HOME??"/root",W=await s$("projects_root",{default:H});fZ(d6,{recursive:!0});let X=["# Lodestar config — generated by `lodestar-setup`","# Edit by hand or re-run setup to overwrite.","","[feishu]",`app_id = "${V7(Y)}"`,`app_secret = "${V7(Q)}"`,"","[runtime]",`projects_root = "${V7(W)}"`,"","[runtime.agent_auto_update]","codex = false","claude = false","dsh = false",""];d0(M0,X.join(`
|
|
16
18
|
`)),console.log(`
|
|
17
|
-
${B.green}${B.bold}✓ 配置已写入${B.reset}`),console.log(` ${B.cyan}${
|
|
18
|
-
${B.bold}启动 daemon...${B.reset}`);let V=
|
|
19
|
-
`;if(process.stderr.write(J),!
|
|
20
|
-
${this.stderr}`);this.rejectPending(
|
|
19
|
+
${B.green}${B.bold}✓ 配置已写入${B.reset}`),console.log(` ${B.cyan}${M0}${B.reset}`),console.log(`
|
|
20
|
+
${B.bold}启动 daemon...${B.reset}`);let V=xz(),z=process.platform==="win32"?"\\":"/",G=process.platform==="win32"?`${process.env.LOCALAPPDATA??"%LOCALAPPDATA%"}\\Lodestar\\daemon-YYYY-MM-DD.log`:`${process.env.HOME??"~"}/.local/share/lodestar/daemon-YYYY-MM-DD.log`;if(V.pid)console.log(`${B.green}✓ daemon 已在后台启动${B.reset} (pid ${V.pid})`),console.log(),console.log(`${B.bold}最后一步: 在 Feishu 验证${B.reset}`),console.log(" ① 把机器人拉进任意飞书群"),console.log(` ② 群名 = ${B.cyan}${W}${z}<群名>${B.reset} 下的目录名 (新群第一条消息会自动建)`),console.log(" ③ 在群里发任意一条消息, 默认由 Claude 接管"),console.log(` ${B.dim}(群里发 model 可选择已配置账号、动态模型和 effort)${B.reset}`),console.log(),console.log("日志 (按日滚动, 保留近 7 天):"),console.log(` ${B.cyan}${G}${B.reset}`),console.log(),console.log(`${B.dim}若长期跑后台, Linux 配 systemd --user,macOS 配 launchd,Windows 配任务计划程序。${B.reset}`);else console.log(`${B.yellow}启动失败: ${V.error}${B.reset}`),console.log(`手动运行: ${B.cyan}lodestar-daemon${B.reset}`);console.log(),O2.close()}var B,O2;var hZ=S(()=>{Y0();n0();b1();B={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",green:"\x1B[32m",yellow:"\x1B[33m",cyan:"\x1B[36m",red:"\x1B[31m"},O2=Pz({input:process.stdin,output:process.stdout})});import{existsSync as Cz,readFileSync as bz}from"node:fs";function IZ($,Z){return`${$}:${Z}`}function yz(){if(!Cz(f4))return;try{let $=JSON.parse(bz(f4,"utf8"));if($?.version!==1||!Array.isArray($.ids)||$.ids.some((Z)=>typeof Z!=="string"||!Z))throw Error("invalid delegated-agent session registry");T2=new Set($.ids)}catch($){_7=$ instanceof Error?$:Error(String($))}}function gZ(){if(_7)throw Error(`delegated-agent session registry is unavailable: ${_7.message}`)}function cZ($,Z){gZ();let J=Z.trim();if(!J)throw Error("delegated-agent session id is empty");let Y=IZ($,J);if(T2.has(Y))return;let Q=new Set(T2);Q.add(Y),A0(f4,{version:1,ids:[...Q].sort()}),T2=Q}function y1($,Z){return gZ(),T2.has(IZ($,Z))}var T2,_7=null;var E2=S(()=>{Y0();n0();T2=new Set;yz()});var mZ=1;import{appendFileSync as lZ,mkdirSync as wz,readdirSync as fz,unlinkSync as iZ,existsSync as uZ,statSync as vz,renameSync as hz,readFileSync as Iz}from"node:fs";import{join as dZ}from"node:path";function B7($="development"){return $!=="test"}function nZ($){let Z=$.getFullYear(),J=String($.getMonth()+1).padStart(2,"0"),Y=String($.getDate()).padStart(2,"0");return`${Z}-${J}-${Y}`}function aZ($,Z=o){return dZ(Z,`${A7}${nZ($)}${K7}`)}function cz($){if(!$.startsWith(A7)||!$.endsWith(K7))return null;let Z=$.slice(A7.length,$.length-K7.length),J=/^(\d{4})-(\d{2})-(\d{2})$/.exec(Z);if(!J)return null;let Y=new Date(Number(J[1]),Number(J[2])-1,Number(J[3]));return Number.isNaN(Y.getTime())?null:Y}function oZ($,Z=new Date,J=gz){let Y;try{Y=fz($)}catch{return 0}let Q=new Date(Z.getFullYear(),Z.getMonth(),Z.getDate()),H=0;for(let W of Y){let X=cz(W);if(!X)continue;if(Math.round((Q.getTime()-X.getTime())/86400000)<J)continue;try{iZ(dZ($,W)),H++}catch{}}return H}function mz(){try{if(!uZ(x1))return;let $=vz(x1);if(!$.isFile()||$.size===0)return;let Z=aZ($.mtime);if(uZ(Z)){lZ(Z,Iz(x1)),iZ(x1);return}hz(x1,Z)}catch{}}function _($){let Z=new Date,J=`[${Z.toISOString()}] ${$}
|
|
21
|
+
`;if(process.stderr.write(J),!B7())return;try{let Y=nZ(Z);if(pZ!==Y)pZ=Y,oZ(o,Z);lZ(aZ(Z),J)}catch{}}var gz=7,A7="daemon-",K7=".log",pZ=null;var g=S(()=>{Y0();if(B7())try{wz(o,{recursive:!0})}catch{}if(B7()){mz();try{oZ(o)}catch{}}});import{EventEmitter as uz}from"node:events";import{createRequire as pz}from"node:module";import{createHash as lz,randomUUID as iz}from"node:crypto";import{createInterface as dz}from"node:readline";import{dirname as nz,join as z$,isAbsolute as az}from"node:path";import{fileURLToPath as L7}from"node:url";import{tmpdir as oz}from"node:os";import{existsSync as rZ,mkdirSync as tZ,mkdtempSync as rz,readFileSync as N2,renameSync as tz,writeFileSync as sZ,rmSync as q7}from"node:fs";import sz from"cross-spawn";function ez($){let Z=$.LODESTAR_DSH_PROVIDER??"deepseek-official";if(Z==="deepseek-official")return[];if(Z!=="zai-coding-cn"&&Z!=="zai")throw Error(`Unsupported DSH provider: ${Z}`);let J=$.LODESTAR_DSH_MODELS===void 0?void 0:JSON.parse($.LODESTAR_DSH_MODELS);if(J!==void 0&&(!Array.isArray(J)||!J.every((Y)=>typeof Y==="string"&&Y)))throw Error("Invalid DSH GLM model catalog");return[{id:"llm-deepseek",disabled:!0},{id:"llm-pi-ai",disabled:!1,config:{providers:{[Z]:{apiKeyEnv:"LODESTAR_DSH_GLM_API_KEY",baseURL:$.LODESTAR_DSH_BASE_URL,compat:{supportsReasoningEffort:!0},reasoning:"high",...Array.isArray(J)?{models:J.map((Y)=>({id:Y,reasoningEfforts:{off:null,minimal:"minimal",low:"low",medium:"medium",high:"high",xhigh:"xhigh",max:"max"}}))}:{}}}}},{id:"agent-default-model",config:{provider:Z,model:$.LODESTAR_DSH_DEFAULT_MODEL??""}}]}function $G($,Z){if(Z?.loadProjectMcp===!1)return[];let J;try{J=N2(z$($,".mcp.json"),"utf8")}catch(Q){if(Q?.code==="ENOENT")return[];throw Q}let Y=JSON.parse(J);if(!Y.mcpServers||typeof Y.mcpServers!=="object"||Array.isArray(Y.mcpServers))throw Error("DSH project .mcp.json must contain an mcpServers object");return Object.entries(Y.mcpServers).map(([Q,H])=>{if(!/^[A-Za-z0-9_-]{1,32}$/.test(Q)||!H||typeof H!=="object")throw Error(`invalid DSH MCP server: ${Q}`);let W=H,X=W.type==="http"?{transport:"streamable-http",serverName:Q,url:W.url,headers:W.headers??{}}:W.type===void 0||W.type==="stdio"?{transport:"stdio",serverName:Q,command:W.command,args:W.args??[],env:W.env??{},cwd:$}:null;if(!X)throw Error(`DSH does not support MCP transport ${W.type} for ${Q}`);return{id:`lodestar-mcp-${Q}`,name:"@deepseek-ai/dsh-mcp-client",config:{...X,failOnStartupError:!0}}})}async function w1($,Z,J={}){let Y=new l4($);Y.on("failure",(W)=>_(`dsh catalog: ${W}`));let Q,H;try{await Y.initialize(),H=await Y.request(Z,J)}catch(W){Q=W}try{await Y.close()}catch(W){if(Q)throw AggregateError([Q,W],"DSH query and cleanup both failed");throw W}if(Q)throw Q;return H}var l4;var S2=S(()=>{Y0();b1();g();l4=class l4 extends uz{child;pending=new Map;nextId=0;exited=!1;closing=!1;stderr="";initialized=!1;initTask;closeTask;exitTask;launchDir;constructor($){super();if(!az($.cwd))throw Error("DSH requires an absolute workspace");let Z=c4("dsh"),Y=pz(z$(Z,"package.json")).resolve("@deepseek-ai/dsh/package.json"),Q=JSON.parse(N2(Y,"utf8"));_(`dsh runtime: ${Q.version} (${Z})`);let H=ez($.env),W=$.home??k1;tZ(W,{recursive:!0,mode:448});let X=$G($.cwd,$.profile);this.launchDir=rz(z$(oz(),"lodestar-dsh-"));let V=import.meta.url.endsWith(".ts"),z=V?"dsh-bridge.ts":"dsh-bridge.js",G=N2(L7(new URL(`./${z}`,import.meta.url))),A=V?N2(L7(new URL("./dsh-protocol.ts",import.meta.url))):Buffer.alloc(0),K=JSON.parse(N2(L7(new URL("../package.json",import.meta.url)),"utf8")),L=Buffer.from(JSON.stringify({name:K.name,version:K.version,type:"module",private:!0})),D=lz("sha256").update(G).update(A).update(L).digest("hex").slice(0,20),q=z$(Z,".lodestar-bridges",D);tZ(q,{recursive:!0});let P=z$(q,z),x=(y,m)=>{if(rZ(y))return;let N=`${y}.${iz()}.tmp`;try{sZ(N,m),tz(N,y)}finally{if(rZ(N))q7(N)}};if(x(z$(q,"package.json"),L),V)x(z$(q,"dsh-protocol.ts"),A);x(P,G);let F=[...["sdk-jsonrpc-server","session-title-llm","session-telemetry-otel","settings","credentials","llm-pi-ai"].map((y)=>({id:y,disabled:!0})),{id:"approval",config:{policy:"ask"}},{id:"permission",config:{defaultPreset:"lodestar",presets:{lodestar:{sandbox:"danger-full-access",approval:"ask"}}}},{id:"system-prompt",config:{personaPrefix:"You are a coding agent powered by {{model}}.",personaSuffix:"Your working directory is {{cwd}}."}},{id:"skill-filesystem",config:{includeDefaultRoots:!0,...$.managedSkillDir?{customSkillDirs:[$.managedSkillDir]}:{}}},{insert:[{id:"lodestar-bridge",name:P},{id:"lodestar-ask-user",name:"@deepseek-ai/dsh-tool-ask-user"},...X]},...H],M=z$(this.launchDir,"bridge.patch.yml");sZ(M,JSON.stringify(F),{mode:384});let j=$.env.LODESTAR_DSH_NODE||"node",k=[z$(nz(Y),Q.bin.dsh),"--profile","sdk","--patch",M,...($.patches??[]).flatMap((y)=>["--patch",y])],C={...$.env};if(C.LODESTAR_AGENT_CAPABILITY&&C.LODESTAR_AGENT_URL)C.DSH_LODESTAR_AGENT_CONTEXT=JSON.stringify({baseUrl:C.LODESTAR_AGENT_URL,capability:C.LODESTAR_AGENT_CAPABILITY});for(let y of Object.keys(C))if(y.startsWith("LODESTAR_AGENT_"))delete C[y];try{this.child=sz(j,k,{cwd:$.cwd,stdio:["pipe","pipe","pipe"],shell:!1,env:{...C,DSH_HOME:W,DSH_PERMISSION_MODE:"danger-full-access"}})}catch(y){throw q7(this.launchDir,{recursive:!0,force:!0}),y}this.child.stderr.setEncoding("utf8"),this.child.stderr.on("data",(y)=>{this.stderr=(this.stderr+y).slice(-16384),_(`dsh stderr: ${y.trimEnd()}`)}),this.child.stdin.on("error",(y)=>this.transportFailure(y));let c=dz({input:this.child.stdout,crlfDelay:1/0});c.on("line",(y)=>this.receive(y)),this.exitTask=new Promise((y)=>{this.child.once("error",(m)=>this.transportFailure(m)),this.child.once("close",(m,N)=>{this.exited=!0,c.close();let f=Error(`DSH exited code=${m} signal=${N}
|
|
22
|
+
${this.stderr}`);this.rejectPending(f),q7(this.launchDir,{recursive:!0,force:!0}),y(),this.emit("exit",{code:m,signal:N,expected:this.closing})})})}get pid(){return this.child.pid}isAlive(){return!this.exited}initialize(){return this.initTask??=this.request("initialize",{},30000).then(($)=>{if($.protocolVersion!==mZ||typeof $.runtimeVersion!=="string"||!$.runtimeVersion)throw Error(`DSH handshake version mismatch: ${JSON.stringify($)}`);this.initialized=!0})}request($,Z={},J=30000){if(this.exited||this.closing&&$!=="shutdown")return Promise.reject(Error("DSH transport is closed"));let Y=++this.nextId;return new Promise((Q,H)=>{let W=J===null?void 0:setTimeout(()=>{this.pending.delete(Y),H(Error(`DSH ${$} timed out after ${J}ms
|
|
21
23
|
${this.stderr}`))},J);this.pending.set(Y,{resolve:Q,reject:H,timer:W}),this.child.stdin.write(JSON.stringify({jsonrpc:"2.0",id:Y,method:$,params:Z})+`
|
|
22
|
-
`,(X)=>{if(X)this.transportFailure(X)})})}receive($){try{let Z=JSON.parse($);if(Z.jsonrpc!=="2.0")throw Error("invalid DSH JSON-RPC envelope");if(typeof Z.id==="number"){let J=this.pending.get(Z.id);if(!J){
|
|
23
|
-
`)){let Q=
|
|
24
|
+
`,(X)=>{if(X)this.transportFailure(X)})})}receive($){try{let Z=JSON.parse($);if(Z.jsonrpc!=="2.0")throw Error("invalid DSH JSON-RPC envelope");if(typeof Z.id==="number"){let J=this.pending.get(Z.id);if(!J){_(`dsh: unexpected response id=${Z.id}`);return}if(this.pending.delete(Z.id),clearTimeout(J.timer),Z.error)J.reject(Error(`DSH RPC error: ${Z.error.message}`));else if("result"in Z)J.resolve(Z.result);else J.reject(Error("DSH response has neither result nor error"))}else if(typeof Z.method==="string"&&Z.params&&typeof Z.params==="object")this.emit("notification",{method:Z.method,params:Z.params});else throw Error("invalid DSH notification")}catch(Z){this.transportFailure(Z instanceof Error?Z:Error(String(Z)))}}rejectPending($){for(let Z of this.pending.values())clearTimeout(Z.timer),Z.reject($);this.pending.clear()}transportFailure($){this.rejectPending($),this.emit("failure",$)}close($=3000){return this.closeTask??=this.dispose($).catch((Z)=>{throw this.closeTask=void 0,Z})}async dispose($){if(this.exited)return;if(this.closing=!0,this.initialized)try{await this.request("shutdown",{},$)}catch(J){_(`dsh shutdown: ${J}`)}this.child.stdin.end();let Z=async(J)=>{let Y;return await Promise.race([this.exitTask,new Promise((Q)=>{Y=setTimeout(Q,J)})]),clearTimeout(Y),this.exited};if(await Z($))return;if(_(`dsh: terminate owned child pid=${this.pid}`),this.child.kill("SIGTERM"),await Z($))return;if(_(`dsh: kill unresponsive owned child pid=${this.pid}`),this.child.kill("SIGKILL"),!await Z($))throw Error(`DSH child exit not confirmed: pid=${this.pid}`)}}});function $$($){return typeof $==="string"&&D7.includes($)}function X0($){return typeof $==="string"&&["off","minimal","low","medium","high","xhigh","max"].includes($)}function R0($){return typeof $==="string"&&P7.includes($)}function f1($){if($?.startsWith("dsh:"))return"dsh";return $?.startsWith("claude:")?"claude":"codex"}function Z$($){return{claude:"Claude",codex:"Codex",dsh:"DeepSeek Harness"}[$]}var D7,P7,E$="max",e$;var K0=S(()=>{D7=["codex","claude","dsh"];P7=["low","medium","high","xhigh","max","default"];e$=class e$ extends Error{constructor($="上下文窗口充足,无需压缩"){super($);this.name="NothingToCompactError"}}});import{readFileSync as ZG}from"node:fs";import{homedir as $J}from"node:os";function eZ($){return $.replace(/^~(?=\/|$)/,$J())}function JG($){let Z={_:{}},J="_";for(let Y of $.split(`
|
|
25
|
+
`)){let Q=YG(Y).trim();if(!Q)continue;let H=Q.match(/^\[([^\]]+)\]$/);if(H){J=H[1].trim(),Z[J]??={};continue}let W=Q.match(/^([\w.-]+)\s*=\s*(.+)$/);if(W){let X=W[2].trim(),V=X.startsWith('"')&&X.endsWith('"'),z=X.startsWith("'")&&X.endsWith("'");if(V||z){if(X=X.slice(1,-1),V)X=X.replace(/\\([\\"])/g,"$1")}Z[J][W[1]]=X}}return Z}function YG($){let Z=null,J=!1;for(let Y=0;Y<$.length;Y++){let Q=$[Y];if(Z==="double"){if(J){J=!1;continue}if(Q==="\\"){J=!0;continue}if(Q==='"')Z=null;continue}if(Z==="single"){if(Q==="'")Z=null;continue}if(Q==='"')Z="double";else if(Q==="'")Z="single";else if(Q==="#")return $.slice(0,Y)}return $}function i4(){let $;try{$=ZG(M0,"utf8")}catch(j){throw process.stderr.write(`lodestar: cannot read config at ${M0}
|
|
24
26
|
`+" → 运行 `lodestar-setup` 走交互式向导生成 (Feishu / Codex / 工作目录)\n"+` → 或手写: 设 LODESTAR_CONFIG=/path/to/config.toml 覆盖默认路径
|
|
25
27
|
`+` [feishu]
|
|
26
28
|
app_id = "cli_xxx"
|
|
27
29
|
app_secret = "xxx"
|
|
28
30
|
|
|
29
|
-
`),
|
|
31
|
+
`),j}let Z=JG($),J=Z.feishu?.app_id,Y=Z.feishu?.app_secret;if(!J||!Y)throw Error(`lodestar: ${M0} is missing [feishu].app_id / [feishu].app_secret`);let Q=eZ(Z.runtime?.projects_root??$J()),H={codex:!1,claude:!1,dsh:!1},W=Z["runtime.agent_auto_update"],X=Z.runtime?.agent_auto_update;if(X!==void 0){if(W)throw Error("lodestar: legacy [runtime].agent_auto_update cannot be combined with [runtime.agent_auto_update]");if(X!=="true"&&X!=="false")throw Error(`lodestar: [runtime].agent_auto_update must be true or false, got "${X}"`);for(let j of["codex","claude","dsh"])H[j]=X==="true";process.stderr.write(`lodestar: 旧 agent_auto_update 总开关已按原值映射为三个开关;请改用 [runtime.agent_auto_update] 的 codex、claude、dsh 配置。
|
|
32
|
+
`)}else if(W)for(let[j,k]of Object.entries(W)){if(j!=="codex"&&j!=="claude"&&j!=="dsh")throw Error(`lodestar: unknown [runtime.agent_auto_update] Agent "${j}"`);if(k!=="true"&&k!=="false")throw Error(`lodestar: [runtime.agent_auto_update].${j} must be true or false, got "${k}"`);H[j]=k==="true"}let V=(Z.runtime?.live_elapsed??"bucket").trim().toLowerCase();if(V!=="bucket"&&V!=="second")throw Error(`lodestar: [runtime].live_elapsed must be "bucket" or "second", got "${Z.runtime?.live_elapsed}"`);let z=V,G=Z.notify?.bind??"127.0.0.1",A=Z.notify?.port??"9876";if(!/^\d+$/.test(A.trim()))throw Error(`lodestar: [notify].port must be an integer, got "${A}"`);let K=Number.parseInt(A,10);if(!Number.isFinite(K)||K<=0||K>65535)throw Error(`lodestar: [notify].port must be 1..65535, got "${A}"`);let L=(j)=>{let k=Z[j]??{},C={};for(let[c,y]of Object.entries(k))if(typeof y==="string"&&y.length>0)C[c]=y;return C},D=()=>{let j={};for(let[k,C]of Object.entries(Z)){if(!k.startsWith("claude.models."))continue;let y=k.slice(14).trim();if(!y)continue;let m={};for(let[N,f]of Object.entries(C)){if(typeof f!=="string"||f.length===0)continue;if(N.trim()==="model")m.model=f}j[y]=m}return j},q=()=>{let j={},k="projects.";for(let[C,c]of Object.entries(Z)){if(!C.startsWith("projects."))continue;let y=C.slice(9).trim();if(!y)continue;let m={};for(let[N,f]of Object.entries(c)){if(typeof f!=="string"||f.length===0)continue;switch(N.trim()){case"cwd":m.cwd=f;break;case"setting_sources":m.settingSources=f;break;case"strict_mcp":m.strictMcp=f==="true";break;case"tools":m.tools=f;break;case"load_project_mcp":m.loadProjectMcp=f==="true";break}}j[y]=m}return j},P=()=>{let j={},k="token_source.";for(let[C,c]of Object.entries(Z)){if(!C.startsWith("token_source."))continue;let y=C.slice(13).trim();if(!y)continue;let m={};for(let[N,f]of Object.entries(c)){if(typeof f!=="string")continue;let I=N.trim();if(I==="default")m.default=f==="true";else if(I==="agent"||I==="display"||I==="auth"||I==="base_url"||I==="auth_token"||I==="api_key"||I==="bin"||I==="model"||I==="effort"||I==="models"||I==="hidden_models"||I==="custom_models"||I==="slots"||I==="usage")m[I]=f}j[y]=m}return j},x=L("codex.env"),F=L("claude.env"),M=Z.claude?.bin?eZ(Z.claude.bin):void 0;return{feishu:{app_id:J,app_secret:Y},runtime:{projects_root:Q,live_elapsed:z,agent_auto_update:H},notify:{bind:G,port:K},codex:{env:x},claude:{bin:M,env:F,models:D()},projects:q(),token_sources:P()}}function ZJ(){v.token_sources=i4().token_sources}var v;var x0=S(()=>{Y0();v=i4()});function Q0($){return typeof $==="string"&&$?$:void 0}function u($){return $!=null&&typeof $==="object"?$:null}function G$($){if($==null||$==="")return"-";return String($).replace(/\s+/g," ").slice(0,300)}function d4($){if(!$)return"[]";let Z=Object.keys($),J=Z.slice(0,80),Y=Z.length>J.length?`,...+${Z.length-J.length}`:"";return`[${J.join(",")}${Y}]`}function HG($){let Z=$.slice(0,M7),J=$.length>Z.length?`,...+${$.length-Z.length}`:"";return`[${Z.join(",")}${J}]`}function WG($){let Z=u($);if(!Z)return null;let J=u(Z.event),Y=u(Z.payload);return u(Z.item)??u(Z.responseItem)??u(Z.rawItem)??u(J?.item)??u(J?.responseItem)??u(J?.rawItem)??u(Y?.item)??u(Y?.responseItem)??u(Y?.rawItem)??(x2(Z.type)?Z:null)??(J&&x2(J.type)?J:null)??(Y&&x2(Y.type)?Y:null)}function XG($){let Z=[],J=new WeakSet,Y=(Q,H,W)=>{if(Z.length>=M7||W>6)return;if(Array.isArray(Q)){if(H)Z.push(`${H}[]`);if(Q.length>0)Y(Q[0],H?`${H}[]`:"[]",W+1);return}if(Q==null||typeof Q!=="object")return;if(J.has(Q))return;J.add(Q);for(let X of Object.keys(Q)){if(Z.length>=M7)return;let V=H?`${H}.${X}`:X;Z.push(V),Y(Q[X],V,W+1)}};return Y($,"",0),Z}function R7($){let Z=new WeakSet,J;try{J=JSON.stringify($,(Y,Q)=>{if(typeof Q==="bigint")return`${Q.toString()}n`;if(typeof Q==="string"&&Q.length>F7)return`${Q.slice(0,F7)}...<truncated ${Q.length-F7} chars>`;if(Q!=null&&typeof Q==="object"){if(Z.has(Q))return"[Circular]";Z.add(Q)}return Q})??String($)}catch(Y){J=`<unserializable: ${Y}>`}if(J.length>j7)return`${J.slice(0,j7)}...<truncated ${J.length-j7} chars>`;return J}function k0($,Z){let J=u(Z),Y=J?u(J.params):null,Q=J?u(J.item)??u(Y?.item):null,H=J?Q0(J.method)??"-":"-";_([`codex-process: APP_SERVER_UNHANDLED_${$}`,`method=${G$(H)}`,`rootKeys=${d4(J)}`,`itemKeys=${d4(Q)}`,`payload=${R7(Z)}`].join(" "))}function U7($,Z,J){let Y=u(Z),Q=WG(Z),H=[`phase=${G$(J.phase??"event")}`,`method=${G$($)}`,`sourceMethod=${G$(J.sourceMethod)}`,`sourceType=${G$(J.sourceType)}`,`sessionId=${G$(J.sessionId)}`,`threadId=${G$(J.threadId)}`,`turnId=${G$(J.turnId)}`,`itemId=${G$(J.itemId)}`].join(" ");if(_(`codex-process: CONTEXT_COMPACTION_EVENT ${H} rootKeys=${d4(Y)} itemKeys=${d4(Q)}`),_(`codex-process: CONTEXT_COMPACTION_PATHS ${H} paths=${HG(XG(Z))}`),Q)_(`codex-process: CONTEXT_COMPACTION_ITEM ${H} item=${R7(Q)}`);_(`codex-process: CONTEXT_COMPACTION_PAYLOAD ${H} payload=${R7(Z)}`)}function x2($){if(typeof $!=="string")return null;return QG.has($)?$:null}function VG($,Z){if(Z==="item/started")return"start";if(Z==="item/completed"||Z==="rawResponseItem/completed")return"end";if($==="compacted")return"start";if($==="context_compacted"||JJ.has(Z))return"end";return"event"}function O7($,Z){return YJ($,u(Z)??{})}function T7($){let Z=u($);if(!Z)return null;let J=Q0(Z.method)??Q0(Z.type)??"raw_message";return YJ(J,Z)}function YJ($,Z){let J=u(Z.payload),Y=[Z,u(Z.event),J,u(Z.item),u(Z.responseItem),u(Z.rawItem)].filter((V)=>V!=null),Q=null;for(let V of Y)if(Q=x2(V.type),Q)break;if(!JJ.has($)&&!Q)return null;let H=u(Z.item)??u(Z.responseItem)??u(Z.rawItem),W=Q==="compacted"&&J?J:H&&x2(H.type)?H:Z,X=u(W.item)??u(W.responseItem)??u(W.rawItem)??H??{};return{...W,threadId:Q0(W.threadId)??Q0(W.thread_id)??Q0(Z.threadId)??Q0(Z.thread_id),turnId:Q0(W.turnId)??Q0(W.turn_id)??Q0(Z.turnId)??Q0(Z.turn_id),itemId:Q0(W.itemId)??Q0(W.item_id)??Q0(X.id)??Q0(X.itemId)??Q0(X.item_id),timestamp:Q0(Z.timestamp)??Q0(W.timestamp),recordType:Q0(Z.type),phase:VG(Q,$),sourceMethod:$,sourceType:Q??$}}var JJ,QG,j7=200000,F7=50000,M7=400;var E7=S(()=>{g();JJ=new Set(["thread/compacted","context/compacted","context_compacted","contextCompacted"]),QG=new Set(["compacted","compaction","compaction_trigger","context_compacted","context_compaction","contextCompaction","ContextCompaction"])});function k2($){return $!=null&&typeof $==="object"?$:null}function _$($){return typeof $==="number"&&Number.isFinite($)?$:void 0}function QJ($){return Object.values($).some((Z)=>typeof Z==="number"&&Number.isFinite(Z))}function n4($,Z){return $?_$($[Z]):void 0}function v1($){let Z=k2($);if(!Z)return null;let J=k2(Z.inputTokensDetails)??k2(Z.input_tokens_details),Y=k2(Z.outputTokensDetails)??k2(Z.output_tokens_details),Q={total_tokens:_$(Z.totalTokens??Z.total_tokens),input_tokens:_$(Z.inputTokens??Z.input_tokens),output_tokens:_$(Z.outputTokens??Z.output_tokens),reasoning_output_tokens:_$(Z.reasoningOutputTokens??Z.reasoning_output_tokens??n4(Y,"reasoningTokens")??n4(Y,"reasoning_tokens")),cache_creation_input_tokens:_$(Z.cacheCreationInputTokens??Z.cache_creation_input_tokens),cache_read_input_tokens:_$(Z.cachedInputTokens??Z.cached_input_tokens??Z.cacheReadInputTokens??Z.cache_read_input_tokens??n4(J,"cachedTokens")??n4(J,"cached_tokens"))};return QJ(Q)?Q:null}function N7($,Z){let J=(Q)=>{let H=_$($?.[Q]),W=_$(Z?.[Q]);if(H===void 0&&W===void 0)return;return Math.max(0,(H??0)-(W??0))},Y={total_tokens:J("total_tokens"),input_tokens:J("input_tokens"),output_tokens:J("output_tokens"),reasoning_output_tokens:J("reasoning_output_tokens"),cache_creation_input_tokens:J("cache_creation_input_tokens"),cache_read_input_tokens:J("cache_read_input_tokens")};return QJ(Y)?Y:null}function S7($){if(!$)return null;if(typeof $.input_tokens==="number"||typeof $.cache_creation_input_tokens==="number"||typeof $.output_tokens==="number")return($.input_tokens??0)+($.cache_creation_input_tokens??0)+($.output_tokens??0);return typeof $.total_tokens==="number"&&Number.isFinite($.total_tokens)?$.total_tokens:null}function HJ($){let Z=$.trim();if(Z.length<2)return Z;let J=a4[Z[0]];if(!J||!Z.endsWith(J))return Z;let Y=Z.slice(1,-1);if(Z[0]==="'")return Y.replace(/''/g,"'");if(Z[0]==='"')return Y.replace(/\\"/g,'"');return Y}function k7($){let Z=GG(String($??"")),J=Z.split(`
|
|
30
33
|
`,1)[0]?.trim()??"",Q=(J.startsWith("#")&&!J.startsWith("#!")?J.replace(/^#\s*/,"").trim():"").replace(/^(?:desc|dec|description|说明|目的|用途)\s*[::]\s*/i,"").trim(),H=Q?Z.split(`
|
|
31
34
|
`).slice(1).join(`
|
|
32
|
-
`).trimStart():Z;return{description:Q,command:H||Z}}function
|
|
33
|
-
`).trim(),J=Z.match(/^(?:\/usr\/bin\/env\s+)?(?:\/[\w./-]+\/)?(?:ba|z|fi)?sh\s+-[A-Za-z]*c[A-Za-z]*\s+([\s\S]+)$/);if(J){let Q=
|
|
34
|
-
`)}function
|
|
35
|
-
`).replace(/\s*"\s*'\$\(([^)]*)\)'/g,(W,X)=>` $(${X})`)}function
|
|
36
|
-
`)}var _J,
|
|
37
|
-
`))>=0){let J=this.stdoutBuf.slice(0,Z).trim();if(this.stdoutBuf=this.stdoutBuf.slice(Z+1),!J)continue;let Y;try{Y=JSON.parse(J)}catch(Q){
|
|
35
|
+
`).trimStart():Z;return{description:Q,command:H||Z}}function h1($,Z=60){let{description:J,command:Y}=k7($);if(J)return J;return zG(Y).replace(/\s+/g," ").trim().slice(0,Z)}function zG($){let Z=$.split(/\r?\n/).map((J)=>J.trim()).filter(Boolean);return Z.find((J)=>!J.startsWith("#")&&!/^set\s+-/.test(J)&&!/^cd\s+/.test(J)&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(J)&&!/^cat\s+<<['"]?\w+['"]?/.test(J))??Z[Z.length-1]??""}function GG($){let Z=$.replace(/\r\n/g,`
|
|
36
|
+
`).trim(),J=Z.match(/^(?:\/usr\/bin\/env\s+)?(?:\/[\w./-]+\/)?(?:ba|z|fi)?sh\s+-[A-Za-z]*c[A-Za-z]*\s+([\s\S]+)$/);if(J){let Q=AG(J[1]);return x7(Q||Z)}let Y=_G(Z);if(Y)return Y;return x7(Z)}function _G($){let Z=$.match(/^("[^"]*"|'[^']*'|“[^”]*”|\S+)\s+([\s\S]*)$/);if(!Z)return null;let J=HJ(Z[1]).replace(/\.exe$/i,"");if(!/(?:^|[\\/])(?:powershell|pwsh)$/i.test(J))return null;let Y=Z[2];for(;;){let Q=Y.match(/^(-[A-Za-z][\w-]*)\s+([\s\S]*)$/);if(!Q)break;let H=Q[1].toLowerCase();if(H==="-command"||H==="-c")return x7(HJ(Q[2]));if(Y=Q[2],H==="-executionpolicy"||H==="-inputformat"||H==="-outputformat")Y=Y.replace(/^(?:"[^"]*"|'[^']*'|\S+)\s+/,"")}return null}function AG($){let Z=$.trim();if(Z.length<2)return Z;let J=a4[Z[0]];if(!J||!Z.endsWith(J))return Z;let Y=Z.slice(1,-1);if(Z[0]==="'")return Y.replace(/'\\''/g,"'");return Y.replace(/\\(["\\$`])/g,"$1").replace(/\\n/g,`
|
|
37
|
+
`)}function x7($){let Z=$.trim(),J=Z[0];if(!a4[J])return Z;let Y=Z.slice(1);if(!/^#\s*(?:desc|dec|description|说明|目的|用途)\s*[::]/i.test(Y)&&!KG(Y,J))return Z;if(J!=='"')return Y.replace(/'\s*$/,"");return Y.replace(/\s*[”"]\s*$/,"").replace(/\\(["\\$`])/g,"$1").replace(/\\n/g,`
|
|
38
|
+
`).replace(/\s*"\s*'\$\(([^)]*)\)'/g,(W,X)=>` $(${X})`)}function KG($,Z){let J=a4[Z];for(let Y=0;Y<$.length;Y++){let Q=$[Y];if(Z==='"'&&Q==="\\"&&Y+1<$.length){Y++;continue}if(Q===J)return/^[\s]*$/.test($.slice(Y+1))}return!1}var a4;var o4=S(()=>{a4={'"':'"',"'":"'","“":"”"}});function O($){return $ instanceof Error?$.message:String($)}function q0($){return $.length<=16?$:`${$.slice(0,8)}…${$.slice(-4)}`}async function WJ($,Z,J){let Y=null;try{return await Promise.race([$,new Promise((Q,H)=>{Y=setTimeout(()=>H(Error(`${J} timed out after ${Z/1000}s`)),Z)})])}finally{if(Y)clearTimeout(Y)}}import{isAbsolute as XJ}from"node:path";function BG($){return $.kind==="fresh"?null:$.source.provider}function V0($,Z,J){let Y=BG($);if(Y&&Y!==Z)throw Error(`conversation launch provider mismatch: source=${Y} target=${Z}`);if($.kind!=="fresh"&&!$.source.sessionId.trim())throw Error("conversation launch source session id is empty");if($.kind!=="fresh"&&$.source.cwd!==null&&(typeof $.source.cwd!=="string"||!XJ($.source.cwd)))throw Error(`conversation launch source cwd is not absolute: ${String($.source.cwd)}`);if($.kind!=="fresh"&&J!==void 0){if(!XJ(J))throw Error(`expected conversation cwd is not absolute: ${J}`);if($.source.cwd===null)throw Error("conversation launch source cwd is missing");if($.source.cwd!==J)throw Error(`conversation launch cwd mismatch: source=${$.source.cwd} target=${J}`)}if($.kind!=="fork"||!$.through)return;if($.through.provider!==Z||$.through.source.provider!==Z)throw Error(`conversation checkpoint provider mismatch: checkpoint=${$.through.provider} target=${Z}`);if($.through.source.sessionId!==$.source.sessionId)throw Error("conversation checkpoint source does not match fork source");if($.through.source.cwd!==$.source.cwd)throw Error("conversation checkpoint cwd does not match fork source");if(!$.through.id.trim())throw Error("conversation checkpoint id is empty");if(Z==="dsh"&&(!/^\d+$/.test($.through.id)||!Number.isSafeInteger(Number($.through.id))))throw Error("DSH checkpoint must be a non-negative event sequence")}var $1=()=>{};import{closeSync as LG,existsSync as qG,mkdirSync as DG,openSync as PG,readdirSync as jG,readSync as FG,statSync as t4,writeFileSync as MG}from"node:fs";import{homedir as C2}from"node:os";import{delimiter as VJ,isAbsolute as zJ,join as N$}from"node:path";import{EventEmitter as RG}from"node:events";import{StringDecoder as GJ}from"node:string_decoder";import{spawn as UG}from"cross-spawn";function y2(){return U2("codex","codex")}function OG(){if(process.platform==="win32")return process.env.PATH??"";return[...new Set([N$(C2(),".local","npm-global","bin"),N$(C2(),".local","bin"),N$(C2(),".bun","bin"),...(process.env.PATH??"").split(VJ),"/usr/local/bin","/usr/bin","/bin"].filter(Boolean))].join(VJ)}function AJ($){return typeof $==="string"&&/\bselected\s+model\s+is\s+at\s+capacity\b/i.test($)}function CG($=!0){return["app-server","--listen","stdio://",...$?[]:["--disable","multi_agent"]]}function bG($,Z){return{cwd:$,stdio:["pipe","pipe","pipe"],shell:!1,env:Z}}function h0($){return typeof $==="string"&&y7.includes($)}function yG($){if(!Array.isArray($))return[];let Z=new Set,J=[];for(let Y of $){let Q=typeof Y==="string"?Y:typeof Y==="object"&&Y?Y.reasoningEffort:null;if(!h0(Q)||Z.has(Q))continue;Z.add(Q);let H=typeof Y==="object"&&Y&&typeof Y.description==="string"?Y.description:"";J.push({reasoningEffort:Q,description:H})}return J}function C7($,Z){switch($.type){case"commandExecution":return{name:"Bash",input:{command:$.command,cwd:$.cwd,source:$.source}};case"fileChange":return{name:"FileChange",input:{changes:$.changes,status:$.status,cwd:Z}};case"mcpToolCall":return{name:"MCP",input:{server:$.server,tool:$.tool,arguments:$.arguments}};case"dynamicToolCall":return{name:$.namespace?`${$.namespace}.${$.tool}`:$.tool,input:$.arguments};case"webSearch":return{name:"WebSearch",input:{query:$.query,action:$.action}};case"imageGeneration":return{name:"ImageGeneration",input:b7($)}}return null}function wG($){let Z=$?.revisedPrompt??$?.revised_prompt;return typeof Z==="string"&&Z?Z:void 0}function b7($){return{status:$.status,revisedPrompt:wG($),...typeof $?.prompt==="string"&&$.prompt?{prompt:$.prompt}:{}}}function KJ($){if(!$||!qG(_J))return null;let Z=null,J=[_J];while(J.length){let Y=J.pop(),Q;try{Q=jG(Y,{withFileTypes:!0})}catch(H){_(`codex-process: cannot scan Codex session dir ${Y}: ${H instanceof Error?H.message:H}`);continue}for(let H of Q){let W=N$(Y,H.name);if(H.isDirectory()){J.push(W);continue}if(!H.isFile())continue;if(!H.name.startsWith("rollout-")||!H.name.endsWith(`${$}.jsonl`))continue;try{let X=t4(W).mtimeMs;if(!Z||X>Z.mtimeMs)Z={path:W,mtimeMs:X}}catch(X){_(`codex-process: cannot stat Codex rollout ${W}: ${X instanceof Error?X.message:X}`)}}}return Z?.path??null}function DJ($,Z,J=TG){let Y=$?.savedPath??$?.saved_path;if(typeof Y==="string"&&Y)return Y;let Q=$?.result;if(typeof Q==="string"){let H=fG($,Z,J);if(H)return H;if(Q.length>2048){let W=PJ($);return _(`codex-process: image generation inline result could not be decoded id=${W} length=${Q.length}`),`Image generation returned ${Q.length} chars of inline data, but Lodestar could not materialize it as an image file.`}return Q}if(Q&&typeof Q==="object"){let H=Q.savedPath??Q.saved_path??Q.path;if(typeof H==="string"&&H)return H;return JSON.stringify(Q,null,2)}return""}function fG($,Z,J){let Y=$?.result;if(typeof Y!=="string")return null;let Q=vG(Y);if(!Q)return null;let H=BJ(Z??"unknown-thread"),W=BJ(PJ($)),X=N$(J,H),V=N$(X,`${W}.${Q.ext}`);try{return DG(X,{recursive:!0}),MG(V,Q.buffer),V}catch(z){return _(`codex-process: failed to write image generation result ${V}: ${z instanceof Error?z.message:z}`),null}}function PJ($){let Z=$?.callId??$?.call_id??$?.id;return typeof Z==="string"&&Z?Z:`image-${Date.now()}`}function BJ($){let Z=$.trim().replace(/[^a-zA-Z0-9_.-]/g,"_").replace(/^_+|_+$/g,"");return Z?Z.slice(0,140):"unknown"}function vG($){let Z=$.trim(),J=Z,Y=null,Q=Z.match(/^data:image\/([a-zA-Z0-9.+-]+);base64,(.*)$/s);if(Q)Y=IG(Q[1]),J=Q[2];else{if(Z.length<64)return null;if(!/^[a-zA-Z0-9+/=_\-\s]+$/.test(Z))return null}if(J=J.replace(/\s+/g,"").replace(/-/g,"+").replace(/_/g,"/"),!J||J.length%4===1)return null;let H=J.padEnd(Math.ceil(J.length/4)*4,"="),W;try{W=Buffer.from(H,"base64")}catch{return null}if(W.length<12)return null;let X=hG(W)??Y;if(!X)return null;return{buffer:W,ext:X}}function hG($){if($[0]===137&&$[1]===80&&$[2]===78&&$[3]===71&&$[4]===13&&$[5]===10&&$[6]===26&&$[7]===10)return"png";if($[0]===255&&$[1]===216&&$[2]===255)return"jpg";let Z=$.subarray(0,6).toString("ascii");if(Z==="GIF87a"||Z==="GIF89a")return"gif";if($.subarray(0,4).toString("ascii")==="RIFF"&&$.subarray(8,12).toString("ascii")==="WEBP")return"webp";return null}function IG($){let Z=$.toLowerCase();if(Z==="jpeg"||Z==="jpg")return"jpg";if(Z==="png")return"png";if(Z==="gif")return"gif";if(Z==="webp")return"webp";return null}function LJ($,Z,J){let Y=C7($,Z);if(!Y)return null;switch($.type){case"commandExecution":return{...Y,output:$.aggregatedOutput??"",isError:$.exitCode!=null&&$.exitCode!==0};case"fileChange":return{...Y,output:JSON.stringify($.changes??[],null,2),isError:$.status==="failed"};case"mcpToolCall":return{...Y,output:$.error?JSON.stringify($.error,null,2):JSON.stringify($.result??null,null,2),isError:!!$.error};case"dynamicToolCall":return{...Y,output:JSON.stringify($.contentItems??[],null,2),isError:$.success===!1};case"webSearch":return{...Y,output:JSON.stringify($.action??{},null,2),isError:!1};case"imageGeneration":return{...Y,output:DJ($,J),isError:$.status==="failed"}}return null}function r4($,Z){if(typeof $==="string"&&$){let J=$.split("/").filter(Boolean).pop();if(J)return J}return q0(Z)}function qJ($){if(typeof $!=="string"||!$)return;if($.startsWith("gAAAA")&&!/[一-鿿]/.test($))return"(继承主线程历史的密文任务书)";return $}function gG($,Z,J){let Y=(Q)=>typeof Q==="string"?Q:"";switch($){case"Bash":{if(J!=null){let Q=J.replace(/\s+/g," ").trim();return Q?`→ ${Q.slice(0,60)}`:""}return h1(Y(Z?.command))||"(空命令)"}case"FileChange":{let Q=Array.isArray(Z?.changes)?Z.changes.length:0;if(J!=null)return"";return Q>0?`改 ${Q} 个文件`:"文件变更"}case"MCP":return`${Y(Z?.server)}/${Y(Z?.tool)}`.slice(0,60);case"WebSearch":return`"${Y(Z?.query).slice(0,50)}"`;default:{if(J!=null){let Q=J.replace(/\s+/g," ").trim();return Q?`→ ${Q.slice(0,60)}`:""}return JSON.stringify(Z??{}).replace(/\s+/g," ").slice(0,60)}}}function jJ($){return(Array.isArray($.receiverThreadIds)?$.receiverThreadIds:[]).filter((J)=>typeof J==="string"&&!!J)}function cG($){let Z=jJ($);return Z.length>0?`派生 ${Z.length} 个子 agent`:"派生子 agent"}function mG($){let Z=$.agentsStates;if(!Z||typeof Z!=="object")return"";let J=[];for(let[Y,Q]of Object.entries(Z)){let H=Q,W=typeof H?.status==="string"?H.status:"unknown";J.push(`${q0(Y)}: ${W}`)}return J.join(`
|
|
39
|
+
`)}var _J,TG,EG=30000,NG=600000,SG=5000,xG=60000,kG="上一轮因模型暂时满载而中断。请基于当前会话继续完成用户尚未完成的任务,沿用已有进度;执行操作前先确认结果,避免重复已完成的操作。",y7,w2="xhigh",b2,I1;var Z1=S(()=>{x0();g();b1();E7();o4();$1();E2();E7();_J=N$(C2(),".codex","sessions"),TG=N$(C2(),".codex","generated_images");y7=["none","minimal","low","medium","high","xhigh","max","ultra"];b2=class b2 extends Error{method;requestId;serverCode;serverMessage;constructor($,Z,J,Y){super(`codex app-server ${$} failed (id=${Z}, code=${J??"MISS"}): ${Y}`);this.method=$;this.requestId=Z;this.serverCode=J;this.serverMessage=Y;this.name="CodexRpcResponseError"}};I1=class I1 extends RG{provider="codex";tokenSourceId;launchKind;proc;stdoutBuf="";stderrBuf="";requestCounter=0;pending=new Map;serverRequests=new Map;alive=!0;expectedExit=!1;exitEventEmitted=!1;childExitCode=null;childExitSignal=null;exitPromise;resolveExit;opts;readyPromise=null;initializePromise=null;conversationResumable=!1;conversationRolloutPath=null;conversationMaterializationVerification=null;conversationMaterializationRetrySource=null;lastConversationMaterializationFailure=null;currentTurnId=null;turnStartGeneration=0;turnStartOwner=null;turnStartOwnersByTurnId=new Map;finishedTurnIds=new Set;capacityRetryTimer=null;capacityRetryCount=0;capacityRetryHasStarted=!1;capacityRetryEnabled=!0;turnError=null;rolloutFilePath=null;rolloutReadOffset=0;rolloutLineRemainder="";rolloutDecoder=new GJ("utf8");emittedImageGenerationIds=new Set;collabAgentNames=new Map;collabAgentSettled=new Set;collabAgentWasActive=new Set;collabAgentSummaries=new Map;sessionId=null;lastAssistantUuid=null;lastCompletedTurnId=null;lastModel=null;lastEffort=null;lastUsage=null;lastTotalUsage=null;lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:null,subtype:null,is_error:!1};lastContextWindow=null;lastContextTokens=null;turnRetry=null;constructor($){super();this.on("error",()=>{}),this.exitPromise=new Promise((H)=>{this.resolveExit=H}),this.opts=$,this.tokenSourceId=$.tokenSourceId??null,this.launchKind=($.launch??{kind:"fresh"}).kind;let Z=y2(),J=CG($.allowDelegation!==!1);_(`codex-process: spawn ${Z} app-server (cwd=${$.workDir})`);let Y={...process.env,NPM_CONFIG_LOGLEVEL:"error",PATH:OG(),...v.codex.env,...$.hostEnv??{}},Q=$.transformEnv?$.transformEnv(Y):Y;this.proc=UG(Z,J,bG($.workDir,Q)),this.proc.stdout.on("data",(H)=>this.onStdout(H)),this.proc.stderr.on("data",(H)=>this.onStderr(H)),this.proc.stdin.on("error",(H)=>this.handleStdinError(H)),this.proc.on("exit",(H,W)=>this.handleChildExit(H,W)),this.proc.on("close",(H,W)=>this.handleChildClose(H,W)),this.proc.on("error",(H)=>this.handleChildProcessError(H))}handleStdinError($){let Z=$ instanceof Error?$:Error(String($));if(_(`codex-process: stdin failed: ${Z.message}`),!this.expectedExit)this.emit("error",Z)}handleChildExit($,Z){if(!this.alive){_(`codex-process: duplicate exit ignored code=${$} signal=${Z}`);return}this.alive=!1,this.cancelCapacityRetry(),this.childExitCode=$,this.childExitSignal=Z,_(`codex-process: OS exit code=${$} signal=${Z}; awaiting stdio close`)}handleChildClose($,Z){this.alive=!1,this.cancelCapacityRetry(),this.flushStdoutTail(),this.flushStderrTail(),this.rejectPendingRequests((H,W)=>Error(`codex app-server closed before ${W.method} response (id=${H})`)),this.serverRequests.clear();let J=$??this.childExitCode,Y=Z??this.childExitSignal,Q=this.conversationMaterializationBarrier();if(Q){Q.then(()=>this.emitProcessExit(J,Y),()=>this.emitProcessExit(J,Y));return}this.emitProcessExit(J,Y)}handleChildProcessError($){_(`codex-process: child process error: ${$}`),this.rejectPendingRequests((Y,Q)=>Error(`codex app-server process failed before ${Q.method} response (id=${Y}): ${$.message}`,{cause:$}));let Z=typeof this.proc.pid!=="number",J=!1;if(Z&&this.alive)this.alive=!1,this.cancelCapacityRetry(),this.serverRequests.clear(),J=!0;if(this.emit("error",$),J)_(`codex-process: spawn failed before pid assignment expected=${this.expectedExit}`),this.emitProcessExit(null,null)}emitProcessExit($,Z){if(this.exitEventEmitted)return;this.exitEventEmitted=!0,this.resolveExit(),_(`codex-process: exited code=${$} signal=${Z} expected=${this.expectedExit}`),this.emit("exit",{code:$,signal:Z,expected:this.expectedExit})}onStdout($){this.stdoutBuf+=$.toString();let Z;while((Z=this.stdoutBuf.indexOf(`
|
|
40
|
+
`))>=0){let J=this.stdoutBuf.slice(0,Z).trim();if(this.stdoutBuf=this.stdoutBuf.slice(Z+1),!J)continue;let Y;try{Y=JSON.parse(J)}catch(Q){_(`codex-process: bad json: ${J.slice(0,200)} (${Q})`);continue}try{this.handleMessage(Y)}catch(Q){_(`codex-process: dispatch error: ${JSON.stringify(Y).slice(0,200)} (${Q})`)}}}flushStdoutTail(){if(!this.stdoutBuf)return;this.onStdout(Buffer.from(`
|
|
38
41
|
`))}onStderr($){this.stderrBuf+=$.toString();let Z;while((Z=this.stderrBuf.indexOf(`
|
|
39
|
-
`))>=0){let J=this.stderrBuf.slice(0,Z);if(this.stderrBuf=this.stderrBuf.slice(Z+1),J.trim())A(`codex-process[stderr]: ${J}`)}}flushStderrTail(){let $=this.stderrBuf;if(this.stderrBuf="",$.trim())A(`codex-process[stderr]: ${$}`)}handleMessage($){if(Object.prototype.hasOwnProperty.call($,"id")&&!$.method){let J=this.pending.get($.id);if(!J){A(`codex-process: response for unknown id=${$.id}`);return}if(this.pending.delete($.id),clearTimeout(J.timeout),$.error){let Y=typeof $.error?.code==="number"?$.error.code:null,Q=typeof $.error==="string"?$.error:typeof $.error?.message==="string"?$.error.message:JSON.stringify($.error);J.reject(new S2(J.method,$.id,Y,Q))}else J.resolve($.result);return}if(Object.prototype.hasOwnProperty.call($,"id")&&$.method){this.handleServerRequest($);return}if($.method){this.handleNotification($.method,$.params??{});return}let Z=U7($);if(Z){let J=this.withSessionId(Z);M7(Z.sourceMethod??"raw_message",$,J),this.emit("context_compacted",J);return}k0("RAW_MESSAGE",$),this.emit("raw",$)}handleNotification($,Z){if(this.isSubagentThread(Z)){if($==="thread/status/changed")this.handleThreadStatusChanged(Z);else if($==="item/started")this.handleSubagentItemStarted(Z);else if($==="item/completed")this.handleSubagentItemCompleted(Z);return}let J=R7($,Z);if(J){let Y=this.withSessionId(J);M7($,Z,Y),this.emit("context_compacted",Y);return}switch($){case"thread/started":{let Y=Z.thread;if(Y?.id)this.sessionId=Y.id;return}case"thread/settings/updated":{let Y=Z.threadSettings;if(typeof Y?.model==="string")this.lastModel=Y.model;if(v0(Y?.effort))this.lastEffort=Y.effort;return}case"thread/tokenUsage/updated":{let Y=b1(Z.tokenUsage?.last);if(Y)this.lastUsage=Y,this.lastResult.usage=this.lastUsage;else A("codex-process: tokenUsage notification missing last breakdown");this.lastTotalUsage=b1(Z.tokenUsage?.total);let Q=Z.tokenUsage?.modelContextWindow;if(typeof Q==="number"&&Q>0)this.lastContextWindow=Q;this.emit("token_usage",{usage:this.lastUsage,totalUsage:this.lastTotalUsage,contextWindow:this.lastContextWindow,threadId:Z.threadId,turnId:Z.turnId});return}case"turn/started":{if(typeof Z.threadId!=="string"||Z.threadId!==this.sessionId){k0("TURN_STARTED_THREAD_MISMATCH",{method:$,params:Z});return}this.recordTurnStarted(Z.turn,Z.threadId,"turn/started notification"),this.markConversationMaterialized("turn/started notification");return}case"turn/completed":{if(typeof Z.threadId!=="string"||Z.threadId!==this.sessionId){k0("TURN_COMPLETED_THREAD_MISMATCH",{method:$,params:Z});return}let Y=Z.turn??{},Q=typeof Y.id==="string"&&Y.id?Y.id:null;if(Q){if(this.finishedTurnIds?.has(Q)){A(`codex-process: duplicate turn/completed ignored turn=${Q}`);return}if(this.currentTurnId&&this.currentTurnId!==Q){this.markTurnStartTerminal(Q),this.rememberFinishedTurn(Q),A(`codex-process: stale turn/completed ignored turn=${Q} current=${this.currentTurnId}`);return}this.flushRolloutImageGenerations(),this.markConversationMaterialized("turn/completed notification"),this.markTurnStartTerminal(Q),this.rememberFinishedTurn(Q)}else k0("TURN_COMPLETED_MISSING_ID",{method:$,params:Z});let H=Y.status,W=Y.error??(H==="failed"&&this.turnError&&this.turnError.turnId===Q?this.turnError.error:null);this.turnError=null;let X=H==="failed"||!!W,V=H==="completed"&&!X&&!!Q;if(this.lastCompletedTurnId=V?Q:null,this.currentTurnId=null,H==="failed"&&Q&&KJ(W?.message)&&this.scheduleCapacityRetry(W.message,EG))return;this.cancelCapacityRetry(),this.capacityRetryCount=0,this.capacityRetryHasStarted=!1;let z=X?W?.type??W?.message??"failed":"success";this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:typeof Y.durationMs==="number"?Y.durationMs:null,num_turns:1,usage:this.lastUsage,subtype:z,is_error:X},this.emit("result",{subtype:z,is_error:X,...X&&typeof W?.message==="string"?{error:W.message}:{},duration_ms:this.lastResult.duration_ms,usage:this.lastUsage,turn_id:Q,checkpoint:V&&this.sessionId?{provider:"codex",kind:"turn",id:Q,source:{provider:"codex",sessionId:this.sessionId,cwd:this.opts.workDir}}:null});return}case"turn/plan/updated":{this.emit("turn_plan_updated",Z);return}case"item/plan/delta":{this.emit("plan_delta",Z);return}case"thread/goal/updated":{if(Z.goal)this.emit("thread_goal_updated",Z.goal);else A("codex-process: thread/goal/updated missing goal");return}case"thread/goal/cleared":{this.emit("thread_goal_cleared",Z);return}case"thread/status/changed":{this.handleThreadStatusChanged(Z);return}case"item/agentMessage/delta":{if(typeof Z.delta==="string"&&Z.delta.length>0)this.emit("assistant_text",{uuid:Z.itemId,text:Z.delta,parentToolUseId:null});else k0("AGENT_MESSAGE_DELTA_EMPTY",{method:$,params:Z});return}case"item/started":{this.handleItemStarted(Z);return}case"item/completed":{this.handleItemCompleted(Z);return}case"mcpServer/startupStatus/updated":{A(`codex-process: mcp ${Z.name} ${Z.status}${Z.error?`: ${Z.error}`:""}`);return}case"account/rateLimits/updated":{this.emit("rate_limits_updated",Z.rateLimits);return}case"configWarning":case"warning":case"guardianWarning":case"deprecationNotice":{A(`codex-process: ${$}: ${Z.summary??Z.message??JSON.stringify(Z).slice(0,200)}`);return}case"error":{A(`codex-process: server error: ${JSON.stringify(Z).slice(0,500)}`);let Y=Z.error??Z;if(typeof Z.turnId==="string"&&Z.threadId===this.sessionId&&!this.finishedTurnIds?.has(Z.turnId)&&(!this.currentTurnId||this.currentTurnId===Z.turnId))this.turnError={turnId:Z.turnId,error:Y};this.emit("error",Error(Y.message??Y.summary??"codex app-server error"));return}}k0("NOTIFICATION",{method:$,params:Z}),this.emit("raw",{method:$,params:Z})}handleItemStarted($){let Z=$?.item;if(!Z?.id){k0("ITEM_STARTED_MISSING_ID",{method:"item/started",params:$});return}if(this.feedCollabItem(Z,"started"))return;let J=x7(Z,this.opts.workDir);if(!J){k0("ITEM_STARTED_UNMAPPED",{method:"item/started",params:$});return}this.emit("tool_use",{id:Z.id,name:J.name,input:J.input})}handleSubagentItemStarted($){let Z=$?.item;if(!Z?.id)return;if(this.feedCollabItem(Z,"started"))return;this.emitSubagentStep(Z,"started",$)}handleSubagentItemCompleted($){let Z=$?.item;if(!Z?.id)return;if(Z.type==="agentMessage"){let J=typeof Z.text==="string"?Z.text:"";if(J){let Y=typeof $?.threadId==="string"?$.threadId:"";this.collabAgentSummaries.set(Y,J)}return}if(this.feedCollabItem(Z,"completed"))return;this.emitSubagentStep(Z,"completed",$)}handleItemCompleted($){let Z=$?.item;if(!Z?.id){k0("ITEM_COMPLETED_MISSING_ID",{method:"item/completed",params:$});return}if(Z.type==="agentMessage"){this.lastAssistantUuid=Z.id,this.emit("assistant_block_stop",{index:Z.id,parentToolUseId:null});return}if(this.feedCollabItem(Z,"completed"))return;let J=LJ(Z,this.opts.workDir,this.sessionId??void 0);if(!J){k0("ITEM_COMPLETED_UNMAPPED",{method:"item/completed",params:$});return}if(this.emit("tool_result",{tool_use_id:Z.id,content:J.output,is_error:J.isError,...Z.type==="imageGeneration"?{input:k7(Z)}:{}}),Z.type==="imageGeneration")this.emittedImageGenerationIds.add(Z.id)}isSubagentThread($){let Z=typeof $?.threadId==="string"?$.threadId:"";return!!this.sessionId&&!!Z&&Z!==this.sessionId}handleThreadStatusChanged($){let Z=typeof $?.threadId==="string"?$.threadId:"",J=$?.status?.type;if(!Z||typeof J!=="string")return;if(!this.collabAgentNames?.has(Z))return;if(J==="active"){if(this.collabAgentWasActive.add(Z),this.collabAgentSettled.has(Z))this.collabAgentSettled.delete(Z),this.emit("bg_task_started",{task_id:Z,task_type:"local_agent",description:this.collabAgentNames.get(Z)??B0(Z)}),this.emit("bg_task_updated",{task_id:Z,patch:{is_backgrounded:!0}});this.emit("bg_task_updated",{task_id:Z,patch:{status:"running"}});return}if(J==="idle"||J==="systemError"){if(!this.collabAgentWasActive.has(Z))return;if(this.collabAgentSettled.has(Z))return;this.collabAgentSettled.add(Z),this.emit("bg_task_settled",{task_id:Z,status:J==="systemError"?"failed":"completed",summary:this.collabAgentSummaries.get(Z)??void 0})}}emitSubagentStep($,Z,J){let Y=typeof J?.threadId==="string"?J.threadId:"",Q=Z==="started"?x7($,this.opts.workDir):LJ($,this.opts.workDir,this.sessionId??void 0);if(!Q)return;let H="output"in Q&&typeof Q.output==="string"?Q.output:void 0;this.emit("subagent_step",{thread_id:Y,item_id:$.id,tool:Q.name,phase:Z,brief:fG(Q.name,Q.input,H)})}feedCollabItem($,Z){if($.type==="subAgentActivity"){let J=typeof $.agentThreadId==="string"?$.agentThreadId:"";if(!J)return!0;if($.kind==="started"&&!this.collabAgentNames.has(J)){let Y=d4($.agentPath,J);this.collabAgentNames.set(J,Y),this.emit("bg_task_started",{task_id:J,task_type:"local_agent",description:Y}),this.emit("bg_task_updated",{task_id:J,patch:{is_backgrounded:!0}})}else if($.kind==="started"){let Y=this.collabAgentNames.get(J),Q=d4($.agentPath,J);if(Y!==Q&&!this.collabAgentSettled.has(J))this.collabAgentNames.set(J,Q),this.emit("bg_task_started",{task_id:J,task_type:"local_agent",description:Q})}else if($.kind==="interrupted")this.emit("bg_task_updated",{task_id:J,patch:{status:"paused"}});return!0}if($.type==="collabAgentToolCall"){let J=$.agentsStates;if(J&&typeof J==="object")for(let[Y,Q]of Object.entries(J))this.translateAgentState(Y,Q,$);if($.tool==="closeAgent"&&Z==="completed"&&$.status!=="failed"){let Y=FJ($);for(let Q of Y){if(this.collabAgentSettled.has(Q))continue;if(this.collabAgentSettled.add(Q),!this.collabAgentNames.has(Q))this.collabAgentNames.set(Q,d4(null,Q));this.emit("bg_task_settled",{task_id:Q,status:"stopped"})}}if($.tool==="spawnAgent"){if(Z==="started")this.emit("tool_use",{id:$.id,name:"Agent",input:{tool:"spawnAgent",prompt:DJ($.prompt),description:vG($),model:typeof $.model==="string"?$.model:void 0}});else if($.status!=="inProgress")this.emit("tool_result",{tool_use_id:$.id,content:hG($),is_error:$.status==="failed"})}return!0}return!1}translateAgentState($,Z,J){let Y=Z?.status;if(typeof Y!=="string")return;if(this.collabAgentSettled.has($)){if(Y!=="running"&&Y!=="pendingInit"){if(Y==="errored"||Y==="shutdown"||Y==="notFound"||Y==="interrupted")this.emit("bg_task_updated",{task_id:$,patch:{status:Y==="errored"?"failed":"killed",error:typeof Z?.message==="string"&&Z.message?Z.message:void 0}});return}this.collabAgentSettled.delete($);let H=this.collabAgentNames.get($)??d4(null,$);this.emit("bg_task_started",{task_id:$,task_type:"local_agent",description:H}),this.emit("bg_task_updated",{task_id:$,patch:{is_backgrounded:!0}})}if(!this.collabAgentNames.has($)){this.collabAgentNames.set($,"子 agent");let W={task_id:$,task_type:"local_agent",description:"子 agent",prompt:DJ(J.prompt)};this.emit("bg_task_started",W);let X={task_id:$,patch:{is_backgrounded:!0}};this.emit("bg_task_updated",X)}if(Y==="running"||Y==="pendingInit"||Y==="interrupted"){let H={task_id:$,patch:{status:Y==="pendingInit"?"pending":Y==="interrupted"?"paused":"running"}};this.emit("bg_task_updated",H);return}if(this.collabAgentSettled.size>=5000)this.collabAgentSettled.clear();this.collabAgentSettled.add($);let Q={task_id:$,status:Y==="completed"?"completed":Y==="errored"?"failed":"stopped",summary:typeof Z?.message==="string"&&Z.message?Z.message:void 0};this.emit("bg_task_settled",Q)}primeRolloutImageGenerationScan(){if(this.rolloutFilePath=null,this.rolloutReadOffset=0,this.rolloutLineRemainder="",this.rolloutDecoder=new AJ("utf8"),this.emittedImageGenerationIds.clear(),!this.sessionId)return;let $=BJ(this.sessionId);if(!$)return;this.rolloutFilePath=$;try{this.rolloutReadOffset=n4($).size,A(`codex-process: image generation rollout scan primed ${$} offset=${this.rolloutReadOffset}`)}catch(Z){A(`codex-process: image generation rollout stat failed ${$}: ${Z instanceof Error?Z.message:Z}`),this.rolloutFilePath=null,this.rolloutReadOffset=0}}flushRolloutImageGenerations(){if(!this.sessionId)return;let $=this.rolloutFilePath??BJ(this.sessionId);if(!$){A(`codex-process: image generation rollout file not found for thread=${this.sessionId}`);return}this.rolloutFilePath=$;let Z;try{let Q=n4($).size;if(Q<=this.rolloutReadOffset)return;let H=Q-this.rolloutReadOffset;Z=Buffer.allocUnsafe(H);let W=BG($,"r"),X=0;try{while(X<H){let V=LG(W,Z,X,H-X,this.rolloutReadOffset+X);if(V===0)break;X+=V}}finally{AG(W)}Z=Z.subarray(0,X),this.rolloutReadOffset+=X}catch(Q){A(`codex-process: image generation rollout read failed ${$}: ${Q instanceof Error?Q.message:Q}`);return}let J=this.rolloutLineRemainder+this.rolloutDecoder.write(Z),Y=J.split(/\r?\n/);this.rolloutLineRemainder=J.endsWith(`
|
|
40
|
-
`)?"":Y.pop()??"";for(let Q of Y){if(!Q.trim())continue;let H;try{H=JSON.parse(Q)}catch(V){
|
|
41
|
-
`,(Y)=>{if(Y)J(Y)}),!0}catch(Y){return J(Y)}}request($,Z,J=
|
|
42
|
+
`))>=0){let J=this.stderrBuf.slice(0,Z);if(this.stderrBuf=this.stderrBuf.slice(Z+1),J.trim())_(`codex-process[stderr]: ${J}`)}}flushStderrTail(){let $=this.stderrBuf;if(this.stderrBuf="",$.trim())_(`codex-process[stderr]: ${$}`)}handleMessage($){if(Object.prototype.hasOwnProperty.call($,"id")&&!$.method){let J=this.pending.get($.id);if(!J){_(`codex-process: response for unknown id=${$.id}`);return}if(this.pending.delete($.id),clearTimeout(J.timeout),$.error){let Y=typeof $.error?.code==="number"?$.error.code:null,Q=typeof $.error==="string"?$.error:typeof $.error?.message==="string"?$.error.message:JSON.stringify($.error);J.reject(new b2(J.method,$.id,Y,Q))}else J.resolve($.result);return}if(Object.prototype.hasOwnProperty.call($,"id")&&$.method){this.handleServerRequest($);return}if($.method){this.handleNotification($.method,$.params??{});return}let Z=T7($);if(Z){let J=this.withSessionId(Z);U7(Z.sourceMethod??"raw_message",$,J),this.emit("context_compacted",J);return}k0("RAW_MESSAGE",$),this.emit("raw",$)}handleNotification($,Z){if(this.isSubagentThread(Z)){if($==="thread/status/changed")this.handleThreadStatusChanged(Z);else if($==="item/started")this.handleSubagentItemStarted(Z);else if($==="item/completed")this.handleSubagentItemCompleted(Z);return}let J=O7($,Z);if(J){let Y=this.withSessionId(J);U7($,Z,Y),this.emit("context_compacted",Y);return}switch($){case"thread/started":{let Y=Z.thread;if(Y?.id)this.sessionId=Y.id;return}case"thread/settings/updated":{let Y=Z.threadSettings;if(typeof Y?.model==="string")this.lastModel=Y.model;if(h0(Y?.effort))this.lastEffort=Y.effort;return}case"thread/tokenUsage/updated":{let Y=v1(Z.tokenUsage?.last);if(Y)this.lastUsage=Y,this.lastResult.usage=this.lastUsage;else _("codex-process: tokenUsage notification missing last breakdown");this.lastTotalUsage=v1(Z.tokenUsage?.total);let Q=Z.tokenUsage?.modelContextWindow;if(typeof Q==="number"&&Q>0)this.lastContextWindow=Q;this.emit("token_usage",{usage:this.lastUsage,totalUsage:this.lastTotalUsage,contextWindow:this.lastContextWindow,threadId:Z.threadId,turnId:Z.turnId});return}case"turn/started":{if(typeof Z.threadId!=="string"||Z.threadId!==this.sessionId){k0("TURN_STARTED_THREAD_MISMATCH",{method:$,params:Z});return}this.recordTurnStarted(Z.turn,Z.threadId,"turn/started notification"),this.markConversationMaterialized("turn/started notification");return}case"turn/completed":{if(typeof Z.threadId!=="string"||Z.threadId!==this.sessionId){k0("TURN_COMPLETED_THREAD_MISMATCH",{method:$,params:Z});return}let Y=Z.turn??{},Q=typeof Y.id==="string"&&Y.id?Y.id:null;if(Q){if(this.finishedTurnIds?.has(Q)){_(`codex-process: duplicate turn/completed ignored turn=${Q}`);return}if(this.currentTurnId&&this.currentTurnId!==Q){this.markTurnStartTerminal(Q),this.rememberFinishedTurn(Q),_(`codex-process: stale turn/completed ignored turn=${Q} current=${this.currentTurnId}`);return}this.flushRolloutImageGenerations(),this.markConversationMaterialized("turn/completed notification"),this.markTurnStartTerminal(Q),this.rememberFinishedTurn(Q)}else k0("TURN_COMPLETED_MISSING_ID",{method:$,params:Z});let H=Y.status,W=Y.error??(H==="failed"&&this.turnError&&this.turnError.turnId===Q?this.turnError.error:null);this.turnError=null;let X=H==="failed"||!!W,V=H==="completed"&&!X&&!!Q;if(this.lastCompletedTurnId=V?Q:null,this.currentTurnId=null,H==="failed"&&Q&&AJ(W?.message)&&this.scheduleCapacityRetry(W.message,kG))return;this.cancelCapacityRetry(),this.capacityRetryCount=0,this.capacityRetryHasStarted=!1;let z=X?W?.type??W?.message??"failed":"success";this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:typeof Y.durationMs==="number"?Y.durationMs:null,num_turns:1,usage:this.lastUsage,subtype:z,is_error:X},this.emit("result",{subtype:z,is_error:X,...X&&typeof W?.message==="string"?{error:W.message}:{},duration_ms:this.lastResult.duration_ms,usage:this.lastUsage,turn_id:Q,checkpoint:V&&this.sessionId?{provider:"codex",kind:"turn",id:Q,source:{provider:"codex",sessionId:this.sessionId,cwd:this.opts.workDir}}:null});return}case"turn/plan/updated":{this.emit("turn_plan_updated",Z);return}case"item/plan/delta":{this.emit("plan_delta",Z);return}case"thread/goal/updated":{if(Z.goal)this.emit("thread_goal_updated",Z.goal);else _("codex-process: thread/goal/updated missing goal");return}case"thread/goal/cleared":{this.emit("thread_goal_cleared",Z);return}case"thread/status/changed":{this.handleThreadStatusChanged(Z);return}case"item/agentMessage/delta":{if(typeof Z.delta==="string"&&Z.delta.length>0)this.emit("assistant_text",{uuid:Z.itemId,text:Z.delta,parentToolUseId:null});else k0("AGENT_MESSAGE_DELTA_EMPTY",{method:$,params:Z});return}case"item/started":{this.handleItemStarted(Z);return}case"item/completed":{this.handleItemCompleted(Z);return}case"mcpServer/startupStatus/updated":{_(`codex-process: mcp ${Z.name} ${Z.status}${Z.error?`: ${Z.error}`:""}`);return}case"account/rateLimits/updated":{this.emit("rate_limits_updated",Z.rateLimits);return}case"configWarning":case"warning":case"guardianWarning":case"deprecationNotice":{_(`codex-process: ${$}: ${Z.summary??Z.message??JSON.stringify(Z).slice(0,200)}`);return}case"error":{_(`codex-process: server error: ${JSON.stringify(Z).slice(0,500)}`);let Y=Z.error??Z;if(typeof Z.turnId==="string"&&Z.threadId===this.sessionId&&!this.finishedTurnIds?.has(Z.turnId)&&(!this.currentTurnId||this.currentTurnId===Z.turnId))this.turnError={turnId:Z.turnId,error:Y};this.emit("error",Error(Y.message??Y.summary??"codex app-server error"));return}}k0("NOTIFICATION",{method:$,params:Z}),this.emit("raw",{method:$,params:Z})}handleItemStarted($){let Z=$?.item;if(!Z?.id){k0("ITEM_STARTED_MISSING_ID",{method:"item/started",params:$});return}if(this.feedCollabItem(Z,"started"))return;let J=C7(Z,this.opts.workDir);if(!J){k0("ITEM_STARTED_UNMAPPED",{method:"item/started",params:$});return}this.emit("tool_use",{id:Z.id,name:J.name,input:J.input})}handleSubagentItemStarted($){let Z=$?.item;if(!Z?.id)return;if(this.feedCollabItem(Z,"started"))return;this.emitSubagentStep(Z,"started",$)}handleSubagentItemCompleted($){let Z=$?.item;if(!Z?.id)return;if(Z.type==="agentMessage"){let J=typeof Z.text==="string"?Z.text:"";if(J){let Y=typeof $?.threadId==="string"?$.threadId:"";this.collabAgentSummaries.set(Y,J)}return}if(this.feedCollabItem(Z,"completed"))return;this.emitSubagentStep(Z,"completed",$)}handleItemCompleted($){let Z=$?.item;if(!Z?.id){k0("ITEM_COMPLETED_MISSING_ID",{method:"item/completed",params:$});return}if(Z.type==="agentMessage"){this.lastAssistantUuid=Z.id,this.emit("assistant_block_stop",{index:Z.id,parentToolUseId:null});return}if(this.feedCollabItem(Z,"completed"))return;let J=LJ(Z,this.opts.workDir,this.sessionId??void 0);if(!J){k0("ITEM_COMPLETED_UNMAPPED",{method:"item/completed",params:$});return}if(this.emit("tool_result",{tool_use_id:Z.id,content:J.output,is_error:J.isError,...Z.type==="imageGeneration"?{input:b7(Z)}:{}}),Z.type==="imageGeneration")this.emittedImageGenerationIds.add(Z.id)}isSubagentThread($){let Z=typeof $?.threadId==="string"?$.threadId:"";return!!this.sessionId&&!!Z&&Z!==this.sessionId}handleThreadStatusChanged($){let Z=typeof $?.threadId==="string"?$.threadId:"",J=$?.status?.type;if(!Z||typeof J!=="string")return;if(!this.collabAgentNames?.has(Z))return;if(J==="active"){if(this.collabAgentWasActive.add(Z),this.collabAgentSettled.has(Z))this.collabAgentSettled.delete(Z),this.emit("bg_task_started",{task_id:Z,task_type:"local_agent",description:this.collabAgentNames.get(Z)??q0(Z)}),this.emit("bg_task_updated",{task_id:Z,patch:{is_backgrounded:!0}});this.emit("bg_task_updated",{task_id:Z,patch:{status:"running"}});return}if(J==="idle"||J==="systemError"){if(!this.collabAgentWasActive.has(Z))return;if(this.collabAgentSettled.has(Z))return;this.collabAgentSettled.add(Z),this.emit("bg_task_settled",{task_id:Z,status:J==="systemError"?"failed":"completed",summary:this.collabAgentSummaries.get(Z)??void 0})}}emitSubagentStep($,Z,J){let Y=typeof J?.threadId==="string"?J.threadId:"",Q=Z==="started"?C7($,this.opts.workDir):LJ($,this.opts.workDir,this.sessionId??void 0);if(!Q)return;let H="output"in Q&&typeof Q.output==="string"?Q.output:void 0;this.emit("subagent_step",{thread_id:Y,item_id:$.id,tool:Q.name,phase:Z,brief:gG(Q.name,Q.input,H)})}feedCollabItem($,Z){if($.type==="subAgentActivity"){let J=typeof $.agentThreadId==="string"?$.agentThreadId:"";if(!J)return!0;if($.kind==="started"&&!this.collabAgentNames.has(J)){let Y=r4($.agentPath,J);this.collabAgentNames.set(J,Y),this.emit("bg_task_started",{task_id:J,task_type:"local_agent",description:Y}),this.emit("bg_task_updated",{task_id:J,patch:{is_backgrounded:!0}})}else if($.kind==="started"){let Y=this.collabAgentNames.get(J),Q=r4($.agentPath,J);if(Y!==Q&&!this.collabAgentSettled.has(J))this.collabAgentNames.set(J,Q),this.emit("bg_task_started",{task_id:J,task_type:"local_agent",description:Q})}else if($.kind==="interrupted")this.emit("bg_task_updated",{task_id:J,patch:{status:"paused"}});return!0}if($.type==="collabAgentToolCall"){let J=$.agentsStates;if(J&&typeof J==="object")for(let[Y,Q]of Object.entries(J))this.translateAgentState(Y,Q,$);if($.tool==="closeAgent"&&Z==="completed"&&$.status!=="failed"){let Y=jJ($);for(let Q of Y){if(this.collabAgentSettled.has(Q))continue;if(this.collabAgentSettled.add(Q),!this.collabAgentNames.has(Q))this.collabAgentNames.set(Q,r4(null,Q));this.emit("bg_task_settled",{task_id:Q,status:"stopped"})}}if($.tool==="spawnAgent"){if(Z==="started")this.emit("tool_use",{id:$.id,name:"Agent",input:{tool:"spawnAgent",prompt:qJ($.prompt),description:cG($),model:typeof $.model==="string"?$.model:void 0}});else if($.status!=="inProgress")this.emit("tool_result",{tool_use_id:$.id,content:mG($),is_error:$.status==="failed"})}return!0}return!1}translateAgentState($,Z,J){let Y=Z?.status;if(typeof Y!=="string")return;if(this.collabAgentSettled.has($)){if(Y!=="running"&&Y!=="pendingInit"){if(Y==="errored"||Y==="shutdown"||Y==="notFound"||Y==="interrupted")this.emit("bg_task_updated",{task_id:$,patch:{status:Y==="errored"?"failed":"killed",error:typeof Z?.message==="string"&&Z.message?Z.message:void 0}});return}this.collabAgentSettled.delete($);let H=this.collabAgentNames.get($)??r4(null,$);this.emit("bg_task_started",{task_id:$,task_type:"local_agent",description:H}),this.emit("bg_task_updated",{task_id:$,patch:{is_backgrounded:!0}})}if(!this.collabAgentNames.has($)){this.collabAgentNames.set($,"子 agent");let W={task_id:$,task_type:"local_agent",description:"子 agent",prompt:qJ(J.prompt)};this.emit("bg_task_started",W);let X={task_id:$,patch:{is_backgrounded:!0}};this.emit("bg_task_updated",X)}if(Y==="running"||Y==="pendingInit"||Y==="interrupted"){let H={task_id:$,patch:{status:Y==="pendingInit"?"pending":Y==="interrupted"?"paused":"running"}};this.emit("bg_task_updated",H);return}if(this.collabAgentSettled.size>=5000)this.collabAgentSettled.clear();this.collabAgentSettled.add($);let Q={task_id:$,status:Y==="completed"?"completed":Y==="errored"?"failed":"stopped",summary:typeof Z?.message==="string"&&Z.message?Z.message:void 0};this.emit("bg_task_settled",Q)}primeRolloutImageGenerationScan(){if(this.rolloutFilePath=null,this.rolloutReadOffset=0,this.rolloutLineRemainder="",this.rolloutDecoder=new GJ("utf8"),this.emittedImageGenerationIds.clear(),!this.sessionId)return;let $=KJ(this.sessionId);if(!$)return;this.rolloutFilePath=$;try{this.rolloutReadOffset=t4($).size,_(`codex-process: image generation rollout scan primed ${$} offset=${this.rolloutReadOffset}`)}catch(Z){_(`codex-process: image generation rollout stat failed ${$}: ${Z instanceof Error?Z.message:Z}`),this.rolloutFilePath=null,this.rolloutReadOffset=0}}flushRolloutImageGenerations(){if(!this.sessionId)return;let $=this.rolloutFilePath??KJ(this.sessionId);if(!$){_(`codex-process: image generation rollout file not found for thread=${this.sessionId}`);return}this.rolloutFilePath=$;let Z;try{let Q=t4($).size;if(Q<=this.rolloutReadOffset)return;let H=Q-this.rolloutReadOffset;Z=Buffer.allocUnsafe(H);let W=PG($,"r"),X=0;try{while(X<H){let V=FG(W,Z,X,H-X,this.rolloutReadOffset+X);if(V===0)break;X+=V}}finally{LG(W)}Z=Z.subarray(0,X),this.rolloutReadOffset+=X}catch(Q){_(`codex-process: image generation rollout read failed ${$}: ${Q instanceof Error?Q.message:Q}`);return}let J=this.rolloutLineRemainder+this.rolloutDecoder.write(Z),Y=J.split(/\r?\n/);this.rolloutLineRemainder=J.endsWith(`
|
|
43
|
+
`)?"":Y.pop()??"";for(let Q of Y){if(!Q.trim())continue;let H;try{H=JSON.parse(Q)}catch(V){_(`codex-process: image generation rollout JSON parse failed ${$}: ${V instanceof Error?V.message:V}`);continue}let W=H?.payload,X=W?.type;if(X!=="image_generation_end"&&X!=="image_generation_call")continue;this.emitRolloutImageGeneration(W)}}emitRolloutImageGeneration($){let Z=typeof $?.call_id==="string"?$.call_id:typeof $?.id==="string"?$.id:"";if(!Z||this.emittedImageGenerationIds.has(Z))return;let J=DJ($,this.sessionId??void 0);if(!J)return;let Y=$?.status==="failed",Q=$?.status==="generating"&&zJ(J)?"completed":$?.status;this.emittedImageGenerationIds.add(Z),this.emit("tool_use",{id:Z,name:"ImageGeneration",input:b7({...$,status:Q})}),this.emit("tool_result",{tool_use_id:Z,content:J,is_error:Y})}withSessionId($){let Z=$.sessionId??this.sessionId??void 0;return Z?{...$,sessionId:Z}:$}handleServerRequest($){let Z=String($.id);switch(this.serverRequests.set(Z,{id:$.id,method:$.method,params:$.params}),$.method){case"item/commandExecution/requestApproval":{let J=$.params??{};this.emit("can_use_tool",{request_id:Z,tool_name:"Bash",input:{command:J.command,cwd:J.cwd,reason:J.reason},tool_use_id:J.itemId});return}case"item/fileChange/requestApproval":{let J=$.params??{};this.emit("can_use_tool",{request_id:Z,tool_name:"FileChange",input:{reason:J.reason,grantRoot:J.grantRoot},tool_use_id:J.itemId});return}case"item/tool/requestUserInput":{let J=$.params??{},Y={questions:(J.questions??[]).map((Q)=>({id:Q.id,header:Q.header,question:Q.question,options:Array.isArray(Q.options)&&Q.options.length?Q.options.map((H)=>({label:H.label,description:H.description})):[{label:"自定义回答",description:Q.isSecret?"请直接在群里回复":"可直接在群里回复"}]}))};this.emit("tool_use",{id:J.itemId,name:"AskUserQuestion",input:Y}),this.emit("can_use_tool",{request_id:Z,tool_name:"AskUserQuestion",input:Y,tool_use_id:J.itemId});return}case"item/permissions/requestApproval":{let J=$.params??{};this.emit("can_use_tool",{request_id:Z,tool_name:"PermissionProfile",input:{cwd:J.cwd,reason:J.reason,permissions:J.permissions},tool_use_id:J.itemId});return}case"item/tool/call":{let J=$.params??{};this.emit("tool_use",{id:J.callId,name:J.namespace?`${J.namespace}.${J.tool}`:J.tool,input:J.arguments}),this.respond(Z,{contentItems:[{type:"inputText",text:"Lodestar does not implement this dynamic tool."}],success:!1});return}case"account/chatgptAuthTokens/refresh":case"attestation/generate":case"applyPatchApproval":case"execCommandApproval":default:k0("SERVER_REQUEST_UNSUPPORTED",$),this.respondError(Z,`unsupported server request: ${$.method}`)}}write($,Z){let J=(Y)=>{let Q=Y instanceof Error?Y:Error(String(Y));return _(`codex-process: stdin write failed: ${Q.message}`),Z?.(Q),!1};if(!this.alive)return J(Error(`write to dead process: ${JSON.stringify($).slice(0,200)}`));if(this.proc.stdin.destroyed||this.proc.stdin.writableEnded||!this.proc.stdin.writable)return J(Error("stdin is not writable"));try{return this.proc.stdin.write(JSON.stringify($)+`
|
|
44
|
+
`,(Y)=>{if(Y)J(Y)}),!0}catch(Y){return J(Y)}}request($,Z,J=EG){let Y=++this.requestCounter;return new Promise((Q,H)=>{let W=setTimeout(()=>{let V=this.pending.get(Y);if(!V)return;this.pending.delete(Y),V.reject(Error(`codex app-server ${$} request timed out after ${J}ms (id=${Y})`))},Math.max(0,J)),X={resolve:Q,reject:H,method:$,timeout:W};this.pending.set(Y,X),this.write({id:Y,method:$,params:Z},(V)=>{if(this.pending.get(Y)!==X)return;this.pending.delete(Y),clearTimeout(W),H(Error(`codex app-server ${$} request write failed (id=${Y}): ${V.message}`,{cause:V}))})})}rejectPendingRequests($){for(let[Z,J]of this.pending)clearTimeout(J.timeout),J.reject($(Z,J));this.pending.clear()}respond($,Z){let J=String($),Y=this.serverRequests.get(J);this.serverRequests.delete(J),this.write({id:Y?.id??$,result:Z})}respondError($,Z){let J=String($),Y=this.serverRequests.get(J);this.serverRequests.delete(J),this.write({id:Y?.id??$,error:{code:-32601,message:Z}})}sendInitialize(){if(!this.readyPromise)this.readyPromise=this.initializeAndStartThread(),this.readyPromise.catch(($)=>{_(`codex-process: initialize failed: ${$}`),this.emit("error",$)})}initializationPromise(){if(!this.readyPromise)this.sendInitialize();return this.readyPromise}isConversationResumable(){return this.conversationResumable}conversationMaterializationBarrier(){return this.conversationMaterializationVerification?this.drainConversationMaterialization():null}conversationMaterializationFailure(){return this.lastConversationMaterializationFailure}async drainConversationMaterialization(){while(this.conversationMaterializationVerification){let $=this.conversationMaterializationVerification;try{await $}catch{}await Promise.resolve()}if(!this.conversationResumable&&this.lastConversationMaterializationFailure)throw this.lastConversationMaterializationFailure}async readRateLimits(){return await this.ensureInitialized(),this.request("account/rateLimits/read",{})}initializeParams(){return{clientInfo:{name:"lodestar",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}}async ensureInitialized(){if(!this.initializePromise)this.initializePromise=this.request("initialize",this.initializeParams()).then(()=>{if(!this.write({method:"initialized"}))throw Error("codex app-server initialized notification write failed")});await this.initializePromise}async initializeAndStartThread(){let $=this.conversationLaunch();await this.ensureInitialized();let Z=this.threadParams(),J,Y;if($.kind==="resume")J="thread/resume",Y=await this.request(J,{threadId:$.source.sessionId,...Z,excludeTurns:!0,persistExtendedHistory:!1});else if($.kind==="fork")J="thread/fork",Y=await this.request(J,{threadId:$.source.sessionId,...$.through?{lastTurnId:$.through.id}:{},...Z,excludeTurns:!0});else J="thread/start",Y=await this.request(J,{...Z,experimentalRawEvents:!1,persistExtendedHistory:!1});let Q=Y?.thread;if(typeof Q?.id!=="string"||!Q.id)throw Error(`codex app-server ${J} returned no thread.id`);let H=typeof Q.cwd==="string"?Q.cwd:typeof Y?.cwd==="string"?Y.cwd:null;if(H!==this.opts.workDir)throw Error(`codex app-server ${J} returned cwd=${H??"MISS"}, expected ${this.opts.workDir}`);if($.kind==="fork"&&Q.id===$.source.sessionId)throw Error(`codex app-server thread/fork returned source thread id ${Q.id}`);if($.kind==="resume"&&Q.id!==$.source.sessionId)throw Error(`codex app-server thread/resume returned thread id ${Q.id}, expected ${$.source.sessionId}`);let W=typeof Q.path==="string"&&Q.path?Q.path:null;if(!W||!zJ(W)||!W.endsWith(`${Q.id}.jsonl`))throw Error(`codex app-server ${J} returned invalid thread.path=${W??"MISS"}`);if(this.sessionId=Q.id,this.conversationRolloutPath=W,this.conversationResumable=!1,$.kind!=="fresh")await this.verifyConversationMaterialized(`${J} response`),this.conversationResumable=!0;if(Y?.model)this.lastModel=Y.model;if(h0(Y?.reasoningEffort))this.lastEffort=Y.reasoningEffort;else this.lastEffort=this.opts.effort??null;_(`codex-process: thread=${this.sessionId}`),this.primeRolloutImageGenerationScan(),this.emit("init",{session_id:this.sessionId,thread:Q})}markConversationMaterialized($){if(this.conversationResumable)return;if(!this.sessionId)throw Error(`codex ${$} arrived before thread initialization`);if(this.conversationMaterializationVerification){this.conversationMaterializationRetrySource=$;return}let Z=this.sessionId,J=this.verifyConversationMaterialized($);this.conversationMaterializationVerification=J,J.then(()=>{if(this.sessionId!==Z||this.conversationResumable)return;this.lastConversationMaterializationFailure=null,this.conversationResumable=!0,_(`codex-process: conversation materialized thread=${Z} source=${$}`),this.emit("conversation_materialized",{session_id:Z,source:$})},(Y)=>{let Q=Y instanceof Error?Y:Error(String(Y));this.lastConversationMaterializationFailure=Q,_(`codex-process: conversation materialization check failed thread=${Z} source=${$}: ${Q.message}`),this.emit("conversation_materialization_failed",{session_id:Z,path:this.conversationRolloutPath,source:$,error:Q})}).finally(()=>{if(this.conversationMaterializationVerification===J)this.conversationMaterializationVerification=null;let Y=this.conversationMaterializationRetrySource;if(this.conversationMaterializationRetrySource=null,!this.conversationResumable&&Y)this.markConversationMaterialized(Y)})}async verifyConversationMaterialized($){let Z=this.sessionId,J=this.conversationRolloutPath;if(!Z||!J)throw Error(`codex ${$} has no initialized rollout identity`);let Q=(await this.request("thread/read",{threadId:Z,includeTurns:!0},NG))?.thread;if(Q?.id!==Z||Q.cwd!==this.opts.workDir||Q.path!==J||!Array.isArray(Q.turns))throw Error(`codex ${$} thread/read returned an invalid materialized thread`);this.assertConversationRolloutMaterialized($)}assertConversationRolloutMaterialized($){let Z=this.conversationRolloutPath;if(!Z)throw Error(`codex ${$} has no authoritative rollout path`);let J;try{J=t4(Z)}catch(Y){throw Error(`codex ${$} rollout is not readable at ${Z}: ${Y instanceof Error?Y.message:Y}`,{cause:Y})}if(!J.isFile())throw Error(`codex ${$} rollout path is not a file: ${Z}`)}conversationLaunch(){let $=this.opts.launch??{kind:"fresh"};if(V0($,"codex",this.opts.workDir),$.kind!=="fresh"&&(typeof $.source.sessionId!=="string"||!$.source.sessionId))throw Error(`codex ${$.kind} launch requires a source session id`);if($.kind==="fork"&&$.through){if($.through.provider!=="codex"||$.through.kind!=="turn")throw Error("codex fork through checkpoint must be a codex turn checkpoint");if(typeof $.through.id!=="string"||!$.through.id)throw Error("codex fork through checkpoint requires a turn id")}return $}threadParams(){return{cwd:this.opts.workDir,runtimeWorkspaceRoots:[this.opts.workDir],approvalPolicy:"never",sandbox:"danger-full-access",config:{"features.default_mode_request_user_input":!0,...this.opts.allowDelegation===!1?{"features.multi_agent":!1}:{},...this.opts.effort?{model_reasoning_effort:this.opts.effort}:{}},...this.opts.model?{model:this.opts.model}:{},...this.opts.appendSystemPrompt?{developerInstructions:this.opts.appendSystemPrompt}:{},serviceName:this.opts.serviceName??"lodestar"}}sendUserText($,Z=[]){let J=Z.length?Z.map((Q)=>`[file: ${Q}]`).join(" ")+`
|
|
42
45
|
|
|
43
|
-
`:"";this.cancelCapacityRetry(),this.capacityRetryCount=0,this.capacityRetryHasStarted=!1,this.capacityRetryEnabled=!0,this.turnError=null;let Y=this.beginTurnStart(J+$);this.startTurn(J+$,Y).catch((Q)=>this.failTurnStart(Q,Y))}async listModels(){await this.ensureInitialized();let $=[],Z=null;do{let J=await this.request("model/list",{cursor:Z,limit:100,includeHidden:!1});if(!Array.isArray(J?.data))throw Error("model/list returned no data array");for(let Y of J.data){if(typeof Y?.model!=="string"||!Y.model)continue;$.push({id:typeof Y.id==="string"&&Y.id?Y.id:Y.model,model:Y.model,displayName:typeof Y.displayName==="string"&&Y.displayName?Y.displayName:Y.model,description:typeof Y.description==="string"?Y.description:"",hidden:Y.hidden===!0,isDefault:Y.isDefault===!0,supportedReasoningEfforts:xG(Y.supportedReasoningEfforts),defaultReasoningEffort:v0(Y.defaultReasoningEffort)?Y.defaultReasoningEffort:null})}Z=typeof J?.nextCursor==="string"&&J.nextCursor?J.nextCursor:null}while(Z);return $}async listConversations(){await this.ensureInitialized();let $=[],Z=new Set,J=null;do{let Y=await this.request("thread/list",{cursor:J,limit:100,sortKey:"updated_at",sortDirection:"desc",cwd:this.opts.workDir});if(!Array.isArray(Y?.data))throw Error("thread/list returned no data array");for(let H of Y.data){if(typeof H?.id!=="string"||!H.id||typeof H.preview!=="string"||typeof H.updatedAt!=="number"||!Number.isFinite(H.updatedAt)||typeof H.cwd!=="string"||H.cwd!==this.opts.workDir)throw Error("thread/list returned an invalid thread summary");let W=typeof H.status==="string"?H.status:typeof H.status?.type==="string"?H.status.type:void 0;if(x1("codex",H.id))continue;$.push({provider:"codex",sessionId:H.id,cwd:H.cwd,preview:H.preview,ts:H.updatedAt*1000,...W?{status:W}:{}})}let Q=Y?.nextCursor;if(Q!==null&&typeof Q!=="string")throw Error("thread/list returned an invalid nextCursor");if(Q&&Z.has(Q))throw Error(`thread/list repeated pagination cursor ${Q}`);if(Q)Z.add(Q);J=Q}while(J);return $}async readConversationRef($){if(!$.trim())throw Error("thread/read requires a session id");await this.ensureInitialized();let J=(await this.request("thread/read",{threadId:$,includeTurns:!1}))?.thread;if(J?.id!==$||typeof J.cwd!=="string")throw Error("thread/read returned an invalid conversation reference");return{provider:"codex",sessionId:$,cwd:J.cwd}}async setModelSettings($,Z){A("codex-process: model settings require a process restart")}async compactThread(){if(!this.readyPromise)throw Error("codex thread not initialized");if(await this.readyPromise,!this.sessionId)throw Error("codex thread not initialized");await this.request("thread/compact/start",{threadId:this.sessionId})}failTurnStart($,Z){if(!this.ownsTurnStartFailure(Z)){A(`codex-process: ignored stale turn/start failure generation=${Z.generation}`);return}this.turnStartOwner=null,Z.terminal=!0;let J=$ instanceof Error?$.message:String($);if(A(`codex-process: turn/start failed: ${J}`),$ instanceof S2&&$.method==="turn/start"&&KJ($.serverMessage)&&Z.inputText!==void 0&&this.scheduleCapacityRetry($.serverMessage,Z.inputText))return;this.cancelCapacityRetry(),this.capacityRetryCount=0,this.capacityRetryHasStarted=!1,this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:this.lastUsage,subtype:"codex_turn_start_failed",is_error:!0},this.currentTurnId=null,this.lastCompletedTurnId=null,this.emit("result",{subtype:this.lastResult.subtype,is_error:!0,duration_ms:null,usage:this.lastUsage,error:J})}recordTurnStarted($,Z,J,Y){let Q=typeof $?.id==="string"&&$.id?$.id:null;if(!Q)throw Error(`codex app-server ${J} returned no turn.id`);if(this.finishedTurnIds?.has(Q))return;let H=Y??this.turnStartOwner;if(H?.interrupted){if(this.rememberFinishedTurn(Q),this.turnStartOwner===H)this.turnStartOwner=null;this.interruptTurn(Q);return}this.confirmTurnStart(Q,Y);let W=this.currentTurnId!==Q;if(this.currentTurnId=Q,!W)return;let X=this.capacityRetryHasStarted&&(this.capacityRetryCount??0)>0;if(this.capacityRetryHasStarted=!0,this.capacityRetryTimer&&this.turnRetry){let V={...this.turnRetry,phase:"retrying",delayMs:0};this.cancelCapacityRetry(),this.emit("turn_retry",V)}this.turnRetry=null,this.lastCompletedTurnId=null,this.emit("turn_started",{turn_id:Q,thread_id:typeof Z==="string"&&Z?Z:this.sessionId,...X?{retry:!0}:{}})}beginTurnStart($){let Z={generation:(this.turnStartGeneration??0)+1,turnId:null,confirmed:!1,terminal:!1,inputText:$};return this.turnStartGeneration=Z.generation,this.turnStartOwner=Z,Z}confirmTurnStart($,Z){if(!this.turnStartOwnersByTurnId)this.turnStartOwnersByTurnId=new Map;let J=Z??this.turnStartOwnersByTurnId.get($)??this.turnStartOwner;if(!J)return;if(J.turnId&&J.turnId!==$)throw Error(`codex turn/start generation=${J.generation} changed turn id from ${J.turnId} to ${$}`);if(J.terminal)return;J.turnId=$,J.confirmed=!0,this.turnStartOwnersByTurnId.set($,J)}markTurnStartTerminal($){if(!this.turnStartOwnersByTurnId)this.turnStartOwnersByTurnId=new Map;let Z=this.turnStartOwnersByTurnId.get($);if(!Z&&this.turnStartOwner&&(!this.currentTurnId||this.currentTurnId===$))Z=this.turnStartOwner,this.confirmTurnStart($,Z);if(!Z)return;if(Z.confirmed=!0,Z.terminal=!0,this.turnStartOwnersByTurnId.delete($),this.turnStartOwner===Z)this.turnStartOwner=null}ownsTurnStartFailure($){return this.turnStartOwner===$&&!$.confirmed&&!$.terminal}rememberFinishedTurn($){if(!this.finishedTurnIds)this.finishedTurnIds=new Set;if(this.finishedTurnIds.add($),this.finishedTurnIds.size<=64)return;let Z=this.finishedTurnIds.values().next().value;if(typeof Z==="string")this.finishedTurnIds.delete(Z)}async startTurn($,Z){let J=Z??this.beginTurnStart($);this.lastCompletedTurnId=null;try{if(!this.readyPromise)this.sendInitialize();if(await this.readyPromise,J.interrupted||this.expectedExit||!this.alive)return;if(!this.sessionId)throw Error("codex thread not initialized");let Y=await this.request("turn/start",{threadId:this.sessionId,input:[{type:"text",text:$,text_elements:[]}],cwd:this.opts.workDir,runtimeWorkspaceRoots:[this.opts.workDir],approvalPolicy:"never",sandboxPolicy:{type:"dangerFullAccess"}});this.recordTurnStarted(Y?.turn,this.sessionId,"turn/start response",J)}catch(Y){if(!this.ownsTurnStartFailure(J)){A(`codex-process: ignored stale turn/start rejection generation=${J.generation}`);return}throw Y}}sendInterrupt(){this.capacityRetryEnabled=!1;let $=!!this.turnRetry&&!this.currentTurnId;this.cancelCapacityRetry();let Z=this.turnStartOwner,J=Z&&!Z.confirmed&&!Z.terminal;if(J)Z.interrupted=!0,Z.terminal=!0;if(this.currentTurnId)this.interruptTurn(this.currentTurnId);else if($||J)this.lastCompletedTurnId=null,this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:this.lastUsage,subtype:"interrupted",is_error:!1},this.emit("result",{...this.lastResult,checkpoint:null})}interruptTurn($){if(!this.sessionId)return;this.request("turn/interrupt",{threadId:this.sessionId,turnId:$}).catch((Z)=>A(`codex-process: interrupt failed: ${Z}`))}cancelCapacityRetry(){if(this.capacityRetryTimer)clearTimeout(this.capacityRetryTimer);this.capacityRetryTimer=null,this.turnRetry=null}scheduleCapacityRetry($,Z){if(!this.alive||this.expectedExit||!this.capacityRetryEnabled)return!1;if(this.capacityRetryTimer)return!0;let J=(this.capacityRetryCount??0)+1;this.capacityRetryCount=J;let Y=Math.min(OG*2**Math.min(J-1,4),TG),Q=this.turnStartGeneration??0,H={phase:"waiting",attempt:J,delayMs:Y,message:$};this.turnRetry=H,A(`codex-process: model capacity retry #${J} in ${Y}ms: ${$}`);let W=setTimeout(()=>{if(this.capacityRetryTimer!==W)return;if(this.capacityRetryTimer=null,!this.alive||this.expectedExit||!this.capacityRetryEnabled||this.currentTurnId||Q!==(this.turnStartGeneration??0))return;if(this.turnRetry={...H,phase:"retrying",delayMs:0},this.emit("turn_retry",this.turnRetry),!this.alive||this.expectedExit||!this.capacityRetryEnabled||Q!==(this.turnStartGeneration??0))return;let X=this.beginTurnStart(Z);this.startTurn(Z,X).catch((V)=>this.failTurnStart(V,X))},Y);return this.capacityRetryTimer=W,this.emit("turn_retry",H),!0}sendPermissionResponse($,Z,J){let Y=this.serverRequests.get(String($));if(!Y){A(`codex-process: permission response for unknown request ${$}`);return}let Q=Z==="allow";switch(Y.method){case"item/commandExecution/requestApproval":this.respond($,{decision:Q?"accept":"decline"});return;case"item/fileChange/requestApproval":this.respond($,{decision:Q?"accept":"decline"});return;case"item/permissions/requestApproval":if(Q)this.respond($,{permissions:Y.params?.permissions??{},scope:"session"});else this.respondError($,J?.denyMessage??"denied by user");return;case"item/tool/requestUserInput":{if(!Q){this.respondError($,J?.denyMessage??"denied by user");return}let H=J?.updatedInput?.answers??{},W={};for(let X of Y.params?.questions??[]){let V=H[X.question]??H[X.id];if(V!==void 0)W[X.id]={answers:[String(V)]}}this.respond($,{answers:W});return}default:k0("APPROVAL_RESPONSE_UNSUPPORTED",{requestId:$,method:Y.method,params:Y.params,decision:Z,payload:J}),this.respondError($,J?.denyMessage??"unsupported approval request")}}sendHookResponse($,Z={}){this.respond($,Z)}isAlive(){return!this.exitEventEmitted}async kill($=5000){if(this.capacityRetryEnabled=!1,this.cancelCapacityRetry(),!this.alive){if(await this.waitForExit($))return;throw Error(`codex app-server exited but stdio did not close within ${$}ms`)}this.expectedExit=!0,A(`codex-process: SIGTERM (timeout=${$}ms)`);let Z=[];if(this.sendSignal("SIGTERM",Z),await this.waitForExit($))return;if(A(`codex-process: SIGKILL (lifecycle not closed after ${$}ms)`),this.alive)this.sendSignal("SIGKILL",Z);if(await this.waitForExit($))return;let J=Z.length?`; ${Z.join("; ")}`:"",Y=Error(`codex app-server did not exit after SIGTERM and SIGKILL (${$}ms each)${J}`);throw A(`codex-process: kill failed: ${Y.message}`),Y}sendSignal($,Z){try{if(!this.proc.kill($)&&this.alive)Z.push(`${$} was not delivered`)}catch(J){Z.push(`${$} failed: ${J instanceof Error?J.message:String(J)}`)}}async waitForExit($){if(this.exitEventEmitted)return!0;return new Promise((Z)=>{let J=!1,Y=(H)=>{if(J)return;J=!0,clearTimeout(Q),Z(H)},Q=setTimeout(()=>Y(!1),Math.max(0,$));this.exitPromise.then(()=>Y(!0))})}}});function IG($){return $.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function b7($){let Z=[],J=/^(?: {0,3})(`{3,}|~{3,})[^\n]*(?:\n|$)/gm,Y=0;while(Y<$.length){J.lastIndex=Y;let X=J.exec($);if(!X)break;let V=X[1],z=new RegExp(`^(?: {0,3})${IG(V[0])}{${V.length},}[ \\t]*(?:\\n|$)`,"gm");z.lastIndex=X.index+X[0].length;let G=z.exec($),_=G?G.index+G[0].length:$.length;Z.push({start:X.index,end:_}),Y=_}let Q=[...Z],H=[],W=0;for(let X of Z){if(W<X.start)H.push({start:W,end:X.start});W=X.end}if(W<$.length)H.push({start:W,end:$.length});for(let X of H){let V=$.slice(X.start,X.end),z=/(`+)[^\n]*?\1/g,G;while((G=z.exec(V))!==null)Q.push({start:X.start+G.index,end:X.start+G.index+G[0].length})}return Q.sort((X,V)=>X.start-V.start)}function y7($,Z){if(!$)return $;let J=b7($);if(!J.length)return Z($);let Y="",Q=0;for(let H of J){if(H.start>Q)Y+=Z($.slice(Q,H.start));Y+=$.slice(H.start,H.end),Q=Math.max(Q,H.end)}if(Q<$.length)Y+=Z($.slice(Q));return Y}function gG($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function MJ($){return $.replace(/!\[([^\]]*)\]\(([^)]*)\)/g,(J,Y,Q)=>{let H=Q.trim();return Y.trim()?`\uD83D\uDDBC️ ${Y.trim()} (${H})`:`\uD83D\uDDBC️ ${H}`}).replace(/!\[/g,"\uD83D\uDDBC️ [")}function E$($){if(Array.isArray($))return $.map((Y)=>E$(Y));if($==null||typeof $!=="object")return $;let Z=$,J={};for(let[Y,Q]of Object.entries(Z))J[Y]=E$(Q);if(Z.tag==="markdown"&&typeof Z.content==="string")J.content=w7(Z.content);return J}function a($){return y7($,(Z)=>cG(MJ(gG(Z))))}function cG($){return $.replace(/\\\[([\s\S]*?)\\\]/g,(Z,J)=>`
|
|
46
|
+
`:"";this.cancelCapacityRetry(),this.capacityRetryCount=0,this.capacityRetryHasStarted=!1,this.capacityRetryEnabled=!0,this.turnError=null;let Y=this.beginTurnStart(J+$);this.startTurn(J+$,Y).catch((Q)=>this.failTurnStart(Q,Y))}async listModels(){await this.ensureInitialized();let $=[],Z=null;do{let J=await this.request("model/list",{cursor:Z,limit:100,includeHidden:!1});if(!Array.isArray(J?.data))throw Error("model/list returned no data array");for(let Y of J.data){if(typeof Y?.model!=="string"||!Y.model)continue;$.push({id:typeof Y.id==="string"&&Y.id?Y.id:Y.model,model:Y.model,displayName:typeof Y.displayName==="string"&&Y.displayName?Y.displayName:Y.model,description:typeof Y.description==="string"?Y.description:"",hidden:Y.hidden===!0,isDefault:Y.isDefault===!0,supportedReasoningEfforts:yG(Y.supportedReasoningEfforts),defaultReasoningEffort:h0(Y.defaultReasoningEffort)?Y.defaultReasoningEffort:null})}Z=typeof J?.nextCursor==="string"&&J.nextCursor?J.nextCursor:null}while(Z);return $}async listConversations(){await this.ensureInitialized();let $=[],Z=new Set,J=null;do{let Y=await this.request("thread/list",{cursor:J,limit:100,sortKey:"updated_at",sortDirection:"desc",cwd:this.opts.workDir});if(!Array.isArray(Y?.data))throw Error("thread/list returned no data array");for(let H of Y.data){if(typeof H?.id!=="string"||!H.id||typeof H.preview!=="string"||typeof H.updatedAt!=="number"||!Number.isFinite(H.updatedAt)||typeof H.cwd!=="string"||H.cwd!==this.opts.workDir)throw Error("thread/list returned an invalid thread summary");let W=typeof H.status==="string"?H.status:typeof H.status?.type==="string"?H.status.type:void 0;if(y1("codex",H.id))continue;$.push({provider:"codex",sessionId:H.id,cwd:H.cwd,preview:H.preview,ts:H.updatedAt*1000,...W?{status:W}:{}})}let Q=Y?.nextCursor;if(Q!==null&&typeof Q!=="string")throw Error("thread/list returned an invalid nextCursor");if(Q&&Z.has(Q))throw Error(`thread/list repeated pagination cursor ${Q}`);if(Q)Z.add(Q);J=Q}while(J);return $}async readConversationRef($){if(!$.trim())throw Error("thread/read requires a session id");await this.ensureInitialized();let J=(await this.request("thread/read",{threadId:$,includeTurns:!1}))?.thread;if(J?.id!==$||typeof J.cwd!=="string")throw Error("thread/read returned an invalid conversation reference");return{provider:"codex",sessionId:$,cwd:J.cwd}}async setModelSettings($,Z){_("codex-process: model settings require a process restart")}async compactThread(){if(!this.readyPromise)throw Error("codex thread not initialized");if(await this.readyPromise,!this.sessionId)throw Error("codex thread not initialized");await this.request("thread/compact/start",{threadId:this.sessionId})}failTurnStart($,Z){if(!this.ownsTurnStartFailure(Z)){_(`codex-process: ignored stale turn/start failure generation=${Z.generation}`);return}this.turnStartOwner=null,Z.terminal=!0;let J=$ instanceof Error?$.message:String($);if(_(`codex-process: turn/start failed: ${J}`),$ instanceof b2&&$.method==="turn/start"&&AJ($.serverMessage)&&Z.inputText!==void 0&&this.scheduleCapacityRetry($.serverMessage,Z.inputText))return;this.cancelCapacityRetry(),this.capacityRetryCount=0,this.capacityRetryHasStarted=!1,this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:this.lastUsage,subtype:"codex_turn_start_failed",is_error:!0},this.currentTurnId=null,this.lastCompletedTurnId=null,this.emit("result",{subtype:this.lastResult.subtype,is_error:!0,duration_ms:null,usage:this.lastUsage,error:J})}recordTurnStarted($,Z,J,Y){let Q=typeof $?.id==="string"&&$.id?$.id:null;if(!Q)throw Error(`codex app-server ${J} returned no turn.id`);if(this.finishedTurnIds?.has(Q))return;let H=Y??this.turnStartOwner;if(H?.interrupted){if(this.rememberFinishedTurn(Q),this.turnStartOwner===H)this.turnStartOwner=null;this.interruptTurn(Q);return}this.confirmTurnStart(Q,Y);let W=this.currentTurnId!==Q;if(this.currentTurnId=Q,!W)return;let X=this.capacityRetryHasStarted&&(this.capacityRetryCount??0)>0;if(this.capacityRetryHasStarted=!0,this.capacityRetryTimer&&this.turnRetry){let V={...this.turnRetry,phase:"retrying",delayMs:0};this.cancelCapacityRetry(),this.emit("turn_retry",V)}this.turnRetry=null,this.lastCompletedTurnId=null,this.emit("turn_started",{turn_id:Q,thread_id:typeof Z==="string"&&Z?Z:this.sessionId,...X?{retry:!0}:{}})}beginTurnStart($){let Z={generation:(this.turnStartGeneration??0)+1,turnId:null,confirmed:!1,terminal:!1,inputText:$};return this.turnStartGeneration=Z.generation,this.turnStartOwner=Z,Z}confirmTurnStart($,Z){if(!this.turnStartOwnersByTurnId)this.turnStartOwnersByTurnId=new Map;let J=Z??this.turnStartOwnersByTurnId.get($)??this.turnStartOwner;if(!J)return;if(J.turnId&&J.turnId!==$)throw Error(`codex turn/start generation=${J.generation} changed turn id from ${J.turnId} to ${$}`);if(J.terminal)return;J.turnId=$,J.confirmed=!0,this.turnStartOwnersByTurnId.set($,J)}markTurnStartTerminal($){if(!this.turnStartOwnersByTurnId)this.turnStartOwnersByTurnId=new Map;let Z=this.turnStartOwnersByTurnId.get($);if(!Z&&this.turnStartOwner&&(!this.currentTurnId||this.currentTurnId===$))Z=this.turnStartOwner,this.confirmTurnStart($,Z);if(!Z)return;if(Z.confirmed=!0,Z.terminal=!0,this.turnStartOwnersByTurnId.delete($),this.turnStartOwner===Z)this.turnStartOwner=null}ownsTurnStartFailure($){return this.turnStartOwner===$&&!$.confirmed&&!$.terminal}rememberFinishedTurn($){if(!this.finishedTurnIds)this.finishedTurnIds=new Set;if(this.finishedTurnIds.add($),this.finishedTurnIds.size<=64)return;let Z=this.finishedTurnIds.values().next().value;if(typeof Z==="string")this.finishedTurnIds.delete(Z)}async startTurn($,Z){let J=Z??this.beginTurnStart($);this.lastCompletedTurnId=null;try{if(!this.readyPromise)this.sendInitialize();if(await this.readyPromise,J.interrupted||this.expectedExit||!this.alive)return;if(!this.sessionId)throw Error("codex thread not initialized");let Y=await this.request("turn/start",{threadId:this.sessionId,input:[{type:"text",text:$,text_elements:[]}],cwd:this.opts.workDir,runtimeWorkspaceRoots:[this.opts.workDir],approvalPolicy:"never",sandboxPolicy:{type:"dangerFullAccess"}});this.recordTurnStarted(Y?.turn,this.sessionId,"turn/start response",J)}catch(Y){if(!this.ownsTurnStartFailure(J)){_(`codex-process: ignored stale turn/start rejection generation=${J.generation}`);return}throw Y}}sendInterrupt(){this.capacityRetryEnabled=!1;let $=!!this.turnRetry&&!this.currentTurnId;this.cancelCapacityRetry();let Z=this.turnStartOwner,J=Z&&!Z.confirmed&&!Z.terminal;if(J)Z.interrupted=!0,Z.terminal=!0;if(this.currentTurnId)this.interruptTurn(this.currentTurnId);else if($||J)this.lastCompletedTurnId=null,this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:this.lastUsage,subtype:"interrupted",is_error:!1},this.emit("result",{...this.lastResult,checkpoint:null})}interruptTurn($){if(!this.sessionId)return;this.request("turn/interrupt",{threadId:this.sessionId,turnId:$}).catch((Z)=>_(`codex-process: interrupt failed: ${Z}`))}cancelCapacityRetry(){if(this.capacityRetryTimer)clearTimeout(this.capacityRetryTimer);this.capacityRetryTimer=null,this.turnRetry=null}scheduleCapacityRetry($,Z){if(!this.alive||this.expectedExit||!this.capacityRetryEnabled)return!1;if(this.capacityRetryTimer)return!0;let J=(this.capacityRetryCount??0)+1;this.capacityRetryCount=J;let Y=Math.min(SG*2**Math.min(J-1,4),xG),Q=this.turnStartGeneration??0,H={phase:"waiting",attempt:J,delayMs:Y,message:$};this.turnRetry=H,_(`codex-process: model capacity retry #${J} in ${Y}ms: ${$}`);let W=setTimeout(()=>{if(this.capacityRetryTimer!==W)return;if(this.capacityRetryTimer=null,!this.alive||this.expectedExit||!this.capacityRetryEnabled||this.currentTurnId||Q!==(this.turnStartGeneration??0))return;if(this.turnRetry={...H,phase:"retrying",delayMs:0},this.emit("turn_retry",this.turnRetry),!this.alive||this.expectedExit||!this.capacityRetryEnabled||Q!==(this.turnStartGeneration??0))return;let X=this.beginTurnStart(Z);this.startTurn(Z,X).catch((V)=>this.failTurnStart(V,X))},Y);return this.capacityRetryTimer=W,this.emit("turn_retry",H),!0}sendPermissionResponse($,Z,J){let Y=this.serverRequests.get(String($));if(!Y){_(`codex-process: permission response for unknown request ${$}`);return}let Q=Z==="allow";switch(Y.method){case"item/commandExecution/requestApproval":this.respond($,{decision:Q?"accept":"decline"});return;case"item/fileChange/requestApproval":this.respond($,{decision:Q?"accept":"decline"});return;case"item/permissions/requestApproval":if(Q)this.respond($,{permissions:Y.params?.permissions??{},scope:"session"});else this.respondError($,J?.denyMessage??"denied by user");return;case"item/tool/requestUserInput":{if(!Q){this.respondError($,J?.denyMessage??"denied by user");return}let H=J?.updatedInput?.answers??{},W={};for(let X of Y.params?.questions??[]){let V=H[X.question]??H[X.id];if(V!==void 0)W[X.id]={answers:[String(V)]}}this.respond($,{answers:W});return}default:k0("APPROVAL_RESPONSE_UNSUPPORTED",{requestId:$,method:Y.method,params:Y.params,decision:Z,payload:J}),this.respondError($,J?.denyMessage??"unsupported approval request")}}sendHookResponse($,Z={}){this.respond($,Z)}isAlive(){return!this.exitEventEmitted}async kill($=5000){if(this.capacityRetryEnabled=!1,this.cancelCapacityRetry(),!this.alive){if(await this.waitForExit($))return;throw Error(`codex app-server exited but stdio did not close within ${$}ms`)}this.expectedExit=!0,_(`codex-process: SIGTERM (timeout=${$}ms)`);let Z=[];if(this.sendSignal("SIGTERM",Z),await this.waitForExit($))return;if(_(`codex-process: SIGKILL (lifecycle not closed after ${$}ms)`),this.alive)this.sendSignal("SIGKILL",Z);if(await this.waitForExit($))return;let J=Z.length?`; ${Z.join("; ")}`:"",Y=Error(`codex app-server did not exit after SIGTERM and SIGKILL (${$}ms each)${J}`);throw _(`codex-process: kill failed: ${Y.message}`),Y}sendSignal($,Z){try{if(!this.proc.kill($)&&this.alive)Z.push(`${$} was not delivered`)}catch(J){Z.push(`${$} failed: ${J instanceof Error?J.message:String(J)}`)}}async waitForExit($){if(this.exitEventEmitted)return!0;return new Promise((Z)=>{let J=!1,Y=(H)=>{if(J)return;J=!0,clearTimeout(Q),Z(H)},Q=setTimeout(()=>Y(!1),Math.max(0,$));this.exitPromise.then(()=>Y(!0))})}}});function uG($){return $.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function w7($){let Z=[],J=/^(?: {0,3})(`{3,}|~{3,})[^\n]*(?:\n|$)/gm,Y=0;while(Y<$.length){J.lastIndex=Y;let X=J.exec($);if(!X)break;let V=X[1],z=new RegExp(`^(?: {0,3})${uG(V[0])}{${V.length},}[ \\t]*(?:\\n|$)`,"gm");z.lastIndex=X.index+X[0].length;let G=z.exec($),A=G?G.index+G[0].length:$.length;Z.push({start:X.index,end:A}),Y=A}let Q=[...Z],H=[],W=0;for(let X of Z){if(W<X.start)H.push({start:W,end:X.start});W=X.end}if(W<$.length)H.push({start:W,end:$.length});for(let X of H){let V=$.slice(X.start,X.end),z=/(`+)[^\n]*?\1/g,G;while((G=z.exec(V))!==null)Q.push({start:X.start+G.index,end:X.start+G.index+G[0].length})}return Q.sort((X,V)=>X.start-V.start)}function f7($,Z){if(!$)return $;let J=w7($);if(!J.length)return Z($);let Y="",Q=0;for(let H of J){if(H.start>Q)Y+=Z($.slice(Q,H.start));Y+=$.slice(H.start,H.end),Q=Math.max(Q,H.end)}if(Q<$.length)Y+=Z($.slice(Q));return Y}function pG($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function FJ($){return $.replace(/!\[([^\]]*)\]\(([^)]*)\)/g,(J,Y,Q)=>{let H=Q.trim();return Y.trim()?`\uD83D\uDDBC️ ${Y.trim()} (${H})`:`\uD83D\uDDBC️ ${H}`}).replace(/!\[/g,"\uD83D\uDDBC️ [")}function S$($){if(Array.isArray($))return $.map((Y)=>S$(Y));if($==null||typeof $!=="object")return $;let Z=$,J={};for(let[Y,Q]of Object.entries(Z))J[Y]=S$(Q);if(Z.tag==="markdown"&&typeof Z.content==="string")J.content=v7(Z.content);return J}function r($){return f7($,(Z)=>lG(FJ(pG(Z))))}function lG($){return $.replace(/\\\[([\s\S]*?)\\\]/g,(Z,J)=>`
|
|
44
47
|
\`\`\`
|
|
45
48
|
${J.trim()}
|
|
46
49
|
\`\`\`
|
|
@@ -48,176 +51,176 @@ ${J.trim()}
|
|
|
48
51
|
\`\`\`
|
|
49
52
|
${J.trim()}
|
|
50
53
|
\`\`\`
|
|
51
|
-
`).replace(/\\\(([\s\S]*?)\\\)/g,(Z,J)=>`\`${J.trim()}\``).replace(/\$([^$\n]+)\$/g,(Z,J)=>/\\|\^|_|=/.test(J)?`\`${J.trim()}\``:Z)}function
|
|
52
|
-
`):JSON.stringify($))??"MISS").replace(/\s+/g," ").trim();return Z?`❌ ${Y.slice(0,80)}`:Y.slice(0,80)}function
|
|
53
|
-
`):"_(暂无执行记录)_")}function
|
|
54
|
-
`)}],Y=new Set([...Z,...Array.from($.matchAll(/\[file: ([^\]\r\n]+)\]/g),(H)=>H[1])]),Q=new Set([".png",".jpg",".jpeg",".webp",".gif"]);for(let H of Y){if(!Q.has(
|
|
54
|
+
`).replace(/\\\(([\s\S]*?)\\\)/g,(Z,J)=>`\`${J.trim()}\``).replace(/\$([^$\n]+)\$/g,(Z,J)=>/\\|\^|_|=/.test(J)?`\`${J.trim()}\``:Z)}function v7($){return f7($,FJ)}var R;var I0=S(()=>{R={userInput:"user_input",footer:"footer",taskBoardLive:"task_board_live",planLive:"plan_live",tool:($)=>`tool_${$}`,planUpdate:($)=>`plan_update_${$}`,goalUpdate:($)=>`goal_update_${$}`,contextCompact:($)=>`context_compact_${$}`,assistant:($)=>`assistant_${$}`,consoleCurrentModel:"console_current_model",consoleProjects:"console_projects",consoleHost:"console_host",consoleUsage:"console_usage",modelPanel:"model_panel",modelAgentGroup:($)=>`model_agent_${$}`,tasklistPanel:"tasklist_panel",agentIdentityPanel:"agent_id_panel",agentRunFooter:"agent_run_footer"}});function MJ($){let Z=2166136261;for(let J=0;J<$.length;J++)Z^=$.charCodeAt(J),Z=Math.imul(Z,16777619);return(Z>>>0).toString(36)}function iG($,Z){let J=$??"";if(J==="subagent"||J==="local_agent")return"subagent";if(J==="shell"||J==="local_bash"||J==="local_shell")return"shell";if(J==="monitor"||J==="local_monitor")return"monitor";if(J==="workflow"||J==="local_workflow")return"workflow";if(Z)return"subagent";return"unknown"}function RJ($){return $==="workflow"||$==="monitor"}function g0($){return $.status==="completed"||$.status==="failed"||$.status==="killed"}function J1($){return $.some((Z)=>!g0(Z))}function c7($,Z,J=Date.now()){let Y=iG(Z.task_type,Z.subagent_type),Q=$.active.some((X)=>X.id===Z.task_id),H=$.pending.some((X)=>X.id===Z.task_id);if(Q||H){let X=(V)=>({...V,type:Y,toolUseId:Z.tool_use_id??V.toolUseId,description:Z.description||V.description,subagentType:Z.subagent_type??V.subagentType,workflowName:Z.workflow_name??V.workflowName,prompt:Z.prompt??V.prompt});return{active:Q?$.active.map((V)=>V.id===Z.task_id?X(V):V):$.active,pending:H?$.pending.map((V)=>V.id===Z.task_id?X(V):V):$.pending}}let W={id:Z.task_id,toolUseId:Z.tool_use_id,type:Y,description:Z.description,subagentType:Z.subagent_type,workflowName:Z.workflow_name,prompt:Z.prompt,status:"running",startedAt:J,steps:[],...RJ(Y)?{isBackgrounded:!0}:{}};return RJ(Y)?{active:[...$.active,W],pending:$.pending}:{active:$.active,pending:[...$.pending,W]}}function m7($,Z){let J=$.active.some((H)=>H.id===Z.task_id),Y=$.pending.some((H)=>H.id===Z.task_id);if(!J&&!Y)return $;let Q=(H)=>({...H,description:Z.description??H.description,subagentType:Z.subagent_type??H.subagentType,usage:Z.usage??H.usage,lastToolName:Z.last_tool_name??H.lastToolName,summary:Z.summary??H.summary,status:H.status==="pending"?"running":H.status});return{active:J?$.active.map((H)=>H.id===Z.task_id?Q(H):H):$.active,pending:Y?$.pending.map((H)=>H.id===Z.task_id?Q(H):H):$.pending}}function u7($,Z){let J=$.pending.findIndex((W)=>W.id===Z.task_id),Y=Z.patch;if(Y.is_backgrounded===!0&&J>=0){let W=$.pending[J],X={...W,isBackgrounded:!0,status:Y.status??W.status,description:Y.description??W.description,error:Y.error??W.error,endTime:Y.end_time??W.endTime};return{active:[...$.active,X],pending:$.pending.filter((V)=>V.id!==Z.task_id)}}let Q=$.active.some((W)=>W.id===Z.task_id),H=J>=0;if(Q||H){let W=(X)=>({...X,status:Y.status??X.status,description:Y.description??X.description,error:Y.error??X.error,isBackgrounded:Y.is_backgrounded??X.isBackgrounded,endTime:Y.end_time??X.endTime});return{active:Q?$.active.map((X)=>X.id===Z.task_id?W(X):X):$.active,pending:H?$.pending.map((X)=>X.id===Z.task_id?W(X):X):$.pending}}return $}function p7($){if($.pending.length===0)return $;return{active:[...$.active,...$.pending.map((Z)=>({...Z,isBackgrounded:!0}))],pending:[]}}function l7($,Z,J=Date.now()){let Y=Z.status==="completed"?"completed":Z.status==="failed"?"failed":"killed";if($.pending.some((Q)=>Q.id===Z.task_id))return{active:$.active,pending:$.pending.filter((Q)=>Q.id!==Z.task_id)};if($.active.some((Q)=>Q.id===Z.task_id))return{active:$.active.map((Q)=>Q.id===Z.task_id?{...Q,status:Y,usage:Z.usage??Q.usage,summary:Z.summary??Q.summary,endTime:Q.endTime??J}:Q),pending:$.pending};return $}function s4($){let Z=0,J=0;for(let Y=$.length-1;Y>=0;Y--)if(Z+=$[Y].brief.length+5,Z>dG){J=Y+1;break}return J===0?$:$.slice(J)}function nG($,Z){let J=(Y)=>typeof Y==="string"?Y:"";switch($){case"Bash":return h1(J(Z?.command))||"(空命令)";case"Read":return J(Z?.file_path);case"Edit":return J(Z?.file_path);case"Write":return J(Z?.file_path);case"Grep":return`"${J(Z?.pattern)}" in ${J(Z?.path??".")}`;case"Glob":return`"${J(Z?.pattern)}"`;case"Task":return J(Z?.description);case"WebSearch":return`"${J(Z?.query)}"`;default:return JSON.stringify(Z??{}).replace(/\s+/g," ").slice(0,60)}}function aG($,Z){let Y=((typeof $==="string"?$:Array.isArray($)?$.map((Q)=>typeof Q?.text==="string"?Q.text:JSON.stringify(Q)).join(`
|
|
55
|
+
`):JSON.stringify($))??"MISS").replace(/\s+/g," ").trim();return Z?`❌ ${Y.slice(0,80)}`:Y.slice(0,80)}function i7($,Z,J,Y,Q){if(!Z)return $;let H=$.active.some((V)=>V.toolUseId===Z),W=$.pending.some((V)=>V.toolUseId===Z);if(!H&&!W)return $;let X=(V)=>V.map((z)=>z.toolUseId===Z?{...z,steps:s4([...z.steps,{toolUseId:J,tool:Y,brief:`${Y} ${nG(Y,Q)}`.trim()}])}:z);return{active:H?X($.active):$.active,pending:W?X($.pending):$.pending}}function d7($,Z,J,Y,Q,H){let W=$.active.some((z)=>z.id===Z),X=$.pending.some((z)=>z.id===Z);if(!W&&!X)return $;let V=(z)=>z.map((G)=>{if(G.id!==Z)return G;if(Q==="started")return{...G,steps:s4([...G.steps,{toolUseId:J,tool:Y,brief:`${Y} ${H}`.trim()}])};let A=!1,K=G.steps.map((L)=>{if(A||L.toolUseId!==J)return L;return A=!0,{...L,brief:H?`${L.brief} ${H}`:L.brief}});if(!A&&H)K.push({toolUseId:J,tool:Y,brief:`${Y} ${H}`.trim()});return{...G,steps:s4(K)}});return{active:W?V($.active):$.active,pending:X?V($.pending):$.pending}}function n7($,Z,J,Y,Q){if(!Z)return $;let H=$.active.some((V)=>V.toolUseId===Z),W=$.pending.some((V)=>V.toolUseId===Z);if(!H&&!W)return $;let X=(V)=>V.map((z)=>{if(z.toolUseId!==Z)return z;let G=!1,A=z.steps.map((K)=>{if(G||K.toolUseId!==J)return K;return G=!0,{...K,brief:`${K.brief} → ${aG(Y,Q)}`}});return{...z,steps:s4(A)}});return{active:H?X($.active):$.active,pending:W?X($.pending):$.pending}}function h7($){if(!$||$<0)return"0s";let Z=Math.floor($/1000);if(Z<60)return`${Z}s`;let J=Math.floor(Z/60);if(J<60)return`${J}m${Z%60}s`;return`${Math.floor(J/60)}h${J%60}m`}function TJ($){let Z=Number.isFinite($)?Math.max(0,$):0;for(let H of tG)if(Z<H.limit)return{label:H.label,nextDelayMs:H.limit-Z};let J=600000,Y=Math.floor((Z-600000)/J),Q=600000+(Y+1)*J;return{label:`${(Y+1)*10}m+`,nextDelayMs:Q-Z}}function x$($,Z="bucket"){if(Z==="second"){let J=Number.isFinite($)?Math.max(0,$):0;if(J>=I7){let Y=Math.floor((J-I7)/UJ),Q=I7+(Y+1)*UJ;return{label:`${10+Y*5}m+`,nextDelayMs:Q-J}}return{label:`${Math.floor(J/1000)}s`,nextDelayMs:OJ}}return TJ($)}function sG($){return $.subagentType??$.workflowName??rG[$.type]}function g7($){if($.usage?.duration_ms)return $.usage.duration_ms;if($.endTime&&$.endTime>$.startedAt)return $.endTime-$.startedAt;return 0}function eG($,Z,J="bucket"){let Y=(Q)=>x$(Q,J).label;switch($.status){case"running":return`\uD83D\uDFE1 运行中 (${Y(Z-$.startedAt)})`;case"paused":return`⏸️ 已暂停 (${Y(Z-$.startedAt)})`;case"pending":return"⚪ 等待中";case"completed":return`✅ 用时 ${h7(g7($))}`;case"failed":return`❌ 失败 ${h7(g7($))}`;case"killed":return`\uD83D\uDC80 已终止 ${h7(g7($))}`}}function EJ($){let Z=$.filter((Y)=>!g0(Y)).length,J=$.length-Z;if(Z>0)return`${Z} 进行中${J?` · ${J} 已结束`:""}`;return J?`${J} 已结束`:"空"}function e4($){return`\uD83E\uDDED 后台任务 · ${EJ($)}`}function $_($){let Z=[];if($.error)Z.push(`⚠ ${$.error}`);if(g0($)&&$.summary)Z.push(`\uD83D\uDCDD ${$.summary.slice(0,400)}`,"");for(let J=0;J<$.steps.length;J++)Z.push(`${J+1}. ${$.steps[J].brief}`);return r(Z.length>0?Z.join(`
|
|
56
|
+
`):"_(暂无执行记录)_")}function g1($,Z=Date.now(),J="bucket"){return{tag:"collapsible_panel",element_id:f2.panel($.id),header:{title:{tag:"plain_text",content:`${oG[$.type]} ${sG($)} · ${$.description||"(无描述)"} — ${eG($,Z,J)}`}},expanded:!1,elements:[{tag:"markdown",element_id:f2.body($.id),content:$_($)}]}}function a7($,Z=Date.now(),J="bucket"){return{schema:"2.0",config:{streaming_mode:!0,summary:{content:e4($)}},body:{elements:$.map((Y)=>g1(Y,Z,J))}}}function $9($,Z=Date.now(),J="bucket"){let Y=$.filter(g0);return{schema:"2.0",config:{streaming_mode:!1,summary:{content:`\uD83E\uDDED 后台任务(历史) · ${Y.length} 已结束`}},body:{elements:Y.map((Q)=>g1(Q,Z,J))}}}function o7(){return{schema:"2.0",config:{streaming_mode:!1,summary:{content:"↪ 后台任务进行中"}},body:{elements:[{tag:"markdown",element_id:"bg_marker",content:"↪ 本轮后台任务仍在进行,进度已迁至最新卡片"}]}}}var f2,dG=1000,oG,rG,tG,OJ=1000,I7=600000,UJ=300000;var r7=S(()=>{I0();o4();f2={panel:($)=>`bg_${MJ($)}`,body:($)=>`bgb_${MJ($)}`};oG={subagent:"\uD83D\uDFE2",shell:"⚙️",monitor:"\uD83D\uDCE1",workflow:"\uD83D\uDD01",unknown:"\uD83D\uDD39"},rG={subagent:"子agent",shell:"shell",monitor:"监控",workflow:"工作流",unknown:"任务"};tG=[{limit:30000,label:"<30s"},{limit:60000,label:"<1m"},{limit:180000,label:"<3m"},{limit:300000,label:"<5m"},{limit:600000,label:"<10m"}]});import{EventEmitter as Z_}from"node:events";import{join as J_,isAbsolute as Y_,extname as Q_,basename as H_}from"node:path";import{readFile as W_}from"node:fs/promises";function X_($){if($.length>=8&&$.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])))return"image/png";if($.length>=3&&$[0]===255&&$[1]===216&&$[2]===255)return"image/jpeg";let Z=$.subarray(0,12).toString("ascii");if(Z.startsWith("GIF87a")||Z.startsWith("GIF89a"))return"image/gif";if($.length>=12&&Z.startsWith("RIFF")&&Z.slice(8,12)==="WEBP")return"image/webp";throw Error("DSH image input has unsupported or invalid raster bytes")}var Z9=()=>({cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:null,subtype:null,is_error:!1}),t7,s7;var NJ=S(()=>{K0();$1();S2();g();t7={bash:"Bash",read:"Read",write:"Write",edit:"Edit",glob:"Glob",grep:"Grep"};s7=class s7 extends Z_{opts;provider="dsh";tokenSourceId;launchKind;sessionId=null;lastAssistantUuid=null;lastCompletedTurnId=null;lastModel;lastEffort;lastUsage=null;lastTotalUsage=null;lastResult=Z9();lastContextWindow=null;lastContextTokens=null;runtime;ready;models=[];busy=!1;closing=!1;startedAt=0;questionInputs=new Map;frames=new Map;toolInputs=new Map;children=new Set;settledChildren=new Set;childText=new Map;earlyNotifications=[];pendingInputs=0;terminalError=null;failedUnexpectedly=!1;constructor($){super();this.opts=$;this.tokenSourceId=$.tokenSourceId,this.lastModel=$.model,this.lastEffort=$.effort;let Z=$.launch??{kind:"fresh"};V0(Z,"dsh",$.workDir),this.launchKind=Z.kind;let J={...process.env,...$.hostEnv};this.runtime=new l4({cwd:$.workDir,env:$.transformEnv?$.transformEnv(J):J,profile:$.profile,...$.managedSkillPluginPath?{managedSkillDir:J_($.managedSkillPluginPath,"skills")}:{},...$.runtimeOptions}),this.runtime.on("notification",(Y)=>{if(!this.sessionId&&Y.method!=="failure"){this.earlyNotifications.push(Y);return}if(this.terminalError)return;try{this.onNotification(Y)}catch(Q){this.fail(Q)}}),this.runtime.on("failure",(Y)=>this.fail(Y)),this.runtime.on("exit",(Y)=>this.emit("exit",{...Y,expected:Y.expected&&!this.failedUnexpectedly}))}sendInitialize(){this.initializationPromise().catch(($)=>this.fail($))}initializationPromise(){return this.ready??=(async()=>{await this.runtime.initialize();let $=await this.runtime.request("session/open",{cwd:this.opts.workDir,model:this.opts.model,effort:this.opts.effort,launch:this.opts.launch??{kind:"fresh"},developerInstructions:this.opts.developerInstructions??"",allowDelegation:this.opts.allowDelegation!==!1,...this.opts.profile?.tools?{allowedTools:this.opts.profile.tools.split(",").map((Z)=>{let J=Z.trim();return Object.keys(t7).find((Y)=>t7[Y]===J)??J})}:{}});if(typeof $.sessionId!=="string"||!Array.isArray($.models))throw Error("invalid DSH session/open response");this.sessionId=$.sessionId,this.models=$.models,this.lastContextWindow=this.models.find((Z)=>Z.model===this.lastModel)?.contextWindow??null,this.emit("init",{session_id:this.sessionId});for(let Z of this.earlyNotifications.splice(0))this.onNotification(Z)})()}isAlive(){return this.runtime.isAlive()}isConversationResumable(){return this.sessionId!==null}kill($){return this.closing=!0,this.runtime.close($)}sendUserText($,Z=[]){if(!this.isAlive()||this.closing)throw Error("DSH process is closed");if(Z.some((J)=>!Y_(J)))throw Error("DSH file inputs must use absolute paths");if(this.terminalError)throw this.terminalError;this.pendingInputs++,this.initializationPromise().then(async()=>{let J=[{type:"text",text:[$,...Z.map((H)=>`[file: ${H}]`)].join(`
|
|
57
|
+
`)}],Y=new Set([...Z,...Array.from($.matchAll(/\[file: ([^\]\r\n]+)\]/g),(H)=>H[1])]),Q=new Set([".png",".jpg",".jpeg",".webp",".gif"]);for(let H of Y){if(!Q.has(Q_(H).toLowerCase()))continue;let W=await W_(H);J.push({type:"image",mediaType:X_(W),name:H_(H),data:W.toString("base64")})}await this.runtime.request("session/prompt",{mode:"auto",content:J}),this.pendingInputs--}).catch((J)=>this.fail(J))}sendInterrupt(){this.runtime.request("session/cancel").catch(($)=>this.fail($))}sendPermissionResponse($,Z,J){let Y=String($),Q=this.questionInputs.get(Y);if(!Q)throw Error(`unknown DSH question: ${Y}`);let H=J?.updatedInput?.answers,W=Z==="allow"?Q.map((X)=>{let V=H?.[X.question];if(typeof V!=="string")throw Error(`missing answer to DSH question: ${X.question}`);let z=X.options?.find((G)=>G.label===V);return{id:X.id,selected:z?[V]:[],...z?{}:{custom:V}}}):void 0;this.runtime.request("question/answer",{id:Y,answers:W,...Z==="deny"?{error:J?.denyMessage??"User declined the question"}:{}}).then(()=>{this.questionInputs.delete(Y),this.emit("tool_result",{tool_use_id:Y,content:JSON.stringify({answers:W}),is_error:Z==="deny",parentToolUseId:null})}).catch((X)=>this.fail(X))}sendHookResponse(){throw Error("DSH does not issue hook callback requests")}async listModels(){return await this.runtime.initialize(),this.models=await this.runtime.request("model/list",{models:[this.lastModel??this.opts.model]}),this.models.map(($)=>({id:$.model,model:$.model,displayName:$.display,description:"DeepSeek Harness",hidden:!1,isDefault:$.isDefault,defaultReasoningEffort:$.defaultEffort,supportedReasoningEfforts:$.efforts.map((Z)=>({reasoningEffort:Z,description:""}))}))}async setModelSettings($,Z){if(!X0(Z))throw Error(`invalid DSH effort: ${Z}`);if(await this.initializationPromise(),await this.runtime.request("session/model",{model:$,effort:Z}),!this.busy)this.lastModel=$,this.lastEffort=Z}async compactThread(){if(await this.initializationPromise(),await this.runtime.request("session/compact",{},null)===null)throw new e$}fail($){let Z=$ instanceof Error?$:Error(String($));if(this.terminalError)return;this.failedUnexpectedly=!this.closing,this.terminalError=Z,this.emit("error",Z);for(let J of this.children){if(this.settledChildren.has(J))continue;this.settledChildren.add(J),this.emit("bg_task_settled",{task_id:J,status:"failed",summary:Z.message})}if(this.busy||this.pendingInputs>0)this.busy=!1,this.lastResult={...Z9(),is_error:!0,subtype:"error"},this.emit("result",{errors:[Z.message],error:Z.message,...this.lastResult});this.kill().catch((J)=>this.emit("error",J))}onNotification({method:$,params:Z}){let J=Z.sessionId!==this.sessionId;switch($){case"failure":this.fail(Error(Z.message));return;case"agent.error":this.emit("error",Error(Z.message));return;case"subagent.started":this.children.add(Z.sessionId),this.emit("bg_task_started",{task_id:Z.sessionId,description:"DeepSeek Harness 子 Agent",task_type:"agent",tool_use_id:Z.sessionId});return;case"subagent.disposed":if(this.children.has(Z.sessionId)&&!this.settledChildren.has(Z.sessionId))this.emit("bg_task_settled",{task_id:Z.sessionId,status:"stopped",summary:this.childText.get(Z.sessionId)??""});this.children.delete(Z.sessionId),this.settledChildren.delete(Z.sessionId),this.childText.delete(Z.sessionId);for(let Y of this.frames.keys())if(Y.startsWith(`${Z.sessionId}:`))this.frames.delete(Y);return;case"session.status":return;case"question":{this.questionInputs.set(Z.id,Z.questions);let Y={questions:Z.questions.map((Q)=>({...Q,question:Q.detail?`${Q.question}
|
|
55
58
|
|
|
56
|
-
${Q.detail}`:Q.question}))};this.questionInputs.set(Z.id,Y.questions),this.emit("tool_use",{id:Z.id,name:"AskUserQuestion",input:Y,parentToolUseId:null}),this.emit("can_use_tool",{request_id:Z.id,tool_use_id:Z.id,tool_name:"AskUserQuestion",input:Y});return}case"question.cancelled":this.questionInputs.delete(Z.id),this.emit("tool_result",{tool_use_id:Z.id,content:"Question cancelled",is_error:!0,parentToolUseId:null});return;case"assistant.frame":{let Y=Z.frame,Q=`${Z.sessionId}:${Y.attemptId}`;if(Y.type==="start"){this.frames.set(Q,{revision:Y.revision,nextIndex:0});return}let H=this.frames.get(Q);if(!H||H.revision+1!==Y.revision||H.nextIndex!==Y.index)throw Error("DSH assistant stream sequence mismatch");if(H.revision=Y.revision,Y.type==="end"){if(this.frames.delete(Q),!J)this.emit("assistant_block_stop",{parentToolUseId:null});return}if(Y.type!=="chunk")throw Error(`unknown DSH assistant frame: ${Y.type}`);H.nextIndex++;let W=Y.chunk;if(W.type==="text-delta"){if(J)this.childText.set(Z.sessionId,(this.childText.get(Z.sessionId)??"")+W.text);this.emit("assistant_text",{text:W.text,parentToolUseId:J?Z.sessionId:null})}else if(W.type==="block-end"&&W.block.type==="text"&&!J)this.emit("assistant_block_stop",{parentToolUseId:null});else if(W.type==="usage"&&!J)this.observeUsage(W.usage);return}case"session.event":{let Y=Z.event,Q=Y.data;if(!Y||!Q||typeof Y.type!=="string")throw Error("invalid DSH session event");if(Y.type==="turn/start"&&!J)this.busy=!0,this.startedAt=Date.now(),this.lastUsage=null,this.lastResult=
|
|
57
|
-
`);for(let Y=J.length-1;Y>=0;Y--){let Q=J[Y].trim();if(!Q)continue;try{let H=JSON.parse(Q);if(H?.type==="assistant"&&H?.message?.usage){let W=H.message.usage;if((W.input_tokens??0)+(W.cache_read_input_tokens??0)+(W.cache_creation_input_tokens??0)+(W.output_tokens??0)>0)return W}}catch{}}return null}function
|
|
58
|
-
`);return $==null?"":JSON.stringify($,null,2)}function
|
|
59
|
-
`)}}catch{}return Z}function
|
|
59
|
+
${Q.detail}`:Q.question}))};this.questionInputs.set(Z.id,Y.questions),this.emit("tool_use",{id:Z.id,name:"AskUserQuestion",input:Y,parentToolUseId:null}),this.emit("can_use_tool",{request_id:Z.id,tool_use_id:Z.id,tool_name:"AskUserQuestion",input:Y});return}case"question.cancelled":this.questionInputs.delete(Z.id),this.emit("tool_result",{tool_use_id:Z.id,content:"Question cancelled",is_error:!0,parentToolUseId:null});return;case"assistant.frame":{let Y=Z.frame,Q=`${Z.sessionId}:${Y.attemptId}`;if(Y.type==="start"){this.frames.set(Q,{revision:Y.revision,nextIndex:0});return}let H=this.frames.get(Q);if(!H||H.revision+1!==Y.revision||H.nextIndex!==Y.index)throw Error("DSH assistant stream sequence mismatch");if(H.revision=Y.revision,Y.type==="end"){if(this.frames.delete(Q),!J)this.emit("assistant_block_stop",{parentToolUseId:null});return}if(Y.type!=="chunk")throw Error(`unknown DSH assistant frame: ${Y.type}`);H.nextIndex++;let W=Y.chunk;if(W.type==="text-delta"){if(J)this.childText.set(Z.sessionId,(this.childText.get(Z.sessionId)??"")+W.text);this.emit("assistant_text",{text:W.text,parentToolUseId:J?Z.sessionId:null})}else if(W.type==="block-end"&&W.block.type==="text"&&!J)this.emit("assistant_block_stop",{parentToolUseId:null});else if(W.type==="usage"&&!J)this.observeUsage(W.usage);return}case"session.event":{let Y=Z.event,Q=Y.data;if(!Y||!Q||typeof Y.type!=="string")throw Error("invalid DSH session event");if(Y.type==="turn/start"&&!J)this.busy=!0,this.startedAt=Date.now(),this.lastUsage=null,this.lastResult=Z9(),this.emit("scheduled_turn_input",{text:"DeepSeek Harness 继续执行",promptId:`dsh-turn-${Q.turn}`}),this.emit("turn_started",{turn_id:String(Q.turn),thread_id:this.sessionId});else if(Y.type==="turn/start"&&J&&this.settledChildren.delete(Z.sessionId))this.emit("bg_task_started",{task_id:Z.sessionId,description:"DeepSeek Harness 子 Agent",task_type:"agent",tool_use_id:Z.sessionId});else if(Y.type==="request/header"&&!J&&Q.header?.config)this.lastModel=Q.header.config.model,this.lastEffort=Q.header.config.reasoningEffort,this.lastContextWindow=this.models.find((H)=>H.model===this.lastModel)?.contextWindow??null;else if(Y.type==="tool/call"){let H=JSON.parse(Q.arguments),W=t7[Q.name]??Q.name;if(["read","write","edit"].includes(Q.name)&&H.path)H.file_path=H.path;this.toolInputs.set(Q.callId,{name:W,input:H}),this.emit("tool_use",{id:Q.callId,name:W,input:H,parentToolUseId:J?Z.sessionId:null})}else if(Y.type==="tool/result"){let H=Q.message?.content?.[0];if(H?.type!=="tool-result"||typeof H.toolCallId!=="string")throw Error("invalid DSH tool result");this.emit("tool_result",{tool_use_id:H.toolCallId,content:H.content,is_error:H.isError===!0,parentToolUseId:J?Z.sessionId:null}),this.toolInputs.delete(H.toolCallId)}else if(Y.type==="todo/write"&&!J)this.emit("turn_plan_updated",{threadId:this.sessionId,explanation:null,plan:Q.todos.map((H)=>({step:H.content,status:H.status==="in_progress"?"inProgress":H.status}))});else if(Y.type==="compaction/start"&&!J)this.emit("context_compacted",{threadId:this.sessionId,phase:"start",sourceType:"dsh"});else if(Y.type==="compaction/end"&&!J)if(Q.error)this.emit("error",Error(`DSH compaction: ${Q.error}`));else this.emit("context_compacted",{threadId:this.sessionId,phase:"end",sourceType:"dsh"});else if(Y.type==="goal/change"&&!J)if(Q.operation==="clear")this.emit("thread_goal_cleared",{threadId:this.sessionId});else this.emit("thread_goal_updated",{threadId:this.sessionId,objective:Q.goal.objective,status:Q.goal.phase,tokenBudget:null,tokensUsed:Number.NaN,timeUsedSeconds:Number.NaN});else if(Y.type==="turn/end"&&J&&this.children.has(Z.sessionId))this.settledChildren.add(Z.sessionId),this.emit("bg_task_settled",{task_id:Z.sessionId,status:Q.reason.kind==="completed"?"completed":Q.reason.kind==="aborted"?"stopped":"failed",summary:this.childText.get(Z.sessionId)??""}),this.childText.delete(Z.sessionId);return}case"settled":{if(J)throw Error("DSH settled a different root session");this.busy=!1;let Y=Z.event,Q=Y.data.reason;this.lastCompletedTurnId=String(Y.seq),this.lastResult={...Z9(),duration_ms:Date.now()-this.startedAt,num_turns:1,usage:this.lastUsage,subtype:Q.kind,is_error:Q.kind!=="completed"},this.emit("result",{...this.lastResult,...Q.kind!=="completed"?{error:Q.error?.message??`DSH turn ended: ${Q.kind}`,errors:[Q.error?.message??`DSH turn ended: ${Q.kind}`]}:{},checkpoint:{provider:"dsh",kind:"event",id:String(Y.seq),source:{provider:"dsh",sessionId:this.sessionId,cwd:this.opts.workDir}}});return}default:_(`dsh: unknown notification ${$}`)}}observeUsage($){if(!Number.isFinite($.inputTokens)||!Number.isFinite($.outputTokens))throw Error("invalid DSH token usage");let Z={input_tokens:$.inputTokens,output_tokens:$.outputTokens,total_tokens:$.totalTokens,cache_read_input_tokens:$.cacheReadTokens,cache_creation_input_tokens:$.cacheWriteTokens,reasoning_output_tokens:$.reasoningTokens};this.lastUsage=Z;let J={...this.lastTotalUsage};for(let[Y,Q]of Object.entries(Z))if(Q!==void 0){let H=Y;J[H]=(J[H]??0)+Q}this.lastTotalUsage=J,this.lastContextTokens=$.inputTokens+($.cacheReadTokens??0)+($.cacheWriteTokens??0),this.emit("token_usage",{usage:Z,totalUsage:J,contextWindow:this.lastContextWindow,threadId:this.sessionId})}}});function k$($){return $.startsWith("claude:")?$:`claude:${$}`}function e7($){if(!$||$==="default"||$==="claude:default")return"opus";if(!$.startsWith("claude:"))return $;let Z=$.slice(7);if(Z==="glm"||Object.hasOwn(v.claude.models,Z))return v.claude.models[Z]?.model?.trim()||"opus";return Z}var SJ=S(()=>{x0()});import{existsSync as V_,readFileSync as z_}from"node:fs";function $8(){return process.env.LODESTAR_DATA_DIR?`${process.env.LODESTAR_DATA_DIR.replace(/\/+$/,"")}/context-window-cache.json`:qZ}function h2(){if(v2!==null)return v2;try{v2=V_($8())?JSON.parse(z_($8(),"utf8")):{}}catch($){_(`context-window-observe: cache read MISS (${$?.message??$}), starting fresh`),v2={}}return v2??{}}function __(){try{A0($8(),h2())}catch($){_(`context-window-observe: cache write MISS (${$?.message??$})`)}}function Z8($,Z){return`${$}:${Z.replace(/\[1m\]$/,"")}`}function xJ($,Z,J){if(!Number.isFinite(J)||J<=0)return;let Y=Z8($,Z),Q=h2()[Y];if(Q===J)return;h2()[Y]=J,__(),_(`context-window-observe: ${Y} → ${J} (prev ${Q??"-"})`)}function J9($,Z){if(!Z)return;if(Z.endsWith("[1m]"))return Z;let J=h2()[Z8($,Z)];return J!=null&&J<G_?Z:`${Z}[1m]`}function c1($,Z){return h2()[Z8($,Z)]}var G_=1e6,v2=null;var I2=S(()=>{Y0();g();n0()});var iJ={};n$(iJ,{toolsFromProfile:()=>pJ,settingSourcesFromProfile:()=>uJ,resolveClaudeExecutableConfig:()=>W8,resetClaudeContextWindowCache:()=>D_,readProjectMcpServers:()=>lJ,readLastCallUsageFromTranscript:()=>gJ,claudeTranscriptPath:()=>W9,claudeTranscriptDir:()=>H9,claudeManagedSkillOptions:()=>hJ,buildClaudeSpawnPath:()=>IJ,assertClaudeCodeAvailable:()=>H8,ClaudeAgentProcess:()=>X9,CLAUDE_PERMISSION_MODE:()=>mJ});import{existsSync as wJ,readFileSync as fJ}from"node:fs";import{homedir as Q9}from"node:os";import{spawn as A_}from"cross-spawn";import{delimiter as kJ,join as Y1}from"node:path";import{EventEmitter as K_}from"node:events";function hJ($,Z){if(!Z||$.includes("user"))return{};return{plugins:[{type:"local",path:Z,skipMcpDiscovery:!0}],skills:"all"}}function B_($){let Z=$.toLowerCase();return Z.endsWith(".cmd")||Z.endsWith(".bat")}function L_($){let Z=A_($.command,$.args,{cwd:$.cwd,env:$.env,shell:!1,signal:$.signal,stdio:["pipe","pipe","ignore"],windowsHide:!0});if(!Z.stdin||!Z.stdout)throw Z.kill(),Error("failed to open stdio for Claude Code Windows shell shim");return Z}function H8(){W8(),X7("claude","@anthropic-ai/claude-agent-sdk")}function W8($={}){let Z=$.platform??process.platform,J=$.configuredBin===void 0?v.claude.bin:$.configuredBin;if(J){if(!($.exists??wJ)(J))throw Error(`lodestar: [claude].bin not found: ${J} (config.toml)`);if(Z==="win32"&&B_(J))return{pathToClaudeCodeExecutable:J,spawnClaudeCodeProcess:L_,description:`windows-shell-shim:${J}`};return{pathToClaudeCodeExecutable:J,description:`config:${J}`}}return{description:"sdk-default"}}function IJ(){if(process.platform==="win32")return process.env.PATH??"";let $=[Y1(Q9(),".local","npm-global","bin"),Y1(Q9(),".local","bin"),Y1(Q9(),".bun","bin"),...(process.env.PATH??"").split(kJ),"/usr/local/bin","/usr/bin","/bin"];return[...new Set($.filter(Boolean))].join(kJ)}function q_($){let Z=v1($);if(!Z)return null;let J=(Z.input_tokens??0)+(Z.output_tokens??0)+(Z.cache_creation_input_tokens??0)+(Z.cache_read_input_tokens??0);if((Z.total_tokens??J)<=0)return null;if(Z.total_tokens==null)Z.total_tokens=J;return Z}function CJ($){if(!$)return null;let Z=($.input_tokens??0)+($.cache_read_input_tokens??0)+($.cache_creation_input_tokens??0);return Z>0?Z:null}function H9($){let Z=$.replace(/[^a-zA-Z0-9]/g,"-"),J=process.env.CLAUDE_CONFIG_DIR||Y1(Q9(),".claude");return Y1(J,"projects",Z)}function W9($,Z){return Y1(H9($),`${Z}.jsonl`)}function gJ($){let Z;try{Z=fJ($,"utf8")}catch{return null}let J=Z.split(`
|
|
60
|
+
`);for(let Y=J.length-1;Y>=0;Y--){let Q=J[Y].trim();if(!Q)continue;try{let H=JSON.parse(Q);if(H?.type==="assistant"&&H?.message?.usage){let W=H.message.usage;if((W.input_tokens??0)+(W.cache_read_input_tokens??0)+(W.cache_creation_input_tokens??0)+(W.output_tokens??0)>0)return W}}catch{}}return null}function bJ($,Z){let J=Z?.trim()||"no-source",Y=$&&$.trim()?$:"claude:default";return`${J}:${Y}`}function D_(){Y8.clear()}function P_($){if(!$||typeof $!=="object")return{usage:null,contextWindow:null};let Z={},J=null;for(let Q of Object.values($)){if(!Q||typeof Q!=="object")continue;let H=Q;Z.input_tokens=(Z.input_tokens??0)+m1(H.inputTokens??H.input_tokens),Z.output_tokens=(Z.output_tokens??0)+m1(H.outputTokens??H.output_tokens),Z.reasoning_output_tokens=(Z.reasoning_output_tokens??0)+m1(H.reasoningOutputTokens??H.reasoning_output_tokens),Z.cache_read_input_tokens=(Z.cache_read_input_tokens??0)+m1(H.cacheReadInputTokens??H.cache_read_input_tokens),Z.cache_creation_input_tokens=(Z.cache_creation_input_tokens??0)+m1(H.cacheCreationInputTokens??H.cache_creation_input_tokens);let W=m1(H.contextWindow??H.context_window);if(W>0)J=Math.max(J??0,W)}let Y=(Z.input_tokens??0)+(Z.output_tokens??0)+(Z.cache_creation_input_tokens??0)+(Z.cache_read_input_tokens??0);if(Y<=0)return{usage:null,contextWindow:J};return Z.total_tokens=Y,{usage:Z,contextWindow:J}}function Y9($){return{...$}}function J8($){if(!$||typeof $!=="object")return[];return Object.keys($).slice(0,20)}function j_($,Z){let J=$?{...$}:{},Y=(Q)=>{let H=Z[Q];if(typeof H!=="number"||!Number.isFinite(H))return;J[Q]=(J[Q]??0)+H};return Y("total_tokens"),Y("input_tokens"),Y("output_tokens"),Y("reasoning_output_tokens"),Y("cache_creation_input_tokens"),Y("cache_read_input_tokens"),J}function m1($){return typeof $==="number"&&Number.isFinite($)?$:0}function cJ($){if(typeof $==="string")return $;if(Array.isArray($))return $.map((Z)=>{if(typeof Z==="string")return Z;if(Z&&typeof Z==="object"&&typeof Z.text==="string")return Z.text;return JSON.stringify(Z)}).join(`
|
|
61
|
+
`);return $==null?"":JSON.stringify($,null,2)}function F_($){let Z=cJ($);try{let J=JSON.parse(Z);if(Array.isArray(J)){let Y=J.map((Q)=>{if(typeof Q==="string")return Q;if(Q&&typeof Q==="object"&&typeof Q.text==="string")return Q.text;return JSON.stringify(Q)}).filter(Boolean);if(Y.length>0)return Y.join(`
|
|
62
|
+
`)}}catch{}return Z}function M_($){return`server_tool:${$}`}function R_($){let Z=$.match(/Built-in Tool:\s*([A-Za-z0-9_.:-]+)/)?.[1];if(!Z)return null;let J=$.match(/\*\*Input:\*\*\s*```(?:json)?\s*([\s\S]*?)```/)?.[1]?.trim();if(!J)return{name:Z,input:{}};try{return{name:Z,input:JSON.parse(J)}}catch{return{name:Z,input:{raw:J}}}}function U_($){let Z=$.trim();return Z.includes("Built-in Tool:")||Z.startsWith("**Output:**")&&Z.includes("_result")}function O_($){let Z=$.supportedEffortLevels&&$.supportedEffortLevels.length>0?$.supportedEffortLevels:[E$];return{id:k$($.value),model:k$($.value),displayName:$.displayName||k$($.value),description:$.description||"Claude Agent SDK backend",hidden:!1,isDefault:!1,supportedReasoningEfforts:Z.map((J)=>({reasoningEffort:J,description:""})),defaultReasoningEffort:Z.includes(E$)?E$:Z[0]}}function uJ($){if(!$?.settingSources)return[...yJ];let Z=$.settingSources.split(",").map((J)=>J.trim()).filter(Boolean);return Z.length?Z:[...yJ]}function pJ($){if(!$?.tools)return{type:"preset",preset:"claude_code"};let Z=$.tools.split(",").map((J)=>J.trim()).filter(Boolean);return Z.length?Z:{type:"preset",preset:"claude_code"}}function lJ($){let Z=Y1($,".mcp.json"),J;try{J=fJ(Z,"utf8")}catch(Y){if(Y.code!=="ENOENT")_(`claude-agent-process: project .mcp.json not readable at ${Z}: ${Y}`);return}try{let Y=JSON.parse(J);if(Y&&typeof Y==="object"&&Y.mcpServers&&typeof Y.mcpServers==="object")return Y.mcpServers;_(`claude-agent-process: project .mcp.json has no mcpServers object at ${Z}`);return}catch(Y){_(`claude-agent-process: project .mcp.json parse failed at ${Z}: ${Y}`);return}}function T_($){let Z=$.questions;return(Array.isArray(Z)?Z:Z&&typeof Z==="object"?[Z]:[$]).map((Y)=>E_(Y)).filter((Y)=>Y!==null)}function E_($){let Z=$&&typeof $==="object"?$:{question:$},J=Q8(Z.question,Z.prompt,Z.title,Z.message,Z.text,Z.label);if(!J)return null;if(!J.trim())return null;let Y=N_(Z.options??Z.choices??Z.suggestions);return{...Z,question:J,options:Y,...typeof Z.header==="string"?{header:Z.header}:{},...typeof Z.multiSelect==="boolean"?{multiSelect:Z.multiSelect}:{}}}function N_($){if(!Array.isArray($))return[];let Z=[];for(let J of $){if(typeof J==="string"){Z.push({label:J});continue}if(!J||typeof J!=="object")continue;let Y=J,Q=Q8(Y.label,Y.value,Y.text,Y.title);if(!Q?.trim())continue;let H=Q8(Y.description,Y.detail,Y.preview);Z.push(H?{label:Q,description:H}:{label:Q})}return Z}function Q8(...$){for(let Z of $)if(typeof Z==="string")return Z;return}var vJ,Y8,mJ="default",yJ,X9;var g2=S(()=>{b1();x0();g();K0();SJ();I2();vJ=class vJ{items=[];waiters=[];closed=!1;push($){if(this.closed)throw Error("input stream is closed");let Z=this.waiters.shift();if(Z)Z({value:$,done:!1});else this.items.push($)}close(){if(this.closed)return;this.closed=!0;while(this.waiters.length)this.waiters.shift()?.({value:void 0,done:!0})}abort(){this.items=[],this.close()}[Symbol.asyncIterator](){return this}next(){if(this.items.length>0)return Promise.resolve({value:this.items.shift(),done:!1});if(this.closed)return Promise.resolve({value:void 0,done:!0});return new Promise(($)=>this.waiters.push($))}};Y8=new Map;yJ=["project","local"];X9=class X9 extends K_{provider="claude";tokenSourceId;opts;input=new vJ;query=null;abortController=new AbortController;alive=!0;expectedExit=!1;exitPromise;resolveExit;started=!1;queryStart;pendingPermissions=new Map;requestCounter=0;cumulativeUsageFromResults=null;turnActive=!1;emittedToolUseIds=new Set;emittedToolResultIds=new Set;pendingServerToolInputs=[];sessionId=null;lastAssistantUuid=null;lastModel=null;lastEffort=null;lastThinkingTokens=null;lastUsage=null;lastTotalUsage=null;lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:null,subtype:null,is_error:!1};lastContextWindow=null;lastContextTokens=null;constructor($){super();this.on("error",()=>{}),this.exitPromise=new Promise((Z)=>{this.resolveExit=Z}),this.opts=$,this.tokenSourceId=$.tokenSourceId??null,this.lastEffort=$.effort,this.lastModel=$.model?k$($.model):null}sendInitialize(){if(this.started)return;this.started=!0,this.queryStart=this.initializeQuery().catch(($)=>{this.emit("error",$ instanceof Error?$:Error(String($))),this.finishExit(1,null)})}async initializeQuery(){let $=e7(this.opts.model),Z=this.opts.profile;if(Z)_(`claude-agent-process: project profile active — settingSources=${Z.settingSources??"-"} strictMcp=${Z.strictMcp??!1} tools=${Z.tools??"-"} loadProjectMcp=${Z.loadProjectMcp??!0}`);let J=this.opts.settingSources??uJ(Z),Y=hJ(J,this.opts.managedSkillPluginPath),Q=pJ(Z),H=Z?.strictMcp===!0,W=Z?.loadProjectMcp!==!1?lJ(this.opts.workDir):void 0;try{let X=W8(),{query:V}=await bZ();if(!this.alive||this.abortController.signal.aborted)return;let z={...process.env,PATH:IJ(),...v.claude.env,...this.opts.hostEnv??{}},G=this.opts.transformEnv?this.opts.transformEnv(z):z;if(this.opts.effort==="default")G.CLAUDE_CODE_EFFORT_LEVEL="unset";_(`claude-agent-process: spawn SDK query model=${$??"default"} effort=${this.opts.effort} cwd=${this.opts.workDir} executable=${X.description}`),this.query=V({prompt:this.input,options:{cwd:this.opts.workDir,abortController:this.abortController,...$?{model:$}:{},effort:this.opts.effort==="default"?"high":this.opts.effort,resume:this.opts.resumeSessionId,...this.opts.resumeSessionAt?{resumeSessionAt:this.opts.resumeSessionAt}:{},...this.opts.forkSession?{forkSession:!0}:{},...X.pathToClaudeCodeExecutable?{pathToClaudeCodeExecutable:X.pathToClaudeCodeExecutable}:{},...X.spawnClaudeCodeProcess?{spawnClaudeCodeProcess:X.spawnClaudeCodeProcess}:{},permissionMode:mJ,env:G,settingSources:[...J],...Y,tools:Q,...this.opts.allowDelegation===!1?{disallowedTools:["Agent","Task"]}:{},...H?{strictMcpConfig:!0}:{},...W?{mcpServers:W}:{},toolConfig:{askUserQuestion:{previewFormat:"markdown"}},canUseTool:(A,K,L)=>this.canUseTool(A,K,L),includePartialMessages:!1,systemPrompt:{type:"preset",preset:"claude_code",...this.opts.appendSystemPrompt?{append:this.opts.appendSystemPrompt}:{}},stderr:(A)=>{let K=A.trim();if(K)_(`claude-agent-process[stderr]: ${K}`)}}})}catch(X){let V=X instanceof Error?X:Error(String(X));this.emit("error",V),this.finishExit(1,null);return}this.readLoop(this.query)}sendUserText($,Z=[]){if(!this.alive){_("claude-agent-process: sendUserText ignored on dead process");return}if(!this.started)this.sendInitialize();let J=Z.length?Z.map((Y)=>`[file: ${Y}]`).join(" ")+`
|
|
60
63
|
|
|
61
|
-
`:"";try{this.input.push({type:"user",session_id:this.sessionId??"",message:{role:"user",content:[{type:"text",text:J+$}]},parent_tool_use_id:null,priority:"now"})}catch(Y){let Q=Y instanceof Error?Y:Error(String(Y));A(`claude-agent-process: sendUserText failed: ${Q.message}`),this.failTurnStart(Q)}}sendInterrupt(){this.query?.interrupt().catch(($)=>A(`claude-agent-process: interrupt failed: ${$}`))}sendPermissionResponse($,Z,J){let Y=this.pendingPermissions.get(String($));if(!Y){A(`claude-agent-process: permission response for unknown request ${$}`);return}if(this.pendingPermissions.delete(String($)),Y.cleanup?.(),Z==="allow")Y.resolve({behavior:"allow",updatedInput:J?.updatedInput??{}});else Y.resolve({behavior:"deny",message:J?.denyMessage??""})}sendHookResponse($,Z={}){A("claude-agent-process: sendHookResponse ignored; hooks are handled by SDK callbacks")}isAlive(){return this.alive}async kill($=5000){if(!this.alive)return;if(this.expectedExit=!0,this.denyPendingPermissions("claude process is stopping"),this.input.abort(),!this.started||!this.query){this.finishExit(null,null);return}let Z=null;try{this.query.close()}catch(J){Z=J instanceof Error?J:Error(String(J))}if(!this.abortController.signal.aborted)this.abortController.abort(Z??Error("claude process shutdown requested"));if(!await this.waitForExit($)){let J=Error(`claude Agent SDK query did not exit within ${$}ms after close/abort`,Z?{cause:Z}:void 0);throw A(`claude-agent-process: kill failed: ${J.message}`),J}if(Z){let J=Error(`claude Agent SDK close failed: ${Z.message}`,{cause:Z});throw A(`claude-agent-process: kill failed: ${J.message}`),J}}async listModels(){if(!this.started)this.sendInitialize();if(await this.queryStart,!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");return(await this.query.supportedModels()).map(FA)}async setModelSettings($,Z){let J=t7($);if(!F0(Z))throw Error(`invalid Claude effort: ${String(Z)}`);if(this.opts.effort==="default"!==(Z==="default"))throw Error("effort 参数模式改变,需要使用新的启动环境恢复会话");if(!this.started)this.sendInitialize();if(await this.queryStart,!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");if(J)await this.query.setModel(J);await this.query.applyFlagSettings({effortLevel:Z==="default"?null:Z,ultracode:null}),this.opts.model=$,this.opts.effort=Z,this.lastModel=J?S$($):"claude:default",this.lastEffort=Z}async compactThread(){if(!this.input)throw Error("claude thread not initialized");return this.input.push({type:"user",session_id:this.sessionId??"",message:{role:"user",content:[{type:"text",text:"/compact"}]},parent_tool_use_id:null,priority:"now"}),new Promise(($,Z)=>{let J=!1,Y=()=>{this.off("context_compacted",Q),this.off("assistant_text",H),this.off("exit",W),this.off("error",X)},Q=()=>{if(J)return;J=!0,Y(),$()},H=(V)=>{if(J)return;if((V?.text??"").includes("Not enough messages to compact"))J=!0,Y(),Z(new r$)},W=()=>{if(J)return;J=!0,Y(),Z(Error("claude thread exited during /compact"))},X=(V)=>{if(J)return;J=!0,Y(),Z(V instanceof Error?V:Error(String(V)))};this.on("context_compacted",Q),this.on("assistant_text",H),this.once("exit",W),this.once("error",X)})}canUseTool($,Z,J){if($!=="AskUserQuestion")return Promise.resolve({behavior:"allow",updatedInput:Z});let Y=MA(Z);if(Y.length===0)return A("claude-agent-process: AskUserQuestion 无有效 questions — allow 原样"),Promise.resolve({behavior:"allow",updatedInput:Z});let Q={...Z,questions:Y},H=`claude_perm_${++this.requestCounter}`,W=J.toolUseID||H,X={request_id:H,tool_name:"AskUserQuestion",input:Q,tool_use_id:W},V=new Promise((z)=>{let G=(K)=>{J.signal.removeEventListener("abort",_),z(K)},_=()=>{if(!this.pendingPermissions.delete(H))return;G({behavior:"deny",message:"aborted"})};J.signal.addEventListener("abort",_,{once:!0}),this.pendingPermissions.set(H,{kind:"dialog",resolve:G,request:X})});return this.emitToolUseOnce(W,"AskUserQuestion",Q,null),this.emit("can_use_tool",X),V}async readLoop($){try{for await(let Z of $)this.handleMessage(Z);this.finishExit(null,null)}catch(Z){let J=Z instanceof Error?Z:Error(String(Z));if(this.expectedExit&&this.abortController.signal.aborted){A(`claude-agent-process: read loop stopped after requested shutdown: ${J.message}`),this.finishExit(null,null);return}A(`claude-agent-process: read loop failed: ${J.message}`),this.emit("error",J),this.finishExit(1,null)}}finishExit($,Z){if(!this.alive)return;this.alive=!1,this.turnActive=!1,this.denyPendingPermissions("claude process exited"),this.resolveExit(),A(`claude-agent-process: exited code=${$} signal=${Z} expected=${this.expectedExit}`),this.emit("exit",{code:$,signal:Z,expected:this.expectedExit})}denyPendingPermissions($){for(let[Z,J]of this.pendingPermissions)J.cleanup?.(),J.resolve({behavior:"deny",message:$}),this.pendingPermissions.delete(Z)}async waitForExit($){if(!this.alive)return!0;return new Promise((Z)=>{let J=!1,Y=(H)=>{if(J)return;J=!0,clearTimeout(Q),Z(H)},Q=setTimeout(()=>Y(!this.alive),Math.max(0,$));this.exitPromise.then(()=>Y(!0))})}handleMessage($){let Z=$;if(typeof Z.session_id==="string"&&Z.session_id)this.sessionId=Z.session_id;switch(Z.type){case"system":this.handleSystemMessage(Z);return;case"assistant":this.handleAssistantMessage(Z);return;case"user":this.handleUserMessage(Z);return;case"result":this.handleResultMessage(Z);return;case"rate_limit_event":this.emit("rate_limits_updated",Z.rate_limit_info);return;case"stream_event":return;default:A(`claude-agent-process: unhandled message type=${Z.type??"unknown"} subtype=${Z.subtype??""}`)}}handleSystemMessage($){switch($.subtype){case"init":if(typeof $.model==="string"&&$.model)this.lastModel=S$($.model);this.lastEffort=this.opts.effort,this.emit("init",{session_id:this.sessionId,raw:$});return;case"session_state_changed":if($.state==="running"&&!this.turnActive)this.turnActive=!0,this.lastThinkingTokens=null,this.lastAssistantUuid=null,this.emit("turn_started",{turn_id:$.uuid,thread_id:this.sessionId});else if($.state==="idle")this.turnActive=!1;return;case"compact_boundary":this.emit("context_compacted",{threadId:$.session_id??this.sessionId??void 0,sessionId:$.session_id??this.sessionId??void 0,itemId:$.uuid,phase:"event",sourceMethod:"claude_agent_sdk",sourceType:"compact_boundary",preTokens:$.compact_metadata?.pre_tokens,trigger:$.compact_metadata?.trigger});return;case"api_retry":A(`claude-agent-process: api retry attempt=${$.attempt}/${$.max_retries} status=${$.error_status} error=${$.error}`);return;case"thinking_tokens":if(typeof $.estimated_tokens!=="number"||!Number.isFinite($.estimated_tokens)||$.estimated_tokens<0){A("claude-agent-process: invalid thinking_tokens estimate");return}this.lastThinkingTokens=$.estimated_tokens,this.emit("thinking_progress",{estimatedTokens:$.estimated_tokens});return;case"permission_denied":A(`claude-agent-process: permission denied ${$.tool_name} ${$.tool_use_id}: ${$.message}`);return;case"task_started":this.emit("bg_task_started",{task_id:String($.task_id??""),tool_use_id:typeof $.tool_use_id==="string"?$.tool_use_id:void 0,task_type:typeof $.task_type==="string"?$.task_type:void 0,description:String($.description??""),subagent_type:typeof $.subagent_type==="string"?$.subagent_type:void 0,workflow_name:typeof $.workflow_name==="string"?$.workflow_name:void 0,prompt:typeof $.prompt==="string"?$.prompt:void 0});return;case"task_progress":this.emit("bg_task_progress",{task_id:String($.task_id??""),description:typeof $.description==="string"?$.description:void 0,subagent_type:typeof $.subagent_type==="string"?$.subagent_type:void 0,usage:$.usage,last_tool_name:typeof $.last_tool_name==="string"?$.last_tool_name:void 0,summary:typeof $.summary==="string"?$.summary:void 0});return;case"task_updated":this.emit("bg_task_updated",{task_id:String($.task_id??""),patch:$.patch&&typeof $.patch==="object"?$.patch:{}});return;case"task_notification":if(typeof $.task_id!=="string"||!$.task_id){A("claude-agent-process: task_notification missing task_id");return}if($.status!=="completed"&&$.status!=="failed"&&$.status!=="stopped"){A(`claude-agent-process: task_notification unknown status=${String($.status)} task=${$.task_id}`);return}this.emit("bg_task_settled",{task_id:$.task_id,tool_use_id:typeof $.tool_use_id==="string"?$.tool_use_id:void 0,status:$.status,summary:typeof $.summary==="string"?$.summary:void 0,usage:$.usage});return;default:A(`claude-agent-process: unhandled system subtype=${String($.subtype??"unknown")}`);return}}handleAssistantMessage($){if(!$.parent_tool_use_id)this.lastThinkingTokens=null;let Z=$.message,J=typeof $.parent_tool_use_id==="string"&&$.parent_tool_use_id?$.parent_tool_use_id:null;if(!J&&typeof $.uuid==="string")this.lastAssistantUuid=$.uuid;if(typeof Z?.model==="string"&&Z.model)this.lastModel=S$(Z.model);let Y=Array.isArray(Z?.content)?Z.content:[];for(let Q of Y){if(!Q||typeof Q!=="object")continue;if(Q.type==="text"&&typeof Q.text==="string"&&Q.text.length>0){let H=PA(Q.text);if(H){if(this.pendingServerToolInputs.push(H),this.pendingServerToolInputs.length>20)this.pendingServerToolInputs.shift()}if(jA(Q.text))continue;let W=$.uuid??Z?.id;this.emit("assistant_text",{uuid:W,text:Q.text,parentToolUseId:J}),this.emit("assistant_block_stop",{index:W,parentToolUseId:J})}else if(Q.type==="tool_use"&&typeof Q.id==="string"&&typeof Q.name==="string")this.emitToolUseOnce(Q.id,Q.name,Q.input??{},J);else if(Q.type==="server_tool_use"&&typeof Q.id==="string"&&typeof Q.name==="string")this.emitToolUseOnce(Q.id,DA(Q.name),{tool:Q.name,input:this.serverToolInput(Q.name,Q.input??{})},J);else if(Q.type==="tool_result"&&typeof Q.tool_use_id==="string")this.emitToolResultOnce(Q.tool_use_id,LA(Q.content),Q.is_error===!0,J)}}emitToolUseOnce($,Z,J,Y){if(this.emittedToolUseIds.has($))return;if(this.emittedToolUseIds.add($),!Z.trim())A(`claude-agent-process: tool_use ${$} has an empty name`),Z="MISS";this.emit("tool_use",{id:$,name:Z,input:J,parentToolUseId:Y})}serverToolInput($,Z){let J=Z;if(J&&typeof J==="object"&&!Array.isArray(J)&&Object.keys(J).length>0)return J;let Y=this.pendingServerToolInputs.findIndex((Q)=>Q.name===$);if(Y>=0){let[Q]=this.pendingServerToolInputs.splice(Y,1);return Q.input}return J}emitToolResultOnce($,Z,J,Y){if(this.emittedToolResultIds.has($))return;this.emittedToolResultIds.add($),this.emit("tool_result",{tool_use_id:$,content:Z,is_error:J,parentToolUseId:Y})}handleUserMessage($){let Z=$.message?.content;if($.isMeta===!0&&$.promptSource==="sdk"&&typeof Z==="string"&&Z.trim())this.emit("scheduled_turn_input",{text:Z,promptId:typeof $.promptId==="string"&&$.promptId?$.promptId:null});let J=Array.isArray(Z)?Z:[];for(let Y of J){if(!Y||typeof Y!=="object")continue;if(Y.type!=="tool_result"||typeof Y.tool_use_id!=="string")continue;let Q=$.tool_use_result,H=mJ(Y.content),W=Q&&typeof Q==="object"?[typeof Q.stdout==="string"?Q.stdout:"",typeof Q.stderr==="string"?Q.stderr:""].filter(Boolean).join(`
|
|
62
|
-
`):"",X=H||W;this.emitToolResultOnce(Y.tool_use_id,X,Y.is_error===!0||Q?.interrupted===!0,$.parent_tool_use_id??null)}}handleResultMessage($){if(typeof $.session_id==="string"&&$.session_id)this.sessionId=$.session_id;this.turnActive=!1;let Z=
|
|
63
|
-
`):String($.result??$.error??$.api_error_message??W)}:{},duration_ms:this.lastResult.duration_ms,usage:this.lastUsage,checkpoint:!this.lastResult.is_error&&this.lastAssistantUuid&&this.sessionId?{provider:"claude",kind:"assistant-message",id:this.lastAssistantUuid,source:{provider:"claude",sessionId:this.sessionId,cwd:this.opts.workDir}}:null})}failTurnStart($){this.turnActive=!1,this.lastAssistantUuid=null,this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:this.lastUsage,subtype:"claude_turn_start_failed",is_error:!0},this.emit("result",{subtype:this.lastResult.subtype,is_error:!0,duration_ms:null,usage:this.lastUsage,error:$.message})}}});var rJ={};i$(rJ,{waitForTokenSourceModelRefresh:()=>W9,tokenSourceRuntimeModels:()=>g1,tokenSourceRuntimeModel:()=>x$,tokenSourceProcessRevision:()=>h2,tokenSourceFactories:()=>c1,setDefaultTokenSource:()=>W8,scrubDshEnv:()=>v2,scrubAnthropicEnv:()=>Z$,resetTokenSourceRegistry:()=>X8,registerTokenSourceFactory:()=>M0,registerTokenSource:()=>H8,refreshAllTokenSourceModels:()=>g2,pendingTokenSourceModelRefresh:()=>m1,listTokenSourcesByAgent:()=>oJ,listTokenSources:()=>A$,listEnabledTokenSourcesByAgent:()=>H9,getTokenSource:()=>p});function Z$($){let Z={...$};for(let J of OA)delete Z[J];return Z}function v2($){let Z=Z$($);for(let J of Object.keys(Z))if(/^(DSH_|DEEPSEEK_|LODESTAR_DSH_|ZAI_|ZHIPU_)/.test(J))delete Z[J];return Z}function g1($){return $.modelSelection?[...$.models,...$.modelSelection.availableModels.filter((Z)=>!$.models.some((J)=>J.model===Z.model))]:$.models}function x$($,Z){let J=(Y)=>$.agent==="claude"?Y?.replace(/\[1m\]$/,""):Y;return g1($).find((Y)=>J(Y.model)===J(Z))}function h2($,Z){let J=$?.spawnRevision??null,Y=$?.modelEnvironmentRevision?.(Z??$.defaultModel);return Y===void 0?J:JSON.stringify([J,Y])}function M0($){nJ.set($.kind,$)}function c1(){return[...nJ.values()]}function H8($,Z){if(I2.set($.id,$),Z?.default||Q9===null)Q9=$.id}function p($){return $?I2.get($):void 0}function A$(){return[...I2.values()]}function oJ($){return A$().filter((Z)=>Z.agent===$)}function H9($){return oJ($).filter((Z)=>Z.enabled)}function W8($){if(I2.has($))Q9=$}function X8(){I2.clear(),Q9=null,aJ++}function g2(){let $=aJ;if(I1?.generation===$)return I1.promise;let Z=Promise.allSettled(A$().map(async(J)=>{await J.refreshModels(),A(`token-source ${J.id}: ${J.models.length} models loaded`)})).then(()=>{}).finally(()=>{if(I1?.promise===Z)I1=null});return I1={generation:$,promise:Z},Z}function m1(){return I1?.promise??null}async function W9(){let $;while($=m1())await $}var OA,nJ,I2,Q9=null,aJ=0,I1=null;var $0=E(()=>{g();OA=["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_MODEL","ANTHROPIC_SMALL_FAST_MODEL","CLAUDE_CODE_SUBAGENT_MODEL","ANTHROPIC_CUSTOM_HEADERS","CLAUDE_CODE_OAUTH_TOKEN","CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_VERTEX","CLAUDE_CODE_USE_FOUNDRY","CLAUDE_CODE_EFFORT_LEVEL"];nJ=new Map;I2=new Map});function X9($){let Z=$.tokenSourceId?p($.tokenSourceId):void 0;if($.tokenSourceId&&!Z)throw Error(`token source not found: ${$.tokenSourceId}`);if(Z&&!Z.enabled)throw Error(`token source disabled: ${Z.id}`);if(Z&&Z.agent!==$.provider)throw Error(`token source ${Z.id} belongs to ${Z.agent}, not ${$.provider}`);if(Z?.modelCatalogState?.status==="failed")throw Error(`model catalog refresh failed for ${Z.id}: ${Z.modelCatalogState.error??"MISS"}`);if(Z?.modelCatalogState?.status==="idle"||Z?.modelCatalogState?.status==="loading")throw Error(`model catalog is not ready for ${Z.id}: ${Z.modelCatalogState.status}`);let J=$.model??Z?.defaultModel,Y=h2(Z,J),Q=Z&&x$(Z,J);if(Z&&J&&!Q)throw Error(`model is not present in token source ${Z.id}: ${J}`);if(Q&&(Q.unavailableReason||!Q.efforts.length||$.effort!==void 0&&!Q.efforts.includes($.effort)))throw Error(`model effort unavailable: ${Z.id}/${J}/${$.effort??"MISS"}`);let H=Z&&J?Z.resolveSpawnModel(J):J;if(J&&!H)throw Error(`model did not resolve: ${$.tokenSourceId??"default"}/${J}`);let W=Z?(X)=>Z.spawnEnv(X,H):void 0;if($.provider==="dsh"){if(!Z||!H||!Q0($.effort))throw Error("DSH requires a configured source, model and valid effort");return{process:new r7({...$,model:H,effort:$.effort,tokenSourceId:Z.id,transformEnv:W}),sourceRevision:Y}}if($.provider==="claude"){if(Y8(),!F0($.effort))throw Error(`invalid Claude effort: ${$.effort??"MISS"}`);return{process:new Y9({workDir:$.workDir,model:H,effort:$.effort,...$.launch?.kind==="fresh"||!$.launch?{}:{resumeSessionId:$.launch.source.sessionId,...$.launch.kind==="fork"?{forkSession:!0}:{},...$.launch.kind==="fork"&&$.launch.through?.provider==="claude"?{resumeSessionAt:$.launch.through.id}:{}},...$.developerInstructions?{appendSystemPrompt:$.developerInstructions}:{},...$.allowDelegation===!1?{allowDelegation:!1}:{},...$.profile?{profile:$.profile}:{},...Z?{settingSources:Z.settingSources??["project","local"]}:{},...$.managedSkillPluginPath?{managedSkillPluginPath:$.managedSkillPluginPath}:{},tokenSourceId:Z?.id??null,transformEnv:W,hostEnv:$.hostEnv}),sourceRevision:Y}}if($.effort!==void 0&&!v0($.effort))throw Error(`invalid Codex effort: ${$.effort}`);return{process:new w1({workDir:$.workDir,model:H,effort:$.effort,launch:$.launch,...$.developerInstructions?{appendSystemPrompt:$.developerInstructions}:{},...$.allowDelegation===!1?{allowDelegation:!1}:{},tokenSourceId:Z?.id??null,transformEnv:W,hostEnv:$.hostEnv,serviceName:$.serviceName}),sourceRevision:Y}}var V8=E(()=>{A0();SJ();f2();s$();$0()});function V9($,Z){return`http://${$==="0.0.0.0"?"127.0.0.1":$==="::"||$==="::1"?"[::1]":$}:${Z}`}async function z8($){let Z=await _8("feishu chat.get",()=>t.im.chat.get({path:{chat_id:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)z9("feishu chat.get",Z);let J=Z.data?.owner_id;if(!J)throw Error("feishu chat.get returned no owner_id; cannot add project group owner to tasklist");return J}async function G8($,Z){let J=await _8("feishu tasklist.create",()=>t.task.v2.tasklist.create({params:{user_id_type:"open_id"},data:{name:$,members:[{id:Z,type:"user",role:"editor"}]}}));if(J.code&&J.code!==0)z9("feishu tasklist.create",J);let Y=J.data?.tasklist,Q=Y?.guid;if(!Q)throw Error("feishu tasklist.create returned no guid");return{guid:Q,name:Y?.name||$,url:Y?.url??"",createdAt:Y?.created_at}}async function A8($){let Z=await _8("feishu tasklist.delete",()=>t.task.v2.tasklist.delete({path:{tasklist_guid:$}}));if(Z.code&&Z.code!==0)z9("feishu tasklist.delete",Z)}function tJ($,Z){let J=Z&&typeof Z==="object"?Z:{},Y=J.response?.data&&typeof J.response.data==="object"?J.response.data:J.data&&typeof J.data==="object"?J.data:J,Q=Y.code??J.code,H=Y.msg??Y.message??J.msg??J.message??"unknown error",W=Y.error?.permission_violations??Y.permission_violations??J.error?.permission_violations,X=Array.isArray(W)?W.map((V)=>V?.scope??V?.subject??V?.name??V).filter(Boolean).join(", "):"";return`${$} failed code=${Q??"unknown"} msg=${H}${X?` missing_scopes=${X}`:""}`}async function _8($,Z){try{return await Z()}catch(J){z9($,J)}}function z9($,Z){throw Error(tJ($,Z))}var sJ=E(()=>{s()});var Z0={};i$(Z0,{writeAliveMarker:()=>n2,urgentApp:()=>H1,uploadImageKey:()=>g8,uploadAndSend:()=>r2,updateCard:()=>Y$,unbindSessionChat:()=>_9,tempProjectName:()=>J$,tempChatName:()=>E8,setPendingConversationLaunchChecked:()=>k$,sendTextRaw:()=>w,sendText:()=>T,sendImage:()=>j9,sendFile:()=>RY,sendCard:()=>d,sanitizeSessionName:()=>m8,resolveProjectDir:()=>q9,replaceTurnAnchors:()=>n0,registerTempSessionLease:()=>j8,refreshChatList:()=>a2,readAliveMarker:()=>b8,provisionProject:()=>c8,projectProfile:()=>p1,preferredChatForSession:()=>X0,loadTempSessionLeases:()=>P8,loadSessionTurnsMap:()=>O8,loadSessionResumeMap:()=>R8,loadSessionModelMap:()=>N8,loadSessionChatMap:()=>M8,listNormalChatIdsByName:()=>D9,isOpenAIChatGPTAuthenticated:()=>t2,hasTempSessionLease:()=>F8,getTurnAnchors:()=>l2,getTenantToken:()=>_$,getSessionResumeRef:()=>Q1,getSessionModelSelection:()=>k8,getSessionBranchBase:()=>i2,getPendingConversationLaunch:()=>d2,formatFeishuApiError:()=>tJ,findNormalChatIdByName:()=>P9,fetchChatOwnerOpenId:()=>z8,fetchChatName:()=>h8,ensureChatForSession:()=>y8,downloadAttachment:()=>o2,disbandChatForSessionExact:()=>v8,disbandChatForSession:()=>f8,deleteTasklistByGuid:()=>A8,deleteReaction:()=>U0,createTempChatForSession:()=>w8,createTasklistWithOwner:()=>G8,client:()=>t,clearSessionResumeChecked:()=>l1,clearSessionConversationState:()=>C8,chatNameCache:()=>V0,chatIdForSession:()=>L9,bindSessionToChat:()=>u1,bindSessionResumeChecked:()=>p2,bindSessionModelChecked:()=>x8,bindSessionModel:()=>S8,appendTurnAnchorChecked:()=>T8,addReaction:()=>b0,PROJECTS_ROOT:()=>KY,MAX_UPLOAD_BYTES:()=>I8});import*as HY from"@larksuiteoapi/node-sdk";import{execSync as WY}from"node:child_process";import{randomUUID as D8}from"node:crypto";import{existsSync as TA,mkdirSync as B8,readFileSync as J1,statSync as XY,writeFileSync as VY}from"node:fs";import{readFile as zY}from"node:fs/promises";import{homedir as eJ}from"node:os";import{basename as Z1,extname as EA,isAbsolute as GY,join as A9}from"node:path";function q8(){let $={};for(let[Z,J]of C0)$[Z]=J;G0(o6,$)}function P8(){C0.clear();try{let $=JSON.parse(J1(o6,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("lease file must contain an object");for(let[Z,J]of Object.entries($)){let Y=J;if(typeof Z!=="string"||!Z||Y.chatId!==Z||typeof Y.sessionName!=="string"||!J$(Y.sessionName)||typeof Y.createdAt!=="number"||!Number.isFinite(Y.createdAt)){A(`feishu: rejected malformed temp-session lease chat=${Z}`);continue}C0.set(Z,{chatId:Z,sessionName:Y.sessionName,createdAt:Y.createdAt})}A(`feishu: loaded ${C0.size} temporary-session leases`)}catch($){if($?.code!=="ENOENT")A(`feishu: load temp-session leases failed: ${$?.message??$}`)}}function j8($,Z){if(!J$($))throw Error(`refusing to lease non-temporary session name "${$}"`);if(!Z)throw Error("cannot lease a temporary session without chat_id");for(let Q of C0.values())if(Q.sessionName===$&&Q.chatId!==Z)throw Error(`temporary session name "${$}" is already leased to ${Q.chatId}`);let J=C0.get(Z),Y={sessionName:$,chatId:Z,createdAt:Date.now()};C0.set(Z,Y);try{q8()}catch(Q){if(J)C0.set(Z,J);else C0.delete(Z);throw Q}}function F8($,Z){let J=C0.get(Z);return J?.sessionName===$&&J.chatId===Z}function p1($){return I.projects[$]}function q9($){return p1($)?.cwd?.trim()||A9(KY,$)}function Y1($,Z={}){return fetch($,{...Z,signal:Z.signal??AbortSignal.timeout(NA)})}async function _$(){if(G9&&Date.now()<$Y)return G9;return K8??=(async()=>{let $=await Y1("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({app_id:AY,app_secret:_Y})}),Z=await $.json();if(!$.ok||!Z.tenant_access_token)throw Error(`feishu: tenant token failed HTTP ${$.status} code=${Z.code??"MISS"} msg=${Z.msg??"MISS"}`);return G9=Z.tenant_access_token,$Y=Date.now()+Math.max(0,(Z.expire??7200)-60)*1000,G9})().finally(()=>{K8=null}),K8}function M8(){try{let $=JSON.parse(J1(i6,"utf8"));for(let[Z,J]of Object.entries($))if(typeof J==="string")X0.set(Z,J);A(`feishu: loaded ${X0.size} session→chat bindings`)}catch($){if($?.code!=="ENOENT")A(`feishu: load session-chat-map failed: ${$?.message??$}`)}}function BY(){try{L8()}catch($){A(`feishu: save session-chat-map failed: ${$}`)}}function L8(){let $={};for(let[Z,J]of X0)$[Z]=J;G0(i6,$)}function u1($,Z){if(X0.get($)===Z)return;let J=X0.get($);X0.set($,Z),BY(),A(`feishu: bound session "${$}" → ${Z}${J?` (was ${J})`:""}`)}function _9($){let Z=X0.get($);if(!Z)return;X0.delete($),BY(),A(`feishu: unbound session "${$}" from ${Z}`)}function m2($,Z){let J=W0.get($)??{};J[Z.provider]=Z,W0.set($,J)}function ZY($,Z){if(!$||typeof $!=="object"||Array.isArray($))return null;let J=$,Y=e0(J.provider)?J.provider:Z??null;if(!Y||Z&&Y!==Z)return null;let Q=typeof J.sessionId==="string"?J.sessionId.trim():typeof J.session_id==="string"?J.session_id.trim():"";if(!Q)return null;if(J.cwd===void 0||J.cwd===null)return{provider:Y,sessionId:Q,cwd:null};if(typeof J.cwd!=="string"||!GY(J.cwd))return null;return{provider:Y,sessionId:Q,cwd:J.cwd}}function JY($){let Z=$.sessionId.trim();if(!Z)throw Error("cannot bind an empty conversation session id");if(!e0($.provider))throw Error(`cannot bind an unknown conversation provider: ${String($.provider)}`);if(typeof $.cwd!=="string"||!GY($.cwd))throw Error(`cannot bind a conversation without an absolute cwd: ${String($.cwd)}`);return{provider:$.provider,sessionId:Z,cwd:$.cwd}}function SA($,Z,J){if(typeof $!=="string")return JY($);if(!Z)throw Error("cannot bind a conversation without a provider");return JY({provider:Z,sessionId:$,cwd:J??null})}function R8(){try{let $=JSON.parse(J1(d6,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("resume map must contain an object");W0.clear();for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){m2(Z,{provider:"codex",sessionId:J.trim(),cwd:null});continue}if(!J||typeof J!=="object"||Array.isArray(J))continue;let Y=J,Q=ZY(Y);if(Q){m2(Z,Q);continue}for(let H of q7){let W=Y[H];if(typeof W==="string"&&W.trim()){m2(Z,{provider:H,sessionId:W.trim(),cwd:null});continue}let X=ZY(W,H);if(X)m2(Z,X)}}A(`feishu: loaded ${W0.size} session→resume bindings`)}catch($){if($?.code!=="ENOENT")A(`feishu: load session-resume-map failed: ${$?.message??$}`)}}function K9(){let $={};for(let[Z,J]of W0){let Y={};if(J.codex)Y.codex={...J.codex};if(J.claude)Y.claude={...J.claude};if(J.dsh)Y.dsh={...J.dsh};$[Z]=Y}G0(d6,$)}function p2($,Z,J,Y){let Q=SA(Z,J,Y),H=W0.get($),W=H?{...H}:void 0,X=H?.[Q.provider];if(X?.sessionId===Q.sessionId&&X.cwd===Q.cwd)return;m2($,Q);try{K9()}catch(V){if(W)W0.set($,W);else W0.delete($);throw V}}function Q1($,Z="codex"){let J=W0.get($)?.[Z];return J?{...J}:null}function l1($,Z){let J=W0.get($);if(!J||Z&&J[Z]===void 0)return;let Y={...J};if(!Z)W0.delete($);else{let Q={...J};if(delete Q[Z],!Q.codex&&!Q.claude)W0.delete($);else W0.set($,Q)}try{K9()}catch(Q){throw W0.set($,Y),Q}}function qY($){if(!$||typeof $!=="object")return null;let Z=$;if(!e0(Z.provider))return null;let J=typeof Z.sessionId==="string"?Z.sessionId.trim():"";if(!J)return null;let Y;if(Z.cwd===void 0||Z.cwd===null)Y=null;else if(typeof Z.cwd==="string"&&Z.cwd.trim())Y=Z.cwd;else return null;return{provider:Z.provider,sessionId:J,cwd:Y}}function LY($){if(!$||typeof $!=="object")return null;let Z=$,J=Z.source;if(!J||typeof J!=="object")return null;let Y=qY(J),Q=typeof Z.id==="string"?Z.id.trim():"";if(!Q||!Y)return null;if(Z.provider==="dsh"&&Z.kind==="event"&&Y.provider==="dsh"&&/^\d+$/.test(Q)&&Number.isSafeInteger(Number(Q)))return{provider:"dsh",kind:"event",id:Q,source:{...Y,provider:"dsh"}};if(Z.provider==="claude"&&Z.kind==="assistant-message"&&Y.provider==="claude")return{provider:"claude",kind:"assistant-message",id:Q,source:{...Y,provider:"claude"}};if(Z.provider==="codex"&&Z.kind==="turn"&&Y.provider==="codex")return{provider:"codex",kind:"turn",id:Q,source:{...Y,provider:"codex"}};return null}function DY($){if(!$||typeof $!=="object")return null;let Z=$;if(Z.kind==="fresh")return{kind:"fresh"};if(Z.kind!=="resume"&&Z.kind!=="fork")return null;let J=qY(Z.source);if(!J)return null;let Y=Z.kind==="resume"?{kind:"resume",source:J}:(()=>{if(!Object.prototype.hasOwnProperty.call(Z,"through"))return{kind:"fork",source:J};let Q=LY(Z.through);return Q?{kind:"fork",source:J,through:Q}:null})();if(!Y)return null;try{H0(Y,J.provider)}catch{return null}return Y}function xA($){if(!Array.isArray($))return[];return $.filter((Z)=>Z&&typeof Z.path==="string").map((Z)=>({tool:String(Z.tool??"Write"),path:String(Z.path),body:String(Z.body??"")})).filter((Z)=>Z.path!==""||Z.body!=="")}function kA($,Z){if(!$||typeof $!=="object")return null;let J=$;if(typeof J.ts!=="number"||!Number.isFinite(J.ts))return null;let Y=Object.prototype.hasOwnProperty.call(J,"checkpoint"),Q=LY(J.checkpoint);if(Y&&!Q)return null;if(!Q){if(Z!=="claude")return null;let H=typeof J.uuid==="string"?J.uuid.trim():"",W=typeof J.sid==="string"?J.sid.trim():"";if(!H||!W)return null;Q={provider:"claude",kind:"assistant-message",id:H,source:{provider:"claude",sessionId:W,cwd:null}}}return{checkpoint:Q,preview:String(J.preview??""),ts:J.ts,writes:xA(J.writes)}}function CA($){if(!$||typeof $!=="object")return null;let Z=$,J=DY(Z.launch);if(J?.kind!=="fork"||J.source.provider!=="claude"||J.source.cwd===null)return null;let Y=Z.previousSessionId,Q=Y===null?null:typeof Y==="string"&&Y.trim()?Y.trim():void 0;if(Q===void 0)return null;return{launch:{...J,source:{...J.source,provider:"claude"}},previousSessionId:Q}}function U8($){let Z=$.launch.through;if($.launch.source.provider!=="claude"||Z&&(Z.provider!=="claude"||Z.kind!=="assistant-message"||Z.source.provider!=="claude"))throw Error("pending conversation launch is not a Claude fork");return{launch:{kind:"fork",source:{...$.launch.source,provider:"claude"},...Z?{through:{...Z,provider:"claude",kind:"assistant-message",source:{...Z.source,provider:"claude"}}}:{}},previousSessionId:$.previousSessionId}}function O8(){try{let $=JSON.parse(J1(n6,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("turns map must contain an object");i.clear();let Z=0,J=0;for(let[Y,Q]of Object.entries($)){let H,W,X=null;if(Array.isArray(Q))H=Q,W=null;else if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let _=Q;if(!Array.isArray(_.anchors)||!Object.prototype.hasOwnProperty.call(_,"base")){J++;continue}if(H=_.anchors,_.base===null)W=null;else{let K=DY(_.base);if(!K){J++;continue}W=K}if(Object.prototype.hasOwnProperty.call(_,"pendingLaunch")){let K=CA(_.pendingLaunch);if(!K){J++;continue}X=K}}else{J++;continue}let V=W0.get(Y),z=V?.claude!==void 0&&V.codex===void 0?"claude":null,G=[];for(let _ of H){let K=kA(_,z);if(K)G.push(K);else J++}if(G.length||W!==null||X)i.set(Y,{base:W,anchors:G,...X?{pendingLaunch:X}:{}}),Z+=G.length}if(A(`feishu: loaded ${Z} turn anchors across ${i.size} sessions`),J>0)A(`feishu: rejected ${J} malformed turn anchors while loading`)}catch($){if($?.code!=="ENOENT")A(`feishu: load session-turns-map failed: ${$?.message??$}`)}}function u2(){let $={};for(let[Z,J]of i)$[Z]=J;G0(n6,$)}function T8($,Z){let J=i.get($),Y=[...J?.anchors??[],Z],Q=J?.base??null;if(Y.length>YY){let H=Y.splice(0,Y.length-YY),W=H[H.length-1].checkpoint;Q={kind:"fork",source:W.source,through:W}}i.set($,{base:Q,anchors:Y,...J?.pendingLaunch?{pendingLaunch:J.pendingLaunch}:{}});try{u2()}catch(H){if(J)i.set($,J);else i.delete($);throw H}}function l2($){return i.get($)?.anchors??[]}function i2($){return i.get($)?.base??null}function d2($){let Z=i.get($)?.pendingLaunch;return Z?U8(Z):null}function k$($,Z){if(Z){if(Z.launch.source.cwd===null)throw Error("pending conversation launch source cwd is missing");H0(Z.launch,"claude",Z.launch.source.cwd)}let J=i.get($),Y=J?.base??null,Q=J?.anchors.slice()??[];if(!Z&&Q.length===0&&Y===null)i.delete($);else i.set($,{base:Y,anchors:Q,...Z?{pendingLaunch:U8(Z)}:{}});try{u2()}catch(H){if(J)i.set($,J);else i.delete($);throw H}}function n0($,Z,J,Y){let Q=i.get($),H=Y===void 0?Q?.pendingLaunch:Y??void 0,W=H?U8(H):void 0;if(Z.length===0&&J===null&&!W)i.delete($);else i.set($,{base:J,anchors:Z.slice(),...W?{pendingLaunch:W}:{}});try{u2()}catch(X){if(Q)i.set($,Q);else i.delete($);throw X}}function J$($){return QY.test($)?$.replace(QY,""):null}function E8($,Z=[]){let J=new Date,Y=(X)=>String(X).padStart(2,"0"),Q=`${Y(J.getMonth()+1)}${Y(J.getDate())}-${Y(J.getHours())}${Y(J.getMinutes())}`,H=new Set([...V0.values(),...i.keys(),...Z]),W=`${$}*${Q}`;for(let X=2;H.has(W);X++)W=`${$}*${Q}-${X}`;return W}function N8(){try{let $=JSON.parse(J1(a6,"utf8"));for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){R0.set(Z,{provider:C1(J),model:J,effort:null});continue}if(!J||typeof J!=="object")continue;let{model:Y,provider:Q}=J,H=e0(Q)?Q:typeof Y==="string"&&Y.trim()?C1(Y):"claude",W=typeof Y==="string"&&Y.trim()?Y:null;if(H==="claude"&&!W)continue;let{effort:X,tokenSourceId:V}=J,z=typeof V==="string"&&V.trim()?V.trim():null,G=H==="dsh"?Q0(X)?X:null:H==="claude"?F0(X)?X:null:v0(X)?X:null;R0.set(Z,{provider:H,model:W,effort:G,...z?{tokenSourceId:z}:{}})}A(`feishu: loaded ${R0.size} session→model bindings`)}catch($){if($?.code!=="ENOENT")A(`feishu: load session-model-map failed: ${$?.message??$}`)}}function bA(){try{B9()}catch($){A(`feishu: save session-model-map failed: ${$}`)}}function B9(){let $={};for(let[Z,J]of R0)$[Z]=J;G0(a6,$)}function S8($,Z,J,Y,Q){let H=R0.get($);if(H?.provider===Z&&H.model===J&&H.effort===Y&&(H.tokenSourceId??null)===(Q??null))return;R0.set($,{provider:Z,model:J,effort:Y,...Q?{tokenSourceId:Q}:{}}),bA()}function x8($,Z,J,Y,Q){let H=R0.get($),W={provider:Z,model:J,effort:Y,...Q?{tokenSourceId:Q}:{}};if(H?.provider===Z&&H.model===J&&H.effort===Y&&(H.tokenSourceId??null)===(Q??null))return;R0.set($,W);try{B9()}catch(X){if(H)R0.set($,H);else R0.delete($);throw X}}function k8($){let Z=R0.get($);if(Z)return Z;let J=J$($);return J?R0.get(J)??null:null}function C8($){let Z=X0.get($),J=W0.get($),Y=R0.get($),Q=i.get($),H=[...C0.entries()].filter(([,W])=>W.sessionName===$);X0.delete($),W0.delete($),R0.delete($),i.delete($);for(let[W]of H)C0.delete(W);try{L8(),K9(),B9(),u2(),q8()}catch(W){if(Z)X0.set($,Z);if(J)W0.set($,J);if(Y)R0.set($,Y);if(Q)i.set($,Q);for(let[V,z]of H)C0.set(V,z);let X=[W];for(let V of[L8,K9,B9,u2,q8])try{V()}catch(z){X.push(z)}throw X.length===1?X[0]:AggregateError(X,`failed to clear and restore conversation state for ${$}`)}}function n2($){try{G0(y4,$)}catch(Z){A(`feishu: write alive marker failed: ${Z}`)}}function b8(){if(!TA(y4))return[];try{let $=J1(y4,"utf8"),Z=JSON.parse($);return Array.isArray(Z)?Z.filter((J)=>typeof J==="string"):[]}catch($){return A(`feishu: read alive marker failed: ${$}`),[]}}function L9($){let Z=X0.get($);if(Z){let Y=V0.get(Z);if(Y&&Y!==$)A(`feishu: chatIdForSession("${$}"): persisted binding ${Z} has cached name "${Y}", using persisted binding`);return Z}let J=[];for(let[Y,Q]of V0)if(Q===$)J.push(Y);if(J.length===1)return J[0];if(J.length>1)A(`feishu: chatIdForSession("${$}"): ${J.length} candidates with no binding — [${J.join(", ")}]`);return null}async function a2(){try{let $;do{let Z=await t.im.chat.list({params:{page_size:100,...$?{page_token:$}:{}}});for(let J of Z.data?.items??[])if(J.chat_id&&J.name)V0.set(J.chat_id,J.name);$=Z.data?.page_token}while($);A(`feishu: refreshed chat list — ${V0.size} groups`)}catch($){A(`feishu: refresh chat list failed: ${$}`)}}async function D9(){let $=new Map,Z;do{let J=await t.im.chat.list({params:{page_size:100,...Z?{page_token:Z}:{}}});if(J.code&&J.code!==0)throw Error(`feishu chat.list failed code=${J.code} msg=${J.msg}`);for(let Y of J.data?.items??[]){if(!Y.chat_id||!Y.name)continue;if(Y.chat_status&&Y.chat_status!=="normal")continue;V0.set(Y.chat_id,Y.name);let Q=$.get(Y.name)??[];Q.push(Y.chat_id),$.set(Y.name,Q)}Z=J.data?.page_token}while(Z);return $}async function P9($){let Z=X0.get($);if(Z&&V0.get(Z)===$){let H=await jY(Z);if(H.name===$&&FY(H.status))return Z;V0.delete(Z),_9($)}let Y=(await D9()).get($)??[];if(Y.length===0)return null;let Q=X0.get($);if(Q&&Y.includes(Q))return Q;if(Y.length===1)return Y[0];throw Error(`multiple Feishu groups named "${$}": ${Y.join(", ")}`)}async function y8($,Z){if(!Z)throw Error("missing sender open_id; cannot add user to worktree group");let J=await P9($);if(J){let H=await yA(J,Z);return u1($,J),{chatId:J,created:!1,joined:H}}let Y=await t.im.chat.create({params:{user_id_type:"open_id",uuid:D8()},data:{name:$,user_id_list:[Z],group_message_type:"chat"}});if(Y.code&&Y.code!==0)throw Error(`feishu chat.create failed code=${Y.code} msg=${Y.msg}`);let Q=Y.data?.chat_id;if(!Q)throw Error("feishu chat.create returned no chat_id");return V0.set(Q,$),u1($,Q),{chatId:Q,created:!0,joined:!0}}async function w8($,Z){if(!Z)throw Error("missing sender open_id; cannot create temporary group");if(await P9($))throw Error(`temporary group name already exists: ${$}`);let Y=await t.im.chat.create({params:{user_id_type:"open_id",uuid:D8()},data:{name:$,user_id_list:[Z],group_message_type:"chat"}});if(Y.code&&Y.code!==0)throw Error(`feishu chat.create failed code=${Y.code} msg=${Y.msg}`);let Q=Y.data?.chat_id;if(!Q)throw Error("feishu chat.create returned no chat_id");return V0.set(Q,$),u1($,Q),{chatId:Q,created:!0,joined:!0}}async function f8($){let Z=await P9($);if(!Z)return _9($),{chatId:null,disbanded:!1};let J=await t.im.chat.delete({path:{chat_id:Z}});if(J.code&&J.code!==0)throw Error(`feishu chat.delete failed code=${J.code} msg=${J.msg}`);if(V0.delete(Z),X0.get($)===Z)_9($);return{chatId:Z,disbanded:!0}}async function v8($,Z){if(!Z)throw Error("cannot disband a temporary session without an exact chat_id");let J=await jY(Z);if(J.name!==$)throw Error(`refusing to delete chat ${Z}: expected name "${$}", got "${J.name??""}"`);if(!FY(J.status))throw Error(`refusing to delete chat ${Z}: status=${J.status??"unknown"}`);let Y=await t.im.chat.delete({path:{chat_id:Z}});if(Y.code&&Y.code!==0)throw Error(`feishu chat.delete failed code=${Y.code} msg=${Y.msg}`);return V0.delete(Z),{chatId:Z,disbanded:!0}}async function yA($,Z){let J;do{let Q=await t.im.chatMembers.get({path:{chat_id:$},params:{member_id_type:"open_id",page_size:100,...J?{page_token:J}:{}}});if(Q.code&&Q.code!==0)throw Error(`feishu chatMembers.get failed code=${Q.code} msg=${Q.msg}`);for(let H of Q.data?.items??[])if(H.member_id===Z)return!1;J=Q.data?.page_token}while(J);let Y=await t.im.chatMembers.create({path:{chat_id:$},params:{member_id_type:"open_id"},data:{id_list:[Z]}});if(Y.code&&Y.code!==0)throw Error(`feishu chatMembers.create failed code=${Y.code} msg=${Y.msg}`);return!0}async function h8($){try{let Z=await _$(),Y=await(await Y1(`https://open.feishu.cn/open-apis/im/v1/chats/${encodeURIComponent($)}`,{headers:{Authorization:`Bearer ${Z}`}})).json();if(Y?.code!==0)return A(`feishu: fetchChatName ${$} code=${Y?.code} msg=${Y?.msg}`),null;let Q=Y.data?.name;if(typeof Q==="string"&&Q)return V0.set($,Q),A(`feishu: fetchChatName ${$} → "${Q}" (point lookup)`),Q;return A(`feishu: fetchChatName ${$} — chat has no name (unnamed group?)`),null}catch(Z){return A(`feishu: fetchChatName ${$} failed: ${Z}`),null}}async function PY($,Z,J,Y){let Q=D8(),H=null;for(let W=0;W<c2.length;W++){if(c2[W]>0)await new Promise((X)=>setTimeout(X,c2[W]));try{let X=await t.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:Z,msg_type:J,content:Y,uuid:Q}});if(X?.code&&X.code!==0)return A(`feishu: send${$==="text"?"Text":"Card"} rejected chat=${Z} code=${X.code} msg=${X.msg}`),null;return X?.data?.message_id??null}catch(X){H=X,A(`feishu: send${$==="text"?"Text":"Card"} attempt ${W+1}/${c2.length} chat=${Z} failed: ${X}`)}}return A(`feishu: send${$==="text"?"Text":"Card"} chat=${Z} EXHAUSTED ${c2.length} retries: ${H}`),null}async function jY($){let Z=await t.im.chat.get({path:{chat_id:$}});if(Z.code&&Z.code!==0)throw Error(`feishu chat.get failed code=${Z.code} msg=${Z.msg}`);return{name:Z.data?.name??null,status:Z.data?.chat_status??null}}function FY($){return $===null||$==="normal"}async function T($,Z){return PY("text",$,"text",JSON.stringify({text:Z}))}async function d($,Z){return PY("card",$,"interactive",JSON.stringify(E$(Z)))}async function Y$($,Z){let J=await t.im.v1.message.patch({path:{message_id:$},data:{content:JSON.stringify(E$(Z))}});if(J?.code&&J.code!==0)throw Error(`feishu message.patch failed code=${J.code} msg=${J.msg}`)}async function w($,Z){try{let J=await _$(),Q=await(await Y1("https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id",{method:"POST",headers:{Authorization:`Bearer ${J}`,"Content-Type":"application/json"},body:JSON.stringify({receive_id:$,msg_type:"text",content:JSON.stringify({text:Z})})})).json();if(Q?.code!==0)return A(`feishu: sendTextRaw rejected chat=${$} code=${Q?.code} msg=${Q?.msg}`),null;return Q.data?.message_id??null}catch(J){return A(`feishu: sendTextRaw chat=${$} failed: ${J}`),null}}async function b0($,Z){if(!$)return null;try{return(await t.im.messageReaction.create({path:{message_id:$},data:{reaction_type:{emoji_type:Z}}}))?.data?.reaction_id??null}catch(J){return A(`feishu: addReaction ${Z} on ${$} failed: ${J}`),null}}async function U0($,Z){if(!$||!Z)return;try{await t.im.messageReaction.delete({path:{message_id:$,reaction_id:Z}})}catch(J){A(`feishu: deleteReaction ${Z} on ${$} failed: ${J}`)}}async function H1($,Z){if(!$){A("feishu: urgentApp skip — missing messageId");return}if(Z.length===0){A(`feishu: urgentApp skip — empty openIds (msg=${$})`);return}let J=await _$(),Y=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/urgent_app?user_id_type=open_id`;try{let H=await(await Y1(Y,{method:"PATCH",headers:{Authorization:`Bearer ${J}`,"Content-Type":"application/json"},body:JSON.stringify({user_id_list:Z})})).json();if(H?.code!==0){A(`feishu: urgentApp ${$} code=${H?.code} msg=${H?.msg}`);return}let W=H.data?.invalid_user_id_list??[],X=Z.length-W.length;A(`feishu: urgentApp ${$} ok — delivered=${X}${W.length?` invalid=${W.length}`:""}`)}catch(Q){A(`feishu: urgentApp ${$} failed: ${Q}`)}}async function o2($,Z,J,Y){try{let Q=await _$(),H=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/resources/${Z}?type=${J}`,W=await Y1(H,{headers:{Authorization:`Bearer ${Q}`}});if(!W.ok){A(`feishu: download ${J} HTTP ${W.status}: ${(await W.text()).slice(0,200)}`);return}let X=Buffer.from(await W.arrayBuffer());B8(t6,{recursive:!0});let V=Y?Y.replace(/[^a-zA-Z0-9._-]/g,"_"):`${Z.replace(/[^a-zA-Z0-9_-]/g,"_")}.png`,z=A9(t6,`${Date.now()}-${V}`);return VY(z,X),A(`feishu: downloaded ${J} ${z} (${X.length}B)`),z}catch(Q){A(`feishu: download ${J} failed: ${Q instanceof Error?Q.message:Q}`);return}}function fA($){return wA.has(EA($).toLowerCase())}async function MY($){let Z=await _$(),J=new Blob([Uint8Array.from(await zY($))]),Y=new FormData;Y.append("image_type","message"),Y.append("image",J,Z1($));let H=await(await Y1("https://open.feishu.cn/open-apis/im/v1/images",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Y})).json();if(H?.code!==0)return A(`feishu: uploadImage ${$} code=${H.code} msg=${H.msg}`),null;return H.data?.image_key??null}async function g8($){try{let Z=XY($);if(!Z.isFile())return A(`feishu: uploadImageKey not a file — ${$}`),null;if(Z.size>I8)return A(`feishu: uploadImageKey oversize — ${$} (${(Z.size/1024/1024).toFixed(1)} MB)`),null}catch(Z){return A(`feishu: uploadImageKey stat failed — ${$}: ${Z}`),null}return MY($)}async function vA($){let Z=await _$(),J=new Blob([Uint8Array.from(await zY($))]),Y=new FormData;Y.append("file_type","stream"),Y.append("file_name",Z1($)),Y.append("file",J,Z1($));let H=await(await Y1("https://open.feishu.cn/open-apis/im/v1/files",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Y})).json();if(H?.code!==0)return A(`feishu: uploadFile ${$} code=${H.code} msg=${H.msg}`),null;return H.data?.file_key??null}async function j9($,Z){try{let J=await t.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:$,msg_type:"image",content:JSON.stringify({image_key:Z})}});if(J?.code&&J.code!==0)return A(`feishu: sendImage rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return A(`feishu: sendImage failed chat=${$}: ${J}`),null}}async function RY($,Z){try{let J=await t.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:$,msg_type:"file",content:JSON.stringify({file_key:Z})}});if(J?.code&&J.code!==0)return A(`feishu: sendFile rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return A(`feishu: sendFile failed chat=${$}: ${J}`),null}}async function r2($,Z){try{let Y=XY(Z);if(!Y.isFile())return await T($,`❌ 出站文件: 路径不是文件 — ${Z}`),!1;if(Y.size>I8)return await T($,`❌ 出站文件: ${Z1(Z)} 超过 30 MB (${(Y.size/1024/1024).toFixed(1)} MB)`),!1}catch(Y){return await T($,`❌ 出站文件: 无法读取 ${Z} (${Y})`),!1}let J=fA(Z);try{if(J){let Y=await MY(Z);if(!Y)return await T($,`❌ 出站图片上传失败: ${Z1(Z)}`),!1;return await j9($,Y)!=null}else{let Y=await vA(Z);if(!Y)return await T($,`❌ 出站文件上传失败: ${Z1(Z)}`),!1;return await RY($,Y)!=null}}catch(Y){return A(`feishu: uploadAndSend ${Z} failed: ${Y}`),await T($,`❌ 出站文件异常: ${Z1(Z)} — ${Y}`),!1}}function c8($){B8($,{recursive:!0}),A(`feishu: provisioned ${$}`);let Z=A9(eJ(),".codex","config.toml");try{B8(A9(eJ(),".codex"),{recursive:!0});let J="";try{J=J1(Z,"utf8")}catch{}let Y=`[projects.${JSON.stringify($)}]`;if(!J.includes(Y)){let Q=J.trimEnd();J=`${Q}${Q?`
|
|
64
|
+
`:"";try{this.input.push({type:"user",session_id:this.sessionId??"",message:{role:"user",content:[{type:"text",text:J+$}]},parent_tool_use_id:null,priority:"now"})}catch(Y){let Q=Y instanceof Error?Y:Error(String(Y));_(`claude-agent-process: sendUserText failed: ${Q.message}`),this.failTurnStart(Q)}}sendInterrupt(){this.query?.interrupt().catch(($)=>_(`claude-agent-process: interrupt failed: ${$}`))}sendPermissionResponse($,Z,J){let Y=this.pendingPermissions.get(String($));if(!Y){_(`claude-agent-process: permission response for unknown request ${$}`);return}if(this.pendingPermissions.delete(String($)),Y.cleanup?.(),Z==="allow")Y.resolve({behavior:"allow",updatedInput:J?.updatedInput??{}});else Y.resolve({behavior:"deny",message:J?.denyMessage??""})}sendHookResponse($,Z={}){_("claude-agent-process: sendHookResponse ignored; hooks are handled by SDK callbacks")}isAlive(){return this.alive}async kill($=5000){if(!this.alive)return;if(this.expectedExit=!0,this.denyPendingPermissions("claude process is stopping"),this.input.abort(),!this.started||!this.query){this.finishExit(null,null);return}let Z=null;try{this.query.close()}catch(J){Z=J instanceof Error?J:Error(String(J))}if(!this.abortController.signal.aborted)this.abortController.abort(Z??Error("claude process shutdown requested"));if(!await this.waitForExit($)){let J=Error(`claude Agent SDK query did not exit within ${$}ms after close/abort`,Z?{cause:Z}:void 0);throw _(`claude-agent-process: kill failed: ${J.message}`),J}if(Z){let J=Error(`claude Agent SDK close failed: ${Z.message}`,{cause:Z});throw _(`claude-agent-process: kill failed: ${J.message}`),J}}async listModels(){if(!this.started)this.sendInitialize();if(await this.queryStart,!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");return(await this.query.supportedModels()).map(O_)}async setModelSettings($,Z){let J=e7($);if(!R0(Z))throw Error(`invalid Claude effort: ${String(Z)}`);if(this.opts.effort==="default"!==(Z==="default"))throw Error("effort 参数模式改变,需要使用新的启动环境恢复会话");if(!this.started)this.sendInitialize();if(await this.queryStart,!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");if(J)await this.query.setModel(J);await this.query.applyFlagSettings({effortLevel:Z==="default"?null:Z,ultracode:null}),this.opts.model=$,this.opts.effort=Z,this.lastModel=J?k$($):"claude:default",this.lastEffort=Z}async compactThread(){if(!this.input)throw Error("claude thread not initialized");return this.input.push({type:"user",session_id:this.sessionId??"",message:{role:"user",content:[{type:"text",text:"/compact"}]},parent_tool_use_id:null,priority:"now"}),new Promise(($,Z)=>{let J=!1,Y=()=>{this.off("context_compacted",Q),this.off("assistant_text",H),this.off("exit",W),this.off("error",X)},Q=()=>{if(J)return;J=!0,Y(),$()},H=(V)=>{if(J)return;if((V?.text??"").includes("Not enough messages to compact"))J=!0,Y(),Z(new e$)},W=()=>{if(J)return;J=!0,Y(),Z(Error("claude thread exited during /compact"))},X=(V)=>{if(J)return;J=!0,Y(),Z(V instanceof Error?V:Error(String(V)))};this.on("context_compacted",Q),this.on("assistant_text",H),this.once("exit",W),this.once("error",X)})}canUseTool($,Z,J){if($!=="AskUserQuestion")return Promise.resolve({behavior:"allow",updatedInput:Z});let Y=T_(Z);if(Y.length===0)return _("claude-agent-process: AskUserQuestion 无有效 questions — allow 原样"),Promise.resolve({behavior:"allow",updatedInput:Z});let Q={...Z,questions:Y},H=`claude_perm_${++this.requestCounter}`,W=J.toolUseID||H,X={request_id:H,tool_name:"AskUserQuestion",input:Q,tool_use_id:W},V=new Promise((z)=>{let G=(K)=>{J.signal.removeEventListener("abort",A),z(K)},A=()=>{if(!this.pendingPermissions.delete(H))return;G({behavior:"deny",message:"aborted"})};J.signal.addEventListener("abort",A,{once:!0}),this.pendingPermissions.set(H,{kind:"dialog",resolve:G,request:X})});return this.emitToolUseOnce(W,"AskUserQuestion",Q,null),this.emit("can_use_tool",X),V}async readLoop($){try{for await(let Z of $)this.handleMessage(Z);this.finishExit(null,null)}catch(Z){let J=Z instanceof Error?Z:Error(String(Z));if(this.expectedExit&&this.abortController.signal.aborted){_(`claude-agent-process: read loop stopped after requested shutdown: ${J.message}`),this.finishExit(null,null);return}_(`claude-agent-process: read loop failed: ${J.message}`),this.emit("error",J),this.finishExit(1,null)}}finishExit($,Z){if(!this.alive)return;this.alive=!1,this.turnActive=!1,this.denyPendingPermissions("claude process exited"),this.resolveExit(),_(`claude-agent-process: exited code=${$} signal=${Z} expected=${this.expectedExit}`),this.emit("exit",{code:$,signal:Z,expected:this.expectedExit})}denyPendingPermissions($){for(let[Z,J]of this.pendingPermissions)J.cleanup?.(),J.resolve({behavior:"deny",message:$}),this.pendingPermissions.delete(Z)}async waitForExit($){if(!this.alive)return!0;return new Promise((Z)=>{let J=!1,Y=(H)=>{if(J)return;J=!0,clearTimeout(Q),Z(H)},Q=setTimeout(()=>Y(!this.alive),Math.max(0,$));this.exitPromise.then(()=>Y(!0))})}handleMessage($){let Z=$;if(typeof Z.session_id==="string"&&Z.session_id)this.sessionId=Z.session_id;switch(Z.type){case"system":this.handleSystemMessage(Z);return;case"assistant":this.handleAssistantMessage(Z);return;case"user":this.handleUserMessage(Z);return;case"result":this.handleResultMessage(Z);return;case"rate_limit_event":this.emit("rate_limits_updated",Z.rate_limit_info);return;case"stream_event":return;default:_(`claude-agent-process: unhandled message type=${Z.type??"unknown"} subtype=${Z.subtype??""}`)}}handleSystemMessage($){switch($.subtype){case"init":if(typeof $.model==="string"&&$.model)this.lastModel=k$($.model);this.lastEffort=this.opts.effort,this.emit("init",{session_id:this.sessionId,raw:$});return;case"session_state_changed":if($.state==="running"&&!this.turnActive)this.turnActive=!0,this.lastThinkingTokens=null,this.lastAssistantUuid=null,this.emit("turn_started",{turn_id:$.uuid,thread_id:this.sessionId});else if($.state==="idle")this.turnActive=!1;return;case"compact_boundary":this.emit("context_compacted",{threadId:$.session_id??this.sessionId??void 0,sessionId:$.session_id??this.sessionId??void 0,itemId:$.uuid,phase:"event",sourceMethod:"claude_agent_sdk",sourceType:"compact_boundary",preTokens:$.compact_metadata?.pre_tokens,trigger:$.compact_metadata?.trigger});return;case"api_retry":_(`claude-agent-process: api retry attempt=${$.attempt}/${$.max_retries} status=${$.error_status} error=${$.error}`);return;case"thinking_tokens":if(typeof $.estimated_tokens!=="number"||!Number.isFinite($.estimated_tokens)||$.estimated_tokens<0){_("claude-agent-process: invalid thinking_tokens estimate");return}this.lastThinkingTokens=$.estimated_tokens,this.emit("thinking_progress",{estimatedTokens:$.estimated_tokens});return;case"permission_denied":_(`claude-agent-process: permission denied ${$.tool_name} ${$.tool_use_id}: ${$.message}`);return;case"task_started":this.emit("bg_task_started",{task_id:String($.task_id??""),tool_use_id:typeof $.tool_use_id==="string"?$.tool_use_id:void 0,task_type:typeof $.task_type==="string"?$.task_type:void 0,description:String($.description??""),subagent_type:typeof $.subagent_type==="string"?$.subagent_type:void 0,workflow_name:typeof $.workflow_name==="string"?$.workflow_name:void 0,prompt:typeof $.prompt==="string"?$.prompt:void 0});return;case"task_progress":this.emit("bg_task_progress",{task_id:String($.task_id??""),description:typeof $.description==="string"?$.description:void 0,subagent_type:typeof $.subagent_type==="string"?$.subagent_type:void 0,usage:$.usage,last_tool_name:typeof $.last_tool_name==="string"?$.last_tool_name:void 0,summary:typeof $.summary==="string"?$.summary:void 0});return;case"task_updated":this.emit("bg_task_updated",{task_id:String($.task_id??""),patch:$.patch&&typeof $.patch==="object"?$.patch:{}});return;case"task_notification":if(typeof $.task_id!=="string"||!$.task_id){_("claude-agent-process: task_notification missing task_id");return}if($.status!=="completed"&&$.status!=="failed"&&$.status!=="stopped"){_(`claude-agent-process: task_notification unknown status=${String($.status)} task=${$.task_id}`);return}this.emit("bg_task_settled",{task_id:$.task_id,tool_use_id:typeof $.tool_use_id==="string"?$.tool_use_id:void 0,status:$.status,summary:typeof $.summary==="string"?$.summary:void 0,usage:$.usage});return;default:_(`claude-agent-process: unhandled system subtype=${String($.subtype??"unknown")}`);return}}handleAssistantMessage($){if(!$.parent_tool_use_id)this.lastThinkingTokens=null;let Z=$.message,J=typeof $.parent_tool_use_id==="string"&&$.parent_tool_use_id?$.parent_tool_use_id:null;if(!J&&typeof $.uuid==="string")this.lastAssistantUuid=$.uuid;if(typeof Z?.model==="string"&&Z.model)this.lastModel=k$(Z.model);let Y=Array.isArray(Z?.content)?Z.content:[];for(let Q of Y){if(!Q||typeof Q!=="object")continue;if(Q.type==="text"&&typeof Q.text==="string"&&Q.text.length>0){let H=R_(Q.text);if(H){if(this.pendingServerToolInputs.push(H),this.pendingServerToolInputs.length>20)this.pendingServerToolInputs.shift()}if(U_(Q.text))continue;let W=$.uuid??Z?.id;this.emit("assistant_text",{uuid:W,text:Q.text,parentToolUseId:J}),this.emit("assistant_block_stop",{index:W,parentToolUseId:J})}else if(Q.type==="tool_use"&&typeof Q.id==="string"&&typeof Q.name==="string")this.emitToolUseOnce(Q.id,Q.name,Q.input??{},J);else if(Q.type==="server_tool_use"&&typeof Q.id==="string"&&typeof Q.name==="string")this.emitToolUseOnce(Q.id,M_(Q.name),{tool:Q.name,input:this.serverToolInput(Q.name,Q.input??{})},J);else if(Q.type==="tool_result"&&typeof Q.tool_use_id==="string")this.emitToolResultOnce(Q.tool_use_id,F_(Q.content),Q.is_error===!0,J)}}emitToolUseOnce($,Z,J,Y){if(this.emittedToolUseIds.has($))return;if(this.emittedToolUseIds.add($),!Z.trim())_(`claude-agent-process: tool_use ${$} has an empty name`),Z="MISS";this.emit("tool_use",{id:$,name:Z,input:J,parentToolUseId:Y})}serverToolInput($,Z){let J=Z;if(J&&typeof J==="object"&&!Array.isArray(J)&&Object.keys(J).length>0)return J;let Y=this.pendingServerToolInputs.findIndex((Q)=>Q.name===$);if(Y>=0){let[Q]=this.pendingServerToolInputs.splice(Y,1);return Q.input}return J}emitToolResultOnce($,Z,J,Y){if(this.emittedToolResultIds.has($))return;this.emittedToolResultIds.add($),this.emit("tool_result",{tool_use_id:$,content:Z,is_error:J,parentToolUseId:Y})}handleUserMessage($){let Z=$.message?.content;if($.isMeta===!0&&$.promptSource==="sdk"&&typeof Z==="string"&&Z.trim())this.emit("scheduled_turn_input",{text:Z,promptId:typeof $.promptId==="string"&&$.promptId?$.promptId:null});let J=Array.isArray(Z)?Z:[];for(let Y of J){if(!Y||typeof Y!=="object")continue;if(Y.type!=="tool_result"||typeof Y.tool_use_id!=="string")continue;let Q=$.tool_use_result,H=cJ(Y.content),W=Q&&typeof Q==="object"?[typeof Q.stdout==="string"?Q.stdout:"",typeof Q.stderr==="string"?Q.stderr:""].filter(Boolean).join(`
|
|
65
|
+
`):"",X=H||W;this.emitToolResultOnce(Y.tool_use_id,X,Y.is_error===!0||Q?.interrupted===!0,$.parent_tool_use_id??null)}}handleResultMessage($){if(typeof $.session_id==="string"&&$.session_id)this.sessionId=$.session_id;this.turnActive=!1;let Z=q_($.usage),J=$.modelUsage??$.model_usage,Y=P_(J);if(!Z&&!Y.usage)_(`claude-agent-process: result usage missing rootKeys=${J8($).join(",")||"-"} usageKeys=${J8($.usage).join(",")||"-"} modelUsageKeys=${J8(J).join(",")||"-"}`);if(this.lastUsage=Z,Y.usage)this.cumulativeUsageFromResults=Y9(Y.usage),this.lastTotalUsage=Y9(Y.usage);else if(Z)this.cumulativeUsageFromResults=j_(this.cumulativeUsageFromResults,Z),this.lastTotalUsage=Y9(this.cumulativeUsageFromResults);else this.lastTotalUsage=this.cumulativeUsageFromResults?Y9(this.cumulativeUsageFromResults):null;if(Y.contextWindow!=null){let X=bJ(this.opts.model,this.tokenSourceId);if(Y8.set(X,Y.contextWindow),this.tokenSourceId)for(let[V,z]of Object.entries(J??{})){let G=z?.contextWindow;if(typeof G==="number"&&G>0)xJ(this.tokenSourceId,V,G)}}this.lastContextWindow=Y8.get(bJ(this.opts.model,this.tokenSourceId))??Y.contextWindow??null;let Q=W9(this.opts.workDir,this.sessionId??""),H=gJ(Q);if(this.lastContextTokens=CJ(H)??(wJ(Q)?CJ(Z):null),this.lastTotalUsage||this.lastUsage)this.emit("token_usage",{usage:this.lastUsage,totalUsage:this.lastTotalUsage,contextWindow:this.lastContextWindow,threadId:this.sessionId??void 0,turnId:$.uuid});let W=typeof $.subtype==="string"?$.subtype:$.is_error?"error":"success";this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:typeof $.duration_ms==="number"?$.duration_ms:null,num_turns:typeof $.num_turns==="number"?$.num_turns:1,usage:this.lastUsage,subtype:W,is_error:$.is_error===!0||W!=="success"},this.emit("result",{subtype:W,is_error:this.lastResult.is_error,...this.lastResult.is_error?{error:Array.isArray($.errors)&&$.errors.length?$.errors.map(String).join(`
|
|
66
|
+
`):String($.result??$.error??$.api_error_message??W)}:{},duration_ms:this.lastResult.duration_ms,usage:this.lastUsage,checkpoint:!this.lastResult.is_error&&this.lastAssistantUuid&&this.sessionId?{provider:"claude",kind:"assistant-message",id:this.lastAssistantUuid,source:{provider:"claude",sessionId:this.sessionId,cwd:this.opts.workDir}}:null})}failTurnStart($){this.turnActive=!1,this.lastAssistantUuid=null,this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:this.lastUsage,subtype:"claude_turn_start_failed",is_error:!0},this.emit("result",{subtype:this.lastResult.subtype,is_error:!0,duration_ms:null,usage:this.lastUsage,error:$.message})}}});var oJ={};n$(oJ,{waitForTokenSourceModelRefresh:()=>G9,tokenSourceRuntimeModels:()=>p1,tokenSourceRuntimeModel:()=>C$,tokenSourceProcessRevision:()=>m2,tokenSourceFactories:()=>l1,setDefaultTokenSource:()=>V8,scrubDshEnv:()=>c2,scrubAnthropicEnv:()=>J$,resetTokenSourceRegistry:()=>z8,registerTokenSourceFactory:()=>U0,registerTokenSource:()=>X8,refreshAllTokenSourceModels:()=>p2,pendingTokenSourceModelRefresh:()=>i1,listTokenSourcesByAgent:()=>aJ,listTokenSources:()=>A$,listEnabledTokenSourcesByAgent:()=>z9,getTokenSource:()=>p});function J$($){let Z={...$};for(let J of S_)delete Z[J];return Z}function c2($){let Z=J$($);for(let J of Object.keys(Z))if(/^(DSH_|DEEPSEEK_|LODESTAR_DSH_|ZAI_|ZHIPU_)/.test(J))delete Z[J];return Z}function p1($){return $.modelSelection?[...$.models,...$.modelSelection.availableModels.filter((Z)=>!$.models.some((J)=>J.model===Z.model))]:$.models}function C$($,Z){let J=(Y)=>$.agent==="claude"?Y?.replace(/\[1m\]$/,""):Y;return p1($).find((Y)=>J(Y.model)===J(Z))}function m2($,Z){let J=$?.spawnRevision??null,Y=$?.modelEnvironmentRevision?.(Z??$.defaultModel);return Y===void 0?J:JSON.stringify([J,Y])}function U0($){dJ.set($.kind,$)}function l1(){return[...dJ.values()]}function X8($,Z){if(u2.set($.id,$),Z?.default||V9===null)V9=$.id}function p($){return $?u2.get($):void 0}function A$(){return[...u2.values()]}function aJ($){return A$().filter((Z)=>Z.agent===$)}function z9($){return aJ($).filter((Z)=>Z.enabled)}function V8($){if(u2.has($))V9=$}function z8(){u2.clear(),V9=null,nJ++}function p2(){let $=nJ;if(u1?.generation===$)return u1.promise;let Z=Promise.allSettled(A$().map(async(J)=>{await J.refreshModels(),_(`token-source ${J.id}: ${J.models.length} models loaded`)})).then(()=>{}).finally(()=>{if(u1?.promise===Z)u1=null});return u1={generation:$,promise:Z},Z}function i1(){return u1?.promise??null}async function G9(){let $;while($=i1())await $}var S_,dJ,u2,V9=null,nJ=0,u1=null;var Z0=S(()=>{g();S_=["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL","ANTHROPIC_DEFAULT_FABLE_MODEL","ANTHROPIC_MODEL","ANTHROPIC_SMALL_FAST_MODEL","CLAUDE_CODE_SUBAGENT_MODEL","ANTHROPIC_CUSTOM_HEADERS","CLAUDE_CODE_OAUTH_TOKEN","CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_VERTEX","CLAUDE_CODE_USE_FOUNDRY","CLAUDE_CODE_EFFORT_LEVEL"];dJ=new Map;u2=new Map});function _9($){let Z=$.tokenSourceId?p($.tokenSourceId):void 0;if($.tokenSourceId&&!Z)throw Error(`token source not found: ${$.tokenSourceId}`);if(Z&&!Z.enabled)throw Error(`token source disabled: ${Z.id}`);if(Z&&Z.agent!==$.provider)throw Error(`token source ${Z.id} belongs to ${Z.agent}, not ${$.provider}`);if(Z?.modelCatalogState?.status==="failed")throw Error(`model catalog refresh failed for ${Z.id}: ${Z.modelCatalogState.error??"MISS"}`);if(Z?.modelCatalogState?.status==="idle"||Z?.modelCatalogState?.status==="loading")throw Error(`model catalog is not ready for ${Z.id}: ${Z.modelCatalogState.status}`);let J=$.model??Z?.defaultModel,Y=m2(Z,J),Q=Z&&C$(Z,J);if(Z&&J&&!Q)throw Error(`model is not present in token source ${Z.id}: ${J}`);if(Q&&(Q.unavailableReason||!Q.efforts.length||$.effort!==void 0&&!Q.efforts.includes($.effort)))throw Error(`model effort unavailable: ${Z.id}/${J}/${$.effort??"MISS"}`);let H=Z&&J?Z.resolveSpawnModel(J):J;if(J&&!H)throw Error(`model did not resolve: ${$.tokenSourceId??"default"}/${J}`);let W=Z?(X)=>Z.spawnEnv(X,H):void 0;if($.provider==="dsh"){if(!Z||!H||!X0($.effort))throw Error("DSH requires a configured source, model and valid effort");return{process:new s7({...$,model:H,effort:$.effort,tokenSourceId:Z.id,transformEnv:W}),sourceRevision:Y}}if($.provider==="claude"){if(H8(),!R0($.effort))throw Error(`invalid Claude effort: ${$.effort??"MISS"}`);return{process:new X9({workDir:$.workDir,model:H,effort:$.effort,...$.launch?.kind==="fresh"||!$.launch?{}:{resumeSessionId:$.launch.source.sessionId,...$.launch.kind==="fork"?{forkSession:!0}:{},...$.launch.kind==="fork"&&$.launch.through?.provider==="claude"?{resumeSessionAt:$.launch.through.id}:{}},...$.developerInstructions?{appendSystemPrompt:$.developerInstructions}:{},...$.allowDelegation===!1?{allowDelegation:!1}:{},...$.profile?{profile:$.profile}:{},...Z?{settingSources:Z.settingSources??["project","local"]}:{},...$.managedSkillPluginPath?{managedSkillPluginPath:$.managedSkillPluginPath}:{},tokenSourceId:Z?.id??null,transformEnv:W,hostEnv:$.hostEnv}),sourceRevision:Y}}if($.effort!==void 0&&!h0($.effort))throw Error(`invalid Codex effort: ${$.effort}`);return{process:new I1({workDir:$.workDir,model:H,effort:$.effort,launch:$.launch,...$.developerInstructions?{appendSystemPrompt:$.developerInstructions}:{},...$.allowDelegation===!1?{allowDelegation:!1}:{},tokenSourceId:Z?.id??null,transformEnv:W,hostEnv:$.hostEnv,serviceName:$.serviceName}),sourceRevision:Y}}var G8=S(()=>{K0();NJ();g2();Z1();Z0()});function A9($,Z){return`http://${$==="0.0.0.0"?"127.0.0.1":$==="::"||$==="::1"?"[::1]":$}:${Z}`}async function _8($){let Z=await B8("feishu chat.get",()=>s.im.chat.get({path:{chat_id:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)K9("feishu chat.get",Z);let J=Z.data?.owner_id;if(!J)throw Error("feishu chat.get returned no owner_id; cannot add project group owner to tasklist");return J}async function A8($,Z){let J=await B8("feishu tasklist.create",()=>s.task.v2.tasklist.create({params:{user_id_type:"open_id"},data:{name:$,members:[{id:Z,type:"user",role:"editor"}]}}));if(J.code&&J.code!==0)K9("feishu tasklist.create",J);let Y=J.data?.tasklist,Q=Y?.guid;if(!Q)throw Error("feishu tasklist.create returned no guid");return{guid:Q,name:Y?.name||$,url:Y?.url??"",createdAt:Y?.created_at}}async function K8($){let Z=await B8("feishu tasklist.delete",()=>s.task.v2.tasklist.delete({path:{tasklist_guid:$}}));if(Z.code&&Z.code!==0)K9("feishu tasklist.delete",Z)}function rJ($,Z){let J=Z&&typeof Z==="object"?Z:{},Y=J.response?.data&&typeof J.response.data==="object"?J.response.data:J.data&&typeof J.data==="object"?J.data:J,Q=Y.code??J.code,H=Y.msg??Y.message??J.msg??J.message??"unknown error",W=Y.error?.permission_violations??Y.permission_violations??J.error?.permission_violations,X=Array.isArray(W)?W.map((V)=>V?.scope??V?.subject??V?.name??V).filter(Boolean).join(", "):"";return`${$} failed code=${Q??"unknown"} msg=${H}${X?` missing_scopes=${X}`:""}`}async function B8($,Z){try{return await Z()}catch(J){K9($,J)}}function K9($,Z){throw Error(rJ($,Z))}var tJ=S(()=>{e()});var J0={};n$(J0,{writeAliveMarker:()=>w8,urgentApp:()=>V1,uploadImageKey:()=>u8,uploadAndSend:()=>e2,updateCard:()=>Q$,unbindSessionChat:()=>q9,tempProjectName:()=>Y$,tempChatName:()=>S8,setPendingConversationLaunchChecked:()=>b$,sendTextRaw:()=>w,sendText:()=>E,sendImage:()=>U9,sendFile:()=>MY,sendCard:()=>a,sanitizeSessionName:()=>l8,resolveProjectDir:()=>j9,replaceTurnAnchors:()=>a0,registerTempSessionLease:()=>M8,refreshChatList:()=>t2,readAliveMarker:()=>f8,provisionProject:()=>p8,projectProfile:()=>n1,preferredChatForSession:()=>G0,loadTempSessionLeases:()=>F8,loadSessionTurnsMap:()=>E8,loadSessionResumeMap:()=>O8,loadSessionModelMap:()=>x8,loadSessionChatMap:()=>U8,listNormalChatIdsByName:()=>M9,isOpenAIChatGPTAuthenticated:()=>$4,hasTempSessionLease:()=>R8,getTurnAnchors:()=>a2,getTenantToken:()=>K$,getSessionResumeRef:()=>X1,getSessionModelSelection:()=>b8,getSessionBranchBase:()=>o2,getPendingConversationLaunch:()=>r2,formatFeishuApiError:()=>rJ,findNormalChatIdByName:()=>R9,fetchChatOwnerOpenId:()=>_8,fetchChatName:()=>c8,ensureChatForSession:()=>v8,downloadAttachment:()=>s2,disbandChatForSessionExact:()=>g8,disbandChatForSession:()=>I8,deleteTasklistByGuid:()=>K8,deleteReaction:()=>T0,createTempChatForSession:()=>h8,createTasklistWithOwner:()=>A8,client:()=>s,clearSessionResumeChecked:()=>a1,clearSessionConversationState:()=>y8,chatNameCache:()=>_0,chatIdForSession:()=>F9,bindSessionToChat:()=>d1,bindSessionResumeChecked:()=>n2,bindSessionModelChecked:()=>C8,bindSessionModel:()=>k8,appendTurnAnchorChecked:()=>N8,addReaction:()=>b0,PROJECTS_ROOT:()=>AY,MAX_UPLOAD_BYTES:()=>m8});import*as QY from"@larksuiteoapi/node-sdk";import{execSync as HY}from"node:child_process";import{randomUUID as j8}from"node:crypto";import{mkdirSync as q8,readFileSync as H1,statSync as WY,writeFileSync as XY}from"node:fs";import{readFile as VY}from"node:fs/promises";import{homedir as sJ}from"node:os";import{basename as Q1,extname as x_,isAbsolute as zY,join as L9}from"node:path";function D8(){let $={};for(let[Z,J]of C0)$[Z]=J;A0(t6,$)}function F8(){C0.clear();try{let $=JSON.parse(H1(t6,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("lease file must contain an object");for(let[Z,J]of Object.entries($)){let Y=J;if(typeof Z!=="string"||!Z||Y.chatId!==Z||typeof Y.sessionName!=="string"||!Y$(Y.sessionName)||typeof Y.createdAt!=="number"||!Number.isFinite(Y.createdAt)){_(`feishu: rejected malformed temp-session lease chat=${Z}`);continue}C0.set(Z,{chatId:Z,sessionName:Y.sessionName,createdAt:Y.createdAt})}_(`feishu: loaded ${C0.size} temporary-session leases`)}catch($){if($?.code!=="ENOENT")_(`feishu: load temp-session leases failed: ${$?.message??$}`)}}function M8($,Z){if(!Y$($))throw Error(`refusing to lease non-temporary session name "${$}"`);if(!Z)throw Error("cannot lease a temporary session without chat_id");for(let Q of C0.values())if(Q.sessionName===$&&Q.chatId!==Z)throw Error(`temporary session name "${$}" is already leased to ${Q.chatId}`);let J=C0.get(Z),Y={sessionName:$,chatId:Z,createdAt:Date.now()};C0.set(Z,Y);try{D8()}catch(Q){if(J)C0.set(Z,J);else C0.delete(Z);throw Q}}function R8($,Z){let J=C0.get(Z);return J?.sessionName===$&&J.chatId===Z}function n1($){return v.projects[$]}function j9($){return n1($)?.cwd?.trim()||L9(AY,$)}function W1($,Z={}){return fetch($,{...Z,signal:Z.signal??AbortSignal.timeout(k_)})}async function K$(){if(B9&&Date.now()<eJ)return B9;return L8??=(async()=>{let $=await W1("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({app_id:GY,app_secret:_Y})}),Z=await $.json();if(!$.ok||!Z.tenant_access_token)throw Error(`feishu: tenant token failed HTTP ${$.status} code=${Z.code??"MISS"} msg=${Z.msg??"MISS"}`);return B9=Z.tenant_access_token,eJ=Date.now()+Math.max(0,(Z.expire??7200)-60)*1000,B9})().finally(()=>{L8=null}),L8}function U8(){try{let $=JSON.parse(H1(n6,"utf8"));for(let[Z,J]of Object.entries($))if(typeof J==="string")G0.set(Z,J);_(`feishu: loaded ${G0.size} session→chat bindings`)}catch($){if($?.code!=="ENOENT")_(`feishu: load session-chat-map failed: ${$?.message??$}`)}}function KY(){try{P8()}catch($){_(`feishu: save session-chat-map failed: ${$}`)}}function P8(){let $={};for(let[Z,J]of G0)$[Z]=J;A0(n6,$)}function d1($,Z){if(G0.get($)===Z)return;let J=G0.get($);G0.set($,Z),KY(),_(`feishu: bound session "${$}" → ${Z}${J?` (was ${J})`:""}`)}function q9($){let Z=G0.get($);if(!Z)return;G0.delete($),KY(),_(`feishu: unbound session "${$}" from ${Z}`)}function i2($,Z){let J=z0.get($)??{};J[Z.provider]=Z,z0.set($,J)}function $Y($,Z){if(!$||typeof $!=="object"||Array.isArray($))return null;let J=$,Y=$$(J.provider)?J.provider:Z??null;if(!Y||Z&&Y!==Z)return null;let Q=typeof J.sessionId==="string"?J.sessionId.trim():typeof J.session_id==="string"?J.session_id.trim():"";if(!Q)return null;if(J.cwd===void 0||J.cwd===null)return{provider:Y,sessionId:Q,cwd:null};if(typeof J.cwd!=="string"||!zY(J.cwd))return null;return{provider:Y,sessionId:Q,cwd:J.cwd}}function ZY($){let Z=$.sessionId.trim();if(!Z)throw Error("cannot bind an empty conversation session id");if(!$$($.provider))throw Error(`cannot bind an unknown conversation provider: ${String($.provider)}`);if(typeof $.cwd!=="string"||!zY($.cwd))throw Error(`cannot bind a conversation without an absolute cwd: ${String($.cwd)}`);return{provider:$.provider,sessionId:Z,cwd:$.cwd}}function C_($,Z,J){if(typeof $!=="string")return ZY($);if(!Z)throw Error("cannot bind a conversation without a provider");return ZY({provider:Z,sessionId:$,cwd:J??null})}function O8(){try{let $=JSON.parse(H1(a6,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("resume map must contain an object");z0.clear();for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){i2(Z,{provider:"codex",sessionId:J.trim(),cwd:null});continue}if(!J||typeof J!=="object"||Array.isArray(J))continue;let Y=J,Q=$Y(Y);if(Q){i2(Z,Q);continue}for(let H of D7){let W=Y[H];if(typeof W==="string"&&W.trim()){i2(Z,{provider:H,sessionId:W.trim(),cwd:null});continue}let X=$Y(W,H);if(X)i2(Z,X)}}_(`feishu: loaded ${z0.size} session→resume bindings`)}catch($){if($?.code!=="ENOENT")_(`feishu: load session-resume-map failed: ${$?.message??$}`)}}function D9(){let $={};for(let[Z,J]of z0){let Y={};if(J.codex)Y.codex={...J.codex};if(J.claude)Y.claude={...J.claude};if(J.dsh)Y.dsh={...J.dsh};$[Z]=Y}A0(a6,$)}function n2($,Z,J,Y){let Q=C_(Z,J,Y),H=z0.get($),W=H?{...H}:void 0,X=H?.[Q.provider];if(X?.sessionId===Q.sessionId&&X.cwd===Q.cwd)return;i2($,Q);try{D9()}catch(V){if(W)z0.set($,W);else z0.delete($);throw V}}function X1($,Z="codex"){let J=z0.get($)?.[Z];return J?{...J}:null}function a1($,Z){let J=z0.get($);if(!J||Z&&J[Z]===void 0)return;let Y={...J};if(!Z)z0.delete($);else{let Q={...J};if(delete Q[Z],!Q.codex&&!Q.claude)z0.delete($);else z0.set($,Q)}try{D9()}catch(Q){throw z0.set($,Y),Q}}function BY($){if(!$||typeof $!=="object")return null;let Z=$;if(!$$(Z.provider))return null;let J=typeof Z.sessionId==="string"?Z.sessionId.trim():"";if(!J)return null;let Y;if(Z.cwd===void 0||Z.cwd===null)Y=null;else if(typeof Z.cwd==="string"&&Z.cwd.trim())Y=Z.cwd;else return null;return{provider:Z.provider,sessionId:J,cwd:Y}}function LY($){if(!$||typeof $!=="object")return null;let Z=$,J=Z.source;if(!J||typeof J!=="object")return null;let Y=BY(J),Q=typeof Z.id==="string"?Z.id.trim():"";if(!Q||!Y)return null;if(Z.provider==="dsh"&&Z.kind==="event"&&Y.provider==="dsh"&&/^\d+$/.test(Q)&&Number.isSafeInteger(Number(Q)))return{provider:"dsh",kind:"event",id:Q,source:{...Y,provider:"dsh"}};if(Z.provider==="claude"&&Z.kind==="assistant-message"&&Y.provider==="claude")return{provider:"claude",kind:"assistant-message",id:Q,source:{...Y,provider:"claude"}};if(Z.provider==="codex"&&Z.kind==="turn"&&Y.provider==="codex")return{provider:"codex",kind:"turn",id:Q,source:{...Y,provider:"codex"}};return null}function qY($){if(!$||typeof $!=="object")return null;let Z=$;if(Z.kind==="fresh")return{kind:"fresh"};if(Z.kind!=="resume"&&Z.kind!=="fork")return null;let J=BY(Z.source);if(!J)return null;let Y=Z.kind==="resume"?{kind:"resume",source:J}:(()=>{if(!Object.prototype.hasOwnProperty.call(Z,"through"))return{kind:"fork",source:J};let Q=LY(Z.through);return Q?{kind:"fork",source:J,through:Q}:null})();if(!Y)return null;try{V0(Y,J.provider)}catch{return null}return Y}function b_($){if(!Array.isArray($))return[];return $.filter((Z)=>Z&&typeof Z.path==="string").map((Z)=>({tool:String(Z.tool??"Write"),path:String(Z.path),body:String(Z.body??"")})).filter((Z)=>Z.path!==""||Z.body!=="")}function y_($,Z){if(!$||typeof $!=="object")return null;let J=$;if(typeof J.ts!=="number"||!Number.isFinite(J.ts))return null;let Y=Object.prototype.hasOwnProperty.call(J,"checkpoint"),Q=LY(J.checkpoint);if(Y&&!Q)return null;if(!Q){if(Z!=="claude")return null;let H=typeof J.uuid==="string"?J.uuid.trim():"",W=typeof J.sid==="string"?J.sid.trim():"";if(!H||!W)return null;Q={provider:"claude",kind:"assistant-message",id:H,source:{provider:"claude",sessionId:W,cwd:null}}}return{checkpoint:Q,preview:String(J.preview??""),ts:J.ts,writes:b_(J.writes)}}function w_($){if(!$||typeof $!=="object")return null;let Z=$,J=qY(Z.launch);if(J?.kind!=="fork"||J.source.provider!=="claude"||J.source.cwd===null)return null;let Y=Z.previousSessionId,Q=Y===null?null:typeof Y==="string"&&Y.trim()?Y.trim():void 0;if(Q===void 0)return null;return{launch:{...J,source:{...J.source,provider:"claude"}},previousSessionId:Q}}function T8($){let Z=$.launch.through;if($.launch.source.provider!=="claude"||Z&&(Z.provider!=="claude"||Z.kind!=="assistant-message"||Z.source.provider!=="claude"))throw Error("pending conversation launch is not a Claude fork");return{launch:{kind:"fork",source:{...$.launch.source,provider:"claude"},...Z?{through:{...Z,provider:"claude",kind:"assistant-message",source:{...Z.source,provider:"claude"}}}:{}},previousSessionId:$.previousSessionId}}function E8(){try{let $=JSON.parse(H1(o6,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("turns map must contain an object");n.clear();let Z=0,J=0;for(let[Y,Q]of Object.entries($)){let H,W,X=null;if(Array.isArray(Q))H=Q,W=null;else if(Q&&typeof Q==="object"&&!Array.isArray(Q)){let A=Q;if(!Array.isArray(A.anchors)||!Object.prototype.hasOwnProperty.call(A,"base")){J++;continue}if(H=A.anchors,A.base===null)W=null;else{let K=qY(A.base);if(!K){J++;continue}W=K}if(Object.prototype.hasOwnProperty.call(A,"pendingLaunch")){let K=w_(A.pendingLaunch);if(!K){J++;continue}X=K}}else{J++;continue}let V=z0.get(Y),z=V?.claude!==void 0&&V.codex===void 0?"claude":null,G=[];for(let A of H){let K=y_(A,z);if(K)G.push(K);else J++}if(G.length||W!==null||X)n.set(Y,{base:W,anchors:G,...X?{pendingLaunch:X}:{}}),Z+=G.length}if(_(`feishu: loaded ${Z} turn anchors across ${n.size} sessions`),J>0)_(`feishu: rejected ${J} malformed turn anchors while loading`)}catch($){if($?.code!=="ENOENT")_(`feishu: load session-turns-map failed: ${$?.message??$}`)}}function d2(){let $={};for(let[Z,J]of n)$[Z]=J;A0(o6,$)}function N8($,Z){let J=n.get($),Y=[...J?.anchors??[],Z],Q=J?.base??null;if(Y.length>JY){let H=Y.splice(0,Y.length-JY),W=H[H.length-1].checkpoint;Q={kind:"fork",source:W.source,through:W}}n.set($,{base:Q,anchors:Y,...J?.pendingLaunch?{pendingLaunch:J.pendingLaunch}:{}});try{d2()}catch(H){if(J)n.set($,J);else n.delete($);throw H}}function a2($){return n.get($)?.anchors??[]}function o2($){return n.get($)?.base??null}function r2($){let Z=n.get($)?.pendingLaunch;return Z?T8(Z):null}function b$($,Z){if(Z){if(Z.launch.source.cwd===null)throw Error("pending conversation launch source cwd is missing");V0(Z.launch,"claude",Z.launch.source.cwd)}let J=n.get($),Y=J?.base??null,Q=J?.anchors.slice()??[];if(!Z&&Q.length===0&&Y===null)n.delete($);else n.set($,{base:Y,anchors:Q,...Z?{pendingLaunch:T8(Z)}:{}});try{d2()}catch(H){if(J)n.set($,J);else n.delete($);throw H}}function a0($,Z,J,Y){let Q=n.get($),H=Y===void 0?Q?.pendingLaunch:Y??void 0,W=H?T8(H):void 0;if(Z.length===0&&J===null&&!W)n.delete($);else n.set($,{base:J,anchors:Z.slice(),...W?{pendingLaunch:W}:{}});try{d2()}catch(X){if(Q)n.set($,Q);else n.delete($);throw X}}function Y$($){return YY.test($)?$.replace(YY,""):null}function S8($,Z=[]){let J=new Date,Y=(X)=>String(X).padStart(2,"0"),Q=`${Y(J.getMonth()+1)}${Y(J.getDate())}-${Y(J.getHours())}${Y(J.getMinutes())}`,H=new Set([..._0.values(),...n.keys(),...Z]),W=`${$}*${Q}`;for(let X=2;H.has(W);X++)W=`${$}*${Q}-${X}`;return W}function x8(){try{let $=JSON.parse(H1(r6,"utf8"));for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){O0.set(Z,{provider:f1(J),model:J,effort:null});continue}if(!J||typeof J!=="object")continue;let{model:Y,provider:Q}=J,H=$$(Q)?Q:typeof Y==="string"&&Y.trim()?f1(Y):"claude",W=typeof Y==="string"&&Y.trim()?Y:null;if(H==="claude"&&!W)continue;let{effort:X,tokenSourceId:V}=J,z=typeof V==="string"&&V.trim()?V.trim():null,G=H==="dsh"?X0(X)?X:null:H==="claude"?R0(X)?X:null:h0(X)?X:null;O0.set(Z,{provider:H,model:W,effort:G,...z?{tokenSourceId:z}:{}})}_(`feishu: loaded ${O0.size} session→model bindings`)}catch($){if($?.code!=="ENOENT")_(`feishu: load session-model-map failed: ${$?.message??$}`)}}function f_(){try{P9()}catch($){_(`feishu: save session-model-map failed: ${$}`)}}function P9(){let $={};for(let[Z,J]of O0)$[Z]=J;A0(r6,$)}function k8($,Z,J,Y,Q){let H=O0.get($);if(H?.provider===Z&&H.model===J&&H.effort===Y&&(H.tokenSourceId??null)===(Q??null))return;O0.set($,{provider:Z,model:J,effort:Y,...Q?{tokenSourceId:Q}:{}}),f_()}function C8($,Z,J,Y,Q){let H=O0.get($),W={provider:Z,model:J,effort:Y,...Q?{tokenSourceId:Q}:{}};if(H?.provider===Z&&H.model===J&&H.effort===Y&&(H.tokenSourceId??null)===(Q??null))return;O0.set($,W);try{P9()}catch(X){if(H)O0.set($,H);else O0.delete($);throw X}}function b8($){let Z=O0.get($);if(Z)return Z;let J=Y$($);return J?O0.get(J)??null:null}function y8($){let Z=G0.get($),J=z0.get($),Y=O0.get($),Q=n.get($),H=[...C0.entries()].filter(([,W])=>W.sessionName===$);G0.delete($),z0.delete($),O0.delete($),n.delete($);for(let[W]of H)C0.delete(W);try{P8(),D9(),P9(),d2(),D8()}catch(W){if(Z)G0.set($,Z);if(J)z0.set($,J);if(Y)O0.set($,Y);if(Q)n.set($,Q);for(let[V,z]of H)C0.set(V,z);let X=[W];for(let V of[P8,D9,P9,d2,D8])try{V()}catch(z){X.push(z)}throw X.length===1?X[0]:AggregateError(X,`failed to clear and restore conversation state for ${$}`)}}function w8($){A0(e6,$)}function f8(){let $;try{$=H1(e6,"utf8")}catch(J){if(J.code==="ENOENT")return[];throw J}let Z=JSON.parse($);if(!Array.isArray(Z)||Z.some((J)=>typeof J!=="string"||!J.trim()))throw Error("invalid alive session marker: expected non-empty session names");return Z}function F9($){let Z=G0.get($);if(Z){let Y=_0.get(Z);if(Y&&Y!==$)_(`feishu: chatIdForSession("${$}"): persisted binding ${Z} has cached name "${Y}", using persisted binding`);return Z}let J=[];for(let[Y,Q]of _0)if(Q===$)J.push(Y);if(J.length===1)return J[0];if(J.length>1)_(`feishu: chatIdForSession("${$}"): ${J.length} candidates with no binding — [${J.join(", ")}]`);return null}async function t2(){try{let $;do{let Z=await s.im.chat.list({params:{page_size:100,...$?{page_token:$}:{}}});for(let J of Z.data?.items??[])if(J.chat_id&&J.name)_0.set(J.chat_id,J.name);$=Z.data?.page_token}while($);_(`feishu: refreshed chat list — ${_0.size} groups`)}catch($){_(`feishu: refresh chat list failed: ${$}`)}}async function M9(){let $=new Map,Z;do{let J=await s.im.chat.list({params:{page_size:100,...Z?{page_token:Z}:{}}});if(J.code&&J.code!==0)throw Error(`feishu chat.list failed code=${J.code} msg=${J.msg}`);for(let Y of J.data?.items??[]){if(!Y.chat_id||!Y.name)continue;if(Y.chat_status&&Y.chat_status!=="normal")continue;_0.set(Y.chat_id,Y.name);let Q=$.get(Y.name)??[];Q.push(Y.chat_id),$.set(Y.name,Q)}Z=J.data?.page_token}while(Z);return $}async function R9($){let Z=G0.get($);if(Z&&_0.get(Z)===$){let H=await PY(Z);if(H.name===$&&jY(H.status))return Z;_0.delete(Z),q9($)}let Y=(await M9()).get($)??[];if(Y.length===0)return null;let Q=G0.get($);if(Q&&Y.includes(Q))return Q;if(Y.length===1)return Y[0];throw Error(`multiple Feishu groups named "${$}": ${Y.join(", ")}`)}async function v8($,Z){if(!Z)throw Error("missing sender open_id; cannot add user to worktree group");let J=await R9($);if(J){let H=await v_(J,Z);return d1($,J),{chatId:J,created:!1,joined:H}}let Y=await s.im.chat.create({params:{user_id_type:"open_id",uuid:j8()},data:{name:$,user_id_list:[Z],group_message_type:"chat"}});if(Y.code&&Y.code!==0)throw Error(`feishu chat.create failed code=${Y.code} msg=${Y.msg}`);let Q=Y.data?.chat_id;if(!Q)throw Error("feishu chat.create returned no chat_id");return _0.set(Q,$),d1($,Q),{chatId:Q,created:!0,joined:!0}}async function h8($,Z){if(!Z)throw Error("missing sender open_id; cannot create temporary group");if(await R9($))throw Error(`temporary group name already exists: ${$}`);let Y=await s.im.chat.create({params:{user_id_type:"open_id",uuid:j8()},data:{name:$,user_id_list:[Z],group_message_type:"chat"}});if(Y.code&&Y.code!==0)throw Error(`feishu chat.create failed code=${Y.code} msg=${Y.msg}`);let Q=Y.data?.chat_id;if(!Q)throw Error("feishu chat.create returned no chat_id");return _0.set(Q,$),d1($,Q),{chatId:Q,created:!0,joined:!0}}async function I8($){let Z=await R9($);if(!Z)return q9($),{chatId:null,disbanded:!1};let J=await s.im.chat.delete({path:{chat_id:Z}});if(J.code&&J.code!==0)throw Error(`feishu chat.delete failed code=${J.code} msg=${J.msg}`);if(_0.delete(Z),G0.get($)===Z)q9($);return{chatId:Z,disbanded:!0}}async function g8($,Z){if(!Z)throw Error("cannot disband a temporary session without an exact chat_id");let J=await PY(Z);if(J.name!==$)throw Error(`refusing to delete chat ${Z}: expected name "${$}", got "${J.name??""}"`);if(!jY(J.status))throw Error(`refusing to delete chat ${Z}: status=${J.status??"unknown"}`);let Y=await s.im.chat.delete({path:{chat_id:Z}});if(Y.code&&Y.code!==0)throw Error(`feishu chat.delete failed code=${Y.code} msg=${Y.msg}`);return _0.delete(Z),{chatId:Z,disbanded:!0}}async function v_($,Z){let J;do{let Q=await s.im.chatMembers.get({path:{chat_id:$},params:{member_id_type:"open_id",page_size:100,...J?{page_token:J}:{}}});if(Q.code&&Q.code!==0)throw Error(`feishu chatMembers.get failed code=${Q.code} msg=${Q.msg}`);for(let H of Q.data?.items??[])if(H.member_id===Z)return!1;J=Q.data?.page_token}while(J);let Y=await s.im.chatMembers.create({path:{chat_id:$},params:{member_id_type:"open_id"},data:{id_list:[Z]}});if(Y.code&&Y.code!==0)throw Error(`feishu chatMembers.create failed code=${Y.code} msg=${Y.msg}`);return!0}async function c8($){try{let Z=await K$(),Y=await(await W1(`https://open.feishu.cn/open-apis/im/v1/chats/${encodeURIComponent($)}`,{headers:{Authorization:`Bearer ${Z}`}})).json();if(Y?.code!==0)return _(`feishu: fetchChatName ${$} code=${Y?.code} msg=${Y?.msg}`),null;let Q=Y.data?.name;if(typeof Q==="string"&&Q)return _0.set($,Q),_(`feishu: fetchChatName ${$} → "${Q}" (point lookup)`),Q;return _(`feishu: fetchChatName ${$} — chat has no name (unnamed group?)`),null}catch(Z){return _(`feishu: fetchChatName ${$} failed: ${Z}`),null}}async function DY($,Z,J,Y){let Q=j8(),H=null;for(let W=0;W<l2.length;W++){if(l2[W]>0)await new Promise((X)=>setTimeout(X,l2[W]));try{let X=await s.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:Z,msg_type:J,content:Y,uuid:Q}});if(X?.code&&X.code!==0)return _(`feishu: send${$==="text"?"Text":"Card"} rejected chat=${Z} code=${X.code} msg=${X.msg}`),null;return X?.data?.message_id??null}catch(X){H=X,_(`feishu: send${$==="text"?"Text":"Card"} attempt ${W+1}/${l2.length} chat=${Z} failed: ${X}`)}}return _(`feishu: send${$==="text"?"Text":"Card"} chat=${Z} EXHAUSTED ${l2.length} retries: ${H}`),null}async function PY($){let Z=await s.im.chat.get({path:{chat_id:$}});if(Z.code&&Z.code!==0)throw Error(`feishu chat.get failed code=${Z.code} msg=${Z.msg}`);return{name:Z.data?.name??null,status:Z.data?.chat_status??null}}function jY($){return $===null||$==="normal"}async function E($,Z){return DY("text",$,"text",JSON.stringify({text:Z}))}async function a($,Z){return DY("card",$,"interactive",JSON.stringify(S$(Z)))}async function Q$($,Z){let J=await s.im.v1.message.patch({path:{message_id:$},data:{content:JSON.stringify(S$(Z))}});if(J?.code&&J.code!==0)throw Error(`feishu message.patch failed code=${J.code} msg=${J.msg}`)}async function w($,Z){try{let J=await K$(),Q=await(await W1("https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id",{method:"POST",headers:{Authorization:`Bearer ${J}`,"Content-Type":"application/json"},body:JSON.stringify({receive_id:$,msg_type:"text",content:JSON.stringify({text:Z})})})).json();if(Q?.code!==0)return _(`feishu: sendTextRaw rejected chat=${$} code=${Q?.code} msg=${Q?.msg}`),null;return Q.data?.message_id??null}catch(J){return _(`feishu: sendTextRaw chat=${$} failed: ${J}`),null}}async function b0($,Z){if(!$)return null;try{return(await s.im.messageReaction.create({path:{message_id:$},data:{reaction_type:{emoji_type:Z}}}))?.data?.reaction_id??null}catch(J){return _(`feishu: addReaction ${Z} on ${$} failed: ${J}`),null}}async function T0($,Z){if(!$||!Z)return;try{await s.im.messageReaction.delete({path:{message_id:$,reaction_id:Z}})}catch(J){_(`feishu: deleteReaction ${Z} on ${$} failed: ${J}`)}}async function V1($,Z){if(!$){_("feishu: urgentApp skip — missing messageId");return}if(Z.length===0){_(`feishu: urgentApp skip — empty openIds (msg=${$})`);return}let J=await K$(),Y=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/urgent_app?user_id_type=open_id`;try{let H=await(await W1(Y,{method:"PATCH",headers:{Authorization:`Bearer ${J}`,"Content-Type":"application/json"},body:JSON.stringify({user_id_list:Z})})).json();if(H?.code!==0){_(`feishu: urgentApp ${$} code=${H?.code} msg=${H?.msg}`);return}let W=H.data?.invalid_user_id_list??[],X=Z.length-W.length;_(`feishu: urgentApp ${$} ok — delivered=${X}${W.length?` invalid=${W.length}`:""}`)}catch(Q){_(`feishu: urgentApp ${$} failed: ${Q}`)}}async function s2($,Z,J,Y){try{let Q=await K$(),H=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/resources/${Z}?type=${J}`,W=await W1(H,{headers:{Authorization:`Bearer ${Q}`}});if(!W.ok){_(`feishu: download ${J} HTTP ${W.status}: ${(await W.text()).slice(0,200)}`);return}let X=Buffer.from(await W.arrayBuffer());q8($7,{recursive:!0});let V=Y?Y.replace(/[^a-zA-Z0-9._-]/g,"_"):`${Z.replace(/[^a-zA-Z0-9_-]/g,"_")}.png`,z=L9($7,`${Date.now()}-${V}`);return XY(z,X),_(`feishu: downloaded ${J} ${z} (${X.length}B)`),z}catch(Q){_(`feishu: download ${J} failed: ${Q instanceof Error?Q.message:Q}`);return}}function I_($){return h_.has(x_($).toLowerCase())}async function FY($){let Z=await K$(),J=new Blob([Uint8Array.from(await VY($))]),Y=new FormData;Y.append("image_type","message"),Y.append("image",J,Q1($));let H=await(await W1("https://open.feishu.cn/open-apis/im/v1/images",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Y})).json();if(H?.code!==0)return _(`feishu: uploadImage ${$} code=${H.code} msg=${H.msg}`),null;return H.data?.image_key??null}async function u8($){try{let Z=WY($);if(!Z.isFile())return _(`feishu: uploadImageKey not a file — ${$}`),null;if(Z.size>m8)return _(`feishu: uploadImageKey oversize — ${$} (${(Z.size/1024/1024).toFixed(1)} MB)`),null}catch(Z){return _(`feishu: uploadImageKey stat failed — ${$}: ${Z}`),null}return FY($)}async function g_($){let Z=await K$(),J=new Blob([Uint8Array.from(await VY($))]),Y=new FormData;Y.append("file_type","stream"),Y.append("file_name",Q1($)),Y.append("file",J,Q1($));let H=await(await W1("https://open.feishu.cn/open-apis/im/v1/files",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Y})).json();if(H?.code!==0)return _(`feishu: uploadFile ${$} code=${H.code} msg=${H.msg}`),null;return H.data?.file_key??null}async function U9($,Z){try{let J=await s.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:$,msg_type:"image",content:JSON.stringify({image_key:Z})}});if(J?.code&&J.code!==0)return _(`feishu: sendImage rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return _(`feishu: sendImage failed chat=${$}: ${J}`),null}}async function MY($,Z){try{let J=await s.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:$,msg_type:"file",content:JSON.stringify({file_key:Z})}});if(J?.code&&J.code!==0)return _(`feishu: sendFile rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return _(`feishu: sendFile failed chat=${$}: ${J}`),null}}async function e2($,Z){try{let Y=WY(Z);if(!Y.isFile())return await E($,`❌ 出站文件: 路径不是文件 — ${Z}`),!1;if(Y.size>m8)return await E($,`❌ 出站文件: ${Q1(Z)} 超过 30 MB (${(Y.size/1024/1024).toFixed(1)} MB)`),!1}catch(Y){return await E($,`❌ 出站文件: 无法读取 ${Z} (${Y})`),!1}let J=I_(Z);try{if(J){let Y=await FY(Z);if(!Y)return await E($,`❌ 出站图片上传失败: ${Q1(Z)}`),!1;return await U9($,Y)!=null}else{let Y=await g_(Z);if(!Y)return await E($,`❌ 出站文件上传失败: ${Q1(Z)}`),!1;return await MY($,Y)!=null}}catch(Y){return _(`feishu: uploadAndSend ${Z} failed: ${Y}`),await E($,`❌ 出站文件异常: ${Q1(Z)} — ${Y}`),!1}}function p8($){q8($,{recursive:!0}),_(`feishu: provisioned ${$}`);let Z=L9(sJ(),".codex","config.toml");try{q8(L9(sJ(),".codex"),{recursive:!0});let J="";try{J=H1(Z,"utf8")}catch{}let Y=`[projects.${JSON.stringify($)}]`;if(!J.includes(Y)){let Q=J.trimEnd();J=`${Q}${Q?`
|
|
64
67
|
|
|
65
68
|
`:""}${Y}
|
|
66
69
|
trust_level = "trusted"
|
|
67
|
-
`,
|
|
68
|
-
`)).digest("hex")}async function
|
|
69
|
-
`)}]}}function
|
|
70
|
-
`)}function
|
|
71
|
-
`)}]}}function
|
|
72
|
-
`)});continue}if(W===J){if(H.push({tag:"markdown",content:`**\uD83E\uDD14 ${V}**`}),X.options.length>0)H.push(
|
|
73
|
-
*— 由 ${
|
|
70
|
+
`,XY(Z,J)}}catch(J){_(`feishu: codex trust write failed for ${$}: ${J}`)}try{HY("git init -q",{cwd:$,stdio:"ignore"})}catch{}}function $4(){try{let $=HY(`"${y2()}" login status 2>&1`,{timeout:1e4}).toString();return/Logged in using ChatGPT/i.test($)}catch{return!1}}function l8($){return $.replace(/[^\w一-鿿\-\[\]\*]/g,"_").slice(0,64)}var GY,_Y,AY,C0,s,k_=15000,B9="",eJ=0,L8=null,_0,G0,z0,n,JY=200,YY,O0,l2,m8=31457280,h_;var e=S(()=>{K0();x0();Z1();K0();Y0();g();n0();I0();$1();tJ();GY=v.feishu.app_id,_Y=v.feishu.app_secret,AY=v.runtime.projects_root,C0=new Map;s=new QY.Client({appId:GY,appSecret:_Y,disableTokenCache:!1});_0=new Map,G0=new Map;z0=new Map;n=new Map;YY=/\*[0-9]{4}-[0-9]{4}(-[0-9]+)?$/;O0=new Map;l2=[0,1000,4000];h_=new Set([".png",".jpg",".jpeg",".gif",".bmp",".webp"])});import{createHash as RY}from"node:crypto";function i8($,Z){if($===300305||$===200860)return!0;if($!==300315)return!1;let J=Z?.message??"";return/(?:code\s*[:=]\s*(?:300305|200860)\b|number of card components[^\n.]{0,60}exceed|\bcard over max size\b)/i.test(J)}function UY($,Z){if($!==300315)return!1;return/(?:duplicate\s+(?:element\s*)?id|code\s*1001\s*:\s*duplicate id)/i.test(Z?.message??"")}function y$($){let Z=o0.get($);if(!Z)throw Error(`cardkit card is not registered: ${$}`);return Z}function B$($){return!o0.has($)}function r0($,Z,J){o0.set($,{sequence:0,queue:Promise.resolve(),elementCount:Z,contentFingerprints:new Map,deadElements:new Set,failedAdds:new Map,failedReplacements:new Set,onFailure:J,closing:!1})}function d8($){return o0.get($)?.elementCount??0}function OY($){let Z=o0.get($);return Z?[...Z.contentFingerprints.keys()].filter((J)=>!Z.deadElements.has(J)):[]}function r1($,Z){return o0.get($)?.deadElements.has(Z)??!1}function TY($,Z){let J=o0.get($);J?.deadElements.delete(Z),J?.failedAdds.delete(Z),J?.failedReplacements.delete(Z)}function O9($){let Z=y$($);return Z.sequence+=1,Z.sequence}function EY($,Z){$.deadElements.add(Z)}function NY($){return RY("sha256").update(JSON.stringify($,(Z,J)=>Z==="element_id"?void 0:J)).digest("hex")}function l_($,Z,J){let Y=[...$.contentFingerprints].filter(([Q])=>Q!==Z).map(([,Q])=>Q);if(J&&Z!==R.footer)Y.push(J);return RY("sha256").update(Y.sort().join(`
|
|
71
|
+
`)).digest("hex")}async function o1($,Z,J){let Y=await K$(),Q=await fetch(`${c_}${Z}`,{method:$,headers:{Authorization:`Bearer ${Y}`,"Content-Type":"application/json"},...J?{body:JSON.stringify(J)}:{},signal:AbortSignal.timeout(m_)}),H=await Q.json();if(!Q.ok||H?.code!==0){let W=typeof H?.code==="number"?H.code:Q.status,X=Q.headers.get("x-tt-logid")??Q.headers.get("x-request-id")??Q.headers.get("request-id")??void 0,V=Error(`cardkit ${$} ${Z}: HTTP ${Q.status} code=${String(H?.code??"MISS")} msg=${H?.msg??"MISS"}${X?` log_id=${X}`:""}`);throw V.code=W,V.httpStatus=Q.status,V.logId=X,V}return H?.data}function i_($){return new Promise((Z)=>setTimeout(Z,$))}function d_($){if(typeof $!=="object"||$===null)return!1;let Z=$.code;return Z===300309||Z===200850}async function n_($){let Z=O9($);await o1("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify({config:{streaming_mode:!0}}),sequence:Z})}async function n8($,Z,J,Y,Q=!1,H={}){let W=(X)=>{let V=typeof X==="object"&&X!==null?X:null,z={cardId:$,operation:Z,elementId:H.elementId,targetElementId:H.targetElementId,code:V?.code,httpStatus:V?.httpStatus,logId:V?.logId,message:X instanceof Error?X.message:String(X)};if(i8(z.code,z))z.capacityFingerprint=l_(y$($),H.elementId,H.contentFingerprint);try{if(!Q)y$($).onFailure?.(z.code,z)}catch(G){_(`cardkit failure callback ${$}: ${G}`)}try{Y?.(z)}catch(G){_(`cardkit per-call failure callback ${$}: ${G}`)}};try{await J();return}catch(X){if(!d_(X)){_(`cardkit ${Z} ${$}: ${X}`),W(X);return}_(`cardkit ${Z} ${$}: streaming closed (code=${X.code}) — reopening`)}try{await n_($)}catch(X){_(`cardkit STREAMING_REOPEN_FAILED ${$}: ${X}`),W(X);return}try{await J()}catch(X){_(`cardkit ${Z} ${$} retry-after-reopen: ${X}`),W(X)}}function a_($){return typeof $==="object"&&$!==null&&$.code===200740}async function H$($,Z={}){let J=Z.retryDelaysMs?.length?Z.retryDelaysMs:u_,Y=null;for(let Q=0;Q<J.length;Q++){let H=J[Q]??0;if(H>0)await i_(H);try{let W=await o1("POST","/cards/id_convert",{message_id:$});if(typeof W?.card_id!=="string"||!W.card_id)throw Error("cardkit POST /cards/id_convert: missing card_id");return W.card_id}catch(W){if(Y=W,!a_(W)||Q===J.length-1)throw W;let X=J[Q+1]??0;_(`cardkit id_convert ${$}: empty result, retry ${Q+2}/${J.length} in ${X}ms`)}}throw Y}async function c0($){let Z=o0.get($);if(!Z)return;await Z.queue}function B0($,Z,J={},Y){if(B$($))return Promise.resolve();let Q=y$($);if(Q.closing)return Promise.resolve();let H=S$(Z),W=H.element_id,X=NY(H),V=()=>{if(!W)return;EY(Q,W),Q.failedAdds.set(W,J)};return Q.queue=Q.queue.then(()=>n8($,"addElement",async()=>{let z=O9($);if(await o1("POST",`/cards/${$}/elements`,{type:J.type??"append",...J.targetElementId?{target_element_id:J.targetElementId}:{},elements:JSON.stringify([H]),sequence:z}),Q.elementCount+=1,W!==R.footer)Q.contentFingerprints.set(W??`#${z}`,X);if(W)Q.deadElements.delete(W),Q.failedAdds.delete(W),Q.failedReplacements.delete(W)},(z)=>{V(),Y?.(z.code,z)},!1,{elementId:W,targetElementId:J.targetElementId,contentFingerprint:X})),Q.queue}function t($,Z,J,Y,Q=!0){if(B$($))return Promise.resolve();let H=y$($);if(H.closing)return Promise.resolve();let W=S$(J),X=NY(W),V=()=>{EY(H,Z),H.failedReplacements.add(Z)};return H.queue=H.queue.then(()=>n8($,`replaceElement ${Z}`,async()=>{let z=H.failedAdds.get(Z);if(H.deadElements.has(Z)&&!z&&!H.failedReplacements.has(Z))return;let G=O9($);if(z)await o1("POST",`/cards/${$}/elements`,{type:z.type??"append",...z.targetElementId?{target_element_id:z.targetElementId}:{},elements:JSON.stringify([W]),sequence:G}),H.elementCount++;else await o1("PUT",`/cards/${$}/elements/${Z}`,{element:JSON.stringify(W),sequence:G});if(H.deadElements.delete(Z),H.failedAdds.delete(Z),H.failedReplacements.delete(Z),Z!==R.footer)H.contentFingerprints.set(Z,X)},(z)=>{if(Q)V();Y?.(z.code,z)},!Q,{elementId:Z,contentFingerprint:X})),H.queue}async function L0($,Z,J,Y={}){if(B$($))return!1;let Q=y$($);if(Q.closing)return!1;let H=!1;return await t($,Z,J,()=>{H=!0},Y.notifyCardFailure!==!1),!H&&!Q.deadElements.has(Z)}async function w$($,Z,J={}){return(await T9($,Z,J)).landed}async function T9($,Z,J={}){if(B$($))return{landed:!1};let Y=y$($);if(Y.closing)return{landed:!1};let Q=Z.element_id,H;return await B0($,Z,J,(W,X)=>{H=X}),{landed:!H&&!(Q&&Y.deadElements.has(Q)),...H?{failure:H}:{}}}function L$($,Z){if(B$($)||o0.get($)?.closing)return;let J=(Z??"").replace(/\s+/g," ").trim();if(!J)return;let Y=z1.get($);if(!Y)Y={latest:J,lastSent:"",timer:null},z1.set($,Y);else Y.latest=J;if(Y.timer)return;Y.timer=setTimeout(()=>{let Q=z1.get($);if(!Q)return;if(B$($)){z1.delete($);return}if(Q.timer=null,Q.latest===Q.lastSent)return;let H=Q.latest;P0($,{config:{summary:{content:H}}}).then((W)=>{let X=z1.get($);if(W&&X===Q)X.lastSent=H})},p_)}function D0($){let Z=z1.get($);if(!Z)return;if(Z.timer)clearTimeout(Z.timer),Z.timer=null;z1.delete($)}function E9($,Z){return P0($,Z).then(()=>{})}async function P0($,Z){if(B$($))return!1;let J=y$($);if(J.closing)return!1;let Y=!1,Q=!1;return J.queue=J.queue.then(()=>n8($,"patchSettings",async()=>{if(B$($))return;let H=O9($);await o1("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify(Z),sequence:H}),Y=!0},()=>{Q=!0},!0)),await J.queue,Y&&!Q&&!B$($)}async function m0($){let Z=o0.get($);if(!Z){D0($);return}if(Z.closing){await Z.queue;return}Z.closing=!0,D0($),await Z.queue,o0.delete($)}var c_="https://open.feishu.cn/open-apis/cardkit/v1",m_=15000,u_,o0,z1,p_=1500;var G1=S(()=>{e();g();I0();u_=[0,250,750,1500];o0=new Map,z1=new Map});function N9($){if(!$)return null;return typeof $.total_tokens==="number"&&Number.isFinite($.total_tokens)?$.total_tokens:null}function S9($){return typeof $==="number"&&Number.isFinite($)&&$>0?$:null}function o_($,Z,J=12000){if(Z==null||Z<=0)return null;if(Z<=J)return 0;let Y=Z-J,Q=Math.max(0,$-J),H=Math.max(0,Y-Q);return Math.round(Math.min(100,Math.max(0,H/Y*100)))}function xY($,Z,J){let Y=o_($,Z,J??12000);if(Y==null)return null;return{used:Math.min(100,Math.max(0,100-Y)),remaining:Y}}function SY($){let Z=Math.max(0,$);if(Z<1000)return String(Math.round(Z));if(Z<1e6)return(Z/1000).toFixed(Z<1e4?1:0).replace(/\.0$/,"")+"K";return(Z/1e6).toFixed(Z<1e7?1:0).replace(/\.0$/,"")+"M"}function x9($,Z){let J=SY($);return Z!=null&&Z>0?`${J}/${SY(Z)}`:`${J}/--`}function kY($,Z){if(Z==null||Z<=0)return"--";let J=Math.max(0,$/Z*100);if(J>0&&J<1)return"<1%";return`${Math.round(Math.min(100,J))}%`}function o8($,Z,J){let Y=Z?.replace(/^claude:/i,"").replace(/\[1m\]$/i,"");return`${$} · ${Y||"MISS"}/${J||"MISS"}`}function C9($){return JSON.stringify({objective:$.objective,status:$.status,tokenBudget:$.tokenBudget})}function r_($){switch($){case"pending":return"☐";case"inProgress":return"\uD83D\uDD04";case"completed":return"✅";default:return"·"}}function t_($,Z){return $.length>Z?$.slice(0,Z)+"…":$}function k9($){if(!Number.isFinite($)||$<0)return"--";if($<1000)return String(Math.round($));if($<1e6)return($/1000).toFixed($<1e4?1:0).replace(/\.0$/,"")+"k";return($/1e6).toFixed(2).replace(/\.?0+$/,"")+"m"}function CY($){switch($){case"active":return"进行中";case"paused":return"已暂停";case"blocked":return"受阻";case"usageLimited":return"额度受限";case"budgetLimited":return"预算受限";case"complete":return"已完成";default:return $}}function yY($){let Z=$.filter((H)=>H.status==="completed").length,J=$.filter((H)=>H.status==="inProgress").length,Y=$.filter((H)=>H.status==="pending").length,Q=[`${$.length} 项`];if(J)Q.push(`${J} 进行中`);if(Z)Q.push(`${Z} 完成`);if(Y)Q.push(`${Y} 待办`);return Q.join(" · ")}function s_($,Z=""){let J=Z.trim();if($.length===0)return J?"\uD83D\uDCCB 计划草稿":"\uD83D\uDCCB 计划更新";return`\uD83D\uDCCB 计划更新 · ${yY($)}`}function wY($){if(!Number.isFinite($)||$<0)return"MISS";if($<60)return`${Math.round($)}s`;let Z=Math.floor($/60),J=Math.round($%60);if(Z<60)return J?`${Z}m ${J}s`:`${Z}m`;let Y=Math.floor(Z/60),Q=Z%60;return Q?`${Y}h ${Q}m`:`${Y}h`}function a8($){return typeof $==="number"&&Number.isFinite($)?$:null}function e_($){let Z=a8($.startedAtMs),J=a8($.completedAtMs);if(Z==null||J==null||J<Z)return"";return` · 耗时 ${wY((J-Z)/1000)}`}function $A($){let Z=a8($);return Z==null?null:k9(Z)}function ZA($,Z){if(!Z)return["压缩中..."];let J=[],Y=typeof $.trigger==="string"&&$.trigger.trim()?$.trigger.trim():"",Q=$A($.preTokens),H=typeof $.sourceType==="string"&&$.sourceType.trim()?$.sourceType.trim():"";if(Y)J.push(`**触发**: ${Y}`);if(Q)J.push(`**压缩前**: ${Q} tokens`);if(H)J.push(`**来源**: ${H}`);return J.length>0?J:["压缩完成,无摘要内容"]}function r8($,Z,J){if($==null||!Number.isFinite($))return null;let Y=xY($,Z,J);return Y?`${Y.used}% · ${x9($,Z)}`:"--"}function t8($){let Z=k9($?.input_tokens??Number.NaN),J=k9($?.cache_read_input_tokens??Number.NaN),Y=k9($?.output_tokens??Number.NaN);return`└ 入 ${Z} | 缓 ${J} | 出 ${Y}`}function Z4($,Z,J){let Y=Z&&typeof Z==="object"?Z:{},Q=Y.phase==="end"||Y.phase==="event",H=Q?"✅":"⏳",W=Q?e_(Y):"",X=`${H} \uD83D\uDEA8 上下文压缩 #${$+1}${W}`,V=ZA(Y,Q);return{tag:"collapsible_panel",element_id:J,header:{title:{tag:"plain_text",content:X}},expanded:!1,elements:[{tag:"markdown",content:V.join(`
|
|
72
|
+
`)}]}}function fY($,Z,J=""){let Y=["**\uD83D\uDCCB 当前计划**"],Q=Z?.trim();if(Q)Y.push(""),Y.push(Q);if($.length>0){Y.push("");for(let H of $)Y.push(`- ${r_(H.status)} ${H.step}`)}else{let H=J.trim();if(Y.push(""),H)Y.push("正在生成计划草稿..."),Y.push(""),Y.push(H);else Y.push("--")}return Y.join(`
|
|
73
|
+
`)}function s8($,Z,J="",Y){return{tag:"collapsible_panel",element_id:Y,header:{title:{tag:"plain_text",content:s_($,J)}},expanded:!1,elements:[{tag:"markdown",content:fY($,Z,J)}]}}function J4($,Z,J){let Y=$.length>0?`\uD83D\uDCCB 当前计划 · ${yY($)}`:"\uD83D\uDCCB 当前计划";return{tag:"collapsible_panel",element_id:J,header:{title:{tag:"plain_text",content:Y}},expanded:!0,elements:[{tag:"markdown",content:fY($,Z)}]}}function e8($,Z){let J=Number.isFinite($.tokensUsed)?String($.tokensUsed):"MISS",Y=$.tokenBudget==null?"":Number.isFinite($.tokenBudget)?` / ${$.tokenBudget}`:" / MISS",Q=[`**\uD83C\uDFAF 当前目标** · ${CY($.status)}`,"",$.objective,"",`- 用量: ${J}${Y} tokens`,`- 用时: ${wY($.timeUsedSeconds)}`];return{tag:"collapsible_panel",element_id:Z,header:{title:{tag:"plain_text",content:`\uD83C\uDFAF 目标更新 · ${CY($.status)}: ${t_($.objective,48)}`}},expanded:!1,elements:[{tag:"markdown",content:Q.join(`
|
|
74
|
+
`)}]}}function b9($){let Z=$.provider==="claude"?"Claude":"Codex",J=$.kind==="card_full"?[{tag:"markdown",content:`\uD83D\uDCE8 接续上一张(同一轮 ${Z},前卡写满或写入受限)`}]:$.kind==="bg_task_resume"?[{tag:"markdown",content:`\uD83D\uDD01 后台任务完成,${Z} 继续处理结果 #${$.turn}`}]:$.kind==="scheduled_wakeup"?[{tag:"markdown",content:`⏰ 定时任务触发,${Z} 正在执行巡检 #${$.turn}`}]:[],Y=$.userInputs??[],Q=`\uD83D\uDCE5 收到 (${Y.length}) ${$.directStart?"\uD83D\uDE80":`#${$.turn}`}`,H=Y.length>0?[{tag:"collapsible_panel",element_id:R.userInput,header:{title:{tag:"plain_text",content:Q}},expanded:!1,elements:Y.map((W)=>({tag:"markdown",content:r(W)}))}]:[];return{schema:"2.0",config:{streaming_mode:!0,summary:{content:"[Lodestar 正在生成…]"},streaming_config:{print_frequency_ms:{default:60,android:60,ios:60,pc:30},print_step:{default:2,android:2,ios:2,pc:4},print_strategy:"fast"}},body:{elements:[...J,...H,{tag:"markdown",element_id:R.footer,content:$.initialFooter??"Waiting...(0s)"}]}}}function vY($,Z,J){let Y=$.question.trim()||`问题 ${Z+1}`;return`${Z+1}/${J} · ${Y}`}function JA($,Z){if(!Z)return"?";return Z.customText??(Z.optionIdx!==void 0?$.options[Z.optionIdx]?.label:void 0)??"?"}function YA($,Z,J){let Y=[];for(let Q=0;Q<$.options.length;Q++){let H=$.options[Q],W=H.description?` · ${r(H.description)}`:"";Y.push({tag:"interactive_container",background_style:"default",has_border:!0,corner_radius:"6px",padding:"8px 12px",margin:"4px 0px 4px 0px",behaviors:[{type:"callback",value:{kind:"ask",tool_use_id:Z,question_idx:J,option_idx:Q}}],elements:[{tag:"markdown",content:`**${r(H.label)}**${W}`}]})}return Y}function bY($,Z,J,Y){if($.length===0)return null;let Q=$.length,H=[];for(let W=0;W<$.length;W++){let X=$[W];if(!X)continue;let V=vY(X,W,Q),z=Y.get(W);if(z){let G=JA(X,z),A=[`**✅ ${V}**`,`**回答**:${G}`];H.push({tag:"markdown",content:A.join(`
|
|
75
|
+
`)});continue}if(W===J){if(H.push({tag:"markdown",content:`**\uD83E\uDD14 ${V}**`}),X.options.length>0)H.push(...YA(X,Z,W));H.push({tag:"markdown",content:"_\uD83D\uDCAC 也可以直接在群里回复你的答案(裸词命令 `hi`/`stop`/`kill`/`restart`/`clear`/`model` 仍然优先)_"});continue}H.push({tag:"markdown",content:`**⏳ ${V}**`})}return H}function s1($,Z,J,Y="\uD83E\uDD14",Q){let H=J.length,W=Q?.answered??new Map,X=Q?.currentIdx,V=X===void 0&&W.size>0,z=[],G;if(Q?.waitingFor)G=Q.waitingFor==="notification"?"⏳ 等待通知回复完成":"⏳ 提问排队中",z.push({tag:"markdown",content:Q.waitingFor==="notification"?"请先完成或取消通知回复,再回答这个问题。":"先回答当前问题,再显示这个提问。"});else if(V){G=`${Y} 已回答 · ${H}/${H}`,z.push(...bY(J,Z,X,W)??[]);let A=[...W.values()].reverse().find((K)=>K.user)?.user;if(A)z.push({tag:"markdown",content:`
|
|
76
|
+
*— 由 ${A} 回答*`})}else if(X!==void 0&&J[X])G=`${Y} 等你确认 · ${X+1}/${H}`,z.push(...bY(J,Z,X,W)??[]);else if(G=`${Y} 等你确认`,J[0])z.push({tag:"markdown",content:`**${vY(J[0],0,H||1)}**`});return{tag:"collapsible_panel",element_id:R.tool($),header:{title:{tag:"plain_text",content:G}},expanded:!V&&!Q?.waitingFor,elements:z}}var hY=S(()=>{I0()});import{isAbsolute as $5,relative as QA}from"node:path";function w9($){return $==="Bash"||$==="exec_command"||$.endsWith(".exec_command")}function f9($){return $==="write_stdin"||$.endsWith(".write_stdin")}function WA($){return w9($)||f9($)}function v9($){return $==="FileChange"||$==="fileChange"}function Q4($){return $==="WebSearch"||$==="webSearch"}function h9($){return $==="WebFetch"||$==="webFetch"}function W5($){return $==="MCP"}function H4($){return $==="ImageGeneration"||$==="imageGeneration"}function X5($){return $==="Agent"||$==="Task"}function I9($){return $==="Read"}function g9($){return $==="Write"}function c9($){return $==="Edit"||$==="NotebookEdit"}function m9($){return $==="MultiEdit"}function V5($){return $==="Glob"||$==="Grep"||$==="LS"}function u9($){return $==="TodoWrite"}function p9($){return $==="ExitPlanMode"}function l9($){return $.startsWith(gY)}function cY($){return l9($)?$.slice(gY.length):$}function _1($){if(l9($))return"服务端工具";if(v9($))return"文件变更";if(Q4($))return"网页搜索";if(h9($))return"网页读取";if(H4($))return"图片生成";if(I9($))return"读取文件";if(g9($))return"写入文件";if(c9($)||m9($))return"编辑文件";if($==="Glob")return"匹配文件";if($==="Grep")return"搜索文件";if($==="LS")return"列目录";if(u9($))return"更新待办";if(p9($))return"确认计划";if($==="Task")return"子任务";return WA($)?"Bash":$}function f$($,Z){let J=(Y,Q)=>Y.length>Q?Y.slice(0,Q)+"…":Y;if(l9($))return J(XA($,Z),80);if(!Z||typeof Z!=="object")return"";if(w9($))return VA(Z);if(f9($))return zA(Z);if(v9($))return J(AA(Z),80);if(Q4($))return J(YQ(Z),80);if(h9($))return J(jA(Z),80);if(W5($))return J(MA(Z),80);if(H4($))return J(UA(Z),80);if(X5($))return J(OA(Z),80);if(I9($))return J(KA(Z),80);if(g9($))return J(BA(Z),80);if(c9($))return J(LA(Z),80);if(m9($))return J(qA(Z),80);if(V5($))return J(DA($,Z),80);if(u9($))return J(PA(Z),80);if(p9($))return J(W4(Z)||"提交计划",80);switch($){case"Skill":return J(String(Z.skill??""),80)}for(let Y of Object.values(Z))if(typeof Y==="string"&&Y)return J(Y,80);return""}function XA($,Z){let J=typeof Z?.tool==="string"&&Z.tool?Z.tool:cY($),Y=W4(Z?.input);return Y?`${J}: ${Y}`:J}function VA($){let Z=(H,W)=>H.length>W?H.slice(0,W)+"…":H,J=uY($);if(J.description)return Z(J.description.replace(/\s+/g," "),80);let Y=J.command;if(!Y)return"";let Q=Y.split(/\r?\n/).map((H)=>H.trim()).filter(Boolean);if(Q.length<=1)return Z(Y.replace(/\s+/g," "),80);return`Shell 脚本 · ${Q.length} 行 · ${Z(h1(Y),46)}`}function mY($){let Z=typeof $?.chars==="string"?$.chars:"";if(Z==="")return"读取会话输出";if(Z==="\x03")return"中断会话";return"发送输入"}function zA($){let Z=$?.session_id??$?.sessionId,J=Z===void 0?"":` ${Z}`;return`${mY($)}${J}`}function uY($){let Z=String($?.command??$?.cmd??$?.script??""),J=String($?.description??$?.reason??"").trim(),Y=k7(Z);return{description:Y.description||J,command:Y.command}}function y0($,Z=""){let J="```";while($.includes(J))J+="`";return`${J}${Z}
|
|
74
77
|
${$}
|
|
75
|
-
${J}`}function q$($,Z=
|
|
78
|
+
${J}`}function q$($,Z=HA,J=""){if($.length<=Z)return y0($,J);let Y=$.slice(0,Z).trimEnd();return[`_已截断: 仅显示前 ${Z} / ${$.length} 字符。_`,y0(`${Y}
|
|
76
79
|
... output 已截断 ...`,J)].join(`
|
|
77
|
-
`)}function
|
|
78
|
-
`)}function
|
|
79
|
-
`)}function
|
|
80
|
-
... diff 已截断 ...`:$}function
|
|
81
|
-
`):y0(JSON.stringify($??{},null,2).slice(0,2000))}let W=Y.map((z)=>
|
|
82
|
-
`)}function
|
|
83
|
-
`):
|
|
84
|
-
`):
|
|
85
|
-
`):
|
|
86
|
-
`)}function
|
|
87
|
-
`)}function
|
|
88
|
-
`)}function
|
|
89
|
-
`)}function
|
|
90
|
-
`)}function
|
|
91
|
-
`).slice(0,3000));if(H.structuredContent)Y.push(""),Y.push("**structuredContent**"),Y.push(
|
|
92
|
-
`):
|
|
93
|
-
`)}function
|
|
94
|
-
`):
|
|
95
|
-
`):
|
|
96
|
-
|
|
97
|
-
${H}`:"",K=
|
|
80
|
+
`)}function h($){return"`"+String($??"").replace(/`/g,"'")+"`"}function u0($,Z=3000){return y0(JSON.stringify($??null,null,2).slice(0,Z),"json")}function W4($){if(!$||typeof $!=="object")return"";let Z=$;for(let J of["query","prompt","path","file_path","url","name","id"]){let Y=Z[J];if(typeof Y==="string"&&Y.length>0)return Y}for(let J of Object.values(Z))if(typeof J==="string"&&J.length>0)return J;return""}function pY($,Z,J){let Y=uY($),Q=Y.command,H=Y.description,W=[];if(H)W.push(`**目的**: ${H}`);let X=$?.cwd??$?.workdir;if(X)W.push(`**cwd**: ${h(X)}`);if($?.source)W.push(`**source**: ${h($.source)}`);if(W.length>0)W.push("");if(W.push("**命令**"),W.push(y0(Q||"(空命令)","bash")),J)W.push(""),W.push(J);if(Z!=null)W.push(""),W.push("---"),W.push("**output:**"),W.push(q$(Z));return W.join(`
|
|
81
|
+
`)}function lY($,Z,J){let Y=[],Q=$?.session_id??$?.sessionId;if(Y.push(`**操作**: ${mY($)}`),Q!==void 0)Y.push(`**session**: ${h(Q)}`);if(typeof $?.chars==="string"&&$.chars.length>0){let H=$.chars==="\x03"?"^C":$.chars;Y.push(""),Y.push("**输入**"),Y.push(y0(H))}if(J)Y.push(""),Y.push(J);if(Z!=null)Y.push(""),Y.push("---"),Y.push("**output:**"),Y.push(q$(Z));return Y.join(`
|
|
82
|
+
`)}function iY($){return Array.isArray($?.changes)?$.changes:[]}function dY($){let Z=$?.cwd??$?.grantRoot;return typeof Z==="string"&&Z.length>0?Z:void 0}function Y4($,Z){let J=String($??"");if(!J)return"(无 path)";if(Z&&$5(J)&&$5(Z)){let Y=QA(Z,J);if(Y&&!Y.startsWith("..")&&!$5(Y))return Y}return J}function GA($){let Z=$?.kind;if(typeof Z==="string")return Z.toLowerCase();if(typeof Z?.type==="string")return Z.type.toLowerCase();if(typeof $?.type==="string")return $.type.toLowerCase();return""}function nY($){return $?.kind?.move_path??$?.kind?.movePath??$?.move_path??$?.movePath}function J5($){let Z=GA($);if(nY($))return Z==="update"?"移动/修改":"移动";switch(Z){case"add":return"新增";case"delete":return"删除";case"update":return"修改";default:return"变更"}}function Y5($){let Z=$?.diff??$?.unified_diff;return typeof Z==="string"?Z:""}function Q5($){let Z=0,J=0;for(let Y of $.split(/\r?\n/)){if(Y.startsWith("+++")||Y.startsWith("---"))continue;if(Y.startsWith("+"))Z++;if(Y.startsWith("-"))J++}return{added:Z,removed:J}}function aY($,Z){return{added:$.added+Z.added,removed:$.removed+Z.removed}}function H5($){return $.added>0||$.removed>0?`+${$.added} -${$.removed}`:""}function _A($){return $.length>1800?$.slice(0,1800)+`
|
|
83
|
+
... diff 已截断 ...`:$}function AA($){let Z=iY($),J=dY($);if(Z.length===0){let V=typeof $?.reason==="string"?$.reason.trim():"",z=$?.grantRoot?Y4($.grantRoot):"";if(V&&z)return`${V} · ${z}`;return V||(z?`申请修改 ${z}`:"")}let Y=Z.map((V)=>Q5(Y5(V))).reduce(aY,{added:0,removed:0}),Q=H5(Y),H=[...new Set(Z.map(J5))],W=Y4(Z[0]?.path,J),X=Q?` · ${Q}`:"";if(Z.length===1)return`${H[0]} ${W}${X}`;return`${Z.length} 个文件 · ${H.join("/")} · ${W} 等${X}`}function oY($,Z,J){let Y=iY($),Q=dY($),H=[];if(Y.length===0){let z=typeof $?.reason==="string"?$.reason.trim():"";if(z)H.push(`**原因**: ${z}`);if($?.grantRoot)H.push(`**范围**: ${h(Y4($.grantRoot))}`);if(J)H.push(""),H.push(J);if(Z!=null)H.push(""),H.push("---"),H.push("**output:**"),H.push(y0(Z.slice(0,3000)));return H.length>0?H.join(`
|
|
84
|
+
`):y0(JSON.stringify($??{},null,2).slice(0,2000))}let W=Y.map((z)=>Q5(Y5(z))).reduce(aY,{added:0,removed:0}),X=H5(W);if(H.push(`**文件**: ${Y.length} 个`),X)H.push(`**行数**: ${X}`);if($?.status)H.push(`**状态**: ${h($.status)}`);let V=Y.slice(0,5);for(let z of V){let G=Y5(z),A=H5(Q5(G)),K=Y4(z?.path,Q),L=A?`**${J5(z)}** ${h(K)} · ${A}`:`**${J5(z)}** ${h(K)}`;H.push(""),H.push(L);let D=nY(z);if(D)H.push(`来自 ${h(Y4(D,Q))}`);H.push(G?y0(_A(G),"diff"):"_无 diff 内容_")}if(Y.length>V.length)H.push(""),H.push(`还有 ${Y.length-V.length} 个文件未展开显示。`);if(J)H.push(""),H.push(J);return H.join(`
|
|
85
|
+
`)}function v$($){return String($?.file_path??$?.path??$?.notebook_path??"")}function KA($){let Z=v$($),J=[$?.offset!=null?`offset ${$.offset}`:"",$?.limit!=null?`limit ${$.limit}`:""].filter(Boolean).join(" · ");return J&&Z?`${Z} · ${J}`:Z}function BA($){let Z=v$($),J=typeof $?.content==="string"?$.content:"",Y=J?J.split(/\r?\n/).length:0;return Z&&Y?`${Z} · ${Y} 行`:Z}function LA($){let Z=v$($),J=$?.replace_all?"全局替换":"替换";return Z?`${J} ${Z}`:J}function qA($){let Z=v$($),J=Array.isArray($?.edits)?$.edits.length:0,Y=J?` · ${J} 处`:"";return Z?`批量编辑 ${Z}${Y}`:`批量编辑${Y}`}function DA($,Z){if($==="Glob"){let J=String(Z?.pattern??"");return Z?.path?`${J} · ${Z.path}`:J}if($==="Grep"){let J=String(Z?.pattern??"");return Z?.path?`${J} · ${Z.path}`:J}return String(Z?.path??"")}function rY($){switch($){case"pending":return"待办";case"in_progress":return"进行中";case"completed":return"完成";default:return String($??"未知")}}function PA($){let Z=Array.isArray($?.todos)?$.todos:[];if(Z.length===0)return"";let J=new Map;for(let Q of Z){let H=rY(Q?.status);J.set(H,(J.get(H)??0)+1)}let Y=[...J.entries()].map(([Q,H])=>`${Q} ${H}`).join(" · ");return`${Z.length} 项${Y?` · ${Y}`:""}`}function jA($){let Z=String($?.url??""),J=typeof $?.prompt==="string"?$.prompt.trim():"";return Z&&J?`${Z} · ${J}`:Z||J}function e1($,Z){if(Z==null)return;$.push(""),$.push("---"),$.push("**结果**"),$.push(q$(Z,1200))}function tY($,Z,J){let Y=[],Q=v$($);if(Q)Y.push(`**路径**: ${h(Q)}`);if($?.offset!=null)Y.push(`**offset**: ${h($.offset)}`);if($?.limit!=null)Y.push(`**limit**: ${h($.limit)}`);if(J)Y.push(""),Y.push(J);if(Z!=null)Y.push(""),Y.push("_内容已读取,未展开到群聊卡片。_");return Y.length>0?Y.join(`
|
|
86
|
+
`):u0($??{},2000)}function sY($,Z,J){let Y=[],Q=v$($),H=typeof $?.content==="string"?$.content:"";if(Q)Y.push(`**路径**: ${h(Q)}`);if(H){let W=H.split(/\r?\n/).length;Y.push(`**内容**: ${W} 行 / ${H.length} 字符`),Y.push(q$(H,1200))}if(J)Y.push(""),Y.push(J);return e1(Y,Z),Y.length>0?Y.join(`
|
|
87
|
+
`):u0($??{},2000)}function eY($,Z,J){let Y=[],Q=v$($);if(Q)Y.push(`**路径**: ${h(Q)}`);if($?.cell_id)Y.push(`**cell**: ${h($.cell_id)}`);if($?.edit_mode)Y.push(`**模式**: ${h($.edit_mode)}`);if($?.replace_all)Y.push("**范围**: 全局替换");if(typeof $?.old_string==="string")Y.push(""),Y.push("**查找**"),Y.push(q$($.old_string,800));let H=typeof $?.new_string==="string"?$.new_string:typeof $?.new_source==="string"?$.new_source:"";if(H)Y.push(""),Y.push("**替换为**"),Y.push(q$(H,800));if(J)Y.push(""),Y.push(J);return e1(Y,Z),Y.length>0?Y.join(`
|
|
88
|
+
`):u0($??{},2000)}function $Q($,Z,J){let Y=[],Q=v$($),H=Array.isArray($?.edits)?$.edits:[];if(Q)Y.push(`**路径**: ${h(Q)}`);Y.push(`**编辑**: ${H.length} 处`);for(let[W,X]of H.slice(0,5).entries()){if(Y.push(""),Y.push(`**#${W+1}${X?.replace_all?" · 全局替换":""}**`),typeof X?.old_string==="string")Y.push("查找:"),Y.push(q$(X.old_string,500));if(typeof X?.new_string==="string")Y.push("替换为:"),Y.push(q$(X.new_string,500))}if(H.length>5)Y.push(""),Y.push(`还有 ${H.length-5} 处编辑未展开显示。`);if(J)Y.push(""),Y.push(J);return e1(Y,Z),Y.join(`
|
|
89
|
+
`)}function ZQ($,Z,J,Y){let Q=[];if($==="Glob"){if(Q.push("**动作**: 匹配文件"),Z?.pattern)Q.push(`**pattern**: ${h(Z.pattern)}`);if(Z?.path)Q.push(`**path**: ${h(Z.path)}`)}else if($==="Grep"){if(Q.push("**动作**: 搜索文件"),Z?.pattern)Q.push(`**pattern**: ${h(Z.pattern)}`);if(Z?.path)Q.push(`**path**: ${h(Z.path)}`);if(Z?.glob)Q.push(`**glob**: ${h(Z.glob)}`);if(Z?.type)Q.push(`**type**: ${h(Z.type)}`);if(Z?.output_mode)Q.push(`**output**: ${h(Z.output_mode)}`)}else{if(Q.push("**动作**: 列目录"),Z?.path)Q.push(`**path**: ${h(Z.path)}`);if(Array.isArray(Z?.ignore)&&Z.ignore.length)Q.push(`**ignore**: ${Z.ignore.map(h).join(" ")}`)}if(Y)Q.push(""),Q.push(Y);return e1(Q,J),Q.join(`
|
|
90
|
+
`)}function JQ($,Z,J){let Y=Array.isArray($?.todos)?$.todos:[],Q=[`**待办**: ${Y.length} 项`];for(let H of Y.slice(0,12)){let W=rY(H?.status),X=String(H?.content??H?.activeForm??"").trim()||"(空)";Q.push(`- ${W}: ${X}`)}if(Y.length>12)Q.push(`- 还有 ${Y.length-12} 项未显示`);if(J)Q.push(""),Q.push(J);return e1(Q,Z),Q.join(`
|
|
91
|
+
`)}function z5($){if(!$)return null;try{let Z=JSON.parse($);return Z&&typeof Z==="object"?Z:null}catch{return null}}function G5($,Z){return z5(Z)??$?.action??{}}function _5($,Z){let J=G5($,Z),Y=Array.isArray(J?.queries)?J.queries.filter((H)=>typeof H==="string"&&H.length>0):[],Q=typeof J?.query==="string"&&J.query.length>0?J.query:typeof $?.query==="string"&&$.query.length>0?$.query:"";return Y.length>0?Y:Q?[Q]:[]}function A5($,Z){let J=G5($,Z);return String(J?.url??$?.url??"")}function YQ($){let Z=_5($,null);if(Z.length===1)return Z[0];if(Z.length>1)return`${Z.length} 条查询 · ${Z[0]}`;let J=A5($,null);if(J)return J;let Y=$?.action?.type;return typeof Y==="string"&&Y!=="other"?Y:""}function FA($,Z){let J=_5($,Z);if(J.length===1)return J[0];if(J.length>1)return`${J.length} 条查询 · ${J[0]}`;let Y=A5($,Z);if(Y)return Y;return YQ($)}function QQ($,Z,J){let Y=G5($,Z),Q=_5($,Z),H=A5($,Z),W=[],X=typeof Y?.type==="string"?Y.type:"";if(X==="search"||Q.length>0){if(W.push("**动作**: 搜索"),Q.length>0){W.push(""),W.push("**查询**");for(let V of Q.slice(0,6))W.push(`- ${h(V)}`);if(Q.length>6)W.push(`- 还有 ${Q.length-6} 条未显示`)}}else if(X==="open_page"){if(W.push("**动作**: 打开页面"),H)W.push(`**URL**: ${h(H)}`)}else if(X==="find_in_page"){if(W.push("**动作**: 页内查找"),H)W.push(`**URL**: ${h(H)}`);if(Y?.pattern)W.push(`**关键词**: ${h(Y.pattern)}`)}else if(W.push(`**动作**: ${X?h(X):"网页搜索"}`),H)W.push(`**URL**: ${h(H)}`);if(J)W.push(""),W.push(J);if(W.length===1&&!Q.length&&!H&&Z!=null)W.push(""),W.push("---"),W.push("**output:**"),W.push(y0(Z.slice(0,3000),"json"));return W.join(`
|
|
92
|
+
`)}function HQ($,Z,J){let Y=["**动作**: 读取网页"];if($?.url)Y.push(`**URL**: ${h($.url)}`);if($?.prompt)Y.push(""),Y.push("**问题**"),Y.push(String($.prompt).slice(0,1200));if(J)Y.push(""),Y.push(J);return e1(Y,Z),Y.join(`
|
|
93
|
+
`)}function MA($){let Z=String($?.server??""),J=String($?.tool??""),Y=Z&&J?`${Z}.${J}`:J||Z,Q=W4($?.arguments);return Q&&Y?`${Y}: ${Q}`:Y||Q}function WQ($,Z,J){let Y=[];if($?.server)Y.push(`**server**: ${h($.server)}`);if($?.tool)Y.push(`**tool**: ${h($.tool)}`);let Q=$?.arguments;if(Q&&typeof Q==="object"&&Object.keys(Q).length>0){if(Y.length>0)Y.push("");Y.push("**arguments**"),Y.push(u0(Q,2000))}if(J)Y.push(""),Y.push(J);if(Z!=null){let H=z5(Z);if(Y.push(""),Y.push("---"),Y.push("**结果**"),H&&Array.isArray(H.content)){let W=H.content.map((X)=>typeof X?.text==="string"?X.text:"").filter(Boolean);if(W.length>0)Y.push(W.join(`
|
|
94
|
+
`).slice(0,3000));if(H.structuredContent)Y.push(""),Y.push("**structuredContent**"),Y.push(u0(H.structuredContent,2000));if(W.length===0&&!H.structuredContent)Y.push(u0(H,3000))}else Y.push(H?u0(H,3000):y0(Z.slice(0,3000)))}return Y.length>0?Y.join(`
|
|
95
|
+
`):u0($??{},2000)}function RA($,Z,J,Y){let Q=["**类型**: 模型服务端内置工具",`**tool**: ${h(typeof Z?.tool==="string"&&Z.tool?Z.tool:cY($))}`],H=Z?.input;if(H&&typeof H==="object")if(Q.push(""),Q.push("**input**"),Object.keys(H).length>0)Q.push(u0(H,2000));else Q.push("_provider 未提供结构化 input_");else if(H!=null&&H!=="")Q.push(`**input**: ${h(H)}`);if(Y)Q.push(""),Q.push(Y);if(J!=null)Q.push(""),Q.push("---"),Q.push("**结果**"),Q.push(q$(J,3000));return Q.join(`
|
|
96
|
+
`)}function UA($){return typeof $?.status==="string"?$.status:""}function XQ($,Z,J,Y){let Q=[];if($?.status)Q.push(`**状态**: ${h($.status)}`);if($?.prompt)Q.push("","**提示词**",y0(String($.prompt)));if($?.revisedPrompt){if($.revisedPrompt!==$.prompt)Q.push("",$.prompt?"**实际提示词**":"**提示词**",y0(String($.revisedPrompt)))}if(J)Q.push(""),Q.push(J);if(!Y&&Z!=null&&Z.trim())Q.push(""),Q.push("---"),Q.push("**输出**"),Q.push(h(Z.trim()));return Q.length>0?Q.join(`
|
|
97
|
+
`):u0($??{},2000)}function OA($){let Z=typeof $?.tool==="string"?$.tool:"",J=typeof $?.prompt==="string"?$.prompt:"",Y=typeof $?.description==="string"?$.description:"",Q=typeof $?.subject==="string"?$.subject:"",H=Y||Q||J;return Z&&H?`${Z}: ${H}`:H||Z}function y9($,Z,J){let Y=[];if($?.tool)Y.push(`**tool**: ${h($.tool)}`);if($?.model)Y.push(`**model**: ${h($.model)}`);if($?.description)Y.push(`**描述**: ${$.description}`);if($?.subagent_type)Y.push(`**类型**: ${h($.subagent_type)}`);if($?.prompt){if(Y.length>0)Y.push("");Y.push("**prompt**"),Y.push(String($.prompt).slice(0,2000))}if(J)Y.push(""),Y.push(J);if(Z!=null){Y.push(""),Y.push("---"),Y.push("**状态**");let Q=z5(Z);Y.push(Q?u0(Q,3000):y0(Z.slice(0,3000)))}return Y.length>0?Y.join(`
|
|
98
|
+
`):u0($??{},2000)}function W$($,Z,J,Y,Q="⏳",H,W){let X=Q4(Z)&&Y!=null?FA(J,Y):f$(Z,J),V=X.length>80?X.slice(0,80)+"…":X,z=_1(Z),G=V?`${Q} \uD83D\uDD27 ${z}: ${V}`:`${Q} \uD83D\uDD27 ${z}`,A=H?`
|
|
99
|
+
|
|
100
|
+
${H}`:"",K=w9(Z)?pY(J,Y,H):f9(Z)?lY(J,Y,H):l9(Z)?RA(Z,J,Y,H):v9(Z)?oY(J,Y,H):Q4(Z)?QQ(J,Y,H):h9(Z)?HQ(J,Y,H):W5(Z)?WQ(J,Y,H):H4(Z)?XQ(J,Y,H,W):I9(Z)?tY(J,Y,H):g9(Z)?sY(J,Y,H):c9(Z)?eY(J,Y,H):m9(Z)?$Q(J,Y,H):V5(Z)?ZQ(Z,J,Y,H):u9(Z)?JQ(J,Y,H):p9(Z)?y9({prompt:W4(J)||"提交计划"},Y,H):X5(Z)?y9(J,Y,H):"```\n"+JSON.stringify(J??{},null,2).slice(0,2000)+"\n```"+A+(Y!=null?`
|
|
98
101
|
---
|
|
99
102
|
**output:**
|
|
100
103
|
\`\`\`
|
|
101
|
-
`+Y.slice(0,3000)+"\n```":"");return{tag:"collapsible_panel",element_id:R.tool($),header:{title:{tag:"plain_text",content:G}},expanded:!1,elements:[{tag:"markdown",content:
|
|
102
|
-
`))}]}}function
|
|
103
|
-
`))}]}}function
|
|
104
|
-
`).map((V)=>V.trim()).filter((V)=>V.length>0);if(Z.length===0)return{services:[],error:null};let J=[];for(let V of Z){let G=V.replace(/^●\s*/,"").split(/\s+/)[0];if(!G)continue;if(!
|
|
105
|
-
`)){let K=
|
|
106
|
-
`);let Z=[];if($.cpu){let{cores:J,load1:Y,load5:Q,load15:H}=$.cpu;Z.push(`**负载** ${Y.toFixed(2)} / ${Q.toFixed(2)} / ${H.toFixed(2)} (${J}核)`)}else Z.push("**负载** _n/a_");if($.mem)Z.push(`**内存** ${$.mem.percent}% (${LQ($.mem.usedBytes)}/${LQ($.mem.totalBytes)})`);else Z.push("**内存** _n/a_");if($.servicesError)Z.push(`**服务** ${
|
|
107
|
-
`)}function
|
|
108
|
-
`)}function
|
|
109
|
-
`)}function
|
|
110
|
-
`):
|
|
111
|
-
**重置卡** ${$.resetCredits===null?"MISS":`${$.resetCredits} 次可用`}`;return Z+J}function
|
|
112
|
-
选账号进入模型选择。`},...["claude","codex","dsh"].flatMap((Z)=>{let J=$.providers.filter((Y)=>(Y.provider??"codex")===Z);return J.length?[{tag:"collapsible_panel",element_id:R.modelAgentGroup(Z),expanded:!0,header:{title:{tag:"markdown",content:`**Agent · ${{claude:"Claude Code",codex:"Codex",dsh:"DeepSeek Harness"}[Z]}**`},background_color:"blue-50"},border:{color:"blue-100",corner_radius:"8px"},padding:"8px",margin:"8px 0px 0px 0px",elements:J.map((Y)=>
|
|
113
|
-
${Y}`}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:$.selected?"primary":"default",behaviors:[{type:"callback",value:{kind:"provider_select",panel_id:Z,source_id:$.sourceId,...$.provider?{provider:$.provider}:{}}}]}]}]}}function
|
|
114
|
-
`)},...$.models.length?Z:[{tag:"markdown",content:$.editable?$.mode==="add"?"_没有待显示的接口模型_":"_列表为空,可显示接口模型或补录_":"_未返回可用模型列表_"}],...$.pagination?
|
|
115
|
-
`)},{tag:"button",text:{tag:"plain_text",content:"取消"},type:"default",width:"default",behaviors:[{type:"callback",value:{kind:"model_panel_cancel",panel_id:J}}]}]},"blue")}function
|
|
116
|
-
${J}`:""}`:`❌ \`${Z}\` 未加入 — ${J}`}]}}function
|
|
117
|
-
`)},...$.model.efforts.length?$.model.efforts.map((Z)=>
|
|
118
|
-
`)}]}}function
|
|
119
|
-
${
|
|
120
|
-
`+
|
|
121
|
-
`)+W}]},{tag:"column",width:"weighted",weight:1,vertical_align:"center",elements:[...J==="add"?[X("model_add","显")]:$.unavailableReason?[{tag:"markdown",content:"**MISS**"}]:[{tag:"button",text:{tag:"plain_text",content:"选"},type:$.selected?"primary":"default",behaviors:[{type:"callback",value:
|
|
122
|
-
`)}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:H?"primary":"default",behaviors:[{type:"callback",value:{kind:"model_effort_select",panel_id:J,...$.sourceId?{source_id:$.sourceId}:{},...$.provider?{provider:$.provider}:{},model:$.model,effort:Z.effort}}]}]}]}}function
|
|
104
|
+
`+Y.slice(0,3000)+"\n```":"");return{tag:"collapsible_panel",element_id:R.tool($),header:{title:{tag:"plain_text",content:G}},expanded:!1,elements:[{tag:"markdown",content:r(K)},...H4(Z)&&W?[{tag:"img",img_key:W,alt:{tag:"plain_text",content:"生成的图片"},scale_type:"fit_horizontal",preview:!0}]:[]]}}function X4($,Z){let J=Z.length,Y=Z.some((V)=>V.isError),Q=Z.every((V)=>V.output!==null),H=Y?"❌":Q?"✅":"⏳",W=J===1?(()=>{let V=IY(Z[0]);return V?`${H} \uD83D\uDD27 编辑文件: ${V}`:`${H} \uD83D\uDD27 编辑文件`})():`${H} \uD83D\uDD27 编辑文件 · ${J} 次`,X=Z.map((V)=>{let z=IY(V);return z?`\`${z}\``:"`(无 path)`"});return{tag:"collapsible_panel",element_id:R.tool($),header:{title:{tag:"plain_text",content:W}},expanded:!1,elements:[{tag:"markdown",content:r(X.join(`
|
|
105
|
+
`))}]}}function IY($){let Z=$.input??{},J=String(Z.file_path??Z.path??Z.notebook_path??"");if(Array.isArray(Z.edits)&&Z.edits.length>0)return J?`${J} · ${Z.edits.length} 处`:`${Z.edits.length} 处`;if(Z.replace_all&&J)return`${J} · 全局替换`;return J}function V4($,Z){let J=Z.length,Y=Z.some((V)=>V.isError),Q=Z.every((V)=>V.output!==null),H=Y?"❌":Q?"✅":"⏳",W=J===1?(()=>{let V=f$("Read",Z[0]?.input);return V?`${H} \uD83D\uDD27 Read: ${V}`:`${H} \uD83D\uDD27 Read`})():`${H} \uD83D\uDD27 Read · ${J} 次`,X=Z.map((V)=>`\`${String(V.input.file_path??"(无 path)")}\``);return{tag:"collapsible_panel",element_id:R.tool($),header:{title:{tag:"plain_text",content:W}},expanded:!1,elements:[{tag:"markdown",content:r(X.join(`
|
|
106
|
+
`))}]}}function K5($,Z,J,Y){let Q=f$(Z,J),H=_1(Z),W=Q?`\uD83D\uDD10 等审批 · ${H}: ${Q}`:`\uD83D\uDD10 等审批 · ${H}`,X=w9(Z)?pY(J,null):f9(Z)?lY(J,null):v9(Z)?oY(J,null):Q4(Z)?QQ(J,null):h9(Z)?HQ(J,null):W5(Z)?WQ(J,null):H4(Z)?XQ(J,null):I9(Z)?tY(J,null):g9(Z)?sY(J,null):c9(Z)?eY(J,null):m9(Z)?$Q(J,null):V5(Z)?ZQ(Z,J,null):u9(Z)?JQ(J,null):p9(Z)?y9({prompt:W4(J)||"提交计划"},null):X5(Z)?y9(J,null):"```\n"+JSON.stringify(J??{},null,2).slice(0,2000)+"\n```";return{tag:"collapsible_panel",element_id:R.tool($),header:{title:{tag:"plain_text",content:W}},expanded:!0,elements:[{tag:"markdown",content:X},{tag:"column_set",columns:[Z5("✅ 允许","primary",Y,"allow"),Z5("♾️ 始终允许","default",Y,"allow_always"),Z5("❌ 拒绝","danger",Y,"deny")]}]}}function Z5($,Z,J,Y){return{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:$},type:Z,behaviors:[{type:"callback",value:{kind:"permission",request_id:J,decision:Y}}]}]}}var HA=300,gY="server_tool:";var VQ=S(()=>{I0();o4()});import{execFile as TA}from"node:child_process";import{readFileSync as B5,statfsSync as EA,statSync as zQ}from"node:fs";import{cpus as NA,homedir as SA}from"node:os";import{promisify as xA}from"node:util";function CA(){try{let $=B5("/proc/loadavg","utf8").trim().split(/\s+/);return{cores:NA().length,load1:parseFloat($[0]??"0"),load5:parseFloat($[1]??"0"),load15:parseFloat($[2]??"0")}}catch($){return _(`sysinfo: read /proc/loadavg failed: ${$}`),null}}function bA(){try{let $=B5("/proc/meminfo","utf8"),Z=(H)=>{let W=$.match(new RegExp(`^${H}:\\s+(\\d+)\\s*kB`,"m"));return W?parseInt(W[1],10)*1024:0},J=Z("MemTotal"),Y=Z("MemAvailable");if(!J)return null;let Q=Math.max(0,J-Y);return{totalBytes:J,availBytes:Y,usedBytes:Q,percent:Math.round(Q/J*100)}}catch($){return _(`sysinfo: read /proc/meminfo failed: ${$}`),null}}function GQ($,Z){try{let J=EA(Z,{bigint:!1}),Y=J.blocks*J.bsize,Q=J.bavail*J.bsize,H=Math.max(0,Y-Q);if(!Y)return null;return{label:$,path:Z,totalBytes:Y,availBytes:Q,usedBytes:H,percent:Math.round(H/Y*100)}}catch(J){return _(`sysinfo: statfs ${Z} failed: ${J}`),null}}function yA(){let $=[],Z=GQ("/","/");if(Z)$.push(Z);let J=SA();if(J&&J!=="/"){let Y=!1;try{let Q=zQ("/"),H=zQ(J);Y=Q.dev===H.dev}catch{}if(!Y){let Q=GQ("$HOME",J);if(Q)$.push(Q)}}return $}function wA(){try{let $=B5("/proc/uptime","utf8").trim().split(/\s+/);return parseFloat($[0]??"0")}catch{return null}}async function _Q($,Z=2000){try{let{stdout:J}=await kA("systemctl",["--user",...$],{timeout:Z,maxBuffer:4194304});return J}catch(J){return _(`sysinfo: systemctl ${$.join(" ")} failed: ${J}`),null}}function AQ($){return KQ.some((Z)=>$.startsWith(Z))&&$.endsWith(".service")}async function fA(){let $=await _Q(["list-units","--type=service","--all","--no-legend","--plain",...KQ.map((V)=>`${V}*`)]);if($===null)return{services:[],error:"systemctl 不可用"};let Z=$.split(`
|
|
107
|
+
`).map((V)=>V.trim()).filter((V)=>V.length>0);if(Z.length===0)return{services:[],error:null};let J=[];for(let V of Z){let G=V.replace(/^●\s*/,"").split(/\s+/)[0];if(!G)continue;if(!AQ(G))continue;J.push(G)}if(J.length===0)return{services:[],error:null};let Y=await _Q(["show",...J,"-p","Id","-p","ActiveState","-p","SubState","-p","ActiveEnterTimestampMonotonic","-p","StateChangeTimestampMonotonic"]);if(Y===null)return{services:[],error:"systemctl show 失败"};let Q=wA(),H=Y.split(/\n\s*\n/),W=[],X=(V)=>{let z=parseInt(V??"0",10);if(z<=0||Q===null)return null;return Math.max(0,Q-z/1e6)};for(let V of H){let z={};for(let A of V.split(`
|
|
108
|
+
`)){let K=A.indexOf("=");if(K<=0)continue;z[A.slice(0,K)]=A.slice(K+1)}let G=z.Id??"";if(!AQ(G))continue;W.push({name:G.replace(/\.service$/,""),active:z.ActiveState??"unknown",sub:z.SubState??"",lastActiveAgoSec:X(z.ActiveEnterTimestampMonotonic),stateAgoSec:X(z.StateChangeTimestampMonotonic)})}return W.sort((V,z)=>V.name.localeCompare(z.name)),{services:W,error:null}}async function BQ(){if(process.platform==="win32")return{cpu:null,mem:null,disks:[],services:[],servicesError:"Windows: sysinfo 暂未支持"};let $=CA(),Z=bA(),J=yA(),{services:Y,error:Q}=await fA();return{cpu:$,mem:Z,disks:J,services:Y,servicesError:Q}}var kA,KQ,z4="cc-* / codex-*";var L5=S(()=>{g();kA=xA(TA),KQ=["cc-","codex-"]});function _4($,Z){return Z}function q5($){return{schema:"2.0",config:{update_multi:!0,streaming_mode:!0,summary:{content:$.status}},body:{elements:[{tag:"markdown",element_id:R.footer,content:_4($.title,$.status)}]}}}function LQ($){if($<1024)return`${$}B`;if($<1048576)return`${($/1024).toFixed(0)}K`;if($<1073741824)return`${($/1048576).toFixed(0)}M`;let Z=$/1073741824;return Z<10?`${Z.toFixed(1)}G`:`${Z.toFixed(0)}G`}function vA($){if(!$)return"0";if($<1000)return String($);if($<1e6)return($/1000).toFixed($<1e4?1:0).replace(/\.0$/,"")+"K";return($/1e6).toFixed(2).replace(/\.?0+$/,"")+"M"}function G4($){if($<60000)return`${Math.round($/1000)}s`;let Z=Math.floor($/60000);if(Z<60)return`${Z}m`;let J=Math.floor(Z/60),Y=Z%60;if(J<24)return`${J}h ${Y}m`;return`${Math.floor(J/24)}d ${J%24}h`}function D5($){if(!$)return"?";let Z=$.getTime()-Date.now();if(Z<=0)return"已重置";if(Z<3600000)return`${Math.max(1,Math.round(Z/60000))}m`;if(Z<86400000)return`${(Z/3600000).toFixed(1)}h`;return`${(Z/86400000).toFixed(1)}d`}function cA($){let Z=[];if($?.cpu)Z.push(`L${$.cpu.load1.toFixed(2)}`);if($?.mem)Z.push(`M${$.mem.percent}%`);if($&&!$.servicesError)Z.push(`S${$.services.length}`);return Z}function mA($){if(!$)return["**负载** _n/a_","**内存** _n/a_",`**服务** ${z4} _n/a_`].join(`
|
|
109
|
+
`);let Z=[];if($.cpu){let{cores:J,load1:Y,load5:Q,load15:H}=$.cpu;Z.push(`**负载** ${Y.toFixed(2)} / ${Q.toFixed(2)} / ${H.toFixed(2)} (${J}核)`)}else Z.push("**负载** _n/a_");if($.mem)Z.push(`**内存** ${$.mem.percent}% (${LQ($.mem.usedBytes)}/${LQ($.mem.totalBytes)})`);else Z.push("**内存** _n/a_");if($.servicesError)Z.push(`**服务** ${z4} _${$.servicesError}_`);else if($.services.length===0)Z.push(`**服务** ${z4} _无_`);else{Z.push(`**服务** ${z4} (${$.services.length})`);for(let J of $.services){let Y=gA[J.active]??"·",Q=J.lastActiveAgoSec,H=J.stateAgoSec,W=[J.active];if(J.active==="active"){if(H!=null)W.push(`已运行 ${G4(H*1000)}`)}else if(J.active==="inactive"||J.active==="failed"){if(Q!=null)W.push(`上次活跃 ${G4(Q*1000)}前`);else W.push("从未启动");if(H!=null){let X=J.active==="failed"?"已挂":"已停";W.push(`${X} ${G4(H*1000)}`)}}else if(H!=null)W.push(`已 ${G4(H*1000)}`);Z.push(` · ${Y} \`${J.name}\` · ${W.join(" · ")}`)}}return Z.join(`
|
|
110
|
+
`)}function uA($){let Z=$.peers??[];if(Z.length===0)return"_无_";return Z.map((J)=>{let Y=hA[J.status]??"·",Q=IA[J.status]??J.status,H=J.uptimeMs!=null&&J.uptimeMs>0?` · ${G4(J.uptimeMs)}`:"",W=J.isCurrent?" · 当前":"";return` · ${Y} \`${J.name}\` · ${Q}${H}${W}`}).join(`
|
|
111
|
+
`)}function i9($,Z=R.consoleProjects){let J=$.peers??[];return{tag:"collapsible_panel",element_id:Z,header:{title:{tag:"plain_text",content:`\uD83D\uDDC2 活跃项目 (${J.length})`}},expanded:!1,elements:[{tag:"markdown",content:uA($)}]}}function pA($){let Z=$.model?`${$.model}${$.effort?`/${$.effort}`:""}`:$.effort?`强度 ${$.effort}`:"未就绪";return[`**\uD83E\uDD16 当前模型${$.provider==="claude"?` (${U5($.provider)})`:""}** \`${Z}\``,...$.worktreeInstructionNotice?[$.worktreeInstructionNotice]:[]].join(`
|
|
112
|
+
`)}function d9($,Z=R.consoleCurrentModel){return{tag:"markdown",element_id:Z,content:pA($)}}function n9($,Z=R.consoleHost){let J=cA($);return{tag:"collapsible_panel",element_id:Z,header:{title:{tag:"plain_text",content:J.length>0?`\uD83D\uDDA5 主机 · ${J.join(" · ")}`:"\uD83D\uDDA5 主机"}},expanded:!1,elements:[{tag:"markdown",content:mA($)}]}}function a9($){let Z=$?.kind==="balance"?"余额":"额度";if(!$)return`${Z} 加载中…`;if($.state==="not_applicable")return`${Z} —`;if($.state!=="ok")return`${Z} MISS`;let J=(Y,Q)=>`${Q==="USD"?"$":Q==="CNY"?"¥":`${Q} `}${Y.toFixed(2)}`;if($.kind==="balance")return $.balance?`余额 ${J($.balance.remaining,$.balance.currency)}`:"余额 MISS";if($.quota)return $.quota.limit===null?"额度 未设上限":$.quota.remaining===null?"额度 MISS":`额度 ${J($.quota.remaining,$.quota.currency)} / ${J($.quota.limit,$.quota.currency)}`;if(!$.windows.length)return"额度 MISS";return`额度 ${$.windows.map(qQ).join(" · ")}`}function qQ($){let Z=typeof $.used==="number"&&typeof $.total==="number"?`${$.used}/${$.total}`:$.percent===null?"MISS":`${Math.round($.percent)}%`;return`${$.label} 已用 ${Z}`}function lA($){let Z=$?.state==="ok"&&$.kind!=="balance"&&!$.quota&&$.windows.length?["**\uD83D\uDCCA 额度**",...$.windows.map(qQ)].join(`
|
|
113
|
+
`):a9($).replace(/^(额度|余额)/,"**\uD83D\uDCCA $1**"),J=$?.resetCredits===void 0?"":`
|
|
114
|
+
**重置卡** ${$.resetCredits===null?"MISS":`${$.resetCredits} 次可用`}`;return Z+J}function A4($){let Z=lA($.unifiedUsage);return{tag:"markdown",element_id:R.consoleUsage,content:Z}}function DQ($,Z){return[d9($,Z),i9($),n9($.sysinfo),A4($)]}function P5($){let{sessionName:Z,status:J}=$,Y=J==="working"?"blue":J==="awaiting_permission"?"orange":J==="stopped"?"grey":"green";return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83C\uDF1F Lodestar · ${Z}`},template:Y},body:{elements:DQ($)}}}function j5($){return $2($.sessionName,{tag:"collapsible_panel",element_id:R.modelPanel,header:{title:{tag:"plain_text",content:"选择账号"}},expanded:!0,elements:[{tag:"markdown",content:`当前: ${A1($.currentDisplay??"未选择")}
|
|
115
|
+
选账号进入模型选择。`},...["claude","codex","dsh"].flatMap((Z)=>{let J=$.providers.filter((Y)=>(Y.provider??"codex")===Z);return J.length?[{tag:"collapsible_panel",element_id:R.modelAgentGroup(Z),expanded:!0,header:{title:{tag:"markdown",content:`**Agent · ${{claude:"Claude Code",codex:"Codex",dsh:"DeepSeek Harness"}[Z]}**`},background_color:"blue-50"},border:{color:"blue-100",corner_radius:"8px"},padding:"8px",margin:"8px 0px 0px 0px",elements:J.map((Y)=>iA(Y,$.panelId))}]:[]})]})}function iA($,Z){if(!$.enabled)return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`⚙️ **${X$($.display)}** · 未配置`}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"启"},type:"primary",behaviors:[{type:"callback",value:{kind:"token_source_enable",source_id:$.sourceId}}]}]}]};let J=$.catalogStatus==="failed"?`模型目录 MISS${$.catalogError?`:${$.catalogError}`:""}`:$.catalogStatus==="loading"||$.catalogStatus==="idle"?"模型目录加载中":`${$.modelCount} 个模型`,Y=[$.selected?"当前账号":"",J].filter(Boolean).join(" · ");return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`**${X$($.display)}**
|
|
116
|
+
${Y}`}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:$.selected?"primary":"default",behaviors:[{type:"callback",value:{kind:"provider_select",panel_id:Z,source_id:$.sourceId,...$.provider?{provider:$.provider}:{}}}]}]}]}}function F5($){return $2($.sessionName,PQ($))}function M5($){return $2($.sessionName,t9($))}function o9($){return $2($.sessionName,s9($),"green")}function $2($,Z,J="turquoise"){return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83E\uDD16 model · ${$}`},template:J},body:{elements:[Z]}}}function PQ($){let Z=aA($.models,$.panelId,$.mode,$.editable);return{tag:"collapsible_panel",element_id:R.modelPanel,header:{title:{tag:"plain_text",content:$.mode==="add"?"显示模型":"选择模型"}},expanded:!0,elements:[{tag:"markdown",content:[`当前: ${jQ($.currentModel,$.currentEffort)}`,$.mode==="add"?"显示账号接口中的模型。":"接口模型可隐藏,补录模型可删除。有多个 effort 档位时再选择档位。"].join(`
|
|
117
|
+
`)},...$.models.length?Z:[{tag:"markdown",content:$.editable?$.mode==="add"?"_没有待显示的接口模型_":"_列表为空,可显示接口模型或补录_":"_未返回可用模型列表_"}],...$.pagination?dA($.panelId,$.pagination):[],...$.editable&&$.allowCustom?[{tag:"button",text:{tag:"plain_text",content:"补录模型"},type:"default",behaviors:[{type:"callback",value:{kind:"model_custom_prompt",panel_id:$.panelId,source_id:$.sourceId}}]}]:[],{tag:"button",text:{tag:"plain_text",content:$.editable?$.mode==="add"?"返回模型列表":"显示模型":"补录模型"},type:"default",width:"default",behaviors:[{type:"callback",value:{kind:$.editable?"model_list_open":"model_custom_prompt",panel_id:$.panelId,...$.sourceId||$.models[0]?.sourceId?{source_id:$.sourceId??$.models[0]?.sourceId}:{},...$.editable?{mode:$.mode==="add"?"select":"add"}:{}}}]}]}}function dA($,Z){let{sourceId:J,page:Y,totalPages:Q}=Z,H=(W,X)=>({tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:W},type:"default",behaviors:[{type:"callback",value:{kind:"model_page",panel_id:$,source_id:J,page:X}}]}]});return[{tag:"markdown",content:`第 ${Y+1} / ${Q} 页`},{tag:"column_set",columns:[...Y>0?[H("上一页",Y-1)]:[],...Y+1<Q?[H("下一页",Y+1)]:[]]}]}function r9($,Z="cancelled"){return $2($,{tag:"collapsible_panel",element_id:R.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:Z==="stale"?"_此补录面板已失效 — 当前等待中的补录未受影响_":"_已取消补录 — 列表未改动_"}]},"grey")}function R5($,Z,J){return $2($,{tag:"collapsible_panel",element_id:R.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:[`**直接回复模型名补录到 ${Z}**`,"补录后可选择 effort 并使用;模型是否接受该档位由实际请求确认。","_裸词命令(hi/stop/model 等)不受影响_"].join(`
|
|
118
|
+
`)},{tag:"button",text:{tag:"plain_text",content:"取消"},type:"default",width:"default",behaviors:[{type:"callback",value:{kind:"model_panel_cancel",panel_id:J}}]}]},"blue")}function Z2($,Z,J){return{tag:"collapsible_panel",element_id:R.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:$?`✅ \`${Z}\` 已加入列表${J?`
|
|
119
|
+
${J}`:""}`:`❌ \`${Z}\` 未加入 — ${J}`}]}}function t9($){return{tag:"collapsible_panel",element_id:R.modelPanel,header:{title:{tag:"plain_text",content:"选择 effort"}},expanded:!0,elements:[{tag:"markdown",content:[`模型: ${tA($.model)}`,`当前: ${jQ($.currentModel,$.currentEffort)}`].join(`
|
|
120
|
+
`)},...$.model.efforts.length?$.model.efforts.map((Z)=>oA($.model,Z,$.panelId,$.currentModel,$.currentEffort)):[{tag:"markdown",content:"_该模型未返回可用 effort_"}]]}}function s9($){return{tag:"collapsible_panel",element_id:R.modelPanel,header:{title:{tag:"plain_text",content:"选择已保存"}},expanded:!0,elements:[{tag:"markdown",content:["**已保存**",A1(FQ($.model,$.effort,$.provider)),X$($.scope)].join(`
|
|
121
|
+
`)}]}}function nA($,Z,J,Y=!1){if($.enabled===!1)return[{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`⚙️ **${X$($.displayName)}** · 未配置
|
|
122
|
+
${X$($.description??"")}`}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"启"},type:"primary",behaviors:[{type:"callback",value:{kind:"token_source_enable",source_id:$.sourceId}}]}]}]}];let Q=$.displayName&&$.displayName!==$.model?`**${X$($.displayName)}**`:`**${A1($.model)}**`,H=[$.isDefault?`${U5($.provider)} 默认`:"",$.selected?"当前模型":""].filter(Boolean),W=$.description?`
|
|
123
|
+
`+X$(sA($.description,110)):"",X=(z,G)=>({tag:"button",text:{tag:"plain_text",content:G},type:"default",behaviors:[{type:"callback",value:{kind:z,panel_id:Z,source_id:$.sourceId,model:$.model}}]});return[{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,vertical_align:"center",elements:[{tag:"markdown",content:[Q,$.displayName&&$.displayName!==$.model?A1($.model):"",H.length?H.join(" · "):""].filter(Boolean).join(`
|
|
124
|
+
`)+W}]},{tag:"column",width:"weighted",weight:1,vertical_align:"center",elements:[...J==="add"?[X("model_add","显")]:$.unavailableReason?[{tag:"markdown",content:"**MISS**"}]:[{tag:"button",text:{tag:"plain_text",content:"选"},type:$.selected?"primary":"default",behaviors:[{type:"callback",value:rA($,Z)}]}],...Y&&J!=="add"?[$.origin==="custom"?X("model_custom_remove","删"):X("model_remove","隐")]:[]]}]}]}function aA($,Z,J,Y=!1){let Q=[{title:"Codex",models:$.filter((X)=>(X.provider??"codex")==="codex")},{title:"Claude Code 后端",models:$.filter((X)=>X.provider==="claude")},{title:"DeepSeek Harness",models:$.filter((X)=>X.provider==="dsh")}].filter((X)=>X.models.length>0),H=(X)=>X.flatMap((V,z)=>[...z?[{tag:"hr"}]:[],...nA(V,Z,J,Y)]);if(Q.length<=1)return H($);let W=[];for(let X of Q)W.push({tag:"markdown",content:`**${X.title}**`}),W.push(...H(X.models));return W}function oA($,Z,J,Y,Q){let H=Y===$.model&&Q===Z.effort,W=[Z.isDefault?"默认":"",H?"当前":""].filter(Boolean).join(" · ");return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:[`**${Z.effort==="default"?"模型默认":X$(Z.effort)}**`,W,Z.description?X$(Z.description):""].filter(Boolean).join(`
|
|
125
|
+
`)}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:H?"primary":"default",behaviors:[{type:"callback",value:{kind:"model_effort_select",panel_id:J,...$.sourceId?{source_id:$.sourceId}:{},...$.provider?{provider:$.provider}:{},model:$.model,effort:Z.effort}}]}]}]}}function rA($,Z){return{kind:"model_select",panel_id:Z,...$.sourceId?{source_id:$.sourceId}:{},...$.provider&&$.provider!=="codex"?{provider:$.provider}:{},model:$.model,display_name:$.displayName,is_default:$.isDefault===!0,efforts:$.efforts.map((J)=>({effort:J.effort,description:J.description??"",is_default:J.isDefault===!0}))}}function tA($){return $.displayName&&$.displayName!==$.model?`${X$($.displayName)} (${A1($.model)})`:A1($.model)}function jQ($,Z){return A1(FQ($,Z))}function FQ($,Z,J){let Y=J&&J!=="codex"?`${U5(J)} · `:"";if($&&Z)return`${Y}${$}/${Z}`;if($)return`${Y}${$}`;if(Z)return`${Y}${Z}`;return"未选择"}function U5($){return Z$($??"codex")}function sA($,Z){return $.length<=Z?$:$.slice(0,Z-1)+"…"}function X$($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function A1($){return"`"+$.replace(/`/g,"\\`")+"`"}function D$($){let Z=[];if(Z.push($.suffix??"✅"),$.durationSec)Z.push(`⏱ ${$.durationSec}s`);if($.outputTokens!=null&&$.outputTokens>0)Z.push(`\uD83D\uDCF6 ${vA($.outputTokens)}`);return{config:{streaming_mode:!1,summary:{content:Z.join(" · ")}}}}var hA,IA,gA;var MQ=S(()=>{K0();L5();I0();hA={idle:"\uD83D\uDFE2",working:"⚙️",awaiting_permission:"\uD83D\uDD10",starting:"\uD83D\uDE80",stopped:"⚪"},IA={idle:"闲",working:"工作中",awaiting_permission:"等审批",starting:"启动中",stopped:"未运行"},gA={active:"\uD83D\uDFE2",activating:"\uD83D\uDE80",reloading:"\uD83D\uDD04",inactive:"⚪",deactivating:"\uD83D\uDFE1",failed:"❌"}});function O5($){let Z=ZK($);return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:"\uD83C\uDF3F wt"},template:eA($.notice)},body:{elements:[...$.notice?[$K($.notice)]:[],...Z?[{tag:"markdown",content:Z}]:[],...$.entries.flatMap(JK)]}}}function eA($){if($?.type==="error")return"red";if($?.type==="success")return"green";return"turquoise"}function $K($){let Z=$.type==="error"?"red":$.type==="success"?"green":"grey";return{tag:"markdown",content:$.content.split(`
|
|
123
126
|
`).map((J)=>`<font color='${Z}'>${J||" "}</font>`).join(`
|
|
124
|
-
`)}}function
|
|
127
|
+
`)}}function ZK($){let Z=$.hiddenMergedUnmountedCount??0;if(!$.entries.length&&Z===0)return`_无 work/* 分支。发 ${e9("wt name")} 创建。_`;if(Z>0)return`${Z}个已归档分支`;return""}function JK($){let Z=$.error?"出错":$.mounted&&$.dirtyCount&&$.dirtyCount>0?`有未提交改动 ${$.dirtyCount}`:$.state==="merged"?"已合并":$.state==="stale"?"两边都有新改动":$.mounted?"进行中":"未挂载",J=$.duplicateChatCount>1?`群重复 ${$.duplicateChatCount} 个`:$.chatId?"群正常":"无群",Y=[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`**${e9($.slug)}**
|
|
125
128
|
${Z} · ${J}
|
|
126
|
-
${
|
|
127
|
-
`)}]}}}function
|
|
129
|
+
${e9($.branch)}`}]}];if($.mounted||$.chatId)Y.push({tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"删"},type:"danger",behaviors:[{type:"callback",value:{kind:"worktree_disband",slug:$.slug}}]}]});return[{tag:"column_set",columns:Y}]}function K4($){return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83C\uDF3F ${$.slug}`},template:$.template??"green"},body:{elements:[{tag:"markdown",content:[$.status,e9($.branch),...$.body?[$.body]:[]].join(`
|
|
130
|
+
`)}]}}}function e9($){return"`"+$.replace(/`/g,"\\`")+"`"}function E5($){let Z=$.mode==="fork",J=Z?"分叉":"回退",Y=Z?"temp_fork_select":"temp_back_select",Q=Z?`\uD83D\uDCA1 选择一条「用户输入」,将在临时群从它**之前**创建独立对话分支;选中的输入本身不包含。
|
|
128
131
|
分支与本群共享 cwd 和磁盘文件;只分叉对话历史,不复制或回滚文件,原会话不动。`:`⚠️ 选择一条「用户输入」,将停止本群当前 turn 和后台任务,并从它**之前**创建后续对话分支;选中的输入本身不包含。
|
|
129
|
-
只回退对话历史,不会回滚 cwd 中的文件。`,H=[];if($.notice)H.push({tag:"markdown",content
|
|
130
|
-
${
|
|
131
|
-
新分支共享当前 cwd 和磁盘文件;只分叉对话历史,不复制或回滚文件。`});for(let J of $.entries)Z.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:5,elements:[{tag:"markdown",content:`**${
|
|
132
|
-
${
|
|
132
|
+
只回退对话历史,不会回滚 cwd 中的文件。`,H=[];if($.notice)H.push({tag:"markdown",content:YK($.notice)});if(!$.entries.length)H.push({tag:"markdown",content:"_当前会话还没有已完成的 turn,无法分叉/回退。_"});else{H.push({tag:"markdown",content:Q});for(let W of $.entries)H.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:5,elements:[{tag:"markdown",content:`**${k5(W.ts)}**
|
|
133
|
+
${h$(W.preview.slice(0,60)||"(空)")}`}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:J},type:Z?"primary":"danger",behaviors:[{type:"callback",value:{kind:Y,panel_id:$.panelId,choice_id:W.choiceId}}]}]}]})}return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`${Z?"\uD83D\uDD31 fk 分叉":"⏪ bk 回退"} · ${$.projectName}`},template:Z?"turquoise":"orange"},body:{elements:H}}}function N5($){let Z=[];if(!$.entries.length)Z.push({tag:"markdown",content:`_项目「${$.projectName}」没有可创建分支的历史会话。_`});else{Z.push({tag:"markdown",content:`\uD83D\uDCA1 选择一个历史会话,在**当前群**创建独立对话分支;源会话不动。
|
|
134
|
+
新分支共享当前 cwd 和磁盘文件;只分叉对话历史,不复制或回滚文件。`});for(let J of $.entries)Z.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:5,elements:[{tag:"markdown",content:`**${k5(J.ts)}**
|
|
135
|
+
${h$(J.preview.slice(0,60)||"(无摘要)")}`}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"分支"},type:"primary",behaviors:[{type:"callback",value:{kind:"temp_resume_select",panel_id:$.panelId,choice_id:J.choiceId}}]}]}]})}return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83D\uDD01 rs 独立分支 · ${$.projectName}`},template:"purple"},body:{elements:Z}}}function S5($){let Z=$.entries.length===0?"(回退范围内未观察到 Write/Edit/FileChange 类文件变更)":$.entries.map((J)=>{let Y=J.body.length>800?J.body.slice(0,800)+`
|
|
133
136
|
…(截断)`:J.body;return`${J.path} (${J.tool})
|
|
134
137
|
${Y}`}).join(`
|
|
135
138
|
|
|
136
|
-
`);return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83D\uDCCB 观察到的文件变更 · ${$.projectName}`},template:"grey"},body:{elements:[{tag:"markdown",content:"以下是回退范围内观察到的文件变更,可复制、编辑后交给新分支参考。bk 只回退对话历史,不会回滚磁盘文件;Shell/MCP 等工具造成的副作用可能未被记录。"},{tag:"markdown",content:"```\n"+Z+"\n```"}]}}}function
|
|
139
|
+
`);return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83D\uDCCB 观察到的文件变更 · ${$.projectName}`},template:"grey"},body:{elements:[{tag:"markdown",content:"以下是回退范围内观察到的文件变更,可复制、编辑后交给新分支参考。bk 只回退对话历史,不会回滚磁盘文件;Shell/MCP 等工具造成的副作用可能未被记录。"},{tag:"markdown",content:"```\n"+Z+"\n```"}]}}}function I$($){return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:$.title},template:$.ok?"green":"red"},body:{elements:[{tag:"markdown",content:`${$.ok?"✅":"❌"} ${T5($.message)}`}]}}}function x5($){let Z=$.provider==="codex"?"Codex":"Claude",J=$.bindingState==="changed"?"已接入":$.bindingState==="prepared"?"已准备":$.bindingState==="unchanged"?"未切换":"状态待确认",Y=$.bindingState==="changed"?"✅":$.bindingState==="prepared"?"⏳":$.bindingState==="unchanged"?"❌":"⚠️",Q=$.selectedPreview.slice(0,80)||"(无摘要)",H=$.sourceStatus?` · 状态 ${h$($.sourceStatus)}`:"",W=$.bindingState==="changed"?["**当前群**",`新会话 ${h$($6($.newSessionId))}`,"","源会话未修改;新分支与当前群共享 cwd 和磁盘文件。"].join(`
|
|
137
140
|
`):$.bindingState==="prepared"?["**当前群**","Claude 独立分支已准备;发送下一条消息时生成并接入新会话。","","源会话未修改;新分支与当前群共享 cwd 和磁盘文件。"].join(`
|
|
138
|
-
`):$.bindingState==="unchanged"?[`${
|
|
139
|
-
`):[`${
|
|
140
|
-
`);return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83D\uDD01 rs ${J} · ${$.projectName}`},template:$.bindingState==="changed"?"green":$.bindingState==="prepared"?"purple":$.bindingState==="unchanged"?"red":"orange"},body:{elements:[{tag:"markdown",content:`${Y} ${$.bindingState==="changed"?"已从所选历史创建独立分支":$.bindingState==="prepared"?"已准备从所选历史创建独立分支":$.bindingState==="unchanged"?"历史分支创建失败":"分支结果需要确认"}`},{tag:"markdown",content:[`**所选历史 · ${Z}**`,`**${
|
|
141
|
-
`)},{tag:"markdown",content:W}]}}}function
|
|
141
|
+
`):$.bindingState==="unchanged"?[`${T5($.message)}`,"",`本群原绑定 ${h$($6($.previousSessionId))};源会话未修改。`].join(`
|
|
142
|
+
`):[`${T5($.message)}`,"",`后端返回会话 ${h$($6($.newSessionId))};当前绑定无法确认。`,"请发送 hi 或 rs 检查当前状态,不要把本卡视为成功回执。"].join(`
|
|
143
|
+
`);return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83D\uDD01 rs ${J} · ${$.projectName}`},template:$.bindingState==="changed"?"green":$.bindingState==="prepared"?"purple":$.bindingState==="unchanged"?"red":"orange"},body:{elements:[{tag:"markdown",content:`${Y} ${$.bindingState==="changed"?"已从所选历史创建独立分支":$.bindingState==="prepared"?"已准备从所选历史创建独立分支":$.bindingState==="unchanged"?"历史分支创建失败":"分支结果需要确认"}`},{tag:"markdown",content:[`**所选历史 · ${Z}**`,`**${k5($.selectedTs)}**${H}`,h$(Q),`源会话 ${h$($6($.sourceSessionId))}`].join(`
|
|
144
|
+
`)},{tag:"markdown",content:W}]}}}function k5($){let Z=new Date($),J=(Y)=>String(Y).padStart(2,"0");return`${J(Z.getMonth()+1)}-${J(Z.getDate())} ${J(Z.getHours())}:${J(Z.getMinutes())}`}function h$($){return"`"+RQ($.replace(/`/g,"\\`").replace(/\n/g," "))+"`"}function $6($){let Z=$?.trim()??"";if(!Z)return"MISS";return Z.length>13?`${Z.slice(0,8)}…${Z.slice(-4)}`:Z}function T5($){return RQ($).replace(/\\/g,"\\\\").replace(/([`*_{}\[\]()#+\-.!|>~])/g,"\\$1")}function RQ($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function YK($){let Z=$.type==="error"?"red":"grey";return $.content.split(`
|
|
142
145
|
`).map((J)=>`<font color='${Z}'>${J||" "}</font>`).join(`
|
|
143
|
-
`)}function
|
|
146
|
+
`)}function UQ($){if(!$||typeof $!=="object")return"";if(typeof $.content==="string")return $.content;if(typeof $.new_string==="string")return $.new_string;if(typeof $.new_source==="string")return $.new_source;if(Array.isArray($.edits))return $.edits.map((Z)=>typeof Z?.new_string==="string"?Z.new_string:"").filter(Boolean).join(`
|
|
144
147
|
---
|
|
145
|
-
`);return""}function
|
|
146
|
-
`);if(Z.push("","已启用"),Z.push(`GUID:${
|
|
147
|
-
`)}function
|
|
148
|
-
`).map((J)=>`<font color='${Z}'>${
|
|
149
|
-
`)}}function
|
|
150
|
-
`)}];if($.failures.length)Z.push({tag:"collapsible_panel",header:{title:{tag:"plain_text",content:`MISS · ${$.failures.length} 个账号`}},expanded:!1,elements:[{tag:"markdown",content:$.failures.map((J)=>`- **${
|
|
151
|
-
`)}]});return Z.push(...$.catalog.map(
|
|
152
|
-
`)}]}}function
|
|
153
|
-
`)}}function
|
|
154
|
-
${
|
|
155
|
-
`)}}function
|
|
156
|
-
|
|
157
|
-
${J}`}function
|
|
158
|
-
|
|
159
|
-
${J}`}function
|
|
160
|
-
`)}function
|
|
161
|
-
`))>=0){let J=this.buf.slice(0,Z).trim();if(this.buf=this.buf.slice(Z+1),!J)continue;let Y;try{Y=JSON.parse(J)}catch{continue}if(!Object.prototype.hasOwnProperty.call(Y,"id"))continue;let Q=this.pending.get(Y.id);if(!Q)continue;if(this.pending.delete(Y.id),clearTimeout(Q.timer),Y.error)Q.reject(Error(JSON.stringify(Y.error)));else Q.resolve(Y.result)}}request($,Z,J=
|
|
162
|
-
`,(X)=>{if(!X)return;let V=this.pending.get(Y);if(!V)return;this.pending.delete(Y),clearTimeout(V.timer),V.reject(Error(`codex app-server write failed for ${$}: ${X.message}`))})}catch(X){this.pending.delete(Y),clearTimeout(W),H(X instanceof Error?X:Error(String(X)))}})}async close($=2000){if(!this.alive)return;if(!this.proc.kill("SIGTERM"))throw Error("codex app-server rejected SIGTERM");if(await Promise.race([this.exitPromise.then(()=>!0),new Promise((Y)=>setTimeout(()=>Y(!1),$))]))return;if(!this.proc.kill("SIGKILL"))throw Error("codex app-server rejected SIGKILL");if(!await Promise.race([this.exitPromise.then(()=>!0),new Promise((Y)=>setTimeout(()=>Y(!1),$))]))throw Error(`codex app-server did not exit after SIGKILL (${$}ms)`)}}function
|
|
148
|
+
`);return""}function C5($,Z){if(!Z||typeof Z!=="object")return[];if($==="FileChange"||$==="fileChange"){if(!Array.isArray(Z.changes))return[];return Z.changes.filter((Y)=>Y&&typeof Y==="object").map((Y)=>({tool:$,path:typeof Y.path==="string"&&Y.path?Y.path:"?",body:typeof Y.diff==="string"?Y.diff:typeof Y.unified_diff==="string"?Y.unified_diff:""}))}if(!["Write","Edit","NotebookEdit","MultiEdit"].includes($))return[];let J=Z.file_path??Z.path??Z.notebook_path;return[{tool:$,path:typeof J==="string"&&J?J:"?",body:UQ(Z)}]}function y5($){let Z=!!$.binding,J=$.notice?.type==="error"?"red":$.confirmDelete?"red":Z?"green":"blue";return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:"task"},template:J},body:{elements:[...$.notice?[WK($.notice)]:[],{tag:"markdown",element_id:R.tasklistPanel,content:QK($)},HK($)]}}}function QK($){let Z=[`项目:${b5($.projectName)}`,`清单:${b5($.tasklistName)}`];if(!$.binding)return Z.push("","未启用"),Z.join(`
|
|
149
|
+
`);if(Z.push("","已启用"),Z.push(`GUID:${b5($.binding.guid)}`),$.binding.url)Z.push(`链接:${$.binding.url}`);if($.confirmDelete)Z.push(""),Z.push("<font color='red'>确认后会删除该清单以及清单内所有任务。</font>");return Z.join(`
|
|
150
|
+
`)}function HK($){if(!$.binding)return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"启用"},type:"primary",behaviors:[{type:"callback",value:{kind:"tasklist_enable"}}]}]}]};if($.confirmDelete)return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:"<font color='red'>会删除所有清单内任务</font>"}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"确认"},type:"danger",behaviors:[{type:"callback",value:{kind:"tasklist_delete_confirm",guid:$.binding.guid}}]}]}]};return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"删"},type:"danger",behaviors:[{type:"callback",value:{kind:"tasklist_delete_prompt",guid:$.binding.guid}}]}]}]}}function WK($){let Z=$.type==="error"?"red":$.type==="success"?"green":"grey";return{tag:"markdown",content:$.content.split(`
|
|
151
|
+
`).map((J)=>`<font color='${Z}'>${XK(J)||" "}</font>`).join(`
|
|
152
|
+
`)}}function b5($){return"`"+$.replace(/`/g,"\\`")+"`"}function XK($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}var OQ=S(()=>{I0()});import{createHash as VK}from"node:crypto";function v5($){let Z=[{tag:"markdown",element_id:R.agentIdentityPanel,content:["**全局 Agent 身份**","选择一个或多个 Agent 执行任务,由主 Agent 统一分配和汇总结果。",`目录第 ${$.page+1}/${$.totalPages} 页`].join(`
|
|
153
|
+
`)}];if($.failures.length)Z.push({tag:"collapsible_panel",header:{title:{tag:"plain_text",content:`MISS · ${$.failures.length} 个账号`}},expanded:!1,elements:[{tag:"markdown",content:$.failures.map((J)=>`- **${g$(J.display)}**:${g$(J.reason)}`).join(`
|
|
154
|
+
`)}]});return Z.push(...$.catalog.map(_K),AK($)),{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:"\uD83E\uDDE0 可用 Agent"},template:"purple"},body:{elements:Z}}}function h5($){let Z=Y6($.workers.length);return{schema:"2.0",config:{update_multi:!0,streaming_mode:!NQ($.status),summary:{content:L4($)}},header:{title:{tag:"plain_text",content:`\uD83E\uDDE0 ${$.parentKind==="follow_up"?"继续委派任务":"委派任务"} · ${$.workers.length} 位 Agent`},template:"purple"},body:{elements:[B4($),{tag:"collapsible_panel",header:{title:{tag:"plain_text",content:`任务说明 · ${f5($.prompt,56)}`}},expanded:!1,elements:[{tag:"markdown",content:BK($.prompt)}]},...$.workers.map((J)=>Z6(J,Z,$.workers.length===1))]}}}function Z6($,Z=EQ,J=!1){let Y=KK($),Q=[`模型 ${K1($.model)} · 推理 ${K1($.effort)}`];if($.durationMs!=null)Q.push(`用时 ${xQ($.durationMs)}`);if($.status==="queued"&&$.queuedReason)Q.push("",g$($.queuedReason));if($.pendingInput){Q.push("","**等待主 Agent 回答**");for(let H of $.pendingInput.questions)if(Q.push(`- ${g$(H.question)}`),H.options.length)Q.push(` 选项:${H.options.map((W)=>K1(W.label)).join(" / ")}`)}if($.error)Q.push("",$.status==="cancelled"?"**停止原因**":"**失败原因**",r($.error));if($.output)Q.push("",$.status==="failed"||$.status==="cancelled"?"**已生成的内容**":"**结果**",LK(r($.output),Z));if(!$.output&&!$.error&&!$.pendingInput)Q.push("",$.status==="completed"?"_任务已完成,没有正文输出。_":$.status==="cancelled"?"_任务已取消。_":$.status==="queued"?"_等待开始执行。_":"_正在执行任务,结果会显示在这里。_");if($.steps.length){Q.push("","**最近动作**");for(let H of $.steps.slice(-3)){let W=H.tool==="tool error"?"❌":H.phase==="completed"?"✓":H.phase==="started"?"→":"·",X=H.tool==="tool error"?"工具执行失败":H.tool==="tool result"?"工具执行完成":H.tool;Q.push(`- ${W} ${K1(X)} ${g$(f5(H.detail,180))}`)}}return{tag:"collapsible_panel",element_id:J6($.identityId),header:{title:{tag:"plain_text",content:`${Y} · ${f5($.identityName,48)}`}},expanded:$.status==="failed"||$.status==="needs_input"||J&&$.status==="completed"&&!!$.output,elements:[{tag:"markdown",content:Q.join(`
|
|
155
|
+
`)}]}}function B4($){let Z=$.workers.filter((G)=>G.status==="completed").length,J=$.workers.filter((G)=>G.status==="failed").length,Y=$.workers.filter((G)=>G.status==="needs_input").length,Q=$.workers.filter((G)=>G.status==="running").length,H=$.workers.filter((G)=>G.status==="queued").length,W=$.workers.filter((G)=>G.status==="cancelled").length,X=[Q?`执行中 ${Q}`:"",H?`排队 ${H}`:"",Y?`待答 ${Y}`:"",J?`失败 ${J}`:"",W?`已取消 ${W}`:""].filter(Boolean),V=$.finishedAt?Date.parse($.finishedAt)-Date.parse($.createdAt):null,z=[`**${SQ($)}** · 完成 ${Z}/${$.workers.length}`,...X.length?[X.join(" · ")]:[],...V!=null&&Number.isFinite(V)?[`⏱ 用时 ${xQ(V)}`]:[],...$.error?[g$($.error)]:[]];return{tag:"markdown",element_id:R.agentRunFooter,content:z.join(`
|
|
156
|
+
`)}}function J6($){return`aw_${VK("sha256").update($).digest("hex").slice(0,16)}`}function Y6($){let Z=Math.max(1,Math.floor($));return Math.min(EQ,Math.max(GK,Math.floor(zK/Z)))}function L4($){let Z=$.workers.filter((J)=>J.status==="completed").length;return`${SQ($)} · ${Z}/${$.workers.length}`}function _K($){let J=$.status==="ready"?"可用":`不可用:${$.reason??"MISS"}`;return{tag:"markdown",content:[`**${g$($.displayName)}** ${$.sourceDefault?"· 默认":""}`,`${K1($.id)}
|
|
157
|
+
${K1($.model)} · 默认 ${K1($.defaultEffort??"MISS")} · ${g$(J)}`].join(`
|
|
158
|
+
`)}}function AK($){return{tag:"column_set",columns:[w5("上一页",{kind:"agent_identity_page",panel_id:$.panelId,page:Math.max(0,$.page-1)}),w5("刷新",{kind:"agent_identity_page",panel_id:$.panelId,page:$.page}),w5("下一页",{kind:"agent_identity_page",panel_id:$.panelId,page:Math.min($.totalPages-1,$.page+1)})]}}function w5($,Z){return{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:$},type:"default",behaviors:[{type:"callback",value:Z}]}]}}function KK($){switch($.status){case"completed":return"✅ 完成";case"failed":return"❌ 失败";case"cancelled":return"\uD83D\uDED1 取消";case"needs_input":return"❓ 等待输入";case"running":return"⏳ 运行中";default:return"⏳ 排队中"}}function NQ($){return $==="completed"||$==="failed"||$==="cancelled"}function SQ($){switch($.status){case"completed":return"✅ 委派完成";case"failed":return"❌ 委派失败";case"cancelled":return"\uD83D\uDED1 委派已取消";case"needs_input":return"❓ 等待主 Agent 回复";case"queued":return"⏳ 等待执行";case"running":return $.workers.length>0&&$.workers.every((Z)=>NQ(Z.status))?"⏳ 正在收尾":"⏳ 正在执行"}}function xQ($){if(!Number.isFinite($)||$<0)return"—";let Z=Math.floor($/1000);if(Z<60)return`${Z} 秒`;let J=Math.floor(Z/60);if(J<60)return`${J} 分 ${Z%60} 秒`;return`${Math.floor(J/60)} 小时 ${J%60} 分`}function BK($){let Z=r($);if(Z.length<=TQ)return Z;let J="_这里仅显示任务预览,Agent 使用的是完整任务内容。_";return`${Z.slice(0,TQ-J.length-2)}
|
|
159
|
+
|
|
160
|
+
${J}`}function LK($,Z){if($.length<=Z)return $;let J="_这里仅显示结果预览,完整内容已保存。_";return`${$.slice(0,Math.max(0,Z-J.length-2))}
|
|
161
|
+
|
|
162
|
+
${J}`}function K1($){return"`"+$.replace(/`/g,"\\`")+"`"}function g$($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function f5($,Z){let J=$.replace(/\s+/g," ").trim();return J.length<=Z?J:`${J.slice(0,Z-1)}…`}var TQ=1e4,zK=48000,EQ=8000,GK=512;var kQ=S(()=>{I0()});function L1($){return qK.has($)?$:null}function Q6($){if(!$)return null;try{let Z=JSON.parse($);return Z&&typeof Z==="object"?Z:null}catch{return null}}function J2($){return String($?.taskId??$?.id??$?.task_id??"").trim()}function B1($){return String($?.subject??$?.content??"").trim()}function I5($){let Z=$?.status;return Z==="pending"||Z==="in_progress"||Z==="completed"||Z==="deleted"?Z:void 0}function yQ($){return`subj:${$}`}function CQ($){let Z=$.match(/#\s*(\d+)/);return Z?Z[1]:""}function FK($){let Z=B1($);if(!Z)return null;return{id:J2($)||yQ(Z),subject:Z,description:typeof $?.description==="string"?$.description:void 0,activeForm:typeof $?.activeForm==="string"?$.activeForm:void 0,status:I5($)??"pending"}}function g5($,Z,J,Y){if(Z==="TaskList"){let Q=Q6(Y),H=Array.isArray(Q?.tasks)?Q.tasks:Array.isArray(Q)?Q:null;if(H===null)return $;let W=[];for(let X of H){let V=FK(X);if(V)W.push(V)}return W}if(Z==="TaskCreate"){let Q=Array.isArray(J?.tasks)?J.tasks:null;if(Q){let z=Q6(Y),G=Array.isArray(z?.tasks)?z.tasks:Array.isArray(z)?z:null,A=$;return Q.forEach((K,L)=>{let D=B1(K);if(!D)return;let q=G?.[L],P=q&&J2(q)||CQ(Y??"");A=bQ(A,P,D,K)}),A}let H=Q6(Y),W=H?.task??H,X=J2(W)||CQ(Y??""),V=B1(W)||B1(J);if(!V)return $;return bQ($,X,V,J)}if(Z==="TaskUpdate"){let Q=J2(J);if(!Q)return $;let H=I5(J);if(H==="deleted")return $.filter((X)=>X.id!==Q);let W=B1(J);if($.some((X)=>X.id===Q))return $.map((X)=>X.id===Q?{...X,...H?{status:H}:{},...W?{subject:W}:{},...typeof J?.activeForm==="string"?{activeForm:J.activeForm}:{}}:X);return $}if(Z==="TaskGet"){let Q=Q6(Y),H=Q?.task??Q,W=J2(H)||J2(J);if(!W)return $;let X=$.find((G)=>G.id===W),V=B1(H)||X?.subject||B1(J);if(!V)return $;let z={id:W,subject:V,description:typeof H?.description==="string"?H.description:X?.description,activeForm:typeof H?.activeForm==="string"?H.activeForm:X?.activeForm,status:I5(H)??X?.status??"pending"};return X?$.map((G)=>G.id===W?z:G):[...$,z]}return $}function bQ($,Z,J,Y){let Q=Z||yQ(J),H={...typeof Y?.activeForm==="string"&&Y.activeForm?{activeForm:Y.activeForm}:{},...typeof Y?.description==="string"&&Y.description?{description:Y.description}:{}};if($.some((W)=>W.id===Q))return $.map((W)=>W.id===Q?{...W,id:Q,subject:J,...H}:W);return[...$,{id:Q,subject:J,status:"pending",...H}]}function c5($){let Z=$.filter((H)=>H.status!=="deleted");if(Z.length===0)return"空";let J=new Map;for(let H of Z){let W=PK[H.status];J.set(W,(J.get(W)??0)+1)}let Q=["进行中","待办","完成"].map((H)=>J.has(H)?`${H} ${J.get(H)}`:"").filter(Boolean).join(" · ");return`${Z.length} 项${Q?` · ${Q}`:""}`}function wQ($,Z){let J=$.filter((W)=>W.status!=="deleted"),Y=[`**待办**: ${J.length} 项`],Q=(W)=>{let X=parseInt(W,10);return Number.isNaN(X)?Number.MAX_SAFE_INTEGER:X},H=[...J].sort((W,X)=>{let V=Q(W.id)-Q(X.id);return V!==0?V:W.id.localeCompare(X.id)});for(let W of H.slice(0,12)){let X=jK[W.status],V=W.status==="in_progress"&&W.activeForm?W.activeForm:W.subject;Y.push(`- ${X} ${V||"(空)"}`)}if(H.length>12)Y.push(`- 还有 ${H.length-12} 项未显示`);if(Z)Y.push(""),Y.push(Z);return Y.join(`
|
|
163
|
+
`)}function c$($,Z,J,Y){let Q=DK[J.name],H=c5(Z),W=`${J.status} \uD83D\uDD27 ${Q}: ${H}`;return{tag:"collapsible_panel",element_id:R.tool($),header:{title:{tag:"plain_text",content:W}},expanded:!1,elements:[{tag:"markdown",content:wQ(Z,Y)}]}}function q1($){return{tag:"collapsible_panel",element_id:R.taskBoardLive,header:{title:{tag:"plain_text",content:`\uD83D\uDCCB 任务总览 · ${c5($)}`}},expanded:!0,elements:[{tag:"markdown",content:wQ($)}]}}var qK,DK,PK,jK;var fQ=S(()=>{I0();qK=new Set(["TaskCreate","TaskUpdate","TaskList","TaskGet"]);DK={TaskCreate:"创建任务",TaskUpdate:"更新任务",TaskList:"任务列表",TaskGet:"查看任务"},PK={pending:"待办",in_progress:"进行中",completed:"完成",deleted:"已删"},jK={pending:"⬜",in_progress:"\uD83D\uDD04",completed:"✅",deleted:"\uD83D\uDDD1️"}});var p0=S(()=>{I0();hY();VQ();MQ();OQ();kQ();fQ();r7()});import{spawn as MK}from"cross-spawn";class X6{proc;buf="";nextId=1;alive=!0;exitPromise;resolveExit;pending=new Map;constructor(){this.proc=MK(y2(),["app-server","--listen","stdio://"],{stdio:["pipe","pipe","pipe"],shell:!1}),this.exitPromise=new Promise((Z)=>{this.resolveExit=Z}),this.proc.stdout.on("data",(Z)=>this.onStdout(Z)),this.proc.stderr.on("data",(Z)=>{let J=Z.toString().trim();if(J)_(`usage[codex stderr]: ${J}`)});let $=(Z)=>{if(!this.alive)return;this.alive=!1;for(let[J,Y]of this.pending)clearTimeout(Y.timer),Y.reject(Error(`${Z.message}; pending ${Y.method} id=${J}`));this.pending.clear(),this.resolveExit()};this.proc.on("error",(Z)=>$(Error(`codex app-server spawn failed: ${Z.message}`))),this.proc.on("exit",(Z,J)=>{$(Error(`codex app-server exited code=${Z} signal=${J}`))})}onStdout($){this.buf+=$.toString();let Z;while((Z=this.buf.indexOf(`
|
|
164
|
+
`))>=0){let J=this.buf.slice(0,Z).trim();if(this.buf=this.buf.slice(Z+1),!J)continue;let Y;try{Y=JSON.parse(J)}catch{continue}if(!Object.prototype.hasOwnProperty.call(Y,"id"))continue;let Q=this.pending.get(Y.id);if(!Q)continue;if(this.pending.delete(Y.id),clearTimeout(Q.timer),Y.error)Q.reject(Error(JSON.stringify(Y.error)));else Q.resolve(Y.result)}}request($,Z,J=H6){let Y=this.nextId++;return new Promise((Q,H)=>{if(!this.alive){H(Error(`codex app-server is not alive; cannot request ${$}`));return}let W=setTimeout(()=>{if(!this.pending.delete(Y))return;H(Error(`codex app-server ${$} timed out after ${J}ms`))},J);this.pending.set(Y,{resolve:Q,reject:H,method:$,timer:W});try{this.proc.stdin.write(JSON.stringify({id:Y,method:$,params:Z})+`
|
|
165
|
+
`,(X)=>{if(!X)return;let V=this.pending.get(Y);if(!V)return;this.pending.delete(Y),clearTimeout(V.timer),V.reject(Error(`codex app-server write failed for ${$}: ${X.message}`))})}catch(X){this.pending.delete(Y),clearTimeout(W),H(X instanceof Error?X:Error(String(X)))}})}async close($=2000){if(!this.alive)return;if(!this.proc.kill("SIGTERM"))throw Error("codex app-server rejected SIGTERM");if(await Promise.race([this.exitPromise.then(()=>!0),new Promise((Y)=>setTimeout(()=>Y(!1),$))]))return;if(!this.proc.kill("SIGKILL"))throw Error("codex app-server rejected SIGKILL");if(!await Promise.race([this.exitPromise.then(()=>!0),new Promise((Y)=>setTimeout(()=>Y(!1),$))]))throw Error(`codex app-server did not exit after SIGKILL (${$}ms)`)}}function u5($,Z){return new Promise((J,Y)=>{let Q=setTimeout(()=>Y(Error(`timeout after ${Z}ms`)),Z);$.then((H)=>{clearTimeout(Q),J(H)},(H)=>{clearTimeout(Q),Y(H)})})}function RK($){return typeof $==="number"&&isFinite($)?Math.max(0,Math.min(100,$)):null}function W6($){if(!$)return null;return{percent:RK($.usedPercent),resetsAt:typeof $.resetsAt==="number"?new Date($.resetsAt*1000):null,durationMins:typeof $.windowDurationMins==="number"?$.windowDurationMins:null}}function UK($){let Z=W6($?.primary),J=W6($?.secondary),Y=(H)=>H?.durationMins!=null&&H.durationMins>0&&H.durationMins<=720,Q=(H)=>H?.durationMins!=null&&H.durationMins>720;if(Y(Z)&&Q(J))return{fiveHour:Z,weekly:J};if(Y(J)&&Q(Z))return{fiveHour:J,weekly:Z};if(Q(Z)&&!J)return{fiveHour:null,weekly:Z};if(Q(J)&&!Z)return{fiveHour:null,weekly:J};return{fiveHour:Z,weekly:J}}function OK($){let Z=$?.rateLimitsByLimitId,J=Z&&typeof Z==="object"?Object.entries(Z):$?.rateLimits?[[$.rateLimits.limitId??"codex",$.rateLimits]]:[],Y=[];for(let[Q,H]of J){let{fiveHour:W,weekly:X}=UK(H);if(!W&&!X)continue;Y.push({limitId:Q,limitName:H?.limitName??null,fiveHour:W,weekly:X})}return{buckets:Y,defaultLimitId:$?.rateLimits?.limitId??void 0}}function TK($){if(!$)return"empty";let Z=(J)=>J?`${J.usedPercent??"?"}%/${J.windowDurationMins??"?"}m`:"null";return`limitId=${$.limitId??"null"} name=${$.limitName??"null"} primary=${Z($.primary)} secondary=${Z($.secondary)}`}function hQ($){let Z=TK($),J=D1?.state==="ok"?D1.buckets??[]:[],Y=J.filter((Q)=>vQ(Q.fiveHour,W6($?.primary))&&vQ(Q.weekly,W6($?.secondary)));if(J.length>0&&Y.length===0)_(`usage: rate-limit notification matches NO known bucket — possible relabel or new bucket, will resolve on next read. (${Z})`);else if($?.limitId&&Y.length===1&&Y[0].limitId!==$.limitId)_(`usage: rate-limit notification labeled limitId=${$.limitId} but content matches bucket ${Y[0].limitId} (known codex parser fallback relabels; ignoring notification payload)`)}function vQ($,Z){if(!$||!Z)return!$&&!Z;return $.percent===Z.percent&&$.durationMins===Z.durationMins&&$.resetsAt?.getTime()===Z.resetsAt?.getTime()}async function EK(){let $=new X6;try{await u5($.request("initialize",{clientInfo:{name:"lodestar-usage",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}),H6);let J=(await u5($.request("account/read",{}),H6))?.account;if(!J)return{state:"no_credentials"};if(J.type!=="chatgpt")return{state:"auth_failed"};let Y=await mQ(()=>$.request("account/rateLimits/read",{}));return IQ(Y,J.planType)}catch(Z){return _(`usage: codex app-server usage failed: ${Z?.message??Z}`),{state:"network",reason:Z?.message??String(Z)}}finally{await $.close()}}function IQ($,Z){let{buckets:J,defaultLimitId:Y}=OK($),Q=J.find((H)=>H.limitId===Y)??J[0];if(!Q)return{state:"network",reason:"empty rate limit response"};return{state:"ok",subscriptionType:Z??Q.limitName??$?.rateLimits?.planType??"chatgpt",fiveHour:Q.fiveHour,weekly:Q.weekly,buckets:J,defaultLimitId:Q.limitId,resetCredits:Number.isInteger($?.rateLimitResetCredits?.availableCount)&&$.rateLimitResetCredits.availableCount>=0?$.rateLimitResetCredits.availableCount:null,fetchedAt:Date.now()}}function gQ(){return D1}async function V6(){if(Y2)return Y2;return Y2=EK().then(($)=>{if(Y2=null,$.state==="network")return D1??$;return D1=$,$}).catch(($)=>{return _(`usage: fetchUsage threw: ${$}`),Y2=null,D1??{state:"network",reason:String($)}}),Y2}function cQ($){return m5??=mQ(()=>$("account/rateLimits/read",{})).then((Z)=>{let J=IQ(Z);if(J.state==="ok")D1=J;else _(`usage: refresh from connection: ${J.state==="network"?J.reason:J.state}`);return J}).catch((Z)=>{return _(`usage: refresh from connection failed: ${Z?.message??Z}`),null}).finally(()=>{m5=null}),m5}async function mQ($){let Z=[250,750];for(let J=0;;J++)try{return await u5($(),H6)}catch(Y){let Q=Y instanceof Error?Y.message:String(Y);if(!/error sending request|timed? ?out|timeout|ECONNRESET|ETIMEDOUT|EAI_AGAIN|connection (?:reset|closed)|\b(?:429|502|503|504)\b/i.test(Q)||J>=Z.length)throw Y;_(`usage: rate limit request retry ${J+1}/${Z.length}: ${Q}`),await new Promise((W)=>setTimeout(W,Z[J]))}}var H6=1e4,D1=null,Y2=null,m5=null;var z6=S(()=>{Z1();g()});import{readFileSync as NK}from"node:fs";import{homedir as SK}from"node:os";import{join as iQ}from"node:path";function xK(){return process.env.CLAUDE_CONFIG_DIR||iQ(SK(),".claude")}function l5(){try{let $=NK(iQ(xK(),"settings.json"),"utf8"),Z=JSON.parse($)?.env;return Z&&typeof Z==="object"?Z:{}}catch($){return _(`glm-usage: read settings.json env failed: ${$}`),{}}}function P1($){try{let Z=new URL($).hostname.toLowerCase();return Z==="open.bigmodel.cn"||Z==="dev.bigmodel.cn"||Z==="api.z.ai"}catch{return!1}}function kK($){try{let Z=new URL($);return`${Z.protocol}//${Z.host}`}catch{return null}}function CK($){let Z=kK($);return Z&&P1($)?Z:null}function pQ($){return typeof $==="number"&&isFinite($)?Math.max(0,Math.min(100,$)):null}function lQ($){return typeof $==="number"&&isFinite($)&&$>0?new Date($):null}function bK($){let Z=Array.isArray($?.limits)?$.limits:[],J=Z.filter((G)=>G?.type==="TOKENS_LIMIT"),Y=J.find((G)=>G?.unit===3&&G?.number===5),Q=J.find((G)=>G?.unit===6&&G?.number===1),H=Z.find((G)=>G?.type==="TIME_LIMIT"),W=(G)=>G?{percent:pQ(G.percentage),resetsAt:lQ(G.nextResetTime)}:null,X=W(Y),V=W(Q),z=H?{percent:pQ(H.percentage),resetsAt:lQ(H.nextResetTime),...typeof H.currentValue==="number"?{used:H.currentValue}:{},...typeof H.usage==="number"?{total:H.usage}:{}}:null;return{state:"ok",level:typeof $?.level==="string"&&$.level?$.level:void 0,fiveHour:X,weekly:V,monthly:z,fetchedAt:Date.now()}}async function q4($,Z){let J=$&&Z?{ANTHROPIC_BASE_URL:$,ANTHROPIC_AUTH_TOKEN:Z}:l5(),Y=J.ANTHROPIC_AUTH_TOKEN,Q=J.ANTHROPIC_BASE_URL||"";if(!Y)return{state:"no_credentials"};let H=CK(Q);if(!H)return{state:"not_glm",baseUrl:Q||void 0};let W=`${H}/api/monitor/usage/quota/limit`,X=new AbortController,V=setTimeout(()=>X.abort(),uQ);try{let z=await fetch(W,{headers:{Authorization:Y,"Content-Type":"application/json","Accept-Language":"en-US,en"},signal:X.signal});if(z.status===429)return{state:"rate_limited"};if(!z.ok)return{state:"network",reason:`HTTP ${z.status}`};let G=await z.json();if(G?.success===!1||typeof G?.code==="number"&&G.code!==200)return{state:"network",reason:G?.msg?String(G.msg):`code ${G?.code}`};let A=G?.data??G;return bK(A)}catch(z){let G=z?.name==="AbortError"?`timeout ${uQ}ms`:z?.message??String(z);return _(`glm-usage: quota/limit fetch failed: ${G}`),{state:"network",reason:G}}finally{clearTimeout(V)}}async function dQ(){if(Q2)return Q2;return Q2=q4().then(($)=>{if(Q2=null,$.state==="network")return p5??$;return p5=$,$}).catch(($)=>{return _(`glm-usage: fetchGlmUsage threw: ${$}`),Q2=null,p5??{state:"network",reason:String($)}}),Q2}var uQ=1e4,p5=null,Q2=null;var D4=S(()=>{g()});function nQ($){let Z=[];for(let J of $.matchAll(yK)){let Y=J[1]?.trim();if(Y)Z.push(Y)}return Z}function G6($,Z=process.platform){if(Z!=="win32")return $;let J=wK.exec($);if(!J)return $;return`${J[1].toUpperCase()}:\\`+$.slice(J[0].length).replace(/\//g,"\\")}var yK,wK;var i5=S(()=>{yK=/\[\[send:[ \t]*([^\n]*?)[ \t]*\]\]/g;wK=/^\/([a-zA-Z])\//});function rQ($){if(aQ.test($))return{marker:"start",body:$.replace(aQ,"")};if(oQ.test($))return{marker:"end",body:$.replace(oQ,"")};return{marker:"none",body:$}}var aQ,oQ;var tQ=S(()=>{aQ=/^>{3,}[ \t]?/,oQ=/^<{3,}[ \t]?/});async function sQ($,Z,J,Y,Q){let{marker:H,body:W}=rQ(Z);if(H==="start"){if($.multiMsgBuffer!==null&&$.multiMsgBuffer.length>0)n5($,"reopen");return $.multiMsgBuffer=[],d5($,W,J,Y,Q),!0}if(H==="end"){if($.multiMsgBuffer===null){if(W.trim()||J.length)return!1;return _(`session "${$.sessionName}": end marker without active multi-msg buffer, ignoring`),!0}d5($,W,J,Y,Q);let{multiMsgBuffer:X,multiMsgReactions:V}=$;return $.multiMsgBuffer=null,$.multiMsgReactions=new Map,await vK($,X,V),!0}if($.multiMsgBuffer!==null)return d5($,Z,J,Y,Q),!0;return!1}function d5($,Z,J,Y,Q){if(Z.trim()||J.length)$.multiMsgBuffer.push({text:Z,files:J,userOpenId:Y,msgId:Q});if(Q)fK($,Q)}function fK($,Z){$.multiMsgReactions.set(Z,""),(async()=>{let J=await b0(Z,"Pin");if(!J)return;if($.multiMsgReactions.has(Z))$.multiMsgReactions.set(Z,J);else T0(Z,J)})()}async function vK($,Z,J){for(let[W,X]of J)if(X)T0(W,X);let Y=Z.filter((W)=>W.text.trim()||W.files.length);if(Y.length===0){_(`session "${$.sessionName}": multi-msg flush with empty buffer, not sent`),await E($.chatId,"⚠️ 多条消息缓冲为空,未发送(只收到标记没有正文)。");return}let Q=Y.map((W)=>{return(W.files.length?W.files.map((V)=>`[file: ${V}]`).join(" ")+`
|
|
163
166
|
`:"")+W.text}).join(`
|
|
164
167
|
|
|
165
|
-
`),H=Y[Y.length-1];A(`session "${$.sessionName}": multi-msg flush ${Y.length} segment(s) → 1 turn`),await $.onUserMessage(Q,[],H.userOpenId,H.msgId)}function l5($,Z){if($.multiMsgBuffer===null)return;let J=$.multiMsgBuffer.length;A(`session "${$.sessionName}": clear multi-msg buffer (${Z}): ${J} segment(s)`);for(let[Y,Q]of $.multiMsgReactions){if(Q)U0(Y,Q);b0(Y,"CrossMark")}$.multiMsgBuffer=null,$.multiMsgReactions=new Map}var $H=E(()=>{s();g();sQ()});import{mkdtemp as fK,rm as vK,writeFile as hK}from"node:fs/promises";import{createRequire as IK}from"node:module";import{tmpdir as gK}from"node:os";import{join as ZH}from"node:path";function nK($){let Z=HH.get($);if(Z)return Z;let{liteAdaptor:J}=D1("mathjax-full/js/adaptors/liteAdaptor.js"),{RegisterHTMLHandler:Y}=D1("mathjax-full/js/handlers/html.js"),{mathjax:Q}=D1("mathjax-full/js/mathjax.js"),{TeX:H}=D1("mathjax-full/js/input/tex.js"),{AllPackages:W}=D1("mathjax-full/js/input/tex/AllPackages.js"),{SVG:X}=D1("mathjax-full/js/output/svg.js"),V=J({fontSize:$});Y(V);let z=Q.document("",{InputJax:new H({packages:W}),OutputJax:new X({fontCache:"none"})}),G={adaptor:V,doc:z};return HH.set($,G),G}function WH($,Z){let J=Number.parseFloat($??"");if(!Number.isFinite(J)||J<=0)throw Error(`MathJax SVG missing valid ${Z}`);return J}function aK($){return $.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function oK($,Z=n5,J=!0){try{let Y=Z*cK,{adaptor:Q,doc:H}=nK(Z),W=H.convert($,{display:J,em:Z,ex:Y,containerWidth:80*Z}),X=Q.outerHTML(W);if(/data-mjx-error=|mjx-merror/.test(X)){let N0=X.match(/data-mjx-error="([^"]+)"/)?.[1]??"MathJax parse error";throw Error(N0)}let V=X.indexOf("<svg"),z=X.lastIndexOf("</svg>");if(V<0||z<0)throw Error("MathJax returned no SVG");let G=X.slice(V,z+6),_=G.match(/^<svg\b[^>]*>/)?.[0];if(!_)throw Error("MathJax returned malformed SVG root");let K=WH(_.match(/\bwidth="([\d.]+)ex"/)?.[1],"width"),q=WH(_.match(/\bheight="([\d.]+)ex"/)?.[1],"height"),D=_.match(/\bviewBox="([^"]+)"/)?.[1];if(!D)throw Error("MathJax SVG missing viewBox");let L=D.trim().split(/[\s,]+/).map(Number);if(L.length!==4||L.some((N0)=>!Number.isFinite(N0))||L[2]<=0||L[3]<=0)throw Error("MathJax SVG has invalid viewBox");let[P,N,F,j]=L,M=/<text\b/.test(G)?iK:0,C=`${P} ${N} ${F+M} ${j}`,b=K*Y,m=M*(b/F),y=Math.max(1,Math.ceil(b+m)),h=Math.max(1,Math.ceil(q*Y)),S=mK-i5*2,x=Math.min(1,S/y),c=Math.max(1,Math.round(y*x)),O=Math.max(1,Math.round(h*x));if(x<1&&O<uK)throw Error(`formula would be unreadable after width cap (${c}x${O})`);let k=c+i5*2,f=O+YH*2,E0=G.slice(_.length,-6).replace(/currentColor/g,JH).replace(/font-family="serif"/g,`font-family="${dK}"`);return{svg:[`<svg xmlns="http://www.w3.org/2000/svg" width="${k}" height="${f}" viewBox="0 0 ${k} ${f}" style="color:${JH}">`,`<rect x="0" y="0" width="${k}" height="${f}" rx="6" fill="${GH}"/>`,`<svg x="${i5}" y="${YH}" width="${c}" height="${O}" viewBox="${aK(C)}" preserveAspectRatio="xMidYMid meet">`,E0,"</svg>","</svg>"].join(""),width:k,height:f}}catch(Y){return A(`math-render: TeX→SVG failed for ${$.slice(0,80)}…: ${Y}`),null}}function rK($,Z=n5,J=!0){let Y=oK($,Z,J);if(!Y)return null;try{let{Resvg:Q}=D1("@resvg/resvg-js"),W=new Q(Y.svg,{background:GH,fitTo:{mode:"original"},shapeRendering:2,textRendering:1,font:{loadSystemFonts:!0,serifFamily:QH,sansSerifFamily:QH}}).render().asPng(),X=new DataView(W.buffer,W.byteOffset,W.byteLength),V=X.getUint32(16),z=X.getUint32(20);if(V!==Y.width||z!==Y.height)throw Error(`PNG dimensions ${V}x${z} != SVG ${Y.width}x${Y.height}`);return{png:W,width:V,height:z}}catch(Q){return A(`math-render: SVG→PNG failed for ${$.slice(0,80)}…: ${Q}`),null}}function tK($){if(/^[A-Za-zΑ-ω]$/.test($))return!0;if(/\\[A-Za-z]+|[_^=]|[{}]|[≤≥≠≈∑∫√]/.test($))return!0;return/[A-Za-zΑ-ω]\s*[+\-*/<>]\s*[A-Za-zΑ-ω0-9]/.test($)}function XH($,Z){let J=[],Y=(G,_,K)=>{let q=G[0],D=_.trim();if(!D)return;J.push({start:Z+G.index,end:Z+G.index+q.length,tex:D,raw:q,display:K})},Q,H=/(?<!\\)\$\$([\s\S]+?)(?<!\\)\$\$|\\\[([\s\S]+?)\\\]/g;while((Q=H.exec($))!==null)Y(Q,Q[1]??Q[2]??"",!0);let W=/\\\(([\s\S]+?)\\\)/g;while((Q=W.exec($))!==null)Y(Q,Q[1]??"",!1);let X=/(?<![\\$])\$(?!\$)([^$\n]+?)(?<![\\$])\$(?!\$)/g;while((Q=X.exec($))!==null){let G=(Q[1]??"").trim();if(tK(G))Y(Q,G,!1)}J.sort((G,_)=>G.start-_.start||_.end-G.end);let V=[],z=-1;for(let G of J){if(G.start<z)continue;V.push(G),z=G.end}return V}function AH($){let Z=b7($),J=[],Y=0;for(let Q of Z){if(Y<Q.start)J.push(...XH($.slice(Y,Q.start),Y));Y=Math.max(Y,Q.end)}if(Y<$.length)J.push(...XH($.slice(Y),Y));return J}function sK($){let Z=$;if(Z=Z.replace(/\\text\{([^{}]*)\}/g,"$1"),Z=Z.replace(/\\left\s*/g,"").replace(/\\right\s*/g,""),Z=Z.replace(/\\([A-Za-z]+)\b/g,(J,Y)=>{if(VH[Y])return VH[Y];if(Y==="times")return"×";if(Y==="cdot")return"·";if(Y==="div")return"÷";if(Y==="pm")return"±";if(Y==="leq"||Y==="le")return"≤";if(Y==="geq"||Y==="ge")return"≥";if(Y==="neq"||Y==="ne")return"≠";if(Y==="approx")return"≈";if(Y==="sim")return"~";if(Y==="infty")return"∞";if(Y==="partial")return"∂";if(Y==="nabla")return"∇";if(Y==="sqrt")return"√";if(Y==="to")return"→";return J}),/\\/.test(Z))return null;if(Z=Z.replace(/([_^])\{([^{}]+)\}/g,(J,Y,Q)=>Q.length===1?`${Y}${Q}`:`${Y}(${Q})`),Z=Z.replace(/√\{([^{}]+)\}/g,"√($1)"),/[{}]/.test(Z))return null;return Z}function JB($){let Z=zH.get($);if(Z!==void 0)return Z;return Z=$B++,zH.set($,Z),Z}function YB($,Z){return`${lK}\x00${JB(Z)}\x00${$}`}function QB($){let Z=2166136261;for(let J=0;J<$.length;J++)Z^=$.charCodeAt(J),Z=Math.imul(Z,16777619);return(Z>>>0).toString(36)}async function HB($,Z){let J=YB($,Z),Y=L1.get(J);if(Y)return Y;let Q=d5.get(J);if(Q)return Q;let H=(async()=>{let W=rK($,n5,!0);if(!W)return null;let X=null;try{X=await fK(ZH(gK(),"lodestar-math-"));let V=ZH(X,`formula-${QB($)}.png`);await hK(V,W.png);let z=await Z(V,{tex:$,width:W.width,height:W.height});if(!z)return A(`math-render: upload returned no image key for ${$.slice(0,80)}…`),null;let G={key:z,width:W.width,height:W.height};if(L1.has(J))L1.delete(J);L1.set(J,G);while(L1.size>ZB){let _=L1.keys().next().value;if(typeof _!=="string")break;L1.delete(_)}return G}catch(V){return A(`math-render: upload failed for ${$.slice(0,80)}…: ${V}`),null}finally{if(X)try{await vK(X,{recursive:!0,force:!0})}catch(V){A(`math-render: temp cleanup failed for ${X}: ${V}`)}}})();d5.set(J,H);try{return await H}finally{d5.delete(J)}}function WB($,Z,J){let Y=$.width<=pK;return{type:"image",tex:Z.tex,index:J,element:{tag:"img",img_key:$.key,alt:{tag:"plain_text",content:Z.tex.replace(/\s+/g," ").slice(0,80)},scale_type:Y?"crop_center":"fit_horizontal",...Y?{size:`${$.width}px ${$.height}px`}:{},preview:!1}}}async function _H($,Z={}){let J=AH($);if(!J.length)return{blocks:[{type:"markdown",text:$}],formulaCount:0,renderedImageCount:0};let Y=Z.uploader??eK,Q=await Promise.all(J.map(async(G)=>{if(!G.display){let _=sK(G.tex);if(_!==null)return{unicode:_,uploaded:null}}return{unicode:null,uploaded:await HB(G.tex,Y)}})),H=[],W="",X=0,V=0,z=()=>{if(!W)return;if(W.trim())H.push({type:"markdown",text:W});W=""};for(let G=0;G<J.length;G++){let _=J[G],K=Q[G];if(W+=$.slice(X,_.start),K.unicode!==null){W+=K.unicode,X=_.end;continue}let q=K.uploaded;if(!q){W+=_.raw,X=_.end;continue}z(),H.push(WB(q,_,V++)),X=_.end}if(W+=$.slice(X),z(),!H.length)H.push({type:"markdown",text:$});return{blocks:H,formulaCount:J.length,renderedImageCount:V}}function a5($){return AH($).length>0}var D1,cK=0.5,n5=22,JH="#1F2329",GH="#F7F8FA",i5=12,YH=8,mK=720,uK=14,pK=278,lK="v4-native-cjk-tail-pad",iK=1100,QH,dK="Noto Sans CJK SC, Noto Sans CJK JP, Microsoft YaHei, PingFang SC, Arial Unicode MS, sans-serif",HH,VH,eK=async($)=>{let{uploadImageKey:Z}=await Promise.resolve().then(() => (s(),Z0));return Z($)},zH,$B=1,L1,d5,ZB=512;var KH=E(()=>{g();D1=IK(import.meta.url),QH=process.platform==="win32"?"Microsoft YaHei":process.platform==="darwin"?"PingFang SC":"Noto Sans CJK SC",HH=new Map;VH={alpha:"α",beta:"β",gamma:"γ",delta:"δ",epsilon:"ε",zeta:"ζ",eta:"η",theta:"θ",iota:"ι",kappa:"κ",lambda:"λ",mu:"μ",nu:"ν",xi:"ξ",pi:"π",rho:"ρ",sigma:"σ",tau:"τ",phi:"φ",chi:"χ",psi:"ψ",omega:"ω",Gamma:"Γ",Delta:"Δ",Theta:"Θ",Lambda:"Λ",Pi:"Π",Sigma:"Σ",Phi:"Φ",Psi:"Ψ",Omega:"Ω"};zH=new WeakMap,L1=new Map,d5=new Map});import{readFileSync as VB}from"node:fs";function Z2($){return o5.has($)}function q4($){o5.add($)}function L4($){o5.delete($)}function J2(){try{let $={};for(let[Z,J]of w0)$[Z]=J;G0(X6,$)}catch($){throw A(`notify-callbacks: save failed (${X6}): ${$}`),$}}function DH(){let $=[],Z;try{Z=VB(X6,"utf8")}catch{return[]}try{let J=JSON.parse(Z),Y=Date.now()-LH,Q=0,H=0;for(let W of Object.values(J)){if(!W||typeof W!=="object")continue;if(typeof W.notifyId!=="string"||typeof W.callbackUrl!=="string")continue;if(typeof W.createdAt!=="number"||W.createdAt<Y){Q++;continue}if(W.replyState?.status==="sending"&&!W.resolvedAt&&!W.unknownAt)W.unknownAt=Date.now(),W.unknownBy={openId:W.replyState.openId},W.unknownReason="服务在文字回复回传期间中断,无法确认是否送达,禁止自动重试",H++;if(w0.set(W.notifyId,W),W.replyState?.status==="sending"&&W.unknownAt)$.push(W)}if(A(`notify-callbacks: loaded ${w0.size} registration(s)${Q?`, dropped ${Q} stale`:""}`),H)A(`notify-callbacks: ${H} interrupted text reply(s) marked UNKNOWN`);if(Q>0||H>0)J2()}catch(J){A(`notify-callbacks: load failed (${X6}): ${J}`)}return $}function PH($){let Z=Date.now();if(Z-qH>=zB)GB(Z),qH=Z;w0.set($.notifyId,$),J2()}function D$($){return w0.get($)}function r5($){return[...w0.values()].filter((Z)=>Z.chatId===$&&!Z.resolvedAt&&!Z.unknownAt&&(Z.replyState?.status==="waiting"||Z.replyState?.status==="sending"))}function D4($,Z){if(!$)return;return r5($).find((J)=>Z===void 0||J.replyState?.openId===Z)}function jH($,Z){return!!Z&&[...w0.values()].some((J)=>J.chatId===$&&(J.replyMessageIds?.includes(Z)||J.replyState?.response?.message_id===Z))}function Y2($,Z){let J=w0.get($);if(!J)throw Error(`notify registration not found: ${$}`);let{replyState:Y,replyMessageIds:Q}=J;if(J.replyState=Z,Z.response&&!J.replyMessageIds?.includes(Z.response.message_id))J.replyMessageIds=[...J.replyMessageIds??[],Z.response.message_id];try{J2()}catch(H){if(Y)J.replyState=Y;else delete J.replyState;if(Q)J.replyMessageIds=Q;else delete J.replyMessageIds;throw H}}function P4($,Z,J){let Y=w0.get($);if(!Y)throw Error(`notify registration not found: ${$}`);let Q={resolvedAt:Y.resolvedAt,resolvedBy:Y.resolvedBy,unknownAt:Y.unknownAt,unknownBy:Y.unknownBy,unknownReason:Y.unknownReason};Y.resolvedAt=Date.now(),Y.resolvedBy={...Z!==void 0?{buttonId:Z}:{},openId:J},delete Y.unknownAt,delete Y.unknownBy,delete Y.unknownReason;try{J2()}catch(H){if(Q.resolvedAt===void 0)delete Y.resolvedAt;else Y.resolvedAt=Q.resolvedAt;if(Q.resolvedBy===void 0)delete Y.resolvedBy;else Y.resolvedBy=Q.resolvedBy;if(Q.unknownAt===void 0)delete Y.unknownAt;else Y.unknownAt=Q.unknownAt;if(Q.unknownBy===void 0)delete Y.unknownBy;else Y.unknownBy=Q.unknownBy;if(Q.unknownReason===void 0)delete Y.unknownReason;else Y.unknownReason=Q.unknownReason;throw H}}function t5($,Z,J,Y){let Q=w0.get($);if(!Q)throw Error(`notify registration not found: ${$}`);delete Q.resolvedAt,delete Q.resolvedBy,Q.unknownAt=Date.now(),Q.unknownBy={...Z!==void 0?{buttonId:Z}:{},openId:J},Q.unknownReason=Y,J2()}function V6($,Z,J){try{return P4($,Z,J),{state:"complete"}}catch(Y){let H=`resolved tombstone persistence failed: ${Y instanceof Error?Y.message:String(Y)}`;try{t5($,Z,J,H)}catch(W){let X=W instanceof Error?W.message:String(W);H+=`; unknown tombstone persistence also failed: ${X}`;let V=w0.get($);if(V)V.unknownReason=H}return{state:"unknown",detail:H}}}function GB($=Date.now()){let Z=$-LH,J=0;for(let[Y,Q]of w0)if(typeof Q.createdAt!=="number"||Q.createdAt<Z)w0.delete(Y),J++;if(J>0)J2();return J}async function s5($,Z,J){let Y={notify_id:$.notifyId,message_id:$.messageId,chat_id:$.chatId,project:$.project,..."id"in Z?{button:{id:Z.id,text:Z.text,type:Z.type}}:{response:{type:"text",...Z}},operator:{open_id:J},timestamp:Math.floor(Date.now()/1000)},Q=new AbortController,H=setTimeout(()=>Q.abort(),BH);try{let W=await fetch($.callbackUrl,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(Y),signal:Q.signal});if(W.status>=200&&W.status<300){let V;try{let z=(await W.text()).trim();if(z.startsWith("{")){let G=JSON.parse(z),_=typeof G?.text==="string"?G.text:typeof G?.reply==="string"?G.reply:typeof G?.message==="string"?G.message:"";if(_.trim())V=_.trim().slice(0,500)}else if(z)V=z.slice(0,500)}catch{}return{ok:!0,detail:`${W.status}`,reply:V}}let X="";try{X=(await W.text()).slice(0,120)}catch{}return{ok:!1,detail:`HTTP ${W.status}${X?` ${X}`:""}`}}catch(W){if(W?.name==="AbortError")return{ok:!1,detail:`回调超时 ${BH}ms(本地服务未在窗口内 2xx)`};return{ok:!1,detail:`回调失败: ${String(W?.message??W).slice(0,160)}`}}finally{clearTimeout(H)}}function FH($){let Z=!!$.resolvedAt,J=!!$.unknownAt,Y=$.resolvedBy?.buttonId??$.unknownBy?.buttonId,Q=Y?$.buttons.find((X)=>X.id===Y):void 0,H=$.replyState?.response,W=Y!==void 0?{button:Q?{id:Q.id,text:Q.text,type:Q.type}:{id:Y}}:H?{response:{type:"text",...H}}:{};return{notify_id:$.notifyId,project:$.project,message_id:$.messageId,resolved:Z,unknown:J,...$.replyState?{reply:{status:Z&&Y===void 0?"resolved":J&&Y===void 0?"unknown":$.replyState.status,prompt_message_id:$.replyState.promptMessageId,operator:{open_id:$.replyState.openId},...$.replyState.cancelReason?{cancel_reason:$.replyState.cancelReason}:{},...$.replyState.error?{error:$.replyState.error}:{}}}:{},...Z?{...W,resolved_at:$.resolvedAt,resolved_by:$.resolvedBy?.openId??null}:{},...J?{...W,unknown_at:$.unknownAt,unknown_by:$.unknownBy?.openId??null,unknown_reason:$.unknownReason}:{}}}var LH=604800000,BH=2500,w0,qH,zB=86400000,o5,X6;var j4=E(()=>{g();J0();d0();w0=new Map,qH=Date.now(),o5=new Set;X6=LZ});function z6($){return[...$.pendingAsks.entries()].find(([,Z])=>Z.currentIdx!==void 0)}function Q2($,Z){let J=$.pendingAsks.get(Z);if(!J||J.currentIdx===void 0)return null;if(D4($.chatId))return"请先完成或取消通知回复,再回答 Agent 的提问";if(z6($)?.[0]!==Z)return"请先回答当前问题,再回答排队中的提问";return null}function e5($,Z){let J=$.pendingAsks.get(Z);if(!J)throw Error(`missing pending ask: ${Z}`);let Y=J.currentIdx===void 0?void 0:D4($.chatId)?"notification":z6($)?.[0]!==Z?"question":void 0;return{currentIdx:J.currentIdx,answered:J.answered,waitingFor:Y}}function $3($,Z){let J=$.pendingAsks.get(Z),Y=$.currentTurn;if(!J||J.currentIdx===void 0||J.announced||Q2($,Z)||!Y?.userOpenId||!Y.messageId)return;J.announced=!0;let Q=(J.announcementVersion??0)+1;J.announcementVersion=Q;let H=J.questions[J.currentIdx]?.question.trim()??"",W=H.length>40?H.slice(0,40)+"…":H,X=J.questions.length>1?`❓ 待回答 ${J.questions.length} 题${W?`: ${W}`:""}`:W?`❓ ${W}`:"❓ 等你回答问题";(async()=>{if(q0(Y.cardId),await R9(Y.cardId,{config:{summary:{content:X}}}),$.currentTurn!==Y||$.pendingAsks.get(Z)!==J||J.announcementVersion!==Q||J.currentIdx===void 0||Q2($,Z))return;await H1(Y.messageId,[Y.userOpenId])})().catch((V)=>A(`session "${$.sessionName}": question notification failed: ${V}`))}function G6($){let Z=$.currentTurn;if(!Z)return;for(let[J,Y]of $.pendingAsks){let Q=Z.toolByUseId.get(J);if(!Q||Y.currentIdx===void 0)continue;let H=e5($,J);if(H.waitingFor)Y.announced=!1,Y.announcementVersion=(Y.announcementVersion??0)+1;r(Z.cardId,R.tool(Q.i),a1(Q.i,J,Y.questions,"\uD83E\uDD14",H)),$3($,J)}}function MH($){return z6($)!==void 0}async function RH($,Z,J,Y){let Q=z6($);if(!Q){A(`session "${$.sessionName}": no unanswered question; routing text to Agent`),await $.onUserMessage(Z,[],J,Y);return}let[H,W]=Q,X=Q2($,H);if(X){let z=`${X}。这条文字未提交,请稍后重新发送。`;if(!await T($.chatId,z))throw Error(`提问等待提示发送失败: ${z}`);return}if(await Z3($,H,W.currentIdx,Z,J)&&Y)b0(Y,"CheckMark")}async function UH($,Z,J,Y,Q){let H=$.pendingAsks.get(Z);if(!H)return A(`session "${$.sessionName}": stray ask answer for ${Z}`),!1;if(J!==H.currentIdx)return A(`session "${$.sessionName}": stale ask click q=${J} current=${H.currentIdx}`),!1;return OH($,Z,{optionIdx:Y,user:Q})}async function Z3($,Z,J,Y,Q){let H=$.pendingAsks.get(Z);if(!H)return A(`session "${$.sessionName}": stray ask custom for ${Z}`),!1;let W=(Y??"").trim();if(!W)return A(`session "${$.sessionName}": empty custom answer, ignoring`),!1;if(J!==H.currentIdx)return A(`session "${$.sessionName}": stale ask custom q=${J} current=${H.currentIdx}`),!1;return OH($,Z,{customText:W,user:Q})}function OH($,Z,J){let Y=$.pendingAsks.get(Z);if(!Y||Y.currentIdx===void 0)return!1;let Q=Q2($,Z);if(Q)return A(`session "${$.sessionName}": ask ${Z} waiting: ${Q}`),!1;let H=Y.currentIdx,W=Y.questions[H];if(!W)return A(`session "${$.sessionName}": advanceAsk currentIdx=${H} out of range`),!1;let X;if(J.customText!==void 0)X=J.customText;else if(J.optionIdx!==void 0){let K=W.options?.[J.optionIdx];if(!K)return A(`session "${$.sessionName}": advanceAsk option ${J.optionIdx} out of range`),!1;X=K.label}else return A(`session "${$.sessionName}": advanceAsk with neither customText nor optionIdx`),!1;Y.answers[W.question]=X,Y.answered.set(H,{optionIdx:J.optionIdx,customText:J.customText,user:J.user});let V=Y.questions.length,z=void 0;for(let K=H+1;K<V;K++)if(!Y.answered.has(K)){z=K;break}Y.currentIdx=z;let G=$.currentTurn,_=G?.toolByUseId.get(Z);if(G&&_){let K=a1(_.i,Z,Y.questions,z===void 0?"✅":"\uD83E\uDD14",{currentIdx:z,answered:Y.answered});r(G.cardId,R.tool(_.i),K)}if(z===void 0)if(Y.requestId)J3($,Z);else A(`session "${$.sessionName}": ask ${Z} all answered, waiting for can_use_tool`),G6($);return!0}function J3($,Z){let J=$.pendingAsks.get(Z);if(!J||!J.requestId)return;let Y=$.currentTurn?.toolByUseId.get(Z),Q=Y?.input??{};if($.proc?.sendPermissionResponse(J.requestId,"allow",{updatedInput:{...Q,answers:J.answers}}),$.pendingPermissions.delete(J.requestId),Y)Y.output=JSON.stringify({answers:J.answers}),Y.isError=!1;if($.pendingAsks.delete(Z),G6($),$.pendingPermissions.size===0&&$.status==="awaiting_permission")$.status="working"}var A6=E(()=>{X1();u0();s();g();j4()});import{isAbsolute as _B}from"node:path";function D0($){if($?.planLiveInserted)return R.planLive;return $?.taskLiveInserted?R.taskBoardLive:R.footer}function KB($){return $==="ImageGeneration"||$==="imageGeneration"}function BB($,Z,J){if(J||!KB($))return null;let Y=W6(Z.trim());return _B(Y)?Y:null}function qB($){if($==="Read")return"read";if($==="Edit"||$==="MultiEdit"||$==="NotebookEdit")return"edit";return null}function TH($,Z,J){return $==="read"?H4(Z,J):Q4(Z,J)}function EH($,Z,J,Y){if(!$.currentTurn)return;if($.maybeMidTurnRotate(),$.startWorkingFooter($.currentTurn),$.currentTurn.currentAssistantSegmentId)$.finalizeCurrentAssistantSegment();let Q=qB(J);if(Q&&$.currentTurn.openBatchI!==null){let V=$.currentTurn.openBatchI,z=$.currentTurn.toolBatches.get(V);if(z&&z.kind===Q){let G=z.items.length;z.items.push({toolUseId:Z,input:Y,output:null,isError:!1}),$.currentTurn.toolByUseId.set(Z,{i:V,name:J,input:Y,batchSlot:G});let _=Q==="read"?H4(V,z.items):Q4(V,z.items);r($.currentTurn.cardId,R.tool(V),_),_6($.currentTurn,J,Y);return}}if(!Q)$.currentTurn.openBatchI=null;let H=_1(J);if(H){let V=$.currentTurn;if(H==="TaskCreate"&&!V.taskBoardResetThisTurn)$.taskBoard=[],V.taskBoardResetThisTurn=!0;if(!V.taskLiveInserted)V.taskLiveInserted=!0,_0(V.cardId,K1($.taskBoard),{type:"insert_before",targetElementId:R.footer});else r(V.cardId,R.taskBoardLive,K1($.taskBoard));let z=H==="TaskCreate";if(z)V.taskUpdateI=null;else V.taskCreateI=null;let G=(z?V.taskCreateI:V.taskUpdateI)===null;if(G)if(z)V.taskCreateI=V.toolCount++;else V.taskUpdateI=V.toolCount++;let _=z?V.taskCreateI:V.taskUpdateI;V.toolByUseId.set(Z,{i:_,name:J,input:Y});let K=I$(_,$.taskBoard,{name:H,status:"⏳"});G?_0(V.cardId,K,{type:"insert_before",targetElementId:D0(V)}):r(V.cardId,R.tool(_),K),_6(V,J,Y);return}$.currentTurn.taskCreateI=null,$.currentTurn.taskUpdateI=null;let W=$.currentTurn.toolCount++;if(Q){$.currentTurn.openBatchI=W;let V=[{toolUseId:Z,input:Y,output:null,isError:!1}];$.currentTurn.toolBatches.set(W,{kind:Q,items:V}),$.currentTurn.toolByUseId.set(Z,{i:W,name:J,input:Y,batchSlot:0});let z=Q==="read"?H4(W,V):Q4(W,V);_0($.currentTurn.cardId,z,{type:"insert_before",targetElementId:D0($.currentTurn)}),_6($.currentTurn,J,Y);return}if($.currentTurn.toolByUseId.set(Z,{i:W,name:J,input:Y}),J==="AskUserQuestion"){let V=Array.isArray(Y?.questions)?Y.questions:[],z=V.length>0?0:void 0,G=new Map;$.pendingAsks.set(Z,{questions:V,i:W,answers:{},answered:G,currentIdx:z});let _=a1(W,Z,V,"\uD83E\uDD14",e5($,Z));_0($.currentTurn.cardId,_,{type:"insert_before",targetElementId:D0($.currentTurn)}),$3($,Z);return}let X=H$(W,J,Y,null,"⏳");_0($.currentTurn.cardId,X,{type:"insert_before",targetElementId:D0($.currentTurn)}),_6($.currentTurn,J,Y)}function _6($,Z,J){if(!$)return;let Y=y$(Z,J),Q=Y.length>80?Y.slice(0,80)+"…":Y,H=V1(Z),W=Q?`\uD83D\uDD27 ${H}: ${Q}`:`\uD83D\uDD27 ${H}`;B$($.cardId,W)}function NH($,Z,J,Y,Q){if(!$.currentTurn)return;let H=$.currentTurn.toolByUseId.get(Z);if(!H)return;if(Q&&typeof Q==="object")H.input={...H.input,...Object.fromEntries(Object.entries(Q).filter(([,G])=>G!==void 0))};let W=typeof J==="string"?J:Array.isArray(J)?J.map((G)=>G?.text??JSON.stringify(G)).join(`
|
|
166
|
-
`):JSON.stringify(J);if(H.output=W,H.isError=Y,$.currentTurn.cardRotationFailed)$.maybeMidTurnRotate();let X=BB(H.name,W,Y);if(X){LB($,$.currentTurn,H,X),F4($);return}if(H.name==="AskUserQuestion"){F4($);return}if(H.batchSlot!=null){let G=$.currentTurn.toolBatches.get(H.i);if(G){let _=G.items[H.batchSlot];if(_)_.output=W,_.isError=Y;let K=TH(G.kind,H.i,G.items);r($.currentTurn.cardId,R.tool(H.i),K)}F4($);return}let V=_1(H.name);if(V){DB($,H,V,H.input,W,Y,H.resolvedNote);return}let z=H$(H.i,H.name,H.input,W,Y?"❌":"✅",H.resolvedNote);r($.currentTurn.cardId,R.tool(H.i),z),F4($)}function LB($,Z,J,Y){if(Z.outboundSeenPaths.has(Y))return;Z.outboundSeenPaths.add(Y);let Q=Z.cardId,H=R.tool(J.i),W=Z.imageDeliveryInflight??=new Map,X=W.get(Q)??new Set;W.set(Q,X);let V=(async()=>{let z=null;try{z=await g8(Y)}catch(_){A(`generated image upload failed: ${_}`)}if(z){let _=!1;try{_=await K0(Q,H,H$(J.i,J.name,J.input,J.output??null,"✅",J.resolvedNote,z),{notifyCardFailure:!1})}catch(K){A(`generated image embed failed: ${K}`)}if(_){J.imageKey=z,Z.outboundSentPaths.add(Y);return}A(`generated image could not be embedded in card ${Q}; sending it as a separate message`)}let G=z?await j9($.chatId,z)!==null:await r2($.chatId,Y);if(G)Z.outboundSentPaths.add(Y);else A(`generated image delivery failed: ${Y}`);if(J.resolvedNote=G?"图片已单独发送。":"图片发送失败。",await K0(Q,H,H$(J.i,J.name,J.input,J.output??null,G?"✅":"❌",J.resolvedNote),{notifyCardFailure:!1}),!G&&z)await T($.chatId,"❌ 生成图片发送失败,请稍后重试。")})().catch(async(z)=>{A(`generated image delivery failed: ${z}`),await T($.chatId,`❌ 生成图片发送失败:${z instanceof Error?z.message:String(z)}`)});X.add(V),V.finally(()=>{if(X.delete(V),!X.size)W.delete(Q)}).catch((z)=>A(`generated image failure notice failed: ${z}`))}async function Y3($,Z){let J=Z?[...$.imageDeliveryInflight?.get(Z)??[]]:[...$.imageDeliveryInflight?.values()??[]].flatMap((Y)=>[...Y]);await Promise.allSettled(J)}function DB($,Z,J,Y,Q,H,W){if(!$.currentTurn)return;if(!H)$.taskBoard=v5($.taskBoard,J,Y,Q);let X=I$(Z.i,$.taskBoard,{name:J,status:H?"❌":"✅"},W);if(r($.currentTurn.cardId,R.tool(Z.i),X),$.currentTurn.taskLiveInserted)r($.currentTurn.cardId,R.taskBoardLive,K1($.taskBoard));F4($)}function F4($){let Z=$.currentTurn;if(!Z)return;for(let J of Z.toolByUseId.values())if(J.output==null)return;$.startThinkingFooter(Z)}function Q3($,Z,J,Y,Q,H=$.currentTurn){let W=H;if(!W)return;for(let[X,V]of Y){if(W.toolByUseId.has(X))continue;let z=V.batchSlot??null,G=V.input,_,K;if(z!=null){let F=Q.get(V.i)?.items[z];if(!F)continue;G=F.input,_=F.output,K=F.isError}else _=V.output??null,K=V.isError??!1;let q=_!=null,D=d1(Z,R.tool(V.i));if(q&&!D)continue;if(z!=null){let F=Q.get(V.i)?.kind;if(!F)continue;let j=W.toolCount++,M={toolUseId:X,input:G,output:_,isError:K};W.toolBatches.set(j,{kind:F,items:[M]}),W.toolByUseId.set(X,{...V,i:j,batchSlot:0}),_0(J,TH(F,j,[M]),{type:"insert_before",targetElementId:D0(W)});continue}let L=_1(V.name);if(L){let F=L==="TaskCreate";if(F)W.taskUpdateI=null;else W.taskCreateI=null;let j=(F?W.taskCreateI:W.taskUpdateI)===null;if(j)if(F)W.taskCreateI=W.toolCount++;else W.taskUpdateI=W.toolCount++;let M=F?W.taskCreateI:W.taskUpdateI;W.toolByUseId.set(X,{...V,i:M});let C=!q?"⏳":K?"❌":"✅",b=I$(M,$.taskBoard,{name:L,status:C},V.resolvedNote);j?_0(J,b,{type:"insert_before",targetElementId:D0(W)}):r(J,R.tool(M),b);continue}let P=W.toolCount++;W.toolByUseId.set(X,{...V,i:P});let N=!q?"⏳":K?"❌":"✅";_0(J,H$(P,V.name,V.input,_,N,V.resolvedNote,V.imageKey),{type:"insert_before",targetElementId:D0(W)})}}var SH=E(()=>{u5();X1();u0();s();g();A6()});async function xH($,Z,J,Y){let Q=$.pendingPermissions.get(Z);if(!Q)return A(`session "${$.sessionName}": stray permission ${Z}`),{ok:!1,message:"此权限请求已失效或已处理"};let H=$.proc;if(!H)return A(`session "${$.sessionName}": permission ${Z} has no active process`),{ok:!1,message:"后端进程已退出,权限决定未送达"};let W=J==="deny"?"deny":"allow";try{H.sendPermissionResponse(Z,W,J==="allow_always"?{updatedPermissions:Q.permissionSuggestions}:void 0)}catch(z){return A(`session "${$.sessionName}": permission response ${Z} failed: ${z}`),{ok:!1,message:`权限决定发送失败: ${z instanceof Error?z.message:z}`}}$.pendingPermissions.delete(Z);let X=$.currentTurn,V=X?.toolByUseId.get(Q.toolUseId);if(X&&V){let z=_1(V.name);if(J==="deny"){let G=`\uD83D\uDEAB 已拒绝 by ${Y||"匿名"}`,_=z?I$(V.i,$.taskBoard,{name:z,status:"❌"},G):H$(V.i,V.name,V.input,G,"❌");r(X.cardId,R.tool(V.i),_)}else{let G=J==="allow_always"?"始终允许":"已允许";V.resolvedNote=`✅ **${G}** by ${Y||"匿名"}`;let _=z?I$(V.i,$.taskBoard,{name:z,status:"⏳"},V.resolvedNote):H$(V.i,V.name,V.input,null,"⏳",V.resolvedNote);r(X.cardId,R.tool(V.i),_)}}if(A(`session "${$.sessionName}": permission decision request=${Z} tool_use_id=${Q.toolUseId} decision=${J}`),$.pendingPermissions.size===0&&$.status==="awaiting_permission")$.status="working";return{ok:!0,message:J==="deny"?"已拒绝":J==="allow_always"?"已始终允许":"已允许"}}function kH($,Z){let J=$.currentTurn;if(!J){A(`session "${$.sessionName}": can_use_tool with no current turn — auto-deny req=${Z.request_id}`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"no active turn"});return}let Y=Z.tool_use_id;if(!Y){A(`session "${$.sessionName}": can_use_tool without tool_use_id — auto-deny req=${Z.request_id}`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"no tool_use_id"});return}let Q=J.toolByUseId.get(Y);if(!Q){A(`session "${$.sessionName}": can_use_tool for unknown tool_use_id=${Y} — auto-deny req=${Z.request_id}`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"unknown tool_use_id"});return}if(Q.name==="AskUserQuestion"){let W=$.pendingAsks.get(Y);if(!W){A(`session "${$.sessionName}": AskUserQuestion ${Y} missing pendingAsk — deny`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"no pending ask"});return}if(W.requestId=Z.request_id,$.pendingPermissions.set(Z.request_id,{toolUseId:Y}),W.currentIdx===void 0)J3($,Y);return}$.status="awaiting_permission",$.pendingPermissions.set(Z.request_id,{toolUseId:Y,permissionSuggestions:Z.permission_suggestions}),A(`session "${$.sessionName}": can_use_tool request=${Z.request_id} tool_use_id=${Y} tool=${Q.name}`);let H=G5(Q.i,Q.name,Q.input,Z.request_id);if(r(J.cardId,R.tool(Q.i),H),J.userOpenId&&J.messageId){let W=y$(Q.name,Q.input),X=V1(Q.name),V=W&&W.length>30?W.slice(0,30)+"…":W,z=V?`\uD83D\uDD10 等审批: ${X} · ${V}`:`\uD83D\uDD10 等审批: ${X}`;(async()=>{q0(J.cardId),await R9(J.cardId,{config:{summary:{content:z}}}),await H1(J.messageId,[J.userOpenId])})()}}var CH=E(()=>{X1();u0();s();g();A6()});function O0($){return[...new Set(($??"").split(",").map((Z)=>Z.trim()).filter(Boolean))]}function H3($,Z){let J=$.agent==="claude"?L7.filter((Q)=>Q!=="default"):$.agent==="codex"?[...C7]:["off","minimal","low","medium","high","xhigh","max"],Y=Z.effort?.trim();return{efforts:J,defaultEffort:Y&&J.includes(Y)?Y:$.agent==="claude"?"max":$.agent==="codex"?"xhigh":"high"}}function bH($,Z){let J=$.modelSelection,Y=new Set(O0(Z.hidden_models)),Q=[...new Set([...O0(Z.custom_models),...J?[]:O0(Z.models)])],H=$.modelSelection=J??{mode:"catalog",modelIds:[],availableModels:[]},W=$.refreshModels.bind($);return $.refreshModels=async()=>{if($.models=[],H.availableModels=[],!J)H.modelIds=[];try{await W()}catch(G){throw $.models=[],$.modelCatalogState={status:"failed",updatedAt:Date.now(),error:G instanceof Error?G.message:String(G)},G}if($.modelCatalogState?.status!=="ready")return;let X=$.models,V=(J?H.availableModels:X).map((G)=>({...G,origin:G.origin??"upstream"}));for(let G of Q){if(V.some((_)=>_.model.toLowerCase()===G.toLowerCase()))continue;V.push({model:G,display:G,origin:"custom",...H3($,Z)})}H.availableModels=V;let z=J?X.map((G)=>V.find((_)=>_.model===G.model)??{...G,origin:"upstream"}):V;$.models=[...z.filter((G)=>G.origin==="custom"||!Y.has(G.model)),...V.filter((G)=>G.origin==="custom"&&!z.some((_)=>_.model===G.model))],H.modelIds=$.models.map((G)=>G.model)},$}var M4=E(()=>{A0();s$()});import{homedir as FB}from"node:os";function W3($,Z=wH){return new Promise((J,Y)=>{let Q=setTimeout(()=>Y(Error(`timeout ${Z}ms`)),Z);$.then((H)=>{clearTimeout(Q),J(H)},(H)=>{clearTimeout(Q),Y(H)})})}function yH($){return typeof $==="string"&&MB.includes($)?$:null}async function fH(){let{ClaudeAgentProcess:$}=await Promise.resolve().then(() => (f2(),dJ)),Z=new $({workDir:FB(),effort:"high",settingSources:["user"],allowDelegation:!1,profile:{loadProjectMcp:!1}});Z.on("error",(J)=>A(`Claude model catalog MISS: ${J.message}`));try{let J=await W3(Z.listModels());if(!J.length)throw Error("Claude SDK model catalog is empty");return J.map((Y)=>({model:Y.model.replace(/^claude:/,""),display:Y.displayName,efforts:Y.supportedReasoningEfforts.map((Q)=>Q.reasoningEffort),defaultEffort:Y.defaultReasoningEffort}))}finally{await Z.kill()}}async function vH(){let $=new Y6;try{await W3($.request("initialize",{clientInfo:{name:"lodestar-models",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}));let Z=await W3($.request("model/list",{}));if(!Array.isArray(Z?.data))throw Error("Codex model/list 缺少 data 数组");let J=Z.data,Y=[];for(let Q of J){if(!Q||Q.hidden||!Q.id)continue;let H=(Array.isArray(Q.supportedReasoningEfforts)?Q.supportedReasoningEfforts:[]).map((X)=>yH(X?.reasoningEffort)).filter((X)=>X!==null);if(!H.length)continue;let W=yH(Q.defaultReasoningEffort)??H[0];Y.push({model:String(Q.id),display:typeof Q.displayName==="string"&&Q.displayName?String(Q.displayName):String(Q.id),efforts:H,defaultEffort:W})}return Y}finally{await $.close()}}async function hH($,Z){let J=new URL($),Y=J.pathname.replace(/\/+$/,""),Q=`${J.protocol}//${J.host}${Y}/v1/models`,H=await fetch(Q,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(wH)});if(!H.ok)throw Error(`HTTP ${H.status}`);let W=await H.json();if(!Array.isArray(W?.data))throw Error("GLM models 缺少 data 数组");return W.data.filter((V)=>V&&(V.display_name||V.id)).map((V)=>{let z=String(V.display_name||V.id);return{model:z,display:z,efforts:H2,defaultEffort:"max"}})}var wH=1e4,MB,H2;var R4=E(()=>{H6();g();MB=["none","minimal","low","medium","high","xhigh","max","ultra"];H2=["max","xhigh","high","medium","low"]});import{existsSync as RB}from"node:fs";import{homedir as UB}from"node:os";import{join as IH}from"node:path";function K6($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function OB($){if($.state!=="ok")return{state:$.state==="auth_failed"?"no_credentials":$.state==="no_credentials"?"no_credentials":$.state==="rate_limited"?"rate_limited":"network",windows:[],resetCredits:null};let Z=[];if($.fiveHour)Z.push(K6($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(K6($.weekly,"weekly","周配额"));return{state:"ok",planLabel:$.subscriptionType,windows:Z,fetchedAt:$.fetchedAt,resetCredits:$.resetCredits??null}}function TB($){if($.state!=="ok"||!$.buckets?.length)return null;let Z=[];for(let J of $.buckets){let Y=J.limitId===$.defaultLimitId?J.limitName??"默认配额":J.limitName??J.limitId;if(J.fiveHour)Z.push(K6(J.fiveHour,"fiveHour",`${Y} 5h`));if(J.weekly)Z.push(K6(J.weekly,"weekly",`${Y} 周`))}return Z.length?Z:null}function EB(){let $=process.env.CODEX_HOME||IH(UB(),".codex");return RB(IH($,"auth.json"))}var gH=E(()=>{x0();$0();H6();R4();g();M0({kind:"codex-subscription",configSectionId:"codex-sub",build:($)=>{let Z=EB(),J=$.model?.trim()||void 0,Y=$.effort?.trim()||void 0,Q={id:"codex-sub",kind:"codex-subscription",agent:"codex",display:$.display?.trim()||"Codex 订阅",enabled:Z,models:[],modelCatalogState:{status:Z?"idle":"disabled",updatedAt:Date.now()},defaultModel:J??"",async refreshModels(){if(!Q.enabled){Q.models=[],Q.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}Q.modelCatalogState={status:"loading",updatedAt:null};try{if(Q.models=await vH(),Y)for(let H of Q.models)H.defaultEffort=Y;if(!J)Q.defaultModel=Q.models[0]?.model??"";Q.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(H){A(`codex-sub refreshModels MISS: ${H?.message??H}`),Q.models=[],Q.modelCatalogState={status:"failed",updatedAt:Date.now(),error:H?.message??String(H)}}},spawnEnv(H){let W=Z$(H);return Object.assign(W,I.codex.env),W},resolveSpawnModel(H){return H},async readUsage(){let H=await Q6(),W=OB(H),X=TB(H);if(X)W.windows=X;return W}};return Q}})});function SB($){let Z=new URL($),J=Z.pathname.replace(/\/+$/,"");return`${Z.protocol}//${Z.host}${J}/v1/messages`}async function B6($,Z,J){try{let Y=await fetch(SB($),{method:"POST",headers:{"Content-Type":"application/json",...Z},body:JSON.stringify({model:J,max_tokens:1,messages:[{role:"user",content:"hi"}]}),signal:AbortSignal.timeout(NB)});if(Y.ok)return"exists";if(Y.status===400){let Q=await Y.text();return Q.includes("1214")||Q.includes("不存在")||Q.includes("not exist")?"not_found":"no_verdict"}return A(`model-existence: ${J} HTTP ${Y.status}, no verdict`),"no_verdict"}catch(Y){return A(`model-existence: ${J} MISS (${Y?.message??Y})`),"no_verdict"}}var NB=15000;var X3=E(()=>{g()});function cH($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function xB($){return{kind:"monthly",label:"月度工具",percent:$.percent,resetsAt:$.resetsAt,...$.used!=null?{used:$.used}:{},...$.total!=null?{total:$.total}:{}}}function mH($){return($??"").split(",").map((Z)=>Z.trim()).filter(Boolean)}function kB($){let Z=(J)=>{let Y=J.match(/(\d+(?:\.\d+)?)/);return Y?Number(Y[1]):-1};return[...$].sort((J,Y)=>Z(Y)-Z(J))[0]??""}function CB($){let Z={};for(let J of($??"").split(",")){let Y=J.indexOf("=");if(Y<=0)continue;let Q=J.slice(0,Y).trim().toLowerCase(),H=J.slice(Y+1).trim();if((Q==="opus"||Q==="sonnet"||Q==="haiku")&&H)Z[Q]=H}return Z}function V3($){if($.state!=="ok")return{state:$.state==="no_credentials"?"no_credentials":$.state==="not_glm"?"not_applicable":$.state==="rate_limited"?"rate_limited":"network",windows:[],...$.state==="network"&&$.reason?{reason:$.reason}:{}};let Z=[];if($.fiveHour)Z.push(cH($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(cH($.weekly,"weekly","周额度"));if($.monthly)Z.push(xB($.monthly));return{state:"ok",planLabel:$.level?`${$.level} 套餐`:void 0,windows:Z,fetchedAt:$.fetchedAt}}var z3=E(()=>{$0();B4();R4();w2();X3();g();M0({kind:"glm-coding-plan",configSectionId:"glm",build:($,Z)=>{let J=$.base_url?.trim()||Z?.base_url?.trim()||"",Y=$.auth_token?.trim()||Z?.auth_token?.trim()||"",Q=!!(J&&Y)&&q1(J),H=$.model?.trim()||void 0,W=CB($.slots),X={id:"glm",kind:"glm-coding-plan",agent:"claude",display:$.display?.trim()||"GLM Coding Plan",enabled:Q,models:[],modelCatalogState:{status:Q?"idle":"disabled",updatedAt:Date.now()},defaultModel:H??"",async refreshModels(){if(!X.enabled){X.models=[],X.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}X.modelCatalogState={status:"loading",updatedAt:null};try{let V=await hH(J,Y),G=[...new Set([...mH($.models),...mH($.custom_models)])].filter((_)=>!V.some((K)=>K.model.toLowerCase()===_.toLowerCase())).map((_)=>({model:_,display:_,efforts:H2,defaultEffort:"max",origin:"custom"}));if(X.models=[...V,...G],!H)X.defaultModel=kB(X.models.map((_)=>_.model));for(let _ of X.models){let K=v1("glm",_.model);_.context1m=K!=null&&K>=1e6||void 0}X.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(V){A(`glm refreshModels MISS: ${V?.message??V}`),X.models=[],X.modelCatalogState={status:"failed",updatedAt:Date.now(),error:V?.message??String(V)}}},spawnEnv(V){let G={...Z$(V)};if(G.ANTHROPIC_BASE_URL=J,G.ANTHROPIC_AUTH_TOKEN=Y,W.opus)G.ANTHROPIC_DEFAULT_OPUS_MODEL=W.opus;if(W.sonnet)G.ANTHROPIC_DEFAULT_SONNET_MODEL=W.sonnet;if(W.haiku)G.ANTHROPIC_DEFAULT_HAIKU_MODEL=W.haiku;return G},resolveSpawnModel(V){return s4("glm",V)},async verifyModel(V){return B6(J,{Authorization:`Bearer ${Y}`},V)},async readUsage(){return V3(await K4(J,Y))}};return X},setup:{commandSuffix:"glm",hint:($)=>`启用 ${$}:发送
|
|
168
|
+
`),H=Y[Y.length-1];_(`session "${$.sessionName}": multi-msg flush ${Y.length} segment(s) → 1 turn`),await $.onUserMessage(Q,[],H.userOpenId,H.msgId)}function n5($,Z){if($.multiMsgBuffer===null)return;let J=$.multiMsgBuffer.length;_(`session "${$.sessionName}": clear multi-msg buffer (${Z}): ${J} segment(s)`);for(let[Y,Q]of $.multiMsgReactions){if(Q)T0(Y,Q);b0(Y,"CrossMark")}$.multiMsgBuffer=null,$.multiMsgReactions=new Map}var eQ=S(()=>{e();g();tQ()});import{mkdtemp as IK,rm as gK,writeFile as cK}from"node:fs/promises";import{createRequire as mK}from"node:module";import{tmpdir as uK}from"node:os";import{join as $H}from"node:path";function rK($){let Z=QH.get($);if(Z)return Z;let{liteAdaptor:J}=F1("mathjax-full/js/adaptors/liteAdaptor.js"),{RegisterHTMLHandler:Y}=F1("mathjax-full/js/handlers/html.js"),{mathjax:Q}=F1("mathjax-full/js/mathjax.js"),{TeX:H}=F1("mathjax-full/js/input/tex.js"),{AllPackages:W}=F1("mathjax-full/js/input/tex/AllPackages.js"),{SVG:X}=F1("mathjax-full/js/output/svg.js"),V=J({fontSize:$});Y(V);let z=Q.document("",{InputJax:new H({packages:W}),OutputJax:new X({fontCache:"none"})}),G={adaptor:V,doc:z};return QH.set($,G),G}function HH($,Z){let J=Number.parseFloat($??"");if(!Number.isFinite(J)||J<=0)throw Error(`MathJax SVG missing valid ${Z}`);return J}function tK($){return $.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function sK($,Z=r5,J=!0){try{let Y=Z*pK,{adaptor:Q,doc:H}=rK(Z),W=H.convert($,{display:J,em:Z,ex:Y,containerWidth:80*Z}),X=Q.outerHTML(W);if(/data-mjx-error=|mjx-merror/.test(X)){let W0=X.match(/data-mjx-error="([^"]+)"/)?.[1]??"MathJax parse error";throw Error(W0)}let V=X.indexOf("<svg"),z=X.lastIndexOf("</svg>");if(V<0||z<0)throw Error("MathJax returned no SVG");let G=X.slice(V,z+6),A=G.match(/^<svg\b[^>]*>/)?.[0];if(!A)throw Error("MathJax returned malformed SVG root");let K=HH(A.match(/\bwidth="([\d.]+)ex"/)?.[1],"width"),L=HH(A.match(/\bheight="([\d.]+)ex"/)?.[1],"height"),D=A.match(/\bviewBox="([^"]+)"/)?.[1];if(!D)throw Error("MathJax SVG missing viewBox");let q=D.trim().split(/[\s,]+/).map(Number);if(q.length!==4||q.some((W0)=>!Number.isFinite(W0))||q[2]<=0||q[3]<=0)throw Error("MathJax SVG has invalid viewBox");let[P,x,F,M]=q,j=/<text\b/.test(G)?aK:0,k=`${P} ${x} ${F+j} ${M}`,C=K*Y,c=j*(C/F),y=Math.max(1,Math.ceil(C+c)),m=Math.max(1,Math.ceil(L*Y)),N=lK-a5*2,f=Math.min(1,N/y),I=Math.max(1,Math.round(y*f)),T=Math.max(1,Math.round(m*f));if(f<1&&T<iK)throw Error(`formula would be unreadable after width cap (${I}x${T})`);let U=I+a5*2,b=T+JH*2,H0=G.slice(A.length,-6).replace(/currentColor/g,ZH).replace(/font-family="serif"/g,`font-family="${oK}"`);return{svg:[`<svg xmlns="http://www.w3.org/2000/svg" width="${U}" height="${b}" viewBox="0 0 ${U} ${b}" style="color:${ZH}">`,`<rect x="0" y="0" width="${U}" height="${b}" rx="6" fill="${zH}"/>`,`<svg x="${a5}" y="${JH}" width="${I}" height="${T}" viewBox="${tK(k)}" preserveAspectRatio="xMidYMid meet">`,H0,"</svg>","</svg>"].join(""),width:U,height:b}}catch(Y){return _(`math-render: TeX→SVG failed for ${$.slice(0,80)}…: ${Y}`),null}}function eK($,Z=r5,J=!0){let Y=sK($,Z,J);if(!Y)return null;try{let{Resvg:Q}=F1("@resvg/resvg-js"),W=new Q(Y.svg,{background:zH,fitTo:{mode:"original"},shapeRendering:2,textRendering:1,font:{loadSystemFonts:!0,serifFamily:YH,sansSerifFamily:YH}}).render().asPng(),X=new DataView(W.buffer,W.byteOffset,W.byteLength),V=X.getUint32(16),z=X.getUint32(20);if(V!==Y.width||z!==Y.height)throw Error(`PNG dimensions ${V}x${z} != SVG ${Y.width}x${Y.height}`);return{png:W,width:V,height:z}}catch(Q){return _(`math-render: SVG→PNG failed for ${$.slice(0,80)}…: ${Q}`),null}}function $B($){if(/^[A-Za-zΑ-ω]$/.test($))return!0;if(/\\[A-Za-z]+|[_^=]|[{}]|[≤≥≠≈∑∫√]/.test($))return!0;return/[A-Za-zΑ-ω]\s*[+\-*/<>]\s*[A-Za-zΑ-ω0-9]/.test($)}function WH($,Z){let J=[],Y=(G,A,K)=>{let L=G[0],D=A.trim();if(!D)return;J.push({start:Z+G.index,end:Z+G.index+L.length,tex:D,raw:L,display:K})},Q,H=/(?<!\\)\$\$([\s\S]+?)(?<!\\)\$\$|\\\[([\s\S]+?)\\\]/g;while((Q=H.exec($))!==null)Y(Q,Q[1]??Q[2]??"",!0);let W=/\\\(([\s\S]+?)\\\)/g;while((Q=W.exec($))!==null)Y(Q,Q[1]??"",!1);let X=/(?<![\\$])\$(?!\$)([^$\n]+?)(?<![\\$])\$(?!\$)/g;while((Q=X.exec($))!==null){let G=(Q[1]??"").trim();if($B(G))Y(Q,G,!1)}J.sort((G,A)=>G.start-A.start||A.end-G.end);let V=[],z=-1;for(let G of J){if(G.start<z)continue;V.push(G),z=G.end}return V}function GH($){let Z=w7($),J=[],Y=0;for(let Q of Z){if(Y<Q.start)J.push(...WH($.slice(Y,Q.start),Y));Y=Math.max(Y,Q.end)}if(Y<$.length)J.push(...WH($.slice(Y),Y));return J}function ZB($){let Z=$;if(Z=Z.replace(/\\text\{([^{}]*)\}/g,"$1"),Z=Z.replace(/\\left\s*/g,"").replace(/\\right\s*/g,""),Z=Z.replace(/\\([A-Za-z]+)\b/g,(J,Y)=>{if(XH[Y])return XH[Y];if(Y==="times")return"×";if(Y==="cdot")return"·";if(Y==="div")return"÷";if(Y==="pm")return"±";if(Y==="leq"||Y==="le")return"≤";if(Y==="geq"||Y==="ge")return"≥";if(Y==="neq"||Y==="ne")return"≠";if(Y==="approx")return"≈";if(Y==="sim")return"~";if(Y==="infty")return"∞";if(Y==="partial")return"∂";if(Y==="nabla")return"∇";if(Y==="sqrt")return"√";if(Y==="to")return"→";return J}),/\\/.test(Z))return null;if(Z=Z.replace(/([_^])\{([^{}]+)\}/g,(J,Y,Q)=>Q.length===1?`${Y}${Q}`:`${Y}(${Q})`),Z=Z.replace(/√\{([^{}]+)\}/g,"√($1)"),/[{}]/.test(Z))return null;return Z}function HB($){let Z=VH.get($);if(Z!==void 0)return Z;return Z=YB++,VH.set($,Z),Z}function WB($,Z){return`${nK}\x00${HB(Z)}\x00${$}`}function XB($){let Z=2166136261;for(let J=0;J<$.length;J++)Z^=$.charCodeAt(J),Z=Math.imul(Z,16777619);return(Z>>>0).toString(36)}async function VB($,Z){let J=WB($,Z),Y=j1.get(J);if(Y)return Y;let Q=o5.get(J);if(Q)return Q;let H=(async()=>{let W=eK($,r5,!0);if(!W)return null;let X=null;try{X=await IK($H(uK(),"lodestar-math-"));let V=$H(X,`formula-${XB($)}.png`);await cK(V,W.png);let z=await Z(V,{tex:$,width:W.width,height:W.height});if(!z)return _(`math-render: upload returned no image key for ${$.slice(0,80)}…`),null;let G={key:z,width:W.width,height:W.height};if(j1.has(J))j1.delete(J);j1.set(J,G);while(j1.size>QB){let A=j1.keys().next().value;if(typeof A!=="string")break;j1.delete(A)}return G}catch(V){return _(`math-render: upload failed for ${$.slice(0,80)}…: ${V}`),null}finally{if(X)try{await gK(X,{recursive:!0,force:!0})}catch(V){_(`math-render: temp cleanup failed for ${X}: ${V}`)}}})();o5.set(J,H);try{return await H}finally{o5.delete(J)}}function zB($,Z,J){let Y=$.width<=dK;return{type:"image",tex:Z.tex,index:J,element:{tag:"img",img_key:$.key,alt:{tag:"plain_text",content:Z.tex.replace(/\s+/g," ").slice(0,80)},scale_type:Y?"crop_center":"fit_horizontal",...Y?{size:`${$.width}px ${$.height}px`}:{},preview:!1}}}async function _H($,Z={}){let J=GH($);if(!J.length)return{blocks:[{type:"markdown",text:$}],formulaCount:0,renderedImageCount:0};let Y=Z.uploader??JB,Q=await Promise.all(J.map(async(G)=>{if(!G.display){let A=ZB(G.tex);if(A!==null)return{unicode:A,uploaded:null}}return{unicode:null,uploaded:await VB(G.tex,Y)}})),H=[],W="",X=0,V=0,z=()=>{if(!W)return;if(W.trim())H.push({type:"markdown",text:W});W=""};for(let G=0;G<J.length;G++){let A=J[G],K=Q[G];if(W+=$.slice(X,A.start),K.unicode!==null){W+=K.unicode,X=A.end;continue}let L=K.uploaded;if(!L){W+=A.raw,X=A.end;continue}z(),H.push(zB(L,A,V++)),X=A.end}if(W+=$.slice(X),z(),!H.length)H.push({type:"markdown",text:$});return{blocks:H,formulaCount:J.length,renderedImageCount:V}}function t5($){return GH($).length>0}var F1,pK=0.5,r5=22,ZH="#1F2329",zH="#F7F8FA",a5=12,JH=8,lK=720,iK=14,dK=278,nK="v4-native-cjk-tail-pad",aK=1100,YH,oK="Noto Sans CJK SC, Noto Sans CJK JP, Microsoft YaHei, PingFang SC, Arial Unicode MS, sans-serif",QH,XH,JB=async($)=>{let{uploadImageKey:Z}=await Promise.resolve().then(() => (e(),J0));return Z($)},VH,YB=1,j1,o5,QB=512;var AH=S(()=>{g();F1=mK(import.meta.url),YH=process.platform==="win32"?"Microsoft YaHei":process.platform==="darwin"?"PingFang SC":"Noto Sans CJK SC",QH=new Map;XH={alpha:"α",beta:"β",gamma:"γ",delta:"δ",epsilon:"ε",zeta:"ζ",eta:"η",theta:"θ",iota:"ι",kappa:"κ",lambda:"λ",mu:"μ",nu:"ν",xi:"ξ",pi:"π",rho:"ρ",sigma:"σ",tau:"τ",phi:"φ",chi:"χ",psi:"ψ",omega:"ω",Gamma:"Γ",Delta:"Δ",Theta:"Θ",Lambda:"Λ",Pi:"Π",Sigma:"Σ",Phi:"Φ",Psi:"Ψ",Omega:"Ω"};VH=new WeakMap,j1=new Map,o5=new Map});import{readFileSync as _B}from"node:fs";function H2($){return s5.has($)}function P4($){s5.add($)}function j4($){s5.delete($)}function W2(){try{let $={};for(let[Z,J]of w0)$[Z]=J;A0(_6,$)}catch($){throw _(`notify-callbacks: save failed (${_6}): ${$}`),$}}function qH(){let $=[],Z;try{Z=_B(_6,"utf8")}catch{return[]}try{let J=JSON.parse(Z),Y=Date.now()-LH,Q=0,H=0;for(let W of Object.values(J)){if(!W||typeof W!=="object")continue;if(typeof W.notifyId!=="string"||typeof W.callbackUrl!=="string")continue;if(typeof W.createdAt!=="number"||W.createdAt<Y){Q++;continue}if(W.replyState?.status==="sending"&&!W.resolvedAt&&!W.unknownAt)W.unknownAt=Date.now(),W.unknownBy={openId:W.replyState.openId},W.unknownReason="服务在文字回复回传期间中断,无法确认是否送达,禁止自动重试",H++;if(w0.set(W.notifyId,W),W.replyState?.status==="sending"&&W.unknownAt)$.push(W)}if(_(`notify-callbacks: loaded ${w0.size} registration(s)${Q?`, dropped ${Q} stale`:""}`),H)_(`notify-callbacks: ${H} interrupted text reply(s) marked UNKNOWN`);if(Q>0||H>0)W2()}catch(J){_(`notify-callbacks: load failed (${_6}): ${J}`)}return $}function DH($){let Z=Date.now();if(Z-BH>=AB)KB(Z),BH=Z;w0.set($.notifyId,$),W2()}function P$($){return w0.get($)}function e5($){return[...w0.values()].filter((Z)=>Z.chatId===$&&!Z.resolvedAt&&!Z.unknownAt&&(Z.replyState?.status==="waiting"||Z.replyState?.status==="sending"))}function F4($,Z){if(!$)return;return e5($).find((J)=>Z===void 0||J.replyState?.openId===Z)}function PH($,Z){return!!Z&&[...w0.values()].some((J)=>J.chatId===$&&(J.replyMessageIds?.includes(Z)||J.replyState?.response?.message_id===Z))}function X2($,Z){let J=w0.get($);if(!J)throw Error(`notify registration not found: ${$}`);let{replyState:Y,replyMessageIds:Q}=J;if(J.replyState=Z,Z.response&&!J.replyMessageIds?.includes(Z.response.message_id))J.replyMessageIds=[...J.replyMessageIds??[],Z.response.message_id];try{W2()}catch(H){if(Y)J.replyState=Y;else delete J.replyState;if(Q)J.replyMessageIds=Q;else delete J.replyMessageIds;throw H}}function M4($,Z,J){let Y=w0.get($);if(!Y)throw Error(`notify registration not found: ${$}`);let Q={resolvedAt:Y.resolvedAt,resolvedBy:Y.resolvedBy,unknownAt:Y.unknownAt,unknownBy:Y.unknownBy,unknownReason:Y.unknownReason};Y.resolvedAt=Date.now(),Y.resolvedBy={...Z!==void 0?{buttonId:Z}:{},openId:J},delete Y.unknownAt,delete Y.unknownBy,delete Y.unknownReason;try{W2()}catch(H){if(Q.resolvedAt===void 0)delete Y.resolvedAt;else Y.resolvedAt=Q.resolvedAt;if(Q.resolvedBy===void 0)delete Y.resolvedBy;else Y.resolvedBy=Q.resolvedBy;if(Q.unknownAt===void 0)delete Y.unknownAt;else Y.unknownAt=Q.unknownAt;if(Q.unknownBy===void 0)delete Y.unknownBy;else Y.unknownBy=Q.unknownBy;if(Q.unknownReason===void 0)delete Y.unknownReason;else Y.unknownReason=Q.unknownReason;throw H}}function $3($,Z,J,Y){let Q=w0.get($);if(!Q)throw Error(`notify registration not found: ${$}`);delete Q.resolvedAt,delete Q.resolvedBy,Q.unknownAt=Date.now(),Q.unknownBy={...Z!==void 0?{buttonId:Z}:{},openId:J},Q.unknownReason=Y,W2()}function A6($,Z,J){try{return M4($,Z,J),{state:"complete"}}catch(Y){let H=`resolved tombstone persistence failed: ${Y instanceof Error?Y.message:String(Y)}`;try{$3($,Z,J,H)}catch(W){let X=W instanceof Error?W.message:String(W);H+=`; unknown tombstone persistence also failed: ${X}`;let V=w0.get($);if(V)V.unknownReason=H}return{state:"unknown",detail:H}}}function KB($=Date.now()){let Z=$-LH,J=0;for(let[Y,Q]of w0)if(typeof Q.createdAt!=="number"||Q.createdAt<Z)w0.delete(Y),J++;if(J>0)W2();return J}async function Z3($,Z,J){let Y={notify_id:$.notifyId,message_id:$.messageId,chat_id:$.chatId,project:$.project,..."id"in Z?{button:{id:Z.id,text:Z.text,type:Z.type}}:{response:{type:"text",...Z}},operator:{open_id:J},timestamp:Math.floor(Date.now()/1000)},Q=new AbortController,H=setTimeout(()=>Q.abort(),KH);try{let W=await fetch($.callbackUrl,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(Y),signal:Q.signal});if(W.status>=200&&W.status<300){let V;try{let z=(await W.text()).trim();if(z.startsWith("{")){let G=JSON.parse(z),A=typeof G?.text==="string"?G.text:typeof G?.reply==="string"?G.reply:typeof G?.message==="string"?G.message:"";if(A.trim())V=A.trim().slice(0,500)}else if(z)V=z.slice(0,500)}catch{}return{ok:!0,detail:`${W.status}`,reply:V}}let X="";try{X=(await W.text()).slice(0,120)}catch{}return{ok:!1,detail:`HTTP ${W.status}${X?` ${X}`:""}`}}catch(W){if(W?.name==="AbortError")return{ok:!1,detail:`回调超时 ${KH}ms(本地服务未在窗口内 2xx)`};return{ok:!1,detail:`回调失败: ${String(W?.message??W).slice(0,160)}`}}finally{clearTimeout(H)}}function jH($){let Z=!!$.resolvedAt,J=!!$.unknownAt,Y=$.resolvedBy?.buttonId??$.unknownBy?.buttonId,Q=Y?$.buttons.find((X)=>X.id===Y):void 0,H=$.replyState?.response,W=Y!==void 0?{button:Q?{id:Q.id,text:Q.text,type:Q.type}:{id:Y}}:H?{response:{type:"text",...H}}:{};return{notify_id:$.notifyId,project:$.project,message_id:$.messageId,resolved:Z,unknown:J,...$.replyState?{reply:{status:Z&&Y===void 0?"resolved":J&&Y===void 0?"unknown":$.replyState.status,prompt_message_id:$.replyState.promptMessageId,operator:{open_id:$.replyState.openId},...$.replyState.cancelReason?{cancel_reason:$.replyState.cancelReason}:{},...$.replyState.error?{error:$.replyState.error}:{}}}:{},...Z?{...W,resolved_at:$.resolvedAt,resolved_by:$.resolvedBy?.openId??null}:{},...J?{...W,unknown_at:$.unknownAt,unknown_by:$.unknownBy?.openId??null,unknown_reason:$.unknownReason}:{}}}var LH=604800000,KH=2500,w0,BH,AB=86400000,s5,_6;var R4=S(()=>{g();Y0();n0();w0=new Map,BH=Date.now(),s5=new Set;_6=DZ});function K6($){return[...$.pendingAsks.entries()].find(([,Z])=>Z.currentIdx!==void 0)}function V2($,Z){let J=$.pendingAsks.get(Z);if(!J||J.currentIdx===void 0)return null;if(F4($.chatId))return"请先完成或取消通知回复,再回答 Agent 的提问";if(K6($)?.[0]!==Z)return"请先回答当前问题,再回答排队中的提问";return null}function J3($,Z){let J=$.pendingAsks.get(Z);if(!J)throw Error(`missing pending ask: ${Z}`);let Y=J.currentIdx===void 0?void 0:F4($.chatId)?"notification":K6($)?.[0]!==Z?"question":void 0;return{currentIdx:J.currentIdx,answered:J.answered,waitingFor:Y}}function Y3($,Z){let J=$.pendingAsks.get(Z),Y=$.currentTurn;if(!J||J.currentIdx===void 0||J.announced||V2($,Z)||!Y?.userOpenId||!Y.messageId)return;J.announced=!0;let Q=(J.announcementVersion??0)+1;J.announcementVersion=Q;let H=J.questions[J.currentIdx]?.question.trim()??"",W=H.length>40?H.slice(0,40)+"…":H,X=J.questions.length>1?`❓ 待回答 ${J.questions.length} 题${W?`: ${W}`:""}`:W?`❓ ${W}`:"❓ 等你回答问题";(async()=>{if(D0(Y.cardId),await E9(Y.cardId,{config:{summary:{content:X}}}),$.currentTurn!==Y||$.pendingAsks.get(Z)!==J||J.announcementVersion!==Q||J.currentIdx===void 0||V2($,Z))return;await V1(Y.messageId,[Y.userOpenId])})().catch((V)=>_(`session "${$.sessionName}": question notification failed: ${V}`))}function B6($){let Z=$.currentTurn;if(!Z)return;for(let[J,Y]of $.pendingAsks){let Q=Z.toolByUseId.get(J);if(!Q||Y.currentIdx===void 0)continue;let H=J3($,J);if(H.waitingFor)Y.announced=!1,Y.announcementVersion=(Y.announcementVersion??0)+1;t(Z.cardId,R.tool(Q.i),s1(Q.i,J,Y.questions,"\uD83E\uDD14",H)),Y3($,J)}}function FH($){return K6($)!==void 0}async function MH($,Z,J,Y){let Q=K6($);if(!Q){_(`session "${$.sessionName}": no unanswered question; routing text to Agent`),await $.onUserMessage(Z,[],J,Y);return}let[H,W]=Q,X=V2($,H);if(X){let z=`${X}。这条文字未提交,请稍后重新发送。`;if(!await E($.chatId,z))throw Error(`提问等待提示发送失败: ${z}`);return}if(await Q3($,H,W.currentIdx,Z,J)&&Y)b0(Y,"CheckMark")}async function RH($,Z,J,Y,Q){let H=$.pendingAsks.get(Z);if(!H)return _(`session "${$.sessionName}": stray ask answer for ${Z}`),!1;if(J!==H.currentIdx)return _(`session "${$.sessionName}": stale ask click q=${J} current=${H.currentIdx}`),!1;return UH($,Z,{optionIdx:Y,user:Q})}async function Q3($,Z,J,Y,Q){let H=$.pendingAsks.get(Z);if(!H)return _(`session "${$.sessionName}": stray ask custom for ${Z}`),!1;let W=(Y??"").trim();if(!W)return _(`session "${$.sessionName}": empty custom answer, ignoring`),!1;if(J!==H.currentIdx)return _(`session "${$.sessionName}": stale ask custom q=${J} current=${H.currentIdx}`),!1;return UH($,Z,{customText:W,user:Q})}function UH($,Z,J){let Y=$.pendingAsks.get(Z);if(!Y||Y.currentIdx===void 0)return!1;let Q=V2($,Z);if(Q)return _(`session "${$.sessionName}": ask ${Z} waiting: ${Q}`),!1;let H=Y.currentIdx,W=Y.questions[H];if(!W)return _(`session "${$.sessionName}": advanceAsk currentIdx=${H} out of range`),!1;let X;if(J.customText!==void 0)X=J.customText;else if(J.optionIdx!==void 0){let K=W.options?.[J.optionIdx];if(!K)return _(`session "${$.sessionName}": advanceAsk option ${J.optionIdx} out of range`),!1;X=K.label}else return _(`session "${$.sessionName}": advanceAsk with neither customText nor optionIdx`),!1;Y.answers[W.question]=X,Y.answered.set(H,{optionIdx:J.optionIdx,customText:J.customText,user:J.user});let V=Y.questions.length,z=void 0;for(let K=H+1;K<V;K++)if(!Y.answered.has(K)){z=K;break}Y.currentIdx=z;let G=$.currentTurn,A=G?.toolByUseId.get(Z);if(G&&A){let K=s1(A.i,Z,Y.questions,z===void 0?"✅":"\uD83E\uDD14",{currentIdx:z,answered:Y.answered});t(G.cardId,R.tool(A.i),K)}if(z===void 0)if(Y.requestId)H3($,Z);else _(`session "${$.sessionName}": ask ${Z} all answered, waiting for can_use_tool`),B6($);return!0}function H3($,Z){let J=$.pendingAsks.get(Z);if(!J||!J.requestId)return;let Y=$.currentTurn?.toolByUseId.get(Z),Q=Y?.input??{};if($.proc?.sendPermissionResponse(J.requestId,"allow",{updatedInput:{...Q,answers:J.answers}}),$.pendingPermissions.delete(J.requestId),Y)Y.output=JSON.stringify({answers:J.answers}),Y.isError=!1;if($.pendingAsks.delete(Z),B6($),$.pendingPermissions.size===0&&$.status==="awaiting_permission")$.status="working"}var L6=S(()=>{G1();p0();e();g();R4()});import{isAbsolute as LB}from"node:path";function j0($){if($?.planLiveInserted)return R.planLive;return $?.taskLiveInserted?R.taskBoardLive:R.footer}function qB($){return $==="ImageGeneration"||$==="imageGeneration"}function DB($,Z,J){if(J||!qB($))return null;let Y=G6(Z.trim());return LB(Y)?Y:null}function PB($){if($==="Read")return"read";if($==="Edit"||$==="MultiEdit"||$==="NotebookEdit")return"edit";return null}function OH($,Z,J){return $==="read"?V4(Z,J):X4(Z,J)}function TH($,Z,J,Y){if(!$.currentTurn)return;if($.maybeMidTurnRotate(),$.startWorkingFooter($.currentTurn),$.currentTurn.currentAssistantSegmentId)$.finalizeCurrentAssistantSegment();let Q=PB(J);if(Q&&$.currentTurn.openBatchI!==null){let V=$.currentTurn.openBatchI,z=$.currentTurn.toolBatches.get(V);if(z&&z.kind===Q){let G=z.items.length;z.items.push({toolUseId:Z,input:Y,output:null,isError:!1}),$.currentTurn.toolByUseId.set(Z,{i:V,name:J,input:Y,batchSlot:G});let A=Q==="read"?V4(V,z.items):X4(V,z.items);t($.currentTurn.cardId,R.tool(V),A),q6($.currentTurn,J,Y);return}}if(!Q)$.currentTurn.openBatchI=null;let H=L1(J);if(H){let V=$.currentTurn;if(H==="TaskCreate"&&!V.taskBoardResetThisTurn)$.taskBoard=[],V.taskBoardResetThisTurn=!0;if(!V.taskLiveInserted)V.taskLiveInserted=!0,B0(V.cardId,q1($.taskBoard),{type:"insert_before",targetElementId:R.footer});else t(V.cardId,R.taskBoardLive,q1($.taskBoard));let z=H==="TaskCreate";if(z)V.taskUpdateI=null;else V.taskCreateI=null;let G=(z?V.taskCreateI:V.taskUpdateI)===null;if(G)if(z)V.taskCreateI=V.toolCount++;else V.taskUpdateI=V.toolCount++;let A=z?V.taskCreateI:V.taskUpdateI;V.toolByUseId.set(Z,{i:A,name:J,input:Y});let K=c$(A,$.taskBoard,{name:H,status:"⏳"});G?B0(V.cardId,K,{type:"insert_before",targetElementId:j0(V)}):t(V.cardId,R.tool(A),K),q6(V,J,Y);return}$.currentTurn.taskCreateI=null,$.currentTurn.taskUpdateI=null;let W=$.currentTurn.toolCount++;if(Q){$.currentTurn.openBatchI=W;let V=[{toolUseId:Z,input:Y,output:null,isError:!1}];$.currentTurn.toolBatches.set(W,{kind:Q,items:V}),$.currentTurn.toolByUseId.set(Z,{i:W,name:J,input:Y,batchSlot:0});let z=Q==="read"?V4(W,V):X4(W,V);B0($.currentTurn.cardId,z,{type:"insert_before",targetElementId:j0($.currentTurn)}),q6($.currentTurn,J,Y);return}if($.currentTurn.toolByUseId.set(Z,{i:W,name:J,input:Y}),J==="AskUserQuestion"){let V=Array.isArray(Y?.questions)?Y.questions:[],z=V.length>0?0:void 0,G=new Map;$.pendingAsks.set(Z,{questions:V,i:W,answers:{},answered:G,currentIdx:z});let A=s1(W,Z,V,"\uD83E\uDD14",J3($,Z));B0($.currentTurn.cardId,A,{type:"insert_before",targetElementId:j0($.currentTurn)}),Y3($,Z);return}let X=W$(W,J,Y,null,"⏳");B0($.currentTurn.cardId,X,{type:"insert_before",targetElementId:j0($.currentTurn)}),q6($.currentTurn,J,Y)}function q6($,Z,J){if(!$)return;let Y=f$(Z,J),Q=Y.length>80?Y.slice(0,80)+"…":Y,H=_1(Z),W=Q?`\uD83D\uDD27 ${H}: ${Q}`:`\uD83D\uDD27 ${H}`;L$($.cardId,W)}function EH($,Z,J,Y,Q){if(!$.currentTurn)return;let H=$.currentTurn.toolByUseId.get(Z);if(!H)return;if(Q&&typeof Q==="object")H.input={...H.input,...Object.fromEntries(Object.entries(Q).filter(([,G])=>G!==void 0))};let W=typeof J==="string"?J:Array.isArray(J)?J.map((G)=>G?.text??JSON.stringify(G)).join(`
|
|
169
|
+
`):JSON.stringify(J);if(H.output=W,H.isError=Y,$.currentTurn.cardRotationFailed)$.maybeMidTurnRotate();let X=DB(H.name,W,Y);if(X){jB($,$.currentTurn,H,X),U4($);return}if(H.name==="AskUserQuestion"){U4($);return}if(H.batchSlot!=null){let G=$.currentTurn.toolBatches.get(H.i);if(G){let A=G.items[H.batchSlot];if(A)A.output=W,A.isError=Y;let K=OH(G.kind,H.i,G.items);t($.currentTurn.cardId,R.tool(H.i),K)}U4($);return}let V=L1(H.name);if(V){FB($,H,V,H.input,W,Y,H.resolvedNote);return}let z=W$(H.i,H.name,H.input,W,Y?"❌":"✅",H.resolvedNote);t($.currentTurn.cardId,R.tool(H.i),z),U4($)}function jB($,Z,J,Y){if(Z.outboundSeenPaths.has(Y))return;Z.outboundSeenPaths.add(Y);let Q=Z.cardId,H=R.tool(J.i),W=Z.imageDeliveryInflight??=new Map,X=W.get(Q)??new Set;W.set(Q,X);let V=(async()=>{let z=null;try{z=await u8(Y)}catch(A){_(`generated image upload failed: ${A}`)}if(z){let A=!1;try{A=await L0(Q,H,W$(J.i,J.name,J.input,J.output??null,"✅",J.resolvedNote,z),{notifyCardFailure:!1})}catch(K){_(`generated image embed failed: ${K}`)}if(A){J.imageKey=z,Z.outboundSentPaths.add(Y);return}_(`generated image could not be embedded in card ${Q}; sending it as a separate message`)}let G=z?await U9($.chatId,z)!==null:await e2($.chatId,Y);if(G)Z.outboundSentPaths.add(Y);else _(`generated image delivery failed: ${Y}`);if(J.resolvedNote=G?"图片已单独发送。":"图片发送失败。",await L0(Q,H,W$(J.i,J.name,J.input,J.output??null,G?"✅":"❌",J.resolvedNote),{notifyCardFailure:!1}),!G&&z)await E($.chatId,"❌ 生成图片发送失败,请稍后重试。")})().catch(async(z)=>{_(`generated image delivery failed: ${z}`),await E($.chatId,`❌ 生成图片发送失败:${z instanceof Error?z.message:String(z)}`)});X.add(V),V.finally(()=>{if(X.delete(V),!X.size)W.delete(Q)}).catch((z)=>_(`generated image failure notice failed: ${z}`))}async function W3($,Z){let J=Z?[...$.imageDeliveryInflight?.get(Z)??[]]:[...$.imageDeliveryInflight?.values()??[]].flatMap((Y)=>[...Y]);await Promise.allSettled(J)}function FB($,Z,J,Y,Q,H,W){if(!$.currentTurn)return;if(!H)$.taskBoard=g5($.taskBoard,J,Y,Q);let X=c$(Z.i,$.taskBoard,{name:J,status:H?"❌":"✅"},W);if(t($.currentTurn.cardId,R.tool(Z.i),X),$.currentTurn.taskLiveInserted)t($.currentTurn.cardId,R.taskBoardLive,q1($.taskBoard));U4($)}function U4($){let Z=$.currentTurn;if(!Z)return;for(let J of Z.toolByUseId.values())if(J.output==null)return;$.startThinkingFooter(Z)}function X3($,Z,J,Y,Q,H=$.currentTurn){let W=H;if(!W)return;for(let[X,V]of Y){if(W.toolByUseId.has(X))continue;let z=V.batchSlot??null,G=V.input,A,K;if(z!=null){let F=Q.get(V.i)?.items[z];if(!F)continue;G=F.input,A=F.output,K=F.isError}else A=V.output??null,K=V.isError??!1;let L=A!=null,D=r1(Z,R.tool(V.i));if(L&&!D)continue;if(z!=null){let F=Q.get(V.i)?.kind;if(!F)continue;let M=W.toolCount++,j={toolUseId:X,input:G,output:A,isError:K};W.toolBatches.set(M,{kind:F,items:[j]}),W.toolByUseId.set(X,{...V,i:M,batchSlot:0}),B0(J,OH(F,M,[j]),{type:"insert_before",targetElementId:j0(W)});continue}let q=L1(V.name);if(q){let F=q==="TaskCreate";if(F)W.taskUpdateI=null;else W.taskCreateI=null;let M=(F?W.taskCreateI:W.taskUpdateI)===null;if(M)if(F)W.taskCreateI=W.toolCount++;else W.taskUpdateI=W.toolCount++;let j=F?W.taskCreateI:W.taskUpdateI;W.toolByUseId.set(X,{...V,i:j});let k=!L?"⏳":K?"❌":"✅",C=c$(j,$.taskBoard,{name:q,status:k},V.resolvedNote);M?B0(J,C,{type:"insert_before",targetElementId:j0(W)}):t(J,R.tool(j),C);continue}let P=W.toolCount++;W.toolByUseId.set(X,{...V,i:P});let x=!L?"⏳":K?"❌":"✅";B0(J,W$(P,V.name,V.input,A,x,V.resolvedNote,V.imageKey),{type:"insert_before",targetElementId:j0(W)})}}var NH=S(()=>{i5();G1();p0();e();g();L6()});async function SH($,Z,J,Y){let Q=$.pendingPermissions.get(Z);if(!Q)return _(`session "${$.sessionName}": stray permission ${Z}`),{ok:!1,message:"此权限请求已失效或已处理"};let H=$.proc;if(!H)return _(`session "${$.sessionName}": permission ${Z} has no active process`),{ok:!1,message:"后端进程已退出,权限决定未送达"};let W=J==="deny"?"deny":"allow";try{H.sendPermissionResponse(Z,W,J==="allow_always"?{updatedPermissions:Q.permissionSuggestions}:void 0)}catch(z){return _(`session "${$.sessionName}": permission response ${Z} failed: ${z}`),{ok:!1,message:`权限决定发送失败: ${z instanceof Error?z.message:z}`}}$.pendingPermissions.delete(Z);let X=$.currentTurn,V=X?.toolByUseId.get(Q.toolUseId);if(X&&V){let z=L1(V.name);if(J==="deny"){let G=`\uD83D\uDEAB 已拒绝 by ${Y||"匿名"}`,A=z?c$(V.i,$.taskBoard,{name:z,status:"❌"},G):W$(V.i,V.name,V.input,G,"❌");t(X.cardId,R.tool(V.i),A)}else{let G=J==="allow_always"?"始终允许":"已允许";V.resolvedNote=`✅ **${G}** by ${Y||"匿名"}`;let A=z?c$(V.i,$.taskBoard,{name:z,status:"⏳"},V.resolvedNote):W$(V.i,V.name,V.input,null,"⏳",V.resolvedNote);t(X.cardId,R.tool(V.i),A)}}if(_(`session "${$.sessionName}": permission decision request=${Z} tool_use_id=${Q.toolUseId} decision=${J}`),$.pendingPermissions.size===0&&$.status==="awaiting_permission")$.status="working";return{ok:!0,message:J==="deny"?"已拒绝":J==="allow_always"?"已始终允许":"已允许"}}function xH($,Z){let J=$.currentTurn;if(!J){_(`session "${$.sessionName}": can_use_tool with no current turn — auto-deny req=${Z.request_id}`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"no active turn"});return}let Y=Z.tool_use_id;if(!Y){_(`session "${$.sessionName}": can_use_tool without tool_use_id — auto-deny req=${Z.request_id}`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"no tool_use_id"});return}let Q=J.toolByUseId.get(Y);if(!Q){_(`session "${$.sessionName}": can_use_tool for unknown tool_use_id=${Y} — auto-deny req=${Z.request_id}`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"unknown tool_use_id"});return}if(Q.name==="AskUserQuestion"){let W=$.pendingAsks.get(Y);if(!W){_(`session "${$.sessionName}": AskUserQuestion ${Y} missing pendingAsk — deny`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"no pending ask"});return}if(W.requestId=Z.request_id,$.pendingPermissions.set(Z.request_id,{toolUseId:Y}),W.currentIdx===void 0)H3($,Y);return}$.status="awaiting_permission",$.pendingPermissions.set(Z.request_id,{toolUseId:Y,permissionSuggestions:Z.permission_suggestions}),_(`session "${$.sessionName}": can_use_tool request=${Z.request_id} tool_use_id=${Y} tool=${Q.name}`);let H=K5(Q.i,Q.name,Q.input,Z.request_id);if(t(J.cardId,R.tool(Q.i),H),J.userOpenId&&J.messageId){let W=f$(Q.name,Q.input),X=_1(Q.name),V=W&&W.length>30?W.slice(0,30)+"…":W,z=V?`\uD83D\uDD10 等审批: ${X} · ${V}`:`\uD83D\uDD10 等审批: ${X}`;(async()=>{D0(J.cardId),await E9(J.cardId,{config:{summary:{content:z}}}),await V1(J.messageId,[J.userOpenId])})()}}var kH=S(()=>{G1();p0();e();g();L6()});function E0($){return[...new Set(($??"").split(",").map((Z)=>Z.trim()).filter(Boolean))]}function V3($,Z){let J=$.agent==="claude"?P7.filter((Q)=>Q!=="default"):$.agent==="codex"?[...y7]:["off","minimal","low","medium","high","xhigh","max"],Y=Z.effort?.trim();return{efforts:J,defaultEffort:Y&&J.includes(Y)?Y:$.agent==="claude"?"max":$.agent==="codex"?"xhigh":"high"}}function CH($,Z){let J=$.modelSelection,Y=new Set(E0(Z.hidden_models)),Q=[...new Set([...E0(Z.custom_models),...J?[]:E0(Z.models)])],H=$.modelSelection=J??{mode:"catalog",modelIds:[],availableModels:[]},W=$.refreshModels.bind($);return $.refreshModels=async()=>{if($.models=[],H.availableModels=[],!J)H.modelIds=[];try{await W()}catch(G){throw $.models=[],$.modelCatalogState={status:"failed",updatedAt:Date.now(),error:G instanceof Error?G.message:String(G)},G}if($.modelCatalogState?.status!=="ready")return;let X=$.models,V=(J?H.availableModels:X).map((G)=>({...G,origin:G.origin??"upstream"}));for(let G of Q){if(V.some((A)=>A.model.toLowerCase()===G.toLowerCase()))continue;V.push({model:G,display:G,origin:"custom",...V3($,Z)})}H.availableModels=V;let z=J?X.map((G)=>V.find((A)=>A.model===G.model)??{...G,origin:"upstream"}):V;$.models=[...z.filter((G)=>G.origin==="custom"||!Y.has(G.model)),...V.filter((G)=>G.origin==="custom"&&!z.some((A)=>A.model===G.model))],H.modelIds=$.models.map((G)=>G.model)},$}var O4=S(()=>{K0();Z1()});import{homedir as UB}from"node:os";function z3($,Z=yH){return new Promise((J,Y)=>{let Q=setTimeout(()=>Y(Error(`timeout ${Z}ms`)),Z);$.then((H)=>{clearTimeout(Q),J(H)},(H)=>{clearTimeout(Q),Y(H)})})}function bH($){return typeof $==="string"&&OB.includes($)?$:null}async function wH(){let{ClaudeAgentProcess:$}=await Promise.resolve().then(() => (g2(),iJ)),Z=new $({workDir:UB(),effort:"high",settingSources:["user"],allowDelegation:!1,profile:{loadProjectMcp:!1}});Z.on("error",(J)=>_(`Claude model catalog MISS: ${J.message}`));try{let J=await z3(Z.listModels());if(!J.length)throw Error("Claude SDK model catalog is empty");return J.map((Y)=>({model:Y.model.replace(/^claude:/,""),display:Y.displayName,efforts:Y.supportedReasoningEfforts.map((Q)=>Q.reasoningEffort),defaultEffort:Y.defaultReasoningEffort}))}finally{await Z.kill()}}async function fH(){let $=new X6;try{await z3($.request("initialize",{clientInfo:{name:"lodestar-models",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}));let Z=await z3($.request("model/list",{}));if(!Array.isArray(Z?.data))throw Error("Codex model/list 缺少 data 数组");let J=Z.data,Y=[];for(let Q of J){if(!Q||Q.hidden||!Q.id)continue;let H=(Array.isArray(Q.supportedReasoningEfforts)?Q.supportedReasoningEfforts:[]).map((X)=>bH(X?.reasoningEffort)).filter((X)=>X!==null);if(!H.length)continue;let W=bH(Q.defaultReasoningEffort)??H[0];Y.push({model:String(Q.id),display:typeof Q.displayName==="string"&&Q.displayName?String(Q.displayName):String(Q.id),efforts:H,defaultEffort:W})}return Y}finally{await $.close()}}async function vH($,Z){let J=new URL($),Y=J.pathname.replace(/\/+$/,""),Q=`${J.protocol}//${J.host}${Y}/v1/models`,H=await fetch(Q,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(yH)});if(!H.ok)throw Error(`HTTP ${H.status}`);let W=await H.json();if(!Array.isArray(W?.data))throw Error("GLM models 缺少 data 数组");return W.data.filter((V)=>V&&(V.display_name||V.id)).map((V)=>{let z=String(V.display_name||V.id);return{model:z,display:z,efforts:z2,defaultEffort:"max"}})}var yH=1e4,OB,z2;var T4=S(()=>{z6();g();OB=["none","minimal","low","medium","high","xhigh","max","ultra"];z2=["max","xhigh","high","medium","low"]});import{existsSync as TB}from"node:fs";import{homedir as EB}from"node:os";import{join as hH}from"node:path";function D6($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function NB($){if($.state!=="ok")return{state:$.state==="auth_failed"?"no_credentials":$.state==="no_credentials"?"no_credentials":$.state==="rate_limited"?"rate_limited":"network",windows:[],resetCredits:null};let Z=[];if($.fiveHour)Z.push(D6($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(D6($.weekly,"weekly","周配额"));return{state:"ok",planLabel:$.subscriptionType,windows:Z,fetchedAt:$.fetchedAt,resetCredits:$.resetCredits??null}}function SB($){if($.state!=="ok"||!$.buckets?.length)return null;let Z=[];for(let J of $.buckets){let Y=J.limitId===$.defaultLimitId?J.limitName??"默认配额":J.limitName??J.limitId;if(J.fiveHour)Z.push(D6(J.fiveHour,"fiveHour",`${Y} 5h`));if(J.weekly)Z.push(D6(J.weekly,"weekly",`${Y} 周`))}return Z.length?Z:null}function xB(){let $=process.env.CODEX_HOME||hH(EB(),".codex");return TB(hH($,"auth.json"))}var IH=S(()=>{x0();Z0();z6();T4();g();U0({kind:"codex-subscription",configSectionId:"codex-sub",build:($)=>{let Z=xB(),J=$.model?.trim()||void 0,Y=$.effort?.trim()||void 0,Q={id:"codex-sub",kind:"codex-subscription",agent:"codex",display:$.display?.trim()||"Codex 订阅",enabled:Z,models:[],modelCatalogState:{status:Z?"idle":"disabled",updatedAt:Date.now()},defaultModel:J??"",async refreshModels(){if(!Q.enabled){Q.models=[],Q.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}Q.modelCatalogState={status:"loading",updatedAt:null};try{if(Q.models=await fH(),Y)for(let H of Q.models)H.defaultEffort=Y;if(!J)Q.defaultModel=Q.models[0]?.model??"";Q.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(H){_(`codex-sub refreshModels MISS: ${H?.message??H}`),Q.models=[],Q.modelCatalogState={status:"failed",updatedAt:Date.now(),error:H?.message??String(H)}}},spawnEnv(H){let W=J$(H);return Object.assign(W,v.codex.env),W},resolveSpawnModel(H){return H},async readUsage(){let H=await V6(),W=NB(H),X=SB(H);if(X)W.windows=X;return W}};return Q}})});function CB($){let Z=new URL($),J=Z.pathname.replace(/\/+$/,"");return`${Z.protocol}//${Z.host}${J}/v1/messages`}async function P6($,Z,J){try{let Y=await fetch(CB($),{method:"POST",headers:{"Content-Type":"application/json",...Z},body:JSON.stringify({model:J,max_tokens:1,messages:[{role:"user",content:"hi"}]}),signal:AbortSignal.timeout(kB)});if(Y.ok)return"exists";if(Y.status===400){let Q=await Y.text();return Q.includes("1214")||Q.includes("不存在")||Q.includes("not exist")?"not_found":"no_verdict"}return _(`model-existence: ${J} HTTP ${Y.status}, no verdict`),"no_verdict"}catch(Y){return _(`model-existence: ${J} MISS (${Y?.message??Y})`),"no_verdict"}}var kB=15000;var G3=S(()=>{g()});function gH($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function bB($){return{kind:"monthly",label:"月度工具",percent:$.percent,resetsAt:$.resetsAt,...$.used!=null?{used:$.used}:{},...$.total!=null?{total:$.total}:{}}}function cH($){return($??"").split(",").map((Z)=>Z.trim()).filter(Boolean)}function yB($){let Z=(J)=>{let Y=J.match(/(\d+(?:\.\d+)?)/);return Y?Number(Y[1]):-1};return[...$].sort((J,Y)=>Z(Y)-Z(J))[0]??""}function wB($){let Z={};for(let J of($??"").split(",")){let Y=J.indexOf("=");if(Y<=0)continue;let Q=J.slice(0,Y).trim().toLowerCase(),H=J.slice(Y+1).trim();if((Q==="opus"||Q==="sonnet"||Q==="haiku")&&H)Z[Q]=H}return Z}function _3($){if($.state!=="ok")return{state:$.state==="no_credentials"?"no_credentials":$.state==="not_glm"?"not_applicable":$.state==="rate_limited"?"rate_limited":"network",windows:[],...$.state==="network"&&$.reason?{reason:$.reason}:{}};let Z=[];if($.fiveHour)Z.push(gH($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(gH($.weekly,"weekly","周额度"));if($.monthly)Z.push(bB($.monthly));return{state:"ok",planLabel:$.level?`${$.level} 套餐`:void 0,windows:Z,fetchedAt:$.fetchedAt}}var A3=S(()=>{Z0();D4();T4();I2();G3();g();U0({kind:"glm-coding-plan",configSectionId:"glm",build:($,Z)=>{let J=$.base_url?.trim()||Z?.base_url?.trim()||"",Y=$.auth_token?.trim()||Z?.auth_token?.trim()||"",Q=!!(J&&Y)&&P1(J),H=$.model?.trim()||void 0,W=wB($.slots),X={id:"glm",kind:"glm-coding-plan",agent:"claude",display:$.display?.trim()||"GLM Coding Plan",enabled:Q,models:[],modelCatalogState:{status:Q?"idle":"disabled",updatedAt:Date.now()},defaultModel:H??"",async refreshModels(){if(!X.enabled){X.models=[],X.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}X.modelCatalogState={status:"loading",updatedAt:null};try{let V=await vH(J,Y),G=[...new Set([...cH($.models),...cH($.custom_models)])].filter((A)=>!V.some((K)=>K.model.toLowerCase()===A.toLowerCase())).map((A)=>({model:A,display:A,efforts:z2,defaultEffort:"max",origin:"custom"}));if(X.models=[...V,...G],!H)X.defaultModel=yB(X.models.map((A)=>A.model));for(let A of X.models){let K=c1("glm",A.model);A.context1m=K!=null&&K>=1e6||void 0}X.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(V){_(`glm refreshModels MISS: ${V?.message??V}`),X.models=[],X.modelCatalogState={status:"failed",updatedAt:Date.now(),error:V?.message??String(V)}}},spawnEnv(V){let G={...J$(V)};if(G.ANTHROPIC_BASE_URL=J,G.ANTHROPIC_AUTH_TOKEN=Y,W.opus)G.ANTHROPIC_DEFAULT_OPUS_MODEL=W.opus;if(W.sonnet)G.ANTHROPIC_DEFAULT_SONNET_MODEL=W.sonnet;if(W.haiku)G.ANTHROPIC_DEFAULT_HAIKU_MODEL=W.haiku;return G},resolveSpawnModel(V){return J9("glm",V)},async verifyModel(V){return P6(J,{Authorization:`Bearer ${Y}`},V)},async readUsage(){return _3(await q4(J,Y))}};return X},setup:{commandSuffix:"glm",hint:($)=>`启用 ${$}:发送
|
|
167
170
|
\`\`\`
|
|
168
171
|
glm-setup <base_url> <token>
|
|
169
|
-
\`\`\``,parseArgs:($)=>{let Z=$.trim().split(/\s+/);if(Z.length<2)return{error:"用法:`glm-setup <base_url> <token>`"};return{config:{agent:"claude",base_url:Z[0],auth_token:Z[1]}}}},detect:{fromSettingsEnv($){let Z=$.ANTHROPIC_BASE_URL?.trim()??"";if(!
|
|
172
|
+
\`\`\``,parseArgs:($)=>{let Z=$.trim().split(/\s+/);if(Z.length<2)return{error:"用法:`glm-setup <base_url> <token>`"};return{config:{agent:"claude",base_url:Z[0],auth_token:Z[1]}}}},detect:{fromSettingsEnv($){let Z=$.ANTHROPIC_BASE_URL?.trim()??"";if(!P1(Z))return null;let J=$.ANTHROPIC_AUTH_TOKEN?.trim()??"";return J?{base_url:Z,auth_token:J}:null}}})});var mH=S(()=>{Z0();T4();U0({kind:"claude-native",configSectionId:"claude-native",build:($)=>{let Z={id:"claude-native",kind:"claude-native",agent:"claude",display:$.display?.trim()||"Claude",enabled:!1,models:[],modelCatalogState:{status:"disabled",updatedAt:Date.now()},defaultModel:$.model?.trim()||"opus",settingSources:["user","project","local"],async refreshModels(){if(Z.models=[],!Z.enabled){Z.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}Z.modelCatalogState={status:"loading",updatedAt:null};try{if(Z.models=await wH(),!Z.models.some((J)=>J.model===Z.defaultModel))throw Error("Claude 默认模型不在 SDK 目录中");Z.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(J){throw Z.models=[],Z.modelCatalogState={status:"failed",updatedAt:Date.now(),error:J instanceof Error?J.message:String(J)},J}},spawnEnv(J){return J},resolveSpawnModel(J){return J},async readUsage(){return{state:"not_applicable",windows:[]}}};return Z}})});function uH($){return($??"").split(",").map((Z)=>Z.trim()).filter(Boolean)}function vB($){let Z=(J)=>{let Y=J.match(/(\d+(?:\.\d+)?)/);return Y?Number(Y[1]):-1};return[...$].sort((J,Y)=>Z(Y)-Z(J))[0]??""}function hB($){let Z={};for(let J of($??"").split(",")){let Y=J.indexOf("=");if(Y<=0)continue;let Q=J.slice(0,Y).trim().toLowerCase(),H=J.slice(Y+1).trim();if((Q==="opus"||Q==="sonnet"||Q==="haiku")&&H)Z[Q]=H}return Z}function IB($){try{return new URL($).hostname.toLowerCase()==="api.deepseek.com"}catch{return!1}}async function gB($,Z){let J=new URL($).origin,Y=await fetch(`${J}/models`,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(1e4)});if(!Y.ok)throw Error(`HTTP ${Y.status}`);let Q=await Y.json();if(!Array.isArray(Q?.data))throw Error("DeepSeek models 缺少 data 数组");return Q.data.filter((W)=>W&&typeof W.id==="string"&&W.id).map((W)=>({model:W.id,display:W.id,efforts:z2,defaultEffort:"high"}))}async function K3($,Z){let J;try{J=new URL($).origin}catch{return{kind:"balance",state:"network",windows:[],reason:"bad base_url"}}try{let Y=await fetch(`${J}/user/balance`,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(cB)});if(!Y.ok)throw Error(`HTTP ${Y.status}`);let Q=await Y.json(),W=(Array.isArray(Q?.balance_infos)?Q.balance_infos:[])[0],X=typeof W?.currency==="string"?W.currency:"",V=W?.total_balance;if(!X||typeof V!=="string"&&typeof V!=="number"||String(V).trim()===""||!Number.isFinite(Number(V)))throw Error("余额明细缺失或无效");return{kind:"balance",state:"ok",windows:[],balance:{remaining:Number(V),currency:X}}}catch(Y){return _(`deepseek readUsage MISS: ${Y?.message??Y}`),{kind:"balance",state:"network",windows:[],reason:Y?.message??String(Y)}}}var fB="https://api.deepseek.com/anthropic",cB=1e4;var B3=S(()=>{Z0();T4();I2();G3();g();U0({kind:"deepseek",configSectionId:"deepseek",build:($,Z)=>{let J=$.base_url?.trim()||Z?.base_url?.trim()||fB,Y=$.api_key?.trim()||Z?.api_key?.trim()||"",Q=!!Y,H=$.model?.trim()||void 0,W=hB($.slots),X={id:"deepseek",kind:"deepseek",agent:"claude",display:$.display?.trim()||"DeepSeek",enabled:Q,models:[],modelCatalogState:{status:Q?"idle":"disabled",updatedAt:Date.now()},defaultModel:H??"",async refreshModels(){if(!X.enabled){X.models=[],X.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}X.modelCatalogState={status:"loading",updatedAt:null};try{let V=await gB(J,Y),G=[...new Set([...uH($.models),...uH($.custom_models)])].filter((A)=>!V.some((K)=>K.model.toLowerCase()===A.toLowerCase())).map((A)=>({model:A,display:A,efforts:z2,defaultEffort:"high",origin:"custom"}));if(X.models=[...V,...G],!H)X.defaultModel=vB(X.models.map((A)=>A.model));for(let A of X.models){let K=c1("deepseek",A.model);A.context1m=K!=null&&K>=1e6||void 0}X.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(V){_(`deepseek refreshModels MISS: ${V?.message??V}`),X.models=[],X.modelCatalogState={status:"failed",updatedAt:Date.now(),error:V?.message??String(V)}}},spawnEnv(V){let G={...J$(V)};if(G.ANTHROPIC_BASE_URL=J,G.ANTHROPIC_API_KEY=Y,W.opus)G.ANTHROPIC_DEFAULT_OPUS_MODEL=W.opus;if(W.sonnet)G.ANTHROPIC_DEFAULT_SONNET_MODEL=W.sonnet;if(W.haiku)G.ANTHROPIC_DEFAULT_HAIKU_MODEL=W.haiku;return G},resolveSpawnModel(V){return J9("deepseek",V)},async verifyModel(V){return P6(J,{"x-api-key":Y},V)},async readUsage(){if(!Y)return{kind:"balance",state:"no_credentials",windows:[]};return K3(J,Y)}};return X},setup:{commandSuffix:"deepseek",hint:($)=>`启用 ${$}:发送
|
|
170
173
|
\`\`\`
|
|
171
174
|
deepseek-setup <api_key>
|
|
172
175
|
\`\`\`
|
|
173
|
-
默认官方 Anthropic 端点;自建中转用 \`deepseek-setup <base_url> <api_key>\`。`,parseArgs:($)=>{let Z=$.trim().split(/\s+/).filter(Boolean);if(!Z.length)return{error:"用法:`deepseek-setup <api_key>`(官方端点)或 `deepseek-setup <base_url> <api_key>`(自建中转)"};let J=Z.length>=2?Z[0]:void 0,Y=Z.length>=2?Z[1]:Z[0];return{config:{agent:"claude",...J?{base_url:J}:{},api_key:Y}}}},detect:{fromSettingsEnv($){let Z=$.ANTHROPIC_BASE_URL?.trim()??"";if(!fB(Z))return null;let J=$.ANTHROPIC_API_KEY?.trim()??"";return J?{base_url:Z,api_key:J}:null}}})});function P1($){let Z=$.toLowerCase().replace(/^~/,"");return/^(openai|deepseek|z-ai|zai-org|thudm)\//.test(Z)||/^(openrouter\/|@)/.test(Z)}var _3;var lH=E(()=>{_3=[{rank:1,lab:"Anthropic",model:"anthropic/claude-fable-5.1",effort:"max"},{rank:3,lab:"Moonshot",model:"moonshotai/kimi-k3",effort:"max"},{rank:4,lab:"Tencent",model:"tencent/hy4-preview",effort:"high"},{rank:7,lab:"Google",model:"google/gemini-3.8-flash",effort:"high"},{rank:8,lab:"SpaceXAI",model:"x-ai/grok-4.5",effort:"high"},{rank:9,lab:"Alibaba",model:"qwen/qwen3.8-max-0902",effort:"xhigh"},{rank:10,lab:"Meta",model:"meta/muse-spark-1.2",effort:"xhigh"},{rank:11,lab:"Xiaomi",model:"xiaomi/mimo-v2.5-pro",effort:"default"},{rank:12,lab:"MiniMax",model:"minimax/minimax-m3",effort:"default"},{lab:"ByteDance",model:"bytedance-seed/seed-2-1-turbo",effort:"default"},{lab:"Meituan",model:"meituan/longcat-2.0",effort:"default"}]});function g$($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function B3($){return $ instanceof Error?$.message:String($)}function iH($){return[...new Set(($??"").split(",").map((Z)=>Z.trim()).filter(Boolean))]}function W2($){return $.replace(/\[1m\]$/,"")}function q6($){let Z=new URL($);if(!["https:","http:"].includes(Z.protocol)||Z.username||Z.password||Z.search||Z.hash)throw Error("OpenRouter base_url 必须是无凭据、查询参数和 fragment 的 HTTP(S) API 根地址");return Z.pathname=Z.pathname.replace(/\/+$/,"").replace(/\/v1$/,""),Z.toString().replace(/\/+$/,"")}async function nH($,Z,J){if(!Z)throw Error("OpenRouter API key missing");let Y=await fetch(`${q6($)}/v1/${J}`,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(gB)});if(!Y.ok){let Q=await Y.text(),H="";if(Q.trim().startsWith("{"))try{let W=JSON.parse(Q);if(g$(W)&&g$(W.error)&&typeof W.error.message==="string")H=W.error.message}catch{}throw new q3(Y.status,H.replaceAll(Z,"[redacted]"))}return Y.json()}async function cB($,Z){let J=await nH($,Z,"models/user");if(!g$(J)||!Array.isArray(J.data))throw Error("OpenRouter models: data 数组缺失");let Y=[],Q=new Set;for(let H of J.data){if(!g$(H)||typeof H.id!=="string"||!H.id||typeof H.name!=="string")throw Error("OpenRouter models: 模型 id/name 无效");if(!g$(H.architecture)||!Array.isArray(H.architecture.output_modalities)||!Array.isArray(H.supported_parameters))throw Error(`OpenRouter models: ${H.id} 的模型能力缺失`);if(P1(H.id)||!H.architecture.output_modalities.includes("text")||!H.supported_parameters.includes("tools")||H.id.endsWith(":batch")||Q.has(H.id))continue;let W=g$(H.reasoning)?H.reasoning:void 0,X=W?.supported_efforts,V=X===null||X===void 0&&H.supported_parameters.includes("reasoning_effort")?["max","xhigh","high","medium","low"]:Array.isArray(X)?[...new Set(X.filter((K)=>K!=="default"&&F0(K)))]:["default"],z=_3.find((K)=>K.model===H.id),G=z?V.includes(z.effort)?z.effort:null:V[0]==="default"?"default":F0(W?.default_effort)&&V.includes(W.default_effort)?W.default_effort:null,_=v1("openrouter",H.id);Y.push({model:H.id,display:H.name,efforts:V,defaultEffort:G,context1m:_!==void 0&&_>=1e6||void 0}),Q.add(H.id)}if(!Y.length)throw Error("OpenRouter 未返回支持文本和工具调用的交互模型");return Y}function dH($){return typeof $==="number"&&Number.isFinite($)&&$>=0}async function mB($,Z){if(!Z)return{kind:"balance",state:"no_credentials",windows:[]};try{let J=await nH($,Z,"credits");if(!g$(J)||!g$(J.data))throw Error("OpenRouter credits: data 对象缺失");let{total_credits:Y,total_usage:Q}=J.data;if(!dH(Y)||!dH(Q))throw Error("OpenRouter credits: total_credits/total_usage 缺失或无效");return{kind:"balance",state:"ok",fetchedAt:Date.now(),windows:[],balance:{remaining:Y-Q,currency:"USD"}}}catch(J){let Y=B3(J);return A(`openrouter readUsage MISS: ${Y}`),{kind:"balance",state:J instanceof q3&&J.status===429?"rate_limited":"network",windows:[],reason:Y}}}var IB="https://openrouter.ai/api",gB=1e4,K3,q3;var aH=E(()=>{A0();$0();w2();g();lH();K3={opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL"};q3=class q3 extends Error{status;constructor($,Z){super(`HTTP ${$}${Z?`: ${Z}`:""}`);this.status=$}};M0({kind:"openrouter",configSectionId:"openrouter",build($,Z){let J=$.api_key||$.auth_token||$.base_url?$:Z,Y=J?.api_key?.trim()||J?.auth_token?.trim()||"",Q=J?.base_url?.trim()||IB,H=$.model?.trim()||"",W=$.models===void 0?_3.map((V)=>V.model):iH($.models),X={id:"openrouter",kind:"openrouter",agent:"claude",display:$.display?.trim()||"OpenRouter",enabled:!!Y,models:[],defaultModel:H,modelSelection:{mode:"allowlist",modelIds:W,availableModels:[]},validateCustomModelId(V){if(P1(V))throw Error(`OpenRouter 已排除此厂商或自动路由: ${V}`);if(!V.includes("/"))throw Error("OpenRouter 模型请填写完整的 作者/模型 ID")},modelEnvironmentRevision(V){let z=X.modelSelection.availableModels.find((G)=>W2(G.model)===W2(V));if(!z||z.unavailableReason||!z.efforts.length)return"model-unavailable";return z.efforts.includes("default")?"effort-unset":"effort-level"},modelCatalogState:{status:Y?"idle":"disabled",updatedAt:Date.now()},async refreshModels(){if(X.models=[],X.modelSelection.availableModels=[],!X.enabled){X.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}X.modelCatalogState={status:"loading",updatedAt:null};try{let V=await cB(Q,Y),z=V.find((_)=>_.model===W2(H));if(H&&!z)throw Error(`OpenRouter 默认模型不在账号目录中: ${H}`);if($.effort){if(!H)throw Error("OpenRouter effort 需要同时配置 model");if(!F0($.effort)||!z.efforts.includes($.effort))throw Error(`OpenRouter 模型 ${H} 不支持 effort ${$.effort}`);z.defaultEffort=$.effort}let G=W.map((_)=>{let K=V.find((q)=>q.model===W2(_));if(!K)return{model:_,display:_,efforts:[],defaultEffort:null,unavailableReason:P1(_)?"此厂商或自动路由已被排除":"账号目录未返回该模型"};return{...K,model:_}});X.models=G,X.modelSelection.availableModels=V,X.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(V){let z=B3(V);A(`openrouter refreshModels MISS: ${z}`),X.modelCatalogState={status:"failed",updatedAt:Date.now(),error:z}}},spawnEnv(V,z){if(!Y)throw Error("OpenRouter API key missing");let G=z||H;if(!G)throw Error("OpenRouter 未选择模型,请通过 model 面板选择或配置 model");if(P1(G))throw Error(`OpenRouter 已排除此厂商或自动路由: ${G}`);let _=Z$(V);_.ANTHROPIC_BASE_URL=q6(Q),_.ANTHROPIC_AUTH_TOKEN=Y,_.ANTHROPIC_API_KEY="",_.CLAUDE_CODE_NO_MODEL_FALLBACK="1",_.ANTHROPIC_MODEL=G,_.ANTHROPIC_SMALL_FAST_MODEL=G,_.CLAUDE_CODE_SUBAGENT_MODEL=G,_.ANTHROPIC_DEFAULT_FABLE_MODEL=G;for(let K of Object.values(K3))_[K]=G;for(let K of iH($.slots)){let q=K.indexOf("="),D=K.slice(0,q).trim(),L=K.slice(q+1).trim();if(q<1||!Object.hasOwn(K3,D)||!L)throw Error(`OpenRouter slots 无效: ${K}`);if(P1(L)||!X.modelSelection.availableModels.some((P)=>!P.unavailableReason&&W2(P.model)===W2(L)))throw Error(`OpenRouter slot 模型不在账号目录中: ${L}`);if(X.modelEnvironmentRevision(L)!==X.modelEnvironmentRevision(G))throw Error(`OpenRouter slot 不能混合无 effort 档位与有 effort 档位的模型: ${L}`);_[K3[D]]=L}return _},resolveSpawnModel(V){if(P1(V))throw Error(`OpenRouter 已排除此厂商或自动路由: ${V}`);return V||void 0},readUsage(){return mB(Q,Y)}};return X},setup:{commandSuffix:"openrouter",hint:($)=>`启用 ${$}:发送 \`openrouter-setup <api_key>\`,然后通过 \`model\` 选择模型。自建端点用 \`openrouter-setup <base_url> <api_key>\`。`,parseArgs($){let Z=$.trim().split(/\s+/).filter(Boolean);if(Z.length<1||Z.length>2||Z.length===1&&/^https?:\/\//i.test(Z[0]))return{error:"用法: openrouter-setup <api_key> 或 openrouter-setup <base_url> <api_key>"};try{return{config:{agent:"claude",api_key:Z[Z.length-1],...Z.length===2?{base_url:q6(Z[0])}:{}}}}catch(J){return{error:B3(J)}}}},detect:{fromSettingsEnv($){let Z=$.ANTHROPIC_BASE_URL?.trim(),J=$.ANTHROPIC_AUTH_TOKEN?.trim();if(!Z||!J)return null;try{let Y=q6(Z);if(new URL(Y).hostname!=="openrouter.ai")return null;return{base_url:Y,api_key:J}}catch{return null}}}})});var oH=E(()=>{$0();A0();O2();J0();A3();M4();M0({kind:"deepseek-harness",configSectionId:"deepseek-harness",build($){let Z=$.api_key?.trim()??"",J=$.base_url?.trim()||"https://api.deepseek.com",Y={id:"deepseek-harness",kind:"deepseek-harness",agent:"dsh",display:$.display?.trim()||"DeepSeek",enabled:!!Z,models:[],defaultModel:$.model?.trim()??"",modelCatalogState:{status:Z?"idle":"disabled",updatedAt:Date.now()},spawnEnv(Q){let H=v2(Q);if(!Z)throw Error("DeepSeek Harness API key is missing");if(H.DEEPSEEK_API_KEY=Z,H.DEEPSEEK_BASE_URL=J,H.LODESTAR_DSH_PROVIDER="deepseek-official",$.bin)H.LODESTAR_DSH_NODE=$.bin;return H},async refreshModels(){if(!Y.enabled){Y.models=[],Y.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}Y.modelCatalogState={status:"loading",updatedAt:null};try{let Q=await k1({cwd:N1,env:Y.spawnEnv(process.env),profile:{loadProjectMcp:!1}},"model/list",{models:[...O0($.models),...O0($.custom_models)]});if(!Array.isArray(Q)||!Q.length)throw Error("DeepSeek Harness model catalog is empty");for(let W of Q)if(!W.model||!W.efforts.length||!W.efforts.every(Q0)||!Q0(W.defaultEffort)||!W.efforts.includes(W.defaultEffort))throw Error(`Invalid DSH model/effort catalog: ${W.model}`);let H=$.model?.trim()||Q.find((W)=>W.isDefault)?.model;if(!H||!Q.some((W)=>W.model===H))throw Error("DSH default model is not in its catalog");Y.models=Q.map(({model:W,display:X,efforts:V,defaultEffort:z,isCustom:G})=>{let _=$.effort?.trim();if(_&&(!Q0(_)||!V.includes(_)))throw Error(`DSH model ${W} does not support configured effort ${_}`);return{model:W,display:X,efforts:V,defaultEffort:_?_:z,origin:G?"custom":"upstream"}}),Y.defaultModel=H,Y.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(Q){throw Y.models=[],Y.modelCatalogState={status:"failed",updatedAt:Date.now(),error:Q instanceof Error?Q.message:String(Q)},Q}},resolveSpawnModel(Q){return g1(Y).find((H)=>H.model===Q)?.model},readUsage(){return Z?G3(J,Z):Promise.resolve({kind:"balance",state:"no_credentials",windows:[]})}};return Y},setup:{commandSuffix:"deepseek-harness",hint:()=>"启用 DeepSeek Harness:发送 `deepseek-harness-setup <api_key>`,或 `deepseek-harness-setup <base_url> <api_key>`。",parseArgs($){let Z=$.trim().split(/\s+/).filter(Boolean);if(Z.length<1||Z.length>2)return{error:"用法:deepseek-harness-setup [base_url] <api_key>"};return{config:{agent:"dsh",api_key:Z.at(-1),...Z.length===2?{base_url:Z[0]}:{}}}}}})});function L3($){let Z=new URL($);if(!q1(Z.origin))throw Error("DSH GLM 需要 bigmodel.cn 或 z.ai 的 Coding Plan 端点");return Z.pathname="/api/coding/paas/v4",Z.search="",Z.hash="",Z.toString().replace(/\/$/,"")}async function uB($,Z){let J=await fetch(`${$}/models`,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(1e4)});if(!J.ok)throw Error(`GLM Coding Plan models HTTP ${J.status}`);let Y=await J.json();if(!Array.isArray(Y?.data)||!Y.data.length)throw Error("GLM Coding Plan 模型目录为空或无效");return Y.data.map((Q)=>{if(typeof Q?.id!=="string"||!Q.id)throw Error("GLM Coding Plan 模型 id 无效");return{model:Q.id,display:typeof Q.name==="string"?Q.name:Q.id}})}var rH=E(()=>{x0();A0();$0();O2();J0();B4();z3();M4();M0({kind:"dsh-glm",configSectionId:"dsh-glm",detect:{fromSettingsEnv($){let Z=I.token_sources?.glm,J=Z?.auth_token?.trim()||$.ANTHROPIC_AUTH_TOKEN?.trim(),Y=Z?.base_url?.trim()||$.ANTHROPIC_BASE_URL?.trim();return J&&Y&&q1(Y)?{api_key:J,base_url:L3(Y)}:null}},build($,Z){let J=$.api_key?.trim()||$.auth_token?.trim()||Z?.api_key?.trim()||"",Y=L3($.base_url?.trim()||Z?.base_url?.trim()||"https://open.bigmodel.cn/api/coding/paas/v4"),Q=new URL(Y).hostname.endsWith("bigmodel.cn")?"zai-coding-cn":"zai",H,W={id:"dsh-glm",kind:"dsh-glm",agent:"dsh",display:$.display?.trim()||"GLM Coding Plan",enabled:!!J,models:[],defaultModel:$.model?.trim().toLowerCase()??"",modelEnvironmentRevision(){return JSON.stringify([...H??[]].sort())},modelCatalogState:{status:J?"idle":"disabled",updatedAt:Date.now()},spawnEnv(X){if(!J)throw Error("DSH GLM Coding Plan API key is missing");let V=v2(X);if(V.LODESTAR_DSH_PROVIDER=Q,V.LODESTAR_DSH_GLM_API_KEY=J,V.LODESTAR_DSH_BASE_URL=Y,V.LODESTAR_DSH_DEFAULT_MODEL=W.defaultModel,H)V.LODESTAR_DSH_MODELS=JSON.stringify(H);if($.bin)V.LODESTAR_DSH_NODE=$.bin;return V},async refreshModels(){if(W.models=[],H=void 0,!W.enabled){W.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}W.modelCatalogState={status:"loading",updatedAt:null};try{let X=await uB(Y,J),V=[...X];for(let G of[...O0($.models),...O0($.custom_models)])if(!V.some((_)=>_.model.toLowerCase()===G.toLowerCase()))V.push({model:G,display:G});if(H=V.map((G)=>G.model),!$.model?.trim()){let G=(_)=>Number(_.match(/\d+(?:\.\d+)?/)?.[0]??-1);W.defaultModel=[...X].sort((_,K)=>G(K.model)-G(_.model))[0].model}let z=await k1({cwd:N1,env:W.spawnEnv(process.env),profile:{loadProjectMcp:!1}},"model/list");W.models=V.map((G)=>{let _=z.find((L)=>L.model===G.model),K=H3(W,$),q=_?_.efforts.filter(Q0):K.efforts,D=$.effort?.trim()||_?.defaultEffort||K.defaultEffort;return{...G,display:_?.display??G.display,efforts:q,defaultEffort:Q0(D)&&q.includes(D)?D:null,origin:X.some((L)=>L.model===G.model)?"upstream":"custom"}}),W.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(X){throw W.models=[],H=[],W.modelCatalogState={status:"failed",updatedAt:Date.now(),error:X instanceof Error?X.message:String(X)},X}},resolveSpawnModel(X){return g1(W).find((V)=>V.model===X&&!V.unavailableReason)?.model},async readUsage(){return J?V3(await K4(Y,J)):{state:"no_credentials",windows:[]}}};return W},setup:{commandSuffix:"dsh-glm",hint:()=>"DSH 可复用已配置的 GLM Coding Plan;独立账号用 `dsh-glm-setup [base_url] <api_key>`。",parseArgs($){let Z=$.trim().split(/\s+/).filter(Boolean);if(Z.length<1||Z.length>2)return{error:"用法:dsh-glm-setup [base_url] <api_key>"};try{return{config:{agent:"dsh",api_key:Z.at(-1),base_url:L3(Z.length===2?Z[0]:"https://open.bigmodel.cn/api/coding/paas/v4")}}}catch(J){return{error:J instanceof Error?J.message:String(J)}}}}})});var sH={};i$(sH,{tokenSourceSpawnRevision:()=>tH,buildTokenSourcesFromConfig:()=>D3});import{createHash as pB}from"node:crypto";function D3(){X8();let $=m5(),Z=c1().map((H)=>{let W=H.configSectionId?(I.token_sources??{})[H.configSectionId]??{}:{},X=H.detect?.fromSettingsEnv($)??null,V=bH(H.build(W,X),W);return V.spawnRevision=tH(H.kind,W,X),V}),J=Z.find((H)=>H.kind==="claude-native");if(J){let H=Z.some((W)=>W.agent==="claude"&&W.enabled&&W.kind!=="claude-native");J.enabled=!H,J.modelCatalogState={status:J.enabled?"idle":"disabled",updatedAt:Date.now()}}for(let H of Z)H8(H);let Q=Z.find((H)=>H.enabled&&I.token_sources?.[H.id]?.default===!0)??Z.find((H)=>H.enabled);if(Q)W8(Q.id);return Z.length}function tH($,Z,J){let Y=(Q)=>({agent:Q?.agent,auth:Q?.auth,base_url:Q?.base_url,auth_token:Q?.auth_token,api_key:Q?.api_key,bin:Q?.bin,model:Q?.model,effort:Q?.effort,slots:Q?.slots});return pB("sha256").update(JSON.stringify({kind:$,configured:Y(Z),detected:Y(J)})).digest("hex")}var P3=E(()=>{x0();$0();B4();M4();gH();z3();uH();A3();aH();oH();rH()});import{readFileSync as lB}from"node:fs";function iB($){return $.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function dB($,Z){let J=[`[token_source.${$}]`],Y=(Q,H)=>{if(H!==void 0)J.push(`${Q} = "${iB(H)}"`)};if(Y("agent",Z.agent),Y("display",Z.display),Y("auth",Z.auth),Y("base_url",Z.base_url),Y("auth_token",Z.auth_token),Y("api_key",Z.api_key),Y("bin",Z.bin),Y("model",Z.model),Y("effort",Z.effort),Y("models",Z.models),Y("hidden_models",Z.hidden_models),Y("custom_models",Z.custom_models),Y("slots",Z.slots),Y("usage",Z.usage),Z.default!==void 0)J.push(`default = "${Z.default}"`);return J.join(`
|
|
174
|
-
`)}function
|
|
175
|
-
`),H=!1,W=
|
|
176
|
+
默认官方 Anthropic 端点;自建中转用 \`deepseek-setup <base_url> <api_key>\`。`,parseArgs:($)=>{let Z=$.trim().split(/\s+/).filter(Boolean);if(!Z.length)return{error:"用法:`deepseek-setup <api_key>`(官方端点)或 `deepseek-setup <base_url> <api_key>`(自建中转)"};let J=Z.length>=2?Z[0]:void 0,Y=Z.length>=2?Z[1]:Z[0];return{config:{agent:"claude",...J?{base_url:J}:{},api_key:Y}}}},detect:{fromSettingsEnv($){let Z=$.ANTHROPIC_BASE_URL?.trim()??"";if(!IB(Z))return null;let J=$.ANTHROPIC_API_KEY?.trim()??"";return J?{base_url:Z,api_key:J}:null}}})});function M1($){let Z=$.toLowerCase().replace(/^~/,"");return/^(openai|deepseek|z-ai|zai-org|thudm)\//.test(Z)||/^(openrouter\/|@)/.test(Z)}var L3;var pH=S(()=>{L3=[{rank:1,lab:"Anthropic",model:"anthropic/claude-fable-5.1",effort:"max"},{rank:3,lab:"Moonshot",model:"moonshotai/kimi-k3",effort:"max"},{rank:4,lab:"Tencent",model:"tencent/hy4-preview",effort:"high"},{rank:7,lab:"Google",model:"google/gemini-3.8-flash",effort:"high"},{rank:8,lab:"SpaceXAI",model:"x-ai/grok-4.5",effort:"high"},{rank:9,lab:"Alibaba",model:"qwen/qwen3.8-max-0902",effort:"xhigh"},{rank:10,lab:"Meta",model:"meta/muse-spark-1.2",effort:"xhigh"},{rank:11,lab:"Xiaomi",model:"xiaomi/mimo-v2.5-pro",effort:"default"},{rank:12,lab:"MiniMax",model:"minimax/minimax-m3",effort:"default"},{lab:"ByteDance",model:"bytedance-seed/seed-2-1-turbo",effort:"default"},{lab:"Meituan",model:"meituan/longcat-2.0",effort:"default"}]});function m$($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function D3($){return $ instanceof Error?$.message:String($)}function lH($){return[...new Set(($??"").split(",").map((Z)=>Z.trim()).filter(Boolean))]}function G2($){return $.replace(/\[1m\]$/,"")}function j6($){let Z=new URL($);if(!["https:","http:"].includes(Z.protocol)||Z.username||Z.password||Z.search||Z.hash)throw Error("OpenRouter base_url 必须是无凭据、查询参数和 fragment 的 HTTP(S) API 根地址");return Z.pathname=Z.pathname.replace(/\/+$/,"").replace(/\/v1$/,""),Z.toString().replace(/\/+$/,"")}async function dH($,Z,J){if(!Z)throw Error("OpenRouter API key missing");let Y=await fetch(`${j6($)}/v1/${J}`,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(uB)});if(!Y.ok){let Q=await Y.text(),H="";if(Q.trim().startsWith("{"))try{let W=JSON.parse(Q);if(m$(W)&&m$(W.error)&&typeof W.error.message==="string")H=W.error.message}catch{}throw new P3(Y.status,H.replaceAll(Z,"[redacted]"))}return Y.json()}async function pB($,Z){let J=await dH($,Z,"models/user");if(!m$(J)||!Array.isArray(J.data))throw Error("OpenRouter models: data 数组缺失");let Y=[],Q=new Set;for(let H of J.data){if(!m$(H)||typeof H.id!=="string"||!H.id||typeof H.name!=="string")throw Error("OpenRouter models: 模型 id/name 无效");if(!m$(H.architecture)||!Array.isArray(H.architecture.output_modalities)||!Array.isArray(H.supported_parameters))throw Error(`OpenRouter models: ${H.id} 的模型能力缺失`);if(M1(H.id)||!H.architecture.output_modalities.includes("text")||!H.supported_parameters.includes("tools")||H.id.endsWith(":batch")||Q.has(H.id))continue;let W=m$(H.reasoning)?H.reasoning:void 0,X=W?.supported_efforts,V=X===null||X===void 0&&H.supported_parameters.includes("reasoning_effort")?["max","xhigh","high","medium","low"]:Array.isArray(X)?[...new Set(X.filter((K)=>K!=="default"&&R0(K)))]:["default"],z=L3.find((K)=>K.model===H.id),G=z?V.includes(z.effort)?z.effort:null:V[0]==="default"?"default":R0(W?.default_effort)&&V.includes(W.default_effort)?W.default_effort:null,A=c1("openrouter",H.id);Y.push({model:H.id,display:H.name,efforts:V,defaultEffort:G,context1m:A!==void 0&&A>=1e6||void 0}),Q.add(H.id)}if(!Y.length)throw Error("OpenRouter 未返回支持文本和工具调用的交互模型");return Y}function iH($){return typeof $==="number"&&Number.isFinite($)&&$>=0}async function lB($,Z){if(!Z)return{kind:"balance",state:"no_credentials",windows:[]};try{let J=await dH($,Z,"credits");if(!m$(J)||!m$(J.data))throw Error("OpenRouter credits: data 对象缺失");let{total_credits:Y,total_usage:Q}=J.data;if(!iH(Y)||!iH(Q))throw Error("OpenRouter credits: total_credits/total_usage 缺失或无效");return{kind:"balance",state:"ok",fetchedAt:Date.now(),windows:[],balance:{remaining:Y-Q,currency:"USD"}}}catch(J){let Y=D3(J);return _(`openrouter readUsage MISS: ${Y}`),{kind:"balance",state:J instanceof P3&&J.status===429?"rate_limited":"network",windows:[],reason:Y}}}var mB="https://openrouter.ai/api",uB=1e4,q3,P3;var nH=S(()=>{K0();Z0();I2();g();pH();q3={opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL"};P3=class P3 extends Error{status;constructor($,Z){super(`HTTP ${$}${Z?`: ${Z}`:""}`);this.status=$}};U0({kind:"openrouter",configSectionId:"openrouter",build($,Z){let J=$.api_key||$.auth_token||$.base_url?$:Z,Y=J?.api_key?.trim()||J?.auth_token?.trim()||"",Q=J?.base_url?.trim()||mB,H=$.model?.trim()||"",W=$.models===void 0?L3.map((V)=>V.model):lH($.models),X={id:"openrouter",kind:"openrouter",agent:"claude",display:$.display?.trim()||"OpenRouter",enabled:!!Y,models:[],defaultModel:H,modelSelection:{mode:"allowlist",modelIds:W,availableModels:[]},validateCustomModelId(V){if(M1(V))throw Error(`OpenRouter 已排除此厂商或自动路由: ${V}`);if(!V.includes("/"))throw Error("OpenRouter 模型请填写完整的 作者/模型 ID")},modelEnvironmentRevision(V){let z=X.modelSelection.availableModels.find((G)=>G2(G.model)===G2(V));if(!z||z.unavailableReason||!z.efforts.length)return"model-unavailable";return z.efforts.includes("default")?"effort-unset":"effort-level"},modelCatalogState:{status:Y?"idle":"disabled",updatedAt:Date.now()},async refreshModels(){if(X.models=[],X.modelSelection.availableModels=[],!X.enabled){X.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}X.modelCatalogState={status:"loading",updatedAt:null};try{let V=await pB(Q,Y),z=V.find((A)=>A.model===G2(H));if(H&&!z)throw Error(`OpenRouter 默认模型不在账号目录中: ${H}`);if($.effort){if(!H)throw Error("OpenRouter effort 需要同时配置 model");if(!R0($.effort)||!z.efforts.includes($.effort))throw Error(`OpenRouter 模型 ${H} 不支持 effort ${$.effort}`);z.defaultEffort=$.effort}let G=W.map((A)=>{let K=V.find((L)=>L.model===G2(A));if(!K)return{model:A,display:A,efforts:[],defaultEffort:null,unavailableReason:M1(A)?"此厂商或自动路由已被排除":"账号目录未返回该模型"};return{...K,model:A}});X.models=G,X.modelSelection.availableModels=V,X.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(V){let z=D3(V);_(`openrouter refreshModels MISS: ${z}`),X.modelCatalogState={status:"failed",updatedAt:Date.now(),error:z}}},spawnEnv(V,z){if(!Y)throw Error("OpenRouter API key missing");let G=z||H;if(!G)throw Error("OpenRouter 未选择模型,请通过 model 面板选择或配置 model");if(M1(G))throw Error(`OpenRouter 已排除此厂商或自动路由: ${G}`);let A=J$(V);A.ANTHROPIC_BASE_URL=j6(Q),A.ANTHROPIC_AUTH_TOKEN=Y,A.ANTHROPIC_API_KEY="",A.CLAUDE_CODE_NO_MODEL_FALLBACK="1",A.ANTHROPIC_MODEL=G,A.ANTHROPIC_SMALL_FAST_MODEL=G,A.CLAUDE_CODE_SUBAGENT_MODEL=G,A.ANTHROPIC_DEFAULT_FABLE_MODEL=G;for(let K of Object.values(q3))A[K]=G;for(let K of lH($.slots)){let L=K.indexOf("="),D=K.slice(0,L).trim(),q=K.slice(L+1).trim();if(L<1||!Object.hasOwn(q3,D)||!q)throw Error(`OpenRouter slots 无效: ${K}`);if(M1(q)||!X.modelSelection.availableModels.some((P)=>!P.unavailableReason&&G2(P.model)===G2(q)))throw Error(`OpenRouter slot 模型不在账号目录中: ${q}`);if(X.modelEnvironmentRevision(q)!==X.modelEnvironmentRevision(G))throw Error(`OpenRouter slot 不能混合无 effort 档位与有 effort 档位的模型: ${q}`);A[q3[D]]=q}return A},resolveSpawnModel(V){if(M1(V))throw Error(`OpenRouter 已排除此厂商或自动路由: ${V}`);return V||void 0},readUsage(){return lB(Q,Y)}};return X},setup:{commandSuffix:"openrouter",hint:($)=>`启用 ${$}:发送 \`openrouter-setup <api_key>\`,然后通过 \`model\` 选择模型。自建端点用 \`openrouter-setup <base_url> <api_key>\`。`,parseArgs($){let Z=$.trim().split(/\s+/).filter(Boolean);if(Z.length<1||Z.length>2||Z.length===1&&/^https?:\/\//i.test(Z[0]))return{error:"用法: openrouter-setup <api_key> 或 openrouter-setup <base_url> <api_key>"};try{return{config:{agent:"claude",api_key:Z[Z.length-1],...Z.length===2?{base_url:j6(Z[0])}:{}}}}catch(J){return{error:D3(J)}}}},detect:{fromSettingsEnv($){let Z=$.ANTHROPIC_BASE_URL?.trim(),J=$.ANTHROPIC_AUTH_TOKEN?.trim();if(!Z||!J)return null;try{let Y=j6(Z);if(new URL(Y).hostname!=="openrouter.ai")return null;return{base_url:Y,api_key:J}}catch{return null}}}})});var aH=S(()=>{Z0();K0();S2();Y0();B3();O4();U0({kind:"deepseek-harness",configSectionId:"deepseek-harness",build($){let Z=$.api_key?.trim()??"",J=$.base_url?.trim()||"https://api.deepseek.com",Y={id:"deepseek-harness",kind:"deepseek-harness",agent:"dsh",display:$.display?.trim()||"DeepSeek",enabled:!!Z,models:[],defaultModel:$.model?.trim()??"",modelCatalogState:{status:Z?"idle":"disabled",updatedAt:Date.now()},spawnEnv(Q){let H=c2(Q);if(!Z)throw Error("DeepSeek Harness API key is missing");if(H.DEEPSEEK_API_KEY=Z,H.DEEPSEEK_BASE_URL=J,H.LODESTAR_DSH_PROVIDER="deepseek-official",$.bin)H.LODESTAR_DSH_NODE=$.bin;return H},async refreshModels(){if(!Y.enabled){Y.models=[],Y.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}Y.modelCatalogState={status:"loading",updatedAt:null};try{let Q=await w1({cwd:k1,env:Y.spawnEnv(process.env),profile:{loadProjectMcp:!1}},"model/list",{models:[...E0($.models),...E0($.custom_models)]});if(!Array.isArray(Q)||!Q.length)throw Error("DeepSeek Harness model catalog is empty");for(let W of Q)if(!W.model||!W.efforts.length||!W.efforts.every(X0)||!X0(W.defaultEffort)||!W.efforts.includes(W.defaultEffort))throw Error(`Invalid DSH model/effort catalog: ${W.model}`);let H=$.model?.trim()||Q.find((W)=>W.isDefault)?.model;if(!H||!Q.some((W)=>W.model===H))throw Error("DSH default model is not in its catalog");Y.models=Q.map(({model:W,display:X,efforts:V,defaultEffort:z,isCustom:G})=>{let A=$.effort?.trim();if(A&&(!X0(A)||!V.includes(A)))throw Error(`DSH model ${W} does not support configured effort ${A}`);return{model:W,display:X,efforts:V,defaultEffort:A?A:z,origin:G?"custom":"upstream"}}),Y.defaultModel=H,Y.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(Q){throw Y.models=[],Y.modelCatalogState={status:"failed",updatedAt:Date.now(),error:Q instanceof Error?Q.message:String(Q)},Q}},resolveSpawnModel(Q){return p1(Y).find((H)=>H.model===Q)?.model},readUsage(){return Z?K3(J,Z):Promise.resolve({kind:"balance",state:"no_credentials",windows:[]})}};return Y},setup:{commandSuffix:"deepseek-harness",hint:()=>"启用 DeepSeek Harness:发送 `deepseek-harness-setup <api_key>`,或 `deepseek-harness-setup <base_url> <api_key>`。",parseArgs($){let Z=$.trim().split(/\s+/).filter(Boolean);if(Z.length<1||Z.length>2)return{error:"用法:deepseek-harness-setup [base_url] <api_key>"};return{config:{agent:"dsh",api_key:Z.at(-1),...Z.length===2?{base_url:Z[0]}:{}}}}}})});function j3($){let Z=new URL($);if(!P1(Z.origin))throw Error("DSH GLM 需要 bigmodel.cn 或 z.ai 的 Coding Plan 端点");return Z.pathname="/api/coding/paas/v4",Z.search="",Z.hash="",Z.toString().replace(/\/$/,"")}async function iB($,Z){let J=await fetch(`${$}/models`,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(1e4)});if(!J.ok)throw Error(`GLM Coding Plan models HTTP ${J.status}`);let Y=await J.json();if(!Array.isArray(Y?.data)||!Y.data.length)throw Error("GLM Coding Plan 模型目录为空或无效");return Y.data.map((Q)=>{if(typeof Q?.id!=="string"||!Q.id)throw Error("GLM Coding Plan 模型 id 无效");return{model:Q.id,display:typeof Q.name==="string"?Q.name:Q.id}})}var oH=S(()=>{x0();K0();Z0();S2();Y0();D4();A3();O4();U0({kind:"dsh-glm",configSectionId:"dsh-glm",detect:{fromSettingsEnv($){let Z=v.token_sources?.glm,J=Z?.auth_token?.trim()||$.ANTHROPIC_AUTH_TOKEN?.trim(),Y=Z?.base_url?.trim()||$.ANTHROPIC_BASE_URL?.trim();return J&&Y&&P1(Y)?{api_key:J,base_url:j3(Y)}:null}},build($,Z){let J=$.api_key?.trim()||$.auth_token?.trim()||Z?.api_key?.trim()||"",Y=j3($.base_url?.trim()||Z?.base_url?.trim()||"https://open.bigmodel.cn/api/coding/paas/v4"),Q=new URL(Y).hostname.endsWith("bigmodel.cn")?"zai-coding-cn":"zai",H,W={id:"dsh-glm",kind:"dsh-glm",agent:"dsh",display:$.display?.trim()||"GLM Coding Plan",enabled:!!J,models:[],defaultModel:$.model?.trim().toLowerCase()??"",modelEnvironmentRevision(){return JSON.stringify([...H??[]].sort())},modelCatalogState:{status:J?"idle":"disabled",updatedAt:Date.now()},spawnEnv(X){if(!J)throw Error("DSH GLM Coding Plan API key is missing");let V=c2(X);if(V.LODESTAR_DSH_PROVIDER=Q,V.LODESTAR_DSH_GLM_API_KEY=J,V.LODESTAR_DSH_BASE_URL=Y,V.LODESTAR_DSH_DEFAULT_MODEL=W.defaultModel,H)V.LODESTAR_DSH_MODELS=JSON.stringify(H);if($.bin)V.LODESTAR_DSH_NODE=$.bin;return V},async refreshModels(){if(W.models=[],H=void 0,!W.enabled){W.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}W.modelCatalogState={status:"loading",updatedAt:null};try{let X=await iB(Y,J),V=[...X];for(let G of[...E0($.models),...E0($.custom_models)])if(!V.some((A)=>A.model.toLowerCase()===G.toLowerCase()))V.push({model:G,display:G});if(H=V.map((G)=>G.model),!$.model?.trim()){let G=(A)=>Number(A.match(/\d+(?:\.\d+)?/)?.[0]??-1);W.defaultModel=[...X].sort((A,K)=>G(K.model)-G(A.model))[0].model}let z=await w1({cwd:k1,env:W.spawnEnv(process.env),profile:{loadProjectMcp:!1}},"model/list");W.models=V.map((G)=>{let A=z.find((q)=>q.model===G.model),K=V3(W,$),L=A?A.efforts.filter(X0):K.efforts,D=$.effort?.trim()||A?.defaultEffort||K.defaultEffort;return{...G,display:A?.display??G.display,efforts:L,defaultEffort:X0(D)&&L.includes(D)?D:null,origin:X.some((q)=>q.model===G.model)?"upstream":"custom"}}),W.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(X){throw W.models=[],H=[],W.modelCatalogState={status:"failed",updatedAt:Date.now(),error:X instanceof Error?X.message:String(X)},X}},resolveSpawnModel(X){return p1(W).find((V)=>V.model===X&&!V.unavailableReason)?.model},async readUsage(){return J?_3(await q4(Y,J)):{state:"no_credentials",windows:[]}}};return W},setup:{commandSuffix:"dsh-glm",hint:()=>"DSH 可复用已配置的 GLM Coding Plan;独立账号用 `dsh-glm-setup [base_url] <api_key>`。",parseArgs($){let Z=$.trim().split(/\s+/).filter(Boolean);if(Z.length<1||Z.length>2)return{error:"用法:dsh-glm-setup [base_url] <api_key>"};try{return{config:{agent:"dsh",api_key:Z.at(-1),base_url:j3(Z.length===2?Z[0]:"https://open.bigmodel.cn/api/coding/paas/v4")}}}catch(J){return{error:J instanceof Error?J.message:String(J)}}}}})});var tH={};n$(tH,{tokenSourceSpawnRevision:()=>rH,buildTokenSourcesFromConfig:()=>F3});import{createHash as dB}from"node:crypto";function F3(){z8();let $=l5(),Z=l1().map((H)=>{let W=H.configSectionId?(v.token_sources??{})[H.configSectionId]??{}:{},X=H.detect?.fromSettingsEnv($)??null,V=CH(H.build(W,X),W);return V.spawnRevision=rH(H.kind,W,X),V}),J=Z.find((H)=>H.kind==="claude-native");if(J){let H=Z.some((W)=>W.agent==="claude"&&W.enabled&&W.kind!=="claude-native");J.enabled=!H,J.modelCatalogState={status:J.enabled?"idle":"disabled",updatedAt:Date.now()}}for(let H of Z)X8(H);let Q=Z.find((H)=>H.enabled&&v.token_sources?.[H.id]?.default===!0)??Z.find((H)=>H.enabled);if(Q)V8(Q.id);return Z.length}function rH($,Z,J){let Y=(Q)=>({agent:Q?.agent,auth:Q?.auth,base_url:Q?.base_url,auth_token:Q?.auth_token,api_key:Q?.api_key,bin:Q?.bin,model:Q?.model,effort:Q?.effort,slots:Q?.slots});return dB("sha256").update(JSON.stringify({kind:$,configured:Y(Z),detected:Y(J)})).digest("hex")}var M3=S(()=>{x0();Z0();D4();O4();IH();A3();mH();B3();nH();aH();oH()});import{readFileSync as nB}from"node:fs";function aB($){return $.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function oB($,Z){let J=[`[token_source.${$}]`],Y=(Q,H)=>{if(H!==void 0)J.push(`${Q} = "${aB(H)}"`)};if(Y("agent",Z.agent),Y("display",Z.display),Y("auth",Z.auth),Y("base_url",Z.base_url),Y("auth_token",Z.auth_token),Y("api_key",Z.api_key),Y("bin",Z.bin),Y("model",Z.model),Y("effort",Z.effort),Y("models",Z.models),Y("hidden_models",Z.hidden_models),Y("custom_models",Z.custom_models),Y("slots",Z.slots),Y("usage",Z.usage),Z.default!==void 0)J.push(`default = "${Z.default}"`);return J.join(`
|
|
177
|
+
`)}function rB($,Z){let J=nB(M0,"utf8"),Y=`[token_source.${$}]`,Q=J.split(`
|
|
178
|
+
`),H=!1,W=i4().token_sources[$]??{},X=[];for(let A of Q){let K=A.match(/^\s*(\[[^\]]+\])\s*(?:#.*)?$/)?.[1];if(K)H=K===Y;if(!H)X.push(A)}let V={...W},z={...Z};for(let A of Object.keys(z))if(z[A]!==void 0)V[A]=z[A];let G=V;while(X.length&&X[X.length-1]==="")X.pop();d0(M0,X.join(`
|
|
176
179
|
`)+`
|
|
177
180
|
|
|
178
|
-
`+
|
|
179
|
-
`)}function
|
|
180
|
-
⚠️ kill 状态卡片终态写入失败: ${
|
|
181
|
-
请重新发送 model 打开面板。`;if(!await w($.chatId,L))A(`model-custom: visible fallback send MISS (${q})`);return!1},V=(K)=>X(t1(!1,Q,K),`❌ ${Q?`模型 ${Q}`:"模型名"} 未加入:${K}。`);if(!H||!H.enabled)return await V("账号不可用"),!0;if(!Q)return await V("模型名为空"),!0;if(H.models.some((K)=>K.model.toLowerCase()===Q.toLowerCase()))return await X(t1(!1,Q,"已在列表中"),`ℹ️ 模型 ${Q} 已在列表中,未重复加入。`),!0;try{await JW(H.id,Q)}catch(K){return A(`model-custom: config/refresh MISS (${U(K)})`),await V(`配置写入或模型刷新失败:${U(K)}`),!0}A(`model-custom: ${H.id} 补录 ${Q} by ${J}(记录已持久化)`);for(let K of t0.all)for(let[q,D]of K.modelPanels)if(D.sourceId===H.id&&(K!==$||q!==Y.panelId))K.modelPanels.delete(q);let z=p(H.id);if(!z||z.modelCatalogState?.status!=="ready")return await V(z?.modelCatalogState?.error??"刷新后的账号目录不可用"),!0;let G=U3($,z),_=G.find((K)=>K.model===Q);if(!_)return await V("补录已保存,但刷新后的模型列表未返回该项"),!0;if($.modelPanels.set(Y.panelId,{models:G,messageId:Y.cardMessageId}),_.unavailableReason||!_.efforts.length)return await X(t1(!0,Q,`**MISS**:${_.unavailableReason??"后端未确认 effort"}。记录已保存,可在模型面板删除。`),`模型 ${Q} 已补录,能力尚未确认。`),!0;if(_.efforts.length===1){let K=await $.onModelEffortSelect(_.model,_.efforts[0].effort,Y.panelId,J,_.provider);return await X(K.ok?a9({sessionName:$.sessionName,provider:_.provider,model:_.model,effort:_.efforts[0].effort,scope:BW($,_.provider??"codex")}):t1(!0,Q,K.message),K.message),!0}return await X(n9({sessionName:$.sessionName,panelId:Y.panelId,currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:_}),`✅ 模型 ${Q} 已补录成功。`),!0}async function KW($,Z=""){let J=Z.trim(),Y=$.modelCustomPrompt;if(!J||!Y||Y.panelId!==J)return{ok:!1,message:"此补录面板已失效",card:d9($.sessionName,"stale")};return $.modelCustomPrompt=null,{ok:!0,message:"已取消",card:d9($.sessionName)}}function Hq($,Z){return e0(Z?.provider)?Z.provider:C1($)}function BW($,Z){if($.currentTurn)return"当前 turn 不变,后续新 turn 使用。";if($.proc?.isAlive()&&$.proc.provider===Z)return Z==="codex"?"Codex 需重启进程生效(发 restart)。":"下一轮开始使用。";return`下次启动 ${$$(Z)} 时使用。`}async function qW($,Z,J="",Y="",Q=null){let H=Z.trim();if(!H)return await T($.chatId,`❌ ${"模型为空"}`),{ok:!1,message:"模型为空"};let W=Hq(H,Q),X=$.modelPanels.get(J.trim())?.models.find((V)=>V.model===H&&(V.provider??"codex")===W);if(!X)return{ok:!1,message:"模型不在当前选项中,请重新发送 model"};if($.modelPanels.get(J.trim())?.mode==="add")return{ok:!1,message:"请先将模型添加到可选列表"};if(X.unavailableReason)return{ok:!1,message:X.unavailableReason};if(X.enabled===!1)return{ok:!1,message:`${X.displayName} 未配置,请先点「启用」`};if(X.efforts.length===0)return{ok:!1,message:"模型未返回 effort"};if(X.efforts.length===1)return T3($,H,X.efforts[0].effort,J,Y,W);return{ok:!0,message:"",card:P5({sessionName:$.sessionName,panelId:J.trim(),currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:X})}}async function T3($,Z,J,Y="",Q="",H=""){let W=Z.trim(),X=J.trim();if(!W)return{ok:!1,message:"模型为空"};let V=Y.trim(),z=$.modelPanels.get(V),G=e0(H)?H:z?.models.find((M)=>M.model===W)?.provider??C1(W);if(G==="dsh"){if(!Q0(X))return{ok:!1,message:"DSH reasoning effort 无效"}}else if(G==="claude"){if(!F0(X))return{ok:!1,message:"Claude reasoning effort 无效"}}else if(!v0(X))return{ok:!1,message:"Codex reasoning effort 无效"};let _=X,K=z?.models.find((M)=>M.model===W&&(M.provider??"codex")===G);if(!K||!K.efforts.some((M)=>M.effort===_))return{ok:!1,message:`${$$(G)} · ${W}/${_} 不在选项中`};let q=p(K.sourceId);if(q?.modelCatalogState){if(!q.enabled||q.modelCatalogState.status!=="ready")return{ok:!1,message:`模型目录 MISS:${q.modelCatalogState.error??q.modelCatalogState.status}`};if(!q.models.some((M)=>M.model===W&&M.efforts.includes(_)))return{ok:!1,message:"模型或 effort 已不在账号目录中,请重新发送 model"}}let D=!!K.sourceId&&$.currentTokenSource()?.id!==K.sourceId,L=!$.processSourceMatches(q,W)||!!q?.modelEnvironmentRevision&&q.modelEnvironmentRevision($.currentModelLabel()??"")!==q.modelEnvironmentRevision(W);if($.currentProvider()===G&&!D&&$.currentModelLabel()===W&&$.currentEffortLabel()===_)return $.modelPanels.delete(V),{ok:!0,message:`当前已是 ${$$(G)} · ${W} / ${_}`,card:i9({sessionName:$.sessionName,provider:G,model:W,effort:_,scope:"当前已是此设置,无需变更。"})};if($.proc?.isAlive()&&$.proc.provider!==G&&($.currentTurn||$.openingTurn||$.pendingUserMessageCount>0||$.pendingMidTurnMsgs.length>0))return{ok:!1,message:`当前 ${$.backendLabel($.proc.provider)} turn 正在执行或排队;请等结束或 stop 后再切换到 ${$$(G)}`};let F=$.currentModelLabel()!==W||D,j=!!($.currentTurn||$.openingTurn||$.pendingUserMessageCount>0||$.pendingMidTurnMsgs.length>0);if(L&&$.proc?.isAlive()&&j)return{ok:!1,message:"新模型需要更新进程配置,请等当前任务结束后再选择"};if(G==="claude"&&$.proc?.isAlive()&&$.proc.provider==="claude"&&F&&j)return{ok:!1,message:"当前 Claude turn 正在执行或排队;Claude 模型 profile 通过 env 生效,请等结束或 stop 后再切换"};try{if($.proc?.isAlive()&&$.proc.provider===G&&!D&&!L){let C=K.sourceId?p(K.sourceId)?.resolveSpawnModel(W)??W:W;await XJ($.proc.setModelSettings(C,_),20000,"thread/settings/update")}await $.applyModelSelectionUnlocked(G,W,_,K.sourceId);let M=BW($,G);return $.modelPanels.delete(V),{ok:!0,message:`已选择 ${$$(G)} · ${W} / ${_}`,card:i9({sessionName:$.sessionName,provider:G,model:W,effort:_,scope:M})}}catch(M){let C=`模型切换失败: ${U(M)}`;return A(`session "${$.sessionName}": set model settings failed: ${U(M)}`),await T($.chatId,`❌ ${C}`),{ok:!1,message:C}}}var R3=20;var LW=E(()=>{A0();E3();$0();j3();s$();A0();u0();X1();s();g()});import{createHash as Xq}from"node:crypto";function Vq($,Z){return`agent:${Buffer.from(`${$}\x00${Z}`,"utf8").toString("base64url")}`}function j1(){return zq(A$())}function zq($){let Z=[],J=[];for(let Y of $)Gq(Y,Z,J);return{catalogGeneration:Xq("sha256").update(JSON.stringify({identities:Z,sourceFailures:J})).digest("hex").slice(0,16),identities:Z,sourceFailures:J}}function Gq($,Z,J){let Y=$.modelCatalogState?.status??(!$.enabled?"disabled":$.models.length>0?"ready":"idle");if(!$.enabled)J.push({tokenSourceId:$.id,display:$.display,status:"disabled",reason:"账号未启用"});else if(Y==="loading"||Y==="idle")J.push({tokenSourceId:$.id,display:$.display,status:"loading",reason:"模型目录正在刷新"});else if(Y==="failed")J.push({tokenSourceId:$.id,display:$.display,status:"failed",reason:$.modelCatalogState?.error??"模型目录刷新失败"});else if($.models.length===0)J.push({tokenSourceId:$.id,display:$.display,status:"models_miss",reason:"模型目录为空"});for(let Q of $.models)Z.push(Aq($,Q,Y))}function Aq($,Z,J){let Y="ready",Q;if(!$.enabled)Y="source_disabled",Q="所属 Token Source 未启用";else if(J==="loading"||J==="idle")Y="catalog_loading",Q="模型目录正在刷新";else if(J==="failed")Y="catalog_failed",Q=$.modelCatalogState?.error??"模型目录刷新失败";else if(Z.unavailableReason||!Z.efforts.length)Y="model_unavailable",Q=Z.unavailableReason??"effort MISS:上游未声明该后端支持的推理档位";return{id:Vq($.id,Z.model),displayName:`${$.display} · ${Z.display}`,tokenSourceId:$.id,tokenSourceDisplay:$.display,provider:$.agent,model:Z.model,modelDisplay:Z.display,defaultEffort:Z.defaultEffort,supportedEfforts:[...Z.efforts],sourceDefault:DW($.defaultModel)===DW(Z.model),status:Y,...Q?{reason:Q}:{},spawnRevision:$.spawnRevision}}function DW($){return $.replace(/\[1m\]$/i,"").toLowerCase()}var j6=E(()=>{$0()});import{randomUUID as _q}from"node:crypto";async function PW($,Z){if(!Z.trim()){await w($.chatId,"❌ 无法确认操作者身份,未打开 agents 面板");return}MW(),await m1();let J=`agents_${_q()}`;if(U4.set(J,{ownerOpenId:Z,page:0,createdAt:Date.now()}),!await d($.chatId,FW(J)))await w($.chatId,"❌ agents 面板发送失败")}function jW($,Z,J){let Y=qq($,J),Q=Number(Z);if(!Number.isInteger(Q))return Lq("无效页码");let H=Bq();return Y.page=Math.max(0,Math.min(H-1,Q)),Y.createdAt=Date.now(),{ok:!0,message:"已更新",card:FW($)}}function FW($){let Z=U4.get($);if(!Z)throw Error("Agent 身份面板已过期");let J=j1(),Y=Math.max(1,Math.ceil(J.identities.length/F6));Z.page=Math.min(Z.page,Y-1);let Q=Z.page*F6;return y5({panelId:$,page:Z.page,totalPages:Y,catalog:J.identities.slice(Q,Q+F6),failures:J.sourceFailures})}function Bq(){return Math.max(1,Math.ceil(j1().identities.length/F6))}function qq($,Z){MW();let J=U4.get($);if(!J)throw Error("Agent 身份面板已过期,请重新发送 agents");if(!J.ownerOpenId||!Z||J.ownerOpenId!==Z)throw Error("只有打开该面板的用户可操作");return J}function Lq($){return{ok:!1,message:$,card:v$({title:"agents",message:$,ok:!1})}}function MW(){let $=Date.now()-Kq;for(let[Z,J]of U4)if(J.createdAt<$)U4.delete(Z)}var F6=8,Kq=1800000,U4;var RW=E(()=>{u0();s();j6();$0();U4=new Map});var x3={};i$(x3,{withTasklistLifecycleLock:()=>O6,tasklistNameForProject:()=>U6,reconcileTasklistDeletions:()=>Fq,isTasklistAlreadyDeletedError:()=>UW,getTasklistBinding:()=>j$,enableTasklist:()=>N3,deleteTasklistRemoteIdempotently:()=>OW,deleteTasklist:()=>S3});import{existsSync as Pq,readFileSync as jq}from"node:fs";function U6($){return`${$}[lodestar]`}function j$($){let Z=P$.get($);return Z?X2(Z):null}async function O6($,Z){let J=M6.get($)??Promise.resolve(),Y,Q=new Promise((W)=>{Y=W}),H=J.catch(()=>{}).then(()=>Q);M6.set($,H),await J.catch(()=>{});try{return await Z()}finally{if(Y(),M6.get($)===H)M6.delete($)}}function UW($){if($&&typeof $==="object"&&$.code===1470404)return!0;let Z=$ instanceof Error?$.message:String($);return/\bcode=1470404\b/.test(Z)}async function OW($,Z=A8){try{return await Z($),"deleted"}catch(J){if(UW(J))return"already_deleted";throw J}}async function N3($,Z){return await O6($,async()=>{let J=j$($);if(J?.deleting)throw Error(`tasklist deletion is pending for ${$}`);if(J)return J;let Y=U6($);if(Y.length>100)throw Error(`tasklist name is too long (${Y.length}/100): ${Y}`);let Q=await z8(Z),H=await G8(Y,Q),W={guid:H.guid,name:H.name,url:H.url,projectName:$,ownerOpenId:Q,createdAt:H.createdAt};return R6($,W),X2(W)})}async function S3($,Z){return await O6($,async()=>{let J=j$($);if(!J)throw Error("tasklist is not enabled");if(J.guid!==Z)throw Error(`tasklist binding changed: current=${J.guid} requested=${Z}`);if(!J.deleting)J.deleting={requestedAt:new Date().toISOString(),attempts:0},R6($,J);return await TW($,Z)})}async function TW($,Z){let J=j$($);if(!J||J.guid!==Z)throw Error(`tasklist binding changed during deletion: ${$}`);J.deleting??={requestedAt:new Date().toISOString(),attempts:0},J.deleting.attempts++,J.deleting.lastAttemptAt=new Date().toISOString(),J.deleting.lastError=void 0,R6($,J);try{if(await OW(Z)==="already_deleted")A(`tasklist: ${$} remote list ${Z} already deleted; finishing tombstone`);let Q=new Map(P$);return Q.delete($),EW(Q),P$.delete($),X2(J)}catch(Y){let Q=j$($);if(Q?.guid===Z&&Q.deleting)Q.deleting.lastError=Y instanceof Error?Y.message:String(Y),R6($,Q);throw Y}}async function Fq(){let $=[...P$.entries()].filter(([,J])=>!!J.deleting).map(([J,Y])=>({projectName:J,guid:Y.guid})),Z=[];for(let J of $)try{await O6(J.projectName,()=>TW(J.projectName,J.guid)),A(`tasklist: reconciled pending deletion for ${J.projectName}`)}catch(Y){Z.push(`${J.projectName}: ${Y instanceof Error?Y.message:String(Y)}`)}if(Z.length)throw Error(`tasklist deletion reconcile failed: ${Z.join("; ")}`)}function Mq(){if(!Pq(C4))return;try{let $=JSON.parse(jq(C4,"utf8"));if(!$||typeof $!=="object")return;for(let[Z,J]of Object.entries($)){if(!J||typeof J!=="object")continue;let Y=J;if(typeof Y.guid!=="string"||!Y.guid||typeof Y.name!=="string"||!Y.name)continue;let Q={guid:Y.guid,name:Y.name,url:typeof Y.url==="string"?Y.url:"",projectName:Z,ownerOpenId:typeof Y.ownerOpenId==="string"?Y.ownerOpenId:"",createdAt:typeof Y.createdAt==="string"?Y.createdAt:void 0,deleting:Rq(Y.deleting)};P$.set(Z,Q)}A(`tasklist: loaded ${P$.size} project bindings`)}catch($){A(`tasklist: load map failed: ${$}`)}}function Rq($){if(!$||typeof $!=="object")return;let Z=$;if(typeof Z.requestedAt!=="string"||!Z.requestedAt)return;return{requestedAt:Z.requestedAt,lastAttemptAt:typeof Z.lastAttemptAt==="string"?Z.lastAttemptAt:void 0,attempts:typeof Z.attempts==="number"&&Number.isFinite(Z.attempts)&&Z.attempts>=0?Math.floor(Z.attempts):0,lastError:typeof Z.lastError==="string"?Z.lastError:void 0}}function R6($,Z){let J=new Map(P$);J.set($,X2(Z)),EW(J),P$.set($,X2(Z))}function EW($=P$){let Z={};for(let[J,Y]of $)Z[J]=X2(Y);G0(C4,Z)}function X2($){return JSON.parse(JSON.stringify($))}var P$,M6;var k3=E(()=>{J0();s();g();d0();P$=new Map,M6=new Map;Mq()});function c$($,Z,J=!1){let Y=$.worktreeProjectName();return k5({projectName:Y,tasklistName:U6(Y),binding:j$(Y),notice:Z,confirmDelete:J})}async function NW($){if(!await d($.chatId,c$($)))await w($.chatId,"❌ task 面板发送失败")}async function SW($){let Z=$.worktreeProjectName();try{let J=j$(Z),Y=await N3(Z,$.chatId),Q=J?"已启用":`已启用 ${Y.name}`;return{ok:!0,message:Q,card:c$($,{type:"success",content:`✅ ${Q}`})}}catch(J){let Y=`启用失败: ${U(J)}`;return A(`session "${$.sessionName}": tasklist enable failed: ${U(J)}`),{ok:!1,message:Y,card:c$($,{type:"error",content:`❌ ${Y}`})}}}function xW($,Z){let J=$.worktreeProjectName(),Y=j$(J),Q=Z.trim();if(!Y)return{ok:!1,message:"未启用",card:c$($,{type:"error",content:"❌ 未启用"})};if(Y.guid!==Q)return{ok:!1,message:"清单绑定已变化",card:c$($,{type:"error",content:"❌ 清单绑定已变化,请重新打开 task 面板"})};return{ok:!0,message:"请再次确认删除",card:c$($,{type:"error",content:"⚠️ 删除会删除所有清单内任务"},!0)}}async function kW($,Z){let J=$.worktreeProjectName(),Y=Z.trim();try{let H=`已删除 ${(await S3(J,Y)).name}`;return{ok:!0,message:H,card:c$($,{type:"success",content:`✅ ${H}`})}}catch(Q){let H=`删除失败: ${U(Q)}`;return A(`session "${$.sessionName}": tasklist delete failed: ${U(Q)}`),{ok:!1,message:H,card:c$($,{type:"error",content:`❌ ${H}`})}}}var CW=E(()=>{u0();s();g();k3()});var C3,b3,bW,yW,wW;var fW=E(()=>{C3=["- 以 `[file: /abs/path]` 开头的文本表示该路径上挂着一个文件,相关时去读它。","- 在回复任意位置,独占一行写 `[[send: /abs/path]]` 即可把该文件作为单独一条消息送出。只在用户主动要文件、或你要交付最终产物时才发。","- 飞书单个出站文件不能超过 30 MB(30 × 1024 × 1024 字节)。交付前检查大小;超限先压缩或分卷,确保每个文件都不超过上限,再发送。"],b3=["- 判断是否该发文件:导出附件/数据集、用户明确要文件或下载物时,应先写到本机绝对路径,再用独占一行的 `[[send: /abs/path]]` 发给用户;短总结、普通说明、无需留存的正文答复不要为了发文件而发文件。","- 使用图片生成工具生成图片后,不要再补充说明文字或 `[[send: ...]]`;Lodestar 会自动展示图片和提示词,支持时放进折叠面板,无法嵌入时单独发送。若你用脚本或文件编辑生成图片,按上一条用 `[[send: /abs/path]]` 发出。","- 每次调用 Bash / shell 命令时,第一行都必须写 shell 注释 `# desc: <一句中文说明>`,再写真正命令。这个注释只给 Lodestar 卡片做摘要,不要依赖它改变命令行为。"],bW=[...C3,"- 当你有问题需要澄清时,使用 request_user_input 工具向用户提问;不要把多选题写成文本。",...b3].join(`
|
|
182
|
-
`),
|
|
183
|
-
`),
|
|
184
|
-
`)});import{execFileSync as
|
|
185
|
-
`).map((H)=>H.trim()).filter(Boolean).filter((H)=>H.startsWith(
|
|
186
|
-
`).filter(Boolean);K.statusLine=D[0]?.startsWith("## ")?D[0].slice(3):null,K.dirtyCount=D.filter((
|
|
181
|
+
`+oB($,G)+`
|
|
182
|
+
`)}function F6($){let Z=sH.then($);return sH=Z.then(()=>{},()=>{}),Z}async function M6($,Z){rB($,Z),ZJ(),F3(),await p2()}function eH($,Z){return F6(()=>M6($,Z))}function $W($,Z,J){return F6(async()=>{let Y=p($);if(!Y?.enabled||!Y.modelSelection)throw Error("此账号不支持维护可选模型列表");let Q=Y.modelSelection.modelIds.filter((A)=>Y.models.find((K)=>K.model===A)?.origin!=="custom");if(J==="add"){if(Y.modelCatalogState?.status!=="ready")throw Error(Y.modelCatalogState?.error??"模型目录未就绪");let A=Y.modelSelection.availableModels.find((K)=>K.model===Z);if(A?.origin==="custom")throw Error("补录模型请使用删除操作");if(!A||Y.modelSelection.mode!=="catalog"&&(A.unavailableReason||!A.efforts.length))throw Error("模型不在允许添加的账号目录中");if(Q.includes(Z))throw Error("模型已在可选列表中")}else if(!Q.includes(Z))throw Error("模型已不在可选列表中");let H=J==="add"?[...Q,Z]:Q.filter((A)=>A!==Z),W=v.token_sources[$],X=Y.modelSelection.mode==="catalog",V=E0(W?.hidden_models),z=X?{hidden_models:(J==="remove"?[...new Set([...V,Z])]:V.filter((A)=>A!==Z)).join(",")}:{models:H.join(",")};await M6($,z);let G=p($);if(G?.modelCatalogState?.status!=="ready")throw Error(`配置已保存,但目录刷新失败:${G?.modelCatalogState?.error??"MISS"}`)})}function ZW($,Z){return F6(async()=>{let J=Z.trim();if(!J||J.length>256||/[\s,`<>\\\u0000-\u001f]/.test(J))throw Error("模型 ID 无效,请只填写一个完整模型名");let Y=p($);if(!Y?.enabled)throw Error("账号不可用");if(Y.validateCustomModelId?.(J),(Y.modelSelection?.availableModels??Y.models).some((X)=>X.model.toLowerCase()===J.toLowerCase()))throw Error("模型已在目录或补录记录中;隐藏项请使用“显示”");if(Y.modelCatalogState?.status!=="ready")throw Error(Y.modelCatalogState?.error??"模型目录未就绪");if(Y.verifyModel){let X=await Y.verifyModel(J);if(X!=="exists")throw Error(X==="not_found"?"端点确认不存在":"无法校验模型:端点无响应或凭据问题")}let H=v.token_sources[$];await M6($,{custom_models:[...E0(H?.custom_models),J].join(",")});let W=p($);if(W?.modelCatalogState?.status!=="ready")throw Error(`补录已保存,但目录刷新失败:${W?.modelCatalogState?.error??"MISS"}`)})}function JW($,Z){return F6(async()=>{let J=p($),Y=J?.modelSelection?.availableModels.find((V)=>V.model===Z);if(!J?.enabled||Y?.origin!=="custom")throw Error("此模型不是补录项,请使用隐藏操作");let Q=v.token_sources[$]??{},H=(V)=>V?.trim().replace(/\[1m\]$/,"")===Z.replace(/\[1m\]$/,""),W={custom_models:E0(Q.custom_models).filter((V)=>!H(V)).join(","),hidden_models:E0(Q.hidden_models).filter((V)=>!H(V)).join(","),...Q.models!==void 0?{models:E0(Q.models).filter((V)=>!H(V)).join(",")}:{},...H(Q.model)?{model:"",effort:""}:{},...Q.slots?{slots:Q.slots.split(",").filter((V)=>!H(V.slice(V.indexOf("=")+1))).join(",")}:{}};await M6($,W);let X=p($);if(X?.modelCatalogState?.status!=="ready")throw Error(`补录已删除,但目录刷新失败:${X?.modelCatalogState?.error??"MISS"}`)})}var sH;var R3=S(()=>{Y0();x0();M3();Z0();n0();O4();sH=Promise.resolve()});var U3={};n$(U3,{runTokenSourceSetup:()=>sB,onTokenSourceEnable:()=>tB});async function tB($,Z){let J=p(Z);if(!J){await E($.chatId,`❌ 未知 token source: ${Z}`);return}if(J.enabled){await E($.chatId,`${J.display} 已启用,发 \`model\` 选择。`);return}let Y=l1().find((Q)=>Q.setup?.commandSuffix===Z||Q.configSectionId===Z);if(Y?.setup)await E($.chatId,Y.setup.hint(J.display));else if(J.kind==="codex-subscription")await E($.chatId,`${J.display} 需要 ChatGPT 登录:在服务器执行 \`codex login\`,完成后按当前服务管理方式重启 daemon,或重发 \`model\` 刷新。`);else if(J.kind==="claude-native")await E($.chatId,`${J.display} 直接使用本机 Claude Code 配置,无需单独启用。`)}async function sB($,Z,J){let Y=l1().find((H)=>H.setup?.commandSuffix===Z);if(!Y?.setup||!Y.configSectionId){await E($.chatId,`❌ 未知或不可配置的 source: ${Z}`);return}let Q=Y.setup.parseArgs(J);if("error"in Q){await E($.chatId,Q.error);return}try{await eH(Y.configSectionId,Q.config);let H=p(Y.configSectionId);if(H?.modelCatalogState?.status==="failed"){await E($.chatId,`❌ ${H.display} 配置已保存,但模型目录未就绪:${H.modelCatalogState.error??"MISS"}`);return}await E($.chatId,`✅ ${H?.display??Z} 已启用。发 \`model\` 重新选择。`)}catch(H){await E($.chatId,`❌ 启用失败: ${H?.message??H}`)}}var O3=S(()=>{e();Z0();R3()});async function YW($,Z,J=""){let Y=Z.trim().match(/^(?:wt|worktree)(?:\s+(.+))?$/i);if(Y)return await $.runWorktreeCommand((Y[1]??"").trim(),J),!0;if(Z.trim().match(/^btw$/i))return await $.runBtwCommand(J),!0;if(Z.trim().match(/^bye$/i))return await $.runByeCommand(),!0;if(Z.trim().match(/^(?:fk|fork)$/i))return await $.showForkList(J),!0;if(Z.trim().match(/^(?:bk|back)$/i))return await $.showBackList(J),!0;if(Z.trim().toLowerCase()==="task")return await $.showTasklistPanel(),!0;if(Z.trim().match(/^(?:agents|agent)$/i))return await $.showAgentIdentityPanel(J),!0;let Q=Z.trim().match(/^([\w-]+)-setup(?:\s+([\s\S]+))?$/i);if(Q){let{runTokenSourceSetup:W}=await Promise.resolve().then(() => (O3(),U3));return await W($,Q[1].trim().toLowerCase(),(Q[2]??"").trim()),!0}let H=eB.get(Z.trim().toLowerCase());if(!H)return!1;switch(H){case"model":return await $.showModelPanel(),!0;case"compact":return await $.runCompactCommand(),!0;case"hi":{let X=!$.isRunning(),V=$.backendLabel(),z=X?await $.openStatusCard("hi",$.withModel(`\uD83D\uDE80 启动 ${V}`)):null,G=$.withModel(`\uD83D\uDE80 启动 ${V}`);if(!(X?await $.start({announce:!z,onStatus:(K)=>{G=K,$.setStatusCard(z,K)}}):!0))return await $.closeStatusCard(z,G.startsWith("❌")?G:"❌ 启动失败"),!0;if(z)return await $.replaceStatusCardWithConsole(z,$.withModel($.withWorktreeInstructionNotice(`✅ ${$.backendLabel()} 已就绪`))),!0;if(X)await $.closeStatusCard(z,$.withModel($.withWorktreeInstructionNotice(`✅ ${$.backendLabel()} 已就绪`)))}return await $.showConsole(),!0;case"stop":if(await $.cancelAgentRuns("stop command"),$.clearStaleIdleQueueState("stop"),$.clearMultiMsgBuffer("stop command"),!$.currentTurn&&$.pendingUserMessageCount===0&&$.pendingMidTurnMsgs.length===0){let X=await $.openStatusCard("stop","⚪ 当前没有正在执行的 turn","grey");if(X)await $.closeStatusCard(X,"⚪ 无正在执行的 turn");else await E($.chatId,"⚪ 当前没有正在执行的 turn");return!0}_(`session "${$.sessionName}": stop command — interrupt + drop count=${$.pendingUserMessageCount} midBuffer=${$.pendingMidTurnMsgs.length}`);let W=new Set;for(let[X,V]of[...$.pendingReactionIds.entries(),...$.currentBatchReactionIds.entries()]){if(V)T0(X,V);b0(X,"CrossMark"),W.add(X)}for(let X of $.pendingMidTurnMsgs)if(X.msgId&&!W.has(X.msgId))b0(X.msgId,"CrossMark");return $.pendingUserMessageCount=0,$.pendingMidTurnMsgs=[],$.pendingTurnInputs=[],$.lastUserOpenId="",$.pendingReactionIds=new Map,$.currentBatchReactionIds=new Map,$.userInterrupted=!0,$.interrupt(),await $.closeTurnCard("\uD83D\uDED1 打断"),!0;case"kill":{let X=$.isRunning(),V=$.backendLabel($.proc?.provider??$.currentProvider()),z=X?`\uD83D\uDED1 停止 ${V}`:"⚪ session 当前未运行",G=await $.openStatusCard("kill",z,X?"red":"grey"),A=null,K=X?`✅ ${V} 已终止`:`⚪ ${V} 未运行`;try{await $.stop("已终止",{announce:!G,onStatus:(L)=>{$.setStatusCard(G,L)}})}catch(L){A=L,K=$.isRunning()?`❌ ${V} 未确认终止: ${O(L)};会话已阻断,请重试 kill/restart 或等待旧进程退出`:`❌ ${V} 停止收尾失败: ${O(L)}`}finally{try{await $.closeStatusCard(G,K)}catch(L){_(`session "${$.sessionName}": kill status card close failed: ${O(L)}`),await w($.chatId,`${K}
|
|
183
|
+
⚠️ kill 状态卡片终态写入失败: ${O(L)}`)}}if(A&&!G)await w($.chatId,K)}return!0;case"restart":if(!$.isRunning())return await $.showResumeList(J),!0;{let X=$.lastSessionId?q0($.lastSessionId):"",V=$.backendLabel($.proc?.provider??$.currentProvider()),z=$.isRunning()?$.withModel(`\uD83D\uDD01 重启 ${V}`):X?$.withModel(`\uD83D\uDD01 恢复上一会话 thread=${X}`):$.withModel(`\uD83D\uDD01 启动 ${V}`),G=await $.openStatusCard("restart",z),A=z,K=await $.restart(!0,{announce:!G,onStatus:(D)=>{A=D,$.setStatusCard(G,D)}}),L=K?A.startsWith("✅")?A:$.withWorktreeInstructionNotice(X?"✅ 已恢复上一会话":`✅ ${$.backendLabel()} 已就绪`):A.startsWith("❌")?A:"❌ 重启失败";await $.closeStatusCard(G,K?$.withModel(L):L)}return!0;case"clear":if(!$.isRunning()){$.status="stopped",$.opts.onLifecycleChange?.();let X=await $.openStatusCard("clear","⚪ session 当前未运行","grey");if(X)await $.closeStatusCard(X,`⚪ ${$.backendLabel()} 未运行,clear 无效`);else await E($.chatId,`⚪ session "${$.sessionName}" 当前未运行,clear 无效;用 \`hi\` 启动或 \`restart\` 恢复上一会话`);return!0}{let X=await $.openStatusCard("clear","\uD83E\uDDF9 清空并启动新会话","orange"),V="\uD83E\uDDF9 清空并启动新会话",z=await $.restart(!1,{announce:!X,onStatus:(G)=>{V=G,$.setStatusCard(X,G)}});await $.closeStatusCard(X,z?$.withModel($.withWorktreeInstructionNotice("✅ 已清空并启动新会话")):V.startsWith("❌")?V:"❌ 清空失败")}return!0}}var eB;var QW=S(()=>{e();g();eB=new Map([["hi","hi"],["stop","stop"],["st","stop"],["kill","kill"],["kl","kill"],["restart","restart"],["rs","restart"],["clear","clear"],["cl","clear"],["compact","compact"],["cm","compact"],["model","model"],["md","model"]])});function JL($){let Z=!1,J=()=>{},Y=()=>{},Q=$.sessionId,H=()=>{$.off("context_compacted",V),$.off("exit",z),$.off("error",G)},W=(K)=>{if(Z)return;Z=!0,H(),J(K)},X=(K)=>{if(Z)return;Z=!0,H(),Y(K)},V=(K)=>{if(K.phase==="start")return;if(K.threadId&&Q&&K.threadId!==Q)return;W(K)},z=()=>X(Error(`${$.provider} process exited before context compaction completed`)),G=(K)=>X(K instanceof Error?K:Error(String(K))),A=new Promise((K,L)=>{J=K,Y=L});return $.on("context_compacted",V),$.once("exit",z),$.once("error",G),{promise:A,cancel(){if(Z)return;Z=!0,H()}}}function YL($,Z){let J=[],Y=new Set,Q=(X,V)=>{let z=V.threadId??Z;if(z&&X.threadId&&X.threadId!==z)return!1;if(V.turnId)return X.turnId===V.turnId;return!0},H=(X)=>{for(let V=J.length-1;V>=0;V--){let z=J[V];if(z&&Q(z,X))return z}return null},W=(X)=>{if(Z&&X.threadId&&X.threadId!==Z)return;let V={usage:X.usage,contextWindow:X.contextWindow,threadId:X.threadId,turnId:X.turnId};J.push(V);for(let z of[...Y])if(Q(V,z.notice))z.finish(V)};return $.on("token_usage",W),{waitFor(X,V){let z=H(X);if(z)return Promise.resolve(z);return new Promise((G)=>{let A=null,K={notice:X,finish:(L)=>{if(A)clearTimeout(A);Y.delete(K),G(L)}};A=setTimeout(()=>K.finish(null),V),Y.add(K)})},cancel(){$.off("token_usage",W);for(let X of[...Y])X.finish(null)}}}function QL($){if(!$)return" · \uD83E\uDDE0 MISS";let Z=N9($.usage);if(Z==null)return" · \uD83E\uDDE0 MISS";let J=S9($.contextWindow);return` · \uD83E\uDDE0 ${kY(Z,J)} (${x9(Z,J)})`}async function HW($){$.clearStaleIdleQueueState("compact");let Z=!$.currentTurn&&$.pendingUserMessageCount===0&&$.pendingMidTurnMsgs.length===0&&!$.openingTurn;if(!$.isRunning()||!$.proc){$.status="stopped",$.opts.onLifecycleChange?.();let z=await $.openStatusCard("compact","⚪ session 当前未运行","grey");if(z)await $.closeStatusCard(z,"⚪ 后端未运行,compact 无效");else await E($.chatId,`⚪ session "${$.sessionName}" 当前未运行,compact 无效;用 \`hi\` 启动或 \`restart\` 恢复上一会话`);return}if(!Z){let z=await $.openStatusCard("compact","⚠️ 当前 turn 正在执行","grey");if(z)await $.closeStatusCard(z,"⚠️ 先 stop 当前 turn,再 compact");else await E($.chatId,"⚠️ 当前 turn 正在执行,先 `stop` 后再 `compact`。");return}if($.manualContextCompactionPending){let z=await $.openStatusCard("compact","⏳ 上下文压缩已在进行中","grey");if(z)await $.closeStatusCard(z,"⏳ 上下文压缩已在进行中");else await E($.chatId,"⏳ 上下文压缩已在进行中。");return}let J=$.proc,Y=J.sessionId?q0(J.sessionId):"",Q=$.withModel(Y?`\uD83E\uDDE0 压缩上下文 thread=${Y}`:"\uD83E\uDDE0 压缩上下文…"),H=await $.openStatusCard("compact",Q,"orange"),W=async(z)=>{if(H)await $.closeStatusCard(H,z);else await E($.chatId,z)},X=JL(J),V=YL(J,J.sessionId);$.manualContextCompactionPending=!0;try{$.setStatusCard(H,$.withModel("\uD83E\uDDE0 发起上下文压缩")),await J.compactThread(),$.setStatusCard(H,$.withModel("⏳ 等待压缩完成事件"));let z=await X.promise,G=await V.waitFor(z,ZL),A=z.threadId?` thread=${q0(z.threadId)}`:"";await W($.withModel(`✅ 上下文已压缩${A}${QL(G)}`))}catch(z){if(X.cancel(),z instanceof e$)await W($.withModel(`ⓘ ${z.message}`));else await W(`❌ 上下文压缩失败: ${O(z)}`)}finally{V.cancel(),$.manualContextCompactionPending=!1}}var ZL=1500;var WW=S(()=>{K0();e()});import{randomUUID as WL}from"node:crypto";function XL($){let Z=$.currentTokenSource();return A$().filter((J)=>J.enabled||J.kind!=="claude-native").map((J)=>({provider:J.agent,sourceId:J.id,display:J.display,enabled:J.enabled,modelCount:J.models.length,catalogStatus:J.modelCatalogState?.status,catalogError:J.modelCatalogState?.error,selected:Z?.id===J.id}))}function E3($,Z,J=Z.models){let Y=$.currentModelLabel(),Q=$.currentEffortLabel(),H=$.currentTokenSource()?.id===Z.id;return J.map((W)=>{let X=H&&Y===W.model;return{provider:Z.agent,sourceId:Z.id,model:W.model,displayName:W.display,description:W.unavailableReason??(W.efforts.length?"":"effort MISS:上游未声明该后端支持的推理档位"),unavailableReason:W.unavailableReason,origin:W.origin,enabled:!0,isDefault:!1,selected:X,efforts:W.efforts.map((V)=>({effort:V,description:V==="default"?"模型未提供 effort 档位,使用模型原生行为。":"",isDefault:V===W.defaultEffort,selected:X&&Q===V}))}})}async function XW($){await p2();let Z=WL(),J=XL($);$.modelPanels.set(Z,{models:[]});let Y=await a($.chatId,j5({sessionName:$.sessionName,panelId:Z,currentDisplay:$.currentTokenSource()?.display??$.currentModelLabel(),providers:J}));if(!Y)$.modelPanels.delete(Z),await w($.chatId,"❌ 模型面板发送失败");else{let Q=$.modelPanels.get(Z);if(Q)Q.messageId=Y}}async function N3($,Z,J=""){let Y=Z.trim(),Q=p(Y);if(!Q)return{ok:!1,message:`未知账号: ${Y}`};if(!Q.enabled)return{ok:!1,message:`${Q.display} 未配置,请先点「启用」`};let H=J.trim();if(!$.modelPanels.has(H))return{ok:!1,message:"模型面板已失效,请重新发送 model"};if(Q.modelCatalogState?.status==="failed")return{ok:!1,message:`模型目录 MISS:${Q.modelCatalogState.error??"刷新失败"}`};let W=E3($,Q),X=$.modelPanels.get(H)?.messageId;return $.modelPanels.set(H,{models:[],catalog:W,sourceId:Y,messageId:X,mode:"select",editable:!!Q.modelSelection,sourceRevision:Q.spawnRevision}),R6($,H,Y,0)}async function R6($,Z,J,Y){let Q=$.modelPanels.get(Z);if(!Q?.catalog||Q.sourceId!==J)return{ok:!1,message:"模型面板已失效,请重新发送 model"};let H=Math.max(1,Math.ceil(Q.catalog.length/T3));if(!Number.isInteger(Y)||Y<0||Y>=H)return{ok:!1,message:"模型页码无效"};return Q.models=Q.catalog.slice(Y*T3,(Y+1)*T3),Q.page=Y,Q.totalPages=H,{ok:!0,message:"",card:F5({sessionName:$.sessionName,panelId:Z,currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),models:Q.models,sourceId:J,editable:Q.editable,allowCustom:!0,mode:Q.mode,...H>1?{pagination:{sourceId:J,page:Y,totalPages:H}}:{}})}}async function VW($,Z,J){let Y=$.modelPanels.get(Z),Q=p(J);if(!Y||Y.sourceId!==J||!Q?.enabled||!Q.modelSelection)return{ok:!1,message:"模型管理面板已失效,请重新发送 md"};if(Q.modelCatalogState?.status!=="ready")return{ok:!1,message:Q.modelCatalogState?.error??"目录未就绪"};let H=Q.modelSelection.availableModels.filter((W)=>W.origin!=="custom"&&!Q.modelSelection.modelIds.includes(W.model)&&(Q.modelSelection.mode==="catalog"||!W.unavailableReason&&W.efforts.length>0));return $.modelPanels.set(Z,{models:[],catalog:E3($,Q,H),sourceId:J,messageId:Y.messageId,mode:"add",editable:!0,sourceRevision:Q.spawnRevision}),R6($,Z,J,0)}async function zW($,Z,J,Y,Q){let H=$.modelPanels.get(Z),W=p(J);if(!H?.editable||H.sourceId!==J||!W?.modelSelection||H.sourceRevision!==W.spawnRevision||H.mode!==(Q==="add"?"add":"select")||!H.models.some((X)=>X.model===Y))return{ok:!1,message:"模型管理选项已失效,请重新发送 md"};if(Q==="delete"){let X=[...s0.all].filter((V)=>V.currentTokenSource()?.id===J&&V.currentModelLabel()===Y.replace(/\[1m\]$/,""));if(X.length)return{ok:!1,message:`补录模型仍被会话 ${X.map((V)=>V.sessionName).join("、")} 选用,请先切换再删除`}}try{if(Q==="delete")await JW(J,Y);else await $W(J,Y,Q);for(let V of s0.all)for(let[z,G]of V.modelPanels)if(G.sourceId===J&&(V!==$||z!==Z))V.modelPanels.delete(z);return{...await N3($,J,Z),message:Q==="add"?"模型已显示":Q==="delete"?"补录模型已删除":"模型已隐藏"}}catch(X){return{ok:!1,message:`模型列表更新失败:${O(X)}`}}}async function GW($,Z,J,Y=""){let Q=p(Z.trim());if(!Q)return{ok:!1,message:`未知账号: ${Z}`};if(!Q.enabled)return{ok:!1,message:`${Q.display} 未配置`};let H=J.trim();if(!H)return{ok:!1,message:"补录面板缺少 panel_id,请重新发送 model"};return $.modelCustomPrompt={sourceId:Q.id,panelId:H,cardMessageId:Y},{ok:!0,message:"等待模型名",card:R5($.sessionName,Q.display,H)}}async function _W($,Z,J){let Y=$.modelCustomPrompt;if(!Y)return!1;$.modelCustomPrompt=null;let Q=Z.trim(),H=p(Y.sourceId),W=async(K)=>{if(!Y.cardMessageId)return!1;let L="",D=!1,q=!1;try{if(L=await H$(Y.cardMessageId),r0(L,1),D=await L0(L,R.modelPanel,K,{notifyCardFailure:!1}),!D)throw Error("model panel replace rejected");if(q=await P0(L,{config:{streaming_mode:!1}}),!q)throw Error("model panel streaming-off rejected")}catch(P){_(`model-custom: card update MISS (${P?.message??P})`)}finally{if(L){if(!q)try{q=await P0(L,{config:{streaming_mode:!1}})}catch(P){_(`model-custom: streaming-off retry MISS (${P?.message??P})`)}if(D&&q)try{await m0(L)}catch(P){_(`model-custom: card dispose MISS (${P?.message??P})`)}else _(`model-custom: retain card state after checked MISS mutation=${D} streamingOff=${q} card=${L.slice(0,12)}`)}}return D&&q},X=async(K,L)=>{if(await W(K))return!0;let q=`⚠️ 模型补录结果未能写回原卡。${L}
|
|
184
|
+
请重新发送 model 打开面板。`;if(!await w($.chatId,q))_(`model-custom: visible fallback send MISS (${L})`);return!1},V=(K)=>X(Z2(!1,Q,K),`❌ ${Q?`模型 ${Q}`:"模型名"} 未加入:${K}。`);if(!H||!H.enabled)return await V("账号不可用"),!0;if(!Q)return await V("模型名为空"),!0;if(H.models.some((K)=>K.model.toLowerCase()===Q.toLowerCase()))return await X(Z2(!1,Q,"已在列表中"),`ℹ️ 模型 ${Q} 已在列表中,未重复加入。`),!0;try{await ZW(H.id,Q)}catch(K){return _(`model-custom: config/refresh MISS (${O(K)})`),await V(`配置写入或模型刷新失败:${O(K)}`),!0}_(`model-custom: ${H.id} 补录 ${Q} by ${J}(记录已持久化)`);for(let K of s0.all)for(let[L,D]of K.modelPanels)if(D.sourceId===H.id&&(K!==$||L!==Y.panelId))K.modelPanels.delete(L);let z=p(H.id);if(!z||z.modelCatalogState?.status!=="ready")return await V(z?.modelCatalogState?.error??"刷新后的账号目录不可用"),!0;let G=E3($,z),A=G.find((K)=>K.model===Q);if(!A)return await V("补录已保存,但刷新后的模型列表未返回该项"),!0;if($.modelPanels.set(Y.panelId,{models:G,messageId:Y.cardMessageId}),A.unavailableReason||!A.efforts.length)return await X(Z2(!0,Q,`**MISS**:${A.unavailableReason??"后端未确认 effort"}。记录已保存,可在模型面板删除。`),`模型 ${Q} 已补录,能力尚未确认。`),!0;if(A.efforts.length===1){let K=await $.onModelEffortSelect(A.model,A.efforts[0].effort,Y.panelId,J,A.provider);return await X(K.ok?s9({sessionName:$.sessionName,provider:A.provider,model:A.model,effort:A.efforts[0].effort,scope:KW($,A.provider??"codex")}):Z2(!0,Q,K.message),K.message),!0}return await X(t9({sessionName:$.sessionName,panelId:Y.panelId,currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:A}),`✅ 模型 ${Q} 已补录成功。`),!0}async function AW($,Z=""){let J=Z.trim(),Y=$.modelCustomPrompt;if(!J||!Y||Y.panelId!==J)return{ok:!1,message:"此补录面板已失效",card:r9($.sessionName,"stale")};return $.modelCustomPrompt=null,{ok:!0,message:"已取消",card:r9($.sessionName)}}function VL($,Z){return $$(Z?.provider)?Z.provider:f1($)}function KW($,Z){if($.currentTurn)return"当前 turn 不变,后续新 turn 使用。";if($.proc?.isAlive()&&$.proc.provider===Z)return Z==="codex"?"Codex 需重启进程生效(发 restart)。":"下一轮开始使用。";return`下次启动 ${Z$(Z)} 时使用。`}async function BW($,Z,J="",Y="",Q=null){let H=Z.trim();if(!H)return await E($.chatId,`❌ ${"模型为空"}`),{ok:!1,message:"模型为空"};let W=VL(H,Q),X=$.modelPanels.get(J.trim())?.models.find((V)=>V.model===H&&(V.provider??"codex")===W);if(!X)return{ok:!1,message:"模型不在当前选项中,请重新发送 model"};if($.modelPanels.get(J.trim())?.mode==="add")return{ok:!1,message:"请先将模型添加到可选列表"};if(X.unavailableReason)return{ok:!1,message:X.unavailableReason};if(X.enabled===!1)return{ok:!1,message:`${X.displayName} 未配置,请先点「启用」`};if(X.efforts.length===0)return{ok:!1,message:"模型未返回 effort"};if(X.efforts.length===1)return S3($,H,X.efforts[0].effort,J,Y,W);return{ok:!0,message:"",card:M5({sessionName:$.sessionName,panelId:J.trim(),currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:X})}}async function S3($,Z,J,Y="",Q="",H=""){let W=Z.trim(),X=J.trim();if(!W)return{ok:!1,message:"模型为空"};let V=Y.trim(),z=$.modelPanels.get(V),G=$$(H)?H:z?.models.find((j)=>j.model===W)?.provider??f1(W);if(G==="dsh"){if(!X0(X))return{ok:!1,message:"DSH reasoning effort 无效"}}else if(G==="claude"){if(!R0(X))return{ok:!1,message:"Claude reasoning effort 无效"}}else if(!h0(X))return{ok:!1,message:"Codex reasoning effort 无效"};let A=X,K=z?.models.find((j)=>j.model===W&&(j.provider??"codex")===G);if(!K||!K.efforts.some((j)=>j.effort===A))return{ok:!1,message:`${Z$(G)} · ${W}/${A} 不在选项中`};let L=p(K.sourceId);if(L?.modelCatalogState){if(!L.enabled||L.modelCatalogState.status!=="ready")return{ok:!1,message:`模型目录 MISS:${L.modelCatalogState.error??L.modelCatalogState.status}`};if(!L.models.some((j)=>j.model===W&&j.efforts.includes(A)))return{ok:!1,message:"模型或 effort 已不在账号目录中,请重新发送 model"}}let D=!!K.sourceId&&$.currentTokenSource()?.id!==K.sourceId,q=!$.processSourceMatches(L,W)||!!L?.modelEnvironmentRevision&&L.modelEnvironmentRevision($.currentModelLabel()??"")!==L.modelEnvironmentRevision(W);if($.currentProvider()===G&&!D&&$.currentModelLabel()===W&&$.currentEffortLabel()===A)return $.modelPanels.delete(V),{ok:!0,message:`当前已是 ${Z$(G)} · ${W} / ${A}`,card:o9({sessionName:$.sessionName,provider:G,model:W,effort:A,scope:"当前已是此设置,无需变更。"})};if($.proc?.isAlive()&&$.proc.provider!==G&&($.currentTurn||$.openingTurn||$.pendingUserMessageCount>0||$.pendingMidTurnMsgs.length>0))return{ok:!1,message:`当前 ${$.backendLabel($.proc.provider)} turn 正在执行或排队;请等结束或 stop 后再切换到 ${Z$(G)}`};let F=$.currentModelLabel()!==W||D,M=!!($.currentTurn||$.openingTurn||$.pendingUserMessageCount>0||$.pendingMidTurnMsgs.length>0);if(q&&$.proc?.isAlive()&&M)return{ok:!1,message:"新模型需要更新进程配置,请等当前任务结束后再选择"};if(G==="claude"&&$.proc?.isAlive()&&$.proc.provider==="claude"&&F&&M)return{ok:!1,message:"当前 Claude turn 正在执行或排队;Claude 模型 profile 通过 env 生效,请等结束或 stop 后再切换"};try{if($.proc?.isAlive()&&$.proc.provider===G&&!D&&!q){let k=K.sourceId?p(K.sourceId)?.resolveSpawnModel(W)??W:W;await WJ($.proc.setModelSettings(k,A),20000,"thread/settings/update")}await $.applyModelSelectionUnlocked(G,W,A,K.sourceId);let j=KW($,G);return $.modelPanels.delete(V),{ok:!0,message:`已选择 ${Z$(G)} · ${W} / ${A}`,card:o9({sessionName:$.sessionName,provider:G,model:W,effort:A,scope:j})}}catch(j){let k=`模型切换失败: ${O(j)}`;return _(`session "${$.sessionName}": set model settings failed: ${O(j)}`),await E($.chatId,`❌ ${k}`),{ok:!1,message:k}}}var T3=20;var LW=S(()=>{K0();x3();Z0();R3();Z1();K0();p0();G1();e();g()});import{createHash as GL}from"node:crypto";function _L($,Z){return`agent:${Buffer.from(`${$}\x00${Z}`,"utf8").toString("base64url")}`}function R1(){return AL(A$())}function AL($){let Z=[],J=[];for(let Y of $)KL(Y,Z,J);return{catalogGeneration:GL("sha256").update(JSON.stringify({identities:Z,sourceFailures:J})).digest("hex").slice(0,16),identities:Z,sourceFailures:J}}function KL($,Z,J){let Y=$.modelCatalogState?.status??(!$.enabled?"disabled":$.models.length>0?"ready":"idle");if(!$.enabled)J.push({tokenSourceId:$.id,display:$.display,status:"disabled",reason:"账号未启用"});else if(Y==="loading"||Y==="idle")J.push({tokenSourceId:$.id,display:$.display,status:"loading",reason:"模型目录正在刷新"});else if(Y==="failed")J.push({tokenSourceId:$.id,display:$.display,status:"failed",reason:$.modelCatalogState?.error??"模型目录刷新失败"});else if($.models.length===0)J.push({tokenSourceId:$.id,display:$.display,status:"models_miss",reason:"模型目录为空"});for(let Q of $.models)Z.push(BL($,Q,Y))}function BL($,Z,J){let Y="ready",Q;if(!$.enabled)Y="source_disabled",Q="所属 Token Source 未启用";else if(J==="loading"||J==="idle")Y="catalog_loading",Q="模型目录正在刷新";else if(J==="failed")Y="catalog_failed",Q=$.modelCatalogState?.error??"模型目录刷新失败";else if(Z.unavailableReason||!Z.efforts.length)Y="model_unavailable",Q=Z.unavailableReason??"effort MISS:上游未声明该后端支持的推理档位";return{id:_L($.id,Z.model),displayName:`${$.display} · ${Z.display}`,tokenSourceId:$.id,tokenSourceDisplay:$.display,provider:$.agent,model:Z.model,modelDisplay:Z.display,defaultEffort:Z.defaultEffort,supportedEfforts:[...Z.efforts],sourceDefault:qW($.defaultModel)===qW(Z.model),status:Y,...Q?{reason:Q}:{},spawnRevision:$.spawnRevision}}function qW($){return $.replace(/\[1m\]$/i,"").toLowerCase()}var U6=S(()=>{Z0()});import{randomUUID as LL}from"node:crypto";async function DW($,Z){if(!Z.trim()){await w($.chatId,"❌ 无法确认操作者身份,未打开 agents 面板");return}FW(),await i1();let J=`agents_${LL()}`;if(E4.set(J,{ownerOpenId:Z,page:0,createdAt:Date.now()}),!await a($.chatId,jW(J)))await w($.chatId,"❌ agents 面板发送失败")}function PW($,Z,J){let Y=PL($,J),Q=Number(Z);if(!Number.isInteger(Q))return jL("无效页码");let H=DL();return Y.page=Math.max(0,Math.min(H-1,Q)),Y.createdAt=Date.now(),{ok:!0,message:"已更新",card:jW($)}}function jW($){let Z=E4.get($);if(!Z)throw Error("Agent 身份面板已过期");let J=R1(),Y=Math.max(1,Math.ceil(J.identities.length/O6));Z.page=Math.min(Z.page,Y-1);let Q=Z.page*O6;return v5({panelId:$,page:Z.page,totalPages:Y,catalog:J.identities.slice(Q,Q+O6),failures:J.sourceFailures})}function DL(){return Math.max(1,Math.ceil(R1().identities.length/O6))}function PL($,Z){FW();let J=E4.get($);if(!J)throw Error("Agent 身份面板已过期,请重新发送 agents");if(!J.ownerOpenId||!Z||J.ownerOpenId!==Z)throw Error("只有打开该面板的用户可操作");return J}function jL($){return{ok:!1,message:$,card:I$({title:"agents",message:$,ok:!1})}}function FW(){let $=Date.now()-qL;for(let[Z,J]of E4)if(J.createdAt<$)E4.delete(Z)}var O6=8,qL=1800000,E4;var MW=S(()=>{p0();e();U6();Z0();E4=new Map});var b3={};n$(b3,{withTasklistLifecycleLock:()=>S6,tasklistNameForProject:()=>N6,reconcileTasklistDeletions:()=>UL,isTasklistAlreadyDeletedError:()=>RW,getTasklistBinding:()=>F$,enableTasklist:()=>k3,deleteTasklistRemoteIdempotently:()=>UW,deleteTasklist:()=>C3});import{existsSync as ML,readFileSync as RL}from"node:fs";function N6($){return`${$}[lodestar]`}function F$($){let Z=j$.get($);return Z?_2(Z):null}async function S6($,Z){let J=T6.get($)??Promise.resolve(),Y,Q=new Promise((W)=>{Y=W}),H=J.catch(()=>{}).then(()=>Q);T6.set($,H),await J.catch(()=>{});try{return await Z()}finally{if(Y(),T6.get($)===H)T6.delete($)}}function RW($){if($&&typeof $==="object"&&$.code===1470404)return!0;let Z=$ instanceof Error?$.message:String($);return/\bcode=1470404\b/.test(Z)}async function UW($,Z=K8){try{return await Z($),"deleted"}catch(J){if(RW(J))return"already_deleted";throw J}}async function k3($,Z){return await S6($,async()=>{let J=F$($);if(J?.deleting)throw Error(`tasklist deletion is pending for ${$}`);if(J)return J;let Y=N6($);if(Y.length>100)throw Error(`tasklist name is too long (${Y.length}/100): ${Y}`);let Q=await _8(Z),H=await A8(Y,Q),W={guid:H.guid,name:H.name,url:H.url,projectName:$,ownerOpenId:Q,createdAt:H.createdAt};return E6($,W),_2(W)})}async function C3($,Z){return await S6($,async()=>{let J=F$($);if(!J)throw Error("tasklist is not enabled");if(J.guid!==Z)throw Error(`tasklist binding changed: current=${J.guid} requested=${Z}`);if(!J.deleting)J.deleting={requestedAt:new Date().toISOString(),attempts:0},E6($,J);return await OW($,Z)})}async function OW($,Z){let J=F$($);if(!J||J.guid!==Z)throw Error(`tasklist binding changed during deletion: ${$}`);J.deleting??={requestedAt:new Date().toISOString(),attempts:0},J.deleting.attempts++,J.deleting.lastAttemptAt=new Date().toISOString(),J.deleting.lastError=void 0,E6($,J);try{if(await UW(Z)==="already_deleted")_(`tasklist: ${$} remote list ${Z} already deleted; finishing tombstone`);let Q=new Map(j$);return Q.delete($),TW(Q),j$.delete($),_2(J)}catch(Y){let Q=F$($);if(Q?.guid===Z&&Q.deleting)Q.deleting.lastError=Y instanceof Error?Y.message:String(Y),E6($,Q);throw Y}}async function UL(){let $=[...j$.entries()].filter(([,J])=>!!J.deleting).map(([J,Y])=>({projectName:J,guid:Y.guid})),Z=[];for(let J of $)try{await S6(J.projectName,()=>OW(J.projectName,J.guid)),_(`tasklist: reconciled pending deletion for ${J.projectName}`)}catch(Y){Z.push(`${J.projectName}: ${Y instanceof Error?Y.message:String(Y)}`)}if(Z.length)throw Error(`tasklist deletion reconcile failed: ${Z.join("; ")}`)}function OL(){if(!ML(w4))return;try{let $=JSON.parse(RL(w4,"utf8"));if(!$||typeof $!=="object")return;for(let[Z,J]of Object.entries($)){if(!J||typeof J!=="object")continue;let Y=J;if(typeof Y.guid!=="string"||!Y.guid||typeof Y.name!=="string"||!Y.name)continue;let Q={guid:Y.guid,name:Y.name,url:typeof Y.url==="string"?Y.url:"",projectName:Z,ownerOpenId:typeof Y.ownerOpenId==="string"?Y.ownerOpenId:"",createdAt:typeof Y.createdAt==="string"?Y.createdAt:void 0,deleting:TL(Y.deleting)};j$.set(Z,Q)}_(`tasklist: loaded ${j$.size} project bindings`)}catch($){_(`tasklist: load map failed: ${$}`)}}function TL($){if(!$||typeof $!=="object")return;let Z=$;if(typeof Z.requestedAt!=="string"||!Z.requestedAt)return;return{requestedAt:Z.requestedAt,lastAttemptAt:typeof Z.lastAttemptAt==="string"?Z.lastAttemptAt:void 0,attempts:typeof Z.attempts==="number"&&Number.isFinite(Z.attempts)&&Z.attempts>=0?Math.floor(Z.attempts):0,lastError:typeof Z.lastError==="string"?Z.lastError:void 0}}function E6($,Z){let J=new Map(j$);J.set($,_2(Z)),TW(J),j$.set($,_2(Z))}function TW($=j$){let Z={};for(let[J,Y]of $)Z[J]=_2(Y);A0(w4,Z)}function _2($){return JSON.parse(JSON.stringify($))}var j$,T6;var y3=S(()=>{Y0();e();g();n0();j$=new Map,T6=new Map;OL()});function u$($,Z,J=!1){let Y=$.worktreeProjectName();return y5({projectName:Y,tasklistName:N6(Y),binding:F$(Y),notice:Z,confirmDelete:J})}async function EW($){if(!await a($.chatId,u$($)))await w($.chatId,"❌ task 面板发送失败")}async function NW($){let Z=$.worktreeProjectName();try{let J=F$(Z),Y=await k3(Z,$.chatId),Q=J?"已启用":`已启用 ${Y.name}`;return{ok:!0,message:Q,card:u$($,{type:"success",content:`✅ ${Q}`})}}catch(J){let Y=`启用失败: ${O(J)}`;return _(`session "${$.sessionName}": tasklist enable failed: ${O(J)}`),{ok:!1,message:Y,card:u$($,{type:"error",content:`❌ ${Y}`})}}}function SW($,Z){let J=$.worktreeProjectName(),Y=F$(J),Q=Z.trim();if(!Y)return{ok:!1,message:"未启用",card:u$($,{type:"error",content:"❌ 未启用"})};if(Y.guid!==Q)return{ok:!1,message:"清单绑定已变化",card:u$($,{type:"error",content:"❌ 清单绑定已变化,请重新打开 task 面板"})};return{ok:!0,message:"请再次确认删除",card:u$($,{type:"error",content:"⚠️ 删除会删除所有清单内任务"},!0)}}async function xW($,Z){let J=$.worktreeProjectName(),Y=Z.trim();try{let H=`已删除 ${(await C3(J,Y)).name}`;return{ok:!0,message:H,card:u$($,{type:"success",content:`✅ ${H}`})}}catch(Q){let H=`删除失败: ${O(Q)}`;return _(`session "${$.sessionName}": tasklist delete failed: ${O(Q)}`),{ok:!1,message:H,card:u$($,{type:"error",content:`❌ ${H}`})}}}var kW=S(()=>{p0();e();g();y3()});var w3,f3,CW,bW,yW;var wW=S(()=>{w3=["- 以 `[file: /abs/path]` 开头的文本表示该路径上挂着一个文件,相关时去读它。","- 在回复任意位置,独占一行写 `[[send: /abs/path]]` 即可把该文件作为单独一条消息送出。只在用户主动要文件、或你要交付最终产物时才发。","- 飞书单个出站文件不能超过 30 MB(30 × 1024 × 1024 字节)。交付前检查大小;超限先压缩或分卷,确保每个文件都不超过上限,再发送。"],f3=["- 判断是否该发文件:导出附件/数据集、用户明确要文件或下载物时,应先写到本机绝对路径,再用独占一行的 `[[send: /abs/path]]` 发给用户;短总结、普通说明、无需留存的正文答复不要为了发文件而发文件。","- 使用图片生成工具生成图片后,不要再补充说明文字或 `[[send: ...]]`;Lodestar 会自动展示图片和提示词,支持时放进折叠面板,无法嵌入时单独发送。若你用脚本或文件编辑生成图片,按上一条用 `[[send: /abs/path]]` 发出。","- 每次调用 Bash / shell 命令时,第一行都必须写 shell 注释 `# desc: <一句中文说明>`,再写真正命令。这个注释只给 Lodestar 卡片做摘要,不要依赖它改变命令行为。"],CW=[...w3,"- 当你有问题需要澄清时,使用 request_user_input 工具向用户提问;不要把多选题写成文本。",...f3].join(`
|
|
185
|
+
`),bW=[...w3,"- 当你有问题需要澄清时,使用 Claude Code 自带的 AskUserQuestion 工具向用户提问。",...f3].join(`
|
|
186
|
+
`),yW=[...w3,"- 当你有问题需要澄清时,使用 ask_user_question 工具向用户提问;不要把多选题写成文本。",...f3].join(`
|
|
187
|
+
`)});import{execFileSync as NL}from"node:child_process";import{existsSync as U1,readdirSync as SL,readFileSync as xL,realpathSync as v3,statSync as kL}from"node:fs";import{dirname as CL,join as vW,resolve as k6}from"node:path";async function C6($,Z){let J=v3($),Y=process.platform==="win32"?J.toLowerCase():J,Q=x6.get(Y)??Promise.resolve(),H,W=new Promise((V)=>{H=V}),X=Q.catch(()=>{}).then(()=>W);x6.set(Y,X),await Q.catch(()=>{});try{return await Z()}finally{if(H(),x6.get(Y)===X)x6.delete(Y)}}function O1($){let Z=$.trim();if(!bL.test(Z))return null;return Z}function hW($){return $.match(/^(.+)\[[^\[\]]+\]$/)?.[1]??$}function K2($,Z){return`${$}[${Z}]`}function IW($){return`${A2}${$}`}function B2($,Z,J){return vW(CL($),K2(Z,J))}function gW($,Z,J){let Y=yL($,Z,J);if(!Y)return null;let Q=xL(Y.path,"utf8").trim();if(!Q)return null;return{path:Y.path,content:Q,slug:Y.slug}}function cW($,Z){I3($);let J=F0($,["for-each-ref","--format=%(refname:short)",`refs/heads/${A2}`]).split(`
|
|
188
|
+
`).map((H)=>H.trim()).filter(Boolean).filter((H)=>H.startsWith(A2)),Y=g3($),Q=[];for(let H of J){let W=H.slice(A2.length);if(!O1(W))continue;let X=K2(Z,W),V=B2($,Z,W),z=Y.get(H)??null,G=!!z&&U1(z),A=lW($,H,G),K={slug:W,chatName:X,branch:H,state:A,expectedPath:V,worktreePath:G?z:null,mounted:G,dirtyCount:null,statusLine:null,error:null};if(z&&U1(z))try{let D=F0(z,["status","--porcelain=v1","--branch"]).split(`
|
|
189
|
+
`).filter(Boolean);K.statusLine=D[0]?.startsWith("## ")?D[0].slice(3):null,K.dirtyCount=D.filter((q)=>!q.startsWith("## ")).length}catch(L){K.error=c3(L)}Q.push(K)}return Q.sort((H,W)=>H.slug.localeCompare(W.slug))}function mW($,Z,J){let Y=O1(J);if(!Y)throw Error(`invalid worktree name "${J}"`);I3($);let Q=IW(Y),H=K2(Z,Y),W=B2($,Z,Y),X=hL($,Q),V=g3($).get(Q)??null,z=X&&!V&&lW($,Q,!1)==="merged"?F0($,["rev-parse","HEAD"]).trim():null;if(V){if(k6(V)!==k6(W))throw Error(`branch ${Q} is already mounted at ${V}`);return pW(W,Q),{slug:Y,chatName:H,branch:Q,worktreePath:W,createdBranch:!1,createdWorktree:!1}}if(U1(W)){if(!kL(W).isDirectory())throw Error(`${W} exists but is not a directory`);if(!X)throw Error(`${W} already exists while branch ${Q} does not`)}if(X){if(F0($,["worktree","add",W,Q]),z)F0(W,["rebase",z]);return{slug:Y,chatName:H,branch:Q,worktreePath:W,createdBranch:!1,createdWorktree:!0}}return F0($,["worktree","add","-b",Q,W,"HEAD"]),{slug:Y,chatName:H,branch:Q,worktreePath:W,createdBranch:!0,createdWorktree:!0}}function uW($,Z,J){let Y=h3($,Z,J);if(!U1(Y.worktreePath))return Y;return F0($,["worktree","remove",Y.worktreePath]),{...Y,removedWorktree:!0}}function h3($,Z,J){let Y=O1(J);if(!Y)throw Error(`invalid worktree name "${J}"`);I3($);let Q=IW(Y),H=K2(Z,Y),W=B2($,Z,Y),V=g3($).get(Q)??null??W;if(!U1(V))return{slug:Y,chatName:H,branch:Q,worktreePath:V,removedWorktree:!1};pW(V,Q);let z=F0(V,["status","--porcelain=v1"]).split(`
|
|
187
190
|
`).filter(Boolean);if(z.length>0){let G=z.slice(0,8).join(`
|
|
188
191
|
`);throw Error(`worktree has uncommitted changes:
|
|
189
|
-
${G}`)}return{slug:Y,chatName:H,branch:Q,worktreePath:V,removedWorktree:!1}}function
|
|
190
|
-
`)){if(Q.startsWith("worktree ")){Y=Q.slice(9);continue}if(Q.startsWith("branch refs/heads/")&&Y)Z.set(Q.slice(18),Y)}return Z}function
|
|
191
|
-
${Y}`:J}function
|
|
192
|
-
${J}`:Z}function
|
|
193
|
-
`)}async function
|
|
194
|
-
${H}`,card:
|
|
195
|
-
`),type:"success"}})}catch(W){H={ok:!1,message:`❌ 解散 ${J} 失败: ${
|
|
196
|
-
`)){let H=Q.trim();if(!H)continue;let W;try{W=JSON.parse(H)}catch{continue}if(W.type==="queue-operation"&&W.operation==="enqueue"&&typeof W.content==="string"){let X=W.content.trim();if(X)return X.slice(0,80)}if(!Y&&W.type==="user"&&W.message){let X=JL(W.message);if(X)Y=X}}return Y.slice(0,80)}function JL($){let Z=$?.content;if(typeof Z==="string")return Z;if(!Array.isArray(Z))return"";for(let J of Z)if(J?.type==="text"&&typeof J.text==="string")return J.text;return""}async function WX($,Z,J){if(!J){await T($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let Y=tq($),Q=sq($),H=new Map,W=[];for(let G=0;G<Y.length;G++){let _=Y[G];if(G===0&&Q===null)continue;let K=m3(),q=G===0?Q:rq(Y[G-1].checkpoint);H.set(K,{kind:Z,launch:q,branchBase:Q,seedAnchors:Y.slice(0,G),writes:Y.slice(G).flatMap((D)=>D.writes)}),W.push({choiceId:K,preview:_.preview,ts:_.ts})}W.reverse();let X=HX($,Z,J,H),V=U5({projectName:x6($),panelId:X.id,mode:Z,entries:W}),z;try{z=await d($.chatId,V)}catch(G){throw _2($).delete(X.id),G}if(!z)_2($).delete(X.id),await w($.chatId,`❌ ${Z==="fork"?"fk":"bk"} 列表发送失败`)}function XX($,Z){return WX($,"fork",Z)}function VX($,Z){return WX($,"back",Z)}async function zX($,Z){if(!Z){await T($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let J;try{J=$.selectedProvider==="codex"?await $.listCodexConversations():$.selectedProvider==="dsh"?await $.listDshConversations():eq($.workDir)}catch(V){await w($.chatId,`❌ 历史会话读取失败: ${V instanceof Error?V.message:V}`);return}let Y=new Map,Q=$L(J).map((V)=>{let z=m3();return Y.set(z,{kind:"resume",launch:{kind:"fork",source:{provider:V.provider,sessionId:V.sessionId,cwd:V.cwd}},sourcePreview:V.preview,sourceTs:V.ts,sourceStatus:V.status}),{choiceId:z,preview:V.preview,ts:V.ts}}),H=HX($,"resume",Z,Y),W=O5({projectName:x6($),panelId:H.id,entries:Q}),X;try{X=await d($.chatId,W)}catch(V){throw _2($).delete(H.id),V}if(!X)_2($).delete(H.id),await w($.chatId,"❌ rs 历史列表发送失败")}async function GX($,Z){if(!Z){await T($.chatId,"❌ 找不到发起人,无法建临时群。");return}if(!$.opts.onCreateTempSession){await T($.chatId,"❌ 临时群能力未就绪(daemon 未注入回调)。");return}let J=YX(x6($));await T($.chatId,`\uD83D\uDE80 正在创建 ${J} · ${$.backendLabel()} 新会话。它与当前群共享工作目录;当前会话不受影响。`);let Y;try{Y=await $.opts.onCreateTempSession({chatName:J,userOpenId:Z,workDir:$.workDir,routing:$.conversationRouting(),launch:{kind:"fresh"},branchBase:{kind:"fresh"},seedAnchors:[]})}finally{QX(J)}if(!Y.ok){await T($.chatId,`❌ 建临时会话失败: ${Y.error??"未知"}`);return}await T($.chatId,`✅ 已创建 ${J}。临时群不会自动删除;在该群发送 bye 可停止并解散。`)}async function AX($){if(!J$($.sessionName)){await T($.chatId,"❌ bye 只能在带 *MMDD-HHMM 后缀的临时会话群里使用。");return}if(!$.opts.onDisbandTempSession){await T($.chatId,"❌ 解散能力未就绪(daemon 未注入回调)。");return}await T($.chatId,`\uD83D\uDC4B 正在停止会话并解散 ${$.sessionName}…`);let Z=await $.opts.onDisbandTempSession($.sessionName,$.chatId);if(!Z.ok)await T($.chatId,`❌ 解散失败: ${Z.error??"未知"}`)}async function _X($,Z,J,Y){let Q=u3($,"fork",Z,J,Y);if("error"in Q)return{ok:!1,message:Q.error,replaceCard:!1};let{panel:H,choice:W}=Q;try{if(W.kind!=="fork")return{ok:!1,message:"选择项类型不匹配"};if(!$.opts.onCreateTempSession)return{ok:!1,message:"临时群能力未就绪"};let X=YX(H.baseName);A(`session-temp: fork ${$.sessionName} → ${X} (${W.launch.kind})`),await T($.chatId,`\uD83D\uDD31 正在分叉到 ${X}…`);let V;try{V=await $.opts.onCreateTempSession({chatName:X,userOpenId:Y,workDir:H.workDir,routing:H.routing,launch:W.launch,branchBase:W.branchBase,seedAnchors:W.seedAnchors})}finally{QX(X)}if(!V.ok)return{ok:!1,message:`分叉失败: ${V.error??"未知"}`};return{ok:!0,message:`已分叉到 ${X};原会话和磁盘文件未回滚`}}catch(X){return{ok:!1,message:`分叉失败: ${X instanceof Error?X.message:X}`}}finally{S6(H)}}async function KX($,Z,J,Y){let Q=u3($,"back",Z,J,Y);if("error"in Q)return{ok:!1,message:Q.error,replaceCard:!1};let{panel:H,choice:W}=Q;try{if(W.kind!=="back")return{ok:!1,message:"选择项类型不匹配"};let X="";try{if(!await d($.chatId,T5({projectName:H.baseName,entries:W.writes})))X=";文件变更记录卡发送失败"}catch(G){X=`;文件变更记录卡发送失败: ${G instanceof Error?G.message:G}`}if(A(`session-temp: back ${$.sessionName} (${W.launch.kind}, writes=${W.writes.length})`),!await $.rollbackTo(W.launch,{anchors:W.seedAnchors,base:W.branchBase}))return{ok:!1,message:`回退失败;原会话绑定未改,请检查日志后重试${X}`};if(H.routing.provider==="claude")return{ok:!0,message:`本群已准备 Claude 新分支;发送下一条消息时生成并接入,旧会话未删除,磁盘文件未回滚${X}`};return{ok:!0,message:`本群已改接新会话${$.lastSessionId?` ${B0($.lastSessionId)}`:""};旧会话未删除,磁盘文件未回滚${X}`}}catch(X){return{ok:!1,message:`回退失败: ${X instanceof Error?X.message:X}`}}finally{S6(H)}}async function BX($,Z,J,Y){let Q=u3($,"resume",Z,J,Y);if("error"in Q)return{ok:!1,message:Q.error,replaceCard:!1};let{panel:H,choice:W}=Q;if(W.kind!=="resume")throw S6(H),Error("resume panel contained a non-resume choice");let X=W.launch.source.sessionId,V=$.lastSessionId,z=(_,K)=>({projectName:H.baseName,provider:W.launch.source.provider,selectedPreview:W.sourcePreview,selectedTs:W.sourceTs,sourceSessionId:X,...W.sourceStatus?{sourceStatus:W.sourceStatus}:{},previousSessionId:V,newSessionId:_,bindingState:K}),G=(_,K,q,D=null)=>({ok:_,message:K,resumePresentation:z(D,q)});try{if($.isRunning())return G(!1,"当前群已经启动了新进程;为避免误杀,请先停止后重新发送 rs","unchanged");if(W.sourceStatus==="active")return G(!1,"所选 Codex 会话仍在运行;请先在原位置停止后再创建完整分支","unchanged");if(A(`session-temp: history fork ${$.sessionName} ← ${W.launch.source.provider} ${X}`),!await $.rollbackTo(W.launch,{anchors:[],base:W.launch,pendingLaunch:W.launch.source.provider==="claude"?{launch:W.launch,previousSessionId:V}:null}))return G(!1,"历史分支创建失败;原会话绑定未改,请检查日志后重试","unchanged");if(W.launch.source.provider==="claude")return G(!0,"Claude 独立分支已准备;首条消息时生成并接入新会话","prepared");let K=$.lastSessionId;if(!K)return G(!1,"历史分支已启动,但后端没有返回新会话 id","unknown");if(K===X||V&&K===V)return G(!1,"后端没有返回独立的新会话 id;为避免误判,本次不标记为恢复成功","unknown",K);return G(!0,"已创建并接入独立分支;源会话未修改","changed",K)}catch(_){return G(!1,`历史分支创建失败: ${_ instanceof Error?_.message:_}`,"unknown")}finally{S6(H)}}var iq=86400000,dq=1800000,nq=3600000,aq=40,JX,c3;var qX=E(()=>{s();u0();g();f2();R2();t$();JX=new WeakMap,c3=new Set});import{existsSync as LX}from"node:fs";import{randomBytes as QL,timingSafeEqual as HL}from"node:crypto";import{isAbsolute as WL}from"node:path";function l3($,Z=new Set){if($ instanceof S2)return $;if(!$||typeof $!=="object"&&typeof $!=="function"||Z.has($))return null;if(Z.add($),$ instanceof AggregateError)for(let J of $.errors){let Y=l3(J,Z);if(Y)return Y}if($ instanceof Error&&$.cause!==void 0)return l3($.cause,Z);return null}function XL($){return $.itemId||$.turnId||"__latest__"}function DX($){let Z=[];if($.itemId)Z.push(`item:${$.itemId}`);if($.turnId)Z.push(`turn:${$.threadId??$.sessionId??"-"}:${$.turnId}`);return Z}function VL($){let Z=null;for(let J of $.contextCompactionPending.keys())Z=J;return Z}function zL($,Z){if(!$)return Z;return{...$,...Z,phase:"end"}}function R1(){return I.runtime?.live_elapsed??"bucket"}function FX($,Z){return`${$} (${N$(Date.now()-Z,R1()).label})`}var PX="Thinking...",GL="Writing...",AL="Working...",p3=1e4,k6=120000,_L=50,KL=256,C6=1e4,jX=250,t0;var E3=E(()=>{R2();O2();A0();s$();a7();A0();x0();V8();$0();f2();X1();u0();s();g();J0();_5();H6();B4();u5();$H();KH();SH();A6();CH();HW();XW();LW();RW();CW();ZX();qX();t$();t0=class t0{sessionName;chatId;opts;static all=new Set;proc=null;lifecycleTail=Promise.resolve();lifecycleSequence=0;procEpoch=0;stoppingProc=null;blockedProc=null;blockedProcReason=null;agentCapability=null;procSourceRevisions=new WeakMap;currentTurn=null;contextCompactionReceipts=new Map;contextCompactionOwnerIds=new WeakMap;contextCompactionOwnerSequence=0;lastManualContextCompactionCompletedAt=0;lastManualContextCompactionWasAnonymous=!1;backgroundTasks=[];pendingBgTasks=[];backgroundCard=null;settlingBackgroundCard=!1;migratingBackgroundCard=null;backgroundRefreshTimer=null;backgroundRefreshTick=null;openingBackground=!1;openingBackgroundOwner=null;backgroundOpenSequence=0;backgroundGeneration=0;backgroundDetailAdded=new Set;backgroundDetailAdding=new Set;lastMainTaskToolUseId=null;pendingRebuildBackgroundCard=!1;bgResumePending=!1;orphanAssistantSegments=[];orphanAssistantCurrent="";bgResumeCardless=!1;pendingPermissions=new Map;pendingAsks=new Map;currentGoal=null;status="stopped";pendingUserMessageCount=0;pendingMidTurnMsgs=[];pendingTurnInputs=[];multiMsgBuffer=null;multiMsgReactions=new Map;lastUserOpenId="";pendingReactionIds=new Map;currentBatchReactionIds=new Map;initCount=0;openingTurn=!1;openingTurnOwner=null;turnOpenSequence=0;turnCloseInflight=new Set;turnCounter=0;userInterrupted=!1;lastSessionId=null;lastSessionRef=null;selectedProvider="claude";selectedModel=null;selectedEffort=null;selectedTokenSourceId=null;modelPanels=new Map;modelCustomPrompt=null;startedAt=0;cumStats={tokens:0,costUsd:0,turns:0};lastTurnDelta=null;currentTurnUsageBaseline=null;currentTurnUsageBaselineKnown=!1;lastTurnUsage=null;usageTotalsSeedUnknown=!1;resumePersistenceError=null;manualContextCompactionPending=!1;taskBoard=[];constructor($,Z,J={}){this.sessionName=$;this.chatId=Z;this.opts=J;t0.all.add(this);let Y=k8($);this.selectedProvider=Y?.provider??"claude",this.selectedModel=Y?.model??null,this.selectedEffort=Y?.effort??null,this.selectedTokenSourceId=this.deriveTokenSourceId(Y);let Q=p(this.selectedTokenSourceId);if(Q){if(this.selectedProvider=Q.agent,Q.id==="glm"&&this.selectedModel==="claude:glm")this.selectedModel=Q.defaultModel,this.selectedEffort="max"}if(this.selectedModel)A(`session "${$}": restored selected provider=${this.selectedProvider} model=${this.selectedModel} effort=${this.selectedEffort??"unset"}`);if(this.lastSessionRef=Q1($,this.selectedProvider),this.lastSessionId=this.lastSessionRef?.sessionId??null,this.lastSessionId)A(`session "${$}": restored ${this.selectedProvider} lastSessionId=${this.lastSessionId}`);let H=d2($);if(H)if(this.selectedProvider!=="claude")n0($,[],null,null),A(`session "${$}": cleared pending Claude fork after provider changed`);else{H0(H.launch,"claude",this.workDir);let W=this.lastSessionId===H.previousSessionId,X=this.lastSessionRef,V=!W&&X?.provider==="claude"&&X.cwd===this.workDir&&X.sessionId!==H.launch.source.sessionId&&X.sessionId!==H.previousSessionId;if(!W&&!V)throw Error(`pending Claude fork has inconsistent resume binding for session "${$}"`);this.pendingConversationMaterialization=H,A(`session "${$}": restored ${V?"materialized":"pending"} Claude fork source=${H.launch.source.sessionId}`)}}peerSnapshot(){return{name:this.sessionName,status:this.status,uptimeMs:this.startedAt?Date.now()-this.startedAt:void 0}}get workDir(){return aW(this)}isRunning(){return!!this.proc&&this.proc.isAlive()}shouldRevive(){return this.isRunning()&&this.stoppingProc!==this.proc&&this.blockedProc!==this.proc}deriveTokenSourceId($){let Z=$?.tokenSourceId;if(typeof Z==="string"&&Z.trim())return Z.trim();let J=$?.provider??this.selectedProvider;return H9(J)[0]?.id??null}currentTokenSource(){return p(this.selectedTokenSourceId)}currentProvider(){return this.selectedProvider}conversationRouting(){return{provider:this.selectedProvider,tokenSourceId:this.selectedTokenSourceId,model:this.selectedModel,effort:this.selectedEffort}}applyConversationRouting($){if(this.isRunning()||this.currentTurn||this.openingTurn)throw Error("cannot change conversation routing while the session is running");let Z=p($.tokenSourceId);if(Z&&Z.agent!==$.provider)throw Error(`token source "${Z.id}" belongs to ${Z.agent}, not ${$.provider}`);if(this.selectedProvider!==$.provider)n0(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$.provider,this.selectedTokenSourceId=$.tokenSourceId,this.selectedModel=$.model,this.selectedEffort=$.effort,this.lastSessionRef=Q1(this.sessionName,$.provider),this.lastSessionId=this.lastSessionRef?.sessionId??null,x8(this.sessionName,$.provider,$.model,$.effort,$.tokenSourceId)}dshEffortForSpawn(){if(Q0(this.selectedEffort))return this.selectedEffort;let $=this.currentTokenSource(),Z=$&&x$($,this.selectedModel??$.defaultModel);if(!Z||!Q0(Z.defaultEffort))throw Error("DSH model reasoning effort is unavailable");return Z.defaultEffort}async listDshConversations(){if(this.selectedProvider!=="dsh")throw Error("DSH history requested under a different provider");let $=this.currentTokenSource();if(!$?.enabled||$.agent!=="dsh")throw Error("DSH token source is unavailable");return(await k1({cwd:this.workDir,env:$.spawnEnv(process.env),profile:{loadProjectMcp:!1}},"session/list",{cwd:this.workDir})).filter((J)=>!x1("dsh",J.sessionId))}async listCodexConversations(){if(this.selectedProvider!=="codex")throw Error("Codex history requested for a non-Codex session");if(!t2())throw Error("Codex 未登录 ChatGPT 账号");let $=this.currentTokenSource();if(this.selectedTokenSourceId&&(!$||!$.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或选择其他账号`);let Z=$?.enabled?$:void 0,J=Z?(X)=>Z.spawnEnv(X):void 0,Y=new w1({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Z?.id??null,transformEnv:J}),Q=null,H=null;try{Q=await Y.listConversations()}catch(X){H=X}let W=null;try{await Y.kill(2000)}catch(X){W=X}if(H&&W)throw AggregateError([H,W],`Codex history query and cleanup failed: ${U(H)}; ${U(W)}`);if(H)throw H;if(W)throw W;return Q??[]}async resolveLegacyResumeRef($){if($.cwd!==null)return $;if($.provider!==this.selectedProvider)throw Error(`legacy resume provider mismatch: ${$.provider} != ${this.selectedProvider}`);let Z;if($.provider==="dsh")throw Error("DSH resume reference requires its original cwd");else if($.provider==="claude"){let J=J9(this.workDir,$.sessionId);if(!LX(J))throw Error(`旧 Claude 会话不属于当前 cwd,或 transcript 不存在: ${B0($.sessionId)}`);Z={...$,cwd:this.workDir}}else{if(!t2())throw Error("Codex 未登录 ChatGPT 账号");let J=this.currentTokenSource();if(this.selectedTokenSourceId&&(!J||!J.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或选择其他账号`);let Y=J?.enabled?J:void 0,Q=new w1({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Y?.id??null,transformEnv:Y?(X)=>Y.spawnEnv(X):void 0}),H=null;try{Z=await Q.readConversationRef($.sessionId)}catch(X){H=X,Z=$}let W=null;try{await Q.kill(2000)}catch(X){W=X}if(H&&W)throw AggregateError([H,W],`Codex legacy resume lookup and cleanup failed: read=${U(H)}; cleanup=${U(W)}`);if(H)throw H;if(W)throw W}return H0({kind:"resume",source:Z},this.selectedProvider,this.workDir),p2(this.sessionName,Z),Z}hasRunningPeerSession($){return[...t0.all].some((Z)=>Z.sessionName===$&&Z.isRunning())}modelForSpawn(){if(this.selectedProvider==="codex")return;return this.selectedModel??void 0}effortForSpawn(){if(this.selectedProvider==="codex"){let $=this.currentTokenSource();if(!$||!$.enabled)return;return v0(this.selectedEffort)?this.selectedEffort:k2}return k2}claudeEffortForSpawn(){if(this.selectedProvider==="claude"&&F0(this.selectedEffort))return this.selectedEffort;let $=this.currentTokenSource();if(this.selectedProvider==="claude"&&$?.agent==="claude"){let Z=x$($,this.selectedModel??$.defaultModel);if(!F0(Z?.defaultEffort))throw Error("Claude 默认 effort MISS,请通过 model 面板明确选择");return Z.defaultEffort}return O$}currentModelLabel(){return(this.selectedModel??this.currentTokenSource()?.defaultModel??this.proc?.lastModel??null)?.replace(/^claude:/i,"").replace(/\[1m\]$/i,"")??null}currentEffortLabel(){let $=this.currentTokenSource();if(this.selectedProvider==="claude"&&$?.agent==="claude")return this.selectedEffort??x$($,this.selectedModel??$.defaultModel)?.defaultEffort??null;return this.selectedEffort??(this.selectedProvider==="dsh"?this.dshEffortForSpawn():void 0)??this.proc?.lastEffort??(this.selectedProvider==="claude"?O$:k2)}runtimeModelSelection(){let $=this.proc?.isAlive()?this.proc:null,Z=$?.provider??this.selectedProvider,J=!$||$.provider===this.selectedProvider,Y=($?.lastModel??(J?this.currentModelLabel():null))?.replace(/^claude:/i,"").replace(/\[1m\]$/i,"")??null,Q=$?.lastEffort??(J?this.currentEffortLabel():Z==="claude"?O$:k2);return{provider:Z,model:Y,effort:Q}}withModel($,Z){let J=this.modelLine(Z);return $.includes(J)?$:`${$} · ${J}`}replaceFooterContent($,Z){return r($,R.footer,this.footerElement(Z),void 0,!1)}footerElement($){return{tag:"markdown",element_id:R.footer,content:$.trim()||" "}}modelLine($=this.currentTurn??this.runtimeModelSelection()){return d8($.provider,$.model,$.effort)}backendLabel($=this.selectedProvider){return $$($)}pendingConversationLaunch=null;pendingConversationMaterialization=null;lastTurnUserPreview="";pendingCodexTurnAnchors=[];pendingMaterializationLaunch(){let $=this.pendingConversationMaterialization;if(!$)return null;if(H0($.launch,"claude",this.workDir),this.selectedProvider!=="claude")throw Error("pending Claude fork cannot launch under a non-Claude provider");if(this.lastSessionId===$.previousSessionId)return $.launch;let Z=this.lastSessionRef;if(Z?.provider==="claude"&&Z.cwd===this.workDir&&Z.sessionId!==$.launch.source.sessionId&&Z.sessionId!==$.previousSessionId)return{kind:"resume",source:Z};throw Error("pending Claude fork has no safe launch target")}spawnAgent($){this.agentCapability=QL(32).toString("base64url");let Z={LODESTAR_AGENT_URL:V9(I.notify.bind,I.notify.port),LODESTAR_AGENT_CAPABILITY:this.agentCapability,LODESTAR_AGENT_SESSION:this.sessionName,LODESTAR_AGENT_ROLE:"main"},J=this.pendingConversationLaunch??this.pendingMaterializationLaunch()??($?{kind:"resume",source:$}:{kind:"fresh"});H0(J,this.selectedProvider,this.workDir);let Y=this.currentTokenSource();if(this.selectedTokenSourceId&&(!Y||!Y.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或在 model 面板选择其他账号`);let Q=Y?.enabled?Y:void 0,H=X9({provider:this.selectedProvider,workDir:this.workDir,tokenSourceId:Q?.id??null,model:Q?this.selectedModel??Q.defaultModel:this.modelForSpawn(),effort:this.selectedProvider==="dsh"?this.dshEffortForSpawn():this.selectedProvider==="claude"?this.claudeEffortForSpawn():this.effortForSpawn(),launch:J,developerInstructions:this.spawnDeveloperInstructions(),profile:p1(this.worktreeProjectName()),...process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"?{}:{managedSkillPluginPath:n$},hostEnv:Z});return this.procSourceRevisions.set(H.process,H.sourceRevision),H.process}async applyModelSelection($,Z,J,Y){await this.runLifecycle("apply-model-selection",()=>this.applyModelSelectionUnlocked($,Z,J,Y))}async applyModelSelectionUnlocked($,Z,J,Y){if(this.selectedProvider!==$)n0(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$,this.selectedTokenSourceId=Y??this.selectedTokenSourceId;let H=p(this.selectedTokenSourceId);if(H)this.selectedModel=Z||null,this.selectedEffort=J??x$(H,Z||H.defaultModel)?.defaultEffort??null;else this.selectedModel=$==="codex"?null:Z,this.selectedEffort=$==="codex"?null:J;this.lastSessionRef=Q1(this.sessionName,$),this.lastSessionId=this.lastSessionRef?.sessionId??null,S8(this.sessionName,$,this.selectedModel,this.selectedEffort,this.selectedTokenSourceId),await this.stopIdleMismatchedProcessUnlocked()}async stopIdleMismatchedProcess(){await this.runLifecycle("stop-idle-mismatched",()=>this.stopIdleMismatchedProcessUnlocked())}processSourceMatches($,Z){return!this.proc||!this.procSourceRevisions.has(this.proc)||this.procSourceRevisions.get(this.proc)===h2($,Z)}async stopIdleMismatchedProcessUnlocked(){if(!this.proc?.isAlive())return;let $=this.currentTokenSource(),Z=this.processSourceMatches($,this.selectedModel);if(this.proc.provider===this.selectedProvider&&this.proc.tokenSourceId===this.selectedTokenSourceId&&Z)return;if(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0)return;let J=this.proc;A(`session "${this.sessionName}": stop idle ${J.provider} process after switching to ${this.selectedProvider}`),this.beginProcStop(J),this.initCount=0,this.bgResumePending=!1,this.discardOrphanAssistant(),this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.usageTotalsSeedUnknown=!1,this.status="stopped";let Y=await this.settleProcResumableState(J),Q=null;try{await J.kill(1000)}catch(X){Q=X}Y=await this.settleProcResumableState(J);let H=this.finishProcStop(J,Q);this.opts.onLifecycleChange?.();let W=[...!H?[Q??Error(this.blockedProcReason??"process stop unconfirmed")]:[],...Y?[Error(Y)]:[]];if(W.length===1)throw W[0];if(W.length>1)throw AggregateError(W,`idle process stop failed: ${W.map(U).join("; ")}`)}async stopIdleCurrentProcess($){return await this.runLifecycle("stop-idle-current",()=>this.stopIdleCurrentProcessUnlocked($))}async stopIdleCurrentProcessUnlocked($){if(!this.proc?.isAlive())return!1;if(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0)return!1;let Z=this.proc;A(`session "${this.sessionName}": stop idle ${Z.provider} process: ${$}`),this.beginProcStop(Z),this.initCount=0,this.bgResumePending=!1,this.discardOrphanAssistant(),this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.usageTotalsSeedUnknown=!1,this.status="stopped";let J=await this.settleProcResumableState(Z),Y=null;try{await Z.kill(1000)}catch(W){Y=W}J=await this.settleProcResumableState(Z);let Q=this.finishProcStop(Z,Y);this.opts.onLifecycleChange?.();let H=[...!Q?[Y??Error(this.blockedProcReason??"process stop unconfirmed")]:[],...J?[Error(J)]:[]];if(H.length===1)throw H[0];if(H.length>1)throw AggregateError(H,`idle process stop failed: ${H.map(U).join("; ")}`);return!0}startFooterTimer($,Z,J=(Y)=>Y){let Y=Date.now(),Q=Z,H=!1,W=()=>{if(H)return;this.replaceFooterContent($,J(FX(Q,Y)))},X=null,V=()=>{if(H)return;let{nextDelayMs:z}=N$(Date.now()-Y,R1());X=setTimeout(()=>{W(),V()},Math.max(1,Math.ceil(z)))};return W(),V(),{setStatus(z){Q=z,W()},stop(){if(H=!0,X)clearTimeout(X)},elapsedSec(){return((Date.now()-Y)/1000).toFixed(1)}}}async openStatusCard($,Z,J="blue"){let Y=Date.now(),Q=K5({sessionName:this.sessionName,title:$,status:FX(Z,Y),template:J}),H=await d(this.chatId,Q);if(!H)return A(`session "${this.sessionName}": status card send failed title=${$}`),await w(this.chatId,`❌ 创建状态卡片失败: ${$}`),null;let W;try{W=await Q$(H)}catch(X){return A(`session "${this.sessionName}": status card id_convert failed title=${$}: ${X}`),await w(this.chatId,`❌ 状态卡片初始化失败: ${$}`),null}return o0(W,1),{cardId:W,title:$,timer:this.startFooterTimer(W,Z,(X)=>V4($,X))}}setStatusCard($,Z){$?.timer.setStatus(Z)}async closeStatusCard($,Z){if(!$)return;$.timer.stop();let J=$.timer.elapsedSec(),Y=V4($.title,`${Z} (${J}s)`);await g0($.cardId);let Q=await K0($.cardId,R.footer,this.footerElement(Y));q0($.cardId);let H=await L0($.cardId,L$({durationSec:J,suffix:Z}));if(Q&&H)await c0($.cardId);else{let W=`footer=${Q?"ok":"MISS"}, settings=${H?"ok":"MISS"}`;A(`session "${this.sessionName}": status card terminal transaction incomplete card=${$.cardId.slice(0,12)} ${W}`),await w(this.chatId,`⚠️ 状态卡片终态写入失败 (${W}):${Z}`)}}async runLifecycle($,Z){let J=this.lifecycleTail,Y;this.lifecycleTail=new Promise((H)=>{Y=H}),await J;let Q=++this.lifecycleSequence;A(`session "${this.sessionName}": lifecycle#${Q} ${$} begin`);try{return await Z()}finally{Y(),A(`session "${this.sessionName}": lifecycle#${Q} ${$} end`)}}beginTurnOpen($=this.proc,Z=this.procEpoch,J=!1){if(this.openingTurnOwner)throw Error(`turn card open already owned by token=${this.openingTurnOwner.token}; same-process opens must wait for the current owner`);let Y,Q=new Promise((W)=>{Y=W}),H={token:++this.turnOpenSequence,proc:$,procEpoch:Z,sawResult:!1,terminalForcePush:!1,pendingCompactions:[],backendTurnStarted:J,done:Q,resolveDone:Y};return this.openingTurnOwner=H,this.openingTurn=!0,H}ownsTurnOpen($){return this.openingTurnOwner===$&&this.proc===$.proc&&this.procEpoch===$.procEpoch}releaseTurnOpen($){if(this.openingTurnOwner!==$)return;this.openingTurnOwner=null,this.openingTurn=!1,$.resolveDone()}invalidateTurnOpen(){let $=this.openingTurnOwner;this.openingTurnOwner=null,this.openingTurn=!1,$?.resolveDone()}async waitForTurnOpenSlot($,Z){while(this.openingTurnOwner)if(await this.openingTurnOwner.done,this.proc!==$||this.procEpoch!==Z||!$.isAlive())return!1;return this.proc===$&&this.procEpoch===Z&&$.isAlive()}beginBackgroundOpen(){if(this.backgroundCard||this.openingBackgroundOwner)return null;let $={token:++this.backgroundOpenSequence,proc:this.proc,procEpoch:this.procEpoch,generation:this.backgroundGeneration};return this.openingBackgroundOwner=$,this.openingBackground=!0,$}ownsBackgroundOpen($){return this.openingBackgroundOwner===$&&this.backgroundGeneration===$.generation&&this.proc===$.proc&&this.procEpoch===$.procEpoch}releaseBackgroundOpen($){if(this.openingBackgroundOwner!==$)return;this.openingBackgroundOwner=null,this.openingBackground=!1}invalidateBackgroundOpen(){this.backgroundGeneration++,this.openingBackgroundOwner=null,this.openingBackground=!1}attachProc($){this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.stoppingProc=null,this.blockedProc=null,this.blockedProcReason=null,this.proc=$;let Z=++this.procEpoch;this.wireProc($,Z)}detachProc($){if(this.proc!==$)return!1;if(this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.proc=null,this.agentCapability=null,this.stoppingProc===$)this.stoppingProc=null;if(this.blockedProc===$)this.blockedProc=null,this.blockedProcReason=null;return this.procEpoch++,!0}beginProcStop($){this.stoppingProc=$,this.agentCapability=null}acceptsAgentCapability($){let Z=this.agentCapability;if(!Z||!$||!this.proc?.isAlive())return!1;let J=Buffer.from(Z),Y=Buffer.from($);return J.length===Y.length&&HL(J,Y)}async cancelAgentRuns($="用户取消"){await this.opts.onCancelAgentRuns?.(this.sessionName,this.chatId,$)}finishProcStop($,Z){if(this.stoppingProc===$)this.stoppingProc=null;if(!$.isAlive())return this.discardPendingCodexTurnAnchors($,"confirmed process stop"),this.detachProc($),!0;return this.blockedProc=$,this.blockedProcReason=Z?U(Z):"kill returned while process still reports alive",A(`session "${this.sessionName}": process stop unconfirmed; lifecycle blocked: ${this.blockedProcReason}`),!1}blockedProcessMessage(){let $=this.blockedProc;if(!$)return null;if(!$.isAlive())return this.detachProc($),null;return`旧 ${this.backendLabel($.provider)} 进程尚未确认退出,会话已阻断: ${this.blockedProcReason??"未知原因"}`}async stopOwnedProc($,Z){if(this.proc!==$)return!$.isAlive();this.beginProcStop($);let J=null;try{await $.kill(Z)}catch(Y){J=Y}return this.finishProcStop($,J)}async settleProcResumableState($){let Z=null,J=$.conversationMaterializationBarrier?.();if(J)try{await J}catch(H){Z=`Codex 会话落盘确认失败: ${U(H)}`}let Y=$.conversationMaterializationFailure?.();if(Y&&$.isConversationResumable?.()!==!0)Z=`Codex 会话落盘确认失败: ${U(Y)}`;let Q=this.persistResumableSessionId(!1,$,!1);return[Z,Q].filter(Boolean).join(";")||null}resetFreshConversationState(){this.turnCounter=0,this.pendingConversationMaterialization=null,n0(this.sessionName,[],{kind:"fresh"},null),this.currentGoal=null,this.cumStats={tokens:0,costUsd:0,turns:0},this.lastTurnDelta=null,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.lastTurnUsage=null,this.usageTotalsSeedUnknown=!1}async start($={}){return await this.runLifecycle("start",()=>this.startUnlocked($))}async startUnlocked($={}){let Z=$.announce??!0,J=$.onStatus,Y=this.blockedProcessMessage();if(Y){if(this.status="stopped",J?.(`❌ ${Y}`),Z)await T(this.chatId,`❌ ${Y}。请重试 stop/restart,或等待旧进程退出。`);return!1}if(this.proc&&!this.proc.isAlive())this.detachProc(this.proc);if(this.isRunning()){if(this.proc?.provider===this.selectedProvider)return J?.(this.withModel(`✅ ${this.backendLabel()} 已运行`)),!0;if(await this.stopIdleMismatchedProcessUnlocked(),this.proc?.isAlive())return J?.(`⚠️ 当前 ${this.backendLabel(this.proc.provider)} turn 尚未结束,模型切换将在后续新 turn 生效`),!0}if(this.selectedProvider==="codex")J?.("\uD83D\uDD0E 检查 Codex 登录");else J?.("\uD83D\uDD0E 检查 Claude Code");if(this.selectedProvider==="codex"&&!t2()){if(this.status="stopped",this.opts.onLifecycleChange?.(),J?.("❌ Codex 未登录 ChatGPT 账号"),Z)await T(this.chatId,"❌ Codex 未登录 ChatGPT 账号。\n请在服务器上运行 `codex login` 后再试。");return!1}if(!LX(this.workDir)){if(J?.(`\uD83C\uDD95 创建项目目录 ~/${this.sessionName}`),Z)await T(this.chatId,`\uD83C\uDD95 目录 ~/${this.sessionName} 不存在,正在创建…`);try{c8(this.workDir)}catch(G){if(this.status="stopped",this.opts.onLifecycleChange?.(),J?.(`❌ 创建项目失败: ${G}`),Z)await T(this.chatId,`❌ 创建项目失败: ${G}`);return!1}}if(!$.freshConversationStateAlreadyReset&&!this.pendingConversationMaterialization)this.resetFreshConversationState();this.status="starting",J?.(this.withModel(`\uD83D\uDE80 启动 ${this.backendLabel()}`));let Q;try{await W9(),Q=this.spawnAgent()}catch(G){let _=`${this.backendLabel()} 启动失败: ${U(G)}`;if(A(`session "${this.sessionName}": ${_}`),J?.(`❌ ${_}`),Z)await T(this.chatId,`❌ ${_}`);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}this.attachProc(Q);let H=this.backendLabel(),W=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(Q,jX):null;J?.(this.selectedProvider==="claude"?`⏳ 检查 ${H} 启动`:`⏳ 等待 ${H} init`);let X,V=null;try{Q.sendInitialize(),X=Q.initializationPromise?.()}catch(G){X=void 0,V=G}let z=V?{state:"error",error:V}:this.selectedProvider==="claude"?await W:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(X),()=>{A(`session "${this.sessionName}": codex init still pending after ${p3/1000}s`),J?.(this.withModel(`⏳ 仍在等待 ${H} init 确认`))});if(z.state==="error"||z.state==="exit"){let G=z.error?U(z.error):z.state;A(`session "${this.sessionName}": ${this.selectedProvider} init failed: ${G}`);let K=await this.stopOwnedProc(Q,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,q=`❌ ${H} 启动失败: ${G}${K}`;if(J?.(q),Z)await T(this.chatId,q);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(z.state==="timeout"){A(`session "${this.sessionName}": ${this.selectedProvider} init wait timeout (${k6/1000}s)`);let _=await this.stopOwnedProc(Q,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,K=`❌ ${H} 启动超时: ${k6/1000} 秒内初始化事务未完成${_}`;if(J?.(K),Z)await T(this.chatId,K);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(this.proc!==Q||!Q.isAlive()){let G=`${H} 启动期间已退出`;if(A(`session "${this.sessionName}": ${G}`),J?.(`❌ ${G}`),Z)await T(this.chatId,`❌ ${G}`);return this.detachProc(Q),this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(Z){let G=this.modelLine();await T(this.chatId,[this.withWorktreeInstructionNotice(`✅ Lodestar session "${this.sessionName}" 已就绪,发消息开始对话。`),G].filter(Boolean).join(`
|
|
197
|
-
`))}return this.status="idle",this.startedAt=Date.now(),this.opts.onLifecycleChange?.(),J?.(this.withModel(this.withWorktreeInstructionNotice(`✅ ${this.backendLabel()} 已就绪`))),!0}requireCodexInitializationPromise($){if(!$||typeof $.then!=="function")return Promise.reject(Error("Codex process did not expose its initialization transaction"));return Promise.resolve($)}async waitForCodexInitialization($,Z){return await new Promise((J)=>{let Y=!1,Q=(X,V)=>{if(Y)return;Y=!0,clearTimeout(H),clearTimeout(W),J({state:X,error:V})},H=setTimeout(()=>{if(Y)return;try{Z?.()}catch(X){Q("error",X)}},p3),W=setTimeout(()=>{Q("timeout",Error(`codex init timed out after ${k6/1000}s`))},k6);$.then(()=>Q("init"),(X)=>Q("error",X))})}async waitForProcEarlyFailure($,Z){return await new Promise((J)=>{let Y=!1,Q=(z,G)=>{if(Y)return;Y=!0,clearTimeout(H),$.off("init",W),$.off("error",X),$.off("exit",V),J({state:z,error:G})},H=setTimeout(()=>Q("ready"),Z),W=()=>Q("init"),X=(z)=>Q("error",z),V=(z)=>Q("exit",z);$.once("init",W),$.once("error",X),$.once("exit",V)})}releaseAllReactions(){for(let[$,Z]of[...this.pendingReactionIds.entries(),...this.currentBatchReactionIds.entries()])if(Z)U0($,Z);this.pendingReactionIds=new Map,this.currentBatchReactionIds=new Map}clearStaleIdleQueueState($){if(this.initCount<1||this.currentTurn||this.openingTurn||this.pendingUserMessageCount===0)return;A(`session "${this.sessionName}": clear stale pending queue before ${$} pendingCount=${this.pendingUserMessageCount} reactions=${this.pendingReactionIds.size}`),this.pendingUserMessageCount=0;for(let[Z,J]of this.pendingReactionIds)if(J)U0(Z,J);this.pendingReactionIds=new Map}async stop($="已终止",Z={}){await this.runLifecycle("stop",()=>this.stopUnlocked($,Z))}async stopUnlocked($="已终止",Z={}){let J=Z.announce??!0,Y=Z.onStatus;if(await this.cancelAgentRuns($),!this.proc){if(this.status="stopped",this.opts.onLifecycleChange?.(),Y?.("⚪ session 当前未运行"),J)await T(this.chatId,`⚪ session "${this.sessionName}" 当前未运行`);return}let Q=this.proc,H=this.persistResumableSessionId(!1,Q,!1),W=null;if(Y?.(`\uD83D\uDED1 停止 ${this.backendLabel(this.proc.provider)}`),A(`session "${this.sessionName}": stop (${$})`),this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.currentTurn)this.closeTurnCard(`\uD83D\uDED1 ${$}`).catch((P)=>{A(`session "${this.sessionName}": stop current main-card close failed: ${U(P)}`)});let X=this.waitForTurnCloses().catch((P)=>A(`session "${this.sessionName}": stop main-card close failed: ${U(P)}`));this.beginProcStop(Q),this.status="stopped";let V=[];try{this.opts.onLifecycleChange?.()}catch(P){V.push(P),A(`session "${this.sessionName}": stop intent lifecycle write failed: ${U(P)}`)}let z=Q.conversationMaterializationBarrier?.();if(z){try{await z}catch(P){W=`Codex 会话落盘确认失败: ${U(P)}`}H=this.persistResumableSessionId(!1,Q,!1)}this.clearMultiMsgBuffer("stop"),this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),this.initCount=0,this.invalidateTurnOpen(),this.bgResumePending=!1,this.discardOrphanAssistant(),this.pendingAsks.clear(),this.pendingPermissions.clear(),this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.usageTotalsSeedUnknown=!1;let G=null;try{await Q.kill()}catch(P){G=P}let _=Q.conversationMaterializationFailure?.();if(_&&Q.isConversationResumable?.()!==!0)W=`Codex 会话落盘确认失败: ${U(_)}`;H=this.persistResumableSessionId(!1,Q,!1);let q=(await Promise.allSettled([this.resetBackgroundTasks(),X])).filter((P)=>P.status==="rejected").map((P)=>P.reason);for(let P of q)A(`session "${this.sessionName}": stop terminal cleanup failed: ${U(P)}`);let D=this.finishProcStop(Q,G);try{this.opts.onLifecycleChange?.()}catch(P){V.push(P),A(`session "${this.sessionName}": stop final lifecycle write failed: ${U(P)}`)}let L=[...G?[G]:[],...!D&&!G?[Error(this.blockedProcReason??"process stop unconfirmed")]:[],...q,...V,...H?[Error(H)]:[],...W&&Q.isConversationResumable?.()!==!0?[Error(W)]:[]];if(L.length===1)throw L[0];if(L.length>1)throw AggregateError(L,`stop failed: ${L.map(U).join("; ")}`);if(Y?.(`✅ ${$}`),J)await T(this.chatId,`\uD83D\uDD34 ${$} (session: ${this.sessionName})`)}async restart($=!1,Z={}){return await this.runLifecycle("restart",()=>this.restartUnlocked($,Z))}async restartUnlocked($=!1,Z={},J){let Y=Z.announce??!0,Q=Z.onStatus,H=this.status,W=null;if(!$&&!this.pendingConversationLaunch&&this.pendingConversationMaterialization)W=this.pendingConversationMaterialization,k$(this.sessionName,null),this.pendingConversationMaterialization=null;let X=this.pendingConversationLaunch??this.pendingMaterializationLaunch(),V=this.lastSessionRef;if($&&!X&&V?.cwd===null)try{V=await this.resolveLegacyResumeRef(V),this.lastSessionRef=V,this.lastSessionId=V.sessionId}catch(S){let x=this.invalidateMissingCodexResume(V.sessionId,S,J),c=x?`❌ 旧会话不可恢复: ${U(S)};${x}`:`❌ 旧会话 cwd 校验失败: ${U(S)};请在进程已停时发送 rs 重新选择历史会话`;if(this.status=this.proc?.isAlive()?H:"stopped",Q?.(c),Y)await T(this.chatId,c);return!1}let z=V?.sessionId??null,G=X&&X.kind!=="fresh"?X.source.sessionId:z,_=G?B0(G):"",K=null,q=(S=this.proc)=>{if(!$||X||S?.provider!=="codex"||S.isConversationResumable?.()!==!0)return;K=this.persistResumableSessionId(!1,S,!1),V=this.lastSessionRef,z=V?.sessionId??null,G=z,_=G?B0(G):""},D=null;if(!Q&&Y&&$&&z){let S=this.proc?this.withModel(`\uD83D\uDD01 重启 ${this.backendLabel(this.proc.provider)}`):this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${_}`);if(D=await this.openStatusCard("restart",S),D)Q=(x)=>this.setStatusCard(D,x)}let L=Y&&!D,P=async(S)=>{if(D)await this.closeStatusCard(D,S)},N=Boolean(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0||this.pendingTurnInputs.length>0||this.backgroundTasks.length>0||this.pendingBgTasks.length>0||this.openingBackground);if(this.bgResumePending=!1,this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.discardOrphanAssistant(),this.currentTurn)this.closeTurnCard("\uD83D\uDD01 已中止,正在重启").catch((S)=>{A(`session "${this.sessionName}": restart current main-card close failed: ${U(S)}`)});let F=this.waitForTurnCloses().catch((S)=>A(`session "${this.sessionName}": restart main-card close failed: ${U(S)}`)),j=null,M=null;if(this.proc){let S=this.proc;Q?.(`\uD83D\uDED1 停止当前 ${this.backendLabel(S.provider)}`),M=S,this.beginProcStop(S);let x=S.conversationMaterializationBarrier?.();if(x)try{await x}catch(O){K=`Codex 会话落盘确认失败: ${U(O)}`}if(q(S),$&&!X&&K&&!N&&S.isAlive()){if(this.stoppingProc===S)this.stoppingProc=null;this.status=H;let O=`❌ ${this.backendLabel(S.provider)} 恢复点尚未安全落盘,已保留当前进程: ${K}`;if(A(`session "${this.sessionName}": abort restart before kill: ${K}`),Q?.(O),L)await T(this.chatId,O);return await P(O),!1}try{await S.kill()}catch(O){j=O}let c=S.conversationMaterializationFailure?.();if(c&&S.isConversationResumable?.()!==!0)K=`Codex 会话落盘确认失败: ${U(c)}`;q(S)}this.clearMultiMsgBuffer("restart"),this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),this.initCount=0,this.invalidateTurnOpen(),this.pendingAsks.clear(),this.pendingPermissions.clear(),this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;let b=(await Promise.allSettled([this.resetBackgroundTasks(),F])).filter((S)=>S.status==="rejected").map((S)=>S.reason);for(let S of b)A(`session "${this.sessionName}": restart terminal cleanup failed: ${U(S)}`);let m=M?this.finishProcStop(M,j):!0,y=[...j?[`kill=${U(j)}`]:[],...!m&&!j?[`kill=${this.blockedProcReason??"process stop unconfirmed"}`]:[],...b.map((S)=>`cleanup=${U(S)}`),...K?[`resume=${K}`]:[]];if(y.length>0&&W)try{k$(this.sessionName,W),this.pendingConversationMaterialization=W}catch(S){y.push(`pendingRestore=${U(S)}`)}if(y.length>0){let S=`❌ 旧 ${this.backendLabel()} 进程停止/清理失败: ${y.join("; ")}`;if(this.status="stopped",this.opts.onLifecycleChange?.(),Q?.(S),L)await T(this.chatId,S);return await P(S),!1}let h=X?.kind==="resume"||X?.kind==="fork";if($&&V||h){this.status="starting",this.usageTotalsSeedUnknown=!0,Q?.(this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${_}`));let S;try{await W9(),S=this.spawnAgent(V??void 0)}catch(z0){let N0=`❌ ${this.backendLabel()} 恢复失败: ${U(z0)}`;if(A(`session "${this.sessionName}": ${this.selectedProvider} resume failed before spawn: ${U(z0)}`),Q?.(N0),L)await T(this.chatId,N0);return this.status="stopped",this.opts.onLifecycleChange?.(),await P(N0),!1}this.attachProc(S);let x=this.backendLabel(),c=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(S,jX):null;Q?.(this.selectedProvider==="claude"?`⏳ 检查 ${x} 恢复启动`:`⏳ 等待 ${x} init 确认`);let O,k=null;try{S.sendInitialize(),O=S.initializationPromise?.()}catch(z0){O=void 0,k=z0}let f=k?{state:"error",error:k}:this.selectedProvider==="claude"?await c:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(O),()=>{A(`session "${this.sessionName}": codex resume init still pending after ${p3/1000}s`),Q?.(this.withModel(`⏳ 仍在等待 ${x} init 确认 thread=${_}`))});if(f.state==="error"||f.state==="exit"||f.state==="timeout"){let z0=f.state==="error"?this.invalidateMissingCodexResume(G,f.error,J):null,N0=[f.error?U(f.error):f.state,z0].filter(Boolean).join(";");A(`session "${this.sessionName}": ${this.selectedProvider} resume failed: ${N0}`);let D2=await this.stopOwnedProc(S,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,l0=f.state==="timeout"?`❌ ${x} 恢复超时${D2}`:`❌ ${x} 恢复失败: ${N0}${D2}`;if(Q?.(l0),L)await T(this.chatId,l0);return this.status="stopped",this.opts.onLifecycleChange?.(),await P(l0),!1}if(this.proc!==S||!S.isAlive()){let z0=`❌ ${x} 恢复期间已退出`;if(A(`session "${this.sessionName}": ${this.selectedProvider} resume process exited before ready`),Q?.(z0),L)await T(this.chatId,z0);return this.detachProc(S),this.status="stopped",this.opts.onLifecycleChange?.(),await P(z0),!1}let E0=this.withModel(this.withWorktreeInstructionNotice(this.selectedProvider==="claude"&&f.state==="ready"?`✅ 已准备恢复上一会话 thread=${_}`:`✅ 已恢复上一会话 thread=${_}`));if(Q?.(E0),L)await T(this.chatId,E0);this.status="idle",this.startedAt=Date.now(),this.opts.onLifecycleChange?.();try{await P(E0)}catch(z0){A(`session "${this.sessionName}": restart succeeded but status-card close failed: ${U(z0)}`),await w(this.chatId,`⚠️ ${E0}
|
|
198
|
-
状态卡收尾失败: ${U(z0)}`)}return!0}else{if($&&!X){if(Q?.("⚠️ 没有可恢复的上一会话,将以新会话启动"),L)await T(this.chatId,"⚠️ 没有可恢复的上一会话,将以新会话启动")}return this.resetFreshConversationState(),await this.startUnlocked({...Z,freshConversationStateAlreadyReset:!0})}}async startForked($,Z={}){return await this.runLifecycle("start-forked",async()=>{H0($,this.selectedProvider,this.workDir);let J=d2(this.sessionName),Y=this.selectedProvider==="claude"?{launch:$,previousSessionId:this.lastSessionId}:null;if(Y)k$(this.sessionName,Y),this.pendingConversationMaterialization=Y;this.pendingConversationLaunch=$;try{let Q=await this.startUnlocked(Z);if(!Q&&Y)k$(this.sessionName,J),this.pendingConversationMaterialization=J;return Q}catch(Q){if(!Y)throw Q;try{k$(this.sessionName,J),this.pendingConversationMaterialization=J}catch(H){throw AggregateError([Q,H],`fork start and pending-intent restore failed: ${U(Q)}; ${U(H)}`)}throw Q}finally{this.pendingConversationLaunch=null}})}async rollbackTo($,Z,J={}){return await this.runLifecycle("rollback",async()=>{H0($,this.selectedProvider,this.workDir);let Y=Z?{anchors:Z.anchors.slice(),base:Z.base,pendingLaunch:Z.pendingLaunch!==void 0?Z.pendingLaunch:this.selectedProvider==="claude"&&$.kind==="fork"?{launch:$,previousSessionId:this.lastSessionId}:null}:null,Q=this.proc,H=this.lastSessionId,W=this.lastSessionRef,X=l2(this.sessionName).slice(),V=i2(this.sessionName),z=d2(this.sessionName),G={turnCounter:this.turnCounter,currentGoal:this.currentGoal,cumStats:{...this.cumStats},lastTurnDelta:this.lastTurnDelta?{...this.lastTurnDelta}:null,currentTurnUsageBaseline:this.currentTurnUsageBaseline?{...this.currentTurnUsageBaseline}:null,currentTurnUsageBaselineKnown:this.currentTurnUsageBaselineKnown,lastTurnUsage:this.lastTurnUsage?{...this.lastTurnUsage}:null,usageTotalsSeedUnknown:this.usageTotalsSeedUnknown},_=!1,K=()=>{if(_)this.lastSessionId=null,this.lastSessionRef=null,l1(this.sessionName,"codex");else if(this.lastSessionId=H,this.lastSessionRef=W,W)p2(this.sessionName,W);else l1(this.sessionName,this.selectedProvider);n0(this.sessionName,X,V,z),this.pendingConversationMaterialization=z,this.turnCounter=G.turnCounter,this.currentGoal=G.currentGoal,this.cumStats=G.cumStats,this.lastTurnDelta=G.lastTurnDelta,this.currentTurnUsageBaseline=G.currentTurnUsageBaseline,this.currentTurnUsageBaselineKnown=G.currentTurnUsageBaselineKnown,this.lastTurnUsage=G.lastTurnUsage,this.usageTotalsSeedUnknown=G.usageTotalsSeedUnknown},q=!1;if(Y?.pendingLaunch)n0(this.sessionName,Y.anchors,Y.base,Y.pendingLaunch),this.pendingConversationMaterialization=Y.pendingLaunch,q=!0;this.pendingConversationLaunch=$;let D=(L)=>{_=W?.provider==="codex"&&W.sessionId===L};try{let L;try{L=$.kind==="fresh"?await this.restartUnlocked(!1,J,D):await this.restartUnlocked(!0,J,D)}catch(P){let N=null,F=this.proc&&this.proc!==Q?this.proc:null;if(F)try{await this.stopUnlocked("回滚启动事务失败",{announce:!1})}catch(b){N=b}let j=!F||this.proc!==F&&!F.isAlive();if(!j&&!N)N=Error("replacement process stop was not confirmed");let M=null;if(j)try{K()}catch(b){M=b}let C=[P,...N?[N]:[],...M?[M]:[]];if(C.length===1)throw P;throw AggregateError(C,`rollback launch and cleanup failed: ${C.map(U).join("; ")}`)}if(!L)return K(),!1;if(Y)try{if(!q)n0(this.sessionName,Y.anchors,Y.base,Y.pendingLaunch);this.pendingConversationMaterialization=Y.pendingLaunch}catch(P){let N=null,F=this.proc;try{await this.stopUnlocked("回滚分支状态持久化失败",{announce:!1})}catch(b){N=b}let j=!F||this.proc!==F&&!F.isAlive();if(!j&&!N)N=Error("replacement process stop was not confirmed");let M=null;if(j)try{K()}catch(b){M=b}let C=[P,...N?[N]:[],...M?[M]:[]];if(C.length===1)throw P;throw AggregateError(C,`rollback branch commit failed: ${C.map(U).join("; ")}`)}return L}finally{this.pendingConversationLaunch=null}})}dispose(){t0.all.delete(this)}recordTurnAnchor($){let Z=this.proc;if(!Z?.sessionId||!$)return null;if($.provider!==Z.provider||$.source.sessionId!==Z.sessionId||$.source.cwd!==this.workDir){let Y=`拒绝了与当前会话不匹配的 checkpoint provider=${$.provider} source=${$.source.sessionId}`;return A(`session "${this.sessionName}": ${Y}`),this.lastTurnUserPreview="",Y}let J={checkpoint:$,preview:this.lastTurnUserPreview.slice(0,80),ts:Date.now(),writes:this.collectTurnWrites()};if(this.lastTurnUserPreview="",Z.provider==="codex"&&Z.isConversationResumable?.()!==!0){if(this.pendingCodexTurnAnchors.filter((Q)=>Q.proc===Z).length>=64)return A(`session "${this.sessionName}": ${"Codex rollout 长期未确认,延迟 checkpoint 队列已满"} thread=${Z.sessionId}`),"Codex rollout 长期未确认,延迟 checkpoint 队列已满";return this.pendingCodexTurnAnchors.push({proc:Z,anchor:J}),A(`session "${this.sessionName}": defer Codex turn checkpoint until rollout confirmation thread=${Z.sessionId} checkpoint=${$.id}`),null}return this.appendTurnAnchor(J)}appendTurnAnchor($){try{return T8(this.sessionName,$),null}catch(Z){let J=`分叉 checkpoint 持久化失败: ${U(Z)}`;return A(`session "${this.sessionName}": ${J}`),J}}flushPendingCodexTurnAnchors($){let Z=null,J=[];for(let Y of this.pendingCodexTurnAnchors){if(Y.proc!==$||Z){J.push(Y);continue}if(Z=this.appendTurnAnchor(Y.anchor),Z)J.push(Y)}return this.pendingCodexTurnAnchors=J,Z}discardPendingCodexTurnAnchors($,Z){if($.provider!=="codex")return;let J=this.pendingCodexTurnAnchors.length;this.pendingCodexTurnAnchors=this.pendingCodexTurnAnchors.filter((Q)=>Q.proc!==$);let Y=J-this.pendingCodexTurnAnchors.length;if(Y>0)A(`session "${this.sessionName}": dropped ${Y} unmaterialized Codex checkpoint(s): ${Z}`)}collectTurnWrites(){let $=this.currentTurn;if(!$)return[];let Z=[];for(let J of $.toolByUseId.values())Z.push(...S5(J.name,J.input));return Z}worktreeProjectName(){return m$(this)}worktreeProjectDir(){return A2(this)}spawnDeveloperInstructions(){return oW(this)}delegatedAgentDeveloperInstructions($){return rW(this,$)}worktreeInstructionLoadedNotice(){return I3(this)}withWorktreeInstructionNotice($){return tW(this,$)}worktreeExtraInstruction(){return O4(this)}runWorktreeCommand($,Z){return sW(this,$,Z)}showWorktrees(){return g3(this)}showTasklistPanel(){return NW(this)}showAgentIdentityPanel($=""){return PW(this,$)}onAgentIdentityPage($,Z,J){return jW($,Z,J)}onTasklistEnable(){return SW(this)}onTasklistDeletePrompt($){return xW(this,$)}onTasklistDeleteConfirm($){return kW(this,$)}runCompactCommand(){return WW(this)}showModelPanel(){return VW(this)}onModelSelect($,Z="",J="",Y=null){return this.runLifecycle("model-select",()=>qW(this,$,Z,J,Y))}onModelEffortSelect($,Z,J="",Y="",Q=""){return this.runLifecycle("model-effort-select",()=>T3(this,$,Z,J,Y,Q))}onProviderSelect($,Z=""){return O3(this,$,Z)}onModelPage($,Z,J){return P6(this,$,Z,J)}onModelAddOpen($,Z){return zW(this,$,Z)}onModelListEdit($,Z,J,Y){return this.runLifecycle("model-list-edit",()=>GW(this,$,Z,J,Y))}onModelPanelCancel($=""){return KW(this,$)}onModelCustomPrompt($,Z,J=""){return AW(this,$,Z,J)}consumeModelCustomMessage($,Z){return _W(this,$,Z)}onWorktreeDisband($){return $X(this,$)}showForkList($=""){return XX(this,$)}showBackList($=""){return VX(this,$)}showResumeList($=""){return zX(this,$)}runBtwCommand($){return GX(this,$)}runByeCommand(){return AX(this)}onForkSelect($,Z,J=""){return _X(this,$,Z,J)}onBackSelect($,Z,J=""){return KX(this,$,Z,J)}onResumeSelect($,Z,J=""){return BX(this,$,Z,J)}runCommand($,Z=""){return QW(this,$,Z)}async buildConsoleOpts($,Z){let J=await qQ(),Y=this.runtimeModelSelection();return{sessionName:this.sessionName,status:this.status,provider:Y.provider,model:Y.model??void 0,effort:Y.effort??"MISS",worktreeInstructionNotice:this.worktreeInstructionLoadedNotice(),peers:[...t0.all].filter((Q)=>Q.isRunning()).map((Q)=>({...Q.peerSnapshot(),isCurrent:Q===this})),usage:$,glmUsage:Z,sysinfo:J}}async buildConsoleCard($){return q5(await this.buildConsoleOpts($))}async patchConsoleUsage($){let Z=await this.buildConsoleOpts(void 0),J=Z.provider??this.currentProvider(),Y=this.currentTokenSource(),Q=Y&&Y.agent===J&&Y.enabled?Y:this.selectedTokenSourceId?void 0:H9(J)[0];if(Q)Z.unifiedUsage=await Q.readUsage();else if(this.selectedTokenSourceId)Z.unifiedUsage={state:"no_credentials",windows:[],reason:`token source ${this.selectedTokenSourceId} unavailable`};else if(Z.provider==="claude")Z.glmUsage=await nQ();else Z.usage=await Q6();if(!await K0($,R.consoleUsage,z4(Z),{notifyCardFailure:!1}))throw Error("console usage element replace rejected")}async mutateStaticCard($,Z,J){let Y=!0;try{await J()}catch(H){Y=!1,A(`session "${this.sessionName}": ${Z} mutation failed: ${U(H)}`)}let Q=!1;try{Q=await L0($,{config:{streaming_mode:!1}})}catch(H){A(`session "${this.sessionName}": ${Z} streaming-off failed: ${U(H)}`)}if(!Y||!Q)return A(`session "${this.sessionName}": ${Z} state retained after checked MISS mutation=${Y} streamingOff=${Q} card=${$.slice(0,12)}`),!1;try{await c0($)}catch(H){return A(`session "${this.sessionName}": ${Z} dispose failed: ${U(H)}`),!1}return Y}patchConsoleUsageLater($){this.mutateStaticCard($,"console usage",()=>this.patchConsoleUsage($))}async replaceStatusCardWithConsole($,Z){$.timer.stop();let J=$.timer.elapsedSec(),Y=await this.buildConsoleOpts(void 0);await g0($.cardId);let Q=await K0($.cardId,R.footer,u9(Y,R.footer)),H=await b$($.cardId,m9(Y),{type:"insert_after",targetElementId:R.footer}),W=await b$($.cardId,p9(Y.sysinfo),{type:"insert_after",targetElementId:R.consoleProjects}),X=await b$($.cardId,z4(Y),{type:"insert_after",targetElementId:R.consoleHost});if(!Q||!H||!W||!X){await w(this.chatId,"⚠️ 控制台卡片结构写入失败,请重新发送 hi。"),await this.mutateStaticCard($.cardId,"console structure",async()=>{});return}q0($.cardId),await L0($.cardId,L$({durationSec:J,suffix:Z})),this.patchConsoleUsageLater($.cardId)}async showConsole(){let $=await this.buildConsoleCard(void 0),Z=await d(this.chatId,$);if(!Z)return;(async()=>{let J="";try{J=await Q$(Z),o0(J,4)}catch(Y){A(`session "${this.sessionName}": console card conversion failed: ${U(Y)}`);return}await this.mutateStaticCard(J,"console usage",()=>this.patchConsoleUsage(J))})().catch((J)=>A(`session "${this.sessionName}": console async update rejected: ${U(J)}`))}interrupt(){if(!this.proc)return;A(`session "${this.sessionName}": interrupt`),this.proc.sendInterrupt()}sendClaimedUserText($,Z){this.pendingUserMessageCount++;try{$.sendUserText(Z,[])}catch(J){throw this.pendingUserMessageCount=Math.max(0,this.pendingUserMessageCount-1),J}}async startColdUserTurn($,Z,J){if(!this.pendingConversationMaterialization)this.resetFreshConversationState();this.pendingTurnInputs.push($);let Y=this.beginTurnOpen();try{let H=await this.openTurnCard(Y,J,"user_message",{initialFooter:"Waiting...(0s)",startThinking:!1,directStart:!0});if(!H||this.currentTurn!==H)return;let W=this.startFooterTimer(H.cardId,`\uD83D\uDE80 启动 ${this.backendLabel()}`,(G)=>this.withModel(G)),X=`\uD83D\uDE80 启动 ${this.backendLabel()}`,V=await this.startUnlocked({announce:!1,freshConversationStateAlreadyReset:!0,onStatus:(G)=>{X=G,W.setStatus(G)}});if(W.stop(),await g0(H.cardId),!V){this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),await this.closeTurnCard(X.startsWith("❌")?X:"❌ 启动失败",{forcePush:!0});return}let z=this.proc;if(!z?.isAlive()){await this.closeTurnCard(`❌ ${this.backendLabel()} 启动后已退出`,{forcePush:!0});return}this.startThinkingFooter(H),this.sendClaimedUserText(z,Z),this.status="working"}finally{this.releaseTurnOpen(Y)}}async onUserMessage($,Z=[],J="",Y=""){await this.runLifecycle("user-message",()=>this.onUserMessageUnlocked($,Z,J,Y))}async onUserMessageUnlocked($,Z,J,Y){let Q=this.blockedProcessMessage();if(Q){await T(this.chatId,`❌ ${Q}。请重试 stop/restart,或等待旧进程退出。`);return}if(this.clearStaleIdleQueueState("user_message"),this.proc?.isAlive()&&!this.currentTurn&&!this.openingTurn&&this.pendingUserMessageCount===0&&this.pendingMidTurnMsgs.length===0)await this.stopIdleMismatchedProcessUnlocked();let H=this.currentTurn!==null||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0;this.lastUserOpenId=J;let X=(Z.length?Z.map((z)=>`[file: ${z}]`).join(" ")+`
|
|
199
|
-
`:"")+$,V=(z)=>{this.pendingReactionIds.set(z,""),(async()=>{let G=await b0(z,"OneSecond");if(!G)return;if(this.pendingReactionIds.has(z))this.pendingReactionIds.set(z,G);else if(this.currentBatchReactionIds.has(z))this.currentBatchReactionIds.set(z,G);else U0(z,G)})().catch((G)=>{A(`session "${this.sessionName}": reaction tracking failed: ${U(G)}`)})};if(!this.isRunning()){if(this.openingTurn||this.currentTurn){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Y}),Y)V(Y);return}await this.startColdUserTurn($,X,J);return}if(this.currentTurn!==null){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Y}),Y)V(Y);return}if(!this.openingTurn&&this.initCount>=1){let z=this.proc,G=this.procEpoch,_=this.beginTurnOpen(z,G);try{this.pendingTurnInputs.push($);let K=await this.openTurnCard(_,J,"user_message");if(!K||this.currentTurn!==K)return;if(this.proc!==z||this.procEpoch!==G||!z.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel(z.provider)} 已退出`);return}this.sendClaimedUserText(z,X),this.status="working"}finally{this.releaseTurnOpen(_)}return}if(this.openingTurn||this.pendingUserMessageCount>0){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Y}),Y)V(Y);return}if(this.pendingTurnInputs.push($),this.sendClaimedUserText(this.proc,X),H&&Y)V(Y)}hasPendingAsk(){return MH(this)}refreshPendingAsks(){G6(this)}askBlockReason($){return Q2(this,$)}onMultiMessageInbound($,Z,J,Y){return eQ(this,$,Z,J,Y)}clearMultiMsgBuffer($){l5(this,$)}onAskMessageAnswer($,Z,J){return RH(this,$,Z,J)}onAskAnswer($,Z,J,Y){return UH(this,$,Z,J,Y)}onAskCustomAnswer($,Z,J,Y){return Z3(this,$,Z,J,Y)}onPermissionDecision($,Z,J){return xH(this,$,Z,J)}clearResumeBindingForFreshCodex($){if($.isConversationResumable?.())throw Error("fresh Codex thread was unexpectedly marked resumable during init");let Z=Q1(this.sessionName,"codex");if(l1(this.sessionName,"codex"),this.selectedProvider==="codex")this.lastSessionRef=null,this.lastSessionId=null;if(Z)A(`session "${this.sessionName}": cleared pre-fresh Codex resume binding thread=${Z.sessionId}`)}invalidateMissingCodexResume($,Z,J){if(!$||this.selectedProvider!=="codex")return null;let Y=l3(Z);if(!Y||!["thread/read","thread/resume","thread/fork"].includes(Y.method)||Y.serverCode!==-32600||Y.serverMessage!==`no rollout found for thread id ${$}`)return null;let Q=Q1(this.sessionName,"codex");if(!Q||Q.sessionId!==$)return null;try{l1(this.sessionName,"codex")}catch(W){let X=`已确认恢复点无 rollout,但作废失败: ${U(W)}`;return A(`session "${this.sessionName}": ${X} thread=${$}`),X}if(this.lastSessionRef?.provider==="codex"&&this.lastSessionRef.sessionId===$)this.lastSessionRef=null,this.lastSessionId=null;J?.($);let H=`已作废无 rollout 的恢复点 thread=${B0($)}`;return A(`session "${this.sessionName}": ${H} fullThread=${$}`),H}persistResumableSessionId($=!1,Z=this.proc,J=!0){let Y=Z?.provider==="claude"?this.pendingConversationMaterialization:null,Q=Z?.sessionId;if(!Z)return null;if(Z.provider==="codex"&&Z.isConversationResumable?.()!==!0)return null;if(!Q){if(!Y)return null;let X=Error("Claude pending fork did not provide a materialized session id");if(A(`session "${this.sessionName}": ${X.message}`),$)throw X;return X.message}let H={provider:Z.provider,sessionId:Q,cwd:this.workDir};if(Y&&(Q===Y.launch.source.sessionId||Y.previousSessionId!==null&&Q===Y.previousSessionId)){let X=Error(`Claude fork did not materialize an independent session id (${Q})`);if(A(`session "${this.sessionName}": ${X.message}`),$)throw X;return X.message}try{p2(this.sessionName,H)}catch(X){let V=`会话恢复点持久化失败: ${U(X)}`,z=this.resumePersistenceError!==V;if(this.resumePersistenceError=V,Z.provider===this.selectedProvider)this.lastSessionRef=H,this.lastSessionId=Q;if(A(`session "${this.sessionName}": ${V}`),$)throw X;if(z&&J)w(this.chatId,`⚠️ ${V};当前进程可继续,但 daemon 重启前请先解决本机状态目录写入问题。`);return V}if(Z.provider===this.selectedProvider)this.lastSessionRef=H,this.lastSessionId=Q;let W=Z.provider==="codex"?this.flushPendingCodexTurnAnchors(Z):null;if(W){let X=this.resumePersistenceError!==W;if(this.resumePersistenceError=W,$)throw Error(W);if(X&&J)w(this.chatId,`⚠️ ${W}`);return W}return this.resumePersistenceError=null,null}consumePendingConversationMaterialization(){let $=this.pendingConversationMaterialization;if(!$)return null;let Z=this.lastSessionRef;if(Z?.provider!=="claude"||Z.cwd!==this.workDir||Z.sessionId===$.launch.source.sessionId||Z.sessionId===$.previousSessionId)return A(`session "${this.sessionName}": ${"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker"}`),"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker";try{return k$(this.sessionName,null),this.pendingConversationMaterialization=null,null}catch(J){let Y=`Claude 待生成分支标记清除失败: ${U(J)}`;return A(`session "${this.sessionName}": ${Y}`),Y}}bgStore(){return{active:this.backgroundTasks,pending:this.pendingBgTasks}}applyBgStore($){this.backgroundTasks=$.active,this.pendingBgTasks=$.pending}onMainThreadAdvance(){if(this.pendingBgTasks.length===0)return;this.applyBgStore(m7(this.bgStore())),this.onBackgroundTaskChanged()}bgTaskOwns($){return this.backgroundTasks.some((Z)=>Z.toolUseId===$)||this.pendingBgTasks.some((Z)=>Z.toolUseId===$)}onBackgroundTaskChanged(){if(this.migratingBackgroundCard){this.pendingRebuildBackgroundCard=!0;return}if(!e$(this.backgroundTasks)){if(this.backgroundCard)this.settleBackgroundCard().catch((Z)=>{A(`session "${this.sessionName}": background settle failed: ${U(Z)}`)});return}if(!this.backgroundCard&&!this.openingBackground){this.openBackgroundCard().catch((Z)=>{A(`session "${this.sessionName}": background open failed: ${U(Z)}`)});return}this.scheduleBackgroundRefresh()}async openBackgroundCard(){let $=this.beginBackgroundOpen();if(!$)return;let Z=this.backgroundTasks.slice();try{let J=d7(Z,Date.now(),R1()),Y=await d(this.chatId,J);if(!Y){if(this.ownsBackgroundOpen($))A(`session "${this.sessionName}": background card send failed`);return}let Q;try{Q=await Q$(Y)}catch(H){A(`session "${this.sessionName}": background card id_convert failed: ${H}`);return}if(o0(Q,Z.length),!this.ownsBackgroundOpen($)){await this.terminalizeSupersededCard(Q,"⚠️ 后台任务世代已切换,本卡已作废",!1);return}if(this.backgroundCard={messageId:Y,cardId:Q},this.backgroundDetailAdded=new Set(Z.map((H)=>H.id)),this.backgroundDetailAdding.clear(),A(`session "${this.sessionName}": background card opened cardId=${Q.slice(0,12)} tasks=${Z.length}`),!e$(this.backgroundTasks)){this.settleBackgroundCard().catch((H)=>{A(`session "${this.sessionName}": background settle-after-open failed: ${U(H)}`)});return}this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}finally{this.releaseBackgroundOpen($)}}startBackgroundRefreshTick(){if(this.backgroundRefreshTick)return;let $=()=>{if(this.migratingBackgroundCard||!this.backgroundCard||!e$(this.backgroundTasks))return;let Z=R1(),J=Date.now(),Y=1/0;for(let Q of this.backgroundTasks){if(I0(Q))continue;let H=N$(J-Q.startedAt,Z).nextDelayMs;if(H<Y)Y=H}if(!isFinite(Y))return;this.backgroundRefreshTick=setTimeout(()=>{this.refreshBackgroundCardFull(),$()},Math.max(1,Math.ceil(Y)))};$()}stopBackgroundRefreshTick(){if(this.backgroundRefreshTick)clearTimeout(this.backgroundRefreshTick),this.backgroundRefreshTick=null}scheduleBackgroundRefresh(){if(!this.backgroundCard||this.settlingBackgroundCard||this.migratingBackgroundCard)return;if(this.backgroundRefreshTimer)return;this.backgroundRefreshTimer=setTimeout(()=>{this.backgroundRefreshTimer=null,this.refreshBackgroundCardFull()},1500)}refreshBackgroundCardFull(){if(this.migratingBackgroundCard)return;let $=this.backgroundCard;if(!$)return;let Z=Date.now(),J=R1();for(let Y of this.backgroundTasks)if(!this.backgroundDetailAdded.has(Y.id)){if(this.backgroundDetailAdding.has(Y.id))continue;this.backgroundDetailAdding.add(Y.id),b$($.cardId,f1(Y,Z,J)).then((Q)=>{if(Q)this.backgroundDetailAdded.add(Y.id);else A(`session "${this.sessionName}": background panel add MISS task=${Y.id}`)}).finally(()=>{this.backgroundDetailAdding.delete(Y.id)})}else r($.cardId,C2.panel(Y.id),f1(Y,Z,J));B$($.cardId,o4(this.backgroundTasks))}async resetBackgroundTasks(){if(this.invalidateBackgroundOpen(),this.backgroundTasks.some(($)=>!I0($))){let $=Date.now();this.backgroundTasks=this.backgroundTasks.map((Z)=>I0(Z)?Z:{...Z,status:"killed",endTime:Z.endTime??$})}if(this.pendingBgTasks=[],this.backgroundCard)await this.settleBackgroundCard();if(this.stopBackgroundRefreshTick(),this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;this.backgroundTasks=[],this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear()}async settleBackgroundCard(){if(this.migratingBackgroundCard)try{await this.migratingBackgroundCard}catch(J){A(`session "${this.sessionName}": background migration failed before settle; retry terminal snapshot: ${U(J)}`)}let $=this.backgroundCard;if(!$||this.settlingBackgroundCard)return;this.settlingBackgroundCard=!0;let Z=[...this.backgroundTasks];if(this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;this.stopBackgroundRefreshTick();try{if(await g0($.cardId),await Y$($.messageId,r4(Z)),q0($.cardId),!await L0($.cardId,L$({suffix:"\uD83E\uDDED 后台任务已结束"})))throw Error("background history streaming-off rejected");if(await c0($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((Y)=>!I0(Y)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),A(`session "${this.sessionName}": background card settled cardId=${$.cardId.slice(0,12)} remaining=${this.backgroundTasks.length}`)}finally{if(this.settlingBackgroundCard=!1,this.backgroundCard===$&&e$(this.backgroundTasks))this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(this.backgroundTasks.length>0)this.onBackgroundTaskChanged()}migrateBackgroundCard(){if(this.migratingBackgroundCard)return this.migratingBackgroundCard;let $=this.backgroundCard;if(!$)return Promise.resolve();let Z=this.performBackgroundCardMigration($),J;return J=Z.finally(()=>{if(this.migratingBackgroundCard===J)this.migratingBackgroundCard=null}),this.migratingBackgroundCard=J,J}async performBackgroundCardMigration($){if(this.backgroundCard!==$)return;if(this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;if(this.stopBackgroundRefreshTick(),await g0($.cardId),this.backgroundCard!==$)return;let Z=[...this.backgroundTasks],J=new Set(Z.filter(I0).map((H)=>H.id)),Y=J.size;if(Y>0)await Y$($.messageId,r4(Z));else await Y$($.messageId,n7());if(q0($.cardId),!await L0($.cardId,L$({suffix:"\uD83E\uDDED 已迁移至新卡"})))throw Error("background migration streaming-off rejected");if(await c0($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((H)=>!J.has(H.id)||!I0(H)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),A(`session "${this.sessionName}": background card migrated cardId=${$.cardId.slice(0,12)} terminal=${Y} active=${this.backgroundTasks.length}`)}startScheduledTurnCard($,Z,J,Y){if(this.proc!==$||this.procEpoch!==Z||!$.isAlive())return;if(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.bgResumePending)return;let Q;try{Q=this.beginTurnOpen($,Z,!0)}catch(W){A(`session "${this.sessionName}": scheduled turn-open ownership conflict: ${U(W)}`);return}let H=J.replace(/\s+/g," ").trim();this.lastTurnUserPreview=`⏰ ${H.slice(0,78)}`,A(`session "${this.sessionName}": scheduled wakeup prompt=${Y??"MISS"}`),(async()=>{try{let W=await this.openTurnCard(Q,"","scheduled_wakeup");if(this.proc!==$||this.procEpoch!==Z){if(A(`session "${this.sessionName}": scheduled ${$.provider} turn became stale while opening epoch=${Z}`),W&&this.currentTurn===W)await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);return}if(!W||this.currentTurn!==W){if(!this.ownsTurnOpen(Q))return;if(this.bgResumeCardless=!0,Q.sawResult)Q.sawResult=!1,A(`session "${this.sessionName}": scheduled open failed after result — flushing orphan now`),this.flushOrphanAssistantToChat("scheduled open failed, result already arrived");else A(`session "${this.sessionName}": scheduled open failed — orphan text flush will cover the output`)}else if(Q.sawResult)Q.sawResult=!1,A(`session "${this.sessionName}": scheduled result raced card-open — closing freshly-opened card`),await this.closeTurnCard(Q.terminalSuffix,{forcePush:Q.terminalForcePush,hasFreshResult:!0}),this.status="idle";else this.status="working"}finally{this.releaseTurnOpen(Q)}})().catch((W)=>{A(`session "${this.sessionName}": scheduled turn-open handler failed: ${U(W)}`)})}wireProc($,Z){if(Z===void 0)this.invalidateTurnOpen(),this.invalidateBackgroundOpen();let J=Z??++this.procEpoch;if(Z===void 0&&this.proc!==$)this.proc=$;let Y=()=>this.proc===$&&this.procEpoch===J,Q=!1,H=!1,W=(X,V)=>{$.on(X,(z)=>{if(!Y()){if(!Q)Q=!0,A(`session "${this.sessionName}": ignore stale ${$.provider} event=${String(X)} epoch=${J} currentEpoch=${this.procEpoch}`);return}if(X!=="exit"&&(this.stoppingProc===$||this.blockedProc===$)){if(!H)H=!0,A(`session "${this.sessionName}": ignore ${$.provider} event=${String(X)} while process stop is pending`);return}V(z)})};W("error",(X)=>{A(`session "${this.sessionName}": ${$.provider} process error: ${X}`)}),W("init",()=>{if($.provider==="codex"&&$.launchKind==="fresh")this.clearResumeBindingForFreshCodex($);else this.persistResumableSessionId(!0);if(this.initCount++,A(`session "${this.sessionName}": SDK init#${this.initCount} pendingCount=${this.pendingUserMessageCount} midBuffer=${this.pendingMidTurnMsgs.length} currentTurn=${this.currentTurn?"yes":"no"} openingTurn=${this.openingTurn}`),this.currentTurn||this.openingTurn){if(this.pendingUserMessageCount>0)A(`session "${this.sessionName}": SDK init claimed eager input pendingCount=${this.pendingUserMessageCount}`),this.pendingUserMessageCount=0;return}let X=this.pendingUserMessageCount>0,V=!X&&this.bgResumePending;if(!X&&!V)return;let z=this.lastUserOpenId,G;try{G=this.beginTurnOpen($,J,!0)}catch(q){A(`session "${this.sessionName}": init turn-open ownership conflict: ${U(q)}`);return}if(this.bgResumePending=!1,X)this.pendingUserMessageCount=0,this.currentBatchReactionIds=this.pendingReactionIds,this.pendingReactionIds=new Map;let _=X?[...this.currentBatchReactionIds.keys()]:[],K=()=>{for(let q of _){let D=this.currentBatchReactionIds.get(q);if(this.currentBatchReactionIds.delete(q),D)U0(q,D)}};(async()=>{try{let q=await this.openTurnCard(G,z,X?"user_message":"bg_task_resume");if(!Y()){if(A(`session "${this.sessionName}": ${$.provider} became stale while opening turn card epoch=${J}`),q&&this.currentTurn===q)await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);K();return}if(!q||this.currentTurn!==q){if(!this.ownsTurnOpen(G)){K();return}if(G.sawResult&&G.terminalSuffix)w(this.chatId,G.terminalSuffix);if(X)A(`session "${this.sessionName}": init-path openTurnCard failed — sendInterrupt + release reactions`),this.proc?.sendInterrupt(),K();else if(this.bgResumeCardless=!0,G.sawResult)G.sawResult=!1,A(`session "${this.sessionName}": bg-resume openTurnCard failed, result already arrived — flushing orphan now`),this.flushOrphanAssistantToChat("bg-resume open failed, result already arrived");else A(`session "${this.sessionName}": bg-resume openTurnCard failed — orphan text flush will cover the output`)}else if(G.sawResult)G.sawResult=!1,A(`session "${this.sessionName}": result raced card-open — closing freshly-opened turn card now`),await this.closeTurnCard(G.terminalSuffix,{forcePush:G.terminalForcePush,hasFreshResult:!0}),this.status="idle";else this.status="working"}finally{this.releaseTurnOpen(G)}})().catch((q)=>{A(`session "${this.sessionName}": init turn-open handler failed: ${U(q)}`)})}),W("scheduled_turn_input",({text:X,promptId:V})=>{if($.provider!=="claude"&&$.provider!=="dsh")return;this.startScheduledTurnCard($,J,X,V)}),W("conversation_materialized",({session_id:X,source:V})=>{if($.provider!=="codex")return;if($.sessionId!==X){A(`session "${this.sessionName}": ignore mismatched Codex materialization session=${X} current=${$.sessionId??"MISS"} source=${V}`);return}A(`session "${this.sessionName}": Codex resume point materialized thread=${X} source=${V}`),this.persistResumableSessionId()}),W("conversation_materialization_failed",({session_id:X,source:V,error:z})=>{if($.provider!=="codex"||$.sessionId!==X)return;let G=`Codex 会话落盘确认失败,未写恢复点: ${U(z)}`,_=this.resumePersistenceError!==G;if(this.resumePersistenceError=G,A(`session "${this.sessionName}": ${G} thread=${X} source=${V}`),_)w(this.chatId,`⚠️ ${G}`)}),W("turn_retry",()=>{if(this.currentTurn)this.startThinkingFooter(this.currentTurn)}),W("turn_started",({retry:X})=>{if((this.currentTurn||this.openingTurn)&&this.pendingUserMessageCount>0)A(`session "${this.sessionName}": turn_started claimed eager input pendingCount=${this.pendingUserMessageCount}`),this.pendingUserMessageCount=0;if(this.persistResumableSessionId(),X){if(this.currentTurn)this.startThinkingFooter(this.currentTurn);return}let V=this.proc?.lastTotalUsage;if(this.usageTotalsSeedUnknown&&!V){this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;return}this.currentTurnUsageBaseline=V?{...V}:null,this.currentTurnUsageBaselineKnown=!0}),W("token_usage",({totalUsage:X})=>{if(this.persistResumableSessionId(),X)this.usageTotalsSeedUnknown=!1}),W("turn_plan_updated",(X)=>{this.handleTurnPlanUpdated(X)}),W("plan_delta",(X)=>{this.handlePlanDelta(X)}),W("context_compacted",(X)=>{this.handleContextCompacted(X)}),W("rate_limits_updated",(X)=>{if($.provider==="codex")IQ(X)}),W("thread_goal_updated",(X)=>{this.handleThreadGoalUpdated(X)}),W("thread_goal_cleared",()=>{this.handleThreadGoalCleared()}),W("assistant_text",({text:X,parentToolUseId:V})=>{if(V)return;this.appendAssistant(X)}),W("assistant_block_stop",({parentToolUseId:X})=>{if(X)return;this.finalizeCurrentAssistantSegment(),this.onMainThreadAdvance()}),W("tool_use",({id:X,name:V,input:z,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(p7({active:this.backgroundTasks,pending:this.pendingBgTasks},G,X,V,z)),this.onBackgroundTaskChanged();return}if(EH(this,X,V,z),!G)this.onMainThreadAdvance();if(!G&&(V==="Task"||V==="Agent"))this.lastMainTaskToolUseId=X}),W("tool_result",({tool_use_id:X,content:V,is_error:z,parentToolUseId:G,input:_})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(i7({active:this.backgroundTasks,pending:this.pendingBgTasks},G,X,V,z)),this.onBackgroundTaskChanged();return}NH(this,X,V,z,_)}),W("can_use_tool",(X)=>{kH(this,X)}),W("hook_callback",(X)=>{this.proc?.sendHookResponse(X.request_id,{})}),W("result",(X)=>{let V=this.persistResumableSessionId(),z=V?null:this.consumePendingConversationMaterialization(),G=[V,z].filter(Boolean).join(";")||null;if(this.accumulateResultStats(),this.openingTurnOwner)this.openingTurnOwner.sawResult=!0;if(this.userInterrupted){this.userInterrupted=!1,this.discardOrphanAssistant(),this.bgResumePending=!1;let M=this.proc?.lastResult.subtype??"unknown",C=this.proc?.lastResult.is_error===!0;A(`session "${this.sessionName}": SDK result after user stop subtype=${M} isError=${C} — ignored`),this.status="idle";return}let _=X?.is_error!==!0?this.recordTurnAnchor(X?.checkpoint):null;if(X?.is_error===!0)this.lastTurnUserPreview="";if(!this.currentTurn&&!this.openingTurn)this.flushOrphanAssistantToChat("result with no turn card");let K=this.pendingMidTurnMsgs.length>0,q=this.proc?.lastResult.is_error===!0,D=this.proc?.lastResult.subtype??"success",L=typeof X?.error==="string"&&X.error.trim()?X.error.trim():D,P,N=!1,F=this.proc?this.backendLabel(this.proc.provider):this.backendLabel(),j=[G,_].filter(Boolean).join(";")||null;if(j)P=`⚠️ ${j}`,N=!0;else if(K)P=q?`⚠️ ${F} ${L},用户已介入`:"\uD83D\uDCE8 转交新卡";else if(q)P=`⚠️ ${F} ${L}`,N=!0;if(this.openingTurnOwner)this.openingTurnOwner.terminalSuffix=P,this.openingTurnOwner.terminalForcePush=N;if(j&&!this.currentTurn&&!this.openingTurn)w(this.chatId,`⚠️ ${j}`);if(A(`session "${this.sessionName}": SDK result subtype=${D} isError=${q} midBuffer=${this.pendingMidTurnMsgs.length} forcePush=${N}`),this.closeTurnCard(P,{forcePush:N,hasFreshResult:!0}).catch((M)=>{A(`session "${this.sessionName}": result card close failed: ${U(M)}`)}),this.status="idle",K)this.drainMidTurnAndOpen().catch((M)=>{A(`session "${this.sessionName}": mid-turn drain failed: ${U(M)}`)})}),W("bg_task_started",(X)=>{let V=X.tool_use_id??this.lastMainTaskToolUseId??void 0;A(`session "${this.sessionName}": bg_task_started task=${X.task_id} type=${X.task_type??"-"} subagent=${X.subagent_type??"-"} toolUseId=${V?.slice(0,8)??"-"} desc=${(X.description??"").slice(0,40)}`),this.applyBgStore(I7(this.bgStore(),{...X,tool_use_id:V})),this.onBackgroundTaskChanged()}),W("bg_task_progress",(X)=>{this.applyBgStore(g7(this.bgStore(),X)),this.onBackgroundTaskChanged()}),W("bg_task_updated",(X)=>{this.applyBgStore(c7(this.bgStore(),X)),this.onBackgroundTaskChanged()}),W("bg_task_settled",(X)=>{if(A(`session "${this.sessionName}": bg_task_settled task=${X.task_id} status=${X.status}`),this.applyBgStore(u7(this.bgStore(),X)),this.onBackgroundTaskChanged(),$.provider==="claude"&&!this.currentTurn&&!this.openingTurn&&this.initCount>=1)this.bgResumePending=!0}),W("subagent_step",(X)=>{this.applyBgStore(l7(this.bgStore(),X.thread_id,X.item_id,X.tool,X.phase,X.brief)),this.onBackgroundTaskChanged()}),W("exit",({code:X,signal:V,expected:z})=>{if(A(`session "${this.sessionName}": ${$.provider} exited code=${X} signal=${V} expected=${z}`),this.stoppingProc===$||this.blockedProc===$){if(this.blockedProc===$){let D=$.conversationMaterializationFailure?.(),L=this.persistResumableSessionId(!1,$,!1),P=[D&&$.isConversationResumable?.()!==!0?`Codex 会话落盘确认失败: ${U(D)}`:null,L].filter(Boolean).join(";");if(P)w(this.chatId,`⚠️ 旧进程退出后的恢复状态收尾失败: ${P}`);this.discardPendingCodexTurnAnchors($,"blocked process finally exited")}A(`session "${this.sessionName}": blocked/stopping ${$.provider} exit confirmed`),this.detachProc($),this.status="stopped",this.opts.onLifecycleChange?.();return}this.discardPendingCodexTurnAnchors($,"unexpected process exit"),this.cancelAgentRuns(`${$.provider} process exited`).catch((D)=>{A(`session "${this.sessionName}": cancel Agent runs after process exit failed: ${U(D)}`)});let G=this.backendLabel($.provider),_=`code=${X??"null"}, signal=${V??"null"}`,K=z?`\uD83D\uDED1 ${G} 已退出`:`⚠️ ${G} 异常退出 (${_})`;if(this.currentTurn)this.closeTurnCard(K).catch((D)=>{A(`session "${this.sessionName}": process-exit current main-card close failed: ${U(D)}`)});let q=this.waitForTurnCloses().catch((D)=>{A(`session "${this.sessionName}": process-exit main-card close failed: ${U(D)}`)});this.detachProc($),this.flushOrphanAssistantToChat("process exit"),this.bgResumePending=!1,this.bgResumeCardless=!1,this.clearMultiMsgBuffer("process exit"),this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),this.initCount=0,this.invalidateTurnOpen(),this.pendingAsks.clear(),this.pendingPermissions.clear(),this.userInterrupted=!1,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.usageTotalsSeedUnknown=!1,this.status="stopped",this.opts.onLifecycleChange?.(),this.runLifecycle("process-exit-cleanup",async()=>{let D=await Promise.allSettled([q,this.resetBackgroundTasks()]);for(let L of D)if(L.status==="rejected")A(`session "${this.sessionName}": process-exit terminal cleanup failed: ${U(L.reason)}`);if(!z)await T(this.chatId,`⚠️ ${G} 异常退出 (${_})。回复任意消息将重新启动。`)}).catch((D)=>{A(`session "${this.sessionName}": process-exit cleanup rejected: ${U(D)}`)})})}accumulateResultStats(){let $=this.proc?.lastResult;if(!$)return;let Z=this.currentTurnUsageBaselineKnown?T7(this.proc?.lastTotalUsage,this.currentTurnUsageBaseline):this.proc?.provider==="claude"&&$.usage?{...$.usage}:null;this.lastTurnUsage=Z,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;let J=E7(Z),Y=this.proc?.provider==="claude"?0:$.cost_delta_usd??0,Q=$.duration_ms??0;if(J!=null)this.cumStats.tokens+=J;this.cumStats.costUsd+=Y,this.cumStats.turns+=$.num_turns??1,this.lastTurnDelta={tokens:J,costUsd:Y,durationMs:Q}}currentContextTokens($=this.proc){if($?.provider==="claude"||$?.provider==="dsh")return $.lastContextTokens??null;let Z=$?.lastUsage;return U9(Z)}contextLimitForDisplay($=this.proc){return O9($?.lastContextWindow)}async drainMidTurnAndOpen(){if(this.pendingMidTurnMsgs.length===0)return;let $=this.proc,Z=this.procEpoch;if(!$?.isAlive())return;if(!await this.waitForTurnOpenSlot($,Z))return;if(this.currentTurn||this.openingTurn||this.pendingMidTurnMsgs.length===0)return;let J;try{J=this.beginTurnOpen($,Z)}catch(Q){A(`session "${this.sessionName}": mid-turn open ownership conflict: ${U(Q)}`);return}let Y=this.pendingMidTurnMsgs;this.pendingMidTurnMsgs=[];try{for(let V of Y)if(this.pendingTurnInputs.push(V.text),V.msgId){let z=this.pendingReactionIds.get(V.msgId)??"";this.currentBatchReactionIds.set(V.msgId,z),this.pendingReactionIds.delete(V.msgId)}let Q=Y.map((V)=>V.wireText).join(`
|
|
192
|
+
${G}`)}return{slug:Y,chatName:H,branch:Q,worktreePath:V,removedWorktree:!1}}function I3($){if(!U1($))throw Error(`project directory does not exist: ${$}`);let Z=F0($,["rev-parse","--show-toplevel"]).trim();if(v3(Z)!==v3($))throw Error(`${$} is not the git repository root (${Z})`)}function pW($,Z){let J=F0($,["rev-parse","--abbrev-ref","HEAD"]).trim();if(J!==Z)throw Error(`${$} is on ${J}, expected ${Z}`)}function yL($,Z,J){let Y=wL($);if(!Y?.startsWith(A2))return null;let Q=Y.slice(A2.length);if(!O1(Q))throw Error(`invalid worktree branch "${Y}"`);let H=B2(Z,J,Q);if(k6($)!==k6(H))return null;let W=vL($,fL(Q));return W?{path:W,slug:Q}:null}function wL($){if(!U1($))return null;try{return F0($,["branch","--show-current"]).trim()||null}catch(Z){if(IL(Z))return null;throw Z}}function fL($){return $.split("-",1)[0]??$}function vL($,Z){let J=`agents.${Z}.md`,Y=SL($).filter((Q)=>Q.toLowerCase()===J).sort();if(Y.length>1)throw Error(`multiple worktree instruction files match ${J}: ${Y.join(", ")}`);return Y[0]?vW($,Y[0]):null}function hL($,Z){try{return F0($,["show-ref","--verify","--quiet",`refs/heads/${Z}`]),!0}catch{return!1}}function lW($,Z,J){let Y=F0($,["rev-parse",Z]).trim(),Q=F0($,["rev-parse","HEAD"]).trim();if(Y===Q)return J?"active":"merged";if(fW($,Z,"HEAD"))return"merged";if(fW($,"HEAD",Z))return"active";return"stale"}function fW($,Z,J){try{return F0($,["merge-base","--is-ancestor",Z,J]),!0}catch{return!1}}function g3($){let Z=new Map,J=F0($,["worktree","list","--porcelain"]),Y="";for(let Q of J.split(`
|
|
193
|
+
`)){if(Q.startsWith("worktree ")){Y=Q.slice(9);continue}if(Q.startsWith("branch refs/heads/")&&Y)Z.set(Q.slice(18),Y)}return Z}function F0($,Z){try{return NL("git",Z,{cwd:$,encoding:"utf8",stdio:["ignore","pipe","pipe"]})}catch(J){throw Error(c3(J))}}function c3($){if($&&typeof $==="object"){let Z=$,J=Z.stderr?String(Z.stderr).trim():"";if(J)return J;if(Z.message)return Z.message}return String($)}function IL($){return/not a git repository/i.test(c3($))}var A2="work/",bL,x6;var iW=S(()=>{bL=/^[A-Za-z0-9][A-Za-z0-9._-]{0,62}$/,x6=new Map});function p$($){return hW(Y$($.sessionName)??$.sessionName)}function L2($){return j9(p$($))}function nW($){let Z=Y$($.sessionName)??$.sessionName,J=p$($),Y=j9(J);if(J===Z)return Y;let Q=Z.slice(J.length+1,-1);return B2(Y,J,Q)}function aW($,Z=$.currentProvider()){let J=Z==="dsh"?yW:Z==="claude"?bW:CW,Y=N4($);return Y?`${J}
|
|
194
|
+
${Y}`:J}function oW($,Z){return N4($)??""}function m3($){return N4($)?"已载入wt特殊约定":null}function rW($,Z){let J=m3($);return J?`${Z}
|
|
195
|
+
${J}`:Z}function N4($){let Z=p$($),J=gW($.workDir,L2($),Z);if(!J)return null;return[`你要把下面这份额外的工作树约定视为和AGENTS.md一样重要。来源文件:${J.path}`,"",`# Additional AGENTS.md instructions for ${$.workDir}`,"","<INSTRUCTIONS>",J.content,"</INSTRUCTIONS>"].join(`
|
|
196
|
+
`)}async function tW($,Z,J){if(!Z){await u3($);return}let Y=O1(Z);if(!Y){await E($.chatId,"❌ 名称无效。用英文/数字/._-,最长 63。");return}if(!J){await E($.chatId,"❌ 找不到发起人,不能拉群。");return}let Q=p$($),H=L2($);try{await C6(H,async()=>{let W;try{W=mW(H,Q,Y)}catch(X){await E($.chatId,`❌ wt 失败: ${O(X)}`);return}try{let X=await v8(W.chatName,J),V=X.created?"已创建":X.joined?"已加入":"已在群内";if(!await a($.chatId,K4({slug:Y,branch:W.branch,status:V})))await w($.chatId,`❌ wt 卡片失败: ${Y}`);if(!await a(X.chatId,K4({slug:Y,branch:W.branch,status:"就绪",body:"开始吧。"})))await w(X.chatId,`❌ wt 卡片失败: ${Y}`)}catch(X){await E($.chatId,`❌ wt 已建,拉群失败: ${O(X)}`)}})}catch(W){await E($.chatId,`❌ wt 失败: ${O(W)}`)}}async function sW($,Z){let J=p$($),Y=L2($);return await C6(Y,async()=>{return await cL(J,Y,Z)})}async function cL($,Z,J){let Y=cW(Z,$),Q=Y.filter((X)=>X.state==="merged"&&!X.mounted).length,H=Y.filter((X)=>X.state!=="merged"||X.mounted),W=await M9();return O5({projectName:$,projectDir:Z,hiddenMergedUnmountedCount:Q,notice:J,entries:H.map((X)=>{let V=W.get(X.chatName)??[],z=G0.get(X.chatName),G=z&&V.includes(z)?z:V.length===1?V[0]:null;return{slug:X.slug,chatName:X.chatName,branch:X.branch,state:X.state,path:X.worktreePath??X.expectedPath,mounted:X.mounted,dirtyCount:X.dirtyCount,statusLine:X.statusLine,error:X.error,chatId:G,duplicateChatCount:V.length}})})}async function u3($){try{let Z=await sW($);if(!await a($.chatId,Z))await w($.chatId,"❌ wt 列表失败")}catch(Z){await E($.chatId,`❌ wt 列表失败: ${O(Z)}`)}}async function dW($,Z,J,Y){try{return{ok:Z,message:J,card:await sW($,{type:Y,content:J})}}catch(Q){let H=`列表刷新失败: ${O(Q)}`;return _(`session "${$.sessionName}": wt action panel refresh failed: ${O(Q)}`),{ok:!1,message:`${J}
|
|
197
|
+
${H}`,card:K4({slug:"wt",branch:"work/*",status:J,body:H,template:"red"})}}}async function eW($,Z){let J=O1(Z);if(!J)return dW($,!1,"❌ 名称无效","error");let Y=p$($),Q=L2($),H;try{H=await C6(Q,async()=>{let W=K2(Y,J);if($.hasRunningPeerSession(W))return{ok:!1,message:`❌ 解散 ${J} 失败: Codex 正在运行,请先在 ${W} 群里 stop 或 kill。`,type:"error"};h3(Q,Y,J);let X=await I8(W),V=uW(Q,Y,J);return{ok:!0,message:[`✅ ${J} 已解散`,V.removedWorktree?"dir removed":"dir missing",X.disbanded?"group removed":"group missing",V.branch].join(`
|
|
198
|
+
`),type:"success"}})}catch(W){H={ok:!1,message:`❌ 解散 ${J} 失败: ${O(W)}`,type:"error"}}return dW($,H.ok,H.message,H.type)}var $X=S(()=>{wW();p0();e();g();iW()});import{closeSync as uL,openSync as pL,readSync as lL,readdirSync as iL,statSync as dL}from"node:fs";import{randomUUID as l3}from"node:crypto";import{join as nL}from"node:path";function y6($){return Y$($.sessionName)??$.sessionName}function JX($){let Z=S8($,p3);return p3.add(Z),Z}function YX($){p3.delete($)}function q2($){let Z=ZX.get($);if(!Z)Z=new Map,ZX.set($,Z);let J=Date.now();for(let[Y,Q]of Z){let H=Q.status==="consumed"?rL:oL,W=Q.consumedAt??Q.createdAt;if(J-W>H)Z.delete(Y)}return Z}function sL($,Z){return $.provider===Z.provider&&$.tokenSourceId===Z.tokenSourceId&&$.model===Z.model&&$.effort===Z.effort}function QX($,Z,J,Y){let Q={id:l3(),mode:Z,requesterOpenId:J,provider:$.selectedProvider,sourceSessionId:$.lastSessionId,workDir:$.workDir,baseName:y6($),routing:$.conversationRouting(),createdAt:Date.now(),status:"open",choices:Y};return q2($).set(Q.id,Q),Q}function i3($,Z,J,Y,Q){let H=q2($).get(J);if(!H||H.mode!==Z)return{error:"这张选择卡已过期,请重新发送命令"};if(!Q||H.requesterOpenId!==Q)return{error:"只有打开这张选择卡的用户可以执行;请自行发送命令重新打开"};if(H.status!=="open")return{error:"这张选择卡已执行或正在处理,请勿重复点击"};if(H.provider!==$.selectedProvider||H.workDir!==$.workDir||H.sourceSessionId!==$.lastSessionId||!sL(H.routing,$.conversationRouting()))return{error:"这张卡对应的 provider、目录或源会话已经变化,请重新发送命令"};let W=H.choices.get(Y);if(!W)return{error:"无效的选择项,这张卡可能已过期"};return H.status="processing",{panel:H,choice:W}}function b6($){$.status="consumed",$.consumedAt=Date.now()}function eL($){return{kind:"fork",source:$.source,through:$}}function $q($){return a2($.sessionName).filter((Z)=>Z.checkpoint.provider===$.selectedProvider&&Z.checkpoint.source.cwd===$.workDir)}function Zq($){let Z=o2($.sessionName);if(Z===null||Z.kind==="fresh")return Z;try{return V0(Z,$.selectedProvider,$.workDir),Z}catch{return null}}function Jq($){let Z=H9($),J;try{J=iL(Z)}catch(Q){if(Q?.code==="ENOENT")return[];throw Error(`读取 Claude 会话目录失败: ${Q?.message??Q}`)}let Y=[];for(let Q of J){if(!Q.endsWith(".jsonl"))continue;let H=Q.slice(0,-6);if(y1("claude",H))continue;let W=nL(Z,Q),X;try{X=dL(W).mtimeMs}catch(V){throw Error(`读取 Claude 会话元数据失败 (${Q}): ${V?.message??V}`)}Y.push({provider:"claude",sessionId:H,cwd:$,preview:Qq(W),ts:X})}return Y.sort((Q,H)=>H.ts-Q.ts)}function Yq($){let Z=$.slice().sort((Q,H)=>H.ts-Q.ts),J=Date.now()-aL,Y=Z.filter((Q)=>Q.ts>=J).length;return Z.slice(0,Math.min(tL,Math.max(10,Y)))}function Qq($){let Z="",J=null;try{J=pL($,"r");let Q=Buffer.alloc(65536),H=lL(J,Q,0,65536,0);Z=Q.subarray(0,H).toString("utf8")}catch(Q){throw Error(`读取 Claude 会话摘要失败 (${$}): ${Q?.message??Q}`)}finally{if(J!==null)uL(J)}let Y="";for(let Q of Z.split(`
|
|
199
|
+
`)){let H=Q.trim();if(!H)continue;let W;try{W=JSON.parse(H)}catch{continue}if(W.type==="queue-operation"&&W.operation==="enqueue"&&typeof W.content==="string"){let X=W.content.trim();if(X)return X.slice(0,80)}if(!Y&&W.type==="user"&&W.message){let X=Hq(W.message);if(X)Y=X}}return Y.slice(0,80)}function Hq($){let Z=$?.content;if(typeof Z==="string")return Z;if(!Array.isArray(Z))return"";for(let J of Z)if(J?.type==="text"&&typeof J.text==="string")return J.text;return""}async function HX($,Z,J){if(!J){await E($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let Y=$q($),Q=Zq($),H=new Map,W=[];for(let G=0;G<Y.length;G++){let A=Y[G];if(G===0&&Q===null)continue;let K=l3(),L=G===0?Q:eL(Y[G-1].checkpoint);H.set(K,{kind:Z,launch:L,branchBase:Q,seedAnchors:Y.slice(0,G),writes:Y.slice(G).flatMap((D)=>D.writes)}),W.push({choiceId:K,preview:A.preview,ts:A.ts})}W.reverse();let X=QX($,Z,J,H),V=E5({projectName:y6($),panelId:X.id,mode:Z,entries:W}),z;try{z=await a($.chatId,V)}catch(G){throw q2($).delete(X.id),G}if(!z)q2($).delete(X.id),await w($.chatId,`❌ ${Z==="fork"?"fk":"bk"} 列表发送失败`)}function WX($,Z){return HX($,"fork",Z)}function XX($,Z){return HX($,"back",Z)}async function VX($,Z){if(!Z){await E($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let J;try{J=$.selectedProvider==="codex"?await $.listCodexConversations():$.selectedProvider==="dsh"?await $.listDshConversations():Jq($.workDir)}catch(V){await w($.chatId,`❌ 历史会话读取失败: ${V instanceof Error?V.message:V}`);return}let Y=new Map,Q=Yq(J).map((V)=>{let z=l3();return Y.set(z,{kind:"resume",launch:{kind:"fork",source:{provider:V.provider,sessionId:V.sessionId,cwd:V.cwd}},sourcePreview:V.preview,sourceTs:V.ts,sourceStatus:V.status}),{choiceId:z,preview:V.preview,ts:V.ts}}),H=QX($,"resume",Z,Y),W=N5({projectName:y6($),panelId:H.id,entries:Q}),X;try{X=await a($.chatId,W)}catch(V){throw q2($).delete(H.id),V}if(!X)q2($).delete(H.id),await w($.chatId,"❌ rs 历史列表发送失败")}async function zX($,Z){if(!Z){await E($.chatId,"❌ 找不到发起人,无法建临时群。");return}if(!$.opts.onCreateTempSession){await E($.chatId,"❌ 临时群能力未就绪(daemon 未注入回调)。");return}let J=JX(y6($));await E($.chatId,`\uD83D\uDE80 正在创建 ${J} · ${$.backendLabel()} 新会话。它与当前群共享工作目录;当前会话不受影响。`);let Y;try{Y=await $.opts.onCreateTempSession({chatName:J,userOpenId:Z,workDir:$.workDir,routing:$.conversationRouting(),launch:{kind:"fresh"},branchBase:{kind:"fresh"},seedAnchors:[]})}finally{YX(J)}if(!Y.ok){await E($.chatId,`❌ 建临时会话失败: ${Y.error??"未知"}`);return}await E($.chatId,`✅ 已创建 ${J}。临时群不会自动删除;在该群发送 bye 可停止并解散。`)}async function GX($){if(!Y$($.sessionName)){await E($.chatId,"❌ bye 只能在带 *MMDD-HHMM 后缀的临时会话群里使用。");return}if(!$.opts.onDisbandTempSession){await E($.chatId,"❌ 解散能力未就绪(daemon 未注入回调)。");return}await E($.chatId,`\uD83D\uDC4B 正在停止会话并解散 ${$.sessionName}…`);let Z=await $.opts.onDisbandTempSession($.sessionName,$.chatId);if(!Z.ok)await E($.chatId,`❌ 解散失败: ${Z.error??"未知"}`)}async function _X($,Z,J,Y){let Q=i3($,"fork",Z,J,Y);if("error"in Q)return{ok:!1,message:Q.error,replaceCard:!1};let{panel:H,choice:W}=Q;try{if(W.kind!=="fork")return{ok:!1,message:"选择项类型不匹配"};if(!$.opts.onCreateTempSession)return{ok:!1,message:"临时群能力未就绪"};let X=JX(H.baseName);_(`session-temp: fork ${$.sessionName} → ${X} (${W.launch.kind})`),await E($.chatId,`\uD83D\uDD31 正在分叉到 ${X}…`);let V;try{V=await $.opts.onCreateTempSession({chatName:X,userOpenId:Y,workDir:H.workDir,routing:H.routing,launch:W.launch,branchBase:W.branchBase,seedAnchors:W.seedAnchors})}finally{YX(X)}if(!V.ok)return{ok:!1,message:`分叉失败: ${V.error??"未知"}`};return{ok:!0,message:`已分叉到 ${X};原会话和磁盘文件未回滚`}}catch(X){return{ok:!1,message:`分叉失败: ${X instanceof Error?X.message:X}`}}finally{b6(H)}}async function AX($,Z,J,Y){let Q=i3($,"back",Z,J,Y);if("error"in Q)return{ok:!1,message:Q.error,replaceCard:!1};let{panel:H,choice:W}=Q;try{if(W.kind!=="back")return{ok:!1,message:"选择项类型不匹配"};let X="";try{if(!await a($.chatId,S5({projectName:H.baseName,entries:W.writes})))X=";文件变更记录卡发送失败"}catch(G){X=`;文件变更记录卡发送失败: ${G instanceof Error?G.message:G}`}if(_(`session-temp: back ${$.sessionName} (${W.launch.kind}, writes=${W.writes.length})`),!await $.rollbackTo(W.launch,{anchors:W.seedAnchors,base:W.branchBase}))return{ok:!1,message:`回退失败;原会话绑定未改,请检查日志后重试${X}`};if(H.routing.provider==="claude")return{ok:!0,message:`本群已准备 Claude 新分支;发送下一条消息时生成并接入,旧会话未删除,磁盘文件未回滚${X}`};return{ok:!0,message:`本群已改接新会话${$.lastSessionId?` ${q0($.lastSessionId)}`:""};旧会话未删除,磁盘文件未回滚${X}`}}catch(X){return{ok:!1,message:`回退失败: ${X instanceof Error?X.message:X}`}}finally{b6(H)}}async function KX($,Z,J,Y){let Q=i3($,"resume",Z,J,Y);if("error"in Q)return{ok:!1,message:Q.error,replaceCard:!1};let{panel:H,choice:W}=Q;if(W.kind!=="resume")throw b6(H),Error("resume panel contained a non-resume choice");let X=W.launch.source.sessionId,V=$.lastSessionId,z=(A,K)=>({projectName:H.baseName,provider:W.launch.source.provider,selectedPreview:W.sourcePreview,selectedTs:W.sourceTs,sourceSessionId:X,...W.sourceStatus?{sourceStatus:W.sourceStatus}:{},previousSessionId:V,newSessionId:A,bindingState:K}),G=(A,K,L,D=null)=>({ok:A,message:K,resumePresentation:z(D,L)});try{if($.isRunning())return G(!1,"当前群已经启动了新进程;为避免误杀,请先停止后重新发送 rs","unchanged");if(W.sourceStatus==="active")return G(!1,"所选 Codex 会话仍在运行;请先在原位置停止后再创建完整分支","unchanged");if(_(`session-temp: history fork ${$.sessionName} ← ${W.launch.source.provider} ${X}`),!await $.rollbackTo(W.launch,{anchors:[],base:W.launch,pendingLaunch:W.launch.source.provider==="claude"?{launch:W.launch,previousSessionId:V}:null}))return G(!1,"历史分支创建失败;原会话绑定未改,请检查日志后重试","unchanged");if(W.launch.source.provider==="claude")return G(!0,"Claude 独立分支已准备;首条消息时生成并接入新会话","prepared");let K=$.lastSessionId;if(!K)return G(!1,"历史分支已启动,但后端没有返回新会话 id","unknown");if(K===X||V&&K===V)return G(!1,"后端没有返回独立的新会话 id;为避免误判,本次不标记为恢复成功","unknown",K);return G(!0,"已创建并接入独立分支;源会话未修改","changed",K)}catch(A){return G(!1,`历史分支创建失败: ${A instanceof Error?A.message:A}`,"unknown")}finally{b6(H)}}var aL=86400000,oL=1800000,rL=3600000,tL=40,ZX,p3;var BX=S(()=>{e();p0();g();g2();E2();$1();ZX=new WeakMap,p3=new Set});import{existsSync as LX}from"node:fs";import{randomBytes as Xq,timingSafeEqual as Vq}from"node:crypto";import{isAbsolute as zq}from"node:path";function n3($,Z=new Set){if($ instanceof b2)return $;if(!$||typeof $!=="object"&&typeof $!=="function"||Z.has($))return null;if(Z.add($),$ instanceof AggregateError)for(let J of $.errors){let Y=n3(J,Z);if(Y)return Y}if($ instanceof Error&&$.cause!==void 0)return n3($.cause,Z);return null}function Gq($){return $.itemId||$.turnId||"__latest__"}function qX($){let Z=[];if($.itemId)Z.push(`item:${$.itemId}`);if($.turnId)Z.push(`turn:${$.threadId??$.sessionId??"-"}:${$.turnId}`);return Z}function _q($){let Z=null;for(let J of $.contextCompactionPending.keys())Z=J;return Z}function Aq($,Z){if(!$)return Z;return{...$,...Z,phase:"end"}}function T1(){return v.runtime?.live_elapsed??"bucket"}function jX($,Z){return`${$} (${x$(Date.now()-Z,T1()).label})`}var DX="Thinking...",Kq="Writing...",Bq="Working...",d3=1e4,w6=720000,Lq=50,qq=256,f6=1e4,PX=250,s0;var x3=S(()=>{E2();S2();K0();Z1();r7();K0();x0();G8();Z0();g2();G1();p0();e();g();Y0();L5();z6();D4();i5();eQ();AH();NH();L6();kH();QW();WW();LW();MW();kW();$X();BX();$1();s0=class s0{sessionName;chatId;opts;static all=new Set;proc=null;lifecycleTail=Promise.resolve();lifecycleSequence=0;procEpoch=0;stoppingProc=null;blockedProc=null;blockedProcReason=null;agentCapability=null;procSourceRevisions=new WeakMap;currentTurn=null;contextCompactionReceipts=new Map;contextCompactionOwnerIds=new WeakMap;contextCompactionOwnerSequence=0;lastManualContextCompactionCompletedAt=0;lastManualContextCompactionWasAnonymous=!1;backgroundTasks=[];pendingBgTasks=[];backgroundCard=null;settlingBackgroundCard=!1;migratingBackgroundCard=null;backgroundRefreshTimer=null;backgroundRefreshTick=null;openingBackground=!1;openingBackgroundOwner=null;backgroundOpenSequence=0;backgroundGeneration=0;backgroundDetailAdded=new Set;backgroundDetailAdding=new Set;lastMainTaskToolUseId=null;pendingRebuildBackgroundCard=!1;bgResumePending=!1;orphanAssistantSegments=[];orphanAssistantCurrent="";bgResumeCardless=!1;pendingPermissions=new Map;pendingAsks=new Map;currentGoal=null;status="stopped";pendingUserMessageCount=0;pendingMidTurnMsgs=[];pendingTurnInputs=[];multiMsgBuffer=null;multiMsgReactions=new Map;lastUserOpenId="";pendingReactionIds=new Map;currentBatchReactionIds=new Map;initCount=0;openingTurn=!1;openingTurnOwner=null;turnOpenSequence=0;turnCloseInflight=new Set;turnCounter=0;userInterrupted=!1;lastSessionId=null;lastSessionRef=null;selectedProvider="claude";selectedModel=null;selectedEffort=null;selectedTokenSourceId=null;modelPanels=new Map;modelCustomPrompt=null;startedAt=0;cumStats={tokens:0,costUsd:0,turns:0};lastTurnDelta=null;currentTurnUsageBaseline=null;currentTurnUsageBaselineKnown=!1;lastTurnUsage=null;usageTotalsSeedUnknown=!1;resumePersistenceError=null;daemonRestoreRequired=!1;manualContextCompactionPending=!1;taskBoard=[];constructor($,Z,J={}){this.sessionName=$;this.chatId=Z;this.opts=J;s0.all.add(this);let Y=b8($);this.selectedProvider=Y?.provider??"claude",this.selectedModel=Y?.model??null,this.selectedEffort=Y?.effort??null,this.selectedTokenSourceId=this.deriveTokenSourceId(Y);let Q=p(this.selectedTokenSourceId);if(Q){if(this.selectedProvider=Q.agent,Q.id==="glm"&&this.selectedModel==="claude:glm")this.selectedModel=Q.defaultModel,this.selectedEffort="max"}if(this.selectedModel)_(`session "${$}": restored selected provider=${this.selectedProvider} model=${this.selectedModel} effort=${this.selectedEffort??"unset"}`);if(this.lastSessionRef=X1($,this.selectedProvider),this.lastSessionId=this.lastSessionRef?.sessionId??null,this.lastSessionId)_(`session "${$}": restored ${this.selectedProvider} lastSessionId=${this.lastSessionId}`);let H=r2($);if(H)if(this.selectedProvider!=="claude")a0($,[],null,null),_(`session "${$}": cleared pending Claude fork after provider changed`);else{V0(H.launch,"claude",this.workDir);let W=this.lastSessionId===H.previousSessionId,X=this.lastSessionRef,V=!W&&X?.provider==="claude"&&X.cwd===this.workDir&&X.sessionId!==H.launch.source.sessionId&&X.sessionId!==H.previousSessionId;if(!W&&!V)throw Error(`pending Claude fork has inconsistent resume binding for session "${$}"`);this.pendingConversationMaterialization=H,_(`session "${$}": restored ${V?"materialized":"pending"} Claude fork source=${H.launch.source.sessionId}`)}}peerSnapshot(){return{name:this.sessionName,status:this.status,uptimeMs:this.startedAt?Date.now()-this.startedAt:void 0}}get workDir(){return nW(this)}isRunning(){return!!this.proc&&this.proc.isAlive()}shouldRevive(){return this.daemonRestoreRequired||this.isRunning()&&this.stoppingProc!==this.proc&&this.blockedProc!==this.proc}deriveTokenSourceId($){let Z=$?.tokenSourceId;if(typeof Z==="string"&&Z.trim())return Z.trim();let J=$?.provider??this.selectedProvider;return z9(J)[0]?.id??null}currentTokenSource(){return p(this.selectedTokenSourceId)}currentProvider(){return this.selectedProvider}conversationRouting(){return{provider:this.selectedProvider,tokenSourceId:this.selectedTokenSourceId,model:this.selectedModel,effort:this.selectedEffort}}applyConversationRouting($){if(this.isRunning()||this.currentTurn||this.openingTurn)throw Error("cannot change conversation routing while the session is running");let Z=p($.tokenSourceId);if(Z&&Z.agent!==$.provider)throw Error(`token source "${Z.id}" belongs to ${Z.agent}, not ${$.provider}`);if(this.selectedProvider!==$.provider)a0(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$.provider,this.selectedTokenSourceId=$.tokenSourceId,this.selectedModel=$.model,this.selectedEffort=$.effort,this.lastSessionRef=X1(this.sessionName,$.provider),this.lastSessionId=this.lastSessionRef?.sessionId??null,C8(this.sessionName,$.provider,$.model,$.effort,$.tokenSourceId)}dshEffortForSpawn(){if(X0(this.selectedEffort))return this.selectedEffort;let $=this.currentTokenSource(),Z=$&&C$($,this.selectedModel??$.defaultModel);if(!Z||!X0(Z.defaultEffort))throw Error("DSH model reasoning effort is unavailable");return Z.defaultEffort}async listDshConversations(){if(this.selectedProvider!=="dsh")throw Error("DSH history requested under a different provider");let $=this.currentTokenSource();if(!$?.enabled||$.agent!=="dsh")throw Error("DSH token source is unavailable");return(await w1({cwd:this.workDir,env:$.spawnEnv(process.env),profile:{loadProjectMcp:!1}},"session/list",{cwd:this.workDir})).filter((J)=>!y1("dsh",J.sessionId))}async listCodexConversations(){if(this.selectedProvider!=="codex")throw Error("Codex history requested for a non-Codex session");if(!$4())throw Error("Codex 未登录 ChatGPT 账号");let $=this.currentTokenSource();if(this.selectedTokenSourceId&&(!$||!$.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或选择其他账号`);let Z=$?.enabled?$:void 0,J=Z?(X)=>Z.spawnEnv(X):void 0,Y=new I1({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Z?.id??null,transformEnv:J}),Q=null,H=null;try{Q=await Y.listConversations()}catch(X){H=X}let W=null;try{await Y.kill(2000)}catch(X){W=X}if(H&&W)throw AggregateError([H,W],`Codex history query and cleanup failed: ${O(H)}; ${O(W)}`);if(H)throw H;if(W)throw W;return Q??[]}async resolveLegacyResumeRef($){if($.cwd!==null)return $;if($.provider!==this.selectedProvider)throw Error(`legacy resume provider mismatch: ${$.provider} != ${this.selectedProvider}`);let Z;if($.provider==="dsh")throw Error("DSH resume reference requires its original cwd");else if($.provider==="claude"){let J=W9(this.workDir,$.sessionId);if(!LX(J))throw Error(`旧 Claude 会话不属于当前 cwd,或 transcript 不存在: ${q0($.sessionId)}`);Z={...$,cwd:this.workDir}}else{if(!$4())throw Error("Codex 未登录 ChatGPT 账号");let J=this.currentTokenSource();if(this.selectedTokenSourceId&&(!J||!J.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或选择其他账号`);let Y=J?.enabled?J:void 0,Q=new I1({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Y?.id??null,transformEnv:Y?(X)=>Y.spawnEnv(X):void 0}),H=null;try{Z=await Q.readConversationRef($.sessionId)}catch(X){H=X,Z=$}let W=null;try{await Q.kill(2000)}catch(X){W=X}if(H&&W)throw AggregateError([H,W],`Codex legacy resume lookup and cleanup failed: read=${O(H)}; cleanup=${O(W)}`);if(H)throw H;if(W)throw W}return V0({kind:"resume",source:Z},this.selectedProvider,this.workDir),n2(this.sessionName,Z),Z}hasRunningPeerSession($){return[...s0.all].some((Z)=>Z.sessionName===$&&Z.isRunning())}modelForSpawn(){if(this.selectedProvider==="codex")return;return this.selectedModel??void 0}effortForSpawn(){if(this.selectedProvider==="codex"){let $=this.currentTokenSource();if(!$||!$.enabled)return;return h0(this.selectedEffort)?this.selectedEffort:w2}return w2}claudeEffortForSpawn(){if(this.selectedProvider==="claude"&&R0(this.selectedEffort))return this.selectedEffort;let $=this.currentTokenSource();if(this.selectedProvider==="claude"&&$?.agent==="claude"){let Z=C$($,this.selectedModel??$.defaultModel);if(!R0(Z?.defaultEffort))throw Error("Claude 默认 effort MISS,请通过 model 面板明确选择");return Z.defaultEffort}return E$}currentModelLabel(){return(this.selectedModel??this.currentTokenSource()?.defaultModel??this.proc?.lastModel??null)?.replace(/^claude:/i,"").replace(/\[1m\]$/i,"")??null}currentEffortLabel(){let $=this.currentTokenSource();if(this.selectedProvider==="claude"&&$?.agent==="claude")return this.selectedEffort??C$($,this.selectedModel??$.defaultModel)?.defaultEffort??null;return this.selectedEffort??(this.selectedProvider==="dsh"?this.dshEffortForSpawn():void 0)??this.proc?.lastEffort??(this.selectedProvider==="claude"?E$:w2)}runtimeModelSelection(){let $=this.proc?.isAlive()?this.proc:null,Z=$?.provider??this.selectedProvider,J=!$||$.provider===this.selectedProvider,Y=($?.lastModel??(J?this.currentModelLabel():null))?.replace(/^claude:/i,"").replace(/\[1m\]$/i,"")??null,Q=$?.lastEffort??(J?this.currentEffortLabel():Z==="claude"?E$:w2);return{provider:Z,model:Y,effort:Q}}withModel($,Z){let J=this.modelLine(Z);return $.includes(J)?$:`${$} · ${J}`}replaceFooterContent($,Z){return t($,R.footer,this.footerElement(Z),void 0,!1)}footerElement($){return{tag:"markdown",element_id:R.footer,content:$.trim()||" "}}modelLine($=this.currentTurn??this.runtimeModelSelection()){return o8($.provider,$.model,$.effort)}backendLabel($=this.selectedProvider){return Z$($)}pendingConversationLaunch=null;pendingConversationMaterialization=null;lastTurnUserPreview="";pendingCodexTurnAnchors=[];pendingMaterializationLaunch(){let $=this.pendingConversationMaterialization;if(!$)return null;if(V0($.launch,"claude",this.workDir),this.selectedProvider!=="claude")throw Error("pending Claude fork cannot launch under a non-Claude provider");if(this.lastSessionId===$.previousSessionId)return $.launch;let Z=this.lastSessionRef;if(Z?.provider==="claude"&&Z.cwd===this.workDir&&Z.sessionId!==$.launch.source.sessionId&&Z.sessionId!==$.previousSessionId)return{kind:"resume",source:Z};throw Error("pending Claude fork has no safe launch target")}spawnAgent($){this.agentCapability=Xq(32).toString("base64url");let Z={LODESTAR_AGENT_URL:A9(v.notify.bind,v.notify.port),LODESTAR_AGENT_CAPABILITY:this.agentCapability,LODESTAR_AGENT_SESSION:this.sessionName,LODESTAR_AGENT_ROLE:"main"},J=this.pendingConversationLaunch??this.pendingMaterializationLaunch()??($?{kind:"resume",source:$}:{kind:"fresh"});V0(J,this.selectedProvider,this.workDir);let Y=this.currentTokenSource();if(this.selectedTokenSourceId&&(!Y||!Y.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或在 model 面板选择其他账号`);let Q=Y?.enabled?Y:void 0,H=_9({provider:this.selectedProvider,workDir:this.workDir,tokenSourceId:Q?.id??null,model:Q?this.selectedModel??Q.defaultModel:this.modelForSpawn(),effort:this.selectedProvider==="dsh"?this.dshEffortForSpawn():this.selectedProvider==="claude"?this.claudeEffortForSpawn():this.effortForSpawn(),launch:J,developerInstructions:this.spawnDeveloperInstructions(),profile:n1(this.worktreeProjectName()),...process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"?{}:{managedSkillPluginPath:o$},hostEnv:Z});return this.procSourceRevisions.set(H.process,H.sourceRevision),H.process}async applyModelSelection($,Z,J,Y){await this.runLifecycle("apply-model-selection",()=>this.applyModelSelectionUnlocked($,Z,J,Y))}async applyModelSelectionUnlocked($,Z,J,Y){if(this.selectedProvider!==$)a0(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$,this.selectedTokenSourceId=Y??this.selectedTokenSourceId;let H=p(this.selectedTokenSourceId);if(H)this.selectedModel=Z||null,this.selectedEffort=J??C$(H,Z||H.defaultModel)?.defaultEffort??null;else this.selectedModel=$==="codex"?null:Z,this.selectedEffort=$==="codex"?null:J;this.lastSessionRef=X1(this.sessionName,$),this.lastSessionId=this.lastSessionRef?.sessionId??null,k8(this.sessionName,$,this.selectedModel,this.selectedEffort,this.selectedTokenSourceId),await this.stopIdleMismatchedProcessUnlocked()}async stopIdleMismatchedProcess(){await this.runLifecycle("stop-idle-mismatched",()=>this.stopIdleMismatchedProcessUnlocked())}processSourceMatches($,Z){return!this.proc||!this.procSourceRevisions.has(this.proc)||this.procSourceRevisions.get(this.proc)===m2($,Z)}async stopIdleMismatchedProcessUnlocked(){if(!this.proc?.isAlive())return;let $=this.currentTokenSource(),Z=this.processSourceMatches($,this.selectedModel);if(this.proc.provider===this.selectedProvider&&this.proc.tokenSourceId===this.selectedTokenSourceId&&Z)return;if(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0)return;let J=this.proc;_(`session "${this.sessionName}": stop idle ${J.provider} process after switching to ${this.selectedProvider}`),this.beginProcStop(J),this.initCount=0,this.bgResumePending=!1,this.discardOrphanAssistant(),this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.usageTotalsSeedUnknown=!1,this.status="stopped";let Y=await this.settleProcResumableState(J),Q=null;try{await J.kill(1000)}catch(X){Q=X}Y=await this.settleProcResumableState(J);let H=this.finishProcStop(J,Q);this.opts.onLifecycleChange?.();let W=[...!H?[Q??Error(this.blockedProcReason??"process stop unconfirmed")]:[],...Y?[Error(Y)]:[]];if(W.length===1)throw W[0];if(W.length>1)throw AggregateError(W,`idle process stop failed: ${W.map(O).join("; ")}`)}async stopIdleCurrentProcess($){return await this.runLifecycle("stop-idle-current",()=>this.stopIdleCurrentProcessUnlocked($))}async stopIdleCurrentProcessUnlocked($){if(!this.proc?.isAlive())return!1;if(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0)return!1;let Z=this.proc;_(`session "${this.sessionName}": stop idle ${Z.provider} process: ${$}`),this.beginProcStop(Z),this.initCount=0,this.bgResumePending=!1,this.discardOrphanAssistant(),this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.usageTotalsSeedUnknown=!1,this.status="stopped";let J=await this.settleProcResumableState(Z),Y=null;try{await Z.kill(1000)}catch(W){Y=W}J=await this.settleProcResumableState(Z);let Q=this.finishProcStop(Z,Y);this.opts.onLifecycleChange?.();let H=[...!Q?[Y??Error(this.blockedProcReason??"process stop unconfirmed")]:[],...J?[Error(J)]:[]];if(H.length===1)throw H[0];if(H.length>1)throw AggregateError(H,`idle process stop failed: ${H.map(O).join("; ")}`);return!0}startFooterTimer($,Z,J=(Y)=>Y){let Y=Date.now(),Q=Z,H=!1,W=()=>{if(H)return;this.replaceFooterContent($,J(jX(Q,Y)))},X=null,V=()=>{if(H)return;let{nextDelayMs:z}=x$(Date.now()-Y,T1());X=setTimeout(()=>{W(),V()},Math.max(1,Math.ceil(z)))};return W(),V(),{setStatus(z){Q=z,W()},stop(){if(H=!0,X)clearTimeout(X)},elapsedSec(){return((Date.now()-Y)/1000).toFixed(1)}}}async openStatusCard($,Z,J="blue"){let Y=Date.now(),Q=q5({sessionName:this.sessionName,title:$,status:jX(Z,Y),template:J}),H=await a(this.chatId,Q);if(!H)return _(`session "${this.sessionName}": status card send failed title=${$}`),await w(this.chatId,`❌ 创建状态卡片失败: ${$}`),null;let W;try{W=await H$(H)}catch(X){return _(`session "${this.sessionName}": status card id_convert failed title=${$}: ${X}`),await w(this.chatId,`❌ 状态卡片初始化失败: ${$}`),null}return r0(W,1),{cardId:W,title:$,timer:this.startFooterTimer(W,Z,(X)=>_4($,X))}}setStatusCard($,Z){$?.timer.setStatus(Z)}async closeStatusCard($,Z){if(!$)return;$.timer.stop();let J=$.timer.elapsedSec(),Y=_4($.title,`${Z} (${J}s)`);await c0($.cardId);let Q=await L0($.cardId,R.footer,this.footerElement(Y));D0($.cardId);let H=await P0($.cardId,D$({durationSec:J,suffix:Z}));if(Q&&H)await m0($.cardId);else{let W=`footer=${Q?"ok":"MISS"}, settings=${H?"ok":"MISS"}`;_(`session "${this.sessionName}": status card terminal transaction incomplete card=${$.cardId.slice(0,12)} ${W}`),await w(this.chatId,`⚠️ 状态卡片终态写入失败 (${W}):${Z}`)}}async runLifecycle($,Z){let J=this.lifecycleTail,Y;this.lifecycleTail=new Promise((H)=>{Y=H}),await J;let Q=++this.lifecycleSequence;_(`session "${this.sessionName}": lifecycle#${Q} ${$} begin`);try{return await Z()}finally{Y(),_(`session "${this.sessionName}": lifecycle#${Q} ${$} end`)}}beginTurnOpen($=this.proc,Z=this.procEpoch,J=!1){if(this.openingTurnOwner)throw Error(`turn card open already owned by token=${this.openingTurnOwner.token}; same-process opens must wait for the current owner`);let Y,Q=new Promise((W)=>{Y=W}),H={token:++this.turnOpenSequence,proc:$,procEpoch:Z,sawResult:!1,terminalForcePush:!1,pendingCompactions:[],backendTurnStarted:J,done:Q,resolveDone:Y};return this.openingTurnOwner=H,this.openingTurn=!0,H}ownsTurnOpen($){return this.openingTurnOwner===$&&this.proc===$.proc&&this.procEpoch===$.procEpoch}releaseTurnOpen($){if(this.openingTurnOwner!==$)return;this.openingTurnOwner=null,this.openingTurn=!1,$.resolveDone()}invalidateTurnOpen(){let $=this.openingTurnOwner;this.openingTurnOwner=null,this.openingTurn=!1,$?.resolveDone()}async waitForTurnOpenSlot($,Z){while(this.openingTurnOwner)if(await this.openingTurnOwner.done,this.proc!==$||this.procEpoch!==Z||!$.isAlive())return!1;return this.proc===$&&this.procEpoch===Z&&$.isAlive()}beginBackgroundOpen(){if(this.backgroundCard||this.openingBackgroundOwner)return null;let $={token:++this.backgroundOpenSequence,proc:this.proc,procEpoch:this.procEpoch,generation:this.backgroundGeneration};return this.openingBackgroundOwner=$,this.openingBackground=!0,$}ownsBackgroundOpen($){return this.openingBackgroundOwner===$&&this.backgroundGeneration===$.generation&&this.proc===$.proc&&this.procEpoch===$.procEpoch}releaseBackgroundOpen($){if(this.openingBackgroundOwner!==$)return;this.openingBackgroundOwner=null,this.openingBackground=!1}invalidateBackgroundOpen(){this.backgroundGeneration++,this.openingBackgroundOwner=null,this.openingBackground=!1}attachProc($){this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.stoppingProc=null,this.blockedProc=null,this.blockedProcReason=null,this.proc=$;let Z=++this.procEpoch;this.wireProc($,Z)}detachProc($){if(this.proc!==$)return!1;if(this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.proc=null,this.agentCapability=null,this.stoppingProc===$)this.stoppingProc=null;if(this.blockedProc===$)this.blockedProc=null,this.blockedProcReason=null;return this.procEpoch++,!0}beginProcStop($){this.stoppingProc=$,this.agentCapability=null}acceptsAgentCapability($){let Z=this.agentCapability;if(!Z||!$||!this.proc?.isAlive())return!1;let J=Buffer.from(Z),Y=Buffer.from($);return J.length===Y.length&&Vq(J,Y)}async cancelAgentRuns($="用户取消"){await this.opts.onCancelAgentRuns?.(this.sessionName,this.chatId,$)}finishProcStop($,Z){if(this.stoppingProc===$)this.stoppingProc=null;if(!$.isAlive())return this.discardPendingCodexTurnAnchors($,"confirmed process stop"),this.detachProc($),!0;return this.blockedProc=$,this.blockedProcReason=Z?O(Z):"kill returned while process still reports alive",_(`session "${this.sessionName}": process stop unconfirmed; lifecycle blocked: ${this.blockedProcReason}`),!1}blockedProcessMessage(){let $=this.blockedProc;if(!$)return null;if(!$.isAlive())return this.detachProc($),null;return`旧 ${this.backendLabel($.provider)} 进程尚未确认退出,会话已阻断: ${this.blockedProcReason??"未知原因"}`}async stopOwnedProc($,Z){if(this.proc!==$)return!$.isAlive();this.beginProcStop($);let J=null;try{await $.kill(Z)}catch(Y){J=Y}return this.finishProcStop($,J)}async settleProcResumableState($){let Z=null,J=$.conversationMaterializationBarrier?.();if(J)try{await J}catch(H){Z=`Codex 会话落盘确认失败: ${O(H)}`}let Y=$.conversationMaterializationFailure?.();if(Y&&$.isConversationResumable?.()!==!0)Z=`Codex 会话落盘确认失败: ${O(Y)}`;let Q=this.persistResumableSessionId(!1,$,!1);return[Z,Q].filter(Boolean).join(";")||null}resetFreshConversationState(){this.daemonRestoreRequired=!1,this.turnCounter=0,this.pendingConversationMaterialization=null,a0(this.sessionName,[],{kind:"fresh"},null),this.currentGoal=null,this.cumStats={tokens:0,costUsd:0,turns:0},this.lastTurnDelta=null,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.lastTurnUsage=null,this.usageTotalsSeedUnknown=!1}async start($={}){return await this.runLifecycle("start",()=>this.startUnlocked($))}async startUnlocked($={}){let Z=$.announce??!0,J=$.onStatus,Y=this.blockedProcessMessage();if(Y){if(this.status="stopped",J?.(`❌ ${Y}`),Z)await E(this.chatId,`❌ ${Y}。请重试 stop/restart,或等待旧进程退出。`);return!1}if(this.proc&&!this.proc.isAlive())this.detachProc(this.proc);if(this.isRunning()){if(this.proc?.provider===this.selectedProvider)return J?.(this.withModel(`✅ ${this.backendLabel()} 已运行`)),!0;if(await this.stopIdleMismatchedProcessUnlocked(),this.proc?.isAlive())return J?.(`⚠️ 当前 ${this.backendLabel(this.proc.provider)} turn 尚未结束,模型切换将在后续新 turn 生效`),!0}if(this.selectedProvider==="codex")J?.("\uD83D\uDD0E 检查 Codex 登录");else J?.("\uD83D\uDD0E 检查 Claude Code");if(this.selectedProvider==="codex"&&!$4()){if(this.status="stopped",this.opts.onLifecycleChange?.(),J?.("❌ Codex 未登录 ChatGPT 账号"),Z)await E(this.chatId,"❌ Codex 未登录 ChatGPT 账号。\n请在服务器上运行 `codex login` 后再试。");return!1}if(!LX(this.workDir)){if(J?.(`\uD83C\uDD95 创建项目目录 ~/${this.sessionName}`),Z)await E(this.chatId,`\uD83C\uDD95 目录 ~/${this.sessionName} 不存在,正在创建…`);try{p8(this.workDir)}catch(G){if(this.status="stopped",this.opts.onLifecycleChange?.(),J?.(`❌ 创建项目失败: ${G}`),Z)await E(this.chatId,`❌ 创建项目失败: ${G}`);return!1}}if(!$.freshConversationStateAlreadyReset&&!this.pendingConversationMaterialization)this.resetFreshConversationState();this.status="starting",J?.(this.withModel(`\uD83D\uDE80 启动 ${this.backendLabel()}`));let Q;try{await G9(),Q=this.spawnAgent()}catch(G){let A=`${this.backendLabel()} 启动失败: ${O(G)}`;if(_(`session "${this.sessionName}": ${A}`),J?.(`❌ ${A}`),Z)await E(this.chatId,`❌ ${A}`);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}this.attachProc(Q);let H=this.backendLabel(),W=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(Q,PX):null;J?.(this.selectedProvider==="claude"?`⏳ 检查 ${H} 启动`:`⏳ 等待 ${H} init`);let X,V=null;try{Q.sendInitialize(),X=Q.initializationPromise?.()}catch(G){X=void 0,V=G}let z=V?{state:"error",error:V}:this.selectedProvider==="claude"?await W:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(X),()=>{_(`session "${this.sessionName}": codex init still pending after ${d3/1000}s`),J?.(this.withModel(`⏳ 仍在等待 ${H} init 确认`))});if(z.state==="error"||z.state==="exit"){let G=z.error?O(z.error):z.state;_(`session "${this.sessionName}": ${this.selectedProvider} init failed: ${G}`);let K=await this.stopOwnedProc(Q,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,L=`❌ ${H} 启动失败: ${G}${K}`;if(J?.(L),Z)await E(this.chatId,L);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(z.state==="timeout"){_(`session "${this.sessionName}": ${this.selectedProvider} init wait timeout (${w6/1000}s)`);let A=await this.stopOwnedProc(Q,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,K=`❌ ${H} 启动超时: ${w6/1000} 秒内初始化事务未完成${A}`;if(J?.(K),Z)await E(this.chatId,K);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(this.proc!==Q||!Q.isAlive()){let G=`${H} 启动期间已退出`;if(_(`session "${this.sessionName}": ${G}`),J?.(`❌ ${G}`),Z)await E(this.chatId,`❌ ${G}`);return this.detachProc(Q),this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(Z){let G=this.modelLine();await E(this.chatId,[this.withWorktreeInstructionNotice(`✅ Lodestar session "${this.sessionName}" 已就绪,发消息开始对话。`),G].filter(Boolean).join(`
|
|
200
|
+
`))}return this.status="idle",this.startedAt=Date.now(),this.daemonRestoreRequired=!1,this.opts.onLifecycleChange?.(),J?.(this.withModel(this.withWorktreeInstructionNotice(`✅ ${this.backendLabel()} 已就绪`))),!0}requireCodexInitializationPromise($){if(!$||typeof $.then!=="function")return Promise.reject(Error("Codex process did not expose its initialization transaction"));return Promise.resolve($)}async waitForCodexInitialization($,Z){return await new Promise((J)=>{let Y=!1,Q=(X,V)=>{if(Y)return;Y=!0,clearTimeout(H),clearTimeout(W),J({state:X,error:V})},H=setTimeout(()=>{if(Y)return;try{Z?.()}catch(X){Q("error",X)}},d3),W=setTimeout(()=>{Q("timeout",Error(`codex init timed out after ${w6/1000}s`))},w6);$.then(()=>Q("init"),(X)=>Q("error",X))})}async waitForProcEarlyFailure($,Z){return await new Promise((J)=>{let Y=!1,Q=(z,G)=>{if(Y)return;Y=!0,clearTimeout(H),$.off("init",W),$.off("error",X),$.off("exit",V),J({state:z,error:G})},H=setTimeout(()=>Q("ready"),Z),W=()=>Q("init"),X=(z)=>Q("error",z),V=(z)=>Q("exit",z);$.once("init",W),$.once("error",X),$.once("exit",V)})}releaseAllReactions(){for(let[$,Z]of[...this.pendingReactionIds.entries(),...this.currentBatchReactionIds.entries()])if(Z)T0($,Z);this.pendingReactionIds=new Map,this.currentBatchReactionIds=new Map}clearStaleIdleQueueState($){if(this.initCount<1||this.currentTurn||this.openingTurn||this.pendingUserMessageCount===0)return;_(`session "${this.sessionName}": clear stale pending queue before ${$} pendingCount=${this.pendingUserMessageCount} reactions=${this.pendingReactionIds.size}`),this.pendingUserMessageCount=0;for(let[Z,J]of this.pendingReactionIds)if(J)T0(Z,J);this.pendingReactionIds=new Map}async stop($="已终止",Z={}){await this.runLifecycle("stop",()=>this.stopUnlocked($,Z))}async stopUnlocked($="已终止",Z={}){let J=Z.announce??!0,Y=Z.onStatus;if(this.daemonRestoreRequired=!1,await this.cancelAgentRuns($),!this.proc){if(this.status="stopped",this.opts.onLifecycleChange?.(),Y?.("⚪ session 当前未运行"),J)await E(this.chatId,`⚪ session "${this.sessionName}" 当前未运行`);return}let Q=this.proc,H=this.persistResumableSessionId(!1,Q,!1),W=null;if(Y?.(`\uD83D\uDED1 停止 ${this.backendLabel(this.proc.provider)}`),_(`session "${this.sessionName}": stop (${$})`),this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.currentTurn)this.closeTurnCard(`\uD83D\uDED1 ${$}`).catch((P)=>{_(`session "${this.sessionName}": stop current main-card close failed: ${O(P)}`)});let X=this.waitForTurnCloses().catch((P)=>_(`session "${this.sessionName}": stop main-card close failed: ${O(P)}`));this.beginProcStop(Q),this.status="stopped";let V=[];try{this.opts.onLifecycleChange?.()}catch(P){V.push(P),_(`session "${this.sessionName}": stop intent lifecycle write failed: ${O(P)}`)}let z=Q.conversationMaterializationBarrier?.();if(z){try{await z}catch(P){W=`Codex 会话落盘确认失败: ${O(P)}`}H=this.persistResumableSessionId(!1,Q,!1)}this.clearMultiMsgBuffer("stop"),this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),this.initCount=0,this.invalidateTurnOpen(),this.bgResumePending=!1,this.discardOrphanAssistant(),this.pendingAsks.clear(),this.pendingPermissions.clear(),this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.usageTotalsSeedUnknown=!1;let G=null;try{await Q.kill()}catch(P){G=P}let A=Q.conversationMaterializationFailure?.();if(A&&Q.isConversationResumable?.()!==!0)W=`Codex 会话落盘确认失败: ${O(A)}`;H=this.persistResumableSessionId(!1,Q,!1);let L=(await Promise.allSettled([this.resetBackgroundTasks(),X])).filter((P)=>P.status==="rejected").map((P)=>P.reason);for(let P of L)_(`session "${this.sessionName}": stop terminal cleanup failed: ${O(P)}`);let D=this.finishProcStop(Q,G);try{this.opts.onLifecycleChange?.()}catch(P){V.push(P),_(`session "${this.sessionName}": stop final lifecycle write failed: ${O(P)}`)}let q=[...G?[G]:[],...!D&&!G?[Error(this.blockedProcReason??"process stop unconfirmed")]:[],...L,...V,...H?[Error(H)]:[],...W&&Q.isConversationResumable?.()!==!0?[Error(W)]:[]];if(q.length===1)throw q[0];if(q.length>1)throw AggregateError(q,`stop failed: ${q.map(O).join("; ")}`);if(Y?.(`✅ ${$}`),J)await E(this.chatId,`\uD83D\uDD34 ${$} (session: ${this.sessionName})`)}async restart($=!1,Z={}){return await this.runLifecycle("restart",()=>this.restartUnlocked($,Z))}requireDaemonRestore(){this.daemonRestoreRequired=!0}async restoreAfterDaemonRestart(){return await this.runLifecycle("daemon-restore",async()=>{if(this.requireDaemonRestore(),!this.lastSessionRef&&!this.pendingMaterializationLaunch())return this.status="stopped",this.opts.onLifecycleChange?.(),await E(this.chatId,"❌ daemon 重启后没有可用的恢复点。请发送 rs 选择历史会话,或 hi 明确启动新会话。"),!1;return await this.restartUnlocked(!0)})}async restartUnlocked($=!1,Z={},J){let Y=Z.announce??!0,Q=Z.onStatus,H=this.status,W=null;if(!$&&!this.pendingConversationLaunch&&this.pendingConversationMaterialization)W=this.pendingConversationMaterialization,b$(this.sessionName,null),this.pendingConversationMaterialization=null;let X=this.pendingConversationLaunch??this.pendingMaterializationLaunch(),V=this.lastSessionRef;if($&&!X&&V?.cwd===null)try{V=await this.resolveLegacyResumeRef(V),this.lastSessionRef=V,this.lastSessionId=V.sessionId}catch(N){let f=this.invalidateMissingCodexResume(V.sessionId,N,J),I=f?`❌ 旧会话不可恢复: ${O(N)};${f}`:`❌ 旧会话 cwd 校验失败: ${O(N)};请在进程已停时发送 rs 重新选择历史会话`;if(this.status=this.proc?.isAlive()?H:"stopped",Q?.(I),Y)await E(this.chatId,I);return!1}let z=V?.sessionId??null,G=X&&X.kind!=="fresh"?X.source.sessionId:z,A=G?q0(G):"",K=null,L=(N=this.proc)=>{if(!$||X||N?.provider!=="codex"||N.isConversationResumable?.()!==!0)return;K=this.persistResumableSessionId(!1,N,!1),V=this.lastSessionRef,z=V?.sessionId??null,G=z,A=G?q0(G):""},D=null;if(!Q&&Y&&$&&z){let N=this.proc?this.withModel(`\uD83D\uDD01 重启 ${this.backendLabel(this.proc.provider)}`):this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${A}`);if(D=await this.openStatusCard("restart",N),D)Q=(f)=>this.setStatusCard(D,f)}let q=Y&&!D,P=async(N)=>{if(D)await this.closeStatusCard(D,N)},x=Boolean(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0||this.pendingTurnInputs.length>0||this.backgroundTasks.length>0||this.pendingBgTasks.length>0||this.openingBackground);if(this.bgResumePending=!1,this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.discardOrphanAssistant(),this.currentTurn)this.closeTurnCard("\uD83D\uDD01 已中止,正在重启").catch((N)=>{_(`session "${this.sessionName}": restart current main-card close failed: ${O(N)}`)});let F=this.waitForTurnCloses().catch((N)=>_(`session "${this.sessionName}": restart main-card close failed: ${O(N)}`)),M=null,j=null;if(this.proc){let N=this.proc;Q?.(`\uD83D\uDED1 停止当前 ${this.backendLabel(N.provider)}`),j=N,this.beginProcStop(N);let f=N.conversationMaterializationBarrier?.();if(f)try{await f}catch(T){K=`Codex 会话落盘确认失败: ${O(T)}`}if(L(N),$&&!X&&K&&!x&&N.isAlive()){if(this.stoppingProc===N)this.stoppingProc=null;this.status=H;let T=`❌ ${this.backendLabel(N.provider)} 恢复点尚未安全落盘,已保留当前进程: ${K}`;if(_(`session "${this.sessionName}": abort restart before kill: ${K}`),Q?.(T),q)await E(this.chatId,T);return await P(T),!1}try{await N.kill()}catch(T){M=T}let I=N.conversationMaterializationFailure?.();if(I&&N.isConversationResumable?.()!==!0)K=`Codex 会话落盘确认失败: ${O(I)}`;L(N)}this.clearMultiMsgBuffer("restart"),this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),this.initCount=0,this.invalidateTurnOpen(),this.pendingAsks.clear(),this.pendingPermissions.clear(),this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;let C=(await Promise.allSettled([this.resetBackgroundTasks(),F])).filter((N)=>N.status==="rejected").map((N)=>N.reason);for(let N of C)_(`session "${this.sessionName}": restart terminal cleanup failed: ${O(N)}`);let c=j?this.finishProcStop(j,M):!0,y=[...M?[`kill=${O(M)}`]:[],...!c&&!M?[`kill=${this.blockedProcReason??"process stop unconfirmed"}`]:[],...C.map((N)=>`cleanup=${O(N)}`),...K?[`resume=${K}`]:[]];if(y.length>0&&W)try{b$(this.sessionName,W),this.pendingConversationMaterialization=W}catch(N){y.push(`pendingRestore=${O(N)}`)}if(y.length>0){let N=`❌ 旧 ${this.backendLabel()} 进程停止/清理失败: ${y.join("; ")}`;if(this.status="stopped",this.opts.onLifecycleChange?.(),Q?.(N),q)await E(this.chatId,N);return await P(N),!1}let m=X?.kind==="resume"||X?.kind==="fork";if($&&V||m){this.status="starting",this.usageTotalsSeedUnknown=!0,Q?.(this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${A}`));let N;try{await G9(),N=this.spawnAgent(V??void 0)}catch(l){let W0=`❌ ${this.backendLabel()} 恢复失败: ${O(l)}`;if(_(`session "${this.sessionName}": ${this.selectedProvider} resume failed before spawn: ${O(l)}`),Q?.(W0),q)await E(this.chatId,W0);return this.status="stopped",this.opts.onLifecycleChange?.(),await P(W0),!1}this.attachProc(N);let f=this.backendLabel(),I=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(N,PX):null;Q?.(this.selectedProvider==="claude"?`⏳ 检查 ${f} 恢复启动`:`⏳ 等待 ${f} init 确认`);let T,U=null;try{N.sendInitialize(),T=N.initializationPromise?.()}catch(l){T=void 0,U=l}let b=U?{state:"error",error:U}:this.selectedProvider==="claude"?await I:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(T),()=>{_(`session "${this.sessionName}": codex resume init still pending after ${d3/1000}s`),Q?.(this.withModel(`⏳ 仍在等待 ${f} init 确认 thread=${A}`))});if(b.state==="error"||b.state==="exit"||b.state==="timeout"){let l=b.state==="error"?this.invalidateMissingCodexResume(G,b.error,J):null,W0=[b.error?O(b.error):b.state,l].filter(Boolean).join(";");_(`session "${this.sessionName}": ${this.selectedProvider} resume failed: ${W0}`);let M2=await this.stopOwnedProc(N,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,i0=b.state==="timeout"?`❌ ${f} 恢复超时${M2}`:`❌ ${f} 恢复失败: ${W0}${M2}`;if(Q?.(i0),q)await E(this.chatId,i0);return this.status="stopped",this.opts.onLifecycleChange?.(),await P(i0),!1}if(this.proc!==N||!N.isAlive()){let l=`❌ ${f} 恢复期间已退出`;if(_(`session "${this.sessionName}": ${this.selectedProvider} resume process exited before ready`),Q?.(l),q)await E(this.chatId,l);return this.detachProc(N),this.status="stopped",this.opts.onLifecycleChange?.(),await P(l),!1}let H0=this.withModel(this.withWorktreeInstructionNotice(this.selectedProvider==="claude"&&b.state==="ready"?`✅ 已准备恢复上一会话 thread=${A}`:`✅ 已恢复上一会话 thread=${A}`));if(Q?.(H0),q)await E(this.chatId,H0);this.status="idle",this.startedAt=Date.now(),this.daemonRestoreRequired=!1,this.opts.onLifecycleChange?.();try{await P(H0)}catch(l){_(`session "${this.sessionName}": restart succeeded but status-card close failed: ${O(l)}`),await w(this.chatId,`⚠️ ${H0}
|
|
201
|
+
状态卡收尾失败: ${O(l)}`)}return!0}else{if($&&!X){if(Q?.("⚠️ 没有可恢复的上一会话,将以新会话启动"),q)await E(this.chatId,"⚠️ 没有可恢复的上一会话,将以新会话启动")}return this.resetFreshConversationState(),await this.startUnlocked({...Z,freshConversationStateAlreadyReset:!0})}}async startForked($,Z={}){return await this.runLifecycle("start-forked",async()=>{V0($,this.selectedProvider,this.workDir);let J=r2(this.sessionName),Y=this.selectedProvider==="claude"?{launch:$,previousSessionId:this.lastSessionId}:null;if(Y)b$(this.sessionName,Y),this.pendingConversationMaterialization=Y;this.pendingConversationLaunch=$;try{let Q=await this.startUnlocked(Z);if(!Q&&Y)b$(this.sessionName,J),this.pendingConversationMaterialization=J;return Q}catch(Q){if(!Y)throw Q;try{b$(this.sessionName,J),this.pendingConversationMaterialization=J}catch(H){throw AggregateError([Q,H],`fork start and pending-intent restore failed: ${O(Q)}; ${O(H)}`)}throw Q}finally{this.pendingConversationLaunch=null}})}async rollbackTo($,Z,J={}){return await this.runLifecycle("rollback",async()=>{V0($,this.selectedProvider,this.workDir);let Y=Z?{anchors:Z.anchors.slice(),base:Z.base,pendingLaunch:Z.pendingLaunch!==void 0?Z.pendingLaunch:this.selectedProvider==="claude"&&$.kind==="fork"?{launch:$,previousSessionId:this.lastSessionId}:null}:null,Q=this.proc,H=this.lastSessionId,W=this.lastSessionRef,X=a2(this.sessionName).slice(),V=o2(this.sessionName),z=r2(this.sessionName),G={turnCounter:this.turnCounter,currentGoal:this.currentGoal,cumStats:{...this.cumStats},lastTurnDelta:this.lastTurnDelta?{...this.lastTurnDelta}:null,currentTurnUsageBaseline:this.currentTurnUsageBaseline?{...this.currentTurnUsageBaseline}:null,currentTurnUsageBaselineKnown:this.currentTurnUsageBaselineKnown,lastTurnUsage:this.lastTurnUsage?{...this.lastTurnUsage}:null,usageTotalsSeedUnknown:this.usageTotalsSeedUnknown},A=!1,K=()=>{if(A)this.lastSessionId=null,this.lastSessionRef=null,a1(this.sessionName,"codex");else if(this.lastSessionId=H,this.lastSessionRef=W,W)n2(this.sessionName,W);else a1(this.sessionName,this.selectedProvider);a0(this.sessionName,X,V,z),this.pendingConversationMaterialization=z,this.turnCounter=G.turnCounter,this.currentGoal=G.currentGoal,this.cumStats=G.cumStats,this.lastTurnDelta=G.lastTurnDelta,this.currentTurnUsageBaseline=G.currentTurnUsageBaseline,this.currentTurnUsageBaselineKnown=G.currentTurnUsageBaselineKnown,this.lastTurnUsage=G.lastTurnUsage,this.usageTotalsSeedUnknown=G.usageTotalsSeedUnknown},L=!1;if(Y?.pendingLaunch)a0(this.sessionName,Y.anchors,Y.base,Y.pendingLaunch),this.pendingConversationMaterialization=Y.pendingLaunch,L=!0;this.pendingConversationLaunch=$;let D=(q)=>{A=W?.provider==="codex"&&W.sessionId===q};try{let q;try{q=$.kind==="fresh"?await this.restartUnlocked(!1,J,D):await this.restartUnlocked(!0,J,D)}catch(P){let x=null,F=this.proc&&this.proc!==Q?this.proc:null;if(F)try{await this.stopUnlocked("回滚启动事务失败",{announce:!1})}catch(C){x=C}let M=!F||this.proc!==F&&!F.isAlive();if(!M&&!x)x=Error("replacement process stop was not confirmed");let j=null;if(M)try{K()}catch(C){j=C}let k=[P,...x?[x]:[],...j?[j]:[]];if(k.length===1)throw P;throw AggregateError(k,`rollback launch and cleanup failed: ${k.map(O).join("; ")}`)}if(!q)return K(),!1;if(Y)try{if(!L)a0(this.sessionName,Y.anchors,Y.base,Y.pendingLaunch);this.pendingConversationMaterialization=Y.pendingLaunch}catch(P){let x=null,F=this.proc;try{await this.stopUnlocked("回滚分支状态持久化失败",{announce:!1})}catch(C){x=C}let M=!F||this.proc!==F&&!F.isAlive();if(!M&&!x)x=Error("replacement process stop was not confirmed");let j=null;if(M)try{K()}catch(C){j=C}let k=[P,...x?[x]:[],...j?[j]:[]];if(k.length===1)throw P;throw AggregateError(k,`rollback branch commit failed: ${k.map(O).join("; ")}`)}return q}finally{this.pendingConversationLaunch=null}})}dispose(){s0.all.delete(this)}recordTurnAnchor($){let Z=this.proc;if(!Z?.sessionId||!$)return null;if($.provider!==Z.provider||$.source.sessionId!==Z.sessionId||$.source.cwd!==this.workDir){let Y=`拒绝了与当前会话不匹配的 checkpoint provider=${$.provider} source=${$.source.sessionId}`;return _(`session "${this.sessionName}": ${Y}`),this.lastTurnUserPreview="",Y}let J={checkpoint:$,preview:this.lastTurnUserPreview.slice(0,80),ts:Date.now(),writes:this.collectTurnWrites()};if(this.lastTurnUserPreview="",Z.provider==="codex"&&Z.isConversationResumable?.()!==!0){if(this.pendingCodexTurnAnchors.filter((Q)=>Q.proc===Z).length>=64)return _(`session "${this.sessionName}": ${"Codex rollout 长期未确认,延迟 checkpoint 队列已满"} thread=${Z.sessionId}`),"Codex rollout 长期未确认,延迟 checkpoint 队列已满";return this.pendingCodexTurnAnchors.push({proc:Z,anchor:J}),_(`session "${this.sessionName}": defer Codex turn checkpoint until rollout confirmation thread=${Z.sessionId} checkpoint=${$.id}`),null}return this.appendTurnAnchor(J)}appendTurnAnchor($){try{return N8(this.sessionName,$),null}catch(Z){let J=`分叉 checkpoint 持久化失败: ${O(Z)}`;return _(`session "${this.sessionName}": ${J}`),J}}flushPendingCodexTurnAnchors($){let Z=null,J=[];for(let Y of this.pendingCodexTurnAnchors){if(Y.proc!==$||Z){J.push(Y);continue}if(Z=this.appendTurnAnchor(Y.anchor),Z)J.push(Y)}return this.pendingCodexTurnAnchors=J,Z}discardPendingCodexTurnAnchors($,Z){if($.provider!=="codex")return;let J=this.pendingCodexTurnAnchors.length;this.pendingCodexTurnAnchors=this.pendingCodexTurnAnchors.filter((Q)=>Q.proc!==$);let Y=J-this.pendingCodexTurnAnchors.length;if(Y>0)_(`session "${this.sessionName}": dropped ${Y} unmaterialized Codex checkpoint(s): ${Z}`)}collectTurnWrites(){let $=this.currentTurn;if(!$)return[];let Z=[];for(let J of $.toolByUseId.values())Z.push(...C5(J.name,J.input));return Z}worktreeProjectName(){return p$(this)}worktreeProjectDir(){return L2(this)}spawnDeveloperInstructions(){return aW(this)}delegatedAgentDeveloperInstructions($){return oW(this,$)}worktreeInstructionLoadedNotice(){return m3(this)}withWorktreeInstructionNotice($){return rW(this,$)}worktreeExtraInstruction(){return N4(this)}runWorktreeCommand($,Z){return tW(this,$,Z)}showWorktrees(){return u3(this)}showTasklistPanel(){return EW(this)}showAgentIdentityPanel($=""){return DW(this,$)}onAgentIdentityPage($,Z,J){return PW($,Z,J)}onTasklistEnable(){return NW(this)}onTasklistDeletePrompt($){return SW(this,$)}onTasklistDeleteConfirm($){return xW(this,$)}runCompactCommand(){return HW(this)}showModelPanel(){return XW(this)}onModelSelect($,Z="",J="",Y=null){return this.runLifecycle("model-select",()=>BW(this,$,Z,J,Y))}onModelEffortSelect($,Z,J="",Y="",Q=""){return this.runLifecycle("model-effort-select",()=>S3(this,$,Z,J,Y,Q))}onProviderSelect($,Z=""){return N3(this,$,Z)}onModelPage($,Z,J){return R6(this,$,Z,J)}onModelAddOpen($,Z){return VW(this,$,Z)}onModelListEdit($,Z,J,Y){return this.runLifecycle("model-list-edit",()=>zW(this,$,Z,J,Y))}onModelPanelCancel($=""){return AW(this,$)}onModelCustomPrompt($,Z,J=""){return GW(this,$,Z,J)}consumeModelCustomMessage($,Z){return _W(this,$,Z)}onWorktreeDisband($){return eW(this,$)}showForkList($=""){return WX(this,$)}showBackList($=""){return XX(this,$)}showResumeList($=""){return VX(this,$)}runBtwCommand($){return zX(this,$)}runByeCommand(){return GX(this)}onForkSelect($,Z,J=""){return _X(this,$,Z,J)}onBackSelect($,Z,J=""){return AX(this,$,Z,J)}onResumeSelect($,Z,J=""){return KX(this,$,Z,J)}runCommand($,Z=""){return YW(this,$,Z)}async buildConsoleOpts($,Z){let J=await BQ(),Y=this.runtimeModelSelection();return{sessionName:this.sessionName,status:this.status,provider:Y.provider,model:Y.model??void 0,effort:Y.effort??"MISS",worktreeInstructionNotice:this.worktreeInstructionLoadedNotice(),peers:[...s0.all].filter((Q)=>Q.isRunning()).map((Q)=>({...Q.peerSnapshot(),isCurrent:Q===this})),usage:$,glmUsage:Z,sysinfo:J}}async buildConsoleCard($){return P5(await this.buildConsoleOpts($))}async patchConsoleUsage($){let Z=await this.buildConsoleOpts(void 0),J=Z.provider??this.currentProvider(),Y=this.currentTokenSource(),Q=Y&&Y.agent===J&&Y.enabled?Y:this.selectedTokenSourceId?void 0:z9(J)[0];if(Q)Z.unifiedUsage=await Q.readUsage();else if(this.selectedTokenSourceId)Z.unifiedUsage={state:"no_credentials",windows:[],reason:`token source ${this.selectedTokenSourceId} unavailable`};else if(Z.provider==="claude")Z.glmUsage=await dQ();else Z.usage=await V6();if(!await L0($,R.consoleUsage,A4(Z),{notifyCardFailure:!1}))throw Error("console usage element replace rejected")}async mutateStaticCard($,Z,J){let Y=!0;try{await J()}catch(H){Y=!1,_(`session "${this.sessionName}": ${Z} mutation failed: ${O(H)}`)}let Q=!1;try{Q=await P0($,{config:{streaming_mode:!1}})}catch(H){_(`session "${this.sessionName}": ${Z} streaming-off failed: ${O(H)}`)}if(!Y||!Q)return _(`session "${this.sessionName}": ${Z} state retained after checked MISS mutation=${Y} streamingOff=${Q} card=${$.slice(0,12)}`),!1;try{await m0($)}catch(H){return _(`session "${this.sessionName}": ${Z} dispose failed: ${O(H)}`),!1}return Y}patchConsoleUsageLater($){this.mutateStaticCard($,"console usage",()=>this.patchConsoleUsage($))}async replaceStatusCardWithConsole($,Z){$.timer.stop();let J=$.timer.elapsedSec(),Y=await this.buildConsoleOpts(void 0);await c0($.cardId);let Q=await L0($.cardId,R.footer,d9(Y,R.footer)),H=await w$($.cardId,i9(Y),{type:"insert_after",targetElementId:R.footer}),W=await w$($.cardId,n9(Y.sysinfo),{type:"insert_after",targetElementId:R.consoleProjects}),X=await w$($.cardId,A4(Y),{type:"insert_after",targetElementId:R.consoleHost});if(!Q||!H||!W||!X){await w(this.chatId,"⚠️ 控制台卡片结构写入失败,请重新发送 hi。"),await this.mutateStaticCard($.cardId,"console structure",async()=>{});return}D0($.cardId),await P0($.cardId,D$({durationSec:J,suffix:Z})),this.patchConsoleUsageLater($.cardId)}async showConsole(){let $=await this.buildConsoleCard(void 0),Z=await a(this.chatId,$);if(!Z)return;(async()=>{let J="";try{J=await H$(Z),r0(J,4)}catch(Y){_(`session "${this.sessionName}": console card conversion failed: ${O(Y)}`);return}await this.mutateStaticCard(J,"console usage",()=>this.patchConsoleUsage(J))})().catch((J)=>_(`session "${this.sessionName}": console async update rejected: ${O(J)}`))}interrupt(){if(!this.proc)return;_(`session "${this.sessionName}": interrupt`),this.proc.sendInterrupt()}sendClaimedUserText($,Z){this.pendingUserMessageCount++;try{$.sendUserText(Z,[])}catch(J){throw this.pendingUserMessageCount=Math.max(0,this.pendingUserMessageCount-1),J}}async startColdUserTurn($,Z,J){if(!this.pendingConversationMaterialization)this.resetFreshConversationState();this.pendingTurnInputs.push($);let Y=this.beginTurnOpen();try{let H=await this.openTurnCard(Y,J,"user_message",{initialFooter:"Waiting...(0s)",startThinking:!1,directStart:!0});if(!H||this.currentTurn!==H)return;let W=this.startFooterTimer(H.cardId,`\uD83D\uDE80 启动 ${this.backendLabel()}`,(G)=>this.withModel(G)),X=`\uD83D\uDE80 启动 ${this.backendLabel()}`,V=await this.startUnlocked({announce:!1,freshConversationStateAlreadyReset:!0,onStatus:(G)=>{X=G,W.setStatus(G)}});if(W.stop(),await c0(H.cardId),!V){this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),await this.closeTurnCard(X.startsWith("❌")?X:"❌ 启动失败",{forcePush:!0});return}let z=this.proc;if(!z?.isAlive()){await this.closeTurnCard(`❌ ${this.backendLabel()} 启动后已退出`,{forcePush:!0});return}this.startThinkingFooter(H),this.sendClaimedUserText(z,Z),this.status="working"}finally{this.releaseTurnOpen(Y)}}async onUserMessage($,Z=[],J="",Y=""){await this.runLifecycle("user-message",()=>this.onUserMessageUnlocked($,Z,J,Y))}async onUserMessageUnlocked($,Z,J,Y){let Q=this.blockedProcessMessage();if(Q){await E(this.chatId,`❌ ${Q}。请重试 stop/restart,或等待旧进程退出。`);return}if(this.daemonRestoreRequired){await E(this.chatId,"❌ daemon 重启后的会话恢复尚未成功,这条消息未送给 Agent。请发送 rs 选择历史会话,或 hi 明确启动新会话,然后重发消息。");return}if(this.clearStaleIdleQueueState("user_message"),this.proc?.isAlive()&&!this.currentTurn&&!this.openingTurn&&this.pendingUserMessageCount===0&&this.pendingMidTurnMsgs.length===0)await this.stopIdleMismatchedProcessUnlocked();let H=this.currentTurn!==null||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0;this.lastUserOpenId=J;let X=(Z.length?Z.map((z)=>`[file: ${z}]`).join(" ")+`
|
|
202
|
+
`:"")+$,V=(z)=>{this.pendingReactionIds.set(z,""),(async()=>{let G=await b0(z,"OneSecond");if(!G)return;if(this.pendingReactionIds.has(z))this.pendingReactionIds.set(z,G);else if(this.currentBatchReactionIds.has(z))this.currentBatchReactionIds.set(z,G);else T0(z,G)})().catch((G)=>{_(`session "${this.sessionName}": reaction tracking failed: ${O(G)}`)})};if(!this.isRunning()){if(this.openingTurn||this.currentTurn){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Y}),Y)V(Y);return}await this.startColdUserTurn($,X,J);return}if(this.currentTurn!==null){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Y}),Y)V(Y);return}if(!this.openingTurn&&this.initCount>=1){let z=this.proc,G=this.procEpoch,A=this.beginTurnOpen(z,G);try{this.pendingTurnInputs.push($);let K=await this.openTurnCard(A,J,"user_message");if(!K||this.currentTurn!==K)return;if(this.proc!==z||this.procEpoch!==G||!z.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel(z.provider)} 已退出`);return}this.sendClaimedUserText(z,X),this.status="working"}finally{this.releaseTurnOpen(A)}return}if(this.openingTurn||this.pendingUserMessageCount>0){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Y}),Y)V(Y);return}if(this.pendingTurnInputs.push($),this.sendClaimedUserText(this.proc,X),H&&Y)V(Y)}hasPendingAsk(){return FH(this)}refreshPendingAsks(){B6(this)}askBlockReason($){return V2(this,$)}onMultiMessageInbound($,Z,J,Y){return sQ(this,$,Z,J,Y)}clearMultiMsgBuffer($){n5(this,$)}onAskMessageAnswer($,Z,J){return MH(this,$,Z,J)}onAskAnswer($,Z,J,Y){return RH(this,$,Z,J,Y)}onAskCustomAnswer($,Z,J,Y){return Q3(this,$,Z,J,Y)}onPermissionDecision($,Z,J){return SH(this,$,Z,J)}clearResumeBindingForFreshCodex($){if($.isConversationResumable?.())throw Error("fresh Codex thread was unexpectedly marked resumable during init");let Z=X1(this.sessionName,"codex");if(a1(this.sessionName,"codex"),this.selectedProvider==="codex")this.lastSessionRef=null,this.lastSessionId=null;if(Z)_(`session "${this.sessionName}": cleared pre-fresh Codex resume binding thread=${Z.sessionId}`)}invalidateMissingCodexResume($,Z,J){if(!$||this.selectedProvider!=="codex")return null;let Y=n3(Z);if(!Y||!["thread/read","thread/resume","thread/fork"].includes(Y.method)||Y.serverCode!==-32600||Y.serverMessage!==`no rollout found for thread id ${$}`)return null;let Q=X1(this.sessionName,"codex");if(!Q||Q.sessionId!==$)return null;try{a1(this.sessionName,"codex")}catch(W){let X=`已确认恢复点无 rollout,但作废失败: ${O(W)}`;return _(`session "${this.sessionName}": ${X} thread=${$}`),X}if(this.lastSessionRef?.provider==="codex"&&this.lastSessionRef.sessionId===$)this.lastSessionRef=null,this.lastSessionId=null;J?.($);let H=`已作废无 rollout 的恢复点 thread=${q0($)}`;return _(`session "${this.sessionName}": ${H} fullThread=${$}`),H}persistResumableSessionId($=!1,Z=this.proc,J=!0){let Y=Z?.provider==="claude"?this.pendingConversationMaterialization:null,Q=Z?.sessionId;if(!Z)return null;if(Z.provider==="codex"&&Z.isConversationResumable?.()!==!0)return null;if(!Q){if(!Y)return null;let X=Error("Claude pending fork did not provide a materialized session id");if(_(`session "${this.sessionName}": ${X.message}`),$)throw X;return X.message}let H={provider:Z.provider,sessionId:Q,cwd:this.workDir};if(Y&&(Q===Y.launch.source.sessionId||Y.previousSessionId!==null&&Q===Y.previousSessionId)){let X=Error(`Claude fork did not materialize an independent session id (${Q})`);if(_(`session "${this.sessionName}": ${X.message}`),$)throw X;return X.message}try{n2(this.sessionName,H)}catch(X){let V=`会话恢复点持久化失败: ${O(X)}`,z=this.resumePersistenceError!==V;if(this.resumePersistenceError=V,Z.provider===this.selectedProvider)this.lastSessionRef=H,this.lastSessionId=Q;if(_(`session "${this.sessionName}": ${V}`),$)throw X;if(z&&J)w(this.chatId,`⚠️ ${V};当前进程可继续,但 daemon 重启前请先解决本机状态目录写入问题。`);return V}if(Z.provider===this.selectedProvider)this.lastSessionRef=H,this.lastSessionId=Q;let W=Z.provider==="codex"?this.flushPendingCodexTurnAnchors(Z):null;if(W){let X=this.resumePersistenceError!==W;if(this.resumePersistenceError=W,$)throw Error(W);if(X&&J)w(this.chatId,`⚠️ ${W}`);return W}return this.resumePersistenceError=null,null}consumePendingConversationMaterialization(){let $=this.pendingConversationMaterialization;if(!$)return null;let Z=this.lastSessionRef;if(Z?.provider!=="claude"||Z.cwd!==this.workDir||Z.sessionId===$.launch.source.sessionId||Z.sessionId===$.previousSessionId)return _(`session "${this.sessionName}": ${"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker"}`),"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker";try{return b$(this.sessionName,null),this.pendingConversationMaterialization=null,null}catch(J){let Y=`Claude 待生成分支标记清除失败: ${O(J)}`;return _(`session "${this.sessionName}": ${Y}`),Y}}bgStore(){return{active:this.backgroundTasks,pending:this.pendingBgTasks}}applyBgStore($){this.backgroundTasks=$.active,this.pendingBgTasks=$.pending}onMainThreadAdvance(){if(this.pendingBgTasks.length===0)return;this.applyBgStore(p7(this.bgStore())),this.onBackgroundTaskChanged()}bgTaskOwns($){return this.backgroundTasks.some((Z)=>Z.toolUseId===$)||this.pendingBgTasks.some((Z)=>Z.toolUseId===$)}onBackgroundTaskChanged(){if(this.migratingBackgroundCard){this.pendingRebuildBackgroundCard=!0;return}if(!J1(this.backgroundTasks)){if(this.backgroundCard)this.settleBackgroundCard().catch((Z)=>{_(`session "${this.sessionName}": background settle failed: ${O(Z)}`)});return}if(!this.backgroundCard&&!this.openingBackground){this.openBackgroundCard().catch((Z)=>{_(`session "${this.sessionName}": background open failed: ${O(Z)}`)});return}this.scheduleBackgroundRefresh()}async openBackgroundCard(){let $=this.beginBackgroundOpen();if(!$)return;let Z=this.backgroundTasks.slice();try{let J=a7(Z,Date.now(),T1()),Y=await a(this.chatId,J);if(!Y){if(this.ownsBackgroundOpen($))_(`session "${this.sessionName}": background card send failed`);return}let Q;try{Q=await H$(Y)}catch(H){_(`session "${this.sessionName}": background card id_convert failed: ${H}`);return}if(r0(Q,Z.length),!this.ownsBackgroundOpen($)){await this.terminalizeSupersededCard(Q,"⚠️ 后台任务世代已切换,本卡已作废",!1);return}if(this.backgroundCard={messageId:Y,cardId:Q},this.backgroundDetailAdded=new Set(Z.map((H)=>H.id)),this.backgroundDetailAdding.clear(),_(`session "${this.sessionName}": background card opened cardId=${Q.slice(0,12)} tasks=${Z.length}`),!J1(this.backgroundTasks)){this.settleBackgroundCard().catch((H)=>{_(`session "${this.sessionName}": background settle-after-open failed: ${O(H)}`)});return}this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}finally{this.releaseBackgroundOpen($)}}startBackgroundRefreshTick(){if(this.backgroundRefreshTick)return;let $=()=>{if(this.migratingBackgroundCard||!this.backgroundCard||!J1(this.backgroundTasks))return;let Z=T1(),J=Date.now(),Y=1/0;for(let Q of this.backgroundTasks){if(g0(Q))continue;let H=x$(J-Q.startedAt,Z).nextDelayMs;if(H<Y)Y=H}if(!isFinite(Y))return;this.backgroundRefreshTick=setTimeout(()=>{this.refreshBackgroundCardFull(),$()},Math.max(1,Math.ceil(Y)))};$()}stopBackgroundRefreshTick(){if(this.backgroundRefreshTick)clearTimeout(this.backgroundRefreshTick),this.backgroundRefreshTick=null}scheduleBackgroundRefresh(){if(!this.backgroundCard||this.settlingBackgroundCard||this.migratingBackgroundCard)return;if(this.backgroundRefreshTimer)return;this.backgroundRefreshTimer=setTimeout(()=>{this.backgroundRefreshTimer=null,this.refreshBackgroundCardFull()},1500)}refreshBackgroundCardFull(){if(this.migratingBackgroundCard)return;let $=this.backgroundCard;if(!$)return;let Z=Date.now(),J=T1();for(let Y of this.backgroundTasks)if(!this.backgroundDetailAdded.has(Y.id)){if(this.backgroundDetailAdding.has(Y.id))continue;this.backgroundDetailAdding.add(Y.id),w$($.cardId,g1(Y,Z,J)).then((Q)=>{if(Q)this.backgroundDetailAdded.add(Y.id);else _(`session "${this.sessionName}": background panel add MISS task=${Y.id}`)}).finally(()=>{this.backgroundDetailAdding.delete(Y.id)})}else t($.cardId,f2.panel(Y.id),g1(Y,Z,J));L$($.cardId,e4(this.backgroundTasks))}async resetBackgroundTasks(){if(this.invalidateBackgroundOpen(),this.backgroundTasks.some(($)=>!g0($))){let $=Date.now();this.backgroundTasks=this.backgroundTasks.map((Z)=>g0(Z)?Z:{...Z,status:"killed",endTime:Z.endTime??$})}if(this.pendingBgTasks=[],this.backgroundCard)await this.settleBackgroundCard();if(this.stopBackgroundRefreshTick(),this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;this.backgroundTasks=[],this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear()}async settleBackgroundCard(){if(this.migratingBackgroundCard)try{await this.migratingBackgroundCard}catch(J){_(`session "${this.sessionName}": background migration failed before settle; retry terminal snapshot: ${O(J)}`)}let $=this.backgroundCard;if(!$||this.settlingBackgroundCard)return;this.settlingBackgroundCard=!0;let Z=[...this.backgroundTasks];if(this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;this.stopBackgroundRefreshTick();try{if(await c0($.cardId),await Q$($.messageId,$9(Z)),D0($.cardId),!await P0($.cardId,D$({suffix:"\uD83E\uDDED 后台任务已结束"})))throw Error("background history streaming-off rejected");if(await m0($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((Y)=>!g0(Y)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),_(`session "${this.sessionName}": background card settled cardId=${$.cardId.slice(0,12)} remaining=${this.backgroundTasks.length}`)}finally{if(this.settlingBackgroundCard=!1,this.backgroundCard===$&&J1(this.backgroundTasks))this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(this.backgroundTasks.length>0)this.onBackgroundTaskChanged()}migrateBackgroundCard(){if(this.migratingBackgroundCard)return this.migratingBackgroundCard;let $=this.backgroundCard;if(!$)return Promise.resolve();let Z=this.performBackgroundCardMigration($),J;return J=Z.finally(()=>{if(this.migratingBackgroundCard===J)this.migratingBackgroundCard=null}),this.migratingBackgroundCard=J,J}async performBackgroundCardMigration($){if(this.backgroundCard!==$)return;if(this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;if(this.stopBackgroundRefreshTick(),await c0($.cardId),this.backgroundCard!==$)return;let Z=[...this.backgroundTasks],J=new Set(Z.filter(g0).map((H)=>H.id)),Y=J.size;if(Y>0)await Q$($.messageId,$9(Z));else await Q$($.messageId,o7());if(D0($.cardId),!await P0($.cardId,D$({suffix:"\uD83E\uDDED 已迁移至新卡"})))throw Error("background migration streaming-off rejected");if(await m0($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((H)=>!J.has(H.id)||!g0(H)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),_(`session "${this.sessionName}": background card migrated cardId=${$.cardId.slice(0,12)} terminal=${Y} active=${this.backgroundTasks.length}`)}startScheduledTurnCard($,Z,J,Y){if(this.proc!==$||this.procEpoch!==Z||!$.isAlive())return;if(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.bgResumePending)return;let Q;try{Q=this.beginTurnOpen($,Z,!0)}catch(W){_(`session "${this.sessionName}": scheduled turn-open ownership conflict: ${O(W)}`);return}let H=J.replace(/\s+/g," ").trim();this.lastTurnUserPreview=`⏰ ${H.slice(0,78)}`,_(`session "${this.sessionName}": scheduled wakeup prompt=${Y??"MISS"}`),(async()=>{try{let W=await this.openTurnCard(Q,"","scheduled_wakeup");if(this.proc!==$||this.procEpoch!==Z){if(_(`session "${this.sessionName}": scheduled ${$.provider} turn became stale while opening epoch=${Z}`),W&&this.currentTurn===W)await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);return}if(!W||this.currentTurn!==W){if(!this.ownsTurnOpen(Q))return;if(this.bgResumeCardless=!0,Q.sawResult)Q.sawResult=!1,_(`session "${this.sessionName}": scheduled open failed after result — flushing orphan now`),this.flushOrphanAssistantToChat("scheduled open failed, result already arrived");else _(`session "${this.sessionName}": scheduled open failed — orphan text flush will cover the output`)}else if(Q.sawResult)Q.sawResult=!1,_(`session "${this.sessionName}": scheduled result raced card-open — closing freshly-opened card`),await this.closeTurnCard(Q.terminalSuffix,{forcePush:Q.terminalForcePush,hasFreshResult:!0}),this.status="idle";else this.status="working"}finally{this.releaseTurnOpen(Q)}})().catch((W)=>{_(`session "${this.sessionName}": scheduled turn-open handler failed: ${O(W)}`)})}wireProc($,Z){if(Z===void 0)this.invalidateTurnOpen(),this.invalidateBackgroundOpen();let J=Z??++this.procEpoch;if(Z===void 0&&this.proc!==$)this.proc=$;let Y=()=>this.proc===$&&this.procEpoch===J,Q=!1,H=!1,W=(X,V)=>{$.on(X,(z)=>{if(!Y()){if(!Q)Q=!0,_(`session "${this.sessionName}": ignore stale ${$.provider} event=${String(X)} epoch=${J} currentEpoch=${this.procEpoch}`);return}if(X!=="exit"&&(this.stoppingProc===$||this.blockedProc===$)){if(!H)H=!0,_(`session "${this.sessionName}": ignore ${$.provider} event=${String(X)} while process stop is pending`);return}V(z)})};W("error",(X)=>{_(`session "${this.sessionName}": ${$.provider} process error: ${X}`)}),W("init",()=>{if($.provider==="codex"&&$.launchKind==="fresh")this.clearResumeBindingForFreshCodex($);else this.persistResumableSessionId(!0);if(this.initCount++,_(`session "${this.sessionName}": SDK init#${this.initCount} pendingCount=${this.pendingUserMessageCount} midBuffer=${this.pendingMidTurnMsgs.length} currentTurn=${this.currentTurn?"yes":"no"} openingTurn=${this.openingTurn}`),this.currentTurn||this.openingTurn){if(this.pendingUserMessageCount>0)_(`session "${this.sessionName}": SDK init claimed eager input pendingCount=${this.pendingUserMessageCount}`),this.pendingUserMessageCount=0;return}let X=this.pendingUserMessageCount>0,V=!X&&this.bgResumePending;if(!X&&!V)return;let z=this.lastUserOpenId,G;try{G=this.beginTurnOpen($,J,!0)}catch(L){_(`session "${this.sessionName}": init turn-open ownership conflict: ${O(L)}`);return}if(this.bgResumePending=!1,X)this.pendingUserMessageCount=0,this.currentBatchReactionIds=this.pendingReactionIds,this.pendingReactionIds=new Map;let A=X?[...this.currentBatchReactionIds.keys()]:[],K=()=>{for(let L of A){let D=this.currentBatchReactionIds.get(L);if(this.currentBatchReactionIds.delete(L),D)T0(L,D)}};(async()=>{try{let L=await this.openTurnCard(G,z,X?"user_message":"bg_task_resume");if(!Y()){if(_(`session "${this.sessionName}": ${$.provider} became stale while opening turn card epoch=${J}`),L&&this.currentTurn===L)await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);K();return}if(!L||this.currentTurn!==L){if(!this.ownsTurnOpen(G)){K();return}if(G.sawResult&&G.terminalSuffix)w(this.chatId,G.terminalSuffix);if(X)_(`session "${this.sessionName}": init-path openTurnCard failed — sendInterrupt + release reactions`),this.proc?.sendInterrupt(),K();else if(this.bgResumeCardless=!0,G.sawResult)G.sawResult=!1,_(`session "${this.sessionName}": bg-resume openTurnCard failed, result already arrived — flushing orphan now`),this.flushOrphanAssistantToChat("bg-resume open failed, result already arrived");else _(`session "${this.sessionName}": bg-resume openTurnCard failed — orphan text flush will cover the output`)}else if(G.sawResult)G.sawResult=!1,_(`session "${this.sessionName}": result raced card-open — closing freshly-opened turn card now`),await this.closeTurnCard(G.terminalSuffix,{forcePush:G.terminalForcePush,hasFreshResult:!0}),this.status="idle";else this.status="working"}finally{this.releaseTurnOpen(G)}})().catch((L)=>{_(`session "${this.sessionName}": init turn-open handler failed: ${O(L)}`)})}),W("scheduled_turn_input",({text:X,promptId:V})=>{if($.provider!=="claude"&&$.provider!=="dsh")return;this.startScheduledTurnCard($,J,X,V)}),W("conversation_materialized",({session_id:X,source:V})=>{if($.provider!=="codex")return;if($.sessionId!==X){_(`session "${this.sessionName}": ignore mismatched Codex materialization session=${X} current=${$.sessionId??"MISS"} source=${V}`);return}_(`session "${this.sessionName}": Codex resume point materialized thread=${X} source=${V}`),this.persistResumableSessionId()}),W("conversation_materialization_failed",({session_id:X,source:V,error:z})=>{if($.provider!=="codex"||$.sessionId!==X)return;let G=`Codex 会话落盘确认失败,未写恢复点: ${O(z)}`,A=this.resumePersistenceError!==G;if(this.resumePersistenceError=G,_(`session "${this.sessionName}": ${G} thread=${X} source=${V}`),A)w(this.chatId,`⚠️ ${G}`)}),W("turn_retry",()=>{if(this.currentTurn)this.startThinkingFooter(this.currentTurn)}),W("turn_started",({retry:X})=>{if((this.currentTurn||this.openingTurn)&&this.pendingUserMessageCount>0)_(`session "${this.sessionName}": turn_started claimed eager input pendingCount=${this.pendingUserMessageCount}`),this.pendingUserMessageCount=0;if(this.persistResumableSessionId(),X){if(this.currentTurn)this.startThinkingFooter(this.currentTurn);return}let V=this.proc?.lastTotalUsage;if(this.usageTotalsSeedUnknown&&!V){this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;return}this.currentTurnUsageBaseline=V?{...V}:null,this.currentTurnUsageBaselineKnown=!0}),W("token_usage",({totalUsage:X})=>{if(this.persistResumableSessionId(),X)this.usageTotalsSeedUnknown=!1}),W("turn_plan_updated",(X)=>{this.handleTurnPlanUpdated(X)}),W("plan_delta",(X)=>{this.handlePlanDelta(X)}),W("context_compacted",(X)=>{this.handleContextCompacted(X)}),W("rate_limits_updated",(X)=>{if($.provider==="codex")hQ(X)}),W("thread_goal_updated",(X)=>{this.handleThreadGoalUpdated(X)}),W("thread_goal_cleared",()=>{this.handleThreadGoalCleared()}),W("assistant_text",({text:X,parentToolUseId:V})=>{if(V)return;this.appendAssistant(X)}),W("assistant_block_stop",({parentToolUseId:X})=>{if(X)return;this.finalizeCurrentAssistantSegment(),this.onMainThreadAdvance()}),W("tool_use",({id:X,name:V,input:z,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(i7({active:this.backgroundTasks,pending:this.pendingBgTasks},G,X,V,z)),this.onBackgroundTaskChanged();return}if(TH(this,X,V,z),!G)this.onMainThreadAdvance();if(!G&&(V==="Task"||V==="Agent"))this.lastMainTaskToolUseId=X}),W("tool_result",({tool_use_id:X,content:V,is_error:z,parentToolUseId:G,input:A})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(n7({active:this.backgroundTasks,pending:this.pendingBgTasks},G,X,V,z)),this.onBackgroundTaskChanged();return}EH(this,X,V,z,A)}),W("can_use_tool",(X)=>{xH(this,X)}),W("hook_callback",(X)=>{this.proc?.sendHookResponse(X.request_id,{})}),W("result",(X)=>{let V=this.persistResumableSessionId(),z=V?null:this.consumePendingConversationMaterialization(),G=[V,z].filter(Boolean).join(";")||null;if(this.accumulateResultStats(),this.openingTurnOwner)this.openingTurnOwner.sawResult=!0;if(this.userInterrupted){this.userInterrupted=!1,this.discardOrphanAssistant(),this.bgResumePending=!1;let j=this.proc?.lastResult.subtype??"unknown",k=this.proc?.lastResult.is_error===!0;_(`session "${this.sessionName}": SDK result after user stop subtype=${j} isError=${k} — ignored`),this.status="idle";return}let A=X?.is_error!==!0?this.recordTurnAnchor(X?.checkpoint):null;if(X?.is_error===!0)this.lastTurnUserPreview="";if(!this.currentTurn&&!this.openingTurn)this.flushOrphanAssistantToChat("result with no turn card");let K=this.pendingMidTurnMsgs.length>0,L=this.proc?.lastResult.is_error===!0,D=this.proc?.lastResult.subtype??"success",q=typeof X?.error==="string"&&X.error.trim()?X.error.trim():D,P,x=!1,F=this.proc?this.backendLabel(this.proc.provider):this.backendLabel(),M=[G,A].filter(Boolean).join(";")||null;if(M)P=`⚠️ ${M}`,x=!0;else if(K)P=L?`⚠️ ${F} ${q},用户已介入`:"\uD83D\uDCE8 转交新卡";else if(L)P=`⚠️ ${F} ${q}`,x=!0;if(this.openingTurnOwner)this.openingTurnOwner.terminalSuffix=P,this.openingTurnOwner.terminalForcePush=x;if(M&&!this.currentTurn&&!this.openingTurn)w(this.chatId,`⚠️ ${M}`);if(_(`session "${this.sessionName}": SDK result subtype=${D} isError=${L} midBuffer=${this.pendingMidTurnMsgs.length} forcePush=${x}`),this.closeTurnCard(P,{forcePush:x,hasFreshResult:!0}).catch((j)=>{_(`session "${this.sessionName}": result card close failed: ${O(j)}`)}),this.status="idle",K)this.drainMidTurnAndOpen().catch((j)=>{_(`session "${this.sessionName}": mid-turn drain failed: ${O(j)}`)})}),W("bg_task_started",(X)=>{let V=X.tool_use_id??this.lastMainTaskToolUseId??void 0;_(`session "${this.sessionName}": bg_task_started task=${X.task_id} type=${X.task_type??"-"} subagent=${X.subagent_type??"-"} toolUseId=${V?.slice(0,8)??"-"} desc=${(X.description??"").slice(0,40)}`),this.applyBgStore(c7(this.bgStore(),{...X,tool_use_id:V})),this.onBackgroundTaskChanged()}),W("bg_task_progress",(X)=>{this.applyBgStore(m7(this.bgStore(),X)),this.onBackgroundTaskChanged()}),W("bg_task_updated",(X)=>{this.applyBgStore(u7(this.bgStore(),X)),this.onBackgroundTaskChanged()}),W("bg_task_settled",(X)=>{if(_(`session "${this.sessionName}": bg_task_settled task=${X.task_id} status=${X.status}`),this.applyBgStore(l7(this.bgStore(),X)),this.onBackgroundTaskChanged(),$.provider==="claude"&&!this.currentTurn&&!this.openingTurn&&this.initCount>=1)this.bgResumePending=!0}),W("subagent_step",(X)=>{this.applyBgStore(d7(this.bgStore(),X.thread_id,X.item_id,X.tool,X.phase,X.brief)),this.onBackgroundTaskChanged()}),W("exit",({code:X,signal:V,expected:z})=>{if(_(`session "${this.sessionName}": ${$.provider} exited code=${X} signal=${V} expected=${z}`),this.stoppingProc===$||this.blockedProc===$){if(this.blockedProc===$){let D=$.conversationMaterializationFailure?.(),q=this.persistResumableSessionId(!1,$,!1),P=[D&&$.isConversationResumable?.()!==!0?`Codex 会话落盘确认失败: ${O(D)}`:null,q].filter(Boolean).join(";");if(P)w(this.chatId,`⚠️ 旧进程退出后的恢复状态收尾失败: ${P}`);this.discardPendingCodexTurnAnchors($,"blocked process finally exited")}_(`session "${this.sessionName}": blocked/stopping ${$.provider} exit confirmed`),this.detachProc($),this.status="stopped",this.opts.onLifecycleChange?.();return}this.discardPendingCodexTurnAnchors($,"unexpected process exit"),this.cancelAgentRuns(`${$.provider} process exited`).catch((D)=>{_(`session "${this.sessionName}": cancel Agent runs after process exit failed: ${O(D)}`)});let G=this.backendLabel($.provider),A=`code=${X??"null"}, signal=${V??"null"}`,K=z?`\uD83D\uDED1 ${G} 已退出`:`⚠️ ${G} 异常退出 (${A})`;if(this.currentTurn)this.closeTurnCard(K).catch((D)=>{_(`session "${this.sessionName}": process-exit current main-card close failed: ${O(D)}`)});let L=this.waitForTurnCloses().catch((D)=>{_(`session "${this.sessionName}": process-exit main-card close failed: ${O(D)}`)});this.detachProc($),this.flushOrphanAssistantToChat("process exit"),this.bgResumePending=!1,this.bgResumeCardless=!1,this.clearMultiMsgBuffer("process exit"),this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),this.initCount=0,this.invalidateTurnOpen(),this.pendingAsks.clear(),this.pendingPermissions.clear(),this.userInterrupted=!1,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1,this.usageTotalsSeedUnknown=!1,this.status="stopped",this.opts.onLifecycleChange?.(),this.runLifecycle("process-exit-cleanup",async()=>{let D=await Promise.allSettled([L,this.resetBackgroundTasks()]);for(let q of D)if(q.status==="rejected")_(`session "${this.sessionName}": process-exit terminal cleanup failed: ${O(q.reason)}`);if(!z)await E(this.chatId,`⚠️ ${G} 异常退出 (${A})。回复任意消息将重新启动。`)}).catch((D)=>{_(`session "${this.sessionName}": process-exit cleanup rejected: ${O(D)}`)})})}accumulateResultStats(){let $=this.proc?.lastResult;if(!$)return;let Z=this.currentTurnUsageBaselineKnown?N7(this.proc?.lastTotalUsage,this.currentTurnUsageBaseline):this.proc?.provider==="claude"&&$.usage?{...$.usage}:null;this.lastTurnUsage=Z,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;let J=S7(Z),Y=this.proc?.provider==="claude"?0:$.cost_delta_usd??0,Q=$.duration_ms??0;if(J!=null)this.cumStats.tokens+=J;this.cumStats.costUsd+=Y,this.cumStats.turns+=$.num_turns??1,this.lastTurnDelta={tokens:J,costUsd:Y,durationMs:Q}}currentContextTokens($=this.proc){if($?.provider==="claude"||$?.provider==="dsh")return $.lastContextTokens??null;let Z=$?.lastUsage;return N9(Z)}contextLimitForDisplay($=this.proc){return S9($?.lastContextWindow)}async drainMidTurnAndOpen(){if(this.pendingMidTurnMsgs.length===0)return;let $=this.proc,Z=this.procEpoch;if(!$?.isAlive())return;if(!await this.waitForTurnOpenSlot($,Z))return;if(this.currentTurn||this.openingTurn||this.pendingMidTurnMsgs.length===0)return;let J;try{J=this.beginTurnOpen($,Z)}catch(Q){_(`session "${this.sessionName}": mid-turn open ownership conflict: ${O(Q)}`);return}let Y=this.pendingMidTurnMsgs;this.pendingMidTurnMsgs=[];try{for(let V of Y)if(this.pendingTurnInputs.push(V.text),V.msgId){let z=this.pendingReactionIds.get(V.msgId)??"";this.currentBatchReactionIds.set(V.msgId,z),this.pendingReactionIds.delete(V.msgId)}let Q=Y.map((V)=>V.wireText).join(`
|
|
200
203
|
|
|
201
|
-
`),W=Y[Y.length-1]?.userOpenId??this.lastUserOpenId,X=await this.openTurnCard(J,W,"user_message");if(!X||this.currentTurn!==X){for(let V of Y){if(!V.msgId)continue;let z=this.currentBatchReactionIds.get(V.msgId);if(this.currentBatchReactionIds.delete(V.msgId),z)U0(V.msgId,z)}this.status="idle";return}if(this.proc!==$||this.procEpoch!==Z||!$.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);for(let V of Y){if(!V.msgId)continue;let z=this.currentBatchReactionIds.get(V.msgId);if(this.currentBatchReactionIds.delete(V.msgId),z)U0(V.msgId,z)}this.status="stopped";return}try{this.sendClaimedUserText($,Q)}catch(V){A(`session "${this.sessionName}": mid-turn sendUserText failed after card open: ${V}`),await this.closeTurnCard(`❌ ${this.backendLabel($.provider)} 接收消息失败`),await w(this.chatId,`❌ ${this.backendLabel($.provider)} 接收消息失败: ${U(V)}。这批消息未开始处理,请重发。`),this.status="idle";return}this.status="working"}finally{if(this.releaseTurnOpen(J),!this.currentTurn&&this.pendingMidTurnMsgs.length>0&&this.proc===$&&this.procEpoch===Z&&$.isAlive())this.drainMidTurnAndOpen()}}async terminalizeSupersededCard($,Z,J){let Y=J?await K0($,R.footer,this.footerElement(Z)):!0;q0($);let Q=await L0($,L$({suffix:Z}));if(Y&&Q){await c0($);return}let H=`footer=${Y?"ok":"MISS"}, settings=${Q?"ok":"MISS"}`;A(`session "${this.sessionName}": superseded card terminal transaction incomplete card=${$.slice(0,12)} ${H}`),await w(this.chatId,`⚠️ 已作废卡片未能正常关闭 (${H})。`)}rebuildBackgroundAfterTurnOpenFailure(){if(!this.pendingRebuildBackgroundCard)return;if(this.pendingRebuildBackgroundCard=!1,this.backgroundTasks.length===0)return;this.openBackgroundCard().catch(($)=>{A(`session "${this.sessionName}": background rebuild after turn-open failure failed: ${U($)}`)})}async openTurnCard($,Z,J,Y={}){if(!this.ownsTurnOpen($))return null;if(this.bgResumePending=!1,this.backgroundCard&&e$(this.backgroundTasks))try{await this.migrateBackgroundCard(),this.pendingRebuildBackgroundCard=!0}catch(D){A(`session "${this.sessionName}": background migrate failed (non-blocking): ${D}`),this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(!this.ownsTurnOpen($))return null;let Q=++this.turnCounter,H=this.pendingTurnInputs;this.pendingTurnInputs=[],this.lastTurnUserPreview=H[0]?.slice(0,80)??this.lastTurnUserPreview,A(`session "${this.sessionName}": openTurnCard turn=${Q} trigger=${J} inputs=${H.length}`);let W=this.runtimeModelSelection(),X=this.withModel(Y.initialFooter??"Waiting...(0s)",W),V=S9({sessionName:this.sessionName,turn:Q,provider:W.provider,model:W.model??void 0,effort:W.effort??"MISS",kind:J,userInputs:H,initialFooter:X,directStart:Y.directStart}),z=await d(this.chatId,V);if(!z){if(!this.ownsTurnOpen($))return null;if(A(`session "${this.sessionName}": openTurnCard sendCard EXHAUSTED retries — surfacing via raw text`),J==="user_message")await w(this.chatId,`❌ 创建对话卡片失败 (Feishu SDK 重试 3 次后仍连不上)。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);return this.rebuildBackgroundAfterTurnOpenFailure(),null}let G;try{G=await Q$(z)}catch(D){if(A(`session "${this.sessionName}": id_convert failed: ${D}`),J==="user_message"&&this.ownsTurnOpen($))await w(this.chatId,`❌ 对话卡片初始化失败。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);if(this.ownsTurnOpen($))this.rebuildBackgroundAfterTurnOpenFailure();return null}let _=(J==="bg_task_resume"||J==="scheduled_wakeup"?1:0)+(H.length>0?1:0)+1;if(!this.ownsTurnOpen($))return o0(G,_),await this.terminalizeSupersededCard(G,"⚠️ 会话已切换,本卡已作废",!0),null;let K={cardId:G,...W,messageId:z,userOpenId:Z,trigger:J,toolCount:0,toolByUseId:new Map,planSteps:[],planExplanation:null,planUpdateCount:0,goalUpdateCount:0,contextCompactCount:0,contextCompactionPending:new Map,contextCompactionCompleted:new Set,contextCompactionCompleting:new Set,contextCompactionEndOnly:new Map,lastContextCompactionCompletedAt:0,lastContextCompactionWasAnonymous:!1,toolBatches:new Map,openBatchI:null,taskCreateI:null,taskUpdateI:null,taskBoardResetThisTurn:!1,taskLiveInserted:!1,planLiveInserted:!1,assistantSegmentCount:0,currentAssistantSegmentId:null,currentAssistantText:"",segmentTexts:new Map,startedAt:Date.now(),footerStatusHandle:null,footerStatusStartedAt:0,footerStatusLabel:null,rotating:null,rotateCount:0,failureRotateCount:0,cardCapacityFailures:new Map,cardWriteFailureNotices:new Set,cardRotationFailed:!1,outboundSeenPaths:new Set,outboundSentPaths:new Set};if(o0(G,_,(D,L)=>{this.onCardWriteFailure(K,G,D,L)}),this.currentTurn=K,Y.startThinking!==!1)this.startThinkingFooter(K);if($.pendingCompactions.length>0){let D=$.pendingCompactions.splice(0);A(`session "${this.sessionName}": replay ${D.length} context compaction event(s) buffered during card open`);for(let L of D)this.handleContextCompacted(L)}let q=this.takeOrphanAssistantText();if(q)this.appendAssistant(q),this.finalizeCurrentAssistantSegment();if(this.pendingRebuildBackgroundCard){if(this.pendingRebuildBackgroundCard=!1,this.backgroundTasks.length>0)this.openBackgroundCard().catch((D)=>{A(`session "${this.sessionName}": background rebuild failed: ${U(D)}`)})}return K}maybeMidTurnRotate(){let $=this.currentTurn;if(!$)return;if($.rotating)return;if(!$.cardRotationFailed&&p8($.cardId)<_L)return;this.startMidTurnRotate($)}onCardWriteFailure($,Z,J,Y){let Q=this.currentTurn;if(Q!==$){A(`session "${this.sessionName}": ignore stale card failure card=${Z.slice(0,12)} code=${J??"n/a"} (turn owner changed)`);return}if(Q.cardId!==Z){A(`session "${this.sessionName}": ignore retired-card failure card=${Z.slice(0,12)} current=${Q.cardId.slice(0,12)} code=${J??"n/a"}`);return}if(Q.rotating)return;if(Q.cardRotationFailed)return;if(!u8(J,Y)){let W=Y?.operation??"unknown operation",X=Y?.elementId?` element=${Y.elementId}`:"";A(`session "${this.sessionName}": non-capacity card write failure card=${Z.slice(0,12)} operation=${W}${X} code=${J??"n/a"} — not rotating`);let V=`${Z}:${W}:${Y?.elementId??""}:${J??"MISS"}`;if(!Q.cardWriteFailureNotices.has(V))Q.cardWriteFailureNotices.add(V),w(this.chatId,`⚠️ 对话卡片有一项写入失败(code=${J??"MISS"}, ${W}${X})。未识别为卡片容量超限,未自动换卡;其余输出继续处理。`);return}let H=Y?.capacityFingerprint;if(H){let W=Q.cardCapacityFailures.get(H);if(W!==void 0){if(A(`session "${this.sessionName}": unchanged content still exceeds card capacity card=${Z} operation=${Y.operation} element=${Y.elementId??"MISS"} code=${J??"MISS"}`),!W)Q.cardCapacityFailures.set(H,!0),w(this.chatId,`⚠️ 有一项内容换卡后仍超出飞书容量,写入失败(code=${J??"MISS"}, ${Y.operation}, element=${Y.elementId??"MISS"});其余输出继续处理。`);return}Q.cardCapacityFailures.set(H,!1)}A(`session "${this.sessionName}": confirmed card capacity limit (${J}) on card=${Q.cardId.slice(0,8)}… — rotating to fresh card`),Q.failureRotateCount++,this.startMidTurnRotate(Q)}startMidTurnRotate($){if($.rotating)return;$.rotateCount++;let{cardId:Z,toolByUseId:J,toolBatches:Y}=$,Q={value:null},H=(W,X)=>{if(!Q.value)Q.value={code:W,failure:X}};$.rotating=(async()=>{try{A(`session "${this.sessionName}": mid-turn rotate triggered card=${Z.slice(0,8)}… elementCount=${p8(Z)}`);let W=S9({sessionName:this.sessionName,turn:this.turnCounter,provider:$.provider,model:$.model??void 0,effort:$.effort??"MISS",kind:"card_full",userInputs:[]}),X=await d(this.chatId,W);if(!X){if(A(`session "${this.sessionName}": mid-turn rotate sendCard failed — retry on the next content event`),this.currentTurn===$)$.cardRotationFailed=!0,this.stopFooterStatus($);await w(this.chatId,"⚠️ 续卡发送失败,后续内容到达时会再次尝试。");return}let V;try{V=await Q$(X)}catch(L){if(A(`session "${this.sessionName}": mid-turn rotate id_convert failed: ${L}`),this.currentTurn===$)$.cardRotationFailed=!0,this.stopFooterStatus($),await w(this.chatId,"⚠️ 续卡已发送,但 Card Kit 初始化失败;后续内容到达时会再次尝试。");return}o0(V,2,(L,P)=>{if($.rotating){H(L,P);return}this.onCardWriteFailure($,V,L,P)});let z=$.assistantWriteInflight?.get(Z);if(z?.size)await Promise.allSettled([...z]);this.stopFooterStatus($),$.cardId=V,$.cardRotationFailed=!1,$.messageId=X,$.toolCount=0,$.toolByUseId=new Map,$.toolBatches=new Map,$.openBatchI=null,$.planUpdateCount=0,$.goalUpdateCount=0;let G=$.currentAssistantSegmentId,_=$.currentAssistantText??"",K=$.segmentTexts;if($.assistantSegmentCount=0,$.currentAssistantSegmentId=null,$.currentAssistantText="",$.segmentTexts=new Map,G&&_){let L=R.assistant($.assistantSegmentCount++);$.currentAssistantSegmentId=L,$.currentAssistantText=_,$.segmentTexts.set(L,_)}if(_)this.startWritingFooter($);else this.startThinkingFooter($);if($.taskLiveInserted)_0($.cardId,K1(this.taskBoard),{type:"insert_before",targetElementId:R.footer});if($.planLiveInserted)_0($.cardId,e2($.planSteps,$.planExplanation,R.planLive),{type:"insert_before",targetElementId:$.taskLiveInserted?R.taskBoardLive:R.footer});for(let L of $.contextCompactionPending.values()){if(L.cardId!==Z)continue;L.cardId=V,L.created=!1,L.createFailure=void 0;let P=R.contextCompact(L.i);L.createPromise=M9(V,s2(L.i,L.notice,P),{type:"insert_before",targetElementId:D0($)}).then((N)=>{if(L.cardId===V)L.created=N.landed,L.createFailure=N.failure;return N.landed})}for(let[L,P]of K){if(G&&_&&L===G)continue;if(!d1(Z,L))continue;let N=$.assistantSegmentCount++,F=R.assistant(N);$.segmentTexts.set(F,P),await this.addCompletedAssistantSegment($,F,P)}Q3(this,Z,V,J,Y,$),await g0(Z),Q3(this,Z,V,J,Y,$);let q=new Set([R.taskBoardLive,R.planLive,...[...$.contextCompactionPending.values()].map((L)=>R.contextCompact(L.i))]);if(G)q.add(G);for(let L of J.values())if(L.output==null)q.add(R.tool(L.i));if(TY(Z).some((L)=>!q.has(L)))$.cardCapacityFailures.clear();await g0(V);try{await Y3($,Z);let L=$.mathRenderInflight?.get(Z);if(L?.size)await Promise.allSettled([...L]);await g0(Z);let P=$.mathRendered?.get(Z);for(let[M,C]of K){if(G&&_&&M===G)continue;if(d1(Z,M))continue;if(P?.has(M))continue;await r(Z,M,this.completedAssistantElement(M,C))}let N=$.contextCompactCount>0?` · \uD83D\uDEA8 压缩×${$.contextCompactCount}`:"",F=await K0(Z,R.footer,this.footerElement(this.withModel(`\uD83D\uDCE8 已续至下一张卡 ↓${N}`)),{notifyCardFailure:!1});q0(Z);let j=await L0(Z,L$({suffix:"\uD83D\uDCE8 转下一张"}));if(F&&j)await c0(Z);else A(`session "${this.sessionName}": rotate old-card terminal MISS footer=${F} settings=${j}`),await w(this.chatId,`⚠️ 上一张对话卡未能正常关闭 (footer=${F?"ok":"MISS"}, settings=${j?"ok":"MISS"}),本轮输出已续到新卡。`)}catch(L){A(`session "${this.sessionName}": mid-turn rotate close-old failed: ${L}`)}A(`session "${this.sessionName}": mid-turn rotate done old=${Z.slice(0,8)}… new=${V.slice(0,8)}…`)}finally{$.rotating=null;let W=Q.value;if(W&&this.currentTurn===$)this.onCardWriteFailure($,$.cardId,W.code,W.failure)}})()}addPlanSnapshotOnCurrentTurn(){let $=this.currentTurn;if(!$||$.planSteps.length===0)return;this.maybeMidTurnRotate();let Z=$.cardId,J=R.planUpdate($.planUpdateCount++);_0(Z,o8($.planSteps,$.planExplanation,"",J),{type:"insert_before",targetElementId:D0($)})}addGoalUpdateOnCurrentTurn($){let Z=this.currentTurn;if(!Z)return;this.maybeMidTurnRotate();let J=R.goalUpdate(Z.goalUpdateCount++);_0(Z.cardId,r8($,J),{type:"insert_before",targetElementId:D0(Z)})}addGoalClearedOnCurrentTurn(){let $=this.currentTurn;if(!$)return;this.maybeMidTurnRotate();let Z=R.goalUpdate($.goalUpdateCount++);_0($.cardId,{tag:"markdown",element_id:Z,content:`**\uD83C\uDFAF 当前目标**
|
|
204
|
+
`),W=Y[Y.length-1]?.userOpenId??this.lastUserOpenId,X=await this.openTurnCard(J,W,"user_message");if(!X||this.currentTurn!==X){for(let V of Y){if(!V.msgId)continue;let z=this.currentBatchReactionIds.get(V.msgId);if(this.currentBatchReactionIds.delete(V.msgId),z)T0(V.msgId,z)}this.status="idle";return}if(this.proc!==$||this.procEpoch!==Z||!$.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);for(let V of Y){if(!V.msgId)continue;let z=this.currentBatchReactionIds.get(V.msgId);if(this.currentBatchReactionIds.delete(V.msgId),z)T0(V.msgId,z)}this.status="stopped";return}try{this.sendClaimedUserText($,Q)}catch(V){_(`session "${this.sessionName}": mid-turn sendUserText failed after card open: ${V}`),await this.closeTurnCard(`❌ ${this.backendLabel($.provider)} 接收消息失败`),await w(this.chatId,`❌ ${this.backendLabel($.provider)} 接收消息失败: ${O(V)}。这批消息未开始处理,请重发。`),this.status="idle";return}this.status="working"}finally{if(this.releaseTurnOpen(J),!this.currentTurn&&this.pendingMidTurnMsgs.length>0&&this.proc===$&&this.procEpoch===Z&&$.isAlive())this.drainMidTurnAndOpen()}}async terminalizeSupersededCard($,Z,J){let Y=J?await L0($,R.footer,this.footerElement(Z)):!0;D0($);let Q=await P0($,D$({suffix:Z}));if(Y&&Q){await m0($);return}let H=`footer=${Y?"ok":"MISS"}, settings=${Q?"ok":"MISS"}`;_(`session "${this.sessionName}": superseded card terminal transaction incomplete card=${$.slice(0,12)} ${H}`),await w(this.chatId,`⚠️ 已作废卡片未能正常关闭 (${H})。`)}rebuildBackgroundAfterTurnOpenFailure(){if(!this.pendingRebuildBackgroundCard)return;if(this.pendingRebuildBackgroundCard=!1,this.backgroundTasks.length===0)return;this.openBackgroundCard().catch(($)=>{_(`session "${this.sessionName}": background rebuild after turn-open failure failed: ${O($)}`)})}async openTurnCard($,Z,J,Y={}){if(!this.ownsTurnOpen($))return null;if(this.bgResumePending=!1,this.backgroundCard&&J1(this.backgroundTasks))try{await this.migrateBackgroundCard(),this.pendingRebuildBackgroundCard=!0}catch(D){_(`session "${this.sessionName}": background migrate failed (non-blocking): ${D}`),this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(!this.ownsTurnOpen($))return null;let Q=++this.turnCounter,H=this.pendingTurnInputs;this.pendingTurnInputs=[],this.lastTurnUserPreview=H[0]?.slice(0,80)??this.lastTurnUserPreview,_(`session "${this.sessionName}": openTurnCard turn=${Q} trigger=${J} inputs=${H.length}`);let W=this.runtimeModelSelection(),X=this.withModel(Y.initialFooter??"Waiting...(0s)",W),V=b9({sessionName:this.sessionName,turn:Q,provider:W.provider,model:W.model??void 0,effort:W.effort??"MISS",kind:J,userInputs:H,initialFooter:X,directStart:Y.directStart}),z=await a(this.chatId,V);if(!z){if(!this.ownsTurnOpen($))return null;if(_(`session "${this.sessionName}": openTurnCard sendCard EXHAUSTED retries — surfacing via raw text`),J==="user_message")await w(this.chatId,`❌ 创建对话卡片失败 (Feishu SDK 重试 3 次后仍连不上)。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);return this.rebuildBackgroundAfterTurnOpenFailure(),null}let G;try{G=await H$(z)}catch(D){if(_(`session "${this.sessionName}": id_convert failed: ${D}`),J==="user_message"&&this.ownsTurnOpen($))await w(this.chatId,`❌ 对话卡片初始化失败。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);if(this.ownsTurnOpen($))this.rebuildBackgroundAfterTurnOpenFailure();return null}let A=(J==="bg_task_resume"||J==="scheduled_wakeup"?1:0)+(H.length>0?1:0)+1;if(!this.ownsTurnOpen($))return r0(G,A),await this.terminalizeSupersededCard(G,"⚠️ 会话已切换,本卡已作废",!0),null;let K={cardId:G,...W,messageId:z,userOpenId:Z,trigger:J,toolCount:0,toolByUseId:new Map,planSteps:[],planExplanation:null,planUpdateCount:0,goalUpdateCount:0,contextCompactCount:0,contextCompactionPending:new Map,contextCompactionCompleted:new Set,contextCompactionCompleting:new Set,contextCompactionEndOnly:new Map,lastContextCompactionCompletedAt:0,lastContextCompactionWasAnonymous:!1,toolBatches:new Map,openBatchI:null,taskCreateI:null,taskUpdateI:null,taskBoardResetThisTurn:!1,taskLiveInserted:!1,planLiveInserted:!1,assistantSegmentCount:0,currentAssistantSegmentId:null,currentAssistantText:"",segmentTexts:new Map,startedAt:Date.now(),footerStatusHandle:null,footerStatusStartedAt:0,footerStatusLabel:null,rotating:null,rotateCount:0,failureRotateCount:0,cardCapacityFailures:new Map,cardWriteFailureNotices:new Set,cardRotationFailed:!1,outboundSeenPaths:new Set,outboundSentPaths:new Set};if(r0(G,A,(D,q)=>{this.onCardWriteFailure(K,G,D,q)}),this.currentTurn=K,Y.startThinking!==!1)this.startThinkingFooter(K);if($.pendingCompactions.length>0){let D=$.pendingCompactions.splice(0);_(`session "${this.sessionName}": replay ${D.length} context compaction event(s) buffered during card open`);for(let q of D)this.handleContextCompacted(q)}let L=this.takeOrphanAssistantText();if(L)this.appendAssistant(L),this.finalizeCurrentAssistantSegment();if(this.pendingRebuildBackgroundCard){if(this.pendingRebuildBackgroundCard=!1,this.backgroundTasks.length>0)this.openBackgroundCard().catch((D)=>{_(`session "${this.sessionName}": background rebuild failed: ${O(D)}`)})}return K}maybeMidTurnRotate(){let $=this.currentTurn;if(!$)return;if($.rotating)return;if(!$.cardRotationFailed&&d8($.cardId)<Lq)return;this.startMidTurnRotate($)}onCardWriteFailure($,Z,J,Y){let Q=this.currentTurn;if(Q!==$){_(`session "${this.sessionName}": ignore stale card failure card=${Z.slice(0,12)} code=${J??"n/a"} (turn owner changed)`);return}if(Q.cardId!==Z){_(`session "${this.sessionName}": ignore retired-card failure card=${Z.slice(0,12)} current=${Q.cardId.slice(0,12)} code=${J??"n/a"}`);return}if(Q.rotating)return;if(Q.cardRotationFailed)return;if(!i8(J,Y)){let W=Y?.operation??"unknown operation",X=Y?.elementId?` element=${Y.elementId}`:"";_(`session "${this.sessionName}": non-capacity card write failure card=${Z.slice(0,12)} operation=${W}${X} code=${J??"n/a"} — not rotating`);let V=`${Z}:${W}:${Y?.elementId??""}:${J??"MISS"}`;if(!Q.cardWriteFailureNotices.has(V))Q.cardWriteFailureNotices.add(V),w(this.chatId,`⚠️ 对话卡片有一项写入失败(code=${J??"MISS"}, ${W}${X})。未识别为卡片容量超限,未自动换卡;其余输出继续处理。`);return}let H=Y?.capacityFingerprint;if(H){let W=Q.cardCapacityFailures.get(H);if(W!==void 0){if(_(`session "${this.sessionName}": unchanged content still exceeds card capacity card=${Z} operation=${Y.operation} element=${Y.elementId??"MISS"} code=${J??"MISS"}`),!W)Q.cardCapacityFailures.set(H,!0),w(this.chatId,`⚠️ 有一项内容换卡后仍超出飞书容量,写入失败(code=${J??"MISS"}, ${Y.operation}, element=${Y.elementId??"MISS"});其余输出继续处理。`);return}Q.cardCapacityFailures.set(H,!1)}_(`session "${this.sessionName}": confirmed card capacity limit (${J}) on card=${Q.cardId.slice(0,8)}… — rotating to fresh card`),Q.failureRotateCount++,this.startMidTurnRotate(Q)}startMidTurnRotate($){if($.rotating)return;$.rotateCount++;let{cardId:Z,toolByUseId:J,toolBatches:Y}=$,Q={value:null},H=(W,X)=>{if(!Q.value)Q.value={code:W,failure:X}};$.rotating=(async()=>{try{_(`session "${this.sessionName}": mid-turn rotate triggered card=${Z.slice(0,8)}… elementCount=${d8(Z)}`);let W=b9({sessionName:this.sessionName,turn:this.turnCounter,provider:$.provider,model:$.model??void 0,effort:$.effort??"MISS",kind:"card_full",userInputs:[]}),X=await a(this.chatId,W);if(!X){if(_(`session "${this.sessionName}": mid-turn rotate sendCard failed — retry on the next content event`),this.currentTurn===$)$.cardRotationFailed=!0,this.stopFooterStatus($);await w(this.chatId,"⚠️ 续卡发送失败,后续内容到达时会再次尝试。");return}let V;try{V=await H$(X)}catch(q){if(_(`session "${this.sessionName}": mid-turn rotate id_convert failed: ${q}`),this.currentTurn===$)$.cardRotationFailed=!0,this.stopFooterStatus($),await w(this.chatId,"⚠️ 续卡已发送,但 Card Kit 初始化失败;后续内容到达时会再次尝试。");return}r0(V,2,(q,P)=>{if($.rotating){H(q,P);return}this.onCardWriteFailure($,V,q,P)});let z=$.assistantWriteInflight?.get(Z);if(z?.size)await Promise.allSettled([...z]);this.stopFooterStatus($),$.cardId=V,$.cardRotationFailed=!1,$.messageId=X,$.toolCount=0,$.toolByUseId=new Map,$.toolBatches=new Map,$.openBatchI=null,$.planUpdateCount=0,$.goalUpdateCount=0;let G=$.currentAssistantSegmentId,A=$.currentAssistantText??"",K=$.segmentTexts;if($.assistantSegmentCount=0,$.currentAssistantSegmentId=null,$.currentAssistantText="",$.segmentTexts=new Map,G&&A){let q=R.assistant($.assistantSegmentCount++);$.currentAssistantSegmentId=q,$.currentAssistantText=A,$.segmentTexts.set(q,A)}if(A)this.startWritingFooter($);else this.startThinkingFooter($);if($.taskLiveInserted)B0($.cardId,q1(this.taskBoard),{type:"insert_before",targetElementId:R.footer});if($.planLiveInserted)B0($.cardId,J4($.planSteps,$.planExplanation,R.planLive),{type:"insert_before",targetElementId:$.taskLiveInserted?R.taskBoardLive:R.footer});for(let q of $.contextCompactionPending.values()){if(q.cardId!==Z)continue;q.cardId=V,q.created=!1,q.createFailure=void 0;let P=R.contextCompact(q.i);q.createPromise=T9(V,Z4(q.i,q.notice,P),{type:"insert_before",targetElementId:j0($)}).then((x)=>{if(q.cardId===V)q.created=x.landed,q.createFailure=x.failure;return x.landed})}for(let[q,P]of K){if(G&&A&&q===G)continue;if(!r1(Z,q))continue;let x=$.assistantSegmentCount++,F=R.assistant(x);$.segmentTexts.set(F,P),await this.addCompletedAssistantSegment($,F,P)}X3(this,Z,V,J,Y,$),await c0(Z),X3(this,Z,V,J,Y,$);let L=new Set([R.taskBoardLive,R.planLive,...[...$.contextCompactionPending.values()].map((q)=>R.contextCompact(q.i))]);if(G)L.add(G);for(let q of J.values())if(q.output==null)L.add(R.tool(q.i));if(OY(Z).some((q)=>!L.has(q)))$.cardCapacityFailures.clear();await c0(V);try{await W3($,Z);let q=$.mathRenderInflight?.get(Z);if(q?.size)await Promise.allSettled([...q]);await c0(Z);let P=$.mathRendered?.get(Z);for(let[j,k]of K){if(G&&A&&j===G)continue;if(r1(Z,j))continue;if(P?.has(j))continue;await t(Z,j,this.completedAssistantElement(j,k))}let x=$.contextCompactCount>0?` · \uD83D\uDEA8 压缩×${$.contextCompactCount}`:"",F=await L0(Z,R.footer,this.footerElement(this.withModel(`\uD83D\uDCE8 已续至下一张卡 ↓${x}`)),{notifyCardFailure:!1});D0(Z);let M=await P0(Z,D$({suffix:"\uD83D\uDCE8 转下一张"}));if(F&&M)await m0(Z);else _(`session "${this.sessionName}": rotate old-card terminal MISS footer=${F} settings=${M}`),await w(this.chatId,`⚠️ 上一张对话卡未能正常关闭 (footer=${F?"ok":"MISS"}, settings=${M?"ok":"MISS"}),本轮输出已续到新卡。`)}catch(q){_(`session "${this.sessionName}": mid-turn rotate close-old failed: ${q}`)}_(`session "${this.sessionName}": mid-turn rotate done old=${Z.slice(0,8)}… new=${V.slice(0,8)}…`)}finally{$.rotating=null;let W=Q.value;if(W&&this.currentTurn===$)this.onCardWriteFailure($,$.cardId,W.code,W.failure)}})()}addPlanSnapshotOnCurrentTurn(){let $=this.currentTurn;if(!$||$.planSteps.length===0)return;this.maybeMidTurnRotate();let Z=$.cardId,J=R.planUpdate($.planUpdateCount++);B0(Z,s8($.planSteps,$.planExplanation,"",J),{type:"insert_before",targetElementId:j0($)})}addGoalUpdateOnCurrentTurn($){let Z=this.currentTurn;if(!Z)return;this.maybeMidTurnRotate();let J=R.goalUpdate(Z.goalUpdateCount++);B0(Z.cardId,e8($,J),{type:"insert_before",targetElementId:j0(Z)})}addGoalClearedOnCurrentTurn(){let $=this.currentTurn;if(!$)return;this.maybeMidTurnRotate();let Z=R.goalUpdate($.goalUpdateCount++);B0($.cardId,{tag:"markdown",element_id:Z,content:`**\uD83C\uDFAF 当前目标**
|
|
202
205
|
|
|
203
|
-
已清除`},{type:"insert_before",targetElementId:D0($)})}handleContextCompacted($){let Z=DX($);if(this.manualContextCompactionPending){if(Z.length>0)this.rememberContextCompactionReceipt(Z,null,$.phase!=="start");if($.phase!=="start")this.lastManualContextCompactionCompletedAt=Date.now(),this.lastManualContextCompactionWasAnonymous=Z.length===0;A(`session "${this.sessionName}": manual context compaction ${$.phase??"event"} handled by command status card`);return}if($.phase==="start")this.lastManualContextCompactionWasAnonymous=!1;else if((Z.length===0||this.lastManualContextCompactionWasAnonymous)&&Date.now()-this.lastManualContextCompactionCompletedAt<C6){A(`session "${this.sessionName}": late anonymous manual compaction duplicate ignored`);return}let J=this.currentTurn,Y=$.itemId?`item:${$.itemId}`:void 0,Q=Z.find((F)=>F.startsWith("turn:")),H=Y??Q,W=H?this.contextCompactionReceipts.get(H):void 0;if(Y&&!W&&$.phase!=="start"&&Q){let F=this.contextCompactionReceipts.get(Q);if(!F?.hasItemAlias&&F?.completed&&Date.now()-F.completedAt<C6||!F?.hasItemAlias&&F?.completionKey&&J?.contextCompactionCompleting.has(F.completionKey))H=Q,W=F,F.hasItemAlias=!0,this.contextCompactionReceipts.delete(Y),this.contextCompactionReceipts.set(Y,F)}if(!J){if(this.openingTurnOwner?.backendTurnStarted){this.openingTurnOwner.pendingCompactions.push($),A(`session "${this.sessionName}": buffer context compaction ${$.phase??"event"} while turn card opens`);return}if(Z.length>0)this.rememberContextCompactionReceipt(Z,null,$.phase!=="start");A(`session "${this.sessionName}": context compaction ${$.phase??"event"} with no current turn thread=${$.threadId??"-"} turn=${$.turnId??"-"} item=${$.itemId??"-"}`);return}if(H&&W?.completed){A(`session "${this.sessionName}": duplicate context compaction ${$.phase??"event"} ignored receipt=${H}`);return}let X=this.contextCompactionOwnerId(J);if(H&&W&&W.ownerId!==X){this.rememberContextCompactionReceipt(Z,null,!0),A(`session "${this.sessionName}": late context compaction ${$.phase??"event"} ignored receipt=${H} (turn owner changed)`);return}if(H&&W?.completionKey&&J.contextCompactionCompleting.has(W.completionKey)){A(`session "${this.sessionName}": context compaction alias already writing receipt=${H}`);return}if($.phase!=="start"&&Z.length>0&&J.contextCompactionPending.size===0&&J.contextCompactionCompleting.has("__anonymous__")){A(`session "${this.sessionName}": identified context compaction duplicate ignored while anonymous completion writes`);return}if($.phase!=="start"&&Z.length>0&&J.contextCompactionPending.size===0&&J.lastContextCompactionWasAnonymous&&Date.now()-J.lastContextCompactionCompletedAt<C6){A(`session "${this.sessionName}": identified context compaction duplicate ignored after anonymous completion`);return}if($.phase==="start"){let F=XL($);if(J.contextCompactionPending.has(F)||J.contextCompactionCompleted.has(F)){A(`session "${this.sessionName}": duplicate context compaction start ignored key=${F}`);return}if(this.startWorkingFooter(J),J.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();if(J.openBatchI=null,this.maybeMidTurnRotate(),J.lastContextCompactionWasAnonymous=!1,Z.length>0)this.rememberContextCompactionReceipt(Z,X,!1);let j=J.contextCompactCount++,M=J.cardId,C=R.contextCompact(j),b={i:j,cardId:M,notice:$,created:!1,createFailure:void 0,createPromise:Promise.resolve(!1)};b.createPromise=M9(M,s2(j,$,C),{type:"insert_before",targetElementId:D0(J)}).then((m)=>{if(b.cardId===M)b.created=m.landed,b.createFailure=m.failure;return m.landed}),J.contextCompactionPending.set(F,b),A(`session "${this.sessionName}": context compaction start #${j+1} key=${F}`),B$(J.cardId,`\uD83D\uDEA8 压缩×${J.contextCompactCount}`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionCompleting.size>0){A(`session "${this.sessionName}": anonymous context compaction duplicate ignored while completion writes`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionPending.size===0&&Date.now()-J.lastContextCompactionCompletedAt<C6){A(`session "${this.sessionName}": immediate anonymous context compaction duplicate ignored`);return}let V=$.itemId||$.turnId;if(V&&J.contextCompactionCompleted.has(V)){A(`session "${this.sessionName}": duplicate context compaction completion ignored key=${V}`);return}let z=$.itemId?J.contextCompactionPending.has($.itemId)?$.itemId:null:VL(J),G=z?J.contextCompactionPending.get(z):void 0,_=z??V??"__anonymous__";if(J.contextCompactionCompleting.has(_)){A(`session "${this.sessionName}": context compaction completion already writing key=${_}`);return}if(this.startWorkingFooter(J),J.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();J.openBatchI=null,this.maybeMidTurnRotate();let K=zL(G?.notice,$),q=J.contextCompactionEndOnly.get(_),D=G?.i??q??J.contextCompactCount++;if(!G&&q===void 0)J.contextCompactionEndOnly.set(_,D);J.contextCompactionCompleting.add(_);let L=[...new Set([...DX(G?.notice??{}),...Z])];if(L.length>0)this.rememberContextCompactionReceipt(L,X,!1,_);let P=R.contextCompact(D),N=s2(D,K,P);A(`session "${this.sessionName}": context compaction completion write #${D+1} key=${_}`),(async()=>{let F=!1;if(!G)while(!0){let j=J.cardId;if(F=await b$(j,N,{type:"insert_before",targetElementId:D0(J)}),F)break;let M=J.rotating;if(M){await M;continue}if(J.cardId!==j)continue;break}else while(!0){let j=G.cardId;if(await G.createPromise,G.cardId!==j)continue;if(G.created)F=await K0(j,P,N);else{if(OY(G.createFailure?.code,G.createFailure))EY(j,P),F=await K0(j,P,N,{notifyCardFailure:!1});if(!F)F=await b$(j,N,{type:"insert_before",targetElementId:D0(J)})}if(G.cardId!==j)continue;if(F){G.created=!0;break}let M=J.rotating;if(M){await M;continue}if(G.cardId!==j)continue;break}if(J.contextCompactionCompleting.delete(_),!F){A(`session "${this.sessionName}": context compaction completion write MISS #${D+1} key=${_}`);return}if(z&&J.contextCompactionPending.get(z)===G)J.contextCompactionPending.delete(z);if(J.contextCompactionEndOnly.delete(_),_!=="__anonymous__")J.contextCompactionCompleted.add(_);if(J.lastContextCompactionCompletedAt=Date.now(),J.lastContextCompactionWasAnonymous=_==="__anonymous__",L.length>0){let j=[...this.contextCompactionReceipts.entries()].filter(([,M])=>M.completionKey===_).map(([M])=>M);this.rememberContextCompactionReceipt([...new Set([...L,...j])],null,!0)}A(`session "${this.sessionName}": context compaction completed #${D+1} key=${_}`)})().catch((F)=>{J.contextCompactionCompleting.delete(_),A(`session "${this.sessionName}": context compaction completion transaction failed: ${U(F)}`)}),B$(J.cardId,`\uD83D\uDEA8 压缩×${J.contextCompactCount}`)}contextCompactionOwnerId($){let Z=this.contextCompactionOwnerIds.get($);if(Z!==void 0)return Z;let J=++this.contextCompactionOwnerSequence;return this.contextCompactionOwnerIds.set($,J),J}rememberContextCompactionReceipt($,Z,J,Y){let Q={ownerId:J?null:Z,completed:J,completedAt:J?Date.now():0,...J||!Y?{}:{completionKey:Y},hasItemAlias:$.some((H)=>H.startsWith("item:"))};for(let H of $)this.contextCompactionReceipts.delete(H),this.contextCompactionReceipts.set(H,Q);while(this.contextCompactionReceipts.size>KL){let H;for(let W of this.contextCompactionReceipts.values()){if(W.completed){H=W;break}H??=W}if(!H)break;for(let[W,X]of this.contextCompactionReceipts)if(X===H)this.contextCompactionReceipts.delete(W)}}handleTurnPlanUpdated($){let Z=this.currentTurn;if(!Z){A(`session "${this.sessionName}": turn/plan/updated with no current turn`);return}if(this.startWorkingFooter(Z),Z.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();if(Z.openBatchI=null,!Array.isArray($.plan))A(`session "${this.sessionName}": turn/plan/updated missing plan array`),Z.planSteps=[];else Z.planSteps=$.plan.map((J)=>({step:typeof J.step==="string"&&J.step?J.step:"MISS",status:typeof J.status==="string"&&J.status?J.status:"MISS"}));if(Z.planExplanation=typeof $.explanation==="string"?$.explanation:null,Z.planSteps.length>0)if(!Z.planLiveInserted){let J=Z.taskLiveInserted?R.taskBoardLive:R.footer;Z.planLiveInserted=!0,_0(Z.cardId,e2(Z.planSteps,Z.planExplanation,R.planLive),{type:"insert_before",targetElementId:J})}else r(Z.cardId,R.planLive,e2(Z.planSteps,Z.planExplanation,R.planLive));this.addPlanSnapshotOnCurrentTurn()}handlePlanDelta($){if(typeof $.delta!=="string"||!$.delta){A(`session "${this.sessionName}": item/plan/delta missing delta text`);return}if(typeof $.itemId!=="string"||!$.itemId)A(`session "${this.sessionName}": item/plan/delta missing itemId`)}handleThreadGoalUpdated($){if(!$||typeof $.objective!=="string"){A(`session "${this.sessionName}": thread/goal/updated missing objective`);return}if($.tokenBudget!=null&&typeof $.tokenBudget!=="number")A(`session "${this.sessionName}": thread/goal/updated invalid tokenBudget`);let Z=this.currentGoal,J={objective:$.objective,status:typeof $.status==="string"&&$.status?$.status:"MISS",tokenBudget:typeof $.tokenBudget==="number"?$.tokenBudget:$.tokenBudget===null?null:Number.NaN,tokensUsed:typeof $.tokensUsed==="number"?$.tokensUsed:Number.NaN,timeUsedSeconds:typeof $.timeUsedSeconds==="number"?$.timeUsedSeconds:Number.NaN};if(this.currentGoal=J,Z&&N9(Z)===N9(J))return;let Y=this.currentTurn;if(Y){if(this.startWorkingFooter(Y),Y.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();Y.openBatchI=null}this.addGoalUpdateOnCurrentTurn(J)}handleThreadGoalCleared(){if(!this.currentGoal)return;this.currentGoal=null;let $=this.currentTurn;if(!$)return;if(this.startWorkingFooter($),$.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();$.openBatchI=null,this.addGoalClearedOnCurrentTurn()}appendAssistant($){if(!this.currentTurn){if(this.openingTurn||this.bgResumeCardless)this.orphanAssistantCurrent+=$;return}let Z=this.currentTurn;if(this.startWritingFooter(Z),!Z.currentAssistantSegmentId){Z.openBatchI=null,this.maybeMidTurnRotate();let H=Z.assistantSegmentCount++,W=R.assistant(H);Z.currentAssistantSegmentId=W,Z.currentAssistantText=""}Z.currentAssistantText+=$;let J=Z.currentAssistantSegmentId;if(!J)return;Z.segmentTexts.set(J,Z.currentAssistantText),this.processOutboundMarkers(Z.currentAssistantText);let Q=this.cleanAssistantTextForDisplay(Z.currentAssistantText).slice(0,40);B$(Z.cardId,Q)}takeOrphanAssistantText(){let $=[...this.orphanAssistantSegments];if(this.orphanAssistantCurrent.trim())$.push(this.orphanAssistantCurrent);return this.orphanAssistantSegments=[],this.orphanAssistantCurrent="",$.join(`
|
|
206
|
+
已清除`},{type:"insert_before",targetElementId:j0($)})}handleContextCompacted($){let Z=qX($);if(this.manualContextCompactionPending){if(Z.length>0)this.rememberContextCompactionReceipt(Z,null,$.phase!=="start");if($.phase!=="start")this.lastManualContextCompactionCompletedAt=Date.now(),this.lastManualContextCompactionWasAnonymous=Z.length===0;_(`session "${this.sessionName}": manual context compaction ${$.phase??"event"} handled by command status card`);return}if($.phase==="start")this.lastManualContextCompactionWasAnonymous=!1;else if((Z.length===0||this.lastManualContextCompactionWasAnonymous)&&Date.now()-this.lastManualContextCompactionCompletedAt<f6){_(`session "${this.sessionName}": late anonymous manual compaction duplicate ignored`);return}let J=this.currentTurn,Y=$.itemId?`item:${$.itemId}`:void 0,Q=Z.find((F)=>F.startsWith("turn:")),H=Y??Q,W=H?this.contextCompactionReceipts.get(H):void 0;if(Y&&!W&&$.phase!=="start"&&Q){let F=this.contextCompactionReceipts.get(Q);if(!F?.hasItemAlias&&F?.completed&&Date.now()-F.completedAt<f6||!F?.hasItemAlias&&F?.completionKey&&J?.contextCompactionCompleting.has(F.completionKey))H=Q,W=F,F.hasItemAlias=!0,this.contextCompactionReceipts.delete(Y),this.contextCompactionReceipts.set(Y,F)}if(!J){if(this.openingTurnOwner?.backendTurnStarted){this.openingTurnOwner.pendingCompactions.push($),_(`session "${this.sessionName}": buffer context compaction ${$.phase??"event"} while turn card opens`);return}if(Z.length>0)this.rememberContextCompactionReceipt(Z,null,$.phase!=="start");_(`session "${this.sessionName}": context compaction ${$.phase??"event"} with no current turn thread=${$.threadId??"-"} turn=${$.turnId??"-"} item=${$.itemId??"-"}`);return}if(H&&W?.completed){_(`session "${this.sessionName}": duplicate context compaction ${$.phase??"event"} ignored receipt=${H}`);return}let X=this.contextCompactionOwnerId(J);if(H&&W&&W.ownerId!==X){this.rememberContextCompactionReceipt(Z,null,!0),_(`session "${this.sessionName}": late context compaction ${$.phase??"event"} ignored receipt=${H} (turn owner changed)`);return}if(H&&W?.completionKey&&J.contextCompactionCompleting.has(W.completionKey)){_(`session "${this.sessionName}": context compaction alias already writing receipt=${H}`);return}if($.phase!=="start"&&Z.length>0&&J.contextCompactionPending.size===0&&J.contextCompactionCompleting.has("__anonymous__")){_(`session "${this.sessionName}": identified context compaction duplicate ignored while anonymous completion writes`);return}if($.phase!=="start"&&Z.length>0&&J.contextCompactionPending.size===0&&J.lastContextCompactionWasAnonymous&&Date.now()-J.lastContextCompactionCompletedAt<f6){_(`session "${this.sessionName}": identified context compaction duplicate ignored after anonymous completion`);return}if($.phase==="start"){let F=Gq($);if(J.contextCompactionPending.has(F)||J.contextCompactionCompleted.has(F)){_(`session "${this.sessionName}": duplicate context compaction start ignored key=${F}`);return}if(this.startWorkingFooter(J),J.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();if(J.openBatchI=null,this.maybeMidTurnRotate(),J.lastContextCompactionWasAnonymous=!1,Z.length>0)this.rememberContextCompactionReceipt(Z,X,!1);let M=J.contextCompactCount++,j=J.cardId,k=R.contextCompact(M),C={i:M,cardId:j,notice:$,created:!1,createFailure:void 0,createPromise:Promise.resolve(!1)};C.createPromise=T9(j,Z4(M,$,k),{type:"insert_before",targetElementId:j0(J)}).then((c)=>{if(C.cardId===j)C.created=c.landed,C.createFailure=c.failure;return c.landed}),J.contextCompactionPending.set(F,C),_(`session "${this.sessionName}": context compaction start #${M+1} key=${F}`),L$(J.cardId,`\uD83D\uDEA8 压缩×${J.contextCompactCount}`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionCompleting.size>0){_(`session "${this.sessionName}": anonymous context compaction duplicate ignored while completion writes`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionPending.size===0&&Date.now()-J.lastContextCompactionCompletedAt<f6){_(`session "${this.sessionName}": immediate anonymous context compaction duplicate ignored`);return}let V=$.itemId||$.turnId;if(V&&J.contextCompactionCompleted.has(V)){_(`session "${this.sessionName}": duplicate context compaction completion ignored key=${V}`);return}let z=$.itemId?J.contextCompactionPending.has($.itemId)?$.itemId:null:_q(J),G=z?J.contextCompactionPending.get(z):void 0,A=z??V??"__anonymous__";if(J.contextCompactionCompleting.has(A)){_(`session "${this.sessionName}": context compaction completion already writing key=${A}`);return}if(this.startWorkingFooter(J),J.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();J.openBatchI=null,this.maybeMidTurnRotate();let K=Aq(G?.notice,$),L=J.contextCompactionEndOnly.get(A),D=G?.i??L??J.contextCompactCount++;if(!G&&L===void 0)J.contextCompactionEndOnly.set(A,D);J.contextCompactionCompleting.add(A);let q=[...new Set([...qX(G?.notice??{}),...Z])];if(q.length>0)this.rememberContextCompactionReceipt(q,X,!1,A);let P=R.contextCompact(D),x=Z4(D,K,P);_(`session "${this.sessionName}": context compaction completion write #${D+1} key=${A}`),(async()=>{let F=!1;if(!G)while(!0){let M=J.cardId;if(F=await w$(M,x,{type:"insert_before",targetElementId:j0(J)}),F)break;let j=J.rotating;if(j){await j;continue}if(J.cardId!==M)continue;break}else while(!0){let M=G.cardId;if(await G.createPromise,G.cardId!==M)continue;if(G.created)F=await L0(M,P,x);else{if(UY(G.createFailure?.code,G.createFailure))TY(M,P),F=await L0(M,P,x,{notifyCardFailure:!1});if(!F)F=await w$(M,x,{type:"insert_before",targetElementId:j0(J)})}if(G.cardId!==M)continue;if(F){G.created=!0;break}let j=J.rotating;if(j){await j;continue}if(G.cardId!==M)continue;break}if(J.contextCompactionCompleting.delete(A),!F){_(`session "${this.sessionName}": context compaction completion write MISS #${D+1} key=${A}`);return}if(z&&J.contextCompactionPending.get(z)===G)J.contextCompactionPending.delete(z);if(J.contextCompactionEndOnly.delete(A),A!=="__anonymous__")J.contextCompactionCompleted.add(A);if(J.lastContextCompactionCompletedAt=Date.now(),J.lastContextCompactionWasAnonymous=A==="__anonymous__",q.length>0){let M=[...this.contextCompactionReceipts.entries()].filter(([,j])=>j.completionKey===A).map(([j])=>j);this.rememberContextCompactionReceipt([...new Set([...q,...M])],null,!0)}_(`session "${this.sessionName}": context compaction completed #${D+1} key=${A}`)})().catch((F)=>{J.contextCompactionCompleting.delete(A),_(`session "${this.sessionName}": context compaction completion transaction failed: ${O(F)}`)}),L$(J.cardId,`\uD83D\uDEA8 压缩×${J.contextCompactCount}`)}contextCompactionOwnerId($){let Z=this.contextCompactionOwnerIds.get($);if(Z!==void 0)return Z;let J=++this.contextCompactionOwnerSequence;return this.contextCompactionOwnerIds.set($,J),J}rememberContextCompactionReceipt($,Z,J,Y){let Q={ownerId:J?null:Z,completed:J,completedAt:J?Date.now():0,...J||!Y?{}:{completionKey:Y},hasItemAlias:$.some((H)=>H.startsWith("item:"))};for(let H of $)this.contextCompactionReceipts.delete(H),this.contextCompactionReceipts.set(H,Q);while(this.contextCompactionReceipts.size>qq){let H;for(let W of this.contextCompactionReceipts.values()){if(W.completed){H=W;break}H??=W}if(!H)break;for(let[W,X]of this.contextCompactionReceipts)if(X===H)this.contextCompactionReceipts.delete(W)}}handleTurnPlanUpdated($){let Z=this.currentTurn;if(!Z){_(`session "${this.sessionName}": turn/plan/updated with no current turn`);return}if(this.startWorkingFooter(Z),Z.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();if(Z.openBatchI=null,!Array.isArray($.plan))_(`session "${this.sessionName}": turn/plan/updated missing plan array`),Z.planSteps=[];else Z.planSteps=$.plan.map((J)=>({step:typeof J.step==="string"&&J.step?J.step:"MISS",status:typeof J.status==="string"&&J.status?J.status:"MISS"}));if(Z.planExplanation=typeof $.explanation==="string"?$.explanation:null,Z.planSteps.length>0)if(!Z.planLiveInserted){let J=Z.taskLiveInserted?R.taskBoardLive:R.footer;Z.planLiveInserted=!0,B0(Z.cardId,J4(Z.planSteps,Z.planExplanation,R.planLive),{type:"insert_before",targetElementId:J})}else t(Z.cardId,R.planLive,J4(Z.planSteps,Z.planExplanation,R.planLive));this.addPlanSnapshotOnCurrentTurn()}handlePlanDelta($){if(typeof $.delta!=="string"||!$.delta){_(`session "${this.sessionName}": item/plan/delta missing delta text`);return}if(typeof $.itemId!=="string"||!$.itemId)_(`session "${this.sessionName}": item/plan/delta missing itemId`)}handleThreadGoalUpdated($){if(!$||typeof $.objective!=="string"){_(`session "${this.sessionName}": thread/goal/updated missing objective`);return}if($.tokenBudget!=null&&typeof $.tokenBudget!=="number")_(`session "${this.sessionName}": thread/goal/updated invalid tokenBudget`);let Z=this.currentGoal,J={objective:$.objective,status:typeof $.status==="string"&&$.status?$.status:"MISS",tokenBudget:typeof $.tokenBudget==="number"?$.tokenBudget:$.tokenBudget===null?null:Number.NaN,tokensUsed:typeof $.tokensUsed==="number"?$.tokensUsed:Number.NaN,timeUsedSeconds:typeof $.timeUsedSeconds==="number"?$.timeUsedSeconds:Number.NaN};if(this.currentGoal=J,Z&&C9(Z)===C9(J))return;let Y=this.currentTurn;if(Y){if(this.startWorkingFooter(Y),Y.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();Y.openBatchI=null}this.addGoalUpdateOnCurrentTurn(J)}handleThreadGoalCleared(){if(!this.currentGoal)return;this.currentGoal=null;let $=this.currentTurn;if(!$)return;if(this.startWorkingFooter($),$.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();$.openBatchI=null,this.addGoalClearedOnCurrentTurn()}appendAssistant($){if(!this.currentTurn){if(this.openingTurn||this.bgResumeCardless)this.orphanAssistantCurrent+=$;return}let Z=this.currentTurn;if(this.startWritingFooter(Z),!Z.currentAssistantSegmentId){Z.openBatchI=null,this.maybeMidTurnRotate();let H=Z.assistantSegmentCount++,W=R.assistant(H);Z.currentAssistantSegmentId=W,Z.currentAssistantText=""}Z.currentAssistantText+=$;let J=Z.currentAssistantSegmentId;if(!J)return;Z.segmentTexts.set(J,Z.currentAssistantText),this.processOutboundMarkers(Z.currentAssistantText);let Q=this.cleanAssistantTextForDisplay(Z.currentAssistantText).slice(0,40);L$(Z.cardId,Q)}takeOrphanAssistantText(){let $=[...this.orphanAssistantSegments];if(this.orphanAssistantCurrent.trim())$.push(this.orphanAssistantCurrent);return this.orphanAssistantSegments=[],this.orphanAssistantCurrent="",$.join(`
|
|
204
207
|
|
|
205
|
-
`).trim()}discardOrphanAssistant(){this.orphanAssistantSegments=[],this.orphanAssistantCurrent="",this.bgResumeCardless=!1}flushOrphanAssistantToChat($){let Z=this.takeOrphanAssistantText();if(!Z)return;let J=this.cleanAssistantTextForDisplay(Z).trim();if(!J)return;
|
|
208
|
+
`).trim()}discardOrphanAssistant(){this.orphanAssistantSegments=[],this.orphanAssistantCurrent="",this.bgResumeCardless=!1}flushOrphanAssistantToChat($){let Z=this.takeOrphanAssistantText();if(!Z)return;let J=this.cleanAssistantTextForDisplay(Z).trim();if(!J)return;_(`session "${this.sessionName}": flushing ${J.length} chars of orphan assistant text (${$})`),E(this.chatId,`\uD83D\uDCC4 后台轮输出(未能建卡,纯文本兜底):
|
|
206
209
|
|
|
207
|
-
${J}`)}completedAssistantElement($,Z){if(
|
|
210
|
+
${J}`)}completedAssistantElement($,Z){if(t5(Z))return this.mathAssistantContainer($,[{type:"markdown",text:Z}]);return{tag:"markdown",element_id:$,content:this.cleanAssistantTextForDisplay(Z).trim()||" "}}mathAssistantContainer($,Z){let J=Z.map((Y)=>Y.type==="markdown"?{tag:"markdown",content:this.cleanAssistantTextForDisplay(Y.text).trim()||" "}:{...Y.element});return{tag:"column_set",element_id:$,flex_mode:"none",columns:[{tag:"column",width:"weighted",weight:1,elements:J.length?J:[{tag:"markdown",content:" "}]}]}}async replaceSegmentWithMathImgs($,Z,J,Y){let Q=await _H(Y);if(!await L0(Z,J,this.mathAssistantContainer(J,Q.blocks),{notifyCardFailure:!1})){_(`session "${this.sessionName}": math render ${J} write dropped (card closed/element dead) — raw text stays`);return}$.mathRendered??=new Map,$.mathRendered.get(Z)??$.mathRendered.set(Z,new Set),$.mathRendered.get(Z).add(J),_(`session "${this.sessionName}": math rendered ${J} (${Q.renderedImageCount} img, ${Q.blocks.length} blocks)`)}addCompletedAssistantSegment($,Z,J){let Y=$.cardId,Q=j0($),H=(async()=>{if(!await w$(Y,this.completedAssistantElement(Z,J),{type:"insert_before",targetElementId:Q}))return _(`session "${this.sessionName}": assistant segment ${Z} raw write failed on card=${Y}`),!1;if(t5(J)){let X=this.replaceSegmentWithMathImgs($,Y,Z,J).catch((V)=>_(`session "${this.sessionName}": math render ${Z} failed: ${V}`));$.mathRenderInflight??=new Map,$.mathRenderInflight.get(Y)??$.mathRenderInflight.set(Y,new Set),$.mathRenderInflight.get(Y).add(X),X.finally(()=>$.mathRenderInflight?.get(Y)?.delete(X))}return!0})();return $.assistantWriteInflight??=new Map,$.assistantWriteInflight.get(Y)??$.assistantWriteInflight.set(Y,new Set),$.assistantWriteInflight.get(Y).add(H),H.finally(()=>$.assistantWriteInflight?.get(Y)?.delete(H)),H}async sendAssistantTextFallback($,Z){let J=$.trim();if(!J)return;let Y=`⚠️ 对话卡片正文写入失败(${Z}),以下为 agent 原始回复:
|
|
208
211
|
|
|
209
|
-
${J}`;if(!await
|
|
210
|
-
${
|
|
211
|
-
你的下一条文字优先用于这条通知,完成后再回答 Agent 的提问。点击其他通知的「回复」会放弃本次回复;群控制命令仍然优先。`}),H.push({tag:"button",text:{tag:"plain_text",content:"取消回复"},type:"default",behaviors:[{type:"callback",value:{kind:"notify_reply_cancel",notify_id:$.notifyId,reply_id:Z.id}}]});if(Y==="cancelled"&&Z.cancelReason==="switched")H.push({tag:"markdown",content:"已切换到另一条通知,本次回复已放弃。"});let W=J?.detail??Z.error;if(W)H.push({tag:"markdown",content:`<font color='red'>${
|
|
212
|
+
${J}`;if(!await E(this.chatId,Y))_(`session "${this.sessionName}": ASSISTANT_TEXT_PRESERVATION_FAILED (${Z}, ${J.length} chars)`)}finalizeCurrentAssistantSegment(){let $=this.currentTurn;if(!$){if(this.orphanAssistantCurrent.trim())this.orphanAssistantSegments.push(this.orphanAssistantCurrent);this.orphanAssistantCurrent="";return}if($.cardRotationFailed)this.maybeMidTurnRotate();if($.rotating)return;let Z=$.currentAssistantSegmentId,J=$.currentAssistantText??"";if(Z&&J.trim())this.addCompletedAssistantSegment($,Z,J),this.startWorkingFooter($);$.currentAssistantSegmentId=null,$.currentAssistantText=""}processOutboundMarkers($){for(let Z of nQ($))this.sendOutboundPath(Z,"send marker")}cleanAssistantTextForDisplay($){return r($)}sendOutboundPath($,Z){let J=G6($.trim());if(!J)return;let Y=this.currentTurn;if(Y?.outboundSeenPaths.has(J))return;if(Y?.outboundSeenPaths.add(J),!zq(J)){_(`session "${this.sessionName}": ignore non-absolute outbound path from ${Z}: ${J}`);return}Y?.outboundSentPaths.add(J),_(`session "${this.sessionName}": outbound send from ${Z}: ${J}`),e2(this.chatId,J)}startFooterStatus($,Z){if($.cardRotationFailed)return;let J=$.provider==="codex"?this.proc?.turnRetry:null;if(J)Z=J.phase==="waiting"?`⏳ 模型满载 · ${J.delayMs/1000}s 后重试 #${J.attempt}`:`⏳ 模型满载 · 正在重试 #${J.attempt}`;if($.footerStatusHandle&&$.footerStatusLabel===Z)return;this.stopFooterStatus($),$.footerStatusLabel=Z,$.footerStatusStartedAt=Date.now();let Y=()=>{if($.footerStatusLabel!==Z)return;let{label:H}=x$(Date.now()-$.footerStatusStartedAt,T1()),W=Z===DX?this.proc?.lastThinkingTokens:null,X=typeof W==="number"?` · 约 ${W} tokens`:"";this.replaceFooterContent($.cardId,this.withModel(`${Z}${X} (${H})`))},Q=()=>{if($.footerStatusLabel!==Z)return;let{nextDelayMs:H}=x$(Date.now()-$.footerStatusStartedAt,T1());$.footerStatusHandle=setTimeout(()=>{Y(),Q()},Math.max(1,Math.ceil(H)))};Y(),Q()}startThinkingFooter($){this.startFooterStatus($,DX)}startWritingFooter($){this.startFooterStatus($,Kq)}startWorkingFooter($){this.startFooterStatus($,Bq)}stopFooterStatus($){if(!$)return;if($.footerStatusHandle)clearTimeout($.footerStatusHandle);$.footerStatusHandle=null,$.footerStatusStartedAt=0,$.footerStatusLabel=null}async footerUsageSuffix($,Z,J,Y,Q){if(J&&(!Y||!Y.enabled||Y.agent!==$))return" | 额度 MISS";if(Y?.agent===$&&Y.enabled&&($==="claude"||$==="dsh")){let H=await Y.readUsage();if(H.state==="ok"&&H.kind!=="balance"){let W=H.windows.find((V)=>V.kind==="fiveHour"),X=H.windows.find((V)=>V.kind==="weekly");if(W||X)return this.fmtDualWindowSuffix(W??null,X??null)}return` | ${a9(H)}`}if($==="codex"){let H=Z?.isAlive()&&Z.provider==="codex"&&Z.readRateLimits?Z:null,W=H?await cQ(()=>H.readRateLimits()):null,X=H?W:Q;return X?.state==="ok"?this.fmtDualWindowSuffix(X.fiveHour??null,X.weekly??null):" | 额度 MISS"}return" | 额度 MISS"}fmtDualWindowSuffix($,Z){let J=(H)=>{if(!H)return null;if(H.percent==null)return"MISS";let W=H.resetsAt&&H.resetsAt.getTime()>Date.now()?D5(H.resetsAt):"",X=`${Math.round(H.percent)}%`;return W?`${W}·${X}`:X},Y=J($),Q=J(Z);if(Y&&Q)return` | ${Y}·[${Q}]`;if(Y)return` | ${Y}`;if(Q)return` | [${Q}]`;return" | 额度 MISS"}waitForTurnCloses(){let $=[...this.turnCloseInflight];if($.length===0)return Promise.resolve();return Promise.allSettled($).then((Z)=>{let J=Z.filter((Y)=>Y.status==="rejected").map((Y)=>Y.reason);if(J.length===1)throw J[0];if(J.length>1)throw AggregateError(J,`turn close failed: ${J.map(O).join("; ")}`)})}releaseTurnCloseReactions($){for(let[Z,J]of[...$.currentBatchReactionIds.entries(),...$.pendingReactionIds.entries()])if(J)T0(Z,J)}closeTurnCard($,Z={}){let J=this.currentTurn;if(!J)return this.waitForTurnCloses();if(!$&&J.cardRotationFailed)this.maybeMidTurnRotate();this.currentTurn=null,this.stopFooterStatus(J);let Y=this.proc,Q={turn:J,proc:Y,procEpoch:this.procEpoch,contextTokens:this.currentContextTokens(Y),contextLimit:this.contextLimitForDisplay(Y),lastTurnDelta:this.lastTurnDelta?{...this.lastTurnDelta}:null,lastTurnUsage:this.lastTurnUsage?{...this.lastTurnUsage}:null,tokenSourceId:this.selectedTokenSourceId,tokenSource:this.currentTokenSource(),codexUsage:gQ(),currentBatchReactionIds:this.currentBatchReactionIds,pendingReactionIds:this.pendingReactionIds};this.currentBatchReactionIds=new Map,this.pendingReactionIds=new Map;let H=this.finishTurnCardClose(Q,$,Z).finally(()=>this.releaseTurnCloseReactions(Q));return this.turnCloseInflight.add(H),H.then(()=>{this.turnCloseInflight.delete(H)},()=>{this.turnCloseInflight.delete(H)}),H}async finishTurnCardClose($,Z,J={}){let{turn:Y}=$;if(Y.rotating)await Y.rotating;await W3(Y),this.stopFooterStatus(Y);let Q=((Date.now()-Y.startedAt)/1000).toFixed(1),H=Y.cardId,W=Y.segmentTexts;await c0(H);let X=new Map;if(Y.currentAssistantSegmentId&&Y.currentAssistantText.trim()){let{currentAssistantSegmentId:M,currentAssistantText:j}=Y;if(!await this.addCompletedAssistantSegment(Y,M,j))X.set(M,j);Y.currentAssistantSegmentId=null,Y.currentAssistantText=""}let V=Y.assistantWriteInflight?.get(H);if(V?.size)await Promise.allSettled([...V]);let z=Y.mathRenderInflight?.get(H);if(z?.size)await Promise.allSettled([...z]);let G=Y.mathRendered?.get(H);for(let[M,j]of W){if(r1(H,M)){X.set(M,j);continue}if(G?.has(M))continue;await t(H,M,this.completedAssistantElement(M,j))}if(Y.cardRotationFailed)for(let[M,j]of W)X.set(M,j);let A=Z?Z:"✅",K=[`${A} ⏱ ${Q}s`];if(J.hasFreshResult){let{contextTokens:M,contextLimit:j}=$,k=Y.provider==="claude",C=r8(M,j,k?0:void 0);if(C)K.push(`\uD83E\uDDE0 ${C}`);let c=$.lastTurnDelta?.costUsd??0;if(c>0)K.push(`\uD83D\uDCB0 $${c.toFixed(3)}`)}if(Y.contextCompactCount>0)K.push(`\uD83D\uDEA8 压缩×${Y.contextCompactCount}`);if(Y.outboundSentPaths.size>0)K.push(`\uD83D\uDCCE ${Y.outboundSentPaths.size}`);let L=this.modelLine(Y);if(L)K.push(L);let D=K.join(" | "),q=J.hasFreshResult?t8($.lastTurnUsage)+(Y.cardRotationFailed?"":await this.footerUsageSuffix(Y.provider,$.proc,$.tokenSourceId,$.tokenSource,$.codexUsage)):"",P=q?`${D}
|
|
213
|
+
${q}`:D,x=await L0(H,R.footer,this.footerElement(P));D0(H);let F=await P0(H,D$({durationSec:Q,outputTokens:J.hasFreshResult?$.lastTurnUsage?.output_tokens:void 0,suffix:Z}));if(x&&F)await m0(H);else{let M=`footer=${x?"ok":"MISS"}, settings=${F?"ok":"MISS"}`;_(`session "${this.sessionName}": terminal card transaction incomplete card=${H.slice(0,12)} ${M}`),await w(this.chatId,`⚠️ 对话卡片终态写入失败 (${M})。本轮已结束: ${A}`)}for(let M of X.values())await this.sendAssistantTextFallback(M,"CardKit 元素未落地");if((J.forcePush||!Z)&&Y.userOpenId&&Y.messageId&&!Y.cardRotationFailed)V1(Y.messageId,[Y.userOpenId])}}});function l0($){return{card:{type:"raw",data:$}}}import{randomUUID as Dq}from"node:crypto";function a3($){return{session_name:$.sessionName,chat_id:$.chatId,status:$.status,running:$.isRunning(),busy:!!($.currentTurn||$.openingTurn||$.pendingUserMessageCount||$.pendingMidTurnMsgs.length),awaiting_model_input:!!$.modelCustomPrompt,last_result:$.proc?{anchor:$.proc.lastAssistantUuid,subtype:$.proc.lastResult.subtype,is_error:$.proc.lastResult.is_error}:null,selection:{provider:$.selectedProvider,source_id:$.selectedTokenSourceId,model:$.selectedModel,effort:$.selectedEffort},panels:[...$.modelPanels].map(([Z,J])=>({panel_id:Z,message_id:J.messageId,source_id:J.sourceId,mode:J.mode,editable:J.editable,total_models:J.catalog?.length,page:J.page,total_pages:J.totalPages,models:J.models.map((Y)=>({model:Y.model,provider:Y.provider,source_id:Y.sourceId,efforts:Y.efforts.map((Q)=>Q.effort),origin:Y.origin}))})),sources:A$().map((Z)=>({id:Z.id,display:Z.display,agent:Z.agent,enabled:Z.enabled,validates_custom_model:!!Z.verifyModel,status:Z.modelCatalogState?.status,error:Z.modelCatalogState?.error,models:Z.models.map((J)=>({model:J.model,efforts:J.efforts,default_effort:J.defaultEffort,unavailable_reason:J.unavailableReason,origin:J.origin}))}))}}function FX($,Z,J,Y,Q){if(!$||typeof $!=="object"||Array.isArray($))throw Error("bad action body");let H=$;if(!Z.chat_id.startsWith("oc_")||!Z.sender_open_id.startsWith("ou_"))throw Error("invalid debug context");if(H.chat_id!==Z.chat_id)throw Error("debug chat mismatch");if(typeof H.message_id!=="string"||!H.message_id.startsWith("om_"))throw Error("message_id required");if(!Q||H.message_id!==Q)throw Error("stale or mismatched model panel");if(!J||J.message_id!==H.message_id||J.chat_id!==Z.chat_id||J.msg_type!=="interactive"||J.sender?.sender_type!=="app"||J.sender.id!==Y)throw Error("model card must belong to this app and debug chat");if(!H.value||typeof H.value!=="object"||Array.isArray(H.value))throw Error("action value required");let W={};for(let[X,V]of Object.entries(H.value)){if(!jq.has(X))throw Error(`unsupported model action field: ${X}`);if(X==="page"){if(typeof V!=="number"||!Number.isSafeInteger(V)||V<0)throw Error("invalid page");W.page=V}else{if(typeof V!=="string"||!V.trim()||V.length>1024)throw Error(`invalid ${X}`);W[X]=V.trim()}}if(!Pq.has(String(W.kind)))throw Error("only model panel actions are supported");for(let X of["panel_id","source_id"])if(!W[X])throw Error(`${X} required`);if(["model_select","model_effort_select","model_add","model_remove","model_custom_remove"].includes(String(W.kind))&&!W.model)throw Error("model required");if(W.kind==="model_effort_select"&&!W.effort)throw Error("effort required");if(W.kind==="model_page"&&W.page===void 0)throw Error("page required");if(W.kind==="model_list_open"&&W.mode!=="select"&&W.mode!=="add")throw Error("invalid model list mode");if(W.provider!==void 0&&!$$(W.provider))throw Error("invalid provider");return{event_id:`debug-model-${Dq()}`,operator:{open_id:Z.sender_open_id},context:{open_chat_id:Z.chat_id,open_message_id:H.message_id},action:{tag:"button",value:W}}}var Pq,jq;var MX=S(()=>{K0();Z0();Pq=new Set(["provider_select","model_select","model_effort_select","model_page","model_list_open","model_add","model_remove","model_custom_remove","model_custom_prompt","model_panel_cancel"]),jq=new Set(["kind","panel_id","source_id","model","effort","provider","page","mode"])});import{createServer as Fq}from"node:http";import{randomUUID as Mq}from"node:crypto";function TX($){if($.allowReply&&$.buttons?.length)throw Error(OX);let Z=$.level==="error"?"red":$.level==="warn"?"yellow":"blue",J=$.level==="error"?"❌":$.level==="warn"?"⚠️":"\uD83D\uDD14",Y=!!(($.buttons?.length||$.allowReply)&&$.notifyId),Q=new Date,H=`${String(Q.getHours()).padStart(2,"0")}:${String(Q.getMinutes()).padStart(2,"0")}`,W=[];for(let V of $.images??[])if(V.key)W.push({tag:"img",img_key:V.key,alt:{tag:"plain_text",content:"screenshot"}});else W.push({tag:"markdown",content:`<font color='red'>\uD83D\uDCF7 图片上传失败: ${V.src}</font>`});if(W.push({tag:"markdown",content:v7($.text??"")||"_(空消息)_"}),$.resolution){let V=$.resolution,z=V.kind==="text"?"已回复":`已选择:${V.text}`,G;if(V.status==="processing")G=`<font color='blue'>⏳ ${z} · 推送中…</font>`;else if(V.status==="failed")G=`<font color='red'>⚠️ ${V.kind==="text"?z:`已选:${V.text}`} · 回调失败:${r(V.detail??"未知")} · ${H}</font>`;else if(V.status==="delivered")G=`<font color='green'>✅ ${z} · 反馈已送达 · ${H}</font>`;else if(V.status==="unknown")G=`<font color='red'>⚠️ ${z} · ${V.kind==="text"?"送达状态未知,禁止自动重试":"外部回调已成功,但本地确认状态未知,禁止自动重试"} · ${H}</font>`;else G=`<font color='green'>✅ ${z} · ${H}</font>`;if(W.push({tag:"markdown",content:G}),V.status==="delivered"&&V.reply)W.push({tag:"markdown",content:r(V.reply)})}let X=Y&&(!$.resolution||$.resolution.status==="failed");if(X&&$.buttons?.length)W.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:1,elements:$.buttons.map((V)=>({tag:"button",text:{tag:"plain_text",content:V.text},type:V.type,behaviors:[{type:"callback",value:{kind:"notify_callback",notify_id:$.notifyId,button_id:V.id}}]}))}]});if(W.push({tag:"hr"}),W.push({tag:"markdown",content:`<font color='grey'>via notify · ${H}</font>`}),X&&$.allowReply)W.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"回复"},type:"primary",behaviors:[{type:"callback",value:{kind:"notify_reply",notify_id:$.notifyId}}]}]}]});return{schema:"2.0",config:Y?{update_multi:!0}:{},header:{title:{tag:"plain_text",content:`${J} ${$.title}`},template:Z},body:{elements:W}}}function l$($,Z,J){let Y=J?.status??Z.status,Q={waiting:"等待用户输入",sending:"正在发送回复",processing:"正在发送回复",delivered:"回复已送达",done:"回复已记录",failed:"回复发送失败",cancelled:"已取消回复",unknown:"回复送达状态未知"},H=[{tag:"markdown",content:`通知:${r($.title)}`}];if(Z.response)H.push({tag:"markdown",content:r(Z.response.text)});if(Y==="waiting")H.push({tag:"markdown",content:`<at id=${Z.openId}></at> 请在群里发送一条文字消息作为回复。
|
|
214
|
+
你的下一条文字优先用于这条通知,完成后再回答 Agent 的提问。点击其他通知的「回复」会放弃本次回复;群控制命令仍然优先。`}),H.push({tag:"button",text:{tag:"plain_text",content:"取消回复"},type:"default",behaviors:[{type:"callback",value:{kind:"notify_reply_cancel",notify_id:$.notifyId,reply_id:Z.id}}]});if(Y==="cancelled"&&Z.cancelReason==="switched")H.push({tag:"markdown",content:"已切换到另一条通知,本次回复已放弃。"});let W=J?.detail??Z.error;if(W)H.push({tag:"markdown",content:`<font color='red'>${r(W)}</font>`});if(Y==="failed")H.push({tag:"markdown",content:"请点击原通知的「回复」按钮后重新输入。"});if(Y==="unknown")H.push({tag:"markdown",content:"无法确认是否已送达,请联系通知发起方核实;已禁止自动重试。"});if(J?.reply)H.push({tag:"markdown",content:r(J.reply)});return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:Q[Y]},template:Y==="failed"||Y==="unknown"?"red":Y==="delivered"||Y==="done"?"green":"blue"},body:{elements:H}}}function Tq($){if($===void 0||$===null)return{buttons:[]};if(!Array.isArray($))return{error:'"buttons" must be an array'};if($.length===0)return{buttons:[]};let Z=new Set,J=[];for(let Y of $){if(!Y||typeof Y!=="object")return{error:"each button must be an object"};let Q=String(Y.id??"").trim(),H=String(Y.text??"").trim();if(!Oq.test(Q))return{error:`button id "${Q.slice(0,32)}" invalid (need ^[A-Za-z0-9_-]{1,64}$)`};if(!H)return{error:`button "${Q}" missing text`};if(H.length>RX)return{error:`button "${Q}" text > ${RX} chars`};if(Z.has(Q))return{error:`button id "${Q}" duplicated`};Z.add(Q);let W=String(Y.type??"default").toLowerCase(),X=Uq.has(W)?W:"default";J.push({id:Q,text:H,type:X})}return{buttons:J}}function Eq($){if($===void 0||$===null)return{};let Z=String($).trim();if(!Z)return{};let J;try{J=new URL(Z)}catch{return{error:`"callback" bad URL: "${Z.slice(0,64)}"`}}if(J.protocol!=="http:")return{error:`"callback" must be http (本机内), got "${J.protocol}"`};let Y=J.hostname.replace(/^\[|]$/g,"");if(Y!=="127.0.0.1"&&Y!=="localhost"&&Y!=="::1")return{error:`"callback" must be loopback (本机内), got "${J.hostname}"`};return{url:Z}}function EX($){try{let Z=Fq((J,Y)=>{let Q=new URL(J.url??"/",`http://${J.headers.host??"localhost"}`);($.extraHandler?$.extraHandler(J,Y,Q).then((W)=>W?void 0:UX(J,Y)):UX(J,Y)).catch((W)=>{if(_(`notify: handler crash: ${W?.message??W}`),!Y.headersSent)Y.statusCode=500,Y.setHeader("content-type","text/plain; charset=utf-8"),Y.end("internal error");else try{Y.end()}catch{}})});Z.on("error",(J)=>{_(`notify: server bind failed (${$.bind}:${$.port}): ${J.message}`)}),Z.listen($.port,$.bind,()=>{_(`notify: HTTP listening at http://${$.bind}:${$.port}/notify`)})}catch(Z){_(`notify: server bind failed (${$.bind}:${$.port}): ${Z}`)}}async function UX($,Z,J=J0){let Y=new URL($.url??"/",`http://${$.headers.host??"localhost"}`),Q=(T,U)=>{Z.statusCode=T,Z.setHeader("content-type","text/plain; charset=utf-8"),Z.end(U)},H=(T,U)=>{Z.statusCode=T,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify(U))};if($.method==="GET"&&Y.pathname==="/")return Q(200,`lodestar notify
|
|
212
215
|
`+`POST /notify body={project,text,title?,level?,images?,buttons?,allow_reply?,callback?} → push card to group
|
|
213
216
|
`+`GET /notify/result/<notify_id> → poll a button choice or text reply (pull mode, no callback server)
|
|
214
217
|
`+`GET /agents/identities; POST/GET/DELETE /agents/runs[/<id>] → capability-protected delegated Agents
|
|
215
218
|
`+`levels: info|warn|error (default info); images=[/abs/*.png] uploaded + embedded
|
|
216
219
|
card types: plain (neither field), selection (buttons), text reply (allow_reply:true); do not combine buttons and allow_reply:true
|
|
217
220
|
`+`all types support text + images; callback=http://127.0.0.1:PORT/path optional for selection/reply (push) — omit to poll
|
|
218
|
-
`);if($.method==="GET"&&Y.pathname.startsWith("/notify/result/")){let
|
|
219
|
-
`;for(let[H,W]of[[J,Q],[Y,$.body]])try{let X=
|
|
220
|
-
name: ${
|
|
221
|
+
`);if($.method==="GET"&&Y.pathname.startsWith("/notify/result/")){let T=decodeURIComponent(Y.pathname.slice(15)).trim();if(!T)return Q(400,"missing notify_id in path");let U=P$(T);if(!U)return H(404,{error:"unknown notify_id",notify_id:T});return H(200,jH(U))}if($.method!=="POST"||Y.pathname!=="/notify")return Q(405,"use POST /notify");let W="";for await(let T of $)W+=T.toString();let X={};try{X=JSON.parse(W)}catch{return Q(400,"bad json")}if(!X||typeof X!=="object"||Array.isArray(X))return Q(400,"body must be an object");if(X.allow_reply!==void 0&&typeof X.allow_reply!=="boolean")return Q(400,'"allow_reply" must be a boolean');let V=X.allow_reply===!0,z=String(X.project??"").trim(),G=String(X.text??""),A=String(X.title??"").trim(),K=String(X.level??"info").toLowerCase();if(!z)return Q(400,'missing "project"');if(!G)return Q(400,'missing "text"');let{buttons:L,error:D}=Tq(X.buttons);if(D)return Q(400,D);let{url:q,error:P}=Eq(X.callback);if(P)return Q(400,P);let x=!!(L&&L.length);if(x&&V)return Q(400,OX);let F=x||V,M=q??"",j=Rq.has(K)?K:"info",k=A||z,C=J.sanitizeSessionName(z),c=J.chatIdForSession(C);if(!c)return _(`notify: project "${z}" (sanitized "${C}") has no chat binding → 404`),Q(404,`project "${z}" not bound — send any message in that Feishu group at least once after the daemon started, then retry`);let y=Array.isArray(X.images)?X.images:[],m=[];for(let T of y){let U=String(T??"").trim();if(!U)continue;let b=await J.uploadImageKey(U);m.push({key:b??"",src:U})}let N=F?`nf_${Mq()}`:"",f=TX({title:k,text:G,level:j,images:m,buttons:L,allowReply:V,notifyId:N}),I=await J.sendCard(c,f);if(!I)return _(`notify: sendCard failed → 502 (project="${z}" chat=${c.slice(0,8)}…)`),Q(502,"feishu sendCard failed (see daemon log)");if(F&&N){let T={notifyId:N,callbackUrl:M,chatId:c,messageId:I,project:z,title:k,text:G,level:j,imageKeys:m,buttons:L,allowReply:V,createdAt:Date.now()};DH(T)}_(`notify: → ${z} (${c.slice(0,8)}…) level=${j} bytes=${G.length} images=${m.length} buttons=${L?.length??0} allowReply=${V} push=${F&&!!M?1:0} msg=${I}`),H(200,{ok:!0,chat_id:c,message_id:I,...N?{notify_id:N}:{}})}function E1($,Z){return TX({title:$.title,text:$.text,level:$.level,images:$.imageKeys,buttons:$.buttons,allowReply:$.allowReply,notifyId:$.notifyId,resolution:Z})}var Rq,Uq,Oq,RX=64,OX='"buttons" and "allow_reply":true are mutually exclusive; choose button selection or text reply';var v6=S(()=>{g();e();I0();R4();Rq=new Set(["info","warn","error"]),Uq=new Set(["default","primary","danger"]),Oq=/^[A-Za-z0-9_-]{1,64}$/});import{existsSync as o3,readFileSync as r3,rmSync as Nq}from"node:fs";import{homedir as h6}from"node:os";import{join as V$}from"node:path";function I6($,Z){if(process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"){_(`skill: sync disabled, skip ${$.name}`);return}let J=Z??[V$(h6(),".codex","skills"),V$(h6(),".claude","skills")];for(let Y of J){let Q=V$(Y,$.name,"SKILL.md");try{let H=o3(Q)?r3(Q,"utf8"):null;if(H===$.body)continue;d0(Q,$.body),_(`skill: ${H===null?"installed":"updated"} ${Q}`)}catch(H){_(`skill: sync failed (${Q}): ${H}`)}}if(!Z)Sq($,o$)}function Sq($,Z){if(process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"){_(`skill: sync disabled, skip Claude plugin ${$.name}`);return}let J=V$(Z,".claude-plugin","plugin.json"),Y=V$(Z,"skills",$.name,"SKILL.md"),Q=JSON.stringify({name:"lodestar-managed",description:"Lodestar daemon-managed Skills for Claude Agent SDK sessions",version:"1.0.0",author:{name:"Lodestar"}},null,2)+`
|
|
222
|
+
`;for(let[H,W]of[[J,Q],[Y,$.body]])try{let X=o3(H)?r3(H,"utf8"):null;if(X===W)continue;d0(H,W),_(`skill: ${X===null?"installed":"updated"} ${H}`)}catch(X){_(`skill: Claude plugin sync failed (${H}): ${X}`)}}function NX($,Z){if(process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"){_(`skill: sync disabled, skip removal ${$}`);return}let Y=(Z??[V$(h6(),".codex","skills"),V$(h6(),".claude","skills")]).map((Q)=>V$(Q,$));if(!Z)Y.push(V$(o$,"skills",$));for(let Q of Y){let H=V$(Q,"SKILL.md");if(!o3(H))continue;try{let W=r3(H,"utf8");if(!(W.includes(`name: ${$}`)||W.includes(`name: "${$}"`))){_(`skill: obsolete path preserved because ownership is unclear ${H}`);continue}Nq(Q,{recursive:!0,force:!1}),_(`skill: removed obsolete ${Q}`)}catch(W){_(`skill: obsolete removal failed (${Q}): ${W}`)}}}var t3=S(()=>{g();n0();Y0()});function xq($){let Z=`Push a one-shot notification card to a Feishu (Lark) group via the local lodestar daemon's HTTP endpoint. Auto-trigger whenever the user asks to "通知飞书", "推送到飞书", "推到飞书群", "飞书推送", "发到飞书", "脚本跑完通知我", "进程完成发个消息", "send to feishu", "feishu notify", "lodestar notify", "post to lark group", or wants any local script / cron / long-running process to ping a Feishu group (build done, deploy finished, trade filled, monitor alert, error caught). Encodes the call shape — POST http://127.0.0.1:${$}/notify with \`{project, text, level}\` — so consumers do not have to re-derive it. Also covers interactive buttons: add \`buttons\` and either pledge a loopback \`callback\` URL (daemon POSTs the click back) or omit it and poll \`GET /notify/result/NOTIFY_ID\`; all on localhost.`;return`---
|
|
223
|
+
name: ${SX}
|
|
221
224
|
description: ${JSON.stringify(Z+" Also receive free-text replies with allow_reply:true: a fixed 回复 button opens a waiting card, then the user types in the group and the daemon returns the text through the same callback or result endpoint.")}
|
|
222
225
|
---
|
|
223
226
|
|
|
@@ -474,13 +477,13 @@ is the script's acknowledgement, distinct from the user's response.
|
|
|
474
477
|
Hand-edits will be overwritten — set
|
|
475
478
|
\`LODESTAR_DISABLE_SKILL_SYNC=1\` and restart the daemon if you want
|
|
476
479
|
to maintain the file yourself.
|
|
477
|
-
`}function
|
|
478
|
-
`)}function
|
|
479
|
-
`)});function
|
|
480
|
+
`}function xX(){I6({name:SX,body:xq(v.notify.port)})}var SX="feishu-notify";var kX=S(()=>{x0();t3()});import{randomUUID as kq}from"node:crypto";function CX($){let Z=(H)=>H instanceof Error?H.message:String(H),J=(H,W,X)=>{if(!H)return"通知已过期或已移除";if(!X)return"无法识别回复人,操作未执行";if(W&&W!==H.chatId)return"通知不属于当前群,操作未执行";if(!H.allowReply)return"此通知未开启文字回复";if(H.unknownAt)return`回复送达状态未知,禁止自动重试:${H.unknownReason}`;if(H.resolvedAt)return"此通知已处理";if(H2(H.notifyId))return"通知正在处理中";return null},Y=async(H,W)=>{if($.log(`notify-reply: ${W}`),!await $.sendText(H,`❌ ${W}`))throw Error(`通知回复错误提示发送失败: ${W}`)},Q=async(H,W,X,V)=>{try{await $.updateCard(W,X)}catch(z){await Y(H.chatId,`${V},卡片更新失败:${Z(z)}`)}};return{async recover(H){let W=H.replyState;if(!W||!H.unknownAt)return;let X={kind:"text",status:"unknown",text:W.response?.text??"",operatorOpenId:W.openId,detail:H.unknownReason};await Q(H,W.promptMessageId,l$(H,W,X),"回复送达状态未知"),await Q(H,H.messageId,E1(H,X),"回复送达状态未知")},async open(H,W,X){let V=P$(H),z=J(V,W,X);if(z||!V)return{ok:!1,message:z};if(V.replyState?.status==="waiting"||V.replyState?.status==="sending")return{ok:!1,message:"此通知正在等待回复,请先在群里输入或由回复人取消"};let G=e5(V.chatId);if(G.some((A)=>A.replyState?.status==="sending"||H2(A.notifyId)))return{ok:!1,message:"上一条通知回复正在发送,请稍后切换"};P4(H);try{for(let L of G){let D={...L.replyState,status:"cancelled",cancelReason:"switched"};X2(L.notifyId,D),await Q(L,D.promptMessageId,l$(L,D),"已放弃上一条回复并切换通知")}let A={id:kq(),openId:X,promptMessageId:"",openedAt:Date.now(),status:"waiting"},K=await $.sendCard(V.chatId,l$(V,A));if(!K)return{ok:!1,message:"等待输入卡片发送失败,未开始接收回复,请重新点击「回复」"};A.promptMessageId=K;try{X2(H,A)}catch(L){let D=`等待输入状态保存失败,未开始接收回复:${Z(L)}`;return await Q(V,K,l$(V,A,{status:"failed",detail:D}),D),{ok:!1,message:D,presented:!0}}return{ok:!0,message:"等待输入卡片已发送,请在群里回复一条文字",presented:!0}}finally{j4(H),$.onWaitingChanged(V.chatId)}},async cancel(H,W,X,V){let z=P$(H),G=J(z,X,V);if(G||!z)return{ok:!1,message:G};let A=z.replyState;if(!A||A.id!==W||A.status!=="waiting")return{ok:!1,message:"此回复已结束或正在发送,无法取消"};if(A.openId!==V)return{ok:!1,message:"仅点击「回复」的人可以取消"};let K={...A,status:"cancelled"};return X2(H,K),$.onWaitingChanged(z.chatId),await Q(z,A.promptMessageId,l$(z,K),"回复已取消"),{ok:!0,message:"已取消回复",presented:!0}},async consume(H){let{chatId:W,openId:X,messageId:V,text:z,createTime:G}=H;if(!X||!V||!z.trim())return!1;if(PH(W,V))return!0;let A=F4(W,X);if(!A?.replyState)return!1;let K=A.replyState;if(G>0&&G<K.openedAt)return!1;if(K.status!=="waiting"||H2(A.notifyId))return await Y(W,"上一条通知回复正在发送,这条文字未提交,请稍后重发"),!0;let L={text:z,message_id:V,prompt_message_id:K.promptMessageId},D={...K,status:"sending",response:L};P4(A.notifyId);try{try{X2(A.notifyId,D)}catch(F){return await Y(W,`回复保存失败,尚未回传,请重新输入:${Z(F)}`),!0}let q;try{if(await $.updateCard(K.promptMessageId,l$(A,D)),A.callbackUrl)q=await $.dispatch(A,L,X);else M4(A.notifyId,void 0,X),q={ok:!0,detail:"已记录"}}catch(F){q={ok:!1,detail:Z(F)}}let P;if(q.ok){let F=A.callbackUrl?A6(A.notifyId,void 0,X):{state:"complete"};P={kind:"text",text:z,operatorOpenId:X,status:F.state==="unknown"?"unknown":A.callbackUrl?"delivered":"done",...F.state==="unknown"?{detail:F.detail}:{reply:q.reply}}}else{P={kind:"text",text:z,operatorOpenId:X,status:"failed",detail:q.detail};try{X2(A.notifyId,{...D,status:"failed",error:q.detail})}catch(F){let M=`${q.detail};失败状态保存失败:${Z(F)}`;try{$3(A.notifyId,void 0,X,M)}catch(j){$.log(`notify-reply: UNKNOWN persistence failed: ${Z(j)}`)}P={...P,status:"unknown",detail:M}}}let x=P.status==="delivered"?"回复已送达":P.status==="done"?"回复已记录":P.status==="unknown"?`回复送达状态未知:${P.detail}`:`回复未送达:${P.detail}`;return await Q(A,K.promptMessageId,l$(A,D,P),x),await Q(A,A.messageId,E1(A,P),x),$.log(`notify-reply: notify_id=${A.notifyId} status=${P.status}`),!0}finally{j4(A.notifyId),$.onWaitingChanged(A.chatId)}}}}var bX=S(()=>{R4();v6()});function Cq(){return["---",`name: ${yX}`,`description: ${JSON.stringify("Main Agents can delegate a task to a different configured model or Agent through Lodestar. Delegated Agents and subagents must not use this Skill or delegate further. Main-Agent self-calls use native delegation capabilities.")}`,"---","","# lodestar-agent","","Use Lodestar to call the Agent represented by a selected live identity.","Each identity resolves to its configured Token Source, provider Agent backend,","model, and effort. The caller-supplied prompt becomes that Agent run's task.","","## Single-level delegation","","- Only the main Agent may delegate work. If you are already a delegated"," Agent or subagent, complete your assigned task yourself: do not delegate further.","- This prohibition covers this Skill, `lodestar-agent run` / `follow-up`,"," native Agent/subagent tools, and delegation through provider CLIs or HTTP APIs.","- `LODESTAR_AGENT_ROLE=worker` identifies a Lodestar delegated process."," Native subagents are also delegated Agents even when they inherit a main role environment.","- Return additional work requests to the main Agent. It can assign separate"," tasks, continue your session, or answer your questions.","","## Hard rule: native Agent capabilities for self-calls","","- For the main Agent only: when calling yourself or your own model/Agent, use your current"," Agent's native Agent/subagent capabilities. You MUST NOT use this Skill"," or the `lodestar-agent` command for self-calls.","- For example, Codex calling Codex uses Codex native subagents; Claude"," calling Claude uses Claude native Agent capabilities.","- This does not exempt delegated Agents from the single-level rule above.","- If native delegation is unavailable, report that limitation. It does not"," permit routing a self-call through this Skill.","","## Required workflow","","1. For another model/Agent, query the live identity catalog immediately before"," every new task:","","```bash","# desc: 查询当前可用的 Agent 身份","lodestar-agent identities --json","```","",'2. Select only identities with `status: "ready"`. Never invent, cache,'," substitute, or silently downgrade an identity/model/effort.","3. Give the child the complete task, relevant context, authority boundaries,"," expected deliverable, and verification requirements in the raw prompt."," Explicitly tell it to complete the work itself without further delegation.","4. For the same prompt sent to several other models, pass every identity to one run"," with repeated `--identity`; the daemon fans them out concurrently.","5. Wait for the result. Attribute each result to its actual model and surface"," failures. Child file changes are live in the same workspace.","","## Run a task","","```bash","# desc: 把完整任务交给指定 Agent","lodestar-agent run --identity '<identity-id>' --stdin <<'EOF'","<raw task prompt written by the main Agent>","EOF","```","","## Continue the same native Agent session","","```bash","# desc: 在同一原生 Agent 会话中继续任务","lodestar-agent follow-up '<run-id>' --identity '<identity-id>' --stdin <<'EOF'","<follow-up prompt>","EOF","```","","## Answer a child question","","When a run returns `Status: needs_input`, answer the exact request id. JSON","keys may be the question id or the full question text:","","```bash","# desc: 回答 Agent 的阻塞问题并继续运行","lodestar-agent answer '<run-id>' --identity '<identity-id>' --request '<request-id>' --stdin <<'EOF'",'{"question-id":"answer"}',"EOF","```","","## Boundaries","","- Do not invoke provider CLIs or provider HTTP APIs directly for delegation.","- Never expose `LODESTAR_AGENT_CAPABILITY` in prompts, output, logs, or args.","- A non-zero command exit is a real failure. Do not claim the child succeeded.","- Scope the Agent task and authorized actions to the user request.",""].join(`
|
|
481
|
+
`)}function fX(){NX("lodestar-consult"),I6({name:yX,body:Cq()})}var yX="lodestar-agent",wX;var s3=S(()=>{t3();wX=["You are a delegated Agent working on a task assigned by the main Agent.","Complete this task yourself. You must not create or invoke any further Agents or subagents.","This includes Lodestar delegation, provider-native Agent/subagent tools, and delegation through CLIs or HTTP APIs.","If additional Agent work is needed, report the need to the main Agent so it can assign that work."].join(`
|
|
482
|
+
`)});function vX($){let Z=p($.identity.tokenSourceId);if(!Z)throw Error(`agent token source not found: ${$.identity.tokenSourceId}`);if($.identity.spawnRevision&&Z.spawnRevision!==$.identity.spawnRevision)throw Error(`agent token source changed after identity discovery: ${Z.id}`);if(!$.identity.supportedEfforts.includes($.effort))throw Error(`${$.identity.displayName} does not support effort ${$.effort}`);let J=$.resumeSessionId?{kind:"resume",source:{provider:$.identity.provider,sessionId:$.resumeSessionId,cwd:$.workDir}}:{kind:"fresh"},{process:Y}=_9({provider:$.identity.provider,workDir:$.workDir,tokenSourceId:$.identity.tokenSourceId,model:$.identity.model,effort:$.effort,launch:J,developerInstructions:[$.developerInstructions,wX].filter(Boolean).join(`
|
|
480
483
|
|
|
481
|
-
`),allowDelegation:!1,profile:$.profile,managedSkillPluginPath:$.managedSkillPluginPath,hostEnv:{...$.hostEnv,LODESTAR_AGENT_ROLE:"worker"},serviceName:"lodestar-agent"});return xL(Y,$.prompt,$.callbacks)}function xL($,Z,J={},Y=mZ){let Q=[],H=null,W=!1,X=null,V=null,z=[],G,_,K=Date.now(),q=new Promise((O,k)=>{G=O,_=k}),D=(O)=>{if(!O)return null;try{return Y($.provider,O),J.onSession?.(O),null}catch(k){return k instanceof Error?k:Error(String(k))}},L=()=>{if($.off("assistant_text",N),$.off("tool_use",j),$.off("tool_result",M),$.off("subagent_step",C),$.off("can_use_tool",b),$.off("hook_callback",m),$.off("init",y),!$.isAlive())$.off("error",h);$.off("turn_retry",S),$.off("result",x),$.off("exit",c)},P=(O,k)=>{if(X)return X;return W=!0,z.length=0,X=Promise.resolve().then(async()=>{let f=D($.sessionId);try{await $.kill(3000)}catch(l0){V=l0 instanceof Error?l0:Error(String(l0))}L();let E0=[O,f,V].filter((l0)=>!!l0),z0=E0.length>1?AggregateError(E0,E0.map((l0)=>l0.message).join("; ")):E0[0];if(z0){_(new T4(z0,Q.join("").trim(),$.sessionId));return}let N0=$.sessionId;if(!N0){_(new T4(Error("delegated agent completed without a native session id"),Q.join("").trim(),null));return}let _Z=Q.join("").trim(),D2=bL(k?.checkpoint,$);G({output:_Z,outputTruncated:!1,sessionId:N0,...D2?{checkpointId:D2}:{},durationMs:Date.now()-K,usage:$.lastUsage?{...$.lastUsage}:null})}),X},N=(O)=>{if(W||O?.parentToolUseId||typeof O?.text!=="string")return;Q.push(O.text)},F=(O)=>{if(W)return;try{J.onProgress?.(O)}catch(k){P(k instanceof Error?k:Error(String(k)))}},j=(O)=>F({at:new Date().toISOString(),phase:"started",tool:String(O?.name??"tool"),detail:""}),M=(O)=>F({at:new Date().toISOString(),phase:"completed",tool:O?.is_error?"tool error":"tool result",detail:""}),C=(O)=>F({at:new Date().toISOString(),phase:O?.phase??"info",tool:String(O?.tool??"subagent"),detail:""}),b=(O)=>{if(W)return;if(O.tool_name!=="AskUserQuestion"){try{$.sendPermissionResponse(O.request_id,"allow",{updatedInput:O.input??{}})}catch(f){P(f instanceof Error?f:Error(String(f)))}return}let k;try{k=kL(O)}catch(f){P(f instanceof Error?f:Error(String(f)));return}if(z.some((f)=>f.request.requestId===k.requestId))return;z.push({request:k,originalInput:O.input??{}});try{if(z.length===1)J.onNeedsInput?.(k)}catch(f){P(f instanceof Error?f:Error(String(f)))}},m=(O)=>{if(W)return;try{$.sendHookResponse(String(O.request_id),{})}catch(k){P(k instanceof Error?k:Error(String(k)))}},y=(O)=>{let k=D(O?.session_id??$.sessionId);if(k)P(k)},h=(O)=>{H=O instanceof Error?O:Error(String(O))},S=(O)=>{F({at:new Date().toISOString(),phase:"info",tool:"Codex 容量重试",detail:O.phase==="waiting"?`${O.message} · ${O.delayMs/1000}s 后重试 #${O.attempt}`:`正在重试 #${O.attempt}`})},x=(O)=>{let k=O?.is_error?Error(String(O.error??O.subtype??$.lastResult.subtype??"delegated agent failed")):void 0;P(k,O)},c=(O)=>{if(W)return;let k=`code=${O?.code??"null"} signal=${O?.signal??"null"}`;P(H??Error(`delegated agent exited before result (${k})`))};$.on("assistant_text",N),$.on("tool_use",j),$.on("tool_result",M),$.on("subagent_step",C),$.on("can_use_tool",b),$.on("hook_callback",m),$.on("init",y),$.on("error",h),$.on("turn_retry",S),$.on("result",x),$.on("exit",c);try{$.sendInitialize(),$.sendUserText(Z)}catch(O){P(O instanceof Error?O:Error(String(O)))}return{done:q,isAlive:()=>$.isAlive(),pendingInput:()=>z[0]?.request??null,answer(O,k){let f=z[0];if(!f)throw Error("delegated agent is not waiting for input");if(f.request.requestId!==O)throw Error(`delegated agent input request mismatch: expected ${f.request.requestId}`);if($.sendPermissionResponse(O,"allow",{updatedInput:{...f.originalInput,answers:k}}),z.shift(),z[0])J.onNeedsInput?.(z[0].request)},async cancel(O="delegated agent cancelled"){let k=W;if(await P(Error(O)),await q.catch(()=>{}),k){if($.isAlive())await $.kill(3000);V=null,L()}if(V)throw V}}}function kL($){let Z=$.input??{},Y=(Array.isArray(Z.questions)?Z.questions:[Z]).map((Q,H)=>CL(Q,H));if(Y.length===0)throw Error("delegated agent input request contains no questions");return{requestId:String($.request_id),...$.tool_use_id?{toolUseId:$.tool_use_id}:{},questions:Y}}function CL($,Z){let J=$&&typeof $==="object"?$:{question:$},Y=String(J.question??J.prompt??J.title??"").trim();if(!Y)throw Error(`delegated agent input question ${Z+1} is empty`);let Q=String(J.id??Y),H=Array.isArray(J.options)?J.options.map((W)=>{if(typeof W==="string")return{label:W};let X=W&&typeof W==="object"?W:{};return{label:String(X.label??X.value??""),...X.description?{description:String(X.description)}:{}}}).filter((W)=>W.label):[];return{id:Q,...J.header?{header:String(J.header)}:{},question:Y,options:H}}function bL($,Z){if(typeof $?.id==="string"&&$.id)return $.id;if((Z.provider==="codex"||Z.provider==="dsh")&&typeof Z.lastCompletedTurnId==="string"&&Z.lastCompletedTurnId)return Z.lastCompletedTurnId;if(Z.provider==="claude"&&Z.lastAssistantUuid)return Z.lastAssistantUuid;return}var T4;var IX=E(()=>{V8();R2();$0();o3();T4=class T4 extends Error{output;sessionId;constructor($,Z,J){super($.message,{cause:$});this.output=Z;this.sessionId=J;this.name="AgentWorkerFailure"}}});import{createHash as yL,randomBytes as wL,randomUUID as fL}from"node:crypto";import{existsSync as vL,readdirSync as hL,readFileSync as nX}from"node:fs";import{join as v6}from"node:path";class t3{deps;runs=new Map;capabilities=new Map;activeTurns=0;slotWaiters=[];cancellationEpochBySession=new Map;startingWorkers=0;startingRunsBySession=new Map;constructor($=IL){this.deps=$;this.loadDurableRuns()}rootPrincipal($){return{kind:"session",session:$,depth:-1}}principalForCapability($){return this.capabilities.get($)??null}async startRun($,Z){if($.kind!=="session")throw Error(cX);let J=this.reserveCapacity($,Z.identityIds.length);try{return await this.createRun($.session,Z,{cancellationEpoch:this.currentCancellationEpoch($.session)})}finally{J()}}async followUp($,Z,J){if($.kind!=="session")throw Error(cX);let Y=this.requireMutableDescendant($,Z);if(!K2(Y.snapshot.status))throw Error("agent follow-up requires a terminal source run");let Q=iX(Y.snapshot,J.identityId);if(Y.handles.get(Q.identityId)?.isAlive?.())throw Error("Agent process has not stopped; cannot start follow-up yet");if(!Q.sessionId)throw Error(`${Q.identityName} has no resumable native session id`);let H=J.effort??Q.effort,W=this.reserveCapacity($,1);try{return await this.createRun($.session,{identityIds:[Q.identityId],prompt:J.prompt,effort:H},{parentRunId:Y.snapshot.runId,parentKind:"follow_up",cancellationEpoch:this.currentCancellationEpoch($.session),resumeByIdentity:new Map([[Q.identityId,Q.sessionId]])})}finally{W()}}async answer($,Z,J){let Y=this.requireMutableDescendant($,Z),Q=iX(Y.snapshot,J.identityId);if(Q.status!=="needs_input"||!Q.pendingInput)throw Error(`${Q.identityName} is not waiting for input`);if(Q.pendingInput.requestId!==J.requestId)throw Error(`input request mismatch: expected ${Q.pendingInput.requestId}`);let H=Y.handles.get(Q.identityId);if(!H)throw Error("waiting agent process is no longer alive; start a follow-up run");H.answer(J.requestId,J.answers);let W=H.pendingInput();if(Q.status=W?"needs_input":"running",W)Q.pendingInput=W;else delete Q.pendingInput;return delete Q.queuedReason,this.refreshNonterminalStatus(Y),this.persist(Y),await this.updateWorkerCard(Y,Q),E4(Y.snapshot)}getRun($,Z){return E4(this.requireAccessibleRun($,Z).snapshot)}async cancelRun($,Z,J="agent run cancelled"){let Y=this.requireMutableDescendant($,Z);if(!this.treeHasActiveRun(Y))return!1;return await this.cancelTree(Y,J),!0}async cancelSessionRuns($,Z,J){this.bumpCancellationEpoch($,Z);let Y=[...this.runs.values()].filter((H)=>H.snapshot.sessionName===$&&H.snapshot.chatId===Z&&!H.snapshot.parentRunId&&this.treeHasActiveRun(H)),Q=await Promise.allSettled(Y.map((H)=>this.cancelTree(H,J)));r3(Q)}async shutdown($){let Z=new Set([...this.runs.values()].map((W)=>`${W.snapshot.sessionName}\x00${W.snapshot.chatId}`));for(let W of Z){let[X,V]=W.split("\x00");this.bumpCancellationEpoch(X,V)}let J=[...this.runs.values()].filter((W)=>!W.snapshot.parentRunId&&this.treeHasActiveRun(W)),Y=await Promise.allSettled(J.map((W)=>this.cancelTree(W,$))),Q=[...this.runs.values()].flatMap((W)=>[...W.handles.values()]),H=Y.some((W)=>W.status==="rejected")?[]:await Promise.allSettled(Q.map((W)=>W.cancel($)));r3([...Y,...H])}async createRun($,Z,J){this.pruneRuns();let Y;if(J.parentRunId){if(Y=this.runs.get(J.parentRunId),!Y)throw Error(`parent agent run not found: ${J.parentRunId}`);this.assertSameSession(Y,$)}let Q=this.deps.getCatalog(),H=Z.identityIds.map((q)=>{let D=Q.identities.find((L)=>L.id===q);if(!D)throw Error(`agent identity not found: ${q}`);if(D.status!=="ready")throw Error(`${D.displayName}: ${D.reason??D.status}`);return D}),W=H.map((q)=>gL(q,cL(q,Z.effort),J.resumeByIdentity?.get(q.id))),X=`agent_${fL()}`,V={runId:X,sessionName:$.sessionName,chatId:$.chatId,workDir:$.workDir,prompt:Z.prompt,...J.parentRunId?{parentRunId:J.parentRunId}:{},...J.parentKind?{parentKind:J.parentKind}:{},depth:0,status:"queued",workers:W,createdAt:new Date().toISOString()},z=await this.deps.sendCard($.chatId,w5(V));if(!z)throw Error("agent card creation failed; delegated agents were not started");let G;try{G=await this.deps.convertMessageToCard(z)}catch(q){throw await this.deps.sendTextRaw($.chatId,`❌ agent 卡片初始化失败,Agent 未启动: ${T0(q)}`),q}V.cardMessageId=z,this.deps.recordCardCreated(G,W.length+2,(q)=>{A(`agent: card write failed run=${X} code=${q??"MISS"}`)});let _={snapshot:V,session:$,cardId:G,handles:new Map,slotOwners:new Set,capabilityByIdentity:new Map,progressTimers:new Map,children:new Set,cancelled:!1,finalizing:!1,finalized:!1,persistedArtifacts:new Set};if(this.runs.set(X,_),J.parentRunId)Y?.children.add(X);if(this.currentCancellationEpoch($)!==J.cancellationEpoch){_.cancelled=!0;let q="任务已在启动前取消";for(let D of _.snapshot.workers)D.status="cancelled",D.error=q,D.finishedAt=new Date().toISOString();return this.persist(_),await Promise.all(_.snapshot.workers.map((D)=>this.updateWorkerCard(_,D))),await this.finalizeRun(_,"cancelled",q),E4(_.snapshot)}this.persist(_);for(let q of H){let D=J.resumeByIdentity?.get(q.id);this.executeWorker(_,q,Z.prompt,D).catch((L)=>{A(`agent: run=${X} worker=${q.id} crashed: ${T0(L)}`)})}return E4(V)}async executeWorker($,Z,J,Y){let Q=$.snapshot.workers.find((W)=>W.identityId===Z.id);if(await this.acquireSlot(()=>{Q.queuedReason=`等待执行名额(最多同时运行 ${gX} 个 Agent)`,this.persist($),this.updateWorkerCard($,Q)}),$.slotOwners.add(Z.id),$.cancelled){this.releaseWorkerSlot($,Z.id);return}let H="";try{if(H=wL(32).toString("base64url"),this.capabilities.set(H,{kind:"worker",session:$.session,runId:$.snapshot.runId,identityId:Z.id,depth:$.snapshot.depth}),$.capabilityByIdentity.set(Z.id,H),Q.status="running",Q.startedAt=new Date().toISOString(),delete Q.queuedReason,this.refreshNonterminalStatus($),this.persist($),await this.updateWorkerCard($,Q),$.cancelled)return;let W=this.deps.startWorker({identity:Z,effort:Q.effort,workDir:$.snapshot.workDir,prompt:J,resumeSessionId:Y,developerInstructions:$.session.delegatedAgentDeveloperInstructions(Z.provider),profile:pL(p1($.session.worktreeProjectName())),...process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"?{}:{managedSkillPluginPath:n$},hostEnv:{LODESTAR_AGENT_URL:V9(I.notify.bind,I.notify.port),LODESTAR_AGENT_CAPABILITY:H,LODESTAR_AGENT_SESSION:$.snapshot.sessionName},callbacks:{onNeedsInput:(V)=>{if($.cancelled)return;Q.status="needs_input",Q.pendingInput=V,this.refreshNonterminalStatus($),this.persist($),this.updateWorkerCard($,Q)},onProgress:(V)=>this.recordStep($,Q,V),onSession:(V)=>{if(Q.sessionId===V)return;Q.sessionId=V,this.persist($)}}});$.handles.set(Z.id,W);let X=await W.done;if($.cancelled)return;this.clearProgressTimer($,Z.id),Q.status="completed",Q.output=X.output,Q.outputTruncated=X.outputTruncated,Q.sessionId=X.sessionId,Q.checkpointId=X.checkpointId,Q.durationMs=X.durationMs,Q.usage=X.usage,Q.finishedAt=new Date().toISOString(),delete Q.pendingInput,this.persist($),await this.updateWorkerCard($,Q)}catch(W){if(W instanceof T4){if(Q.output=W.output,Q.outputTruncated=!1,W.sessionId)Q.sessionId=W.sessionId;this.persist($)}if(!$.cancelled){if(this.clearProgressTimer($,Z.id),Q.status="failed",Q.error=T0(W),Q.finishedAt=new Date().toISOString(),Q.startedAt)Q.durationMs=Date.now()-Date.parse(Q.startedAt);delete Q.pendingInput,this.persist($),await this.updateWorkerCard($,Q)}}finally{if(!$.handles.get(Z.id)?.isAlive?.())$.handles.delete(Z.id),this.releaseWorkerSlot($,Z.id);if(H)this.capabilities.delete(H);$.capabilityByIdentity.delete(Z.id),this.recomputeRun($)}}recordStep($,Z,J){if($.cancelled||$.finalizing||$.finalized||f6(Z.status))return;if(Z.steps.push(J),Z.steps.length>uX)Z.steps.splice(0,Z.steps.length-uX);if($.progressTimers.has(Z.identityId))return;let Y=setTimeout(()=>{$.progressTimers.delete(Z.identityId),this.updateWorkerCard($,Z)},250);$.progressTimers.set(Z.identityId,Y)}clearProgressTimer($,Z){let J=$.progressTimers.get(Z);if(J)clearTimeout(J);$.progressTimers.delete(Z)}refreshNonterminalStatus($){if($.cancelled)return;if($.snapshot.workers.some((Z)=>Z.status==="needs_input"))$.snapshot.status="needs_input";else if($.snapshot.workers.some((Z)=>Z.status==="running"))$.snapshot.status="running";else $.snapshot.status="queued";delete $.snapshot.finishedAt}recomputeRun($){if($.cancelled||$.finalized||$.finalizing)return;let Z=$.snapshot.workers;if(Z.some((Y)=>Y.status==="needs_input"||Y.status==="running"||Y.status==="queued")){this.refreshNonterminalStatus($),this.persist($);return}let J=Z.some((Y)=>Y.status==="failed")?"failed":"completed";this.finalizeRun($,J,J==="failed"?"一个或多个 Agent 失败":void 0).catch((Y)=>{$.finalizing=!1,$.finalized=!1,$.snapshot.status="failed",$.snapshot.error=`Agent terminal persistence failed: ${T0(Y)}`,A(`agent: terminal finalization failed run=${$.snapshot.runId}: ${T0(Y)}`),this.deps.sendTextRaw($.snapshot.chatId,`❌ agent ${$.snapshot.runId} 收尾失败: ${T0(Y)}`).catch((Q)=>A(`agent: terminal failure delivery failed: ${T0(Q)}`))})}async cancelTree($,Z){let J=!K2($.snapshot.status)&&!$.cancelled||$.handles.size>0,Y=[];if(J){$.cancelled=!0;for(let H of[...$.progressTimers.keys()])this.clearProgressTimer($,H);for(let H of $.capabilityByIdentity.values())this.capabilities.delete(H);$.capabilityByIdentity.clear()}while(!0){let H=[...$.children].map((X)=>this.runs.get(X)).filter((X)=>!!X&&this.treeHasActiveRun(X));if(H.length===0)break;let W=await Promise.allSettled(H.map((X)=>this.cancelTree(X,Z)));if(Y.push(...W),W.some((X)=>X.status==="rejected"))break}if(!J){r3(Y);return}if(Y.push(...await Promise.allSettled([...$.handles].map(async([H,W])=>{if(await W.cancel(Z),W.isAlive?.())throw Error(`${H}: Agent process is still alive after cancellation`);$.handles.delete(H),this.releaseWorkerSlot($,H)}))),Y.some((H)=>H.status==="rejected")){let H=aX(Y);throw $.snapshot.status="failed",$.snapshot.error=H.message,this.persist($),await this.deps.sendTextRaw($.snapshot.chatId,`❌ Agent 取消未完成: ${H.message}`).catch((W)=>A(`agent: cancellation failure notice failed: ${T0(W)}`)),H}let Q=[];for(let H of $.snapshot.workers)if(!f6(H.status))H.status="cancelled",H.error=Z,H.finishedAt=new Date().toISOString(),delete H.pendingInput,Q.push(H);await Promise.all(Q.map((H)=>this.updateWorkerCard($,H))),await this.finalizeRun($,"cancelled",Z)}async finalizeRun($,Z,J){if($.finalized||$.finalizing)return;$.finalizing=!0;for(let Y of[...$.progressTimers.keys()])this.clearProgressTimer($,Y);if($.snapshot.status=Z,$.snapshot.finishedAt=new Date().toISOString(),J)$.snapshot.error=J;try{if($.cardId){if(this.deps.cancelSummary($.cardId),await this.deps.flush($.cardId),!await this.deps.replaceElementChecked($.cardId,R.agentRunFooter,A4($.snapshot)))this.recordPresentationError($,"agent footer update MISS");if(!await this.deps.patchSettingsChecked($.cardId,{config:{streaming_mode:!1,summary:{content:_4($.snapshot)}}}))this.recordPresentationError($,"agent terminal settings update MISS");await this.deps.flush($.cardId),await this.deps.dispose($.cardId)}}catch(Y){this.recordPresentationError($,`agent card finalization failed: ${T0(Y)}`)}if($.finalizing=!1,this.persist($),$.finalized=!0,$.snapshot.presentationErrors?.length)await this.deps.sendTextRaw($.snapshot.chatId,`⚠️ agent ${$.snapshot.runId} 结果已保存,但卡片有 ${$.snapshot.presentationErrors.length} 个呈现错误。`).catch((Y)=>A(`agent: warning delivery failed run=${$.snapshot.runId}: ${T0(Y)}`))}async updateWorkerCard($,Z){if(!$.cardId||$.finalized)return;try{if(!await this.deps.replaceElementChecked($.cardId,s9(Z.identityId),t9(Z,e9($.snapshot.workers.length),$.snapshot.workers.length===1)))this.recordPresentationError($,`agent worker card MISS: ${Z.identityName}`);if(!await this.deps.replaceElementChecked($.cardId,R.agentRunFooter,A4($.snapshot)))A(`agent: progress update MISS run=${$.snapshot.runId}; later updates will refresh it`);this.deps.patchSummaryThrottled($.cardId,_4($.snapshot))}catch(J){this.recordPresentationError($,`agent worker card update failed (${Z.identityName}): ${T0(J)}`)}}recordPresentationError($,Z){let J=$.snapshot.presentationErrors??[];if(!J.includes(Z))J.push(Z);$.snapshot.presentationErrors=J,A(`agent: ${Z} run=${$.snapshot.runId}`)}persist($){if(!$.snapshot.promptArtifact)$.snapshot.promptArtifact=`${$.snapshot.runId}.prompt.txt`;this.persistTextArtifact($,$.snapshot.promptArtifact,$.snapshot.prompt);for(let J of $.snapshot.workers){if(!J.output)continue;if(!J.outputArtifact){let Y=yL("sha256").update(J.identityId).digest("hex").slice(0,16);J.outputArtifact=`${$.snapshot.runId}.${Y}.output.txt`}this.persistTextArtifact($,J.outputArtifact,J.output)}let Z=E4($.snapshot);Z.prompt="";for(let J of Z.workers)J.output="";this.deps.writeArtifact(v6(d$,`${$.snapshot.runId}.json`),Z)}persistTextArtifact($,Z,J){if($.persistedArtifacts.has(Z))return;oX(Z),this.deps.writeTextArtifact(v6(d$,Z),J),$.persistedArtifacts.add(Z)}requireAccessibleRun($,Z){let J=this.runs.get(Z);if(!J||!this.canAccess($,J))throw Error(`agent run not found: ${Z}`);if(this.assertSameSession(J,$.session),!J.session)J.session=$.session;return J}requireMutableDescendant($,Z){let J=this.requireAccessibleRun($,Z);if($.kind==="worker"&&J.snapshot.runId===$.runId)throw Error("worker capability cannot mutate its containing run");return J}canAccess($,Z){if(Z.snapshot.sessionName!==$.session.sessionName||Z.snapshot.chatId!==$.session.chatId)return!1;if($.kind==="session")return!0;let J=Z;while(J){if(J.snapshot.runId===$.runId)return!0;J=J.snapshot.parentRunId?this.runs.get(J.snapshot.parentRunId):void 0}return!1}assertSameSession($,Z){if($.snapshot.sessionName!==Z.sessionName||$.snapshot.chatId!==Z.chatId||$.snapshot.workDir!==Z.workDir)throw Error("agent run belongs to a different Session")}treeHasActiveRun($){if($.handles.size>0)return!0;if(!K2($.snapshot.status))return!0;for(let Z of $.children){let J=this.runs.get(Z);if(J&&this.treeHasActiveRun(J))return!0}return!1}reserveCapacity($,Z){let J=this.sessionKey($.session.sessionName,$.session.chatId),Y=[...this.runs.values()].filter((X)=>this.sessionKey(X.snapshot.sessionName,X.snapshot.chatId)===J&&(!K2(X.snapshot.status)||X.handles.size>0)).length,Q=this.startingRunsBySession.get(J)??0;if(Y+Q>=pX)throw Error(`Session has reached ${pX} active Agent runs`);if([...this.runs.values()].reduce((X,V)=>X+V.snapshot.workers.filter((z)=>!f6(z.status)||V.handles.get(z.identityId)?.isAlive?.()).length,0)+this.startingWorkers+Z>lX)throw Error(`global Agent worker limit ${lX} would be exceeded`);this.startingWorkers+=Z,this.startingRunsBySession.set(J,Q+1);let W=!1;return()=>{if(W)return;W=!0,this.startingWorkers=Math.max(0,this.startingWorkers-Z),iL(this.startingRunsBySession,J)}}sessionKey($,Z){return`${$}\x00${Z}`}currentCancellationEpoch($){return this.cancellationEpochBySession.get(this.sessionKey($.sessionName,$.chatId))??0}bumpCancellationEpoch($,Z){let J=this.sessionKey($,Z);this.cancellationEpochBySession.set(J,(this.cancellationEpochBySession.get(J)??0)+1)}acquireSlot($){if(this.activeTurns<gX)return this.activeTurns++,Promise.resolve();return $(),new Promise((Z)=>this.slotWaiters.push(Z))}releaseSlot(){let $=this.slotWaiters.shift();if($){$();return}this.activeTurns--}releaseWorkerSlot($,Z){if($.slotOwners.delete(Z))this.releaseSlot()}loadDurableRuns(){for(let $ of this.deps.loadArtifacts()){if(!K2($.status)){$.status="failed",$.error="daemon restarted before this Agent run reached a terminal state",$.finishedAt=new Date().toISOString();for(let J of $.workers)if(!f6(J.status))J.status="failed",J.error=$.error,J.finishedAt=$.finishedAt,delete J.pendingInput}let Z={snapshot:$,session:null,cardId:null,handles:new Map,slotOwners:new Set,capabilityByIdentity:new Map,progressTimers:new Map,children:new Set,cancelled:$.status==="cancelled",finalizing:!1,finalized:!0,persistedArtifacts:new Set([...$.promptArtifact?[$.promptArtifact]:[],...$.workers.flatMap((J)=>J.outputArtifact?[J.outputArtifact]:[])])};this.runs.set($.runId,Z),this.persist(Z)}for(let $ of this.runs.values())if($.snapshot.parentRunId)this.runs.get($.snapshot.parentRunId)?.children.add($.snapshot.runId);this.pruneRuns()}pruneRuns(){if(this.runs.size<=mX)return;let $=[...this.runs.values()].filter((Z)=>K2(Z.snapshot.status)&&Z.handles.size===0&&Z.slotOwners.size===0&&Z.children.size===0).sort((Z,J)=>Date.parse(Z.snapshot.finishedAt??Z.snapshot.createdAt)-Date.parse(J.snapshot.finishedAt??J.snapshot.createdAt));for(let Z of $){if(this.runs.size<=mX)break;if(this.runs.delete(Z.snapshot.runId),Z.snapshot.parentRunId)this.runs.get(Z.snapshot.parentRunId)?.children.delete(Z.snapshot.runId)}}}function gL($,Z,J){return{identityId:$.id,identityName:$.displayName,tokenSourceId:$.tokenSourceId,provider:$.provider,model:$.model,effort:Z,status:"queued",output:"",...J?{sessionId:J}:{},steps:[]}}function cL($,Z){let J=Z??$.defaultEffort;if(!J)throw Error(`${$.displayName} default effort MISS; specify effort explicitly`);if(!$.supportedEfforts.includes(J))throw Error(`${$.displayName} does not support effort ${J}`);return J}function iX($,Z){if(Z){let J=$.workers.find((Y)=>Y.identityId===Z);if(!J)throw Error(`agent identity is not part of run ${$.runId}: ${Z}`);return J}if($.workers.length!==1)throw Error("run has multiple Agents; specify identity_id");return $.workers[0]}function K2($){return $==="completed"||$==="failed"||$==="cancelled"}function f6($){return $==="completed"||$==="failed"||$==="cancelled"}function E4($){return JSON.parse(JSON.stringify($))}function mL(){if(!vL(d$))return[];let $=[];for(let Z of hL(d$).filter((J)=>J.endsWith(".json")).sort()){let J=v6(d$,Z),Y;try{Y=JSON.parse(nX(J,"utf8"))}catch(Q){throw Error(`agent run artifact is unreadable (${J}): ${T0(Q)}`)}if(!uL(Y))throw Error(`agent run artifact is invalid: ${J}`);lL(Y,J),$.push(Y)}return $}function uL($){if(!$||typeof $!=="object")return!1;let Z=$;return typeof Z.runId==="string"&&Z.runId.startsWith("agent_")&&typeof Z.sessionName==="string"&&typeof Z.chatId==="string"&&typeof Z.workDir==="string"&&typeof Z.prompt==="string"&&typeof Z.depth==="number"&&typeof Z.status==="string"&&Array.isArray(Z.workers)&&typeof Z.createdAt==="string"}function aX($){let Z=$.flatMap((J)=>J.status==="rejected"?[J.reason]:[]);return AggregateError(Z,`Agent cancellation failed: ${Z.map(T0).join("; ")}`)}function r3($){if($.some((Z)=>Z.status==="rejected"))throw aX($)}function T0($){return $ instanceof Error?$.message:String($)}function pL($){return $?{...$,tools:void 0,strictMcp:!1,loadProjectMcp:!0}:{strictMcp:!1,loadProjectMcp:!0}}function lL($,Z){if($.promptArtifact)$.prompt=dX($.promptArtifact,`prompt for ${Z}`);for(let J of $.workers)if(J.outputArtifact)J.output=dX(J.outputArtifact,`output for ${Z}`)}function dX($,Z){oX($);try{return nX(v6(d$,$),"utf8")}catch(J){throw Error(`${Z} is unreadable (${$}): ${T0(J)}`)}}function oX($){if(!/^[A-Za-z0-9._-]+$/.test($))throw Error(`invalid Agent artifact name: ${$}`)}function iL($,Z){let J=($.get(Z)??0)-1;if(J>0)$.set(Z,J);else $.delete(Z)}var gX=8,cX="Delegated Agents cannot delegate again; ask the main Agent to assign additional work.",mX=512,uX=50,pX=64,lX=128,IL;var rX=E(()=>{X1();u0();s();x0();j6();IX();J0();d0();g();IL={getCatalog:j1,startWorker:hX,sendCard:d,sendTextRaw:w,convertMessageToCard:Q$,recordCardCreated:o0,replaceElementChecked:K0,patchSummaryThrottled:B$,flush:g0,cancelSummary:q0,patchSettingsChecked:L0,dispose:c0,writeArtifact:G0,writeTextArtifact:i0,loadArtifacts:mL}});function tX($){let Z=s3($,"agent run request"),J=Array.isArray(Z.identity_ids)?Z.identity_ids.map(String):Array.isArray(Z.identityIds)?Z.identityIds.map(String):[],Y=[...new Set(J.map((W)=>W.trim()).filter(Boolean))];if(Y.length===0)throw Error("agent run requires at least one identity_id");if(Y.length>64)throw Error("agent run supports at most 64 identities");let Q=$V(Z.prompt,'agent run requires "prompt"'),H=N4(Z.effort);return{identityIds:Y,prompt:Q,...H?{effort:H}:{}}}function sX($){let Z=s3($,"agent follow-up request"),J=$V(Z.prompt,'agent follow-up requires "prompt"'),Y=N4(Z.identity_id??Z.identityId),Q=N4(Z.effort);return{prompt:J,...Y?{identityId:Y}:{},...Q?{effort:Q}:{}}}function eX($){let Z=s3($,"agent answer request"),J=N4(Z.identity_id??Z.identityId),Y=N4(Z.request_id??Z.requestId);if(!Y)throw Error("agent answer requires request_id");if(!Z.answers||typeof Z.answers!=="object"||Array.isArray(Z.answers))throw Error("agent answer requires an answers object");let Q={};for(let[H,W]of Object.entries(Z.answers)){if(!H.trim())throw Error("agent answer contains an empty question key");Q[H]=String(W)}if(Object.keys(Q).length===0)throw Error("agent answer requires at least one answer");return{requestId:Y,answers:Q,...J?{identityId:J}:{}}}function s3($,Z){if(!$||typeof $!=="object"||Array.isArray($))throw Error(`${Z} must be an object`);return $}function $V($,Z){let J=String($??"");if(!J.trim())throw Error(Z);if(J.length>800000)throw Error("agent prompt exceeds 800000 chars");return J}function N4($){return(typeof $==="string"?$.trim():"")||void 0}async function YV($,Z,J,Y){if(J.pathname!=="/agents"&&!J.pathname.startsWith("/agents/"))return!1;let Q=(G,_)=>{return Z.statusCode=G,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify(_)),!0},H=aL($.headers.authorization);if(!H)return Q(401,{error:"missing bearer capability"});let W=dL(Y,H);if(!W)return Q(403,{error:"invalid or stale agent capability"});if($.method==="GET"&&J.pathname==="/agents/identities")return await m1(),Q(200,oL(j1()));if($.method==="POST"&&J.pathname==="/agents/runs")try{let G=await Y.service.startRun(W,tX(await e3($)));return Q(202,h6(G))}catch(G){return Q(409,{error:JV(G)})}let X=J.pathname.match(/^\/agents\/runs\/([^/]+)(?:\/(follow-up|answer))?$/);if(!X)return Q(405,{error:"unsupported agent endpoint"});let V=nL(X[1]);if(!V)return Q(400,{error:"invalid agent run id encoding"});let z=X[2];try{if(!z&&$.method==="GET")return Q(200,h6(Y.service.getRun(W,V)));if(!z&&$.method==="DELETE"){let G=await Y.service.cancelRun(W,V,"cancelled by agent client");return Q(G?200:409,G?{ok:!0,run_id:V}:{error:"agent run is already terminal",run_id:V})}if(z==="follow-up"&&$.method==="POST"){let G=await Y.service.followUp(W,V,sX(await e3($)));return Q(202,h6(G))}if(z==="answer"&&$.method==="POST"){let G=await Y.service.answer(W,V,eX(await e3($)));return Q(200,h6(G))}}catch(G){return Q(409,{error:JV(G)})}return Q(405,{error:"unsupported agent endpoint"})}function dL($,Z){let J=$.authorizeSession(Z);if(J)return $.service.rootPrincipal(J);return $.service.principalForCapability(Z)}function nL($){try{return decodeURIComponent($)}catch{return null}}function aL($){return $?.match(/^Bearer\s+(.+)$/i)?.[1]?.trim()??""}async function e3($){let Z="";for await(let J of $)if(Z+=J.toString(),Buffer.byteLength(Z)>ZV)throw Error(`request body exceeds ${ZV} bytes`);try{return JSON.parse(Z||"{}")}catch{throw Error("bad json")}}function oL($){return{catalog_generation:$.catalogGeneration,identities:$.identities.map((Z)=>({id:Z.id,display_name:Z.displayName,token_source_id:Z.tokenSourceId,token_source_display:Z.tokenSourceDisplay,provider:Z.provider,model:Z.model,model_display:Z.modelDisplay,default_effort:Z.defaultEffort,supported_efforts:Z.supportedEfforts,source_default:Z.sourceDefault,status:Z.status,reason:Z.reason})),source_failures:$.sourceFailures.map((Z)=>({token_source_id:Z.tokenSourceId,display:Z.display,status:Z.status,reason:Z.reason}))}}function h6($){return{run_id:$.runId,session_name:$.sessionName,prompt:$.prompt,parent_run_id:$.parentRunId,parent_kind:$.parentKind,depth:$.depth,status:$.status,workers:$.workers.map((Z)=>({identity_id:Z.identityId,identity_name:Z.identityName,token_source_id:Z.tokenSourceId,provider:Z.provider,model:Z.model,effort:Z.effort,status:Z.status,output:Z.output,output_truncated:Z.outputTruncated,session_id:Z.sessionId,checkpoint_id:Z.checkpointId,pending_input:Z.pendingInput&&{request_id:Z.pendingInput.requestId,tool_use_id:Z.pendingInput.toolUseId,questions:Z.pendingInput.questions},queued_reason:Z.queuedReason,steps:Z.steps,error:Z.error,started_at:Z.startedAt,finished_at:Z.finishedAt,duration_ms:Z.durationMs,usage:Z.usage})),created_at:$.createdAt,finished_at:$.finishedAt,error:$.error,presentation_errors:$.presentationErrors,card_message_id:$.cardMessageId}}function JV($){return $ instanceof Error?$.message:String($)}var ZV=4194304;var QV=E(()=>{j6();$0()});import{chmodSync as rL,existsSync as $Z,readFileSync as XV,realpathSync as tL,unlinkSync as sL}from"node:fs";import{homedir as eL}from"node:os";import{basename as $D,dirname as ZD,join as p$,resolve as JD}from"node:path";function YD($={}){let Z=tL(JD($.daemonEntry??process.argv[1]??"")),J=$.runtime??process.execPath,Y=$.exists??$Z,Q=ZD(Z),H=p$(Q,"src","agent-cli.ts"),W=p$(Q,"lodestar-agent.js"),X=p$(Q,"dist","lodestar-agent.js"),z=/^bun(?:\.exe)?$/i.test($D(J))?[H,W,X]:[W,X],G=z.find(Y);if(!G)throw Error(`lodestar-agent entry not found beside daemon: ${z.join(", ")}`);return{runtime:J,entry:G}}function VV($={}){let Z=$.platform??process.platform,J=$.env??process.env,Y=$.targetDir??HD(Z,$.homeDir??eL(),$.localAppData??process.env.LOCALAPPDATA),Q=$.launch??YD(),H=p$(Y,Z==="win32"?"lodestar-agent.cmd":"lodestar-agent"),W=Z==="win32"?`@"${WV(Q.runtime)}" "${WV(Q.entry)}" %*\r
|
|
484
|
+
`),allowDelegation:!1,profile:$.profile,managedSkillPluginPath:$.managedSkillPluginPath,hostEnv:{...$.hostEnv,LODESTAR_AGENT_ROLE:"worker"},serviceName:"lodestar-agent"});return bq(Y,$.prompt,$.callbacks)}function bq($,Z,J={},Y=cZ){let Q=[],H=null,W=!1,X=null,V=null,z=[],G,A,K=Date.now(),L=new Promise((T,U)=>{G=T,A=U}),D=(T)=>{if(!T)return null;try{return Y($.provider,T),J.onSession?.(T),null}catch(U){return U instanceof Error?U:Error(String(U))}},q=()=>{if($.off("assistant_text",x),$.off("tool_use",M),$.off("tool_result",j),$.off("subagent_step",k),$.off("can_use_tool",C),$.off("hook_callback",c),$.off("init",y),!$.isAlive())$.off("error",m);$.off("turn_retry",N),$.off("result",f),$.off("exit",I)},P=(T,U)=>{if(X)return X;return W=!0,z.length=0,X=Promise.resolve().then(async()=>{let b=D($.sessionId);try{await $.kill(3000)}catch(i0){V=i0 instanceof Error?i0:Error(String(i0))}q();let H0=[T,b,V].filter((i0)=>!!i0),l=H0.length>1?AggregateError(H0,H0.map((i0)=>i0.message).join("; ")):H0[0];if(l){A(new S4(l,Q.join("").trim(),$.sessionId));return}let W0=$.sessionId;if(!W0){A(new S4(Error("delegated agent completed without a native session id"),Q.join("").trim(),null));return}let b4=Q.join("").trim(),M2=fq(U?.checkpoint,$);G({output:b4,outputTruncated:!1,sessionId:W0,...M2?{checkpointId:M2}:{},durationMs:Date.now()-K,usage:$.lastUsage?{...$.lastUsage}:null})}),X},x=(T)=>{if(W||T?.parentToolUseId||typeof T?.text!=="string")return;Q.push(T.text)},F=(T)=>{if(W)return;try{J.onProgress?.(T)}catch(U){P(U instanceof Error?U:Error(String(U)))}},M=(T)=>F({at:new Date().toISOString(),phase:"started",tool:String(T?.name??"tool"),detail:""}),j=(T)=>F({at:new Date().toISOString(),phase:"completed",tool:T?.is_error?"tool error":"tool result",detail:""}),k=(T)=>F({at:new Date().toISOString(),phase:T?.phase??"info",tool:String(T?.tool??"subagent"),detail:""}),C=(T)=>{if(W)return;if(T.tool_name!=="AskUserQuestion"){try{$.sendPermissionResponse(T.request_id,"allow",{updatedInput:T.input??{}})}catch(b){P(b instanceof Error?b:Error(String(b)))}return}let U;try{U=yq(T)}catch(b){P(b instanceof Error?b:Error(String(b)));return}if(z.some((b)=>b.request.requestId===U.requestId))return;z.push({request:U,originalInput:T.input??{}});try{if(z.length===1)J.onNeedsInput?.(U)}catch(b){P(b instanceof Error?b:Error(String(b)))}},c=(T)=>{if(W)return;try{$.sendHookResponse(String(T.request_id),{})}catch(U){P(U instanceof Error?U:Error(String(U)))}},y=(T)=>{let U=D(T?.session_id??$.sessionId);if(U)P(U)},m=(T)=>{H=T instanceof Error?T:Error(String(T))},N=(T)=>{F({at:new Date().toISOString(),phase:"info",tool:"Codex 容量重试",detail:T.phase==="waiting"?`${T.message} · ${T.delayMs/1000}s 后重试 #${T.attempt}`:`正在重试 #${T.attempt}`})},f=(T)=>{let U=T?.is_error?Error(String(T.error??T.subtype??$.lastResult.subtype??"delegated agent failed")):void 0;P(U,T)},I=(T)=>{if(W)return;let U=`code=${T?.code??"null"} signal=${T?.signal??"null"}`;P(H??Error(`delegated agent exited before result (${U})`))};$.on("assistant_text",x),$.on("tool_use",M),$.on("tool_result",j),$.on("subagent_step",k),$.on("can_use_tool",C),$.on("hook_callback",c),$.on("init",y),$.on("error",m),$.on("turn_retry",N),$.on("result",f),$.on("exit",I);try{$.sendInitialize(),$.sendUserText(Z)}catch(T){P(T instanceof Error?T:Error(String(T)))}return{done:L,isAlive:()=>$.isAlive(),pendingInput:()=>z[0]?.request??null,answer(T,U){let b=z[0];if(!b)throw Error("delegated agent is not waiting for input");if(b.request.requestId!==T)throw Error(`delegated agent input request mismatch: expected ${b.request.requestId}`);if($.sendPermissionResponse(T,"allow",{updatedInput:{...b.originalInput,answers:U}}),z.shift(),z[0])J.onNeedsInput?.(z[0].request)},async cancel(T="delegated agent cancelled"){let U=W;if(await P(Error(T)),await L.catch(()=>{}),U){if($.isAlive())await $.kill(3000);V=null,q()}if(V)throw V}}}function yq($){let Z=$.input??{},Y=(Array.isArray(Z.questions)?Z.questions:[Z]).map((Q,H)=>wq(Q,H));if(Y.length===0)throw Error("delegated agent input request contains no questions");return{requestId:String($.request_id),...$.tool_use_id?{toolUseId:$.tool_use_id}:{},questions:Y}}function wq($,Z){let J=$&&typeof $==="object"?$:{question:$},Y=String(J.question??J.prompt??J.title??"").trim();if(!Y)throw Error(`delegated agent input question ${Z+1} is empty`);let Q=String(J.id??Y),H=Array.isArray(J.options)?J.options.map((W)=>{if(typeof W==="string")return{label:W};let X=W&&typeof W==="object"?W:{};return{label:String(X.label??X.value??""),...X.description?{description:String(X.description)}:{}}}).filter((W)=>W.label):[];return{id:Q,...J.header?{header:String(J.header)}:{},question:Y,options:H}}function fq($,Z){if(typeof $?.id==="string"&&$.id)return $.id;if((Z.provider==="codex"||Z.provider==="dsh")&&typeof Z.lastCompletedTurnId==="string"&&Z.lastCompletedTurnId)return Z.lastCompletedTurnId;if(Z.provider==="claude"&&Z.lastAssistantUuid)return Z.lastAssistantUuid;return}var S4;var hX=S(()=>{G8();E2();Z0();s3();S4=class S4 extends Error{output;sessionId;constructor($,Z,J){super($.message,{cause:$});this.output=Z;this.sessionId=J;this.name="AgentWorkerFailure"}}});import{createHash as vq,randomBytes as hq,randomUUID as Iq}from"node:crypto";import{existsSync as gq,readdirSync as cq,readFileSync as dX}from"node:fs";import{join as c6}from"node:path";class $Z{deps;runs=new Map;capabilities=new Map;activeTurns=0;slotWaiters=[];cancellationEpochBySession=new Map;startingWorkers=0;startingRunsBySession=new Map;constructor($=mq){this.deps=$;this.loadDurableRuns()}rootPrincipal($){return{kind:"session",session:$,depth:-1}}principalForCapability($){return this.capabilities.get($)??null}async startRun($,Z){if($.kind!=="session")throw Error(gX);let J=this.reserveCapacity($,Z.identityIds.length);try{return await this.createRun($.session,Z,{cancellationEpoch:this.currentCancellationEpoch($.session)})}finally{J()}}async followUp($,Z,J){if($.kind!=="session")throw Error(gX);let Y=this.requireMutableDescendant($,Z);if(!D2(Y.snapshot.status))throw Error("agent follow-up requires a terminal source run");let Q=lX(Y.snapshot,J.identityId);if(Y.handles.get(Q.identityId)?.isAlive?.())throw Error("Agent process has not stopped; cannot start follow-up yet");if(!Q.sessionId)throw Error(`${Q.identityName} has no resumable native session id`);let H=J.effort??Q.effort,W=this.reserveCapacity($,1);try{return await this.createRun($.session,{identityIds:[Q.identityId],prompt:J.prompt,effort:H},{parentRunId:Y.snapshot.runId,parentKind:"follow_up",cancellationEpoch:this.currentCancellationEpoch($.session),resumeByIdentity:new Map([[Q.identityId,Q.sessionId]])})}finally{W()}}async answer($,Z,J){let Y=this.requireMutableDescendant($,Z),Q=lX(Y.snapshot,J.identityId);if(Q.status!=="needs_input"||!Q.pendingInput)throw Error(`${Q.identityName} is not waiting for input`);if(Q.pendingInput.requestId!==J.requestId)throw Error(`input request mismatch: expected ${Q.pendingInput.requestId}`);let H=Y.handles.get(Q.identityId);if(!H)throw Error("waiting agent process is no longer alive; start a follow-up run");H.answer(J.requestId,J.answers);let W=H.pendingInput();if(Q.status=W?"needs_input":"running",W)Q.pendingInput=W;else delete Q.pendingInput;return delete Q.queuedReason,this.refreshNonterminalStatus(Y),this.persist(Y),await this.updateWorkerCard(Y,Q),x4(Y.snapshot)}getRun($,Z){return x4(this.requireAccessibleRun($,Z).snapshot)}async cancelRun($,Z,J="agent run cancelled"){let Y=this.requireMutableDescendant($,Z);if(!this.treeHasActiveRun(Y))return!1;return await this.cancelTree(Y,J),!0}async cancelSessionRuns($,Z,J){this.bumpCancellationEpoch($,Z);let Y=[...this.runs.values()].filter((H)=>H.snapshot.sessionName===$&&H.snapshot.chatId===Z&&!H.snapshot.parentRunId&&this.treeHasActiveRun(H)),Q=await Promise.allSettled(Y.map((H)=>this.cancelTree(H,J)));e3(Q)}async shutdown($){let Z=new Set([...this.runs.values()].map((W)=>`${W.snapshot.sessionName}\x00${W.snapshot.chatId}`));for(let W of Z){let[X,V]=W.split("\x00");this.bumpCancellationEpoch(X,V)}let J=[...this.runs.values()].filter((W)=>!W.snapshot.parentRunId&&this.treeHasActiveRun(W)),Y=await Promise.allSettled(J.map((W)=>this.cancelTree(W,$))),Q=[...this.runs.values()].flatMap((W)=>[...W.handles.values()]),H=Y.some((W)=>W.status==="rejected")?[]:await Promise.allSettled(Q.map((W)=>W.cancel($)));e3([...Y,...H])}async createRun($,Z,J){this.pruneRuns();let Y;if(J.parentRunId){if(Y=this.runs.get(J.parentRunId),!Y)throw Error(`parent agent run not found: ${J.parentRunId}`);this.assertSameSession(Y,$)}let Q=this.deps.getCatalog(),H=Z.identityIds.map((L)=>{let D=Q.identities.find((q)=>q.id===L);if(!D)throw Error(`agent identity not found: ${L}`);if(D.status!=="ready")throw Error(`${D.displayName}: ${D.reason??D.status}`);return D}),W=H.map((L)=>uq(L,pq(L,Z.effort),J.resumeByIdentity?.get(L.id))),X=`agent_${Iq()}`,V={runId:X,sessionName:$.sessionName,chatId:$.chatId,workDir:$.workDir,prompt:Z.prompt,...J.parentRunId?{parentRunId:J.parentRunId}:{},...J.parentKind?{parentKind:J.parentKind}:{},depth:0,status:"queued",workers:W,createdAt:new Date().toISOString()},z=await this.deps.sendCard($.chatId,h5(V));if(!z)throw Error("agent card creation failed; delegated agents were not started");let G;try{G=await this.deps.convertMessageToCard(z)}catch(L){throw await this.deps.sendTextRaw($.chatId,`❌ agent 卡片初始化失败,Agent 未启动: ${N0(L)}`),L}V.cardMessageId=z,this.deps.recordCardCreated(G,W.length+2,(L)=>{_(`agent: card write failed run=${X} code=${L??"MISS"}`)});let A={snapshot:V,session:$,cardId:G,handles:new Map,slotOwners:new Set,capabilityByIdentity:new Map,progressTimers:new Map,children:new Set,cancelled:!1,finalizing:!1,finalized:!1,persistedArtifacts:new Set};if(this.runs.set(X,A),J.parentRunId)Y?.children.add(X);if(this.currentCancellationEpoch($)!==J.cancellationEpoch){A.cancelled=!0;let L="任务已在启动前取消";for(let D of A.snapshot.workers)D.status="cancelled",D.error=L,D.finishedAt=new Date().toISOString();return this.persist(A),await Promise.all(A.snapshot.workers.map((D)=>this.updateWorkerCard(A,D))),await this.finalizeRun(A,"cancelled",L),x4(A.snapshot)}this.persist(A);for(let L of H){let D=J.resumeByIdentity?.get(L.id);this.executeWorker(A,L,Z.prompt,D).catch((q)=>{_(`agent: run=${X} worker=${L.id} crashed: ${N0(q)}`)})}return x4(V)}async executeWorker($,Z,J,Y){let Q=$.snapshot.workers.find((W)=>W.identityId===Z.id);if(await this.acquireSlot(()=>{Q.queuedReason=`等待执行名额(最多同时运行 ${IX} 个 Agent)`,this.persist($),this.updateWorkerCard($,Q)}),$.slotOwners.add(Z.id),$.cancelled){this.releaseWorkerSlot($,Z.id);return}let H="";try{if(H=hq(32).toString("base64url"),this.capabilities.set(H,{kind:"worker",session:$.session,runId:$.snapshot.runId,identityId:Z.id,depth:$.snapshot.depth}),$.capabilityByIdentity.set(Z.id,H),Q.status="running",Q.startedAt=new Date().toISOString(),delete Q.queuedReason,this.refreshNonterminalStatus($),this.persist($),await this.updateWorkerCard($,Q),$.cancelled)return;let W=this.deps.startWorker({identity:Z,effort:Q.effort,workDir:$.snapshot.workDir,prompt:J,resumeSessionId:Y,developerInstructions:$.session.delegatedAgentDeveloperInstructions(Z.provider),profile:dq(n1($.session.worktreeProjectName())),...process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"?{}:{managedSkillPluginPath:o$},hostEnv:{LODESTAR_AGENT_URL:A9(v.notify.bind,v.notify.port),LODESTAR_AGENT_CAPABILITY:H,LODESTAR_AGENT_SESSION:$.snapshot.sessionName},callbacks:{onNeedsInput:(V)=>{if($.cancelled)return;Q.status="needs_input",Q.pendingInput=V,this.refreshNonterminalStatus($),this.persist($),this.updateWorkerCard($,Q)},onProgress:(V)=>this.recordStep($,Q,V),onSession:(V)=>{if(Q.sessionId===V)return;Q.sessionId=V,this.persist($)}}});$.handles.set(Z.id,W);let X=await W.done;if($.cancelled)return;this.clearProgressTimer($,Z.id),Q.status="completed",Q.output=X.output,Q.outputTruncated=X.outputTruncated,Q.sessionId=X.sessionId,Q.checkpointId=X.checkpointId,Q.durationMs=X.durationMs,Q.usage=X.usage,Q.finishedAt=new Date().toISOString(),delete Q.pendingInput,this.persist($),await this.updateWorkerCard($,Q)}catch(W){if(W instanceof S4){if(Q.output=W.output,Q.outputTruncated=!1,W.sessionId)Q.sessionId=W.sessionId;this.persist($)}if(!$.cancelled){if(this.clearProgressTimer($,Z.id),Q.status="failed",Q.error=N0(W),Q.finishedAt=new Date().toISOString(),Q.startedAt)Q.durationMs=Date.now()-Date.parse(Q.startedAt);delete Q.pendingInput,this.persist($),await this.updateWorkerCard($,Q)}}finally{if(!$.handles.get(Z.id)?.isAlive?.())$.handles.delete(Z.id),this.releaseWorkerSlot($,Z.id);if(H)this.capabilities.delete(H);$.capabilityByIdentity.delete(Z.id),this.recomputeRun($)}}recordStep($,Z,J){if($.cancelled||$.finalizing||$.finalized||g6(Z.status))return;if(Z.steps.push(J),Z.steps.length>mX)Z.steps.splice(0,Z.steps.length-mX);if($.progressTimers.has(Z.identityId))return;let Y=setTimeout(()=>{$.progressTimers.delete(Z.identityId),this.updateWorkerCard($,Z)},250);$.progressTimers.set(Z.identityId,Y)}clearProgressTimer($,Z){let J=$.progressTimers.get(Z);if(J)clearTimeout(J);$.progressTimers.delete(Z)}refreshNonterminalStatus($){if($.cancelled)return;if($.snapshot.workers.some((Z)=>Z.status==="needs_input"))$.snapshot.status="needs_input";else if($.snapshot.workers.some((Z)=>Z.status==="running"))$.snapshot.status="running";else $.snapshot.status="queued";delete $.snapshot.finishedAt}recomputeRun($){if($.cancelled||$.finalized||$.finalizing)return;let Z=$.snapshot.workers;if(Z.some((Y)=>Y.status==="needs_input"||Y.status==="running"||Y.status==="queued")){this.refreshNonterminalStatus($),this.persist($);return}let J=Z.some((Y)=>Y.status==="failed")?"failed":"completed";this.finalizeRun($,J,J==="failed"?"一个或多个 Agent 失败":void 0).catch((Y)=>{$.finalizing=!1,$.finalized=!1,$.snapshot.status="failed",$.snapshot.error=`Agent terminal persistence failed: ${N0(Y)}`,_(`agent: terminal finalization failed run=${$.snapshot.runId}: ${N0(Y)}`),this.deps.sendTextRaw($.snapshot.chatId,`❌ agent ${$.snapshot.runId} 收尾失败: ${N0(Y)}`).catch((Q)=>_(`agent: terminal failure delivery failed: ${N0(Q)}`))})}async cancelTree($,Z){let J=!D2($.snapshot.status)&&!$.cancelled||$.handles.size>0,Y=[];if(J){$.cancelled=!0;for(let H of[...$.progressTimers.keys()])this.clearProgressTimer($,H);for(let H of $.capabilityByIdentity.values())this.capabilities.delete(H);$.capabilityByIdentity.clear()}while(!0){let H=[...$.children].map((X)=>this.runs.get(X)).filter((X)=>!!X&&this.treeHasActiveRun(X));if(H.length===0)break;let W=await Promise.allSettled(H.map((X)=>this.cancelTree(X,Z)));if(Y.push(...W),W.some((X)=>X.status==="rejected"))break}if(!J){e3(Y);return}if(Y.push(...await Promise.allSettled([...$.handles].map(async([H,W])=>{if(await W.cancel(Z),W.isAlive?.())throw Error(`${H}: Agent process is still alive after cancellation`);$.handles.delete(H),this.releaseWorkerSlot($,H)}))),Y.some((H)=>H.status==="rejected")){let H=nX(Y);throw $.snapshot.status="failed",$.snapshot.error=H.message,this.persist($),await this.deps.sendTextRaw($.snapshot.chatId,`❌ Agent 取消未完成: ${H.message}`).catch((W)=>_(`agent: cancellation failure notice failed: ${N0(W)}`)),H}let Q=[];for(let H of $.snapshot.workers)if(!g6(H.status))H.status="cancelled",H.error=Z,H.finishedAt=new Date().toISOString(),delete H.pendingInput,Q.push(H);await Promise.all(Q.map((H)=>this.updateWorkerCard($,H))),await this.finalizeRun($,"cancelled",Z)}async finalizeRun($,Z,J){if($.finalized||$.finalizing)return;$.finalizing=!0;for(let Y of[...$.progressTimers.keys()])this.clearProgressTimer($,Y);if($.snapshot.status=Z,$.snapshot.finishedAt=new Date().toISOString(),J)$.snapshot.error=J;try{if($.cardId){if(this.deps.cancelSummary($.cardId),await this.deps.flush($.cardId),!await this.deps.replaceElementChecked($.cardId,R.agentRunFooter,B4($.snapshot)))this.recordPresentationError($,"agent footer update MISS");if(!await this.deps.patchSettingsChecked($.cardId,{config:{streaming_mode:!1,summary:{content:L4($.snapshot)}}}))this.recordPresentationError($,"agent terminal settings update MISS");await this.deps.flush($.cardId),await this.deps.dispose($.cardId)}}catch(Y){this.recordPresentationError($,`agent card finalization failed: ${N0(Y)}`)}if($.finalizing=!1,this.persist($),$.finalized=!0,$.snapshot.presentationErrors?.length)await this.deps.sendTextRaw($.snapshot.chatId,`⚠️ agent ${$.snapshot.runId} 结果已保存,但卡片有 ${$.snapshot.presentationErrors.length} 个呈现错误。`).catch((Y)=>_(`agent: warning delivery failed run=${$.snapshot.runId}: ${N0(Y)}`))}async updateWorkerCard($,Z){if(!$.cardId||$.finalized)return;try{if(!await this.deps.replaceElementChecked($.cardId,J6(Z.identityId),Z6(Z,Y6($.snapshot.workers.length),$.snapshot.workers.length===1)))this.recordPresentationError($,`agent worker card MISS: ${Z.identityName}`);if(!await this.deps.replaceElementChecked($.cardId,R.agentRunFooter,B4($.snapshot)))_(`agent: progress update MISS run=${$.snapshot.runId}; later updates will refresh it`);this.deps.patchSummaryThrottled($.cardId,L4($.snapshot))}catch(J){this.recordPresentationError($,`agent worker card update failed (${Z.identityName}): ${N0(J)}`)}}recordPresentationError($,Z){let J=$.snapshot.presentationErrors??[];if(!J.includes(Z))J.push(Z);$.snapshot.presentationErrors=J,_(`agent: ${Z} run=${$.snapshot.runId}`)}persist($){if(!$.snapshot.promptArtifact)$.snapshot.promptArtifact=`${$.snapshot.runId}.prompt.txt`;this.persistTextArtifact($,$.snapshot.promptArtifact,$.snapshot.prompt);for(let J of $.snapshot.workers){if(!J.output)continue;if(!J.outputArtifact){let Y=vq("sha256").update(J.identityId).digest("hex").slice(0,16);J.outputArtifact=`${$.snapshot.runId}.${Y}.output.txt`}this.persistTextArtifact($,J.outputArtifact,J.output)}let Z=x4($.snapshot);Z.prompt="";for(let J of Z.workers)J.output="";this.deps.writeArtifact(c6(a$,`${$.snapshot.runId}.json`),Z)}persistTextArtifact($,Z,J){if($.persistedArtifacts.has(Z))return;aX(Z),this.deps.writeTextArtifact(c6(a$,Z),J),$.persistedArtifacts.add(Z)}requireAccessibleRun($,Z){let J=this.runs.get(Z);if(!J||!this.canAccess($,J))throw Error(`agent run not found: ${Z}`);if(this.assertSameSession(J,$.session),!J.session)J.session=$.session;return J}requireMutableDescendant($,Z){let J=this.requireAccessibleRun($,Z);if($.kind==="worker"&&J.snapshot.runId===$.runId)throw Error("worker capability cannot mutate its containing run");return J}canAccess($,Z){if(Z.snapshot.sessionName!==$.session.sessionName||Z.snapshot.chatId!==$.session.chatId)return!1;if($.kind==="session")return!0;let J=Z;while(J){if(J.snapshot.runId===$.runId)return!0;J=J.snapshot.parentRunId?this.runs.get(J.snapshot.parentRunId):void 0}return!1}assertSameSession($,Z){if($.snapshot.sessionName!==Z.sessionName||$.snapshot.chatId!==Z.chatId||$.snapshot.workDir!==Z.workDir)throw Error("agent run belongs to a different Session")}treeHasActiveRun($){if($.handles.size>0)return!0;if(!D2($.snapshot.status))return!0;for(let Z of $.children){let J=this.runs.get(Z);if(J&&this.treeHasActiveRun(J))return!0}return!1}reserveCapacity($,Z){let J=this.sessionKey($.session.sessionName,$.session.chatId),Y=[...this.runs.values()].filter((X)=>this.sessionKey(X.snapshot.sessionName,X.snapshot.chatId)===J&&(!D2(X.snapshot.status)||X.handles.size>0)).length,Q=this.startingRunsBySession.get(J)??0;if(Y+Q>=uX)throw Error(`Session has reached ${uX} active Agent runs`);if([...this.runs.values()].reduce((X,V)=>X+V.snapshot.workers.filter((z)=>!g6(z.status)||V.handles.get(z.identityId)?.isAlive?.()).length,0)+this.startingWorkers+Z>pX)throw Error(`global Agent worker limit ${pX} would be exceeded`);this.startingWorkers+=Z,this.startingRunsBySession.set(J,Q+1);let W=!1;return()=>{if(W)return;W=!0,this.startingWorkers=Math.max(0,this.startingWorkers-Z),aq(this.startingRunsBySession,J)}}sessionKey($,Z){return`${$}\x00${Z}`}currentCancellationEpoch($){return this.cancellationEpochBySession.get(this.sessionKey($.sessionName,$.chatId))??0}bumpCancellationEpoch($,Z){let J=this.sessionKey($,Z);this.cancellationEpochBySession.set(J,(this.cancellationEpochBySession.get(J)??0)+1)}acquireSlot($){if(this.activeTurns<IX)return this.activeTurns++,Promise.resolve();return $(),new Promise((Z)=>this.slotWaiters.push(Z))}releaseSlot(){let $=this.slotWaiters.shift();if($){$();return}this.activeTurns--}releaseWorkerSlot($,Z){if($.slotOwners.delete(Z))this.releaseSlot()}loadDurableRuns(){for(let $ of this.deps.loadArtifacts()){if(!D2($.status)){$.status="failed",$.error="daemon restarted before this Agent run reached a terminal state",$.finishedAt=new Date().toISOString();for(let J of $.workers)if(!g6(J.status))J.status="failed",J.error=$.error,J.finishedAt=$.finishedAt,delete J.pendingInput}let Z={snapshot:$,session:null,cardId:null,handles:new Map,slotOwners:new Set,capabilityByIdentity:new Map,progressTimers:new Map,children:new Set,cancelled:$.status==="cancelled",finalizing:!1,finalized:!0,persistedArtifacts:new Set([...$.promptArtifact?[$.promptArtifact]:[],...$.workers.flatMap((J)=>J.outputArtifact?[J.outputArtifact]:[])])};this.runs.set($.runId,Z),this.persist(Z)}for(let $ of this.runs.values())if($.snapshot.parentRunId)this.runs.get($.snapshot.parentRunId)?.children.add($.snapshot.runId);this.pruneRuns()}pruneRuns(){if(this.runs.size<=cX)return;let $=[...this.runs.values()].filter((Z)=>D2(Z.snapshot.status)&&Z.handles.size===0&&Z.slotOwners.size===0&&Z.children.size===0).sort((Z,J)=>Date.parse(Z.snapshot.finishedAt??Z.snapshot.createdAt)-Date.parse(J.snapshot.finishedAt??J.snapshot.createdAt));for(let Z of $){if(this.runs.size<=cX)break;if(this.runs.delete(Z.snapshot.runId),Z.snapshot.parentRunId)this.runs.get(Z.snapshot.parentRunId)?.children.delete(Z.snapshot.runId)}}}function uq($,Z,J){return{identityId:$.id,identityName:$.displayName,tokenSourceId:$.tokenSourceId,provider:$.provider,model:$.model,effort:Z,status:"queued",output:"",...J?{sessionId:J}:{},steps:[]}}function pq($,Z){let J=Z??$.defaultEffort;if(!J)throw Error(`${$.displayName} default effort MISS; specify effort explicitly`);if(!$.supportedEfforts.includes(J))throw Error(`${$.displayName} does not support effort ${J}`);return J}function lX($,Z){if(Z){let J=$.workers.find((Y)=>Y.identityId===Z);if(!J)throw Error(`agent identity is not part of run ${$.runId}: ${Z}`);return J}if($.workers.length!==1)throw Error("run has multiple Agents; specify identity_id");return $.workers[0]}function D2($){return $==="completed"||$==="failed"||$==="cancelled"}function g6($){return $==="completed"||$==="failed"||$==="cancelled"}function x4($){return JSON.parse(JSON.stringify($))}function lq(){if(!gq(a$))return[];let $=[];for(let Z of cq(a$).filter((J)=>J.endsWith(".json")).sort()){let J=c6(a$,Z),Y;try{Y=JSON.parse(dX(J,"utf8"))}catch(Q){throw Error(`agent run artifact is unreadable (${J}): ${N0(Q)}`)}if(!iq(Y))throw Error(`agent run artifact is invalid: ${J}`);nq(Y,J),$.push(Y)}return $}function iq($){if(!$||typeof $!=="object")return!1;let Z=$;return typeof Z.runId==="string"&&Z.runId.startsWith("agent_")&&typeof Z.sessionName==="string"&&typeof Z.chatId==="string"&&typeof Z.workDir==="string"&&typeof Z.prompt==="string"&&typeof Z.depth==="number"&&typeof Z.status==="string"&&Array.isArray(Z.workers)&&typeof Z.createdAt==="string"}function nX($){let Z=$.flatMap((J)=>J.status==="rejected"?[J.reason]:[]);return AggregateError(Z,`Agent cancellation failed: ${Z.map(N0).join("; ")}`)}function e3($){if($.some((Z)=>Z.status==="rejected"))throw nX($)}function N0($){return $ instanceof Error?$.message:String($)}function dq($){return $?{...$,tools:void 0,strictMcp:!1,loadProjectMcp:!0}:{strictMcp:!1,loadProjectMcp:!0}}function nq($,Z){if($.promptArtifact)$.prompt=iX($.promptArtifact,`prompt for ${Z}`);for(let J of $.workers)if(J.outputArtifact)J.output=iX(J.outputArtifact,`output for ${Z}`)}function iX($,Z){aX($);try{return dX(c6(a$,$),"utf8")}catch(J){throw Error(`${Z} is unreadable (${$}): ${N0(J)}`)}}function aX($){if(!/^[A-Za-z0-9._-]+$/.test($))throw Error(`invalid Agent artifact name: ${$}`)}function aq($,Z){let J=($.get(Z)??0)-1;if(J>0)$.set(Z,J);else $.delete(Z)}var IX=8,gX="Delegated Agents cannot delegate again; ask the main Agent to assign additional work.",cX=512,mX=50,uX=64,pX=128,mq;var oX=S(()=>{G1();p0();e();x0();U6();hX();Y0();n0();g();mq={getCatalog:R1,startWorker:vX,sendCard:a,sendTextRaw:w,convertMessageToCard:H$,recordCardCreated:r0,replaceElementChecked:L0,patchSummaryThrottled:L$,flush:c0,cancelSummary:D0,patchSettingsChecked:P0,dispose:m0,writeArtifact:A0,writeTextArtifact:d0,loadArtifacts:lq}});function rX($){let Z=ZZ($,"agent run request"),J=Array.isArray(Z.identity_ids)?Z.identity_ids.map(String):Array.isArray(Z.identityIds)?Z.identityIds.map(String):[],Y=[...new Set(J.map((W)=>W.trim()).filter(Boolean))];if(Y.length===0)throw Error("agent run requires at least one identity_id");if(Y.length>64)throw Error("agent run supports at most 64 identities");let Q=eX(Z.prompt,'agent run requires "prompt"'),H=k4(Z.effort);return{identityIds:Y,prompt:Q,...H?{effort:H}:{}}}function tX($){let Z=ZZ($,"agent follow-up request"),J=eX(Z.prompt,'agent follow-up requires "prompt"'),Y=k4(Z.identity_id??Z.identityId),Q=k4(Z.effort);return{prompt:J,...Y?{identityId:Y}:{},...Q?{effort:Q}:{}}}function sX($){let Z=ZZ($,"agent answer request"),J=k4(Z.identity_id??Z.identityId),Y=k4(Z.request_id??Z.requestId);if(!Y)throw Error("agent answer requires request_id");if(!Z.answers||typeof Z.answers!=="object"||Array.isArray(Z.answers))throw Error("agent answer requires an answers object");let Q={};for(let[H,W]of Object.entries(Z.answers)){if(!H.trim())throw Error("agent answer contains an empty question key");Q[H]=String(W)}if(Object.keys(Q).length===0)throw Error("agent answer requires at least one answer");return{requestId:Y,answers:Q,...J?{identityId:J}:{}}}function ZZ($,Z){if(!$||typeof $!=="object"||Array.isArray($))throw Error(`${Z} must be an object`);return $}function eX($,Z){let J=String($??"");if(!J.trim())throw Error(Z);if(J.length>800000)throw Error("agent prompt exceeds 800000 chars");return J}function k4($){return(typeof $==="string"?$.trim():"")||void 0}async function JV($,Z,J,Y){if(J.pathname!=="/agents"&&!J.pathname.startsWith("/agents/"))return!1;let Q=(G,A)=>{return Z.statusCode=G,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify(A)),!0},H=tq($.headers.authorization);if(!H)return Q(401,{error:"missing bearer capability"});let W=oq(Y,H);if(!W)return Q(403,{error:"invalid or stale agent capability"});if($.method==="GET"&&J.pathname==="/agents/identities")return await i1(),Q(200,sq(R1()));if($.method==="POST"&&J.pathname==="/agents/runs")try{let G=await Y.service.startRun(W,rX(await JZ($)));return Q(202,m6(G))}catch(G){return Q(409,{error:ZV(G)})}let X=J.pathname.match(/^\/agents\/runs\/([^/]+)(?:\/(follow-up|answer))?$/);if(!X)return Q(405,{error:"unsupported agent endpoint"});let V=rq(X[1]);if(!V)return Q(400,{error:"invalid agent run id encoding"});let z=X[2];try{if(!z&&$.method==="GET")return Q(200,m6(Y.service.getRun(W,V)));if(!z&&$.method==="DELETE"){let G=await Y.service.cancelRun(W,V,"cancelled by agent client");return Q(G?200:409,G?{ok:!0,run_id:V}:{error:"agent run is already terminal",run_id:V})}if(z==="follow-up"&&$.method==="POST"){let G=await Y.service.followUp(W,V,tX(await JZ($)));return Q(202,m6(G))}if(z==="answer"&&$.method==="POST"){let G=await Y.service.answer(W,V,sX(await JZ($)));return Q(200,m6(G))}}catch(G){return Q(409,{error:ZV(G)})}return Q(405,{error:"unsupported agent endpoint"})}function oq($,Z){let J=$.authorizeSession(Z);if(J)return $.service.rootPrincipal(J);return $.service.principalForCapability(Z)}function rq($){try{return decodeURIComponent($)}catch{return null}}function tq($){return $?.match(/^Bearer\s+(.+)$/i)?.[1]?.trim()??""}async function JZ($){let Z="";for await(let J of $)if(Z+=J.toString(),Buffer.byteLength(Z)>$V)throw Error(`request body exceeds ${$V} bytes`);try{return JSON.parse(Z||"{}")}catch{throw Error("bad json")}}function sq($){return{catalog_generation:$.catalogGeneration,identities:$.identities.map((Z)=>({id:Z.id,display_name:Z.displayName,token_source_id:Z.tokenSourceId,token_source_display:Z.tokenSourceDisplay,provider:Z.provider,model:Z.model,model_display:Z.modelDisplay,default_effort:Z.defaultEffort,supported_efforts:Z.supportedEfforts,source_default:Z.sourceDefault,status:Z.status,reason:Z.reason})),source_failures:$.sourceFailures.map((Z)=>({token_source_id:Z.tokenSourceId,display:Z.display,status:Z.status,reason:Z.reason}))}}function m6($){return{run_id:$.runId,session_name:$.sessionName,prompt:$.prompt,parent_run_id:$.parentRunId,parent_kind:$.parentKind,depth:$.depth,status:$.status,workers:$.workers.map((Z)=>({identity_id:Z.identityId,identity_name:Z.identityName,token_source_id:Z.tokenSourceId,provider:Z.provider,model:Z.model,effort:Z.effort,status:Z.status,output:Z.output,output_truncated:Z.outputTruncated,session_id:Z.sessionId,checkpoint_id:Z.checkpointId,pending_input:Z.pendingInput&&{request_id:Z.pendingInput.requestId,tool_use_id:Z.pendingInput.toolUseId,questions:Z.pendingInput.questions},queued_reason:Z.queuedReason,steps:Z.steps,error:Z.error,started_at:Z.startedAt,finished_at:Z.finishedAt,duration_ms:Z.durationMs,usage:Z.usage})),created_at:$.createdAt,finished_at:$.finishedAt,error:$.error,presentation_errors:$.presentationErrors,card_message_id:$.cardMessageId}}function ZV($){return $ instanceof Error?$.message:String($)}var $V=4194304;var YV=S(()=>{U6();Z0()});import{chmodSync as eq,existsSync as YZ,readFileSync as WV,realpathSync as $D,unlinkSync as ZD}from"node:fs";import{homedir as JD}from"node:os";import{basename as YD,dirname as QD,join as i$,resolve as HD}from"node:path";function WD($={}){let Z=$D(HD($.daemonEntry??process.argv[1]??"")),J=$.runtime??process.execPath,Y=$.exists??YZ,Q=QD(Z),H=i$(Q,"src","agent-cli.ts"),W=i$(Q,"lodestar-agent.js"),X=i$(Q,"dist","lodestar-agent.js"),z=/^bun(?:\.exe)?$/i.test(YD(J))?[H,W,X]:[W,X],G=z.find(Y);if(!G)throw Error(`lodestar-agent entry not found beside daemon: ${z.join(", ")}`);return{runtime:J,entry:G}}function XV($={}){let Z=$.platform??process.platform,J=$.env??process.env,Y=$.targetDir??VD(Z,$.homeDir??JD(),$.localAppData??process.env.LOCALAPPDATA),Q=$.launch??WD(),H=i$(Y,Z==="win32"?"lodestar-agent.cmd":"lodestar-agent"),W=Z==="win32"?`@"${HV(Q.runtime)}" "${HV(Q.entry)}" %*\r
|
|
482
485
|
`:`#!/bin/sh
|
|
483
|
-
exec ${
|
|
484
|
-
`,X=$Z(H)?XV(H,"utf8"):null;if(X!==W)OZ(H,W),A(`command: ${X===null?"installed":"updated"} ${H}`);else rL(H,448);return WD(J,Y,Z),QD(Y,Z),H}function QD($,Z){let J=p$($,Z==="win32"?"lodestar-consult.cmd":"lodestar-consult");if(!$Z(J))return;try{let Y=XV(J,"utf8");if(!Y.includes("lodestar-consult")&&!Y.includes("consult-cli")){A(`command: obsolete path preserved because ownership is unclear ${J}`);return}sL(J),A(`command: removed obsolete ${J}`)}catch(Y){A(`command: obsolete removal failed (${J}): ${Y}`)}}function HD($,Z,J){if($==="win32")return p$(J??p$(Z,"AppData","Local"),"Lodestar","bin");return p$(Z,".local","bin")}function WD($,Z,J){let Y=J==="win32"?Object.keys($).find((X)=>X.toLowerCase()==="path")??"Path":"PATH",Q=J==="win32"?";":":",H=$[Y]??"",W=(X)=>J==="win32"?X.toLowerCase():X;if(H.split(Q).some((X)=>W(X)===W(Z)))return;$[Y]=H?`${Z}${Q}${H}`:Z}function HV($){return`'${$.replaceAll("'",`'"'"'`)}'`}function WV($){return $.replaceAll('"','""')}var zV=E(()=>{g();d0()});function GV($,Z,J){return $>0&&Z-$>J}async function AV($){if(await $.reply())return!0;if(!$.hasQuestion())return!1;return await $.answerQuestion(),!0}function _V($){let Z=$==="media"?"视频":$==="image"?"图片":"文件";return`❌ 收到的${Z}下载失败,未转交给 Agent。备注:可能是${Z}超过飞书消息资源 100 MB 下载上限。`}function ZZ($){return typeof $==="string"&&$.length>0?$:void 0}function KV($,Z){if(!Z||typeof Z!=="object")return null;let J=Z;if($==="image"){let W=ZZ(J.image_key);return W?{key:W,type:"image",displayText:""}:null}if($!=="file"&&$!=="media")return null;let Y=ZZ(J.file_key);if(!Y)return null;let Q=ZZ(J.file_name);return{key:Y,type:"file",...Q?{name:Q}:{},displayText:Q?`(${$==="media"?"video":"file"}: ${Q})`:""}}function BV($,Z){return $.add(Z),Z.then(()=>{$.delete(Z)},()=>{$.delete(Z)}),Z}async function qV($){while(!0){let Z=[...$()];if(Z.length===0)return;await Promise.allSettled(Z)}}function VD($){let Z=$?.action?.value??{},J=String(Z.kind??"");if(!J)return"无效操作";if(!XD.has(J))return`不支持的操作: ${J}`;let Y=J==="notify_callback"||J==="notify_reply"||J==="notify_reply_cancel";if(!Y&&!String($?.context?.open_chat_id??""))return"回调缺少 chat_id,操作未执行";if(!Y&&!String($?.context?.open_message_id??""))return"回调缺少原卡 message_id,操作未执行";if(J==="permission"&&!["allow","allow_always","deny"].includes(String(Z.decision??"")))return"无效的权限决定,操作未执行";return null}class YZ{tails=new Map;accepting=!0;tryEnqueue($,Z){if(!this.accepting)return{accepted:!1,reason:"closed"};let J=$.trim();if(!J)return{accepted:!1,reason:"invalid-key"};let Q=(this.tails.get(J)??Promise.resolve()).then(Z),H;return H=Q.then(()=>{},()=>{}).finally(()=>{if(this.tails.get(J)===H)this.tails.delete(J)}),this.tails.set(J,H),{accepted:!0,completion:Q}}enqueue($,Z){let J=this.tryEnqueue($,Z);return J.accepted?J.completion:Promise.reject(Error(`per-key actor ${J.reason}`))}close(){this.accepting=!1}isAccepting(){return this.accepting}pending(){return this.tails.values()}}function LV($){let Z=$.now??Date.now;return{accept(J){let Y=Z();return $.actor.tryEnqueue($.key(J),()=>$.execute(J,Y))}}}class QZ{completedTtlMs;now;maxCompletedEntries;inflight=new Set;completed=new Map;constructor($=30000,Z=Date.now,J=4096){this.completedTtlMs=$;this.now=Z;this.maxCompletedEntries=J}claim($){return this.claimAll([$])}claimAll($){if(this.prune(),$.some((Z)=>this.inflight.has(Z)))return"inflight";if($.some((Z)=>this.completed.has(Z)))return"completed";for(let Z of $)this.inflight.add(Z);return"started"}complete($){this.completeAll([$])}completeAll($){this.prune();let Z=this.now()+this.completedTtlMs;for(let J of $)this.inflight.delete(J),this.completed.delete(J),this.completed.set(J,Z);while(this.completed.size>this.maxCompletedEntries){let J=this.completed.keys().next().value;if(J===void 0)break;this.completed.delete(J)}}fail($){this.failAll([$])}failAll($){for(let Z of $)this.inflight.delete(Z)}prune(){let $=this.now();for(let[Z,J]of this.completed)if(J<=$)this.completed.delete(Z)}}function JZ($){if(Array.isArray($))return`[${$.map(JZ).join(",")}]`;if($===void 0)return"undefined";if(!$||typeof $!=="object")return JSON.stringify($);return`{${Object.entries($).sort(([Z],[J])=>Z.localeCompare(J)).map(([Z,J])=>`${JSON.stringify(Z)}:${JZ(J)}`).join(",")}}`}function zD($){let Z=$?.action?.value??{},J=String(Z?.kind??"unknown"),Y=String($?.context?.open_chat_id??""),Q=String($?.context?.open_message_id??""),H=null;switch(J){case"menu":H={request_id:Z.request_id};break;case"permission":H={request_id:Z.request_id};break;case"ask":H={tool_use_id:Z.tool_use_id,question_idx:Z.question_idx};break;case"worktree_disband":H={slug:Z.slug};break;case"temp_fork_select":case"temp_back_select":case"temp_resume_select":H={panel_id:Z.panel_id};break;case"tasklist_delete_prompt":case"tasklist_delete_confirm":H={guid:Z.guid};break;case"tasklist_enable":H={guid:Z.guid,project:Z.project,panel_id:Z.panel_id};break;case"token_source_enable":H={source_id:Z.source_id};break;case"agent_identity_page":H={panel_id:Z.panel_id,page:Z.page};break;case"model_page":H={panel_id:Z.panel_id,source_id:Z.source_id,page:Z.page};break;case"model_list_open":H={panel_id:Z.panel_id,source_id:Z.source_id,mode:Z.mode};break;case"model_add":case"model_remove":case"model_custom_remove":H={panel_id:Z.panel_id,source_id:Z.source_id,model:Z.model};break;case"notify_callback":H={notify_id:Z.notify_id};break;case"notify_reply":H={notify_id:Z.notify_id};break;case"notify_reply_cancel":H={notify_id:Z.notify_id,reply_id:Z.reply_id};break;case"provider_select":case"model_select":case"model_custom_prompt":case"model_panel_cancel":case"model_effort_select":H={panel_id:Z.panel_id};break;default:H=Z}return`${Y}\x00${Q}\x00${J}\x00${JZ(H)}`}function GD($){let Z=String($?.event_id??$?.header?.event_id??$?.event?.event_id??"");return{...Z?{deliveryKey:`event\x00${Z}`}:{},businessKey:`semantic\x00${zD($)}`,...["agent_identity_page","model_page","model_list_open","model_add","model_remove","model_custom_remove","notify_reply"].includes($?.action?.value?.kind)?{repeatable:!0}:{}}}function AD(){return new Promise(($)=>setTimeout($,0))}function S4($,Z,J){if(Z.deliveryKey)$.complete(Z.deliveryKey);if(J&&!Z.repeatable)$.complete(Z.businessKey);else $.fail(Z.businessKey)}function DV($){let Z=$.afterAck??AD,J=(Q)=>{try{$.onBackgroundError?.(Q)}catch{}},Y=async(Q)=>{try{await Q()}catch(H){J(H)}};return{accept(Q){if(!$.actor.isAccepting())return $.responses.closed(Q);let H=VD(Q);if(H)return $.responses.invalid(Q,H);let W=GD(Q),X=W.deliveryKey?[W.deliveryKey,W.businessKey]:[W.businessKey],V=$.deduper.claimAll(X);if(V==="inflight")return $.responses.inflight(Q);if(V==="completed")return $.responses.completed(Q);let z=$.actor.tryEnqueue($.scope(Q),async()=>{try{await Z()}catch(K){$.deduper.failAll(X),J(K);return}let G;try{G=await $.execute(Q)}catch(K){S4($.deduper,W,!0),await Y(()=>$.presentExecutionFailure(Q,K));return}await Y(async()=>{try{await $.present(Q,G)}catch(K){await $.presentPresentationFailure(Q,K)}});let _;try{_=$.completion(Q,G)}catch(K){S4($.deduper,W,!1),J(K);return}if(_){let K=_.then((q)=>{S4($.deduper,W,q==="complete")},(q)=>{S4($.deduper,W,!1),J(q)});$.track(K);return}S4($.deduper,W,$.businessSucceeded(Q,G))});if(!z.accepted)return $.deduper.failAll(X),$.responses.closed(Q);return $.track(z.completion),z.completion.catch(J),$.responses.accepted(Q)}}}var XD;var PV=E(()=>{XD=new Set(["permission","menu","provider_select","model_select","model_custom_prompt","model_panel_cancel","model_effort_select","ask","worktree_disband","temp_fork_select","temp_back_select","temp_resume_select","tasklist_enable","tasklist_delete_prompt","tasklist_delete_confirm","token_source_enable","agent_identity_page","model_page","notify_callback","notify_reply","notify_reply_cancel","model_list_open","model_add","model_remove","model_custom_remove"])});function F$($){return $ instanceof Error?$.message:String($)}function jV($,Z,J){if(!J.disbanded||!J.chatId)throw Error(`飞书未确认删除临时群 "${$}"`);if(Z&&J.chatId!==Z)throw Error(`飞书删除结果 chat_id 不匹配: expected=${Z} actual=${J.chatId}`);return J.chatId}function FV($){let Z=(Q,H)=>{let W=$.registry.get(Q);if(W&&W.sessionName!==H)throw Error(`chat ${Q} is already owned by session "${W.sessionName}", not "${H}"`);if(!W)W=$.createSession(H,Q),$.registry.set(Q,W);return W};return{sessionFor:Z,createTempSession:async(Q)=>{let H;try{if(H0(Q.launch,Q.routing.provider,Q.workDir),Q.launch.kind==="resume")throw Error("temporary groups must start fresh or fork; resume is not allowed");if(H=await $.ensureChatForSession(Q.chatName,Q.userOpenId),!H.created)return{ok:!1,chatId:H.chatId,error:"临时会话必须使用新群;既有群保留,未执行加入、启动或删除"}}catch(X){let V=F$(X);return $.log(`temp-session: create "${Q.chatName}" failed: ${V}`),{ok:!1,error:V}}let W=async()=>{let X=null;try{if($.registerTempSessionLease(Q.chatName,H.chatId),X=Z(H.chatId,Q.chatName),X.isRunning())return{ok:!1,error:`${Q.chatName} 已有会话在跑,先 bye 解散再重试`};if(X.workDir!==Q.workDir)throw Error(`临时群 cwd 不匹配: source=${Q.workDir} target=${X.workDir}`);if(X.applyConversationRouting(Q.routing),!(Q.launch.kind==="fork"?await X.startForked(Q.launch,{announce:!1}):await X.start({announce:!1})))throw Error(`${X.backendLabel()} 启动失败`);return $.replaceTurnAnchors(Q.chatName,Q.seedAnchors??[],Q.branchBase),{ok:!0,chatId:H.chatId}}catch(V){let z=F$(V);if($.log(`temp-session: initialize "${Q.chatName}" failed: ${z}`),X)try{await X.stop("临时群启动失败清理",{announce:!1})}catch(_){let K=F$(_);return $.log(`temp-session: failed-create stop "${Q.chatName}" failed: ${K}`),{ok:!1,chatId:H.chatId,error:`${z};无法确认 Session 已停止,临时群/session 仍保留: ${K}`}}if(!H.created)return{ok:!1,error:`${z};既有群保留,未执行删除`};let G;try{let _=await $.disbandChatForSessionExact(Q.chatName,H.chatId);G=jV(Q.chatName,H.chatId,_)}catch(_){let K=F$(_);return $.log(`temp-session: create cleanup "${Q.chatName}" failed: ${K}`),{ok:!1,chatId:H.chatId,error:`${z};自动解散失败,临时群/session 仍保留: ${K}`}}try{$.registry.delete(G),X?.dispose(),$.clearSessionConversationState(Q.chatName)}catch(_){let K=F$(_);return $.log(`temp-session: local cleanup "${Q.chatName}" failed: ${K}`),{ok:!1,error:`${z};临时群已确认解散,但本地状态清理失败: ${K}`}}return{ok:!1,error:`${z};本次新建的临时群已确认解散`}}};try{return $.runExclusive?await $.runExclusive(H.chatId,W):await W()}catch(X){let V=F$(X);return $.log(`temp-session: target actor "${Q.chatName}" failed: ${V}`),{ok:!1,chatId:H.chatId,error:`${V};临时群/session 仍保留`}}},disbandTempSession:async(Q,H)=>{let W=$.chatIdForSession(Q);if(!H||W!==H){let z=`临时群 chat_id 已变化: expected=${H||"-"} bound=${W??"-"}`;return $.log(`temp-session: disband identity rejected "${Q}": ${z}`),{ok:!1,error:`${z};未执行停止或删群`}}if(!$.hasTempSessionLease(Q,H)){let z=`群 ${H} 没有 Lodestar 临时会话 lease,拒绝解散`;return $.log(`temp-session: disband lease rejected "${Q}": ${z}`),{ok:!1,error:`${z};未执行停止或删群`}}let X=$.registry.get(W);try{if(X)await X.stop("bye 解散",{announce:!1})}catch(z){let G=F$(z);return $.log(`temp-session: stop before disband "${Q}" failed: ${G}`),{ok:!1,error:`${G};无法确认 Session 已停止,未执行删群`}}let V;try{let z=await $.disbandChatForSessionExact(Q,W);V=jV(Q,W,z)}catch(z){let G=F$(z);return $.log(`temp-session: disband "${Q}" failed: ${G}`),{ok:!1,error:`${G};临时群/session 仍保留`}}try{return $.registry.delete(V),X?.dispose(),$.clearSessionConversationState(Q),{ok:!0}}catch(z){let G=F$(z);return $.log(`temp-session: local cleanup after disband "${Q}" failed: ${G}`),{ok:!1,error:`临时群已确认解散,但本地状态清理失败: ${G}`}}}}}var MV=E(()=>{t$()});var wD={};import*as q2 from"@larksuiteoapi/node-sdk";import{chmodSync as _D,existsSync as WZ,mkdirSync as KD,readFileSync as BD,unlinkSync as c6,writeFileSync as qD}from"node:fs";import{dirname as LD}from"node:path";function L2($,Z){if(O1=Math.max(O1,Z),I6)return I6;p6=!0,OV?.(),TV.abort(),l$.close(),XZ=GZ();try{n2(XZ)}catch(J){A(`shutdown alive marker write failed: ${J}`),O1=1}return I6=(async()=>{A(`${$}: staged shutdown begin sessions=${U$.size}`);try{let J=(async()=>{await qV(()=>[...l$.pending(),...NV]);let W=await Promise.allSettled([VZ.shutdown(`daemon ${$}`)]),X=await Promise.allSettled([...U$.values()].map((V)=>V.stop(`daemon ${$}`,{announce:!1})));return[...W,...X]})(),Y=null,Q=new Promise((W)=>{Y=setTimeout(()=>W("deadline"),UV)}),H=await Promise.race([J.then((W)=>{for(let X of W)if(X.status==="rejected")O1=1,A(`shutdown session stop failed: ${X.reason}`);return"stopped"}),Q]);if(Y)clearTimeout(Y);if(H==="deadline")O1=1,A(`${$}: shutdown deadline ${UV}ms reached; forcing exit`);else A(`${$}: all sessions stopped`)}catch(J){A(`${$}: staged shutdown failed: ${J}`),O1=1}finally{EV(),process.exit(O1)}})(),I6}function zZ($){return BV(NV,$)}function SV($,Z="ws"){if(p6)return A(`${Z}: reject inbound message: daemon shutdown in progress`),!1;let J=String($?.message?.chat_id??""),Y=PD.accept($);if(!Y.accepted)return A(`${Z}: reject inbound message${J?"":" without chat_id"}: actor ${Y.reason}`),!1;return Y.completion.catch((Q)=>{A(`${Z}: handleMessage rejected chat=${J.slice(0,8)}…: ${Q}`)}),!0}function GZ(){let $=new Set;for(let Z of U$.values())if(Z.shouldRevive())$.add(Z.sessionName);for(let Z of x4)$.add(Z);return[...$]}function g6(){n2(GZ())}function xV($,Z){return AZ.sessionFor($,Z)}async function jD($){return await AZ.createTempSession($)}async function FD($,Z){return await AZ.disbandTempSession($,Z)}async function MD(){let $=[...new Set(b8())];if($.length===0)return;x4=new Set($),A(`revive: ${$.length} session(s) marked alive on shutdown: ${$.join(", ")}`);try{await Promise.all($.map(async(Z)=>{let J=L9(Z);if(!J){A(`revive: no chatId binding for "${Z}", skip`),x4.delete(Z),g6();return}let Y=xV(J,Z);try{if(await Y.restart(!0))A(`revive: spawned "${Z}" (chat ${J.slice(0,8)}…)`);else A(`revive: "${Z}" did not start`)}catch(Q){A(`revive: restart "${Z}" failed: ${Q}`)}finally{x4.delete(Z),g6()}}))}finally{x4.clear(),g6()}}function RD($){let Z=[],J=[],Y=[],Q=typeof $?.title==="string"?$.title.trim():"";if(Q)Y.push(`# ${Q}`);let H=Array.isArray($?.content)?$.content:[];for(let W of H){if(!Array.isArray(W))continue;let X=[];for(let z of W){if(!z||typeof z!=="object")continue;switch(z.tag){case"text":{let G=String(z.text??""),_=Array.isArray(z.style)?z.style:[];if(_.includes("bold"))G=`**${G}**`;if(_.includes("italic"))G=`*${G}*`;if(_.includes("lineThrough")||_.includes("strikethrough"))G=`~~${G}~~`;X.push(G);break}case"a":{let G=String(z.href??""),_=String(z.text??G);X.push(`[${_}](${G})`);break}case"at":{let G=String(z.user_name??z.user_id??"");X.push(`@${G}`);break}case"code_inline":X.push(`\`${String(z.text??"")}\``);break;case"hr":X.push("---");break;case"img":if(z.image_key)Z.push(String(z.image_key));break;case"media":if(z.file_key)J.push({key:String(z.file_key),name:z.file_name});break;case"emotion":break;default:if(typeof z.text==="string")X.push(z.text)}}let V=X.join("");if(V.trim())Y.push(V)}return{markdown:Y.join(`
|
|
486
|
+
exec ${QV(Q.runtime)} ${QV(Q.entry)} "$@"
|
|
487
|
+
`,X=YZ(H)?WV(H,"utf8"):null;if(X!==W)TZ(H,W),_(`command: ${X===null?"installed":"updated"} ${H}`);else eq(H,448);return zD(J,Y,Z),XD(Y,Z),H}function XD($,Z){let J=i$($,Z==="win32"?"lodestar-consult.cmd":"lodestar-consult");if(!YZ(J))return;try{let Y=WV(J,"utf8");if(!Y.includes("lodestar-consult")&&!Y.includes("consult-cli")){_(`command: obsolete path preserved because ownership is unclear ${J}`);return}ZD(J),_(`command: removed obsolete ${J}`)}catch(Y){_(`command: obsolete removal failed (${J}): ${Y}`)}}function VD($,Z,J){if($==="win32")return i$(J??i$(Z,"AppData","Local"),"Lodestar","bin");return i$(Z,".local","bin")}function zD($,Z,J){let Y=J==="win32"?Object.keys($).find((X)=>X.toLowerCase()==="path")??"Path":"PATH",Q=J==="win32"?";":":",H=$[Y]??"",W=(X)=>J==="win32"?X.toLowerCase():X;if(H.split(Q).some((X)=>W(X)===W(Z)))return;$[Y]=H?`${Z}${Q}${H}`:Z}function QV($){return`'${$.replaceAll("'",`'"'"'`)}'`}function HV($){return $.replaceAll('"','""')}var VV=S(()=>{g();n0()});function zV($,Z,J){return $>0&&Z-$>J}async function GV($){if(await $.reply())return!0;if(!$.hasQuestion())return!1;return await $.answerQuestion(),!0}function _V($){let Z=$==="media"?"视频":$==="image"?"图片":"文件";return`❌ 收到的${Z}下载失败,未转交给 Agent。备注:可能是${Z}超过飞书消息资源 100 MB 下载上限。`}function QZ($){return typeof $==="string"&&$.length>0?$:void 0}function AV($,Z){if(!Z||typeof Z!=="object")return null;let J=Z;if($==="image"){let W=QZ(J.image_key);return W?{key:W,type:"image",displayText:""}:null}if($!=="file"&&$!=="media")return null;let Y=QZ(J.file_key);if(!Y)return null;let Q=QZ(J.file_name);return{key:Y,type:"file",...Q?{name:Q}:{},displayText:Q?`(${$==="media"?"video":"file"}: ${Q})`:""}}function KV($,Z){return $.add(Z),Z.then(()=>{$.delete(Z)},()=>{$.delete(Z)}),Z}async function BV($){while(!0){let Z=[...$()];if(Z.length===0)return;await Promise.allSettled(Z)}}class HZ{deps;pending=null;shutdownSnapshot=null;revival=null;constructor($){this.deps=$}load(){if(this.pending)throw Error("session recovery already loaded");this.pending=new Set(this.deps.readMarker())}transferPending($){if(!this.pending)throw Error("session recovery not loaded");if(!this.pending.has($.sessionName))return;$.requireDaemonRestore(),this.pending.delete($.sessionName)}currentNames(){let $=new Set(this.pending);for(let Z of this.deps.sessions())if(Z.shouldRevive())$.add(Z.sessionName);return[...$]}persist(){if(!this.pending)return;this.deps.writeMarker(this.shutdownSnapshot??this.currentNames())}freezeForShutdown(){if(!this.pending)return;this.shutdownSnapshot??=this.currentNames(),this.persist()}enqueue(){if(!this.pending)throw Error("session recovery not loaded");if(this.revival)return this.revival;if(this.deps.isShuttingDown())return Promise.resolve();let $=[...this.pending];return this.deps.log(`revive: ${$.length} session(s) marked alive on shutdown: ${$.join(", ")}`),this.revival=Promise.all($.map((Z)=>{let J=this.deps.chatIdForSession(Z);if(!J)return this.deps.log(`revive: no chatId binding for "${Z}"; recovery remains pending`),Promise.resolve();return this.deps.actor.enqueue(J,async()=>{if(this.deps.isShuttingDown())return;let Y;try{Y=this.deps.sessionFor(J,Z);let Q=await Y.restoreAfterDaemonRestart();this.deps.log(`revive: "${Z}" ${Q?"restored":"did not start"}`)}catch(Q){this.deps.log(`revive: restore "${Z}" failed: ${Q}`)}finally{if(Y)this.pending.delete(Z);this.persist()}})})).then(()=>{}),this.revival}}function _D($){let Z=$?.action?.value??{},J=String(Z.kind??"");if(!J)return"无效操作";if(!GD.has(J))return`不支持的操作: ${J}`;let Y=J==="notify_callback"||J==="notify_reply"||J==="notify_reply_cancel";if(!Y&&!String($?.context?.open_chat_id??""))return"回调缺少 chat_id,操作未执行";if(!Y&&!String($?.context?.open_message_id??""))return"回调缺少原卡 message_id,操作未执行";if(J==="permission"&&!["allow","allow_always","deny"].includes(String(Z.decision??"")))return"无效的权限决定,操作未执行";return null}class XZ{tails=new Map;accepting=!0;tryEnqueue($,Z){if(!this.accepting)return{accepted:!1,reason:"closed"};let J=$.trim();if(!J)return{accepted:!1,reason:"invalid-key"};let Q=(this.tails.get(J)??Promise.resolve()).then(Z),H;return H=Q.then(()=>{},()=>{}).finally(()=>{if(this.tails.get(J)===H)this.tails.delete(J)}),this.tails.set(J,H),{accepted:!0,completion:Q}}enqueue($,Z){let J=this.tryEnqueue($,Z);return J.accepted?J.completion:Promise.reject(Error(`per-key actor ${J.reason}`))}close(){this.accepting=!1}isAccepting(){return this.accepting}pending(){return this.tails.values()}}function LV($){let Z=$.now??Date.now;return{accept(J){let Y=Z();return $.actor.tryEnqueue($.key(J),()=>$.execute(J,Y))}}}class VZ{completedTtlMs;now;maxCompletedEntries;inflight=new Set;completed=new Map;constructor($=30000,Z=Date.now,J=4096){this.completedTtlMs=$;this.now=Z;this.maxCompletedEntries=J}claim($){return this.claimAll([$])}claimAll($){if(this.prune(),$.some((Z)=>this.inflight.has(Z)))return"inflight";if($.some((Z)=>this.completed.has(Z)))return"completed";for(let Z of $)this.inflight.add(Z);return"started"}complete($){this.completeAll([$])}completeAll($){this.prune();let Z=this.now()+this.completedTtlMs;for(let J of $)this.inflight.delete(J),this.completed.delete(J),this.completed.set(J,Z);while(this.completed.size>this.maxCompletedEntries){let J=this.completed.keys().next().value;if(J===void 0)break;this.completed.delete(J)}}fail($){this.failAll([$])}failAll($){for(let Z of $)this.inflight.delete(Z)}prune(){let $=this.now();for(let[Z,J]of this.completed)if(J<=$)this.completed.delete(Z)}}function WZ($){if(Array.isArray($))return`[${$.map(WZ).join(",")}]`;if($===void 0)return"undefined";if(!$||typeof $!=="object")return JSON.stringify($);return`{${Object.entries($).sort(([Z],[J])=>Z.localeCompare(J)).map(([Z,J])=>`${JSON.stringify(Z)}:${WZ(J)}`).join(",")}}`}function AD($){let Z=$?.action?.value??{},J=String(Z?.kind??"unknown"),Y=String($?.context?.open_chat_id??""),Q=String($?.context?.open_message_id??""),H=null;switch(J){case"menu":H={request_id:Z.request_id};break;case"permission":H={request_id:Z.request_id};break;case"ask":H={tool_use_id:Z.tool_use_id,question_idx:Z.question_idx};break;case"worktree_disband":H={slug:Z.slug};break;case"temp_fork_select":case"temp_back_select":case"temp_resume_select":H={panel_id:Z.panel_id};break;case"tasklist_delete_prompt":case"tasklist_delete_confirm":H={guid:Z.guid};break;case"tasklist_enable":H={guid:Z.guid,project:Z.project,panel_id:Z.panel_id};break;case"token_source_enable":H={source_id:Z.source_id};break;case"agent_identity_page":H={panel_id:Z.panel_id,page:Z.page};break;case"model_page":H={panel_id:Z.panel_id,source_id:Z.source_id,page:Z.page};break;case"model_list_open":H={panel_id:Z.panel_id,source_id:Z.source_id,mode:Z.mode};break;case"model_add":case"model_remove":case"model_custom_remove":H={panel_id:Z.panel_id,source_id:Z.source_id,model:Z.model};break;case"notify_callback":H={notify_id:Z.notify_id};break;case"notify_reply":H={notify_id:Z.notify_id};break;case"notify_reply_cancel":H={notify_id:Z.notify_id,reply_id:Z.reply_id};break;case"provider_select":case"model_select":case"model_custom_prompt":case"model_panel_cancel":case"model_effort_select":H={panel_id:Z.panel_id};break;default:H=Z}return`${Y}\x00${Q}\x00${J}\x00${WZ(H)}`}function KD($){let Z=String($?.event_id??$?.header?.event_id??$?.event?.event_id??"");return{...Z?{deliveryKey:`event\x00${Z}`}:{},businessKey:`semantic\x00${AD($)}`,...["agent_identity_page","model_page","model_list_open","model_add","model_remove","model_custom_remove","notify_reply"].includes($?.action?.value?.kind)?{repeatable:!0}:{}}}function BD(){return new Promise(($)=>setTimeout($,0))}function C4($,Z,J){if(Z.deliveryKey)$.complete(Z.deliveryKey);if(J&&!Z.repeatable)$.complete(Z.businessKey);else $.fail(Z.businessKey)}function qV($){let Z=$.afterAck??BD,J=(Q)=>{try{$.onBackgroundError?.(Q)}catch{}},Y=async(Q)=>{try{await Q()}catch(H){J(H)}};return{accept(Q){if(!$.actor.isAccepting())return $.responses.closed(Q);let H=_D(Q);if(H)return $.responses.invalid(Q,H);let W=KD(Q),X=W.deliveryKey?[W.deliveryKey,W.businessKey]:[W.businessKey],V=$.deduper.claimAll(X);if(V==="inflight")return $.responses.inflight(Q);if(V==="completed")return $.responses.completed(Q);let z=$.actor.tryEnqueue($.scope(Q),async()=>{try{await Z()}catch(K){$.deduper.failAll(X),J(K);return}let G;try{G=await $.execute(Q)}catch(K){C4($.deduper,W,!0),await Y(()=>$.presentExecutionFailure(Q,K));return}await Y(async()=>{try{await $.present(Q,G)}catch(K){await $.presentPresentationFailure(Q,K)}});let A;try{A=$.completion(Q,G)}catch(K){C4($.deduper,W,!1),J(K);return}if(A){let K=A.then((L)=>{C4($.deduper,W,L==="complete")},(L)=>{C4($.deduper,W,!1),J(L)});$.track(K);return}C4($.deduper,W,$.businessSucceeded(Q,G))});if(!z.accepted)return $.deduper.failAll(X),$.responses.closed(Q);return $.track(z.completion),z.completion.catch(J),$.responses.accepted(Q)}}}var GD;var DV=S(()=>{GD=new Set(["permission","menu","provider_select","model_select","model_custom_prompt","model_panel_cancel","model_effort_select","ask","worktree_disband","temp_fork_select","temp_back_select","temp_resume_select","tasklist_enable","tasklist_delete_prompt","tasklist_delete_confirm","token_source_enable","agent_identity_page","model_page","notify_callback","notify_reply","notify_reply_cancel","model_list_open","model_add","model_remove","model_custom_remove"])});function M$($){return $ instanceof Error?$.message:String($)}function PV($,Z,J){if(!J.disbanded||!J.chatId)throw Error(`飞书未确认删除临时群 "${$}"`);if(Z&&J.chatId!==Z)throw Error(`飞书删除结果 chat_id 不匹配: expected=${Z} actual=${J.chatId}`);return J.chatId}function jV($){let Z=(Q,H)=>{let W=$.registry.get(Q);if(W&&W.sessionName!==H)throw Error(`chat ${Q} is already owned by session "${W.sessionName}", not "${H}"`);if(!W)W=$.createSession(H,Q),$.registry.set(Q,W);return W};return{sessionFor:Z,createTempSession:async(Q)=>{let H;try{if(V0(Q.launch,Q.routing.provider,Q.workDir),Q.launch.kind==="resume")throw Error("temporary groups must start fresh or fork; resume is not allowed");if(H=await $.ensureChatForSession(Q.chatName,Q.userOpenId),!H.created)return{ok:!1,chatId:H.chatId,error:"临时会话必须使用新群;既有群保留,未执行加入、启动或删除"}}catch(X){let V=M$(X);return $.log(`temp-session: create "${Q.chatName}" failed: ${V}`),{ok:!1,error:V}}let W=async()=>{let X=null;try{if($.registerTempSessionLease(Q.chatName,H.chatId),X=Z(H.chatId,Q.chatName),X.isRunning())return{ok:!1,error:`${Q.chatName} 已有会话在跑,先 bye 解散再重试`};if(X.workDir!==Q.workDir)throw Error(`临时群 cwd 不匹配: source=${Q.workDir} target=${X.workDir}`);if(X.applyConversationRouting(Q.routing),!(Q.launch.kind==="fork"?await X.startForked(Q.launch,{announce:!1}):await X.start({announce:!1})))throw Error(`${X.backendLabel()} 启动失败`);return $.replaceTurnAnchors(Q.chatName,Q.seedAnchors??[],Q.branchBase),{ok:!0,chatId:H.chatId}}catch(V){let z=M$(V);if($.log(`temp-session: initialize "${Q.chatName}" failed: ${z}`),X)try{await X.stop("临时群启动失败清理",{announce:!1})}catch(A){let K=M$(A);return $.log(`temp-session: failed-create stop "${Q.chatName}" failed: ${K}`),{ok:!1,chatId:H.chatId,error:`${z};无法确认 Session 已停止,临时群/session 仍保留: ${K}`}}if(!H.created)return{ok:!1,error:`${z};既有群保留,未执行删除`};let G;try{let A=await $.disbandChatForSessionExact(Q.chatName,H.chatId);G=PV(Q.chatName,H.chatId,A)}catch(A){let K=M$(A);return $.log(`temp-session: create cleanup "${Q.chatName}" failed: ${K}`),{ok:!1,chatId:H.chatId,error:`${z};自动解散失败,临时群/session 仍保留: ${K}`}}try{$.registry.delete(G),X?.dispose(),$.clearSessionConversationState(Q.chatName)}catch(A){let K=M$(A);return $.log(`temp-session: local cleanup "${Q.chatName}" failed: ${K}`),{ok:!1,error:`${z};临时群已确认解散,但本地状态清理失败: ${K}`}}return{ok:!1,error:`${z};本次新建的临时群已确认解散`}}};try{return $.runExclusive?await $.runExclusive(H.chatId,W):await W()}catch(X){let V=M$(X);return $.log(`temp-session: target actor "${Q.chatName}" failed: ${V}`),{ok:!1,chatId:H.chatId,error:`${V};临时群/session 仍保留`}}},disbandTempSession:async(Q,H)=>{let W=$.chatIdForSession(Q);if(!H||W!==H){let z=`临时群 chat_id 已变化: expected=${H||"-"} bound=${W??"-"}`;return $.log(`temp-session: disband identity rejected "${Q}": ${z}`),{ok:!1,error:`${z};未执行停止或删群`}}if(!$.hasTempSessionLease(Q,H)){let z=`群 ${H} 没有 Lodestar 临时会话 lease,拒绝解散`;return $.log(`temp-session: disband lease rejected "${Q}": ${z}`),{ok:!1,error:`${z};未执行停止或删群`}}let X=$.registry.get(W);try{if(X)await X.stop("bye 解散",{announce:!1})}catch(z){let G=M$(z);return $.log(`temp-session: stop before disband "${Q}" failed: ${G}`),{ok:!1,error:`${G};无法确认 Session 已停止,未执行删群`}}let V;try{let z=await $.disbandChatForSessionExact(Q,W);V=PV(Q,W,z)}catch(z){let G=M$(z);return $.log(`temp-session: disband "${Q}" failed: ${G}`),{ok:!1,error:`${G};临时群/session 仍保留`}}try{return $.registry.delete(V),X?.dispose(),$.clearSessionConversationState(Q),{ok:!0}}catch(z){let G=M$(z);return $.log(`temp-session: local cleanup after disband "${Q}" failed: ${G}`),{ok:!1,error:`临时群已确认解散,但本地状态清理失败: ${G}`}}}}}var FV=S(()=>{$1()});var hD={};import*as j2 from"@larksuiteoapi/node-sdk";import{chmodSync as LD,existsSync as GZ,mkdirSync as qD,readFileSync as DD,unlinkSync as p6,writeFileSync as PD}from"node:fs";import{dirname as jD}from"node:path";function F2($,Z){if(d$=Math.max(d$,Z),u6)return u6;f0=!0,UV?.(),T$.close();try{OV?.()}catch(J){d$=1,_(`shutdown WebSocket close failed: ${J}`)}try{S1.persist()}catch(J){_(`shutdown alive marker write failed: ${J}`),d$=1}return u6=(async()=>{_(`${$}: staged shutdown begin sessions=${O$.size}`);try{let J=(async()=>{await BV(()=>[...T$.pending(),...EV]),S1.freezeForShutdown();let W=await Promise.allSettled([_Z.shutdown(`daemon ${$}`)]),X=await Promise.allSettled([...O$.values()].map((V)=>V.stop(`daemon ${$}`,{announce:!1})));return[...W,...X]})(),Y=null,Q=new Promise((W)=>{Y=setTimeout(()=>W("deadline"),RV)}),H=await Promise.race([J.then((W)=>{for(let X of W)if(X.status==="rejected")d$=1,_(`shutdown session stop failed: ${X.reason}`);return"stopped"}),Q]);if(Y)clearTimeout(Y);if(H==="deadline")d$=1,_(`${$}: shutdown deadline ${RV}ms reached; forcing exit`);else _(`${$}: all sessions stopped`)}catch(J){_(`${$}: staged shutdown failed: ${J}`),d$=1}finally{TV(),process.exit(d$)}})(),u6}function AZ($){return KV(EV,$)}function NV($,Z="ws"){if(f0)return _(`${Z}: reject inbound message: daemon shutdown in progress`),!1;let J=String($?.message?.chat_id??""),Y=MD.accept($);if(!Y.accepted)return _(`${Z}: reject inbound message${J?"":" without chat_id"}: actor ${Y.reason}`),!1;return Y.completion.catch((Q)=>{_(`${Z}: handleMessage rejected chat=${J.slice(0,8)}…: ${Q}`)}),!0}function RD(){S1.persist()}function SV($,Z){return KZ.sessionFor($,Z)}async function UD($){return await KZ.createTempSession($)}async function OD($,Z){return await KZ.disbandTempSession($,Z)}function TD($){let Z=[],J=[],Y=[],Q=typeof $?.title==="string"?$.title.trim():"";if(Q)Y.push(`# ${Q}`);let H=Array.isArray($?.content)?$.content:[];for(let W of H){if(!Array.isArray(W))continue;let X=[];for(let z of W){if(!z||typeof z!=="object")continue;switch(z.tag){case"text":{let G=String(z.text??""),A=Array.isArray(z.style)?z.style:[];if(A.includes("bold"))G=`**${G}**`;if(A.includes("italic"))G=`*${G}*`;if(A.includes("lineThrough")||A.includes("strikethrough"))G=`~~${G}~~`;X.push(G);break}case"a":{let G=String(z.href??""),A=String(z.text??G);X.push(`[${A}](${G})`);break}case"at":{let G=String(z.user_name??z.user_id??"");X.push(`@${G}`);break}case"code_inline":X.push(`\`${String(z.text??"")}\``);break;case"hr":X.push("---");break;case"img":if(z.image_key)Z.push(String(z.image_key));break;case"media":if(z.file_key)J.push({key:String(z.file_key),name:z.file_name});break;case"emotion":break;default:if(typeof z.text==="string")X.push(z.text)}}let V=X.join("");if(V.trim())Y.push(V)}return{markdown:Y.join(`
|
|
485
488
|
|
|
486
|
-
`),imageKeys:Z,fileKeys:J}}async function OD($,Z=Date.now()){let J=$?.message;if(!J)return;let Q=($?.sender?.sender_id??$?.event?.sender?.sender_id??J?.sender?.sender_id)?.open_id??"",H=J.message_id;if(H&&B2.has(H))return;if(H){if(B2.add(H),B2.size>200){let j=[...B2];B2.clear();for(let M of j.slice(-100))B2.add(M)}}let W=Number(J.create_time??0);if(GV(W,Z,UD)){if(A(`drop stale message ${H} ageAtReceipt=${Math.round((Z-W)/1000)}s`),H)b0(H,"CrossMark");return}let X=J.chat_id,V={};try{V=JSON.parse(J.content??"{}")}catch{}let z=J.message_type==="text"?V.text??"":"";if(typeof z==="string"&&z.startsWith("[DEBUG]")){try{qD(w4,JSON.stringify({chat_id:X,sender_open_id:Q,seeded_at:new Date().toISOString(),seeded_msg_id:H??""},null,2)),A(`debug: seeded inject context chat=${X.slice(0,8)}… sender=${Q.slice(0,8)}…`)}catch(M){A(`debug: seed context failed: ${M}`)}let j=z.slice(7);V.text=j,J.content=JSON.stringify(V)}let G=V0.get(X);if(!G)await a2(),G=V0.get(X);if(!G)G=await h8(X)??void 0;if(!G){A(`unknown chat ${X}, dropping message`),await T(X,"❌ 无法识别群名。请确认:① 机器人已被拉进本群;② 群已设置名称(未命名群拿不到群名,无法映射项目目录)。设置后再发一条消息即可。");return}let _=m8(G);u1(_,X);let K=xV(X,_),q={};try{q=JSON.parse(J.content??"{}")}catch{}let D=J.message_type,L="",P=!1,N=[];if(D==="text")L=(q.text??"").trim();else if(D==="post"){let j=RD(q);P=j.imageKeys.length>0||j.fileKeys.length>0,L=j.markdown.trim();for(let M of j.imageKeys){let C=await o2(J.message_id,M,"image");if(C)N.push(C)}for(let M of j.fileKeys){let C=await o2(J.message_id,M.key,"file",M.name);if(C)N.push(C)}}if(D==="text"&&L){if(await K.runCommand(L,Q))return}if((D==="text"||D==="post")&&L&&!P&&await AV({reply:()=>m6.consume({chatId:X,openId:Q,messageId:H??"",text:L,createTime:W,parentId:J.parent_id}),hasQuestion:()=>K.hasPendingAsk(),answerQuestion:()=>K.onAskMessageAnswer(L,Q,H??"")}))return;if(D==="text"&&L&&await K.consumeModelCustomMessage(L,Q))return;let F=KV(D,q);if(F){let j=await o2(J.message_id,F.key,F.type,F.name);if(!j){await T(X,_V(D));return}if(N.push(j),!L&&F.displayText)L=F.displayText}if(!L&&N.length===0){A(`drop empty message ${H} type=${D}`);return}if(await K.onMultiMessageInbound(L,N,Q,H??""))return;await K.onUserMessage(L||"(empty)",N,Q,H??"")}function u6($){return{permission:"权限决定",menu:"菜单选择",provider_select:"账号选择",model_page:"模型翻页",model_list_open:"模型列表",model_add:"显示模型",model_remove:"隐藏模型",model_custom_remove:"删除补录模型",model_select:"模型选择",model_custom_prompt:"模型补录",model_panel_cancel:"取消模型补录",model_effort_select:"模型 effort 选择",ask:"问题回答",worktree_disband:"worktree 解散",temp_fork_select:"会话分叉",temp_back_select:"会话回滚",temp_resume_select:"会话恢复",tasklist_enable:"启用任务清单",tasklist_delete_prompt:"删除任务清单",tasklist_delete_confirm:"确认删除任务清单",token_source_enable:"启用账号",agent_identity_page:"Agent 身份翻页",notify_callback:"通知反馈",notify_reply:"通知回复",notify_reply_cancel:"取消通知回复"}[$]??$}function TD($){return $?.card?.type==="raw"&&$.card.data&&typeof $.card.data==="object"?$.card.data:null}function e($,Z,J){return{...$,__businessOk:Z,...J?{__businessMessage:J}:{}}}function R$($,Z){return{...Z,__cardActionMessageId:$.messageId,__cardActionChatId:$.chatId}}function M$($){return e($.card?p0($.card):{toast:{type:$.ok?"success":"error",content:$.message}},$.ok)}async function T1($,Z){if(!$){A(`card-action: cannot send receipt without chat_id: ${Z}`);return}if(!await w($,Z))A(`card-action: visible receipt MISS chat=${$.slice(0,8)}… text=${Z.slice(0,120)}`)}async function ED($,Z){if(Z?.__cardActionPresented)return;let J=String($?.action?.value?.kind??"unknown"),Y=u6(J),Q=String(Z?.__cardActionChatId??$?.__cardActionChatId??$?.context?.open_chat_id??""),H=String(Z?.__cardActionMessageId??$?.context?.open_message_id??""),W=TD(Z),X=Z?.__businessOk===!1&&typeof Z?.__businessMessage==="string"?` 业务失败: ${Z.__businessMessage.replace(/\s+/g," ").trim().slice(0,300)}。`:"";if(W&&H)try{await Y$(H,W);return}catch(q){A(`card-action: ${J} original-card update failed: ${q instanceof Error?q.message:q}`),await T1(Q,`⚠️ ${Y}已处理,但原卡更新失败。${X}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":"请重新打开操作面板。"}`);return}if(W){await T1(Q,`⚠️ ${Y}已处理,但回调缺少原卡 message_id,无法更新。${X}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":""}`);return}if(J==="notify_callback"&&Z?.__cardActionCompletion)return;let V=Z?.toast,z=typeof V?.content==="string"&&V.content.trim()?V.content.trim():`${Y}已完成`,G=J==="permission"&&String($?.action?.value?.decision??"")==="deny",_=Z?.__businessOk===!1||V?.type==="error"&&!G;if(!_&&new Set(["permission","ask","token_source_enable"]).has(J))return;await T1(Q,`${_?"❌":"✅"} ${Y}: ${z}`)}async function ND($,Z){let J=String($?.action?.value?.kind??"unknown"),Y=Z instanceof Error?Z.message:String(Z);await T1(String($?.__cardActionChatId??$?.context?.open_chat_id??""),`❌ ${u6(J)}失败: ${Y}`)}function kV($){return SD.accept($)}async function xD($){let Z=$?.action,J=Z?.value;if(!J?.kind)return;let Y=$?.context?.open_chat_id??"",Q=$?.operator?.open_id??"";if(J.kind==="notify_callback"||J.kind==="notify_reply"||J.kind==="notify_reply_cancel"){let W=String(J.notify_id??""),X=D$(W);if(X)$.__cardActionChatId=X.chatId;if(J.kind==="notify_callback")return await kD(J,Y,Q);let V=J.kind==="notify_reply"?await m6.open(W,Y,Q):await m6.cancel(W,String(J.reply_id??""),Y,Q),z=e({toast:{type:V.ok?"success":"error",content:V.message},__cardActionPresented:V.presented===!0},V.ok);return X?R$(X,z):z}let H=U$.get(Y);if(!H)return e({toast:{type:"error",content:"会话不存在,请先发消息启动"}},!1);switch(J.kind){case"permission":{let W=String(J.decision??"");if(!["allow","allow_always","deny"].includes(W))return{toast:{type:"error",content:"无效的权限决定"}};let X=await H.onPermissionDecision(J.request_id,W,Q);return e({toast:{type:X.ok?W==="deny"?"error":"success":"error",content:X.message}},X.ok)}case"menu":{let W=Number(J.choice??-1);try{if(!Number.isInteger(W)||W<0)throw Error("无效的菜单选项");return await H.onUserMessage(`(menu choice ${W+1})`),e(p0(v$({title:"\uD83D\uDCCB 菜单选择",message:`已选择第 ${W+1} 项`,ok:!0})),!0)}catch(X){let V=X instanceof Error?X.message:String(X);return e(p0(v$({title:"\uD83D\uDCCB 菜单选择",message:V,ok:!1})),!1)}}case"provider_select":{let W=await H.onProviderSelect(String(J.source_id??""),String(J.panel_id??""));return M$(W)}case"model_page":{let W=await H.onModelPage(String(J.panel_id??""),String(J.source_id??""),Number(J.page));return M$(W)}case"model_list_open":{let W=String(J.panel_id??""),X=String(J.source_id??"");if(J.mode!=="add"&&J.mode!=="select")throw Error("模型管理模式无效");return M$(await(J.mode==="add"?H.onModelAddOpen(W,X):H.onProviderSelect(X,W)))}case"model_add":case"model_remove":case"model_custom_remove":return M$(await H.onModelListEdit(String(J.panel_id??""),String(J.source_id??""),String(J.model??""),J.kind==="model_add"?"add":J.kind==="model_remove"?"remove":"delete"));case"model_select":{let W=await H.onModelSelect(String(J.model??""),String(J.panel_id??""),Q,J);return M$(W)}case"model_custom_prompt":{let W=await H.onModelCustomPrompt(String(J.source_id??""),String(J.panel_id??""),String($?.context?.open_message_id??""));return M$(W)}case"model_panel_cancel":{let W=await H.onModelPanelCancel(String(J.panel_id??""));return M$(W)}case"model_effort_select":{let W=await H.onModelEffortSelect(String(J.model??""),String(J.effort??""),String(J.panel_id??""),Q,String(J.provider??""));return M$(W)}case"ask":{let W=H.askBlockReason(String(J.tool_use_id??""));if(W)return e({toast:{type:"error",content:W}},!1);if(J.custom){let z=(Z?.form_value??Z?.input??{})?.custom_answer??Z?.input_value??"",G=await H.onAskCustomAnswer(J.tool_use_id,J.question_idx??0,z,Q);return e({toast:{type:G?"success":"error",content:G?"已回答":z.trim()?"问题已失效或答案未被接受":"请输入答案"}},G)}let X=await H.onAskAnswer(J.tool_use_id,J.question_idx??0,J.option_idx,Q);return e({toast:{type:X?"success":"error",content:X?"已回答":"问题已失效或选项无效"}},X)}case"worktree_disband":{let W=await H.onWorktreeDisband(String(J.slug??""));return e(p0(W.card),W.ok)}case"temp_fork_select":{let W=await H.onForkSelect(String(J.panel_id??""),String(J.choice_id??""),Q);return e(W.replaceCard===!1?{toast:{type:"error",content:W.message}}:p0(v$({title:"\uD83D\uDD31 会话分叉",message:W.message,ok:W.ok})),W.ok)}case"temp_back_select":{let W=await H.onBackSelect(String(J.panel_id??""),String(J.choice_id??""),Q);return e(W.replaceCard===!1?{toast:{type:"error",content:W.message}}:p0(v$({title:"⏪ 会话回滚",message:W.message,ok:W.ok})),W.ok)}case"temp_resume_select":{let W=await H.onResumeSelect(String(J.panel_id??""),String(J.choice_id??""),Q);if(W.replaceCard===!1)return e({toast:{type:"error",content:W.message}},W.ok);if(!W.resumePresentation)throw Error("rs selection result missing trusted presentation snapshot");return e(p0(E5({...W.resumePresentation,message:W.message,ok:W.ok})),W.ok,W.message)}case"tasklist_enable":{let W=await H.onTasklistEnable();return e(p0(W.card),W.ok)}case"tasklist_delete_prompt":{let W=H.onTasklistDeletePrompt(String(J.guid??""));return e(p0(W.card),W.ok)}case"tasklist_delete_confirm":{let W=await H.onTasklistDeleteConfirm(String(J.guid??""));return e(p0(W.card),W.ok)}case"token_source_enable":{let{onTokenSourceEnable:W}=await Promise.resolve().then(() => (M3(),F3));return await W(H,String(J.source_id??"")),{toast:{type:"info",content:"已处理"}}}case"agent_identity_page":return M$(H.onAgentIdentityPage(String(J.panel_id??""),J.page,Q))}return{toast:{type:"info",content:"unknown action"}}}async function kD($,Z,J){let Y=String($?.notify_id??""),Q=String($?.button_id??"");if(!Y)return{toast:{type:"error",content:"回调缺少 notify_id"}};let H=D$(Y);if(!H)return A(`notify-callback: notify_id=${Y.slice(0,12)}… not found (expired or pre-restart)`),{toast:{type:"error",content:"通知已过期或已移除"}};if(H.unknownAt)return R$(H,e({toast:{type:"error",content:`外部回调可能已成功,但本地确认状态未知,已禁止自动重试${H.unknownReason?`: ${H.unknownReason}`:""}`}},!0));if(H.resolvedAt)return R$(H,{toast:{type:"info",content:"已处理过"}});if(Z2(Y))return R$(H,{toast:{type:"info",content:"处理中…"}});if(H.replyState?.status==="waiting"||H.replyState?.status==="sending")return R$(H,e({toast:{type:"error",content:"正在等待文字回复,请先发送或取消回复,再选择按钮"}},!1));let W=H.buttons.find((z)=>z.id===Q);if(!W)return A(`notify-callback: notify_id=${Y.slice(0,12)}… unknown button_id="${Q}"`),R$(H,e({toast:{type:"error",content:"未知按钮"}},!1));if(!H.callbackUrl){try{P4(H.notifyId,W.id,J)}catch(z){return R$(H,e({toast:{type:"error",content:`保存反馈结果失败: ${z instanceof Error?z.message:z}`}},!1))}return A(`notify-callback: notify_id=${Y.slice(0,12)}… resolved button="${Q}" by=${J.slice(0,8)}… (no callback, pull/display)`),R$(H,{...p0(U1(H,{status:"done",buttonId:W.id,text:W.text,operatorOpenId:J}))})}q4(H.notifyId);let X=zZ(CD(H,W,J));X.catch((z)=>{A(`notify-callback: notify_id=${H.notifyId.slice(0,12)}… phase-2 rejected: ${z instanceof Error?z.message:z}`)});let V=X.then((z)=>z==="retry"?"retry":"complete").catch(()=>"retry");return R$(H,{toast:{type:"info",content:`⏳ 已选择:${W.text} · 推送中…`},__cardActionCompletion:V})}async function CD($,Z,J){try{let Y=U1($,{status:"processing",buttonId:Z.id,text:Z.text,operatorOpenId:J});try{await Y$($.messageId,Y)}catch(X){A(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-1 (processing) updateCard failed: ${X instanceof Error?X.message:X}`)}let Q=await s5($,Z,J),H=Q.ok?"complete":"retry",W;if(Q.ok){let X=V6($.notifyId,Z.id,J);if(X.state==="complete")W={status:"delivered",buttonId:Z.id,text:Z.text,operatorOpenId:J,reply:Q.reply};else{H="unknown",W={status:"unknown",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:X.detail},A(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… callback succeeded but tombstone is UNKNOWN: ${X.detail}`);try{await T1($.chatId,`⚠️ 通知反馈的外部回调已成功,但本地确认状态未知;为避免重复副作用,已禁止自动重试。${X.detail}`)}catch(V){A(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… UNKNOWN warning receipt failed: ${V instanceof Error?V.message:V}`)}}}else W={status:"failed",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:Q.detail};try{let X=U1($,W);await Y$($.messageId,X)}catch(X){A(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-2 (final) presentation failed: ${X instanceof Error?X.message:X}`);try{await T1($.chatId,`⚠️ 通知反馈${H==="retry"?"失败且结果卡更新失败,可重新点击":"已执行,但结果卡更新失败"}: ${X instanceof Error?X.message:X}`)}catch(V){A(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… final fallback receipt failed: ${V instanceof Error?V.message:V}`)}}return A(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… button="${Z.id}" ${H==="complete"?"delivered":H==="unknown"?"unknown/non-retryable":`failed: ${Q.detail}`} by=${J.slice(0,8)}…`),H}finally{L4($.notifyId)}}function HZ($){return $.map((Z)=>typeof Z==="string"?Z:JSON.stringify(Z)).join(" ")}function bD(){if(process.platform==="win32"){A("debug: inject socket skipped on Windows (dev-only feature)");return}if(typeof Bun>"u"){A("debug: inject socket skipped (Bun runtime only — npm/Node build does not include it)");return}try{if(WZ(a$))c6(a$)}catch{}try{Bun.serve({unix:a$,fetch:async($)=>{let Z=new URL($.url),J=$.method==="GET"&&Z.pathname==="/model-state";if($.method!=="POST"&&!J)return new Response("unsupported debug method",{status:405});if(p6)return new Response("daemon shutdown in progress",{status:503});let Y={};if($.method==="POST")try{Y=await $.json()}catch{return new Response("bad json",{status:400})}if(!WZ(w4))return new Response("no debug context yet — send `[DEBUG]hi` from Feishu first",{status:412});let Q={};try{Q=JSON.parse(BD(w4,"utf8"))}catch(G){return new Response(`ctx read failed: ${G}`,{status:500})}let H=J?Z.searchParams.get("chat_id"):Y.chat_id;if(H!==void 0&&H!==Q.chat_id||Z.pathname!=="/"&&!H)return new Response("explicit debug chat_id must match the seeded context",{status:409});if(J){let G=U$.get(Q.chat_id);return G?Response.json(i3(G)):new Response("send md to open a model panel first",{status:404})}if(Z.pathname==="/model-action"){let G=U$.get(Q.chat_id);if(!G)return new Response("debug session not found",{status:404});try{if(typeof Y.message_id!=="string"||!Y.message_id.startsWith("om_"))throw Error("message_id required");let _=typeof Y.value?.panel_id==="string"?Y.value.panel_id.trim():"",K=G.modelPanels.get(_);if(!K?.messageId||K.messageId!==Y.message_id)throw Error("stale or mismatched model panel");let q=await t.im.v1.message.get({path:{message_id:Y.message_id}});if(q.code!==0)throw Error(`message.get failed: ${q.code} ${q.msg}`);let D=MX(Y,Q,q.data?.items?.[0],I.feishu.app_id,K.messageId);A(`debug: model action ${Y.value.kind} chat=${Q.chat_id.slice(0,8)}…`);let L=kV(D);return await l$.enqueue(Q.chat_id,async()=>{}),Response.json({admission:L,state:i3(G)})}catch(_){return new Response(_ instanceof Error?_.message:String(_),{status:400})}}if(Z.pathname!=="/")return new Response("unknown debug endpoint",{status:404});let W=String(Y.text??"");if(!W)return new Response("text required",{status:400});let X=`【自动化测试】:${W}`,V=await T(Q.chat_id,X);if(!V)return new Response("sendText failed — see daemon log",{status:502});let z={sender:{sender_id:{open_id:Q.sender_open_id}},message:{message_id:V,chat_id:Q.chat_id,message_type:"text",content:JSON.stringify({text:W}),create_time:String(Date.now())}};if(A(`debug: inject text=${JSON.stringify(W).slice(0,80)} msg_id=${V}`),!SV(z,"debug"))return new Response("daemon shutdown in progress",{status:503});if(Y.wait_for_handling===!0)await l$.enqueue(Q.chat_id,async()=>{});return new Response(JSON.stringify({ok:!0,msg_id:V}),{headers:{"content-type":"application/json"}})}});try{_D(a$,384)}catch{}A(`debug: inject socket listening at ${a$}`)}catch($){A(`debug: socket bind failed: ${$}`)}}async function yD(){A(`lodestar-daemon: pid ${process.pid} starting`);try{await H7({report:A,signal:TV.signal})}catch(x){A(`Agent 自动更新未完成,受影响的 Agent 将报告错误: ${x}`)}if(p6)return;OV=wZ(A);let{buildTokenSourcesFromConfig:$}=await Promise.resolve().then(() => (P3(),sH));$();let{refreshAllTokenSourceModels:Z}=await Promise.resolve().then(() => ($0(),rJ));await Z(),P8(),M8(),R8(),O8(),N8(),await a2(),setInterval(()=>{a2()},1800000);let{reconcileTasklistDeletions:J}=await Promise.resolve().then(() => (k3(),x3));try{await J()}catch(x){A(`tasklist deletion reconcile failed: ${x instanceof Error?x.message:x}`)}let Y,Q=Date.now(),H=0,W=!1,X=null,V=1500,z=90000,G=600000,_=3,K=null,q=0,D="",L=!1,P=(x)=>{A(`[ws] rebuild requested before WS init — ${x}`)},N=(x,c=0,O=!1)=>{let k=Date.now()+c;if(K){if(L||=O,k>=q){A(`[ws] rebuild already scheduled — ${x}`);return}clearTimeout(K)}q=k,D=x,L=O,K=setTimeout(()=>{let f=D,E0=L;K=null,q=0,D="",L=!1,P(f,E0)},c)},F={error:(x)=>A(`[ws-sdk error] ${HZ(x)}`),warn:(x)=>{let c=HZ(x);if(A(`[ws-sdk warn] ${c}`),c.includes("no pong/inbound"))N("ping-timeout: SDK liveness watchdog fired",2000,Date.now()-Q<G)},info:(x)=>A(`[ws-sdk] ${HZ(x)}`),debug:(x)=>{},trace:(x)=>{}},j=new q2.EventDispatcher({}),M=()=>{if(Q=Date.now(),H=0,X)clearTimeout(X),X=null};j.register({"im.message.receive_v1":async(x)=>{if(M(),!SV(x))throw Error("daemon shutdown in progress")}}),j.register({"card.action.trigger":async(x)=>{return M(),kV(x)}});let C=()=>new q2.WSClient({appId:I.feishu.app_id,appSecret:I.feishu.app_secret,loggerLevel:q2.LoggerLevel.info,logger:F,wsConfig:{pingTimeout:60},handshakeTimeoutMs:1e4,onReconnecting:()=>A("[ws] reconnecting — WS lost, SDK is retrying"),onReconnected:()=>m(),onError:(x)=>P(`SDK onError: ${x?.message??x}`)});P=(x,c=!1)=>{if(W){A(`[ws] rebuild skipped (already rebuilding) — ${x}`);return}if(K)clearTimeout(K),K=null,q=0;W=!0,H++,A(`[ws] rebuild #${H} (fresh WSClient) — ${x}`);let O=Y;try{O?.close({force:!0})}catch(k){A(`[ws] rebuild: old close failed: ${k}`)}if(Y=C(),Y.start({eventDispatcher:j}).catch((k)=>{A(`[ws] rebuild start failed: ${k}`),N(`fresh client start failed: ${k}`,V,c)}),W=!1,c)b()};let b=()=>{if(X)clearTimeout(X);let x=Date.now();X=setTimeout(()=>{if(X=null,Q>=x){H=0;return}if(H>=_){A(`[ws] STILL deaf after ${_} fresh rebuilds — auto-heal exhausted, `+"leaving last client up (no process exit). Restart the configured service or run lodestar-stop && lodestar-daemon"),H=0;return}P(`verify: no event ${Math.round((Date.now()-x)/1000)}s after rebuild`,!0)},z)},m=()=>{let x=Date.now()-Q<G;A("[ws] reconnected — swapping in a fresh WSClient (cluster-routing precaution; "+`recentlyActive=${x})`),H=0,N("post-reconnect precaution",V,x)};Y=C(),Y.start({eventDispatcher:j}).catch((x)=>{A(`[ws] initial start failed: ${x}`),N(`initial start failed: ${x}`,V,!1)}),A(`lodestar-daemon: WS start requested, watching ${V0.size} groups`);let y=15000,h=2,S=0;setInterval(()=>{let{state:x}=Y.getConnectionStatus();if(x==="connected"){S=0;return}if(x==="failed"||x==="idle"){S=0,P(`watchdog: state=${x}`);return}if(S++,A(`[ws] watchdog: state=${x} (${S}/${h})`),S>=h)S=0,P(`watchdog: stuck in '${x}' ~${Math.round(y*h/1000)}s`)},y),bD();for(let x of DH())zZ(l$.enqueue(x.chatId,()=>m6.recover(x))).catch((c)=>A(`notify-reply recovery failed: ${c instanceof Error?c.message:c}`));NX({bind:I.notify.bind,port:I.notify.port,extraHandler:(x,c,O)=>YV(x,c,O,{service:VZ,authorizeSession:(k)=>{for(let f of U$.values())if(f.acceptsAgentCapability(k))return f;return null}})}),VV(),kX(),vX(),await MD()}var RV=!1,p6=!1,I6=null,O1=0,XZ=null,OV,TV,UV=15000,EV=()=>{if(RV)return;RV=!0;try{let $=XZ??GZ();if(n2($),$.length>0)A(`alive marker: [${$.join(", ")}]`)}catch($){A(`alive marker write failed: ${$}`)}try{c6(f0)}catch{}try{c6(a$)}catch{}},U$,VZ,x4,l$,DD,NV,PD,AZ,UD=30000,B2,m6,SD;var CV=E(()=>{E3();s();u0();RX();j4();b6();b6();CX();yX();rX();QV();o3();zV();x0();g();S1();J0();s6();PV();MV();{let $=f4(f0);if($.state==="exit")console.error(`lodestar-daemon: already running (pid ${$.pid})`),process.exit(1);if(WZ(f0))try{c6(f0)}catch{}}KD(LD(f0),{recursive:!0});jZ(f0);TV=new AbortController;process.on("exit",EV);process.on("SIGTERM",()=>{L2("SIGTERM",0)});process.on("SIGINT",()=>{L2("SIGINT",0)});if(process.platform==="win32")process.on("SIGBREAK",()=>{L2("SIGBREAK",0)});process.on("unhandledRejection",($)=>{A(`unhandledRejection: ${$ instanceof Error?$.stack??$.message:$}`),L2("unhandledRejection",1)});process.on("uncaughtException",($)=>{A(`uncaughtException: ${$.stack??$.message}`),L2("uncaughtException",1)});U$=new Map,VZ=new t3,x4=new Set,l$=new YZ,DD=new QZ(30000),NV=new Set,PD=LV({actor:l$,key:($)=>String($?.message?.chat_id??""),execute:($,Z)=>OD($,Z)});AZ=FV({registry:U$,createSession:($,Z)=>new t0($,Z,{onLifecycleChange:g6,onCreateTempSession:jD,onDisbandTempSession:FD,onCancelAgentRuns:(J,Y,Q)=>VZ.cancelSessionRuns(J,Y,Q)}),ensureChatForSession:w8,disbandChatForSessionExact:v8,chatIdForSession:L9,clearSessionConversationState:C8,registerTempSessionLease:j8,hasTempSessionLease:F8,replaceTurnAnchors:n0,runExclusive:($,Z)=>l$.enqueue($,Z),log:A});B2=new Set,m6=bX({sendCard:d,updateCard:Y$,sendText:T,dispatch:s5,onWaitingChanged:($)=>U$.get($)?.refreshPendingAsks(),log:A});SD=DV({actor:l$,deduper:DD,scope:($)=>{let Z=String($?.action?.value?.kind??"");if(Z.startsWith("agent_identity_"))return"__agent_identities_global__";if(Z==="notify_callback"||Z==="notify_reply"||Z==="notify_reply_cancel"){let J=D$(String($?.action?.value?.notify_id??""));if(J)return J.chatId}return String($?.context?.open_chat_id??"")||"__notify_global__"},execute:xD,present:ED,presentExecutionFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");A(`handleCardAction ${J}: ${Z instanceof Error?Z.stack??Z.message:Z}`),await ND($,Z)},presentPresentationFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");A(`card-action presentation ${J}: ${Z instanceof Error?Z.message:Z}`),await T1(String($?.context?.open_chat_id??""),`⚠️ ${u6(J)}已执行,但结果呈现失败。`)},businessSucceeded:($,Z)=>{if(typeof Z?.__businessOk==="boolean")return Z.__businessOk;return $?.action?.value?.kind==="permission"&&$?.action?.value?.decision==="deny"||Z?.toast?.type!=="error"},completion:($,Z)=>{let J=Z?.__cardActionCompletion;return J&&typeof J.then==="function"?J:null},track:($)=>{zZ($)},onBackgroundError:($)=>{A(`card-action background: ${$ instanceof Error?$.stack??$.message:$}`)},responses:{accepted:($)=>({toast:{type:"info",content:`⏳ ${u6(String($?.action?.value?.kind??"unknown"))}已接收,后台处理中…`}}),inflight:()=>({toast:{type:"info",content:"相同操作正在处理…"}}),completed:()=>({toast:{type:"info",content:"该操作近期已执行或尝试;为防重复暂不再次执行,请查看原卡或群消息"}}),closed:()=>({toast:{type:"error",content:"服务正在重启,请稍后重试"}}),invalid:($,Z)=>({toast:{type:"error",content:Z}})}});yD().catch(($)=>{A(`boot fatal: ${$}`),L2("boot fatal",1)})});J0();s6();import{existsSync as bV,unlinkSync as fD}from"node:fs";var s0={reset:"\x1B[0m",bold:"\x1B[1m",yellow:"\x1B[33m",green:"\x1B[32m",red:"\x1B[31m"};async function vD(){if(!bV(j0)){if(process.stdin.isTTY){console.log(),console.log(`${s0.bold}${s0.yellow}Lodestar: 未找到配置, 启动安装向导...${s0.reset}`);let{runSetup:Z}=await Promise.resolve().then(() => (IZ(),hZ));await Z();return}console.error(`${s0.red}Lodestar: 未找到配置 ${j0}${s0.reset}`),console.error(`请在交互式 cmd / PowerShell 里运行 ${s0.green}lodestar-setup${s0.reset} 完成首次配置 (或直接运行 ${s0.green}lodestar-daemon${s0.reset} 也会触发同一个向导)。`),process.exit(1)}let $=f4(f0);if($.state==="exit")console.error(`${s0.yellow}Lodestar: 已经有一个 daemon 在运行 (pid ${$.pid})${s0.reset}`),console.error(" • 想看日志:"+(process.platform==="win32"?" %LOCALAPPDATA%\\Lodestar\\daemon-YYYY-MM-DD.log":" ~/.local/share/lodestar/daemon-YYYY-MM-DD.log")),console.error(" • 想停: 任务管理器结束 pid 上面那个号 (Windows) / `kill "+$.pid+"` (Linux/macOS)"),console.error(` • 误判 / 已经死了: 手删 ${f0} 后再跑`),process.exit(1);if(bV(f0))try{fD(f0)}catch{}await Promise.resolve().then(() => (CV(),wD))}vD().catch(($)=>{console.error("lodestar fatal:",$?.message??$),process.exit(1)});
|
|
489
|
+
`),imageKeys:Z,fileKeys:J}}async function ND($,Z=Date.now()){let J=$?.message;if(!J)return;let Q=($?.sender?.sender_id??$?.event?.sender?.sender_id??J?.sender?.sender_id)?.open_id??"",H=J.message_id;if(H&&P2.has(H))return;if(H){if(P2.add(H),P2.size>200){let M=[...P2];P2.clear();for(let j of M.slice(-100))P2.add(j)}}let W=Number(J.create_time??0);if(zV(W,Z,ED)){if(_(`drop stale message ${H} ageAtReceipt=${Math.round((Z-W)/1000)}s`),H)b0(H,"CrossMark");return}let X=J.chat_id,V={};try{V=JSON.parse(J.content??"{}")}catch{}let z=J.message_type==="text"?V.text??"":"";if(typeof z==="string"&&z.startsWith("[DEBUG]")){try{PD(v4,JSON.stringify({chat_id:X,sender_open_id:Q,seeded_at:new Date().toISOString(),seeded_msg_id:H??""},null,2)),_(`debug: seeded inject context chat=${X.slice(0,8)}… sender=${Q.slice(0,8)}…`)}catch(j){_(`debug: seed context failed: ${j}`)}let M=z.slice(7);V.text=M,J.content=JSON.stringify(V)}let G=_0.get(X);if(!G)await t2(),G=_0.get(X);if(!G)G=await c8(X)??void 0;if(!G){_(`unknown chat ${X}, dropping message`),await E(X,"❌ 无法识别群名。请确认:① 机器人已被拉进本群;② 群已设置名称(未命名群拿不到群名,无法映射项目目录)。设置后再发一条消息即可。");return}let A=l8(G);d1(A,X);let K=SV(X,A),L={};try{L=JSON.parse(J.content??"{}")}catch{}let D=J.message_type,q="",P=!1,x=[];if(D==="text")q=(L.text??"").trim();else if(D==="post"){let M=TD(L);P=M.imageKeys.length>0||M.fileKeys.length>0,q=M.markdown.trim();for(let j of M.imageKeys){let k=await s2(J.message_id,j,"image");if(k)x.push(k)}for(let j of M.fileKeys){let k=await s2(J.message_id,j.key,"file",j.name);if(k)x.push(k)}}if(D==="text"&&q){if(await K.runCommand(q,Q))return}if((D==="text"||D==="post")&&q&&!P&&await GV({reply:()=>l6.consume({chatId:X,openId:Q,messageId:H??"",text:q,createTime:W,parentId:J.parent_id}),hasQuestion:()=>K.hasPendingAsk(),answerQuestion:()=>K.onAskMessageAnswer(q,Q,H??"")}))return;if(D==="text"&&q&&await K.consumeModelCustomMessage(q,Q))return;let F=AV(D,L);if(F){let M=await s2(J.message_id,F.key,F.type,F.name);if(!M){await E(X,_V(D));return}if(x.push(M),!q&&F.displayText)q=F.displayText}if(!q&&x.length===0){_(`drop empty message ${H} type=${D}`);return}if(await K.onMultiMessageInbound(q,x,Q,H??""))return;await K.onUserMessage(q||"(empty)",x,Q,H??"")}function i6($){return{permission:"权限决定",menu:"菜单选择",provider_select:"账号选择",model_page:"模型翻页",model_list_open:"模型列表",model_add:"显示模型",model_remove:"隐藏模型",model_custom_remove:"删除补录模型",model_select:"模型选择",model_custom_prompt:"模型补录",model_panel_cancel:"取消模型补录",model_effort_select:"模型 effort 选择",ask:"问题回答",worktree_disband:"worktree 解散",temp_fork_select:"会话分叉",temp_back_select:"会话回滚",temp_resume_select:"会话恢复",tasklist_enable:"启用任务清单",tasklist_delete_prompt:"删除任务清单",tasklist_delete_confirm:"确认删除任务清单",token_source_enable:"启用账号",agent_identity_page:"Agent 身份翻页",notify_callback:"通知反馈",notify_reply:"通知回复",notify_reply_cancel:"取消通知回复"}[$]??$}function SD($){return $?.card?.type==="raw"&&$.card.data&&typeof $.card.data==="object"?$.card.data:null}function $0($,Z,J){return{...$,__businessOk:Z,...J?{__businessMessage:J}:{}}}function U$($,Z){return{...Z,__cardActionMessageId:$.messageId,__cardActionChatId:$.chatId}}function R$($){return $0($.card?l0($.card):{toast:{type:$.ok?"success":"error",content:$.message}},$.ok)}async function N1($,Z){if(!$){_(`card-action: cannot send receipt without chat_id: ${Z}`);return}if(!await w($,Z))_(`card-action: visible receipt MISS chat=${$.slice(0,8)}… text=${Z.slice(0,120)}`)}async function xD($,Z){if(Z?.__cardActionPresented)return;let J=String($?.action?.value?.kind??"unknown"),Y=i6(J),Q=String(Z?.__cardActionChatId??$?.__cardActionChatId??$?.context?.open_chat_id??""),H=String(Z?.__cardActionMessageId??$?.context?.open_message_id??""),W=SD(Z),X=Z?.__businessOk===!1&&typeof Z?.__businessMessage==="string"?` 业务失败: ${Z.__businessMessage.replace(/\s+/g," ").trim().slice(0,300)}。`:"";if(W&&H)try{await Q$(H,W);return}catch(L){_(`card-action: ${J} original-card update failed: ${L instanceof Error?L.message:L}`),await N1(Q,`⚠️ ${Y}已处理,但原卡更新失败。${X}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":"请重新打开操作面板。"}`);return}if(W){await N1(Q,`⚠️ ${Y}已处理,但回调缺少原卡 message_id,无法更新。${X}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":""}`);return}if(J==="notify_callback"&&Z?.__cardActionCompletion)return;let V=Z?.toast,z=typeof V?.content==="string"&&V.content.trim()?V.content.trim():`${Y}已完成`,G=J==="permission"&&String($?.action?.value?.decision??"")==="deny",A=Z?.__businessOk===!1||V?.type==="error"&&!G;if(!A&&new Set(["permission","ask","token_source_enable"]).has(J))return;await N1(Q,`${A?"❌":"✅"} ${Y}: ${z}`)}async function kD($,Z){let J=String($?.action?.value?.kind??"unknown"),Y=Z instanceof Error?Z.message:String(Z);await N1(String($?.__cardActionChatId??$?.context?.open_chat_id??""),`❌ ${i6(J)}失败: ${Y}`)}function xV($){return CD.accept($)}async function bD($){let Z=$?.action,J=Z?.value;if(!J?.kind)return;let Y=$?.context?.open_chat_id??"",Q=$?.operator?.open_id??"";if(J.kind==="notify_callback"||J.kind==="notify_reply"||J.kind==="notify_reply_cancel"){let W=String(J.notify_id??""),X=P$(W);if(X)$.__cardActionChatId=X.chatId;if(J.kind==="notify_callback")return await yD(J,Y,Q);let V=J.kind==="notify_reply"?await l6.open(W,Y,Q):await l6.cancel(W,String(J.reply_id??""),Y,Q),z=$0({toast:{type:V.ok?"success":"error",content:V.message},__cardActionPresented:V.presented===!0},V.ok);return X?U$(X,z):z}let H=O$.get(Y);if(!H)return $0({toast:{type:"error",content:"会话不存在,请先发消息启动"}},!1);switch(J.kind){case"permission":{let W=String(J.decision??"");if(!["allow","allow_always","deny"].includes(W))return{toast:{type:"error",content:"无效的权限决定"}};let X=await H.onPermissionDecision(J.request_id,W,Q);return $0({toast:{type:X.ok?W==="deny"?"error":"success":"error",content:X.message}},X.ok)}case"menu":{let W=Number(J.choice??-1);try{if(!Number.isInteger(W)||W<0)throw Error("无效的菜单选项");return await H.onUserMessage(`(menu choice ${W+1})`),$0(l0(I$({title:"\uD83D\uDCCB 菜单选择",message:`已选择第 ${W+1} 项`,ok:!0})),!0)}catch(X){let V=X instanceof Error?X.message:String(X);return $0(l0(I$({title:"\uD83D\uDCCB 菜单选择",message:V,ok:!1})),!1)}}case"provider_select":{let W=await H.onProviderSelect(String(J.source_id??""),String(J.panel_id??""));return R$(W)}case"model_page":{let W=await H.onModelPage(String(J.panel_id??""),String(J.source_id??""),Number(J.page));return R$(W)}case"model_list_open":{let W=String(J.panel_id??""),X=String(J.source_id??"");if(J.mode!=="add"&&J.mode!=="select")throw Error("模型管理模式无效");return R$(await(J.mode==="add"?H.onModelAddOpen(W,X):H.onProviderSelect(X,W)))}case"model_add":case"model_remove":case"model_custom_remove":return R$(await H.onModelListEdit(String(J.panel_id??""),String(J.source_id??""),String(J.model??""),J.kind==="model_add"?"add":J.kind==="model_remove"?"remove":"delete"));case"model_select":{let W=await H.onModelSelect(String(J.model??""),String(J.panel_id??""),Q,J);return R$(W)}case"model_custom_prompt":{let W=await H.onModelCustomPrompt(String(J.source_id??""),String(J.panel_id??""),String($?.context?.open_message_id??""));return R$(W)}case"model_panel_cancel":{let W=await H.onModelPanelCancel(String(J.panel_id??""));return R$(W)}case"model_effort_select":{let W=await H.onModelEffortSelect(String(J.model??""),String(J.effort??""),String(J.panel_id??""),Q,String(J.provider??""));return R$(W)}case"ask":{let W=H.askBlockReason(String(J.tool_use_id??""));if(W)return $0({toast:{type:"error",content:W}},!1);if(J.custom){let z=(Z?.form_value??Z?.input??{})?.custom_answer??Z?.input_value??"",G=await H.onAskCustomAnswer(J.tool_use_id,J.question_idx??0,z,Q);return $0({toast:{type:G?"success":"error",content:G?"已回答":z.trim()?"问题已失效或答案未被接受":"请输入答案"}},G)}let X=await H.onAskAnswer(J.tool_use_id,J.question_idx??0,J.option_idx,Q);return $0({toast:{type:X?"success":"error",content:X?"已回答":"问题已失效或选项无效"}},X)}case"worktree_disband":{let W=await H.onWorktreeDisband(String(J.slug??""));return $0(l0(W.card),W.ok)}case"temp_fork_select":{let W=await H.onForkSelect(String(J.panel_id??""),String(J.choice_id??""),Q);return $0(W.replaceCard===!1?{toast:{type:"error",content:W.message}}:l0(I$({title:"\uD83D\uDD31 会话分叉",message:W.message,ok:W.ok})),W.ok)}case"temp_back_select":{let W=await H.onBackSelect(String(J.panel_id??""),String(J.choice_id??""),Q);return $0(W.replaceCard===!1?{toast:{type:"error",content:W.message}}:l0(I$({title:"⏪ 会话回滚",message:W.message,ok:W.ok})),W.ok)}case"temp_resume_select":{let W=await H.onResumeSelect(String(J.panel_id??""),String(J.choice_id??""),Q);if(W.replaceCard===!1)return $0({toast:{type:"error",content:W.message}},W.ok);if(!W.resumePresentation)throw Error("rs selection result missing trusted presentation snapshot");return $0(l0(x5({...W.resumePresentation,message:W.message,ok:W.ok})),W.ok,W.message)}case"tasklist_enable":{let W=await H.onTasklistEnable();return $0(l0(W.card),W.ok)}case"tasklist_delete_prompt":{let W=H.onTasklistDeletePrompt(String(J.guid??""));return $0(l0(W.card),W.ok)}case"tasklist_delete_confirm":{let W=await H.onTasklistDeleteConfirm(String(J.guid??""));return $0(l0(W.card),W.ok)}case"token_source_enable":{let{onTokenSourceEnable:W}=await Promise.resolve().then(() => (O3(),U3));return await W(H,String(J.source_id??"")),{toast:{type:"info",content:"已处理"}}}case"agent_identity_page":return R$(H.onAgentIdentityPage(String(J.panel_id??""),J.page,Q))}return{toast:{type:"info",content:"unknown action"}}}async function yD($,Z,J){let Y=String($?.notify_id??""),Q=String($?.button_id??"");if(!Y)return{toast:{type:"error",content:"回调缺少 notify_id"}};let H=P$(Y);if(!H)return _(`notify-callback: notify_id=${Y.slice(0,12)}… not found (expired or pre-restart)`),{toast:{type:"error",content:"通知已过期或已移除"}};if(H.unknownAt)return U$(H,$0({toast:{type:"error",content:`外部回调可能已成功,但本地确认状态未知,已禁止自动重试${H.unknownReason?`: ${H.unknownReason}`:""}`}},!0));if(H.resolvedAt)return U$(H,{toast:{type:"info",content:"已处理过"}});if(H2(Y))return U$(H,{toast:{type:"info",content:"处理中…"}});if(H.replyState?.status==="waiting"||H.replyState?.status==="sending")return U$(H,$0({toast:{type:"error",content:"正在等待文字回复,请先发送或取消回复,再选择按钮"}},!1));let W=H.buttons.find((z)=>z.id===Q);if(!W)return _(`notify-callback: notify_id=${Y.slice(0,12)}… unknown button_id="${Q}"`),U$(H,$0({toast:{type:"error",content:"未知按钮"}},!1));if(!H.callbackUrl){try{M4(H.notifyId,W.id,J)}catch(z){return U$(H,$0({toast:{type:"error",content:`保存反馈结果失败: ${z instanceof Error?z.message:z}`}},!1))}return _(`notify-callback: notify_id=${Y.slice(0,12)}… resolved button="${Q}" by=${J.slice(0,8)}… (no callback, pull/display)`),U$(H,{...l0(E1(H,{status:"done",buttonId:W.id,text:W.text,operatorOpenId:J}))})}P4(H.notifyId);let X=AZ(wD(H,W,J));X.catch((z)=>{_(`notify-callback: notify_id=${H.notifyId.slice(0,12)}… phase-2 rejected: ${z instanceof Error?z.message:z}`)});let V=X.then((z)=>z==="retry"?"retry":"complete").catch(()=>"retry");return U$(H,{toast:{type:"info",content:`⏳ 已选择:${W.text} · 推送中…`},__cardActionCompletion:V})}async function wD($,Z,J){try{let Y=E1($,{status:"processing",buttonId:Z.id,text:Z.text,operatorOpenId:J});try{await Q$($.messageId,Y)}catch(X){_(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-1 (processing) updateCard failed: ${X instanceof Error?X.message:X}`)}let Q=await Z3($,Z,J),H=Q.ok?"complete":"retry",W;if(Q.ok){let X=A6($.notifyId,Z.id,J);if(X.state==="complete")W={status:"delivered",buttonId:Z.id,text:Z.text,operatorOpenId:J,reply:Q.reply};else{H="unknown",W={status:"unknown",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:X.detail},_(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… callback succeeded but tombstone is UNKNOWN: ${X.detail}`);try{await N1($.chatId,`⚠️ 通知反馈的外部回调已成功,但本地确认状态未知;为避免重复副作用,已禁止自动重试。${X.detail}`)}catch(V){_(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… UNKNOWN warning receipt failed: ${V instanceof Error?V.message:V}`)}}}else W={status:"failed",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:Q.detail};try{let X=E1($,W);await Q$($.messageId,X)}catch(X){_(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-2 (final) presentation failed: ${X instanceof Error?X.message:X}`);try{await N1($.chatId,`⚠️ 通知反馈${H==="retry"?"失败且结果卡更新失败,可重新点击":"已执行,但结果卡更新失败"}: ${X instanceof Error?X.message:X}`)}catch(V){_(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… final fallback receipt failed: ${V instanceof Error?V.message:V}`)}}return _(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… button="${Z.id}" ${H==="complete"?"delivered":H==="unknown"?"unknown/non-retryable":`failed: ${Q.detail}`} by=${J.slice(0,8)}…`),H}finally{j4($.notifyId)}}function zZ($){return $.map((Z)=>typeof Z==="string"?Z:JSON.stringify(Z)).join(" ")}function fD(){if(process.platform==="win32"){_("debug: inject socket skipped on Windows (dev-only feature)");return}if(typeof Bun>"u"){_("debug: inject socket skipped (Bun runtime only — npm/Node build does not include it)");return}try{if(GZ(r$))p6(r$)}catch{}try{Bun.serve({unix:r$,fetch:async($)=>{let Z=new URL($.url),J=$.method==="GET"&&Z.pathname==="/model-state";if($.method!=="POST"&&!J)return new Response("unsupported debug method",{status:405});if(f0)return new Response("daemon shutdown in progress",{status:503});let Y={};if($.method==="POST")try{Y=await $.json()}catch{return new Response("bad json",{status:400})}if(!GZ(v4))return new Response("no debug context yet — send `[DEBUG]hi` from Feishu first",{status:412});let Q={};try{Q=JSON.parse(DD(v4,"utf8"))}catch(G){return new Response(`ctx read failed: ${G}`,{status:500})}let H=J?Z.searchParams.get("chat_id"):Y.chat_id;if(H!==void 0&&H!==Q.chat_id||Z.pathname!=="/"&&!H)return new Response("explicit debug chat_id must match the seeded context",{status:409});if(J){let G=O$.get(Q.chat_id);return G?Response.json(a3(G)):new Response("send md to open a model panel first",{status:404})}if(Z.pathname==="/model-action"){let G=O$.get(Q.chat_id);if(!G)return new Response("debug session not found",{status:404});try{if(typeof Y.message_id!=="string"||!Y.message_id.startsWith("om_"))throw Error("message_id required");let A=typeof Y.value?.panel_id==="string"?Y.value.panel_id.trim():"",K=G.modelPanels.get(A);if(!K?.messageId||K.messageId!==Y.message_id)throw Error("stale or mismatched model panel");let L=await s.im.v1.message.get({path:{message_id:Y.message_id}});if(L.code!==0)throw Error(`message.get failed: ${L.code} ${L.msg}`);let D=FX(Y,Q,L.data?.items?.[0],v.feishu.app_id,K.messageId);_(`debug: model action ${Y.value.kind} chat=${Q.chat_id.slice(0,8)}…`);let q=xV(D);return await T$.enqueue(Q.chat_id,async()=>{}),Response.json({admission:q,state:a3(G)})}catch(A){return new Response(A instanceof Error?A.message:String(A),{status:400})}}if(Z.pathname!=="/")return new Response("unknown debug endpoint",{status:404});let W=String(Y.text??"");if(!W)return new Response("text required",{status:400});let X=`【自动化测试】:${W}`,V=await E(Q.chat_id,X);if(!V)return new Response("sendText failed — see daemon log",{status:502});let z={sender:{sender_id:{open_id:Q.sender_open_id}},message:{message_id:V,chat_id:Q.chat_id,message_type:"text",content:JSON.stringify({text:W}),create_time:String(Date.now())}};if(_(`debug: inject text=${JSON.stringify(W).slice(0,80)} msg_id=${V}`),!NV(z,"debug"))return new Response("daemon shutdown in progress",{status:503});if(Y.wait_for_handling===!0)await T$.enqueue(Q.chat_id,async()=>{});return new Response(JSON.stringify({ok:!0,msg_id:V}),{headers:{"content-type":"application/json"}})}});try{LD(r$,384)}catch{}_(`debug: inject socket listening at ${r$}`)}catch($){_(`debug: socket bind failed: ${$}`)}}async function vD(){_(`lodestar-daemon: pid ${process.pid} starting`),S1.load();let{buildTokenSourcesFromConfig:$}=await Promise.resolve().then(() => (M3(),tH));if(f0)return;$();let{refreshAllTokenSourceModels:Z}=await Promise.resolve().then(() => (Z0(),oJ));if(f0)return;if(await Z(),f0)return;if(F8(),U8(),O8(),E8(),x8(),await t2(),f0)return;setInterval(()=>{t2()},1800000);let{reconcileTasklistDeletions:J}=await Promise.resolve().then(() => (y3(),b3));if(f0)return;try{await J()}catch(U){_(`tasklist deletion reconcile failed: ${U instanceof Error?U.message:U}`)}if(f0)return;let Y,Q=Date.now(),H=0,W=!1,X=null,V=1500,z=90000,G=600000,A=3,K=null,L=0,D="",q=!1,P=(U)=>{_(`[ws] rebuild requested before WS init — ${U}`)},x=(U,b=0,H0=!1)=>{if(f0)return;let l=Date.now()+b;if(K){if(q||=H0,l>=L){_(`[ws] rebuild already scheduled — ${U}`);return}clearTimeout(K)}L=l,D=U,q=H0,K=setTimeout(()=>{let W0=D,b4=q;K=null,L=0,D="",q=!1,P(W0,b4)},b)},F={error:(U)=>_(`[ws-sdk error] ${zZ(U)}`),warn:(U)=>{let b=zZ(U);if(_(`[ws-sdk warn] ${b}`),b.includes("no pong/inbound"))x("ping-timeout: SDK liveness watchdog fired",2000,Date.now()-Q<G)},info:(U)=>_(`[ws-sdk] ${zZ(U)}`),debug:(U)=>{},trace:(U)=>{}},M=new j2.EventDispatcher({}),j=()=>{if(Q=Date.now(),H=0,X)clearTimeout(X),X=null};M.register({"im.message.receive_v1":async(U)=>{if(j(),!NV(U))throw Error("daemon shutdown in progress")}}),M.register({"card.action.trigger":async(U)=>{return j(),xV(U)}});let k=()=>new j2.WSClient({appId:v.feishu.app_id,appSecret:v.feishu.app_secret,loggerLevel:j2.LoggerLevel.info,logger:F,wsConfig:{pingTimeout:60},handshakeTimeoutMs:1e4,onReconnecting:()=>_("[ws] reconnecting — WS lost, SDK is retrying"),onReconnected:()=>c(),onError:(U)=>P(`SDK onError: ${U?.message??U}`)});P=(U,b=!1)=>{if(f0)return;if(W){_(`[ws] rebuild skipped (already rebuilding) — ${U}`);return}if(K)clearTimeout(K),K=null,L=0;W=!0,H++,_(`[ws] rebuild #${H} (fresh WSClient) — ${U}`);let H0=Y;try{H0?.close({force:!0})}catch(l){_(`[ws] rebuild: old close failed: ${l}`)}if(Y=k(),Y.start({eventDispatcher:M}).catch((l)=>{_(`[ws] rebuild start failed: ${l}`),x(`fresh client start failed: ${l}`,V,b)}),W=!1,b)C()};let C=()=>{if(X)clearTimeout(X);let U=Date.now();X=setTimeout(()=>{if(X=null,Q>=U){H=0;return}if(H>=A){_(`[ws] STILL deaf after ${A} fresh rebuilds — auto-heal exhausted, `+"leaving last client up (no process exit). Restart the configured service or run lodestar-stop && lodestar-daemon"),H=0;return}P(`verify: no event ${Math.round((Date.now()-U)/1000)}s after rebuild`,!0)},z)},c=()=>{let U=Date.now()-Q<G;_("[ws] reconnected — swapping in a fresh WSClient (cluster-routing precaution; "+`recentlyActive=${U})`),H=0,x("post-reconnect precaution",V,U)};Y=k();let y=15000,m=2,N=0,f=setInterval(()=>{if(f0)return;let{state:U}=Y.getConnectionStatus();if(U==="connected"){N=0;return}if(U==="failed"||U==="idle"){N=0,P(`watchdog: state=${U}`);return}if(N++,_(`[ws] watchdog: state=${U} (${N}/${m})`),N>=m)N=0,P(`watchdog: stuck in '${U}' ~${Math.round(y*m/1000)}s`)},y);OV=()=>{if(clearInterval(f),K)clearTimeout(K);if(X)clearTimeout(X);Y.close({force:!0})};let I=qH();EX({bind:v.notify.bind,port:v.notify.port,extraHandler:(U,b,H0)=>JV(U,b,H0,{service:_Z,authorizeSession:(l)=>{for(let W0 of O$.values())if(W0.acceptsAgentCapability(l))return W0;return null}})}),XV(),xX(),fX();let T=S1.enqueue();UV=yZ(_,{enabled:v.runtime.agent_auto_update}),Y.start({eventDispatcher:M}).catch((U)=>{_(`[ws] initial start failed: ${U}`),x(`initial start failed: ${U}`,V,!1)}),_(`lodestar-daemon: WS start requested, watching ${_0.size} groups`),fD();for(let U of I)AZ(T$.enqueue(U.chatId,()=>l6.recover(U))).catch((b)=>_(`notify-reply recovery failed: ${b instanceof Error?b.message:b}`));await T}var MV=!1,f0=!1,u6=null,d$=0,UV,OV,RV=15000,TV=()=>{if(MV)return;MV=!0;try{S1.persist()}catch($){_(`alive marker write failed: ${$}`)}try{p6(v0)}catch{}try{p6(r$)}catch{}},O$,_Z,T$,S1,FD,EV,MD,KZ,ED=30000,P2,l6,CD;var kV=S(()=>{x3();e();p0();MX();R4();v6();v6();kX();bX();oX();YV();s3();VV();x0();g();b1();Y0();Z7();DV();FV();{let $=h4(v0);if($.state==="exit")console.error(`lodestar-daemon: already running (pid ${$.pid})`),process.exit(1);if(GZ(v0))try{p6(v0)}catch{}}qD(jD(v0),{recursive:!0});FZ(v0);process.on("exit",TV);process.on("SIGTERM",()=>{F2("SIGTERM",0)});process.on("SIGINT",()=>{F2("SIGINT",0)});if(process.platform==="win32")process.on("SIGBREAK",()=>{F2("SIGBREAK",0)});process.on("unhandledRejection",($)=>{_(`unhandledRejection: ${$ instanceof Error?$.stack??$.message:$}`),F2("unhandledRejection",1)});process.on("uncaughtException",($)=>{_(`uncaughtException: ${$.stack??$.message}`),F2("uncaughtException",1)});O$=new Map,_Z=new $Z,T$=new XZ,S1=new HZ({readMarker:f8,writeMarker:w8,sessions:()=>O$.values(),chatIdForSession:F9,sessionFor:SV,actor:T$,isShuttingDown:()=>f0,log:_}),FD=new VZ(30000),EV=new Set,MD=LV({actor:T$,key:($)=>String($?.message?.chat_id??""),execute:($,Z)=>ND($,Z)});KZ=jV({registry:O$,createSession:($,Z)=>{let J=new s0($,Z,{onLifecycleChange:RD,onCreateTempSession:UD,onDisbandTempSession:OD,onCancelAgentRuns:(Y,Q,H)=>_Z.cancelSessionRuns(Y,Q,H)});return S1.transferPending(J),J},ensureChatForSession:h8,disbandChatForSessionExact:g8,chatIdForSession:F9,clearSessionConversationState:y8,registerTempSessionLease:M8,hasTempSessionLease:R8,replaceTurnAnchors:a0,runExclusive:($,Z)=>T$.enqueue($,Z),log:_});P2=new Set,l6=CX({sendCard:a,updateCard:Q$,sendText:E,dispatch:Z3,onWaitingChanged:($)=>O$.get($)?.refreshPendingAsks(),log:_});CD=qV({actor:T$,deduper:FD,scope:($)=>{let Z=String($?.action?.value?.kind??"");if(Z.startsWith("agent_identity_"))return"__agent_identities_global__";if(Z==="notify_callback"||Z==="notify_reply"||Z==="notify_reply_cancel"){let J=P$(String($?.action?.value?.notify_id??""));if(J)return J.chatId}return String($?.context?.open_chat_id??"")||"__notify_global__"},execute:bD,present:xD,presentExecutionFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");_(`handleCardAction ${J}: ${Z instanceof Error?Z.stack??Z.message:Z}`),await kD($,Z)},presentPresentationFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");_(`card-action presentation ${J}: ${Z instanceof Error?Z.message:Z}`),await N1(String($?.context?.open_chat_id??""),`⚠️ ${i6(J)}已执行,但结果呈现失败。`)},businessSucceeded:($,Z)=>{if(typeof Z?.__businessOk==="boolean")return Z.__businessOk;return $?.action?.value?.kind==="permission"&&$?.action?.value?.decision==="deny"||Z?.toast?.type!=="error"},completion:($,Z)=>{let J=Z?.__cardActionCompletion;return J&&typeof J.then==="function"?J:null},track:($)=>{AZ($)},onBackgroundError:($)=>{_(`card-action background: ${$ instanceof Error?$.stack??$.message:$}`)},responses:{accepted:($)=>({toast:{type:"info",content:`⏳ ${i6(String($?.action?.value?.kind??"unknown"))}已接收,后台处理中…`}}),inflight:()=>({toast:{type:"info",content:"相同操作正在处理…"}}),completed:()=>({toast:{type:"info",content:"该操作近期已执行或尝试;为防重复暂不再次执行,请查看原卡或群消息"}}),closed:()=>({toast:{type:"error",content:"服务正在重启,请稍后重试"}}),invalid:($,Z)=>({toast:{type:"error",content:Z}})}});vD().catch(($)=>{_(`boot fatal: ${$}`),F2("boot fatal",1)})});Y0();Z7();import{existsSync as CV,unlinkSync as ID}from"node:fs";var e0={reset:"\x1B[0m",bold:"\x1B[1m",yellow:"\x1B[33m",green:"\x1B[32m",red:"\x1B[31m"};async function gD(){if(!CV(M0)){if(process.stdin.isTTY){console.log(),console.log(`${e0.bold}${e0.yellow}Lodestar: 未找到配置, 启动安装向导...${e0.reset}`);let{runSetup:Z}=await Promise.resolve().then(() => (hZ(),vZ));await Z();return}console.error(`${e0.red}Lodestar: 未找到配置 ${M0}${e0.reset}`),console.error(`请在交互式 cmd / PowerShell 里运行 ${e0.green}lodestar-setup${e0.reset} 完成首次配置 (或直接运行 ${e0.green}lodestar-daemon${e0.reset} 也会触发同一个向导)。`),process.exit(1)}let $=h4(v0);if($.state==="exit")console.error(`${e0.yellow}Lodestar: 已经有一个 daemon 在运行 (pid ${$.pid})${e0.reset}`),console.error(" • 想看日志:"+(process.platform==="win32"?" %LOCALAPPDATA%\\Lodestar\\daemon-YYYY-MM-DD.log":" ~/.local/share/lodestar/daemon-YYYY-MM-DD.log")),console.error(" • 想停: 任务管理器结束 pid 上面那个号 (Windows) / `kill "+$.pid+"` (Linux/macOS)"),console.error(` • 误判 / 已经死了: 手删 ${v0} 后再跑`),process.exit(1);if(CV(v0))try{ID(v0)}catch{}await Promise.resolve().then(() => (kV(),hD))}gD().catch(($)=>{console.error("lodestar fatal:",$?.message??$),process.exit(1)});
|