@leviyuan/lodestar 0.16.3 → 0.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lodestar.js +131 -131
- package/package.json +1 -1
package/dist/lodestar.js
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`),Q=parseInt((J[0]??"").trim(),10),Y=(J[1]??"").trim();if(!Number.isFinite(Q)||Q<=0)return{state:"continue"};if(!Y)try{return process.kill(Q,0),{state:"exit",pid:Q}}catch{return{state:"continue"}}if(
|
|
4
|
-
${
|
|
5
|
-
`)}var
|
|
6
|
-
${K.green}>${K.reset} `)).trim();if(!Q&&Z.default!==void 0)return Z.default;if(!Q&&Z.required){console.log(`${K.red}必填,请重新输入${K.reset}`);continue}return Q}}function
|
|
2
|
+
var xW=Object.defineProperty;var bW=($)=>$;function CW($,Z){this[$]=bW.bind(null,Z)}var G1=($,Z)=>{for(var J in Z)xW($,J,{get:Z[J],enumerable:!0,configurable:!0,set:CW.bind(Z,J)})};var N=($,Z)=>()=>($&&(Z=$($=0)),Z);import{homedir as fW}from"node:os";import{join as l}from"node:path";function l5($,Z,J){if($)return $;if(Z)return l(Z,"lodestar");return J}function wW(){if(p5)return l(process.env.APPDATA??l(d2,"AppData","Roaming"),"Lodestar");return l(d2,".config","lodestar")}function vW(){if(p5)return l(process.env.LOCALAPPDATA??l(d2,"AppData","Local"),"Lodestar");return l(d2,".local","share","lodestar")}var d2,p5,H8,d,P$,k$,_1,W8,X8,V8,z8,A8,o2,y0,a2,x0,i5,n5,r2,G8,b0,t2;var L$=N(()=>{d2=fW(),p5=process.platform==="win32";H8=l5(process.env.LODESTAR_CONFIG_DIR,process.env.XDG_CONFIG_HOME,wW()),d=l5(process.env.LODESTAR_DATA_DIR,process.env.XDG_DATA_HOME,vW()),P$=process.env.LODESTAR_CONFIG??l(H8,"config.toml"),k$=l(d,"daemon.pid"),_1=l(d,"daemon.log"),W8=l(d,"session-chat-map.json"),X8=l(d,"session-resume-map.json"),V8=l(d,"session-turns-map.json"),z8=l(d,"session-model-map.json"),A8=l(d,"temp-session-leases.json"),o2=l(d,"tasklist-map.json"),y0=l(d,"agent-runs"),a2=l(d,"agent-session-ids.json"),x0=l(d,"managed-claude-plugin"),i5=l(d,"context-window-cache.json"),n5=l(d,"notify-callbacks.json"),r2=l(d,"alive-on-shutdown.json"),G8=l(d,"inbox"),b0=l(d,"debug.sock"),t2=l(d,"debug-context.json")});import{execSync as d5}from"node:child_process";import{readFileSync as o5,writeFileSync as hW}from"node:fs";function gW(){return process.argv[1]??`pid:${process.pid}`}function IW($){try{if(process.platform==="linux")return o5(`/proc/${$}/cmdline`,"utf8").replace(/\0/g," ").trim();if(process.platform==="darwin")return d5(`ps -p ${$} -o args=`,{encoding:"utf8",timeout:2000}).trim();if(process.platform==="win32")return d5(`powershell -NoProfile -Command "(Get-CimInstance Win32_Process -Filter 'ProcessId=${$}').CommandLine"`,{encoding:"utf8",timeout:5000}).trim()||null;return null}catch{return null}}function cW($,Z){if(!Number.isFinite($)||$<=0||!Z)return!1;let J=IW($);if(!J)return!1;if(process.platform==="win32")return J.toLowerCase().includes(Z.toLowerCase());return J.includes(Z)}function s2($){let Z="";try{Z=o5($,"utf8")}catch{return{state:"continue"}}let J=Z.split(`
|
|
3
|
+
`),Q=parseInt((J[0]??"").trim(),10),Y=(J[1]??"").trim();if(!Number.isFinite(Q)||Q<=0)return{state:"continue"};if(!Y)try{return process.kill(Q,0),{state:"exit",pid:Q}}catch{return{state:"continue"}}if(cW(Q,Y))return{state:"exit",pid:Q};return{state:"continue"}}function a5($){hW($,`${process.pid}
|
|
4
|
+
${gW()}`)}var _8=()=>{};import{chmodSync as mW,closeSync as K8,fsyncSync as r5,mkdirSync as uW,openSync as t5,renameSync as pW,unlinkSync as lW,writeFileSync as iW}from"node:fs";import{randomUUID as nW}from"node:crypto";import{dirname as s5}from"node:path";function rW($){let Z=s5($);uW(Z,{recursive:!0,mode:aW})}function e5($,Z,J){rW($);let Q=`${$}.${process.pid}.${nW()}.tmp`,Y=null;try{Y=t5(Q,"wx",J),iW(Y,Z),r5(Y),K8(Y),Y=null,pW(Q,$);try{mW($,J)}catch{}if(process.platform!=="win32"){let H=null;try{H=t5(s5($),"r"),r5(H)}catch{}finally{if(H!==null)try{K8(H)}catch{}}}}catch(H){if(Y!==null)try{K8(Y)}catch{}try{lW(Q)}catch{}throw H}}function v$($,Z){e5($,Z,dW)}function $3($,Z){e5($,Z,oW)}function X$($,Z){v$($,JSON.stringify(Z,null,2)+`
|
|
5
|
+
`)}var dW=384,oW=448,aW=448;var h$=()=>{};var Y3={};G1(Y3,{runSetup:()=>_X});import{execSync as tW,spawn as q1}from"node:child_process";import{existsSync as Z4,mkdirSync as Q3,readFileSync as sW}from"node:fs";import{createInterface as eW}from"node:readline/promises";import{delimiter as $X,dirname as ZX,join as J4}from"node:path";import{homedir as JX}from"node:os";import{fileURLToPath as QX}from"node:url";async function C0($,Z={}){while(!0){let J=Z.default?`${K.dim} [${Z.default}]${K.reset}`:"",Q=(await K1.question(`${K.cyan}? ${K.reset}${$}${J}
|
|
6
|
+
${K.green}>${K.reset} `)).trim();if(!Q&&Z.default!==void 0)return Z.default;if(!Q&&Z.required){console.log(`${K.red}必填,请重新输入${K.reset}`);continue}return Q}}function YX($){let Z="═".repeat(58);console.log(`
|
|
7
7
|
${K.bold}${K.cyan}╔${Z}╗${K.reset}`),console.log(`${K.bold}${K.cyan}║ ${$.padEnd(54)} ║${K.reset}`),console.log(`${K.bold}${K.cyan}╚${Z}╝${K.reset}
|
|
8
|
-
`)}function
|
|
8
|
+
`)}function e2($,Z,J){console.log(`
|
|
9
9
|
${K.bold}${K.yellow}[${$}/${Z}] ${J}${K.reset}
|
|
10
|
-
`)}function q8($){return $.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}function
|
|
11
|
-
`),{path:J}}catch(Z){return{error:Z?.message??String(Z)}}}function
|
|
12
|
-
${K.red}安装失败。${K.reset}`),console.error("请手动运行后再开向导:"),console.error(` ${K.cyan}npm install -g @anthropic-ai/claude-code@latest${K.reset}`),console.error(` ${K.cyan}lodestar-setup${K.reset}`),K1.close(),process.exit(1)
|
|
10
|
+
`)}function q8($){return $.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}function $4($){let Z=process.env.PATH??"";if(!Z)return null;let J=process.platform==="win32"?[`${$}.cmd`,`${$}.bat`,`${$}.exe`,$]:[$];for(let Q of Z.split($X)){if(!Q)continue;for(let Y of J){let H=J4(Q,Y);if(Z4(H))return H}}return null}function Z3($){let Z=process.platform==="win32"?"npm.cmd":"npm";return new Promise((J)=>{let Q=q1(Z,["install","-g",`${$}@latest`],{stdio:"inherit",shell:process.platform==="win32"});Q.on("exit",(Y)=>J(Y===0)),Q.on("error",()=>J(!1))})}function J3($){try{let Z=tW(`"${$}" login status 2>&1`,{timeout:1e4}).toString();return/Logged in using ChatGPT/i.test(Z)}catch{return!1}}async function HX($){return new Promise((Z)=>{let J=q1($,["login"],{stdio:"inherit",shell:process.platform==="win32"});J.on("exit",(Q)=>Z(Q===0)),J.on("error",()=>Z(!1))})}function WX(){return process.env.CLAUDE_CONFIG_DIR||J4(JX(),".claude")}async function XX($){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(),Q=(Array.isArray(J?.data)?J.data:[]).map((_)=>typeof _?.display_name==="string"&&_.display_name?_.display_name:String(_?.id??"")).filter(Boolean);if(!Q.length)return null;let Y=(_)=>{let q=_.match(/(\d+(?:\.\d+)?)/);return q?Number(q[1]):-1},H=(_)=>_.replace(/-Turbo|-Air$/i,""),X=[...Q.filter((_)=>!/-Turbo|-Air/i.test(_))].sort((_,q)=>Y(q)-Y(_)),V=X[0],A=X[X.length-1],G={};if(V)G.ANTHROPIC_DEFAULT_OPUS_MODEL=`${V}[1m]`,G.ANTHROPIC_DEFAULT_SONNET_MODEL=`${V}[1m]`;if(A&&H(A)!==H(V))G.ANTHROPIC_DEFAULT_HAIKU_MODEL=A;return Object.keys(G).length?G:null}catch{return null}}async function VX($){try{let Z=WX();Q3(Z,{recursive:!0});let J=J4(Z,"settings.json"),Q={};if(Z4(J)){let X=sW(J,"utf8");try{let V=JSON.parse(X);if(!V||typeof V!=="object"||Array.isArray(V))return{error:`${J} 内容不是 JSON 对象, 拒绝覆盖, 请手动检查`};Q=V}catch{return{error:`${J} 解析失败 (JSON 语法错), 拒绝覆盖, 请手动修复后重跑`}}}let Y=Q.env&&typeof Q.env==="object"&&!Array.isArray(Q.env)?Q.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 XX($);if(W)Object.assign(H,W);return Q.env={...Y,...H},v$(J,JSON.stringify(Q,null,2)+`
|
|
11
|
+
`),{path:J}}catch(Z){return{error:Z?.message??String(Z)}}}function zX($){try{if(process.platform==="win32")q1(process.env.ComSpec??"cmd.exe",["/c","start",'""',$],{detached:!0,stdio:"ignore",windowsHide:!0}).unref();else if(process.platform==="darwin")q1("open",[$],{detached:!0,stdio:"ignore"}).unref();else q1("xdg-open",[$],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function AX($,Z){try{let Q=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(Q.tenant_access_token)return{ok:!0};return{ok:!1,error:`飞书拒绝: code=${Q.code} msg=${Q.msg??"(no msg)"}`}}catch(J){return{ok:!1,error:`网络错误: ${J?.message??String(J)}`}}}function GX(){try{let $=ZX(QX(import.meta.url)),Z=J4($,"lodestar.js");if(!Z4(Z))return{error:`找不到 daemon bundle: ${Z}`};let J=q1(process.execPath,[Z],{detached:!0,stdio:"ignore",windowsHide:!0});return J.unref(),{pid:J.pid}}catch($){return{error:$?.message??String($)}}}async function _X(){if(!process.stdin.isTTY)console.error(`${K.red}lodestar-setup: stdin 不是 TTY,无法交互式输入。${K.reset}`),console.error("请直接在 cmd / PowerShell / Terminal 里跑,不要 pipe 或重定向 stdin。"),process.exit(1);if(Z4(P$)){if(console.log(`${K.yellow}发现已有配置: ${P$}${K.reset}`),(await C0("覆盖? (y/N)",{default:"n"})).toLowerCase()!=="y"){console.log("已取消"),K1.close();return}}YX("Lodestar 安装向导"),console.log("Lodestar 把 Feishu (飞书) 群聊接到 AI agent。"),console.log("默认后端是 Claude Code; Codex 是可选第二后端, 群里发 model 一键切换。"),console.log("每个群对应一个项目目录, agent 在那里跑、能读写文件。"),console.log(),console.log(`${K.yellow}⚠ Claude 官方限制:${K.reset}`),console.log(` ${K.bold}Claude 订阅 (Pro/Max OAuth 登录) 不支持本项目${K.reset},`),console.log(" 必须走 API 方式 —— 推荐 GLM Coding Plan, 或自备 Anthropic API key。"),console.log(),console.log("本向导依次做 4 件事:"),console.log(` ${K.dim}1) 确保 Claude Code CLI 已装好${K.reset}`),console.log(` ${K.dim}2) GLM Coding Plan API key (推荐, 可选) + Codex (可选)${K.reset}`),console.log(` ${K.dim}3) Feishu 自建应用 (含权限 / 事件 / 发版 + 凭据测试)${K.reset}`),console.log(` ${K.dim}4) 工作目录, 自动启动 daemon${K.reset}`),console.log(),await K1.question(`${K.dim}按 Enter 开始 (Ctrl+C 退出)...${K.reset}`),e2(1,4,"准备 Claude Code CLI");let $=$4("claude");if($)console.log(`${K.green}✓ claude CLI 已就位${K.reset}: ${K.dim}${$}${K.reset}`);else{if(console.log(`${K.yellow}未在 PATH 找到 claude CLI, 自动安装...${K.reset}`),console.log(`${K.dim}运行: npm install -g @anthropic-ai/claude-code@latest${K.reset}`),console.log(),!await Z3("@anthropic-ai/claude-code"))console.error(`
|
|
12
|
+
${K.red}安装失败。${K.reset}`),console.error("请手动运行后再开向导:"),console.error(` ${K.cyan}npm install -g @anthropic-ai/claude-code@latest${K.reset}`),console.error(` ${K.cyan}lodestar-setup${K.reset}`),K1.close(),process.exit(1);$=$4("claude"),console.log(`${K.green}✓ 安装完成${K.reset}: ${K.dim}${$??"(应该装好了, 但 PATH 找不到 — 重开终端再试)"}${K.reset}`)}console.log(),console.log(`${K.dim}下一步可选配 GLM Coding Plan 自动写入路由; 不配则用本机 Claude Code 现有配置。${K.reset}`),console.log(`${K.dim}记住: 别用 \`claude\` 走订阅 OAuth 登录 —— 订阅不支持本项目, 要用 API key。${K.reset}`),e2(2,4,"GLM Coding Plan (推荐, 可选)"),console.log("GLM Coding Plan 给 Claude Code 接 GLM 系列模型 (支持 1M token 上下文, 中文友好)。"),console.log("订阅后在智谱开放平台拿一个 API key, 粘到下面 —— 向导自动写进 ~/.claude/settings.json。"),console.log(` ${K.dim}拿 key: https://open.bigmodel.cn → 控制台 → API Keys${K.reset}`),console.log(` ${K.dim}不给也行: 以本机 Claude Code 现有配置启动 (确保是 API key 方式, 非订阅)。${K.reset}`),console.log();let Z=await C0("GLM API key (直接回车跳过)",{});if(Z){let q=await VX(Z);if("path"in q)console.log(`${K.green}✓ GLM 路由已写入${K.reset}: ${K.dim}${q.path}${K.reset}`),console.log(`${K.dim}模型 slots 按端点当前列表自动选取(最新一代 opus/sonnet, 1M ctx)${K.reset}`);else console.log(`${K.red}✗ 写入失败:${K.reset} ${q.error}`),console.log(`${K.dim}跳过 GLM 配置, 以本机 Claude Code 现有配置启动。${K.reset}`)}else console.log(`${K.dim}已跳过 GLM, 以本机 Claude Code 现有配置启动。${K.reset}`);if(console.log(),console.log(`${K.bold}Codex (可选第二后端)${K.reset}`),console.log(` ${K.dim}想用 Codex 的话, 登录 ChatGPT 订阅即可, 模型/effort 走 ~/.codex/config.toml, 群里发 model 切换。${K.reset}`),(await C0("现在顺便配置 Codex 后端吗?",{default:"n"})).toLowerCase()==="y"){let q=$4("codex");if(!q){if(console.log(`${K.dim}未找到 codex CLI, 安装 @openai/codex...${K.reset}`),await Z3("@openai/codex"))q=$4("codex")}if(q&&J3(q))console.log(`${K.green}✓ Codex 已登录 ChatGPT${K.reset}`);else if(q)if(console.log(`${K.dim}启动 \`codex login\`...${K.reset}`),await HX(q)&&J3(q))console.log(`${K.green}✓ Codex 已登录 ChatGPT${K.reset}`);else console.log(`${K.yellow}Codex 登录未完成 — 不影响默认 Claude 后端; 需要时随时跑 codex login。${K.reset}`);else console.log(`${K.yellow}Codex 安装失败 — 不影响默认 Claude 后端; 需要时手动 npm i -g @openai/codex。${K.reset}`)}else console.log(`${K.dim}已跳过 Codex (需要时随时跑 codex login, 群里发 model 切)。${K.reset}`);e2(3,4,"Feishu 自建应用");let Q="https://open.feishu.cn/app";console.log("打开飞书开放平台 (浏览器):"),console.log(` ${K.cyan}${Q}${K.reset}`),zX(Q),console.log(`${K.dim}(如果浏览器没自动开, 复制上面 URL 粘到浏览器)${K.reset}`),console.log(),console.log(`${K.bold}详细操作步骤:${K.reset}`),console.log(),console.log(` ${K.bold}① 创建应用${K.reset}`),console.log(` 点 "创建企业自建应用", 填名字 (如 ${K.dim}Lodestar${K.reset}), logo 随意。`),console.log(),console.log(` ${K.bold}② 添加机器人能力${K.reset}`),console.log(` 左侧菜单 "${K.cyan}添加应用能力${K.reset}" → 找到 "机器人" → 点 "${K.bold}添加${K.reset}" 按钮。`),console.log(),console.log(` ${K.bold}③ 申请权限 (左侧 "${K.cyan}权限管理${K.reset}" → "${K.bold}开通权限${K.reset}")${K.reset}`),console.log(` ${K.yellow}缺一个都会让 daemon 启动后默默丢消息, 一定要全开。${K.reset}`),console.log(` ${K.dim}消息类:${K.reset}`),console.log(` • ${K.bold}im:message:send_as_bot${K.reset} ${K.dim}# 以机器人身份发消息${K.reset}`),console.log(` • ${K.bold}im:message${K.reset} ${K.dim}# 接收/操作消息 (核心)${K.reset}`),console.log(` • ${K.bold}im:chat${K.reset} ${K.dim}# 读/写群信息 (匹配群名 ↔ 项目目录)${K.reset}`),console.log(` • ${K.bold}im:chat:create${K.reset} ${K.dim}# wt: 自动创建 worktree 群${K.reset}`),console.log(` • ${K.bold}im:chat:delete${K.reset} ${K.dim}# wt: 解散 worktree 群${K.reset}`),console.log(` • ${K.bold}im:chat.members:read${K.reset} ${K.dim}# wt: 判断发起人是否已在群内${K.reset}`),console.log(` • ${K.bold}im:chat.members:write_only${K.reset} ${K.dim}# wt: 把发起人拉进已有 worktree 群${K.reset}`),console.log(` • ${K.bold}im:resource${K.reset} ${K.dim}# 上传/下载附件 (图文双向)${K.reset}`),console.log(` • ${K.bold}im:message.urgent${K.reset} ${K.dim}# 加急推送 (锁屏通知 / Ask)${K.reset}`),console.log(` • ${K.bold}im:message.group_msg${K.reset} ${K.dim}# 敏感: 接收群里所有消息${K.reset}`),console.log(` ${K.dim}└ 关键: 没它机器人只收 @ 自己的消息, 拿不到群里其他对话, 一定要开${K.reset}`),console.log(` ${K.dim}└ 敏感权限要走审批: 申请时填用途, 个人开发者通常秒过${K.reset}`),console.log(` • ${K.bold}im:message.group_at_msg:readonly${K.reset} ${K.dim}# 读 @ 机器人消息 (兜底)${K.reset}`),console.log(` ${K.dim}卡片类 (Card Kit):${K.reset}`),console.log(` • ${K.bold}cardkit:card:read${K.reset} ${K.dim}# 读卡片状态${K.reset}`),console.log(` • ${K.bold}cardkit:card:write${K.reset} ${K.dim}# 创建/更新卡片 (流式渲染核心)${K.reset}`),console.log(),console.log(` ${K.bold}④ 订阅事件 (左侧 "${K.cyan}事件与回调${K.reset}", 拆两个子页:)${K.reset}`),console.log(` ${K.dim}a)${K.reset} ${K.bold}事件配置${K.reset} 页:`),console.log(` ${K.yellow}• "订阅方式" → 选 "长连接" → 点保存${K.reset}`),console.log(` • 添加事件: ${K.bold}im.message.receive_v1${K.reset} ${K.dim}# 收群消息${K.reset}`),console.log(` ${K.dim}b)${K.reset} ${K.bold}回调配置${K.reset} 页:`),console.log(` ${K.yellow}• "订阅方式" → 选 "长连接" → 点保存${K.reset}`),console.log(` • 添加事件: ${K.bold}card.action.trigger${K.reset} ${K.dim}# 卡片按钮点击回调${K.reset}`),console.log(),console.log(` ${K.bold}⑤ 发布版本${K.reset}`),console.log(` 页面顶部 "${K.bold}创建版本${K.reset}" → 滚到底点 "${K.bold}保存${K.reset}" → 弹框点 "${K.bold}发布${K.reset}"。`),console.log(` ${K.yellow}没发版的应用收不到任何事件 — 这步九成新手会忘!${K.reset}`),console.log(),console.log(` ${K.bold}⑥ 拿凭据${K.reset}`),console.log(` 左侧 "凭证与基础信息" → 顶部 ${K.bold}App ID${K.reset} (${K.dim}cli_...${K.reset}) 和 ${K.bold}App Secret${K.reset}, 待会粘到下面。`),console.log(),console.log(` ${K.bold}⑦ 把机器人拉进群${K.reset}`),console.log(" 想用的飞书群 → 群设置 → 群机器人 → 添加机器人 → 选你的应用。"),console.log(` ${K.yellow}群名要等于 projects_root 下的项目目录名${K.reset} (下一步设, 默认是用户主目录)。`),console.log();let Y="",H="";while(!0){Y=await C0("App ID (以 cli_ 开头)",{required:!0}),H=await C0("App Secret",{required:!0}),console.log(`${K.dim}测试中... (调 tenant_access_token endpoint)${K.reset}`);let q=await AX(Y,H);if(q.ok){console.log(`${K.green}✓ Feishu 凭据测试通过${K.reset}`);break}if(console.log(`${K.red}✗ 测试失败:${K.reset} ${q.error}`),console.log(`${K.dim}最常见原因: app_id / app_secret 抄错, 或应用还没 "发布上线" (步骤 ⑤)。${K.reset}`),console.log(),(await C0("重新填? (Y/n)",{default:"y"})).toLowerCase()==="n")console.log(`${K.yellow}已取消, 配置未写盘。${K.reset}`),K1.close(),process.exit(1)}e2(4,4,"工作目录 + 启动"),console.log("每个 Feishu 群对应 projects_root 下同名的目录。"),console.log();let W=process.platform==="win32"?process.env.USERPROFILE??"C:\\Users\\Default":process.env.HOME??"/root",X=await C0("projects_root",{default:W});Q3(H8,{recursive:!0});let V=["# Lodestar config — generated by `lodestar-setup`","# Edit by hand or re-run setup to overwrite.","","[feishu]",`app_id = "${q8(Y)}"`,`app_secret = "${q8(H)}"`,"","[runtime]",`projects_root = "${q8(X)}"`,""];v$(P$,V.join(`
|
|
13
13
|
`)),console.log(`
|
|
14
14
|
${K.green}${K.bold}✓ 配置已写入${K.reset}`),console.log(` ${K.cyan}${P$}${K.reset}`),console.log(`
|
|
15
|
-
${K.bold}启动 daemon...${K.reset}`);let A=
|
|
16
|
-
`)){let Y=
|
|
15
|
+
${K.bold}启动 daemon...${K.reset}`);let A=GX(),G=process.platform==="win32"?"\\":"/",_=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(A.pid)console.log(`${K.green}✓ daemon 已在后台启动${K.reset} (pid ${A.pid})`),console.log(),console.log(`${K.bold}最后一步: 在 Feishu 验证${K.reset}`),console.log(" ① 把机器人拉进任意飞书群"),console.log(` ② 群名 = ${K.cyan}${X}${G}<群名>${K.reset} 下的目录名 (新群第一条消息会自动建)`),console.log(" ③ 在群里发任意一条消息, 默认由 Claude 接管"),console.log(` ${K.dim}(群里发 model 可选择已配置账号、动态模型和 effort)${K.reset}`),console.log(),console.log("日志 (按日滚动, 保留近 7 天):"),console.log(` ${K.cyan}${_}${K.reset}`),console.log(),console.log(`${K.dim}若长期跑后台, Linux 配 systemd --user,macOS 配 launchd,Windows 配任务计划程序。${K.reset}`);else console.log(`${K.yellow}启动失败: ${A.error}${K.reset}`),console.log(`手动运行: ${K.cyan}lodestar-daemon${K.reset}`);console.log(),K1.close()}var K,K1;var H3=N(()=>{L$();h$();K={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",green:"\x1B[32m",yellow:"\x1B[33m",cyan:"\x1B[36m",red:"\x1B[31m"},K1=eW({input:process.stdin,output:process.stdout})});import{readFileSync as KX}from"node:fs";import{homedir as X3}from"node:os";function W3($){return $.replace(/^~(?=\/|$)/,X3())}function qX($){let Z={_:{}},J="_";for(let Q of $.split(`
|
|
16
|
+
`)){let Y=BX(Q).trim();if(!Y)continue;let H=Y.match(/^\[([^\]]+)\]$/);if(H){J=H[1].trim(),Z[J]??={};continue}let W=Y.match(/^([\w.-]+)\s*=\s*(.+)$/);if(W){let X=W[2].trim(),V=X.startsWith('"')&&X.endsWith('"'),A=X.startsWith("'")&&X.endsWith("'");if(V||A){if(X=X.slice(1,-1),V)X=X.replace(/\\([\\"])/g,"$1")}Z[J][W[1]]=X}}return Z}function BX($){let Z=null,J=!1;for(let Q=0;Q<$.length;Q++){let Y=$[Q];if(Z==="double"){if(J){J=!1;continue}if(Y==="\\"){J=!0;continue}if(Y==='"')Z=null;continue}if(Z==="single"){if(Y==="'")Z=null;continue}if(Y==='"')Z="double";else if(Y==="'")Z="single";else if(Y==="#")return $.slice(0,Q)}return $}function V3(){let $;try{$=KX(P$,"utf8")}catch(U){throw process.stderr.write(`lodestar: cannot read config at ${P$}
|
|
17
17
|
`+" → 运行 `lodestar-setup` 走交互式向导生成 (Feishu / Codex / 工作目录)\n"+` → 或手写: 设 LODESTAR_CONFIG=/path/to/config.toml 覆盖默认路径
|
|
18
18
|
`+` [feishu]
|
|
19
19
|
app_id = "cli_xxx"
|
|
20
20
|
app_secret = "xxx"
|
|
21
21
|
|
|
22
|
-
`),U}let Z=
|
|
23
|
-
`;if(process.stderr.write(J),!P8())return;try{let Q=
|
|
22
|
+
`),U}let Z=qX($),J=Z.feishu?.app_id,Q=Z.feishu?.app_secret;if(!J||!Q)throw Error(`lodestar: ${P$} is missing [feishu].app_id / [feishu].app_secret`);let Y=W3(Z.runtime?.projects_root??X3()),H=(Z.runtime?.live_elapsed??"bucket").trim().toLowerCase();if(H!=="bucket"&&H!=="second")throw Error(`lodestar: [runtime].live_elapsed must be "bucket" or "second", got "${Z.runtime?.live_elapsed}"`);let W=H,X=Z.notify?.bind??"127.0.0.1",V=Z.notify?.port??"9876";if(!/^\d+$/.test(V.trim()))throw Error(`lodestar: [notify].port must be an integer, got "${V}"`);let A=Number.parseInt(V,10);if(!Number.isFinite(A)||A<=0||A>65535)throw Error(`lodestar: [notify].port must be 1..65535, got "${V}"`);let G=(U)=>{let P=Z[U]??{},j={};for(let[S,b]of Object.entries(P))if(typeof b==="string"&&b.length>0)j[S]=b;return j},_=()=>{let U={};for(let[P,j]of Object.entries(Z)){if(!P.startsWith("claude.models."))continue;let b=P.slice(14).trim();if(!b)continue;let y={};for(let[m,v]of Object.entries(j)){if(typeof v!=="string"||v.length===0)continue;if(m.trim()==="model")y.model=v}U[b]=y}return U},q=()=>{let U={},P="projects.";for(let[j,S]of Object.entries(Z)){if(!j.startsWith("projects."))continue;let b=j.slice(9).trim();if(!b)continue;let y={};for(let[m,v]of Object.entries(S)){if(typeof v!=="string"||v.length===0)continue;switch(m.trim()){case"cwd":y.cwd=v;break;case"setting_sources":y.settingSources=v;break;case"strict_mcp":y.strictMcp=v==="true";break;case"tools":y.tools=v;break;case"load_project_mcp":y.loadProjectMcp=v==="true";break}}U[b]=y}return U},B=()=>{let U={},P="token_source.";for(let[j,S]of Object.entries(Z)){if(!j.startsWith("token_source."))continue;let b=j.slice(13).trim();if(!b)continue;let y={};for(let[m,v]of Object.entries(S)){if(typeof v!=="string"||v.length===0)continue;let g=m.trim();if(g==="default")y.default=v==="true";else if(g==="agent"||g==="display"||g==="auth"||g==="base_url"||g==="auth_token"||g==="api_key"||g==="bin"||g==="model"||g==="effort"||g==="models"||g==="slots"||g==="usage")y[g]=v}U[b]=y}return U},R=G("codex.env"),L=G("claude.env"),F=Z.claude?.bin?W3(Z.claude.bin):void 0;return{feishu:{app_id:J,app_secret:Q},runtime:{projects_root:Y,live_elapsed:W},notify:{bind:X,port:A},codex:{env:R},claude:{bin:F,env:L,models:_()},projects:q(),token_sources:B()}}function z3(){w.token_sources=V3().token_sources}var w;var U$=N(()=>{L$();w=V3()});import{appendFileSync as _3,mkdirSync as RX,readdirSync as PX,unlinkSync as K3,existsSync as A3,statSync as LX,renameSync as DX,readFileSync as jX}from"node:fs";import{join as q3}from"node:path";function P8($="development"){return $!=="test"}function B3($){let Z=$.getFullYear(),J=String($.getMonth()+1).padStart(2,"0"),Q=String($.getDate()).padStart(2,"0");return`${Z}-${J}-${Q}`}function R3($,Z=d){return q3(Z,`${B8}${B3($)}${R8}`)}function MX($){if(!$.startsWith(B8)||!$.endsWith(R8))return null;let Z=$.slice(B8.length,$.length-R8.length),J=/^(\d{4})-(\d{2})-(\d{2})$/.exec(Z);if(!J)return null;let Q=new Date(Number(J[1]),Number(J[2])-1,Number(J[3]));return Number.isNaN(Q.getTime())?null:Q}function P3($,Z=new Date,J=FX){let Q;try{Q=PX($)}catch{return 0}let Y=new Date(Z.getFullYear(),Z.getMonth(),Z.getDate()),H=0;for(let W of Q){let X=MX(W);if(!X)continue;if(Math.round((Y.getTime()-X.getTime())/86400000)<J)continue;try{K3(q3($,W)),H++}catch{}}return H}function UX(){try{if(!A3(_1))return;let $=LX(_1);if(!$.isFile()||$.size===0)return;let Z=R3($.mtime);if(A3(Z)){_3(Z,jX(_1)),K3(_1);return}DX(_1,Z)}catch{}}function z($){let Z=new Date,J=`[${Z.toISOString()}] ${$}
|
|
23
|
+
`;if(process.stderr.write(J),!P8())return;try{let Q=B3(Z);if(G3!==Q)G3=Q,P3(d,Z);_3(R3(Z),J)}catch{}}var FX=7,B8="daemon-",R8=".log",G3=null;var h=N(()=>{L$();if(P8())try{RX(d,{recursive:!0})}catch{}if(P8()){UX();try{P3(d)}catch{}}});function e($){return typeof $==="string"&&$?$:void 0}function c($){return $!=null&&typeof $==="object"?$:null}function $0($){if($==null||$==="")return"-";return String($).replace(/\s+/g," ").slice(0,300)}function Q4($){if(!$)return"[]";let Z=Object.keys($),J=Z.slice(0,80),Q=Z.length>J.length?`,...+${Z.length-J.length}`:"";return`[${J.join(",")}${Q}]`}function EX($){let Z=$.slice(0,j8),J=$.length>Z.length?`,...+${$.length-Z.length}`:"";return`[${Z.join(",")}${J}]`}function TX($){let Z=c($);if(!Z)return null;let J=c(Z.event),Q=c(Z.payload);return c(Z.item)??c(Z.responseItem)??c(Z.rawItem)??c(J?.item)??c(J?.responseItem)??c(J?.rawItem)??c(Q?.item)??c(Q?.responseItem)??c(Q?.rawItem)??(r1(Z.type)?Z:null)??(J&&r1(J.type)?J:null)??(Q&&r1(Q.type)?Q:null)}function kX($){let Z=[],J=new WeakSet,Q=(Y,H,W)=>{if(Z.length>=j8||W>6)return;if(Array.isArray(Y)){if(H)Z.push(`${H}[]`);if(Y.length>0)Q(Y[0],H?`${H}[]`:"[]",W+1);return}if(Y==null||typeof Y!=="object")return;if(J.has(Y))return;J.add(Y);for(let X of Object.keys(Y)){if(Z.length>=j8)return;let V=H?`${H}.${X}`:X;Z.push(V),Q(Y[X],V,W+1)}};return Q($,"",0),Z}function F8($){let Z=new WeakSet,J;try{J=JSON.stringify($,(Q,Y)=>{if(typeof Y==="bigint")return`${Y.toString()}n`;if(typeof Y==="string"&&Y.length>D8)return`${Y.slice(0,D8)}...<truncated ${Y.length-D8} chars>`;if(Y!=null&&typeof Y==="object"){if(Z.has(Y))return"[Circular]";Z.add(Y)}return Y})??String($)}catch(Q){J=`<unserializable: ${Q}>`}if(J.length>L8)return`${J.slice(0,L8)}...<truncated ${J.length-L8} chars>`;return J}function O$($,Z){let J=c(Z),Q=J?c(J.params):null,Y=J?c(J.item)??c(Q?.item):null,H=J?e(J.method)??"-":"-";z([`codex-process: APP_SERVER_UNHANDLED_${$}`,`method=${$0(H)}`,`rootKeys=${Q4(J)}`,`itemKeys=${Q4(Y)}`,`payload=${F8(Z)}`].join(" "))}function M8($,Z,J){let Q=c(Z),Y=TX(Z),H=[`phase=${$0(J.phase??"event")}`,`method=${$0($)}`,`sourceMethod=${$0(J.sourceMethod)}`,`sourceType=${$0(J.sourceType)}`,`sessionId=${$0(J.sessionId)}`,`threadId=${$0(J.threadId)}`,`turnId=${$0(J.turnId)}`,`itemId=${$0(J.itemId)}`].join(" ");if(z(`codex-process: CONTEXT_COMPACTION_EVENT ${H} rootKeys=${Q4(Q)} itemKeys=${Q4(Y)}`),z(`codex-process: CONTEXT_COMPACTION_PATHS ${H} paths=${EX(kX(Z))}`),Y)z(`codex-process: CONTEXT_COMPACTION_ITEM ${H} item=${F8(Y)}`);z(`codex-process: CONTEXT_COMPACTION_PAYLOAD ${H} payload=${F8(Z)}`)}function r1($){if(typeof $!=="string")return null;return OX.has($)?$:null}function SX($,Z){if(Z==="item/started")return"start";if(Z==="item/completed"||Z==="rawResponseItem/completed")return"end";if($==="compacted")return"start";if($==="context_compacted"||L3.has(Z))return"end";return"event"}function U8($,Z){return D3($,c(Z)??{})}function O8($){let Z=c($);if(!Z)return null;let J=e(Z.method)??e(Z.type)??"raw_message";return D3(J,Z)}function D3($,Z){let J=c(Z.payload),Q=[Z,c(Z.event),J,c(Z.item),c(Z.responseItem),c(Z.rawItem)].filter((V)=>V!=null),Y=null;for(let V of Q)if(Y=r1(V.type),Y)break;if(!L3.has($)&&!Y)return null;let H=c(Z.item)??c(Z.responseItem)??c(Z.rawItem),W=Y==="compacted"&&J?J:H&&r1(H.type)?H:Z,X=c(W.item)??c(W.responseItem)??c(W.rawItem)??H??{};return{...W,threadId:e(W.threadId)??e(W.thread_id)??e(Z.threadId)??e(Z.thread_id),turnId:e(W.turnId)??e(W.turn_id)??e(Z.turnId)??e(Z.turn_id),itemId:e(W.itemId)??e(W.item_id)??e(X.id)??e(X.itemId)??e(X.item_id),timestamp:e(Z.timestamp)??e(W.timestamp),recordType:e(Z.type),phase:SX(Y,$),sourceMethod:$,sourceType:Y??$}}var L3,OX,L8=200000,D8=50000,j8=400;var E8=N(()=>{h();L3=new Set(["thread/compacted","context/compacted","context_compacted","contextCompacted"]),OX=new Set(["compacted","compaction","compaction_trigger","context_compacted","context_compaction","contextCompaction","ContextCompaction"])});function t1($){return $!=null&&typeof $==="object"?$:null}function Z0($){return typeof $==="number"&&Number.isFinite($)?$:void 0}function j3($){return Object.values($).some((Z)=>typeof Z==="number"&&Number.isFinite(Z))}function Y4($,Z){return $?Z0($[Z]):void 0}function B1($){let Z=t1($);if(!Z)return null;let J=t1(Z.inputTokensDetails)??t1(Z.input_tokens_details),Q=t1(Z.outputTokensDetails)??t1(Z.output_tokens_details),Y={total_tokens:Z0(Z.totalTokens??Z.total_tokens),input_tokens:Z0(Z.inputTokens??Z.input_tokens),output_tokens:Z0(Z.outputTokens??Z.output_tokens),reasoning_output_tokens:Z0(Z.reasoningOutputTokens??Z.reasoning_output_tokens??Y4(Q,"reasoningTokens")??Y4(Q,"reasoning_tokens")),cache_creation_input_tokens:Z0(Z.cacheCreationInputTokens??Z.cache_creation_input_tokens),cache_read_input_tokens:Z0(Z.cachedInputTokens??Z.cached_input_tokens??Z.cacheReadInputTokens??Z.cache_read_input_tokens??Y4(J,"cachedTokens")??Y4(J,"cached_tokens"))};return j3(Y)?Y:null}function T8($,Z){let J=(Y)=>{let H=Z0($?.[Y]),W=Z0(Z?.[Y]);if(H===void 0&&W===void 0)return;return Math.max(0,(H??0)-(W??0))},Q={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 j3(Q)?Q:null}function k8($){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 F3($){let Z=$.trim();if(Z.length<2)return Z;let J=H4[Z[0]];if(!J||!Z.endsWith(J))return Z;let Q=Z.slice(1,-1);if(Z[0]==="'")return Q.replace(/''/g,"'");if(Z[0]==='"')return Q.replace(/\\"/g,'"');return Q}function N8($){let Z=yX(String($??"")),J=Z.split(`
|
|
24
24
|
`,1)[0]?.trim()??"",Y=(J.startsWith("#")&&!J.startsWith("#!")?J.replace(/^#\s*/,"").trim():"").replace(/^(?:desc|dec|description|说明|目的|用途)\s*[::]\s*/i,"").trim(),H=Y?Z.split(`
|
|
25
25
|
`).slice(1).join(`
|
|
26
|
-
`).trimStart():Z;return{description:Y,command:H||Z}}function R1($,Z=60){let{description:J,command:Q}=N8($);if(J)return J;return
|
|
27
|
-
`).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 Y=
|
|
28
|
-
`)}function S8($){let Z=$.trim(),J=Z[0];if(!
|
|
29
|
-
`).replace(/\s*"\s*'\$\(([^)]*)\)'/g,(W,X)=>` $(${X})`)}function
|
|
30
|
-
`)}var
|
|
26
|
+
`).trimStart():Z;return{description:Y,command:H||Z}}function R1($,Z=60){let{description:J,command:Q}=N8($);if(J)return J;return NX(Q).replace(/\s+/g," ").trim().slice(0,Z)}function NX($){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 yX($){let Z=$.replace(/\r\n/g,`
|
|
27
|
+
`).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 Y=bX(J[1]);return S8(Y||Z)}let Q=xX(Z);if(Q)return Q;return S8(Z)}function xX($){let Z=$.match(/^("[^"]*"|'[^']*'|“[^”]*”|\S+)\s+([\s\S]*)$/);if(!Z)return null;let J=F3(Z[1]).replace(/\.exe$/i,"");if(!/(?:^|[\\/])(?:powershell|pwsh)$/i.test(J))return null;let Q=Z[2];for(;;){let Y=Q.match(/^(-[A-Za-z][\w-]*)\s+([\s\S]*)$/);if(!Y)break;let H=Y[1].toLowerCase();if(H==="-command"||H==="-c")return S8(F3(Y[2]));if(Q=Y[2],H==="-executionpolicy"||H==="-inputformat"||H==="-outputformat")Q=Q.replace(/^(?:"[^"]*"|'[^']*'|\S+)\s+/,"")}return null}function bX($){let Z=$.trim();if(Z.length<2)return Z;let J=H4[Z[0]];if(!J||!Z.endsWith(J))return Z;let Q=Z.slice(1,-1);if(Z[0]==="'")return Q.replace(/'\\''/g,"'");return Q.replace(/\\(["\\$`])/g,"$1").replace(/\\n/g,`
|
|
28
|
+
`)}function S8($){let Z=$.trim(),J=Z[0];if(!H4[J])return Z;let Q=Z.slice(1);if(!/^#\s*(?:desc|dec|description|说明|目的|用途)\s*[::]/i.test(Q)&&!CX(Q,J))return Z;if(J!=='"')return Q.replace(/'\s*$/,"");return Q.replace(/\s*[”"]\s*$/,"").replace(/\\(["\\$`])/g,"$1").replace(/\\n/g,`
|
|
29
|
+
`).replace(/\s*"\s*'\$\(([^)]*)\)'/g,(W,X)=>` $(${X})`)}function CX($,Z){let J=H4[Z];for(let Q=0;Q<$.length;Q++){let Y=$[Q];if(Z==='"'&&Y==="\\"&&Q+1<$.length){Q++;continue}if(Y===J)return/^[\s]*$/.test($.slice(Q+1))}return!1}var H4;var W4=N(()=>{H4={'"':'"',"'":"'","“":"”"}});function D($){return $ instanceof Error?$.message:String($)}function A$($){return $.length<=16?$:`${$.slice(0,8)}…${$.slice(-4)}`}async function y8($,Z,J){let Q=null;try{return await Promise.race([$,new Promise((Y,H)=>{Q=setTimeout(()=>H(Error(`${J} timed out after ${Z/1000}s`)),Z)})])}finally{if(Q)clearTimeout(Q)}}import{isAbsolute as M3}from"node:path";function fX($){return $.kind==="fresh"?null:$.source.provider}function G$($,Z,J){let Q=fX($);if(Q&&Q!==Z)throw Error(`conversation launch provider mismatch: source=${Q} 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"||!M3($.source.cwd)))throw Error(`conversation launch source cwd is not absolute: ${String($.source.cwd)}`);if($.kind!=="fresh"&&J!==void 0){if(!M3(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")}var P1=()=>{};import{existsSync as wX,readFileSync as vX}from"node:fs";function U3($,Z){return`${$}:${Z}`}function hX(){if(!wX(a2))return;try{let $=JSON.parse(vX(a2,"utf8"));if($?.version!==1||!Array.isArray($.ids)||$.ids.some((Z)=>typeof Z!=="string"||!Z))throw Error("invalid delegated-agent session registry");s1=new Set($.ids)}catch($){x8=$ instanceof Error?$:Error(String($))}}function O3(){if(x8)throw Error(`delegated-agent session registry is unavailable: ${x8.message}`)}function E3($,Z){O3();let J=Z.trim();if(!J)throw Error("delegated-agent session id is empty");let Q=U3($,J);if(s1.has(Q))return;let Y=new Set(s1);Y.add(Q),X$(a2,{version:1,ids:[...Y].sort()}),s1=Y}function X4($,Z){return O3(),s1.has(U3($,Z))}var s1,x8=null;var V4=N(()=>{L$();h$();s1=new Set;hX()});import{closeSync as gX,existsSync as G4,mkdirSync as IX,openSync as cX,readdirSync as mX,readSync as uX,statSync as A4,writeFileSync as pX}from"node:fs";import{homedir as f0}from"node:os";import{delimiter as b8,isAbsolute as T3,join as g$}from"node:path";import{EventEmitter as lX}from"node:events";import{StringDecoder as k3}from"node:string_decoder";import{spawn as iX}from"cross-spawn";function $2(){if(process.platform!=="win32"){let $=g$(f0(),".local","npm-global","bin","codex");if(G4($))return $;let Z=g$(f0(),".local","bin","codex");if(G4(Z))return Z}return nX()??"codex"}function nX(){let $=process.env.PATH??"";if(!$)return null;let Z=process.platform==="win32"?["codex.cmd","codex.bat","codex.exe","codex"]:["codex"];for(let J of $.split(b8)){if(!J)continue;for(let Q of Z){let Y=g$(J,Q);if(G4(Y))return Y}}return null}function dX(){if(process.platform==="win32")return process.env.PATH??"";return[...new Set([g$(f0(),".local","npm-global","bin"),g$(f0(),".local","bin"),g$(f0(),".bun","bin"),...(process.env.PATH??"").split(b8),"/usr/local/bin","/usr/bin","/bin"].filter(Boolean))].join(b8)}function N3($){return typeof $==="string"&&/\bselected\s+model\s+is\s+at\s+capacity\b/i.test($)}function $V(){return["app-server","--listen","stdio://"]}function ZV($,Z){return{cwd:$,stdio:["pipe","pipe","pipe"],shell:!1,env:Z}}function S$($){return typeof $==="string"&&JV.includes($)}function QV($){if(!Array.isArray($))return[];let Z=new Set,J=[];for(let Q of $){let Y=typeof Q==="string"?Q:typeof Q==="object"&&Q?Q.reasoningEffort:null;if(!S$(Y)||Z.has(Y))continue;Z.add(Y);let H=typeof Q==="object"&&Q&&typeof Q.description==="string"?Q.description:"";J.push({reasoningEffort:Y,description:H})}return J}function C8($,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:{status:$.status,revisedPrompt:f3($)}}}return null}function f3($){let Z=$?.revisedPrompt??$?.revised_prompt;return typeof Z==="string"&&Z?Z:void 0}function y3($){if(!$||!G4(S3))return null;let Z=null,J=[S3];while(J.length){let Q=J.pop(),Y;try{Y=mX(Q,{withFileTypes:!0})}catch(H){z(`codex-process: cannot scan Codex session dir ${Q}: ${H instanceof Error?H.message:H}`);continue}for(let H of Y){let W=g$(Q,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=A4(W).mtimeMs;if(!Z||X>Z.mtimeMs)Z={path:W,mtimeMs:X}}catch(X){z(`codex-process: cannot stat Codex rollout ${W}: ${X instanceof Error?X.message:X}`)}}}return Z?.path??null}function w3($,Z,J=oX){let Q=$?.savedPath??$?.saved_path;if(typeof Q==="string"&&Q)return Q;let Y=$?.result;if(typeof Y==="string"){let H=YV($,Z,J);if(H)return H;if(Y.length>2048){let W=v3($);return z(`codex-process: image generation inline result could not be decoded id=${W} length=${Y.length}`),`Image generation returned ${Y.length} chars of inline data, but Lodestar could not materialize it as an image file.`}return Y}if(Y&&typeof Y==="object"){let H=Y.savedPath??Y.saved_path??Y.path;if(typeof H==="string"&&H)return H;return JSON.stringify(Y,null,2)}return""}function YV($,Z,J){let Q=$?.result;if(typeof Q!=="string")return null;let Y=HV(Q);if(!Y)return null;let H=x3(Z??"unknown-thread"),W=x3(v3($)),X=g$(J,H),V=g$(X,`${W}.${Y.ext}`);try{return IX(X,{recursive:!0}),pX(V,Y.buffer),V}catch(A){return z(`codex-process: failed to write image generation result ${V}: ${A instanceof Error?A.message:A}`),null}}function v3($){let Z=$?.callId??$?.call_id??$?.id;return typeof Z==="string"&&Z?Z:`image-${Date.now()}`}function x3($){let Z=$.trim().replace(/[^a-zA-Z0-9_.-]/g,"_").replace(/^_+|_+$/g,"");return Z?Z.slice(0,140):"unknown"}function HV($){let Z=$.trim(),J=Z,Q=null,Y=Z.match(/^data:image\/([a-zA-Z0-9.+-]+);base64,(.*)$/s);if(Y)Q=XV(Y[1]),J=Y[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=WV(W)??Q;if(!X)return null;return{buffer:W,ext:X}}function WV($){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 XV($){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 b3($,Z,J){let Q=C8($,Z);if(!Q)return null;switch($.type){case"commandExecution":return{...Q,output:$.aggregatedOutput??"",isError:$.exitCode!=null&&$.exitCode!==0};case"fileChange":return{...Q,output:JSON.stringify($.changes??[],null,2),isError:$.status==="failed"};case"mcpToolCall":return{...Q,output:$.error?JSON.stringify($.error,null,2):JSON.stringify($.result??null,null,2),isError:!!$.error};case"dynamicToolCall":return{...Q,output:JSON.stringify($.contentItems??[],null,2),isError:$.success===!1};case"webSearch":return{...Q,output:JSON.stringify($.action??{},null,2),isError:!1};case"imageGeneration":return{...Q,output:w3($,J),isError:$.status==="failed"}}return null}function z4($,Z){if(typeof $==="string"&&$){let J=$.split("/").filter(Boolean).pop();if(J)return J}return A$(Z)}function C3($){if(typeof $!=="string"||!$)return;if($.startsWith("gAAAA")&&!/[一-鿿]/.test($))return"(继承主线程历史的密文任务书)";return $}function VV($,Z,J){let Q=(Y)=>typeof Y==="string"?Y:"";switch($){case"Bash":{if(J!=null){let Y=J.replace(/\s+/g," ").trim();return Y?`→ ${Y.slice(0,60)}`:""}return R1(Q(Z?.command))||"(空命令)"}case"FileChange":{let Y=Array.isArray(Z?.changes)?Z.changes.length:0;if(J!=null)return"";return Y>0?`改 ${Y} 个文件`:"文件变更"}case"MCP":return`${Q(Z?.server)}/${Q(Z?.tool)}`.slice(0,60);case"WebSearch":return`"${Q(Z?.query).slice(0,50)}"`;default:{if(J!=null){let Y=J.replace(/\s+/g," ").trim();return Y?`→ ${Y.slice(0,60)}`:""}return JSON.stringify(Z??{}).replace(/\s+/g," ").slice(0,60)}}}function h3($){return(Array.isArray($.receiverThreadIds)?$.receiverThreadIds:[]).filter((J)=>typeof J==="string"&&!!J)}function zV($){let Z=h3($);return Z.length>0?`派生 ${Z.length} 个子 agent`:"派生子 agent"}function AV($){let Z=$.agentsStates;if(!Z||typeof Z!=="object")return"";let J=[];for(let[Q,Y]of Object.entries(Z)){let H=Y,W=typeof H?.status==="string"?H.status:"unknown";J.push(`${A$(Q)}: ${W}`)}return J.join(`
|
|
30
|
+
`)}var S3,oX,aX=30000,rX=5000,tX=5000,sX=60000,eX="上一轮因模型暂时满载而中断。请基于当前会话继续完成用户尚未完成的任务,沿用已有进度;执行操作前先确认结果,避免重复已完成的操作。",JV,Z2="xhigh",e1,L1;var D1=N(()=>{U$();h();E8();W4();P1();V4();E8();S3=g$(f0(),".codex","sessions"),oX=g$(f0(),".codex","generated_images");JV=["none","minimal","low","medium","high","xhigh","max","ultra"];e1=class e1 extends Error{method;requestId;serverCode;serverMessage;constructor($,Z,J,Q){super(`codex app-server ${$} failed (id=${Z}, code=${J??"MISS"}): ${Q}`);this.method=$;this.requestId=Z;this.serverCode=J;this.serverMessage=Q;this.name="CodexRpcResponseError"}};L1=class L1 extends lX{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 k3("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=$2(),J=$V();z(`codex-process: spawn ${Z} app-server (cwd=${$.workDir})`);let Q={...process.env,NPM_CONFIG_LOGLEVEL:"error",PATH:dX(),...w.codex.env,...$.hostEnv??{}},Y=$.transformEnv?$.transformEnv(Q):Q;this.proc=iX(Z,J,ZV($.workDir,Y)),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(z(`codex-process: stdin failed: ${Z.message}`),!this.expectedExit)this.emit("error",Z)}handleChildExit($,Z){if(!this.alive){z(`codex-process: duplicate exit ignored code=${$} signal=${Z}`);return}this.alive=!1,this.cancelCapacityRetry(),this.childExitCode=$,this.childExitSignal=Z,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,Q=Z??this.childExitSignal,Y=this.conversationMaterializationBarrier();if(Y){Y.then(()=>this.emitProcessExit(J,Q),()=>this.emitProcessExit(J,Q));return}this.emitProcessExit(J,Q)}handleChildProcessError($){z(`codex-process: child process error: ${$}`),this.rejectPendingRequests((Q,Y)=>Error(`codex app-server process failed before ${Y.method} response (id=${Q}): ${$.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)z(`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(),z(`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(`
|
|
31
31
|
`))>=0){let J=this.stdoutBuf.slice(0,Z).trim();if(this.stdoutBuf=this.stdoutBuf.slice(Z+1),!J)continue;let Q;try{Q=JSON.parse(J)}catch(Y){z(`codex-process: bad json: ${J.slice(0,200)} (${Y})`);continue}try{this.handleMessage(Q)}catch(Y){z(`codex-process: dispatch error: ${JSON.stringify(Q).slice(0,200)} (${Y})`)}}}flushStdoutTail(){if(!this.stdoutBuf)return;this.onStdout(Buffer.from(`
|
|
32
32
|
`))}onStderr($){this.stderrBuf+=$.toString();let Z;while((Z=this.stderrBuf.indexOf(`
|
|
33
|
-
`))>=0){let J=this.stderrBuf.slice(0,Z);if(this.stderrBuf=this.stderrBuf.slice(Z+1),J.trim())z(`codex-process[stderr]: ${J}`)}}flushStderrTail(){let $=this.stderrBuf;if(this.stderrBuf="",$.trim())z(`codex-process[stderr]: ${$}`)}handleMessage($){if(Object.prototype.hasOwnProperty.call($,"id")&&!$.method){let J=this.pending.get($.id);if(!J){z(`codex-process: response for unknown id=${$.id}`);return}if(this.pending.delete($.id),clearTimeout(J.timeout),$.error){let Q=typeof $.error?.code==="number"?$.error.code:null,Y=typeof $.error==="string"?$.error:typeof $.error?.message==="string"?$.error.message:JSON.stringify($.error);J.reject(new G4(J.method,$.id,Q,Y))}else J.resolve($.result);return}if(Object.prototype.hasOwnProperty.call($,"id")&&$.method){this.handleServerRequest($);return}if($.method){this.handleNotification($.method,$.params??{});return}let Z=O8($);if(Z){let J=this.withSessionId(Z);M8(Z.sourceMethod??"raw_message",$,J),this.emit("context_compacted",J);return}O$("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=U8($,Z);if(J){let Q=this.withSessionId(J);M8($,Z,Q),this.emit("context_compacted",Q);return}switch($){case"thread/started":{let Q=Z.thread;if(Q?.id)this.sessionId=Q.id;return}case"thread/settings/updated":{let Q=Z.threadSettings;if(typeof Q?.model==="string")this.lastModel=Q.model;if(S$(Q?.effort))this.lastEffort=Q.effort;return}case"thread/tokenUsage/updated":{let Q=B1(Z.tokenUsage?.last);if(Q)this.lastUsage=Q,this.lastResult.usage=this.lastUsage;else z("codex-process: tokenUsage notification missing last breakdown");this.lastTotalUsage=B1(Z.tokenUsage?.total);let Y=Z.tokenUsage?.modelContextWindow;if(typeof Y==="number"&&Y>0)this.lastContextWindow=Y;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){O$("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){O$("TURN_COMPLETED_THREAD_MISMATCH",{method:$,params:Z});return}let Q=Z.turn??{},Y=typeof Q.id==="string"&&Q.id?Q.id:null;if(Y){if(this.finishedTurnIds?.has(Y)){z(`codex-process: duplicate turn/completed ignored turn=${Y}`);return}if(this.currentTurnId&&this.currentTurnId!==Y){this.markTurnStartTerminal(Y),this.rememberFinishedTurn(Y),z(`codex-process: stale turn/completed ignored turn=${Y} current=${this.currentTurnId}`);return}this.flushRolloutImageGenerations(),this.markConversationMaterialized("turn/completed notification"),this.markTurnStartTerminal(Y),this.rememberFinishedTurn(Y)}else O$("TURN_COMPLETED_MISSING_ID",{method:$,params:Z});let H=Q.status,W=H==="failed"||!!Q.error,X=H==="completed"&&!W&&!!Y;this.lastCompletedTurnId=X?Y:null;let V=W?Q.error?.type??Q.error?.message??"failed":"success";this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:typeof Q.durationMs==="number"?Q.durationMs:null,num_turns:1,usage:this.lastUsage,subtype:V,is_error:W},this.currentTurnId=null,this.emit("result",{subtype:V,is_error:W,duration_ms:this.lastResult.duration_ms,usage:this.lastUsage,turn_id:Y,checkpoint:X&&this.sessionId?{provider:"codex",kind:"turn",id:Y,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 z("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 O$("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":{z(`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":{z(`codex-process: ${$}: ${Z.summary??Z.message??JSON.stringify(Z).slice(0,200)}`);return}case"error":{z(`codex-process: server error: ${JSON.stringify(Z).slice(0,500)}`),this.emit("error",Error(Z.message??Z.summary??"codex app-server error"));return}}O$("NOTIFICATION",{method:$,params:Z}),this.emit("raw",{method:$,params:Z})}handleItemStarted($){let Z=$?.item;if(!Z?.id){O$("ITEM_STARTED_MISSING_ID",{method:"item/started",params:$});return}if(this.feedCollabItem(Z,"started"))return;let J=C8(Z,this.opts.workDir);if(!J){O$("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 Q=typeof $?.threadId==="string"?$.threadId:"";this.collabAgentSummaries.set(Q,J)}return}if(this.feedCollabItem(Z,"completed"))return;this.emitSubagentStep(Z,"completed",$)}handleItemCompleted($){let Z=$?.item;if(!Z?.id){O$("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=y3(Z,this.opts.workDir,this.sessionId??void 0);if(!J){O$("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")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)??A$(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 Q=typeof J?.threadId==="string"?J.threadId:"",Y=Z==="started"?C8($,this.opts.workDir):y3($,this.opts.workDir,this.sessionId??void 0);if(!Y)return;let H="output"in Y&&typeof Y.output==="string"?Y.output:void 0;this.emit("subagent_step",{thread_id:Q,item_id:$.id,tool:Y.name,phase:Z,brief:QV(Y.name,Y.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 Q=V4($.agentPath,J);this.collabAgentNames.set(J,Q),this.emit("bg_task_started",{task_id:J,task_type:"local_agent",description:Q}),this.emit("bg_task_updated",{task_id:J,patch:{is_backgrounded:!0}})}else if($.kind==="started"){let Q=this.collabAgentNames.get(J),Y=V4($.agentPath,J);if(Q!==Y&&!this.collabAgentSettled.has(J))this.collabAgentNames.set(J,Y),this.emit("bg_task_started",{task_id:J,task_type:"local_agent",description:Y})}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[Q,Y]of Object.entries(J))this.translateAgentState(Q,Y,$);if($.tool==="closeAgent"&&Z==="completed"&&$.status!=="failed"){let Q=w3($);for(let Y of Q){if(this.collabAgentSettled.has(Y))continue;if(this.collabAgentSettled.add(Y),!this.collabAgentNames.has(Y))this.collabAgentNames.set(Y,V4(null,Y));this.emit("bg_task_settled",{task_id:Y,status:"stopped"})}}if($.tool==="spawnAgent"){if(Z==="started")this.emit("tool_use",{id:$.id,name:"Agent",input:{tool:"spawnAgent",prompt:x3($.prompt),description:YV($),model:typeof $.model==="string"?$.model:void 0}});else if($.status!=="inProgress")this.emit("tool_result",{tool_use_id:$.id,content:HV($),is_error:$.status==="failed"})}return!0}return!1}translateAgentState($,Z,J){let Q=Z?.status;if(typeof Q!=="string")return;if(this.collabAgentSettled.has($)){if(Q!=="running"&&Q!=="pendingInit"){if(Q==="errored"||Q==="shutdown"||Q==="notFound"||Q==="interrupted")this.emit("bg_task_updated",{task_id:$,patch:{status:Q==="errored"?"failed":"killed",error:typeof Z?.message==="string"&&Z.message?Z.message:void 0}});return}this.collabAgentSettled.delete($);let H=this.collabAgentNames.get($)??V4(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:x3(J.prompt)};this.emit("bg_task_started",W);let X={task_id:$,patch:{is_backgrounded:!0}};this.emit("bg_task_updated",X)}if(Q==="running"||Q==="pendingInit"||Q==="interrupted"){let H={task_id:$,patch:{status:Q==="pendingInit"?"pending":Q==="interrupted"?"paused":"running"}};this.emit("bg_task_updated",H);return}if(this.collabAgentSettled.size>=5000)this.collabAgentSettled.clear();this.collabAgentSettled.add($);let Y={task_id:$,status:Q==="completed"?"completed":Q==="errored"?"failed":"stopped",summary:typeof Z?.message==="string"&&Z.message?Z.message:void 0};this.emit("bg_task_settled",Y)}primeRolloutImageGenerationScan(){if(this.rolloutFilePath=null,this.rolloutReadOffset=0,this.rolloutLineRemainder="",this.rolloutDecoder=new T3("utf8"),this.emittedImageGenerationIds.clear(),!this.sessionId)return;let $=S3(this.sessionId);if(!$)return;this.rolloutFilePath=$;try{this.rolloutReadOffset=z4($).size,z(`codex-process: image generation rollout scan primed ${$} offset=${this.rolloutReadOffset}`)}catch(Z){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??S3(this.sessionId);if(!$){z(`codex-process: image generation rollout file not found for thread=${this.sessionId}`);return}this.rolloutFilePath=$;let Z;try{let Y=z4($).size;if(Y<=this.rolloutReadOffset)return;let H=Y-this.rolloutReadOffset;Z=Buffer.allocUnsafe(H);let W=gX($,"r"),X=0;try{while(X<H){let V=cX(W,Z,X,H-X,this.rolloutReadOffset+X);if(V===0)break;X+=V}}finally{vX(W)}Z=Z.subarray(0,X),this.rolloutReadOffset+=X}catch(Y){z(`codex-process: image generation rollout read failed ${$}: ${Y instanceof Error?Y.message:Y}`);return}let J=this.rolloutLineRemainder+this.rolloutDecoder.write(Z),Q=J.split(/\r?\n/);this.rolloutLineRemainder=J.endsWith(`
|
|
34
|
-
`)?"":Q.pop()??"";for(let Y of Q){if(!Y.trim())continue;let H;try{H=JSON.parse(Y)}catch(V){z(`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=
|
|
35
|
-
`,(Q)=>{if(Q)J(Q)}),!0}catch(Q){return J(Q)}}request($,Z,J=
|
|
33
|
+
`))>=0){let J=this.stderrBuf.slice(0,Z);if(this.stderrBuf=this.stderrBuf.slice(Z+1),J.trim())z(`codex-process[stderr]: ${J}`)}}flushStderrTail(){let $=this.stderrBuf;if(this.stderrBuf="",$.trim())z(`codex-process[stderr]: ${$}`)}handleMessage($){if(Object.prototype.hasOwnProperty.call($,"id")&&!$.method){let J=this.pending.get($.id);if(!J){z(`codex-process: response for unknown id=${$.id}`);return}if(this.pending.delete($.id),clearTimeout(J.timeout),$.error){let Q=typeof $.error?.code==="number"?$.error.code:null,Y=typeof $.error==="string"?$.error:typeof $.error?.message==="string"?$.error.message:JSON.stringify($.error);J.reject(new e1(J.method,$.id,Q,Y))}else J.resolve($.result);return}if(Object.prototype.hasOwnProperty.call($,"id")&&$.method){this.handleServerRequest($);return}if($.method){this.handleNotification($.method,$.params??{});return}let Z=O8($);if(Z){let J=this.withSessionId(Z);M8(Z.sourceMethod??"raw_message",$,J),this.emit("context_compacted",J);return}O$("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=U8($,Z);if(J){let Q=this.withSessionId(J);M8($,Z,Q),this.emit("context_compacted",Q);return}switch($){case"thread/started":{let Q=Z.thread;if(Q?.id)this.sessionId=Q.id;return}case"thread/settings/updated":{let Q=Z.threadSettings;if(typeof Q?.model==="string")this.lastModel=Q.model;if(S$(Q?.effort))this.lastEffort=Q.effort;return}case"thread/tokenUsage/updated":{let Q=B1(Z.tokenUsage?.last);if(Q)this.lastUsage=Q,this.lastResult.usage=this.lastUsage;else z("codex-process: tokenUsage notification missing last breakdown");this.lastTotalUsage=B1(Z.tokenUsage?.total);let Y=Z.tokenUsage?.modelContextWindow;if(typeof Y==="number"&&Y>0)this.lastContextWindow=Y;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){O$("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){O$("TURN_COMPLETED_THREAD_MISMATCH",{method:$,params:Z});return}let Q=Z.turn??{},Y=typeof Q.id==="string"&&Q.id?Q.id:null;if(Y){if(this.finishedTurnIds?.has(Y)){z(`codex-process: duplicate turn/completed ignored turn=${Y}`);return}if(this.currentTurnId&&this.currentTurnId!==Y){this.markTurnStartTerminal(Y),this.rememberFinishedTurn(Y),z(`codex-process: stale turn/completed ignored turn=${Y} current=${this.currentTurnId}`);return}this.flushRolloutImageGenerations(),this.markConversationMaterialized("turn/completed notification"),this.markTurnStartTerminal(Y),this.rememberFinishedTurn(Y)}else O$("TURN_COMPLETED_MISSING_ID",{method:$,params:Z});let H=Q.status,W=Q.error??(H==="failed"&&this.turnError&&this.turnError.turnId===Y?this.turnError.error:null);this.turnError=null;let X=H==="failed"||!!W,V=H==="completed"&&!X&&!!Y;if(this.lastCompletedTurnId=V?Y:null,this.currentTurnId=null,H==="failed"&&Y&&N3(W?.message)&&this.scheduleCapacityRetry(W.message,eX))return;this.cancelCapacityRetry(),this.capacityRetryCount=0,this.capacityRetryHasStarted=!1;let A=X?W?.type??W?.message??"failed":"success";this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:typeof Q.durationMs==="number"?Q.durationMs:null,num_turns:1,usage:this.lastUsage,subtype:A,is_error:X},this.emit("result",{subtype:A,is_error:X,duration_ms:this.lastResult.duration_ms,usage:this.lastUsage,turn_id:Y,checkpoint:V&&this.sessionId?{provider:"codex",kind:"turn",id:Y,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 z("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 O$("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":{z(`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":{z(`codex-process: ${$}: ${Z.summary??Z.message??JSON.stringify(Z).slice(0,200)}`);return}case"error":{z(`codex-process: server error: ${JSON.stringify(Z).slice(0,500)}`);let Q=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:Q};this.emit("error",Error(Q.message??Q.summary??"codex app-server error"));return}}O$("NOTIFICATION",{method:$,params:Z}),this.emit("raw",{method:$,params:Z})}handleItemStarted($){let Z=$?.item;if(!Z?.id){O$("ITEM_STARTED_MISSING_ID",{method:"item/started",params:$});return}if(this.feedCollabItem(Z,"started"))return;let J=C8(Z,this.opts.workDir);if(!J){O$("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 Q=typeof $?.threadId==="string"?$.threadId:"";this.collabAgentSummaries.set(Q,J)}return}if(this.feedCollabItem(Z,"completed"))return;this.emitSubagentStep(Z,"completed",$)}handleItemCompleted($){let Z=$?.item;if(!Z?.id){O$("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=b3(Z,this.opts.workDir,this.sessionId??void 0);if(!J){O$("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")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)??A$(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 Q=typeof J?.threadId==="string"?J.threadId:"",Y=Z==="started"?C8($,this.opts.workDir):b3($,this.opts.workDir,this.sessionId??void 0);if(!Y)return;let H="output"in Y&&typeof Y.output==="string"?Y.output:void 0;this.emit("subagent_step",{thread_id:Q,item_id:$.id,tool:Y.name,phase:Z,brief:VV(Y.name,Y.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 Q=z4($.agentPath,J);this.collabAgentNames.set(J,Q),this.emit("bg_task_started",{task_id:J,task_type:"local_agent",description:Q}),this.emit("bg_task_updated",{task_id:J,patch:{is_backgrounded:!0}})}else if($.kind==="started"){let Q=this.collabAgentNames.get(J),Y=z4($.agentPath,J);if(Q!==Y&&!this.collabAgentSettled.has(J))this.collabAgentNames.set(J,Y),this.emit("bg_task_started",{task_id:J,task_type:"local_agent",description:Y})}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[Q,Y]of Object.entries(J))this.translateAgentState(Q,Y,$);if($.tool==="closeAgent"&&Z==="completed"&&$.status!=="failed"){let Q=h3($);for(let Y of Q){if(this.collabAgentSettled.has(Y))continue;if(this.collabAgentSettled.add(Y),!this.collabAgentNames.has(Y))this.collabAgentNames.set(Y,z4(null,Y));this.emit("bg_task_settled",{task_id:Y,status:"stopped"})}}if($.tool==="spawnAgent"){if(Z==="started")this.emit("tool_use",{id:$.id,name:"Agent",input:{tool:"spawnAgent",prompt:C3($.prompt),description:zV($),model:typeof $.model==="string"?$.model:void 0}});else if($.status!=="inProgress")this.emit("tool_result",{tool_use_id:$.id,content:AV($),is_error:$.status==="failed"})}return!0}return!1}translateAgentState($,Z,J){let Q=Z?.status;if(typeof Q!=="string")return;if(this.collabAgentSettled.has($)){if(Q!=="running"&&Q!=="pendingInit"){if(Q==="errored"||Q==="shutdown"||Q==="notFound"||Q==="interrupted")this.emit("bg_task_updated",{task_id:$,patch:{status:Q==="errored"?"failed":"killed",error:typeof Z?.message==="string"&&Z.message?Z.message:void 0}});return}this.collabAgentSettled.delete($);let H=this.collabAgentNames.get($)??z4(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:C3(J.prompt)};this.emit("bg_task_started",W);let X={task_id:$,patch:{is_backgrounded:!0}};this.emit("bg_task_updated",X)}if(Q==="running"||Q==="pendingInit"||Q==="interrupted"){let H={task_id:$,patch:{status:Q==="pendingInit"?"pending":Q==="interrupted"?"paused":"running"}};this.emit("bg_task_updated",H);return}if(this.collabAgentSettled.size>=5000)this.collabAgentSettled.clear();this.collabAgentSettled.add($);let Y={task_id:$,status:Q==="completed"?"completed":Q==="errored"?"failed":"stopped",summary:typeof Z?.message==="string"&&Z.message?Z.message:void 0};this.emit("bg_task_settled",Y)}primeRolloutImageGenerationScan(){if(this.rolloutFilePath=null,this.rolloutReadOffset=0,this.rolloutLineRemainder="",this.rolloutDecoder=new k3("utf8"),this.emittedImageGenerationIds.clear(),!this.sessionId)return;let $=y3(this.sessionId);if(!$)return;this.rolloutFilePath=$;try{this.rolloutReadOffset=A4($).size,z(`codex-process: image generation rollout scan primed ${$} offset=${this.rolloutReadOffset}`)}catch(Z){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??y3(this.sessionId);if(!$){z(`codex-process: image generation rollout file not found for thread=${this.sessionId}`);return}this.rolloutFilePath=$;let Z;try{let Y=A4($).size;if(Y<=this.rolloutReadOffset)return;let H=Y-this.rolloutReadOffset;Z=Buffer.allocUnsafe(H);let W=cX($,"r"),X=0;try{while(X<H){let V=uX(W,Z,X,H-X,this.rolloutReadOffset+X);if(V===0)break;X+=V}}finally{gX(W)}Z=Z.subarray(0,X),this.rolloutReadOffset+=X}catch(Y){z(`codex-process: image generation rollout read failed ${$}: ${Y instanceof Error?Y.message:Y}`);return}let J=this.rolloutLineRemainder+this.rolloutDecoder.write(Z),Q=J.split(/\r?\n/);this.rolloutLineRemainder=J.endsWith(`
|
|
34
|
+
`)?"":Q.pop()??"";for(let Y of Q){if(!Y.trim())continue;let H;try{H=JSON.parse(Y)}catch(V){z(`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=w3($,this.sessionId??void 0);if(!J)return;let Q=$?.status==="failed",Y=$?.status==="generating"&&T3(J)?"completed":$?.status;this.emittedImageGenerationIds.add(Z),this.emit("tool_use",{id:Z,name:"ImageGeneration",input:{status:Y,revisedPrompt:f3($)}}),this.emit("tool_result",{tool_use_id:Z,content:J,is_error:Q})}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??{},Q={questions:(J.questions??[]).map((Y)=>({id:Y.id,header:Y.header,question:Y.question,options:Array.isArray(Y.options)&&Y.options.length?Y.options.map((H)=>({label:H.label,description:H.description})):[{label:"自定义回答",description:Y.isSecret?"请直接在群里回复":"可直接在群里回复"}]}))};this.emit("tool_use",{id:J.itemId,name:"AskUserQuestion",input:Q}),this.emit("can_use_tool",{request_id:Z,tool_name:"AskUserQuestion",input:Q,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:O$("SERVER_REQUEST_UNSUPPORTED",$),this.respondError(Z,`unsupported server request: ${$.method}`)}}write($,Z){let J=(Q)=>{let Y=Q instanceof Error?Q:Error(String(Q));return z(`codex-process: stdin write failed: ${Y.message}`),Z?.(Y),!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($)+`
|
|
35
|
+
`,(Q)=>{if(Q)J(Q)}),!0}catch(Q){return J(Q)}}request($,Z,J=aX){let Q=++this.requestCounter;return new Promise((Y,H)=>{let W=setTimeout(()=>{let V=this.pending.get(Q);if(!V)return;this.pending.delete(Q),V.reject(Error(`codex app-server ${$} request timed out after ${J}ms (id=${Q})`))},Math.max(0,J)),X={resolve:Y,reject:H,method:$,timeout:W};this.pending.set(Q,X),this.write({id:Q,method:$,params:Z},(V)=>{if(this.pending.get(Q)!==X)return;this.pending.delete(Q),clearTimeout(W),H(Error(`codex app-server ${$} request write failed (id=${Q}): ${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($),Q=this.serverRequests.get(J);this.serverRequests.delete(J),this.write({id:Q?.id??$,result:Z})}respondError($,Z){let J=String($),Q=this.serverRequests.get(J);this.serverRequests.delete(J),this.write({id:Q?.id??$,error:{code:-32601,message:Z}})}sendInitialize(){if(!this.readyPromise)this.readyPromise=this.initializeAndStartThread(),this.readyPromise.catch(($)=>{z(`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,Q;if($.kind==="resume")J="thread/resume",Q=await this.request(J,{threadId:$.source.sessionId,...Z,excludeTurns:!0,persistExtendedHistory:!1});else if($.kind==="fork")J="thread/fork",Q=await this.request(J,{threadId:$.source.sessionId,...$.through?{lastTurnId:$.through.id}:{},...Z,excludeTurns:!0});else J="thread/start",Q=await this.request(J,{...Z,experimentalRawEvents:!1,persistExtendedHistory:!1});let Y=Q?.thread;if(typeof Y?.id!=="string"||!Y.id)throw Error(`codex app-server ${J} returned no thread.id`);let H=typeof Y.cwd==="string"?Y.cwd:typeof Q?.cwd==="string"?Q.cwd:null;if(H!==this.opts.workDir)throw Error(`codex app-server ${J} returned cwd=${H??"MISS"}, expected ${this.opts.workDir}`);if($.kind==="fork"&&Y.id===$.source.sessionId)throw Error(`codex app-server thread/fork returned source thread id ${Y.id}`);if($.kind==="resume"&&Y.id!==$.source.sessionId)throw Error(`codex app-server thread/resume returned thread id ${Y.id}, expected ${$.source.sessionId}`);let W=typeof Y.path==="string"&&Y.path?Y.path:null;if(!W||!T3(W)||!W.endsWith(`${Y.id}.jsonl`))throw Error(`codex app-server ${J} returned invalid thread.path=${W??"MISS"}`);if(this.sessionId=Y.id,this.conversationRolloutPath=W,this.conversationResumable=!1,$.kind!=="fresh")await this.verifyConversationMaterialized(`${J} response`),this.conversationResumable=!0;if(Q?.model)this.lastModel=Q.model;if(S$(Q?.reasoningEffort))this.lastEffort=Q.reasoningEffort;else this.lastEffort=this.opts.effort??null;z(`codex-process: thread=${this.sessionId}`),this.primeRolloutImageGenerationScan(),this.emit("init",{session_id:this.sessionId,thread:Y})}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,z(`codex-process: conversation materialized thread=${Z} source=${$}`),this.emit("conversation_materialized",{session_id:Z,source:$})},(Q)=>{let Y=Q instanceof Error?Q:Error(String(Q));this.lastConversationMaterializationFailure=Y,z(`codex-process: conversation materialization check failed thread=${Z} source=${$}: ${Y.message}`),this.emit("conversation_materialization_failed",{session_id:Z,path:this.conversationRolloutPath,source:$,error:Y})}).finally(()=>{if(this.conversationMaterializationVerification===J)this.conversationMaterializationVerification=null;let Q=this.conversationMaterializationRetrySource;if(this.conversationMaterializationRetrySource=null,!this.conversationResumable&&Q)this.markConversationMaterialized(Q)})}async verifyConversationMaterialized($){let Z=this.sessionId,J=this.conversationRolloutPath;if(!Z||!J)throw Error(`codex ${$} has no initialized rollout identity`);let Y=(await this.request("thread/read",{threadId:Z,includeTurns:!0},rX))?.thread;if(Y?.id!==Z||Y.cwd!==this.opts.workDir||Y.path!==J||!Array.isArray(Y.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=A4(Z)}catch(Q){throw Error(`codex ${$} rollout is not readable at ${Z}: ${Q instanceof Error?Q.message:Q}`,{cause:Q})}if(!J.isFile())throw Error(`codex ${$} rollout path is not a file: ${Z}`)}conversationLaunch(){let $=this.opts.launch??{kind:"fresh"};if(G$($,"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.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((Y)=>`[file: ${Y}]`).join(" ")+`
|
|
36
36
|
|
|
37
|
-
`:"",Q=this.beginTurnStart();this.startTurn(J+$,Q).catch((Y)=>this.failTurnStart(Y,Q))}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 Q of J.data){if(typeof Q?.model!=="string"||!Q.model)continue;$.push({id:typeof Q.id==="string"&&Q.id?Q.id:Q.model,model:Q.model,displayName:typeof Q.displayName==="string"&&Q.displayName?Q.displayName:Q.model,description:typeof Q.description==="string"?Q.description:"",hidden:Q.hidden===!0,isDefault:Q.isDefault===!0,supportedReasoningEfforts:sX(Q.supportedReasoningEfforts),defaultReasoningEffort:S$(Q.defaultReasoningEffort)?Q.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 Q=await this.request("thread/list",{cursor:J,limit:100,sortKey:"updated_at",sortDirection:"desc",cwd:this.opts.workDir});if(!Array.isArray(Q?.data))throw Error("thread/list returned no data array");for(let H of Q.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(W4("codex",H.id))continue;$.push({provider:"codex",sessionId:H.id,cwd:H.cwd,preview:H.preview,ts:H.updatedAt*1000,...W?{status:W}:{}})}let Y=Q?.nextCursor;if(Y!==null&&typeof Y!=="string")throw Error("thread/list returned an invalid nextCursor");if(Y&&Z.has(Y))throw Error(`thread/list repeated pagination cursor ${Y}`);if(Y)Z.add(Y);J=Y}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){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)){z(`codex-process: ignored stale turn/start failure generation=${Z.generation}`);return}this.turnStartOwner=null;let J=$ instanceof Error?$.message:String($);z(`codex-process: turn/start failed: ${J}`),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,Q){let Y=typeof $?.id==="string"&&$.id?$.id:null;if(!Y)throw Error(`codex app-server ${J} returned no turn.id`);if(this.finishedTurnIds?.has(Y))return;this.confirmTurnStart(Y,Q);let H=this.currentTurnId!==Y;if(this.currentTurnId=Y,!H)return;this.lastCompletedTurnId=null,this.emit("turn_started",{turn_id:Y,thread_id:typeof Z==="string"&&Z?Z:this.sessionId})}beginTurnStart(){let $={generation:(this.turnStartGeneration??0)+1,turnId:null,confirmed:!1,terminal:!1};return this.turnStartGeneration=$.generation,this.turnStartOwner=$,$}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,!this.sessionId)throw Error("codex thread not initialized");let Q=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(Q?.turn,this.sessionId,"turn/start response",J)}catch(Q){if(!this.ownsTurnStartFailure(J)){z(`codex-process: ignored stale turn/start rejection generation=${J.generation}`);return}throw Q}}sendInterrupt(){if(!this.sessionId||!this.currentTurnId)return;this.request("turn/interrupt",{threadId:this.sessionId,turnId:this.currentTurnId}).catch(($)=>z(`codex-process: interrupt failed: ${$}`))}sendPermissionResponse($,Z,J){let Q=this.serverRequests.get(String($));if(!Q){z(`codex-process: permission response for unknown request ${$}`);return}let Y=Z==="allow";switch(Q.method){case"item/commandExecution/requestApproval":this.respond($,{decision:Y?"accept":"decline"});return;case"item/fileChange/requestApproval":this.respond($,{decision:Y?"accept":"decline"});return;case"item/permissions/requestApproval":if(Y)this.respond($,{permissions:Q.params?.permissions??{},scope:"session"});else this.respondError($,J?.denyMessage??"denied by user");return;case"item/tool/requestUserInput":{if(!Y){this.respondError($,J?.denyMessage??"denied by user");return}let H=J?.updatedInput?.answers??{},W={};for(let X of Q.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:O$("APPROVAL_RESPONSE_UNSUPPORTED",{requestId:$,method:Q.method,params:Q.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.alive){if(await this.waitForExit($))return;throw Error(`codex app-server exited but stdio did not close within ${$}ms`)}this.expectedExit=!0,z(`codex-process: SIGTERM (timeout=${$}ms)`);let Z=[];if(this.sendSignal("SIGTERM",Z),await this.waitForExit($))return;if(z(`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("; ")}`:"",Q=Error(`codex app-server did not exit after SIGTERM and SIGKILL (${$}ms each)${J}`);throw z(`codex-process: kill failed: ${Q.message}`),Q}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,Q=(H)=>{if(J)return;J=!0,clearTimeout(Y),Z(H)},Y=setTimeout(()=>Q(!1),Math.max(0,$));this.exitPromise.then(()=>Q(!0))})}}});function WV($){return $.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function f8($){let Z=[],J=/^(?: {0,3})(`{3,}|~{3,})[^\n]*(?:\n|$)/gm,Q=0;while(Q<$.length){J.lastIndex=Q;let X=J.exec($);if(!X)break;let V=X[1],A=new RegExp(`^(?: {0,3})${WV(V[0])}{${V.length},}[ \\t]*(?:\\n|$)`,"gm");A.lastIndex=X.index+X[0].length;let G=A.exec($),_=G?G.index+G[0].length:$.length;Z.push({start:X.index,end:_}),Q=_}let Y=[...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),A=/(`+)[^\n]*?\1/g,G;while((G=A.exec(V))!==null)Y.push({start:X.start+G.index,end:X.start+G.index+G[0].length})}return Y.sort((X,V)=>X.start-V.start)}function w8($,Z){if(!$)return $;let J=f8($);if(!J.length)return Z($);let Q="",Y=0;for(let H of J){if(H.start>Y)Q+=Z($.slice(Y,H.start));Q+=$.slice(H.start,H.end),Y=Math.max(Y,H.end)}if(Y<$.length)Q+=Z($.slice(Y));return Q}function XV($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function v3($){return $.replace(/!\[([^\]]*)\]\(([^)]*)\)/g,(J,Q,Y)=>{let H=Y.trim();return Q.trim()?`\uD83D\uDDBC️ ${Q.trim()} (${H})`:`\uD83D\uDDBC️ ${H}`}).replace(/!\[/g,"\uD83D\uDDBC️ [")}function B0($){if(Array.isArray($))return $.map((Q)=>B0(Q));if($==null||typeof $!=="object")return $;let Z=$,J={};for(let[Q,Y]of Object.entries(Z))J[Q]=B0(Y);if(Z.tag==="markdown"&&typeof Z.content==="string")J.content=v8(Z.content);return J}function e($){return w8($,(Z)=>VV(v3(XV(Z))))}function VV($){return $.replace(/\\\[([\s\S]*?)\\\]/g,(Z,J)=>`
|
|
37
|
+
`:"";this.cancelCapacityRetry(),this.capacityRetryCount=0,this.capacityRetryHasStarted=!1,this.capacityRetryEnabled=!0,this.turnError=null;let Q=this.beginTurnStart(J+$);this.startTurn(J+$,Q).catch((Y)=>this.failTurnStart(Y,Q))}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 Q of J.data){if(typeof Q?.model!=="string"||!Q.model)continue;$.push({id:typeof Q.id==="string"&&Q.id?Q.id:Q.model,model:Q.model,displayName:typeof Q.displayName==="string"&&Q.displayName?Q.displayName:Q.model,description:typeof Q.description==="string"?Q.description:"",hidden:Q.hidden===!0,isDefault:Q.isDefault===!0,supportedReasoningEfforts:QV(Q.supportedReasoningEfforts),defaultReasoningEffort:S$(Q.defaultReasoningEffort)?Q.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 Q=await this.request("thread/list",{cursor:J,limit:100,sortKey:"updated_at",sortDirection:"desc",cwd:this.opts.workDir});if(!Array.isArray(Q?.data))throw Error("thread/list returned no data array");for(let H of Q.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(X4("codex",H.id))continue;$.push({provider:"codex",sessionId:H.id,cwd:H.cwd,preview:H.preview,ts:H.updatedAt*1000,...W?{status:W}:{}})}let Y=Q?.nextCursor;if(Y!==null&&typeof Y!=="string")throw Error("thread/list returned an invalid nextCursor");if(Y&&Z.has(Y))throw Error(`thread/list repeated pagination cursor ${Y}`);if(Y)Z.add(Y);J=Y}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){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)){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(z(`codex-process: turn/start failed: ${J}`),$ instanceof e1&&$.method==="turn/start"&&N3($.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,Q){let Y=typeof $?.id==="string"&&$.id?$.id:null;if(!Y)throw Error(`codex app-server ${J} returned no turn.id`);if(this.finishedTurnIds?.has(Y))return;let H=Q??this.turnStartOwner;if(H?.interrupted){if(this.rememberFinishedTurn(Y),this.turnStartOwner===H)this.turnStartOwner=null;this.interruptTurn(Y);return}this.confirmTurnStart(Y,Q);let W=this.currentTurnId!==Y;if(this.currentTurnId=Y,!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:Y,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 Q=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(Q?.turn,this.sessionId,"turn/start response",J)}catch(Q){if(!this.ownsTurnStartFailure(J)){z(`codex-process: ignored stale turn/start rejection generation=${J.generation}`);return}throw Q}}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)=>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 Q=Math.min(tX*2**Math.min(J-1,4),sX),Y=this.turnStartGeneration??0,H={phase:"waiting",attempt:J,delayMs:Q,message:$};this.turnRetry=H,z(`codex-process: model capacity retry #${J} in ${Q}ms: ${$}`);let W=setTimeout(()=>{if(this.capacityRetryTimer!==W)return;if(this.capacityRetryTimer=null,!this.alive||this.expectedExit||!this.capacityRetryEnabled||this.currentTurnId||Y!==(this.turnStartGeneration??0))return;if(this.turnRetry={...H,phase:"retrying",delayMs:0},this.emit("turn_retry",this.turnRetry),!this.alive||this.expectedExit||!this.capacityRetryEnabled||Y!==(this.turnStartGeneration??0))return;let X=this.beginTurnStart(Z);this.startTurn(Z,X).catch((V)=>this.failTurnStart(V,X))},Q);return this.capacityRetryTimer=W,this.emit("turn_retry",H),!0}sendPermissionResponse($,Z,J){let Q=this.serverRequests.get(String($));if(!Q){z(`codex-process: permission response for unknown request ${$}`);return}let Y=Z==="allow";switch(Q.method){case"item/commandExecution/requestApproval":this.respond($,{decision:Y?"accept":"decline"});return;case"item/fileChange/requestApproval":this.respond($,{decision:Y?"accept":"decline"});return;case"item/permissions/requestApproval":if(Y)this.respond($,{permissions:Q.params?.permissions??{},scope:"session"});else this.respondError($,J?.denyMessage??"denied by user");return;case"item/tool/requestUserInput":{if(!Y){this.respondError($,J?.denyMessage??"denied by user");return}let H=J?.updatedInput?.answers??{},W={};for(let X of Q.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:O$("APPROVAL_RESPONSE_UNSUPPORTED",{requestId:$,method:Q.method,params:Q.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,z(`codex-process: SIGTERM (timeout=${$}ms)`);let Z=[];if(this.sendSignal("SIGTERM",Z),await this.waitForExit($))return;if(z(`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("; ")}`:"",Q=Error(`codex app-server did not exit after SIGTERM and SIGKILL (${$}ms each)${J}`);throw z(`codex-process: kill failed: ${Q.message}`),Q}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,Q=(H)=>{if(J)return;J=!0,clearTimeout(Y),Z(H)},Y=setTimeout(()=>Q(!1),Math.max(0,$));this.exitPromise.then(()=>Q(!0))})}}});function GV($){return $.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function f8($){let Z=[],J=/^(?: {0,3})(`{3,}|~{3,})[^\n]*(?:\n|$)/gm,Q=0;while(Q<$.length){J.lastIndex=Q;let X=J.exec($);if(!X)break;let V=X[1],A=new RegExp(`^(?: {0,3})${GV(V[0])}{${V.length},}[ \\t]*(?:\\n|$)`,"gm");A.lastIndex=X.index+X[0].length;let G=A.exec($),_=G?G.index+G[0].length:$.length;Z.push({start:X.index,end:_}),Q=_}let Y=[...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),A=/(`+)[^\n]*?\1/g,G;while((G=A.exec(V))!==null)Y.push({start:X.start+G.index,end:X.start+G.index+G[0].length})}return Y.sort((X,V)=>X.start-V.start)}function w8($,Z){if(!$)return $;let J=f8($);if(!J.length)return Z($);let Q="",Y=0;for(let H of J){if(H.start>Y)Q+=Z($.slice(Y,H.start));Q+=$.slice(H.start,H.end),Y=Math.max(Y,H.end)}if(Y<$.length)Q+=Z($.slice(Y));return Q}function _V($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function g3($){return $.replace(/!\[([^\]]*)\]\(([^)]*)\)/g,(J,Q,Y)=>{let H=Y.trim();return Q.trim()?`\uD83D\uDDBC️ ${Q.trim()} (${H})`:`\uD83D\uDDBC️ ${H}`}).replace(/!\[/g,"\uD83D\uDDBC️ [")}function B0($){if(Array.isArray($))return $.map((Q)=>B0(Q));if($==null||typeof $!=="object")return $;let Z=$,J={};for(let[Q,Y]of Object.entries(Z))J[Q]=B0(Y);if(Z.tag==="markdown"&&typeof Z.content==="string")J.content=v8(Z.content);return J}function $$($){return w8($,(Z)=>KV(g3(_V(Z))))}function KV($){return $.replace(/\\\[([\s\S]*?)\\\]/g,(Z,J)=>`
|
|
38
38
|
\`\`\`
|
|
39
39
|
${J.trim()}
|
|
40
40
|
\`\`\`
|
|
@@ -42,79 +42,79 @@ ${J.trim()}
|
|
|
42
42
|
\`\`\`
|
|
43
43
|
${J.trim()}
|
|
44
44
|
\`\`\`
|
|
45
|
-
`).replace(/\\\(([\s\S]*?)\\\)/g,(Z,J)=>`\`${J.trim()}\``).replace(/\$([^$\n]+)\$/g,(Z,J)=>/\\|\^|_|=/.test(J)?`\`${J.trim()}\``:Z)}function v8($){return w8($,
|
|
46
|
-
`):"_(暂无执行记录)_")}function j1($,Z=Date.now(),J="bucket"){return{tag:"collapsible_panel",element_id:
|
|
47
|
-
`);for(let Q=J.length-1;Q>=0;Q--){let Y=J[Q].trim();if(!Y)continue;try{let H=JSON.parse(Y);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
|
|
48
|
-
`);return $==null?"":JSON.stringify($,null,2)}function
|
|
49
|
-
`)}}catch{}return Z}function
|
|
45
|
+
`).replace(/\\\(([\s\S]*?)\\\)/g,(Z,J)=>`\`${J.trim()}\``).replace(/\$([^$\n]+)\$/g,(Z,J)=>/\\|\^|_|=/.test(J)?`\`${J.trim()}\``:Z)}function v8($){return w8($,g3)}var M;var N$=N(()=>{M={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",tasklistPanel:"tasklist_panel",agentIdentityPanel:"agent_id_panel",agentRunFooter:"agent_run_footer"}});function I3($){let Z=2166136261;for(let J=0;J<$.length;J++)Z^=$.charCodeAt(J),Z=Math.imul(Z,16777619);return(Z>>>0).toString(36)}function qV($,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 c3($){return $==="workflow"||$==="monitor"}function y$($){return $.status==="completed"||$.status==="failed"||$.status==="killed"}function w0($){return $.some((Z)=>!y$(Z))}function c8($,Z,J=Date.now()){let Q=qV(Z.task_type,Z.subagent_type),Y=$.active.some((X)=>X.id===Z.task_id),H=$.pending.some((X)=>X.id===Z.task_id);if(Y||H){let X=(V)=>({...V,type:Q,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:Y?$.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:Q,description:Z.description,subagentType:Z.subagent_type,workflowName:Z.workflow_name,prompt:Z.prompt,status:"running",startedAt:J,steps:[],...c3(Q)?{isBackgrounded:!0}:{}};return c3(Q)?{active:[...$.active,W],pending:$.pending}:{active:$.active,pending:[...$.pending,W]}}function m8($,Z){let J=$.active.some((H)=>H.id===Z.task_id),Q=$.pending.some((H)=>H.id===Z.task_id);if(!J&&!Q)return $;let Y=(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?Y(H):H):$.active,pending:Q?$.pending.map((H)=>H.id===Z.task_id?Y(H):H):$.pending}}function u8($,Z){let J=$.pending.findIndex((W)=>W.id===Z.task_id),Q=Z.patch;if(Q.is_backgrounded===!0&&J>=0){let W=$.pending[J],X={...W,isBackgrounded:!0,status:Q.status??W.status,description:Q.description??W.description,error:Q.error??W.error,endTime:Q.end_time??W.endTime};return{active:[...$.active,X],pending:$.pending.filter((V)=>V.id!==Z.task_id)}}let Y=$.active.some((W)=>W.id===Z.task_id),H=J>=0;if(Y||H){let W=(X)=>({...X,status:Q.status??X.status,description:Q.description??X.description,error:Q.error??X.error,isBackgrounded:Q.is_backgrounded??X.isBackgrounded,endTime:Q.end_time??X.endTime});return{active:Y?$.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 p8($){if($.pending.length===0)return $;return{active:[...$.active,...$.pending.map((Z)=>({...Z,isBackgrounded:!0}))],pending:[]}}function l8($,Z,J=Date.now()){let Q=Z.status==="completed"?"completed":Z.status==="failed"?"failed":"killed";if($.pending.some((Y)=>Y.id===Z.task_id))return{active:$.active,pending:$.pending.filter((Y)=>Y.id!==Z.task_id)};if($.active.some((Y)=>Y.id===Z.task_id))return{active:$.active.map((Y)=>Y.id===Z.task_id?{...Y,status:Q,usage:Z.usage??Y.usage,summary:Z.summary??Y.summary,endTime:Y.endTime??J}:Y),pending:$.pending};return $}function _4($){let Z=0,J=0;for(let Q=$.length-1;Q>=0;Q--)if(Z+=$[Q].brief.length+5,Z>BV){J=Q+1;break}return J===0?$:$.slice(J)}function RV($,Z){let J=(Q)=>typeof Q==="string"?Q:"";switch($){case"Bash":return R1(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 PV($,Z){let J=($??"").replace(/\s+/g," ").trim();return Z?`❌ ${J.slice(0,80)}`:J.slice(0,80)}function i8($,Z,J,Q,Y){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((A)=>A.toolUseId===Z?{...A,steps:_4([...A.steps,{toolUseId:J,tool:Q,brief:`${Q} ${RV(Q,Y)}`.trim()}])}:A);return{active:H?X($.active):$.active,pending:W?X($.pending):$.pending}}function n8($,Z,J,Q,Y,H){let W=$.active.some((A)=>A.id===Z),X=$.pending.some((A)=>A.id===Z);if(!W&&!X)return $;let V=(A)=>A.map((G)=>{if(G.id!==Z)return G;if(Y==="started")return{...G,steps:_4([...G.steps,{toolUseId:J,tool:Q,brief:`${Q} ${H}`.trim()}])};let _=!1,q=G.steps.map((B)=>{if(_||B.toolUseId!==J)return B;return _=!0,{...B,brief:H?`${B.brief} ${H}`:B.brief}});if(!_&&H)q.push({toolUseId:J,tool:Q,brief:`${Q} ${H}`.trim()});return{...G,steps:_4(q)}});return{active:W?V($.active):$.active,pending:X?V($.pending):$.pending}}function d8($,Z,J,Q,Y){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((A)=>{if(A.toolUseId!==Z)return A;let G=!1,_=A.steps.map((q)=>{if(G||q.toolUseId!==J)return q;return G=!0,{...q,brief:`${q.brief} → ${PV(Q,Y)}`}});return{...A,steps:_4(_)}});return{active:H?X($.active):$.active,pending:W?X($.pending):$.pending}}function h8($){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 p3($){let Z=Number.isFinite($)?Math.max(0,$):0;for(let H of jV)if(Z<H.limit)return{label:H.label,nextDelayMs:H.limit-Z};let J=600000,Q=Math.floor((Z-600000)/J),Y=600000+(Q+1)*J;return{label:`${(Q+1)*10}m+`,nextDelayMs:Y-Z}}function R0($,Z="bucket"){if(Z==="second"){let J=Number.isFinite($)?Math.max(0,$):0;if(J>=g8){let Q=Math.floor((J-g8)/m3),Y=g8+(Q+1)*m3;return{label:`${10+Q*5}m+`,nextDelayMs:Y-J}}return{label:`${Math.floor(J/1000)}s`,nextDelayMs:u3}}return p3($)}function FV($){return $.subagentType??$.workflowName??DV[$.type]}function I8($){if($.usage?.duration_ms)return $.usage.duration_ms;if($.endTime&&$.endTime>$.startedAt)return $.endTime-$.startedAt;return 0}function MV($,Z,J="bucket"){let Q=(Y)=>R0(Y,J).label;switch($.status){case"running":return`\uD83D\uDFE1 运行中 (${Q(Z-$.startedAt)})`;case"paused":return`⏸️ 已暂停 (${Q(Z-$.startedAt)})`;case"pending":return"⚪ 等待中";case"completed":return`✅ 用时 ${h8(I8($))}`;case"failed":return`❌ 失败 ${h8(I8($))}`;case"killed":return`\uD83D\uDC80 已终止 ${h8(I8($))}`}}function l3($){let Z=$.filter((Q)=>!y$(Q)).length,J=$.length-Z;if(Z>0)return`${Z} 进行中${J?` · ${J} 已结束`:""}`;return J?`${J} 已结束`:"空"}function K4($){return`\uD83E\uDDED 后台任务 · ${l3($)}`}function UV($){let Z=[];if($.error)Z.push(`⚠ ${$.error}`);if(y$($)&&$.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 $$(Z.length>0?Z.join(`
|
|
46
|
+
`):"_(暂无执行记录)_")}function j1($,Z=Date.now(),J="bucket"){return{tag:"collapsible_panel",element_id:J2.panel($.id),header:{title:{tag:"plain_text",content:`${LV[$.type]} ${FV($)} · ${$.description||"(无描述)"} — ${MV($,Z,J)}`}},expanded:!1,elements:[{tag:"markdown",element_id:J2.body($.id),content:UV($)}]}}function o8($,Z=Date.now(),J="bucket"){return{schema:"2.0",config:{streaming_mode:!0,summary:{content:K4($)}},body:{elements:$.map((Q)=>j1(Q,Z,J))}}}function q4($,Z=Date.now(),J="bucket"){let Q=$.filter(y$);return{schema:"2.0",config:{streaming_mode:!1,summary:{content:`\uD83E\uDDED 后台任务(历史) · ${Q.length} 已结束`}},body:{elements:Q.map((Y)=>j1(Y,Z,J))}}}function a8(){return{schema:"2.0",config:{streaming_mode:!1,summary:{content:"↪ 后台任务进行中"}},body:{elements:[{tag:"markdown",element_id:"bg_marker",content:"↪ 本轮后台任务仍在进行,进度已迁至最新卡片"}]}}}var J2,BV=1000,LV,DV,jV,u3=1000,g8=600000,m3=300000;var r8=N(()=>{N$();W4();J2={panel:($)=>`bg_${I3($)}`,body:($)=>`bgb_${I3($)}`};LV={subagent:"\uD83D\uDFE2",shell:"⚙️",monitor:"\uD83D\uDCE1",workflow:"\uD83D\uDD01",unknown:"\uD83D\uDD39"},DV={subagent:"子agent",shell:"shell",monitor:"监控",workflow:"工作流",unknown:"任务"};jV=[{limit:30000,label:"<30s"},{limit:60000,label:"<1m"},{limit:180000,label:"<3m"},{limit:300000,label:"<5m"},{limit:600000,label:"<10m"}]});function d$($){return typeof $==="string"&&OV.includes($)}function F1($){return $?.startsWith("claude:")?"claude":"codex"}function J0($){return $==="claude"?"Claude":"Codex"}var OV,P0="max",Q2;var v0=N(()=>{OV=["low","medium","high","xhigh","max"];Q2=class Q2 extends Error{constructor($="上下文窗口充足,无需压缩"){super($);this.name="NothingToCompactError"}}});function L0($){return $.startsWith("claude:")?$:`claude:${$}`}function t8($){if(!$||$==="default"||$==="claude:default")return"opus";if(!$.startsWith("claude:"))return $;let Z=$.slice(7);if(Z==="glm"||Object.hasOwn(w.claude.models,Z))return w.claude.models[Z]?.model?.trim()||"opus";return Z}var i3=N(()=>{U$()});import{existsSync as EV,readFileSync as TV}from"node:fs";function s8(){return process.env.LODESTAR_DATA_DIR?`${process.env.LODESTAR_DATA_DIR.replace(/\/+$/,"")}/context-window-cache.json`:i5}function H2(){if(Y2!==null)return Y2;try{Y2=EV(s8())?JSON.parse(TV(s8(),"utf8")):{}}catch($){z(`context-window-observe: cache read MISS (${$?.message??$}), starting fresh`),Y2={}}return Y2??{}}function NV(){try{X$(s8(),H2())}catch($){z(`context-window-observe: cache write MISS (${$?.message??$})`)}}function e8($,Z){return`${$}:${Z.replace(/\[1m\]$/,"")}`}function $6($,Z,J){if(!Number.isFinite(J)||J<=0)return;let Q=e8($,Z),Y=H2()[Q];if(Y===J)return;H2()[Q]=J,NV(),z(`context-window-observe: ${Q} → ${J} (prev ${Y??"-"})`)}function n3($,Z){$6($,Z,SV)}function B4($,Z){if(!Z)return;if(Z.endsWith("[1m]"))return Z;let J=H2()[e8($,Z)];return J!=null&&J<kV?Z:`${Z}[1m]`}function R4($,Z){return H2()[e8($,Z)]}var kV=1e6,SV=200000,Y2=null;var P4=N(()=>{L$();h();h$()});import{existsSync as D4,readFileSync as $Z}from"node:fs";import{homedir as X2}from"node:os";import{spawn as yV}from"cross-spawn";import{delimiter as d3,join as h0,posix as xV,win32 as bV}from"node:path";import{EventEmitter as CV}from"node:events";import{query as fV}from"@anthropic-ai/claude-agent-sdk";function wV($,Z){if(!Z||$.includes("user"))return{};return{plugins:[{type:"local",path:Z,skipMcpDiscovery:!0}],skills:"all"}}function vV($){return $==="win32"?";":":"}function J6($,...Z){return $==="win32"?bV.join(...Z):xV.join(...Z)}function o3($){let Z=$.toLowerCase();return Z.endsWith(".cmd")||Z.endsWith(".bat")}function a3($){let Z=yV($.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 JZ($={}){let Z=$.platform??process.platform,J=$.exists??D4,Q=$.homeDir??X2();if(Z!=="win32"){let H=[J6(Z,Q,".local","npm-global","bin","claude"),J6(Z,Q,".local","bin","claude")];for(let W of H)if(J(W))return W}let Y=gV($);if(Y)return Y;return null}function QZ(){JZ()}function hV($={}){let Z=$.platform??process.platform,J=$.configuredBin===void 0?w.claude.bin:$.configuredBin;if(J){if(!($.exists??D4)(J))throw Error(`lodestar: [claude].bin not found: ${J} (config.toml)`);if(Z==="win32"&&o3(J))return{pathToClaudeCodeExecutable:J,spawnClaudeCodeProcess:a3,description:`windows-shell-shim:${J}`};return{pathToClaudeCodeExecutable:J,description:`config:${J}`}}let Q=JZ($);if(!Q)return{description:"sdk-default"};if(Z==="win32"&&o3(Q))return{pathToClaudeCodeExecutable:Q,spawnClaudeCodeProcess:a3,description:`windows-shell-shim:${Q}`};return{description:"sdk-default"}}function gV($={}){let Z=$.platform??process.platform,J=$.pathEnv??process.env.PATH??"";if(!J)return null;let Q=$.exists??D4,Y=Z==="win32"?["claude.exe","claude.cmd","claude.bat","claude"]:["claude"];for(let H of J.split(vV(Z))){if(!H)continue;for(let W of Y){let X=J6(Z,H,W);if(Q(X))return X}}return null}function r3(){if(process.platform==="win32")return process.env.PATH??"";let $=[h0(X2(),".local","npm-global","bin"),h0(X2(),".local","bin"),h0(X2(),".bun","bin"),...(process.env.PATH??"").split(d3),"/usr/local/bin","/usr/bin","/bin"];return[...new Set($.filter(Boolean))].join(d3)}function IV($){let Z=B1($);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 t3($){if(!$)return null;let Z=($.input_tokens??0)+($.cache_read_input_tokens??0)+($.cache_creation_input_tokens??0);return Z>0?Z:null}function Y6($){let Z=$.replace(/[^a-zA-Z0-9]/g,"-"),J=process.env.CLAUDE_CONFIG_DIR||h0(X2(),".claude");return h0(J,"projects",Z)}function H6($,Z){return h0(Y6($),`${Z}.jsonl`)}function cV($){let Z;try{Z=$Z($,"utf8")}catch{return null}let J=Z.split(`
|
|
47
|
+
`);for(let Q=J.length-1;Q>=0;Q--){let Y=J[Q].trim();if(!Y)continue;try{let H=JSON.parse(Y);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 s3($,Z){let J=Z?.trim()||"no-source",Q=$&&$.trim()?$:"claude:default";return`${J}:${Q}`}function mV($){if(!$||typeof $!=="object")return{usage:null,contextWindow:null};let Z={},J=null;for(let Y of Object.values($)){if(!Y||typeof Y!=="object")continue;let H=Y;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 Q=(Z.input_tokens??0)+(Z.output_tokens??0)+(Z.cache_creation_input_tokens??0)+(Z.cache_read_input_tokens??0);if(Q<=0)return{usage:null,contextWindow:J};return Z.total_tokens=Q,{usage:Z,contextWindow:J}}function L4($){return{...$}}function Z6($){if(!$||typeof $!=="object")return[];return Object.keys($).slice(0,20)}function uV($,Z){let J=$?{...$}:{},Q=(Y)=>{let H=Z[Y];if(typeof H!=="number"||!Number.isFinite(H))return;J[Y]=(J[Y]??0)+H};return Q("total_tokens"),Q("input_tokens"),Q("output_tokens"),Q("reasoning_output_tokens"),Q("cache_creation_input_tokens"),Q("cache_read_input_tokens"),J}function M1($){return typeof $==="number"&&Number.isFinite($)?$:0}function YZ($){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(`
|
|
48
|
+
`);return $==null?"":JSON.stringify($,null,2)}function pV($){let Z=YZ($);try{let J=JSON.parse(Z);if(Array.isArray(J)){let Q=J.map((Y)=>{if(typeof Y==="string")return Y;if(Y&&typeof Y==="object"&&typeof Y.text==="string")return Y.text;return JSON.stringify(Y)}).filter(Boolean);if(Q.length>0)return Q.join(`
|
|
49
|
+
`)}}catch{}return Z}function lV($){return`server_tool:${$}`}function iV($){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 nV($){let Z=$.trim();return Z.includes("Built-in Tool:")||Z.startsWith("**Output:**")&&Z.includes("_result")}function dV($){let Z=$.supportedEffortLevels&&$.supportedEffortLevels.length>0?$.supportedEffortLevels:[P0];return{id:L0($.value),model:L0($.value),displayName:$.displayName||L0($.value),description:$.description||"Claude Agent SDK backend",hidden:!1,isDefault:!1,supportedReasoningEfforts:Z.map((J)=>({reasoningEffort:J,description:""})),defaultReasoningEffort:Z.includes(P0)?P0:Z[0]}}function aV($){if(!$?.settingSources)return[...e3];let Z=$.settingSources.split(",").map((J)=>J.trim()).filter(Boolean);return Z.length?Z:[...e3]}function rV($){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 tV($){let Z=h0($,".mcp.json"),J;try{J=$Z(Z,"utf8")}catch(Q){if(Q.code!=="ENOENT")z(`claude-agent-process: project .mcp.json not readable at ${Z}: ${Q}`);return}try{let Q=JSON.parse(J);if(Q&&typeof Q==="object"&&Q.mcpServers&&typeof Q.mcpServers==="object")return Q.mcpServers;z(`claude-agent-process: project .mcp.json has no mcpServers object at ${Z}`);return}catch(Q){z(`claude-agent-process: project .mcp.json parse failed at ${Z}: ${Q}`);return}}function sV($){let Z=$.questions;return(Array.isArray(Z)?Z:Z&&typeof Z==="object"?[Z]:[$]).map((Q)=>eV(Q)).filter((Q)=>Q!==null)}function eV($){let Z=$&&typeof $==="object"?$:{question:$},J=Q6(Z.question,Z.prompt,Z.title,Z.message,Z.text,Z.label);if(!J)return null;if(!J.trim())return null;let Q=$z(Z.options??Z.choices??Z.suggestions);return{...Z,question:J,options:Q,...typeof Z.header==="string"?{header:Z.header}:{},...typeof Z.multiSelect==="boolean"?{multiSelect:Z.multiSelect}:{}}}function $z($){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 Q=J,Y=Q6(Q.label,Q.value,Q.text,Q.title);if(!Y?.trim())continue;let H=Q6(Q.description,Q.detail,Q.preview);Z.push(H?{label:Y,description:H}:{label:Y})}return Z}function Q6(...$){for(let Z of $)if(typeof Z==="string")return Z;return}var ZZ,W2,oV="default",e3,W6;var j4=N(()=>{U$();h();v0();i3();P4();ZZ=class ZZ{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($))}};W2=new Map;e3=["project","local"];W6=class W6 extends CV{provider="claude";tokenSourceId;opts;input=new ZZ;query=null;abortController=new AbortController;alive=!0;expectedExit=!1;exitPromise;resolveExit;started=!1;pendingPermissions=new Map;requestCounter=0;cumulativeUsageFromResults=null;turnActive=!1;emittedToolUseIds=new Set;emittedToolResultIds=new Set;pendingServerToolInputs=[];sessionId=null;lastAssistantUuid=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;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?L0($.model):null}sendInitialize(){if(this.started)return;this.started=!0;let $=t8(this.opts.model),Z=this.opts.profile;if(Z)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??aV(Z),Q=wV(J,this.opts.managedSkillPluginPath),Y=rV(Z),H=Z?.strictMcp===!0,W=Z?.loadProjectMcp!==!1?tV(this.opts.workDir):void 0;try{let X=hV();z(`claude-agent-process: spawn SDK query model=${$??"default"} effort=${this.opts.effort} cwd=${this.opts.workDir} executable=${X.description}`),this.query=fV({prompt:this.input,options:{cwd:this.opts.workDir,abortController:this.abortController,...$?{model:$}:{},effort: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:oV,env:this.opts.transformEnv?this.opts.transformEnv({...process.env,PATH:r3(),...w.claude.env,...this.opts.hostEnv??{}}):{...process.env,PATH:r3(),...w.claude.env,...this.opts.hostEnv??{}},settingSources:[...J],...Q,tools:Y,...H?{strictMcpConfig:!0}:{},...W?{mcpServers:W}:{},toolConfig:{askUserQuestion:{previewFormat:"markdown"}},canUseTool:(V,A,G)=>this.canUseTool(V,A,G),includePartialMessages:!1,systemPrompt:{type:"preset",preset:"claude_code",...this.opts.appendSystemPrompt?{append:this.opts.appendSystemPrompt}:{}},stderr:(V)=>{let A=V.trim();if(A)z(`claude-agent-process[stderr]: ${A}`)}}})}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){z("claude-agent-process: sendUserText ignored on dead process");return}if(!this.started)this.sendInitialize();let J=Z.length?Z.map((Q)=>`[file: ${Q}]`).join(" ")+`
|
|
50
50
|
|
|
51
|
-
`:"";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(Q){let Y=Q instanceof Error?Q:Error(String(Q));z(`claude-agent-process: sendUserText failed: ${Y.message}`),this.failTurnStart(Y)}}sendInterrupt(){this.query?.interrupt().catch(($)=>z(`claude-agent-process: interrupt failed: ${$}`))}sendPermissionResponse($,Z,J){let Q=this.pendingPermissions.get(String($));if(!Q){z(`claude-agent-process: permission response for unknown request ${$}`);return}if(this.pendingPermissions.delete(String($)),Q.cleanup?.(),Z==="allow")Q.resolve({behavior:"allow",updatedInput:J?.updatedInput??{}});else Q.resolve({behavior:"deny",message:J?.denyMessage??""})}sendHookResponse($,Z={}){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 z(`claude-agent-process: kill failed: ${J.message}`),J}if(Z){let J=Error(`claude Agent SDK close failed: ${Z.message}`,{cause:Z});throw z(`claude-agent-process: kill failed: ${J.message}`),J}}async listModels(){if(!this.started)this.sendInitialize();if(!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");return(await this.query.supportedModels()).map(uV)}async setModelSettings($,Z){let J=t8($);if(!d$(Z))throw Error(`invalid Claude effort: ${String(Z)}`);if(!this.started)this.sendInitialize();if(!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");if(J)await this.query.setModel(J);if(Z==="max")await this.query.applyFlagSettings({ultracode:!0,effortLevel:null});else await this.query.applyFlagSettings({effortLevel:Z,ultracode:null});this.opts.model=$,this.opts.effort=Z,this.lastModel=J?L0($):"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,Q=()=>{this.off("context_compacted",Y),this.off("assistant_text",H),this.off("exit",W),this.off("error",X)},Y=()=>{if(J)return;J=!0,Q(),$()},H=(V)=>{if(J)return;if((V?.text??"").includes("Not enough messages to compact"))J=!0,Q(),Z(new J2)},W=()=>{if(J)return;J=!0,Q(),Z(Error("claude thread exited during /compact"))},X=(V)=>{if(J)return;J=!0,Q(),Z(V instanceof Error?V:Error(String(V)))};this.on("context_compacted",Y),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 Q=dV(Z);if(Q.length===0)return z("claude-agent-process: AskUserQuestion 无有效 questions — allow 原样"),Promise.resolve({behavior:"allow",updatedInput:Z});let Y={...Z,questions:Q},H=`claude_perm_${++this.requestCounter}`,W=J.toolUseID||H,X={request_id:H,tool_name:"AskUserQuestion",input:Y,tool_use_id:W},V=new Promise((A)=>{let G=(q)=>{J.signal.removeEventListener("abort",_),A(q)},_=()=>{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",Y,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){z(`claude-agent-process: read loop stopped after requested shutdown: ${J.message}`),this.finishExit(null,null);return}z(`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(),z(`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,Q=(H)=>{if(J)return;J=!0,clearTimeout(Y),Z(H)},Y=setTimeout(()=>Q(!this.alive),Math.max(0,$));this.exitPromise.then(()=>Q(!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:z(`claude-agent-process: unhandled message type=${Z.type??"unknown"} subtype=${Z.subtype??""}`)}}handleSystemMessage($){switch($.subtype){case"init":if(typeof $.model==="string"&&$.model)this.lastModel=L0($.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.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":z(`claude-agent-process: api retry attempt=${$.attempt}/${$.max_retries} status=${$.error_status} error=${$.error}`);return;case"permission_denied":z(`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){z("claude-agent-process: task_notification missing task_id");return}if($.status!=="completed"&&$.status!=="failed"&&$.status!=="stopped"){z(`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:z(`claude-agent-process: unhandled system subtype=${String($.subtype??"unknown")}`);return}}handleAssistantMessage($){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=L0(Z.model);let Q=Array.isArray(Z?.content)?Z.content:[];for(let Y of Q){if(!Y||typeof Y!=="object")continue;if(Y.type==="text"&&typeof Y.text==="string"&&Y.text.length>0){let H=cV(Y.text);if(H){if(this.pendingServerToolInputs.push(H),this.pendingServerToolInputs.length>20)this.pendingServerToolInputs.shift()}if(mV(Y.text))continue;let W=$.uuid??Z?.id;this.emit("assistant_text",{uuid:W,text:Y.text,parentToolUseId:J}),this.emit("assistant_block_stop",{index:W,parentToolUseId:J})}else if(Y.type==="tool_use"&&typeof Y.id==="string"&&typeof Y.name==="string")this.emitToolUseOnce(Y.id,Y.name,Y.input??{},J);else if(Y.type==="server_tool_use"&&typeof Y.id==="string"&&typeof Y.name==="string")this.emitToolUseOnce(Y.id,IV(Y.name),{tool:Y.name,input:this.serverToolInput(Y.name,Y.input??{})},J);else if(Y.type==="tool_result"&&typeof Y.tool_use_id==="string")this.emitToolResultOnce(Y.tool_use_id,gV(Y.content),Y.is_error===!0,J)}}emitToolUseOnce($,Z,J,Q){if(this.emittedToolUseIds.has($))return;this.emittedToolUseIds.add($),this.emit("tool_use",{id:$,name:Z,input:J,parentToolUseId:Q})}serverToolInput($,Z){let J=Z;if(J&&typeof J==="object"&&!Array.isArray(J)&&Object.keys(J).length>0)return J;let Q=this.pendingServerToolInputs.findIndex((Y)=>Y.name===$);if(Q>=0){let[Y]=this.pendingServerToolInputs.splice(Q,1);return Y.input}return J}emitToolResultOnce($,Z,J,Q){if(this.emittedToolResultIds.has($))return;this.emittedToolResultIds.add($),this.emit("tool_result",{tool_use_id:$,content:Z,is_error:J,parentToolUseId:Q})}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 Q of J){if(!Q||typeof Q!=="object")continue;if(Q.type!=="tool_result"||typeof Q.tool_use_id!=="string")continue;let Y=$.tool_use_result,H=JZ(Q.content),W=Y&&typeof Y==="object"?[typeof Y.stdout==="string"?Y.stdout:"",typeof Y.stderr==="string"?Y.stderr:""].filter(Boolean).join(`
|
|
52
|
-
`):"",X=H||W;this.emitToolResultOnce(Q.tool_use_id,X,Q.is_error===!0||Y?.interrupted===!0,$.parent_tool_use_id??null)}}handleResultMessage($){if(typeof $.session_id==="string"&&$.session_id)this.sessionId=$.session_id;this.turnActive=!1;let Z=fV($.usage),J=$.modelUsage??$.model_usage,Q=vV(J);if(!Z&&!Q.usage)z(`claude-agent-process: result usage missing rootKeys=${Z6($).join(",")||"-"} usageKeys=${Z6($.usage).join(",")||"-"} modelUsageKeys=${Z6(J).join(",")||"-"}`);if(this.lastUsage=Z,Q.usage)this.cumulativeUsageFromResults=L4(Q.usage),this.lastTotalUsage=L4(Q.usage);else if(Z)this.cumulativeUsageFromResults=hV(this.cumulativeUsageFromResults,Z),this.lastTotalUsage=L4(this.cumulativeUsageFromResults);else this.lastTotalUsage=this.cumulativeUsageFromResults?L4(this.cumulativeUsageFromResults):null;if(Q.contextWindow!=null){let X=r3(this.opts.model,this.tokenSourceId),V=H2.get(X)??0;if(Q.contextWindow>V)H2.set(X,Q.contextWindow),z(`claude-agent-process: SDK contextWindow ${Q.contextWindow} (global max for ${X}, prev ${V||"-"})`);else if(Q.contextWindow<(H2.get(X)??0))z(`claude-agent-process: SDK contextWindow ${Q.contextWindow} ignored (global max ${H2.get(X)} locked for ${X})`);if(this.tokenSourceId)for(let[A,G]of Object.entries(J??{})){let _=G?.contextWindow;if(typeof _==="number"&&_>0)$6(this.tokenSourceId,A,_)}}this.lastContextWindow=H2.get(r3(this.opts.model,this.tokenSourceId))??Q.contextWindow??null;let Y=H6(this.opts.workDir,this.sessionId??""),H=wV(Y);if(this.lastContextTokens=a3(H)??(D4(Y)?a3(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";if(this.tokenSourceId&&$.is_error===!0){let X=String($.result??$.error??$.api_error_message??"");if(/context.?window|prompt is too long|exceeds?.*(?:context|token)|too many (?:input )?tokens/i.test(X)){let G=(this.lastModel??(this.opts.model?.trim()||"claude:default")).replace(/^claude:/,"");l3(this.tokenSourceId,G),z(`claude-agent-process: context window exceeded on ${G} — downgraded to 200K (no [1m] next spawn)`)}}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,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 WZ={};G1(WZ,{waitForTokenSourceModelRefresh:()=>U4,tokenSourceFactories:()=>O1,setDefaultTokenSource:()=>V6,scrubAnthropicEnv:()=>g0,resetTokenSourceRegistry:()=>z6,registerTokenSourceFactory:()=>Q0,registerTokenSource:()=>X6,refreshAllTokenSourceModels:()=>V2,pendingTokenSourceModelRefresh:()=>E1,listTokenSourcesByAgent:()=>HZ,listTokenSources:()=>I0,listEnabledTokenSourcesByAgent:()=>M4,getTokenSource:()=>$$});function g0($){let Z={...$};for(let J of rV)delete Z[J];return Z}function Q0($){QZ.set($.kind,$)}function O1(){return[...QZ.values()]}function X6($,Z){if(X2.set($.id,$),Z?.default||F4===null)F4=$.id}function $$($){return $?X2.get($):void 0}function I0(){return[...X2.values()]}function HZ($){return I0().filter((Z)=>Z.agent===$)}function M4($){return HZ($).filter((Z)=>Z.enabled)}function V6($){if(X2.has($))F4=$}function z6(){X2.clear(),F4=null,YZ++}function V2(){let $=YZ;if(U1?.generation===$)return U1.promise;let Z=Promise.allSettled(I0().map(async(J)=>{await J.refreshModels(),z(`token-source ${J.id}: ${J.models.length} models loaded`)})).then(()=>{}).finally(()=>{if(U1?.promise===Z)U1=null});return U1={generation:$,promise:Z},Z}function E1(){return U1?.promise??null}async function U4(){let $;while($=E1())await $}var rV,QZ,X2,F4=null,YZ=0,U1=null;var _$=N(()=>{h();rV=["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL"];QZ=new Map;X2=new Map});function O4($){let Z=$.tokenSourceId?$$($.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;if(Z&&J&&!Z.models.some((H)=>H.model===J))throw Error(`model is not present in token source ${Z.id}: ${J}`);let Q=Z&&J?Z.resolveSpawnModel(J):J;if(J&&!Q)throw Error(`model did not resolve: ${$.tokenSourceId??"default"}/${J}`);let Y=Z?(H)=>Z.spawnEnv(H):void 0;if($.provider==="claude"){if(ZZ(),!d$($.effort))throw Error(`invalid Claude effort: ${$.effort??"MISS"}`);return{process:new W6({workDir:$.workDir,model:Q,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}:{},...$.profile?{profile:$.profile}:{},...Z?{settingSources:Z.settingSources??["project","local"]}:{},...$.managedSkillPluginPath?{managedSkillPluginPath:$.managedSkillPluginPath}:{},tokenSourceId:Z?.id??null,transformEnv:Y,hostEnv:$.hostEnv}),sourceRevision:Z?.spawnRevision??null}}if($.effort!==void 0&&!S$($.effort))throw Error(`invalid Codex effort: ${$.effort}`);return{process:new L1({workDir:$.workDir,model:Q,effort:$.effort,launch:$.launch,...$.developerInstructions?{appendSystemPrompt:$.developerInstructions}:{},tokenSourceId:Z?.id??null,transformEnv:Y,hostEnv:$.hostEnv,serviceName:$.serviceName}),sourceRevision:Z?.spawnRevision??null}}var A6=N(()=>{v0();j4();D1();_$()});function E4($,Z){return`http://${$==="0.0.0.0"?"127.0.0.1":$==="::"||$==="::1"?"[::1]":$}:${Z}`}async function G6($){let Z=await q6("feishu chat.get",()=>t.im.chat.get({path:{chat_id:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)T4("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 _6($,Z){let J=await q6("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)T4("feishu tasklist.create",J);let Q=J.data?.tasklist,Y=Q?.guid;if(!Y)throw Error("feishu tasklist.create returned no guid");return{guid:Y,name:Q?.name||$,url:Q?.url??"",createdAt:Q?.created_at}}async function K6($){let Z=await q6("feishu tasklist.delete",()=>t.task.v2.tasklist.delete({path:{tasklist_guid:$}}));if(Z.code&&Z.code!==0)T4("feishu tasklist.delete",Z)}function XZ($,Z){let J=Z&&typeof Z==="object"?Z:{},Q=J.response?.data&&typeof J.response.data==="object"?J.response.data:J.data&&typeof J.data==="object"?J.data:J,Y=Q.code??J.code,H=Q.msg??Q.message??J.msg??J.message??"unknown error",W=Q.error?.permission_violations??Q.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=${Y??"unknown"} msg=${H}${X?` missing_scopes=${X}`:""}`}async function q6($,Z){try{return await Z()}catch(J){T4($,J)}}function T4($,Z){throw Error(XZ($,Z))}var VZ=N(()=>{r()});var Z$={};G1(Z$,{writeAliveMarker:()=>R2,urgentApp:()=>l0,uploadImageKey:()=>c6,uploadAndSend:()=>m6,updateCard:()=>H0,unbindSessionChat:()=>N4,tempProjectName:()=>o$,tempChatName:()=>S6,setPendingConversationLaunchChecked:()=>D0,sendTextRaw:()=>b,sendText:()=>E,sendImage:()=>CZ,sendFile:()=>fZ,sendCard:()=>i,sanitizeSessionName:()=>j2,resolveProjectDir:()=>b4,replaceTurnAnchors:()=>I$,registerTempSessionLease:()=>F6,refreshChatList:()=>P2,readAliveMarker:()=>f6,provisionProject:()=>u6,projectProfile:()=>k1,preferredChatForSession:()=>Q$,loadTempSessionLeases:()=>j6,loadSessionTurnsMap:()=>T6,loadSessionResumeMap:()=>O6,loadSessionModelMap:()=>N6,loadSessionChatMap:()=>U6,listNormalChatIdsByName:()=>C4,isOpenAIChatGPTAuthenticated:()=>D2,hasTempSessionLease:()=>M6,getTurnAnchors:()=>K2,getTenantToken:()=>Y0,getSessionResumeRef:()=>p0,getSessionModelSelection:()=>b6,getSessionBranchBase:()=>q2,getPendingConversationLaunch:()=>B2,formatFeishuApiError:()=>XZ,findNormalChatIdByName:()=>f4,fetchChatOwnerOpenId:()=>G6,fetchChatName:()=>I6,ensureChatForSession:()=>w6,downloadAttachment:()=>L2,disbandChatForSessionExact:()=>g6,disbandChatForSession:()=>h6,deleteTasklistByGuid:()=>K6,deleteReaction:()=>j$,createTempChatForSession:()=>v6,createTasklistWithOwner:()=>_6,client:()=>t,clearSessionResumeChecked:()=>S1,clearSessionConversationState:()=>C6,chatNameCache:()=>Y$,chatIdForSession:()=>N1,bindSessionToChat:()=>T1,bindSessionResumeChecked:()=>_2,bindSessionModelChecked:()=>x6,bindSessionModel:()=>y6,appendTurnAnchorChecked:()=>k6,addReaction:()=>T$,PROJECTS_ROOT:()=>UZ});import*as BZ from"@larksuiteoapi/node-sdk";import{execSync as RZ}from"node:child_process";import{randomUUID as D6}from"node:crypto";import{existsSync as tV,mkdirSync as R6,readFileSync as m0,statSync as PZ,writeFileSync as LZ}from"node:fs";import{readFile as DZ}from"node:fs/promises";import{homedir as zZ}from"node:os";import{basename as c0,extname as sV,isAbsolute as jZ,join as S4}from"node:path";function P6(){let $={};for(let[Z,J]of E$)$[Z]=J;X$(A8,$)}function j6(){E$.clear();try{let $=JSON.parse(m0(A8,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("lease file must contain an object");for(let[Z,J]of Object.entries($)){let Q=J;if(typeof Z!=="string"||!Z||Q.chatId!==Z||typeof Q.sessionName!=="string"||!o$(Q.sessionName)||typeof Q.createdAt!=="number"||!Number.isFinite(Q.createdAt)){z(`feishu: rejected malformed temp-session lease chat=${Z}`);continue}E$.set(Z,{chatId:Z,sessionName:Q.sessionName,createdAt:Q.createdAt})}z(`feishu: loaded ${E$.size} temporary-session leases`)}catch($){if($?.code!=="ENOENT")z(`feishu: load temp-session leases failed: ${$?.message??$}`)}}function F6($,Z){if(!o$($))throw Error(`refusing to lease non-temporary session name "${$}"`);if(!Z)throw Error("cannot lease a temporary session without chat_id");for(let Y of E$.values())if(Y.sessionName===$&&Y.chatId!==Z)throw Error(`temporary session name "${$}" is already leased to ${Y.chatId}`);let J=E$.get(Z),Q={sessionName:$,chatId:Z,createdAt:Date.now()};E$.set(Z,Q);try{P6()}catch(Y){if(J)E$.set(Z,J);else E$.delete(Z);throw Y}}function M6($,Z){let J=E$.get(Z);return J?.sessionName===$&&J.chatId===Z}function k1($){return w.projects[$]}function b4($){return k1($)?.cwd?.trim()||S4(UZ,$)}function u0($,Z={}){return fetch($,{...Z,signal:Z.signal??AbortSignal.timeout(eV)})}async function Y0(){if(k4&&Date.now()<AZ)return k4;return B6??=(async()=>{let $=await u0("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({app_id:FZ,app_secret:MZ})}),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 k4=Z.tenant_access_token,AZ=Date.now()+Math.max(0,(Z.expire??7200)-60)*1000,k4})().finally(()=>{B6=null}),B6}function U6(){try{let $=JSON.parse(m0(W8,"utf8"));for(let[Z,J]of Object.entries($))if(typeof J==="string")Q$.set(Z,J);z(`feishu: loaded ${Q$.size} session→chat bindings`)}catch($){if($?.code!=="ENOENT")z(`feishu: load session-chat-map failed: ${$?.message??$}`)}}function OZ(){try{L6()}catch($){z(`feishu: save session-chat-map failed: ${$}`)}}function L6(){let $={};for(let[Z,J]of Q$)$[Z]=J;X$(W8,$)}function T1($,Z){if(Q$.get($)===Z)return;let J=Q$.get($);Q$.set($,Z),OZ(),z(`feishu: bound session "${$}" → ${Z}${J?` (was ${J})`:""}`)}function N4($){let Z=Q$.get($);if(!Z)return;Q$.delete($),OZ(),z(`feishu: unbound session "${$}" from ${Z}`)}function A2($,Z){let J=J$.get($)??{};J[Z.provider]=Z,J$.set($,J)}function GZ($,Z){if(!$||typeof $!=="object"||Array.isArray($))return null;let J=$,Q=J.provider==="claude"||J.provider==="codex"?J.provider:Z??null;if(!Q||Z&&Q!==Z)return null;let Y=typeof J.sessionId==="string"?J.sessionId.trim():typeof J.session_id==="string"?J.session_id.trim():"";if(!Y)return null;if(J.cwd===void 0||J.cwd===null)return{provider:Q,sessionId:Y,cwd:null};if(typeof J.cwd!=="string"||!jZ(J.cwd))return null;return{provider:Q,sessionId:Y,cwd:J.cwd}}function _Z($){let Z=$.sessionId.trim();if(!Z)throw Error("cannot bind an empty conversation session id");if($.provider!=="codex"&&$.provider!=="claude")throw Error(`cannot bind an unknown conversation provider: ${String($.provider)}`);if(typeof $.cwd!=="string"||!jZ($.cwd))throw Error(`cannot bind a conversation without an absolute cwd: ${String($.cwd)}`);return{provider:$.provider,sessionId:Z,cwd:$.cwd}}function $z($,Z,J){if(typeof $!=="string")return _Z($);if(!Z)throw Error("cannot bind a conversation without a provider");return _Z({provider:Z,sessionId:$,cwd:J??null})}function O6(){try{let $=JSON.parse(m0(X8,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("resume map must contain an object");J$.clear();for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){A2(Z,{provider:"codex",sessionId:J.trim(),cwd:null});continue}if(!J||typeof J!=="object"||Array.isArray(J))continue;let Q=J,Y=GZ(Q);if(Y){A2(Z,Y);continue}for(let H of["codex","claude"]){let W=Q[H];if(typeof W==="string"&&W.trim()){A2(Z,{provider:H,sessionId:W.trim(),cwd:null});continue}let X=GZ(W,H);if(X)A2(Z,X)}}z(`feishu: loaded ${J$.size} session→resume bindings`)}catch($){if($?.code!=="ENOENT")z(`feishu: load session-resume-map failed: ${$?.message??$}`)}}function y4(){let $={};for(let[Z,J]of J$){let Q={};if(J.codex)Q.codex={...J.codex};if(J.claude)Q.claude={...J.claude};$[Z]=Q}X$(X8,$)}function _2($,Z,J,Q){let Y=$z(Z,J,Q),H=J$.get($),W=H?{...H}:void 0,X=H?.[Y.provider];if(X?.sessionId===Y.sessionId&&X.cwd===Y.cwd)return;A2($,Y);try{y4()}catch(V){if(W)J$.set($,W);else J$.delete($);throw V}}function p0($,Z="codex"){let J=J$.get($)?.[Z];return J?{...J}:null}function S1($,Z){let J=J$.get($);if(!J||Z&&J[Z]===void 0)return;let Q={...J};if(!Z)J$.delete($);else{let Y={...J};if(delete Y[Z],!Y.codex&&!Y.claude)J$.delete($);else J$.set($,Y)}try{y4()}catch(Y){throw J$.set($,Q),Y}}function EZ($){if(!$||typeof $!=="object")return null;let Z=$;if(Z.provider!=="claude"&&Z.provider!=="codex")return null;let J=typeof Z.sessionId==="string"?Z.sessionId.trim():"";if(!J)return null;let Q;if(Z.cwd===void 0||Z.cwd===null)Q=null;else if(typeof Z.cwd==="string"&&Z.cwd.trim())Q=Z.cwd;else return null;return{provider:Z.provider,sessionId:J,cwd:Q}}function TZ($){if(!$||typeof $!=="object")return null;let Z=$,J=Z.source;if(!J||typeof J!=="object")return null;let Q=EZ(J),Y=typeof Z.id==="string"?Z.id.trim():"";if(!Y||!Q)return null;if(Z.provider==="claude"&&Z.kind==="assistant-message"&&Q.provider==="claude")return{provider:"claude",kind:"assistant-message",id:Y,source:{...Q,provider:"claude"}};if(Z.provider==="codex"&&Z.kind==="turn"&&Q.provider==="codex")return{provider:"codex",kind:"turn",id:Y,source:{...Q,provider:"codex"}};return null}function kZ($){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=EZ(Z.source);if(!J)return null;let Q=Z.kind==="resume"?{kind:"resume",source:J}:(()=>{if(!Object.prototype.hasOwnProperty.call(Z,"through"))return{kind:"fork",source:J};let Y=TZ(Z.through);return Y?{kind:"fork",source:J,through:Y}:null})();if(!Q)return null;try{G$(Q,J.provider)}catch{return null}return Q}function Zz($){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 Jz($,Z){if(!$||typeof $!=="object")return null;let J=$;if(typeof J.ts!=="number"||!Number.isFinite(J.ts))return null;let Q=Object.prototype.hasOwnProperty.call(J,"checkpoint"),Y=TZ(J.checkpoint);if(Q&&!Y)return null;if(!Y){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;Y={provider:"claude",kind:"assistant-message",id:H,source:{provider:"claude",sessionId:W,cwd:null}}}return{checkpoint:Y,preview:String(J.preview??""),ts:J.ts,writes:Zz(J.writes)}}function Qz($){if(!$||typeof $!=="object")return null;let Z=$,J=kZ(Z.launch);if(J?.kind!=="fork"||J.source.provider!=="claude"||J.source.cwd===null)return null;let Q=Z.previousSessionId,Y=Q===null?null:typeof Q==="string"&&Q.trim()?Q.trim():void 0;if(Y===void 0)return null;return{launch:{...J,source:{...J.source,provider:"claude"}},previousSessionId:Y}}function E6($){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 T6(){try{let $=JSON.parse(m0(V8,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("turns map must contain an object");l.clear();let Z=0,J=0;for(let[Q,Y]of Object.entries($)){let H,W,X=null;if(Array.isArray(Y))H=Y,W=null;else if(Y&&typeof Y==="object"&&!Array.isArray(Y)){let _=Y;if(!Array.isArray(_.anchors)||!Object.prototype.hasOwnProperty.call(_,"base")){J++;continue}if(H=_.anchors,_.base===null)W=null;else{let q=kZ(_.base);if(!q){J++;continue}W=q}if(Object.prototype.hasOwnProperty.call(_,"pendingLaunch")){let q=Qz(_.pendingLaunch);if(!q){J++;continue}X=q}}else{J++;continue}let V=J$.get(Q),A=V?.claude!==void 0&&V.codex===void 0?"claude":null,G=[];for(let _ of H){let q=Jz(_,A);if(q)G.push(q);else J++}if(G.length||W!==null||X)l.set(Q,{base:W,anchors:G,...X?{pendingLaunch:X}:{}}),Z+=G.length}if(z(`feishu: loaded ${Z} turn anchors across ${l.size} sessions`),J>0)z(`feishu: rejected ${J} malformed turn anchors while loading`)}catch($){if($?.code!=="ENOENT")z(`feishu: load session-turns-map failed: ${$?.message??$}`)}}function G2(){let $={};for(let[Z,J]of l)$[Z]=J;X$(V8,$)}function k6($,Z){let J=l.get($),Q=[...J?.anchors??[],Z],Y=J?.base??null;if(Q.length>KZ){let H=Q.splice(0,Q.length-KZ),W=H[H.length-1].checkpoint;Y={kind:"fork",source:W.source,through:W}}l.set($,{base:Y,anchors:Q,...J?.pendingLaunch?{pendingLaunch:J.pendingLaunch}:{}});try{G2()}catch(H){if(J)l.set($,J);else l.delete($);throw H}}function K2($){return l.get($)?.anchors??[]}function q2($){return l.get($)?.base??null}function B2($){let Z=l.get($)?.pendingLaunch;return Z?E6(Z):null}function D0($,Z){if(Z){if(Z.launch.source.cwd===null)throw Error("pending conversation launch source cwd is missing");G$(Z.launch,"claude",Z.launch.source.cwd)}let J=l.get($),Q=J?.base??null,Y=J?.anchors.slice()??[];if(!Z&&Y.length===0&&Q===null)l.delete($);else l.set($,{base:Q,anchors:Y,...Z?{pendingLaunch:E6(Z)}:{}});try{G2()}catch(H){if(J)l.set($,J);else l.delete($);throw H}}function I$($,Z,J,Q){let Y=l.get($),H=Q===void 0?Y?.pendingLaunch:Q??void 0,W=H?E6(H):void 0;if(Z.length===0&&J===null&&!W)l.delete($);else l.set($,{base:J,anchors:Z.slice(),...W?{pendingLaunch:W}:{}});try{G2()}catch(X){if(Y)l.set($,Y);else l.delete($);throw X}}function o$($){return qZ.test($)?$.replace(qZ,""):null}function S6($,Z=[]){let J=new Date,Q=(X)=>String(X).padStart(2,"0"),Y=`${Q(J.getMonth()+1)}${Q(J.getDate())}-${Q(J.getHours())}${Q(J.getMinutes())}`,H=new Set([...Y$.values(),...l.keys(),...Z]),W=`${$}*${Y}`;for(let X=2;H.has(W);X++)W=`${$}*${Y}-${X}`;return W}function N6(){try{let $=JSON.parse(m0(z8,"utf8"));for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){D$.set(Z,{provider:F1(J),model:J,effort:null});continue}if(!J||typeof J!=="object")continue;let{model:Q,provider:Y}=J,H=Y==="claude"||Y==="codex"?Y:typeof Q==="string"&&Q.trim()?F1(Q):"claude",W=typeof Q==="string"&&Q.trim()?Q:null;if(H==="claude"&&!W)continue;let{effort:X,tokenSourceId:V}=J,A=typeof V==="string"&&V.trim()?V.trim():null,G=H==="claude"?d$(X)?X:null:S$(X)?X:null;D$.set(Z,{provider:H,model:W,effort:G,...A?{tokenSourceId:A}:{}})}z(`feishu: loaded ${D$.size} session→model bindings`)}catch($){if($?.code!=="ENOENT")z(`feishu: load session-model-map failed: ${$?.message??$}`)}}function Yz(){try{x4()}catch($){z(`feishu: save session-model-map failed: ${$}`)}}function x4(){let $={};for(let[Z,J]of D$)$[Z]=J;X$(z8,$)}function y6($,Z,J,Q,Y){let H=D$.get($);if(H?.provider===Z&&H.model===J&&H.effort===Q&&(H.tokenSourceId??null)===(Y??null))return;D$.set($,{provider:Z,model:J,effort:Q,...Y?{tokenSourceId:Y}:{}}),Yz()}function x6($,Z,J,Q,Y){let H=D$.get($),W={provider:Z,model:J,effort:Q,...Y?{tokenSourceId:Y}:{}};if(H?.provider===Z&&H.model===J&&H.effort===Q&&(H.tokenSourceId??null)===(Y??null))return;D$.set($,W);try{x4()}catch(X){if(H)D$.set($,H);else D$.delete($);throw X}}function b6($){let Z=D$.get($);if(Z)return Z;let J=o$($);return J?D$.get(J)??null:null}function C6($){let Z=Q$.get($),J=J$.get($),Q=D$.get($),Y=l.get($),H=[...E$.entries()].filter(([,W])=>W.sessionName===$);Q$.delete($),J$.delete($),D$.delete($),l.delete($);for(let[W]of H)E$.delete(W);try{L6(),y4(),x4(),G2(),P6()}catch(W){if(Z)Q$.set($,Z);if(J)J$.set($,J);if(Q)D$.set($,Q);if(Y)l.set($,Y);for(let[V,A]of H)E$.set(V,A);let X=[W];for(let V of[L6,y4,x4,G2,P6])try{V()}catch(A){X.push(A)}throw X.length===1?X[0]:AggregateError(X,`failed to clear and restore conversation state for ${$}`)}}function R2($){try{X$(a2,$)}catch(Z){z(`feishu: write alive marker failed: ${Z}`)}}function f6(){if(!tV(a2))return[];try{let $=m0(a2,"utf8"),Z=JSON.parse($);return Array.isArray(Z)?Z.filter((J)=>typeof J==="string"):[]}catch($){return z(`feishu: read alive marker failed: ${$}`),[]}}function N1($){let Z=Q$.get($);if(Z){let Q=Y$.get(Z);if(Q&&Q!==$)z(`feishu: chatIdForSession("${$}"): persisted binding ${Z} has cached name "${Q}", using persisted binding`);return Z}let J=[];for(let[Q,Y]of Y$)if(Y===$)J.push(Q);if(J.length===1)return J[0];if(J.length>1)z(`feishu: chatIdForSession("${$}"): ${J.length} candidates with no binding — [${J.join(", ")}]`);return null}async function P2(){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)Y$.set(J.chat_id,J.name);$=Z.data?.page_token}while($);z(`feishu: refreshed chat list — ${Y$.size} groups`)}catch($){z(`feishu: refresh chat list failed: ${$}`)}}async function C4(){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 Q of J.data?.items??[]){if(!Q.chat_id||!Q.name)continue;if(Q.chat_status&&Q.chat_status!=="normal")continue;Y$.set(Q.chat_id,Q.name);let Y=$.get(Q.name)??[];Y.push(Q.chat_id),$.set(Q.name,Y)}Z=J.data?.page_token}while(Z);return $}async function f4($){let Z=Q$.get($);if(Z&&Y$.get(Z)===$){let H=await NZ(Z);if(H.name===$&&yZ(H.status))return Z;Y$.delete(Z),N4($)}let Q=(await C4()).get($)??[];if(Q.length===0)return null;let Y=Q$.get($);if(Y&&Q.includes(Y))return Y;if(Q.length===1)return Q[0];throw Error(`multiple Feishu groups named "${$}": ${Q.join(", ")}`)}async function w6($,Z){if(!Z)throw Error("missing sender open_id; cannot add user to worktree group");let J=await f4($);if(J){let H=await Hz(J,Z);return T1($,J),{chatId:J,created:!1,joined:H}}let Q=await t.im.chat.create({params:{user_id_type:"open_id",uuid:D6()},data:{name:$,user_id_list:[Z],group_message_type:"chat"}});if(Q.code&&Q.code!==0)throw Error(`feishu chat.create failed code=${Q.code} msg=${Q.msg}`);let Y=Q.data?.chat_id;if(!Y)throw Error("feishu chat.create returned no chat_id");return Y$.set(Y,$),T1($,Y),{chatId:Y,created:!0,joined:!0}}async function v6($,Z){if(!Z)throw Error("missing sender open_id; cannot create temporary group");if(await f4($))throw Error(`temporary group name already exists: ${$}`);let Q=await t.im.chat.create({params:{user_id_type:"open_id",uuid:D6()},data:{name:$,user_id_list:[Z],group_message_type:"chat"}});if(Q.code&&Q.code!==0)throw Error(`feishu chat.create failed code=${Q.code} msg=${Q.msg}`);let Y=Q.data?.chat_id;if(!Y)throw Error("feishu chat.create returned no chat_id");return Y$.set(Y,$),T1($,Y),{chatId:Y,created:!0,joined:!0}}async function h6($){let Z=await f4($);if(!Z)return N4($),{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(Y$.delete(Z),Q$.get($)===Z)N4($);return{chatId:Z,disbanded:!0}}async function g6($,Z){if(!Z)throw Error("cannot disband a temporary session without an exact chat_id");let J=await NZ(Z);if(J.name!==$)throw Error(`refusing to delete chat ${Z}: expected name "${$}", got "${J.name??""}"`);if(!yZ(J.status))throw Error(`refusing to delete chat ${Z}: status=${J.status??"unknown"}`);let Q=await t.im.chat.delete({path:{chat_id:Z}});if(Q.code&&Q.code!==0)throw Error(`feishu chat.delete failed code=${Q.code} msg=${Q.msg}`);return Y$.delete(Z),{chatId:Z,disbanded:!0}}async function Hz($,Z){let J;do{let Y=await t.im.chatMembers.get({path:{chat_id:$},params:{member_id_type:"open_id",page_size:100,...J?{page_token:J}:{}}});if(Y.code&&Y.code!==0)throw Error(`feishu chatMembers.get failed code=${Y.code} msg=${Y.msg}`);for(let H of Y.data?.items??[])if(H.member_id===Z)return!1;J=Y.data?.page_token}while(J);let Q=await t.im.chatMembers.create({path:{chat_id:$},params:{member_id_type:"open_id"},data:{id_list:[Z]}});if(Q.code&&Q.code!==0)throw Error(`feishu chatMembers.create failed code=${Q.code} msg=${Q.msg}`);return!0}async function I6($){try{let Z=await Y0(),Q=await(await u0(`https://open.feishu.cn/open-apis/im/v1/chats/${encodeURIComponent($)}`,{headers:{Authorization:`Bearer ${Z}`}})).json();if(Q?.code!==0)return z(`feishu: fetchChatName ${$} code=${Q?.code} msg=${Q?.msg}`),null;let Y=Q.data?.name;if(typeof Y==="string"&&Y)return Y$.set($,Y),z(`feishu: fetchChatName ${$} → "${Y}" (point lookup)`),Y;return z(`feishu: fetchChatName ${$} — chat has no name (unnamed group?)`),null}catch(Z){return z(`feishu: fetchChatName ${$} failed: ${Z}`),null}}async function SZ($,Z,J,Q){let Y=D6(),H=null;for(let W=0;W<z2.length;W++){if(z2[W]>0)await new Promise((X)=>setTimeout(X,z2[W]));try{let X=await t.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:Z,msg_type:J,content:Q,uuid:Y}});if(X?.code&&X.code!==0)return z(`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,z(`feishu: send${$==="text"?"Text":"Card"} attempt ${W+1}/${z2.length} chat=${Z} failed: ${X}`)}}return z(`feishu: send${$==="text"?"Text":"Card"} chat=${Z} EXHAUSTED ${z2.length} retries: ${H}`),null}async function NZ($){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 yZ($){return $===null||$==="normal"}async function E($,Z){return SZ("text",$,"text",JSON.stringify({text:Z}))}async function i($,Z){return SZ("card",$,"interactive",JSON.stringify(B0(Z)))}async function H0($,Z){let J=await t.im.v1.message.patch({path:{message_id:$},data:{content:JSON.stringify(B0(Z))}});if(J?.code&&J.code!==0)throw Error(`feishu message.patch failed code=${J.code} msg=${J.msg}`)}async function b($,Z){try{let J=await Y0(),Y=await(await u0("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(Y?.code!==0)return z(`feishu: sendTextRaw rejected chat=${$} code=${Y?.code} msg=${Y?.msg}`),null;return Y.data?.message_id??null}catch(J){return z(`feishu: sendTextRaw chat=${$} failed: ${J}`),null}}async function T$($,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 z(`feishu: addReaction ${Z} on ${$} failed: ${J}`),null}}async function j$($,Z){if(!$||!Z)return;try{await t.im.messageReaction.delete({path:{message_id:$,reaction_id:Z}})}catch(J){z(`feishu: deleteReaction ${Z} on ${$} failed: ${J}`)}}async function l0($,Z){if(!$){z("feishu: urgentApp skip — missing messageId");return}if(Z.length===0){z(`feishu: urgentApp skip — empty openIds (msg=${$})`);return}let J=await Y0(),Q=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/urgent_app?user_id_type=open_id`;try{let H=await(await u0(Q,{method:"PATCH",headers:{Authorization:`Bearer ${J}`,"Content-Type":"application/json"},body:JSON.stringify({user_id_list:Z})})).json();if(H?.code!==0){z(`feishu: urgentApp ${$} code=${H?.code} msg=${H?.msg}`);return}let W=H.data?.invalid_user_id_list??[],X=Z.length-W.length;z(`feishu: urgentApp ${$} ok — delivered=${X}${W.length?` invalid=${W.length}`:""}`)}catch(Y){z(`feishu: urgentApp ${$} failed: ${Y}`)}}async function L2($,Z,J,Q){try{let Y=await Y0(),H=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/resources/${Z}?type=${J}`,W=await u0(H,{headers:{Authorization:`Bearer ${Y}`}});if(!W.ok){z(`feishu: download ${J} HTTP ${W.status}: ${(await W.text()).slice(0,200)}`);return}let X=Buffer.from(await W.arrayBuffer());R6(G8,{recursive:!0});let V=Q?Q.replace(/[^a-zA-Z0-9._-]/g,"_"):`${Z.replace(/[^a-zA-Z0-9_-]/g,"_")}.png`,A=S4(G8,`${Date.now()}-${V}`);return LZ(A,X),z(`feishu: downloaded ${J} ${A} (${X.length}B)`),A}catch(Y){z(`feishu: download ${J} failed: ${Y instanceof Error?Y.message:Y}`);return}}function Xz($){return Wz.has(sV($).toLowerCase())}async function bZ($){let Z=await Y0(),J=new Blob([Uint8Array.from(await DZ($))]),Q=new FormData;Q.append("image_type","message"),Q.append("image",J,c0($));let H=await(await u0("https://open.feishu.cn/open-apis/im/v1/images",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Q})).json();if(H?.code!==0)return z(`feishu: uploadImage ${$} code=${H.code} msg=${H.msg}`),null;return H.data?.image_key??null}async function c6($){try{let Z=PZ($);if(!Z.isFile())return z(`feishu: uploadImageKey not a file — ${$}`),null;if(Z.size>xZ)return z(`feishu: uploadImageKey oversize — ${$} (${(Z.size/1024/1024).toFixed(1)} MB)`),null}catch(Z){return z(`feishu: uploadImageKey stat failed — ${$}: ${Z}`),null}return bZ($)}async function Vz($){let Z=await Y0(),J=new Blob([Uint8Array.from(await DZ($))]),Q=new FormData;Q.append("file_type","stream"),Q.append("file_name",c0($)),Q.append("file",J,c0($));let H=await(await u0("https://open.feishu.cn/open-apis/im/v1/files",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Q})).json();if(H?.code!==0)return z(`feishu: uploadFile ${$} code=${H.code} msg=${H.msg}`),null;return H.data?.file_key??null}async function CZ($,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 z(`feishu: sendImage rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return z(`feishu: sendImage failed chat=${$}: ${J}`),null}}async function fZ($,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 z(`feishu: sendFile rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return z(`feishu: sendFile failed chat=${$}: ${J}`),null}}async function m6($,Z){try{let Q=PZ(Z);if(!Q.isFile())return await E($,`❌ 出站文件: 路径不是文件 — ${Z}`),!1;if(Q.size>xZ)return await E($,`❌ 出站文件: ${c0(Z)} 超过 30 MB (${(Q.size/1024/1024).toFixed(1)} MB)`),!1}catch(Q){return await E($,`❌ 出站文件: 无法读取 ${Z} (${Q})`),!1}let J=Xz(Z);try{if(J){let Q=await bZ(Z);if(!Q)return await E($,`❌ 出站图片上传失败: ${c0(Z)}`),!1;return await CZ($,Q)!=null}else{let Q=await Vz(Z);if(!Q)return await E($,`❌ 出站文件上传失败: ${c0(Z)}`),!1;return await fZ($,Q)!=null}}catch(Q){return z(`feishu: uploadAndSend ${Z} failed: ${Q}`),await E($,`❌ 出站文件异常: ${c0(Z)} — ${Q}`),!1}}function u6($){R6($,{recursive:!0}),z(`feishu: provisioned ${$}`);let Z=S4(zZ(),".codex","config.toml");try{R6(S4(zZ(),".codex"),{recursive:!0});let J="";try{J=m0(Z,"utf8")}catch{}let Q=`[projects.${JSON.stringify($)}]`;if(!J.includes(Q)){let Y=J.trimEnd();J=`${Y}${Y?`
|
|
51
|
+
`:"";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(Q){let Y=Q instanceof Error?Q:Error(String(Q));z(`claude-agent-process: sendUserText failed: ${Y.message}`),this.failTurnStart(Y)}}sendInterrupt(){this.query?.interrupt().catch(($)=>z(`claude-agent-process: interrupt failed: ${$}`))}sendPermissionResponse($,Z,J){let Q=this.pendingPermissions.get(String($));if(!Q){z(`claude-agent-process: permission response for unknown request ${$}`);return}if(this.pendingPermissions.delete(String($)),Q.cleanup?.(),Z==="allow")Q.resolve({behavior:"allow",updatedInput:J?.updatedInput??{}});else Q.resolve({behavior:"deny",message:J?.denyMessage??""})}sendHookResponse($,Z={}){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 z(`claude-agent-process: kill failed: ${J.message}`),J}if(Z){let J=Error(`claude Agent SDK close failed: ${Z.message}`,{cause:Z});throw z(`claude-agent-process: kill failed: ${J.message}`),J}}async listModels(){if(!this.started)this.sendInitialize();if(!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");return(await this.query.supportedModels()).map(dV)}async setModelSettings($,Z){let J=t8($);if(!d$(Z))throw Error(`invalid Claude effort: ${String(Z)}`);if(!this.started)this.sendInitialize();if(!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");if(J)await this.query.setModel(J);if(Z==="max")await this.query.applyFlagSettings({ultracode:!0,effortLevel:null});else await this.query.applyFlagSettings({effortLevel:Z,ultracode:null});this.opts.model=$,this.opts.effort=Z,this.lastModel=J?L0($):"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,Q=()=>{this.off("context_compacted",Y),this.off("assistant_text",H),this.off("exit",W),this.off("error",X)},Y=()=>{if(J)return;J=!0,Q(),$()},H=(V)=>{if(J)return;if((V?.text??"").includes("Not enough messages to compact"))J=!0,Q(),Z(new Q2)},W=()=>{if(J)return;J=!0,Q(),Z(Error("claude thread exited during /compact"))},X=(V)=>{if(J)return;J=!0,Q(),Z(V instanceof Error?V:Error(String(V)))};this.on("context_compacted",Y),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 Q=sV(Z);if(Q.length===0)return z("claude-agent-process: AskUserQuestion 无有效 questions — allow 原样"),Promise.resolve({behavior:"allow",updatedInput:Z});let Y={...Z,questions:Q},H=`claude_perm_${++this.requestCounter}`,W=J.toolUseID||H,X={request_id:H,tool_name:"AskUserQuestion",input:Y,tool_use_id:W},V=new Promise((A)=>{let G=(q)=>{J.signal.removeEventListener("abort",_),A(q)},_=()=>{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",Y,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){z(`claude-agent-process: read loop stopped after requested shutdown: ${J.message}`),this.finishExit(null,null);return}z(`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(),z(`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,Q=(H)=>{if(J)return;J=!0,clearTimeout(Y),Z(H)},Y=setTimeout(()=>Q(!this.alive),Math.max(0,$));this.exitPromise.then(()=>Q(!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:z(`claude-agent-process: unhandled message type=${Z.type??"unknown"} subtype=${Z.subtype??""}`)}}handleSystemMessage($){switch($.subtype){case"init":if(typeof $.model==="string"&&$.model)this.lastModel=L0($.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.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":z(`claude-agent-process: api retry attempt=${$.attempt}/${$.max_retries} status=${$.error_status} error=${$.error}`);return;case"permission_denied":z(`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){z("claude-agent-process: task_notification missing task_id");return}if($.status!=="completed"&&$.status!=="failed"&&$.status!=="stopped"){z(`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:z(`claude-agent-process: unhandled system subtype=${String($.subtype??"unknown")}`);return}}handleAssistantMessage($){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=L0(Z.model);let Q=Array.isArray(Z?.content)?Z.content:[];for(let Y of Q){if(!Y||typeof Y!=="object")continue;if(Y.type==="text"&&typeof Y.text==="string"&&Y.text.length>0){let H=iV(Y.text);if(H){if(this.pendingServerToolInputs.push(H),this.pendingServerToolInputs.length>20)this.pendingServerToolInputs.shift()}if(nV(Y.text))continue;let W=$.uuid??Z?.id;this.emit("assistant_text",{uuid:W,text:Y.text,parentToolUseId:J}),this.emit("assistant_block_stop",{index:W,parentToolUseId:J})}else if(Y.type==="tool_use"&&typeof Y.id==="string"&&typeof Y.name==="string")this.emitToolUseOnce(Y.id,Y.name,Y.input??{},J);else if(Y.type==="server_tool_use"&&typeof Y.id==="string"&&typeof Y.name==="string")this.emitToolUseOnce(Y.id,lV(Y.name),{tool:Y.name,input:this.serverToolInput(Y.name,Y.input??{})},J);else if(Y.type==="tool_result"&&typeof Y.tool_use_id==="string")this.emitToolResultOnce(Y.tool_use_id,pV(Y.content),Y.is_error===!0,J)}}emitToolUseOnce($,Z,J,Q){if(this.emittedToolUseIds.has($))return;this.emittedToolUseIds.add($),this.emit("tool_use",{id:$,name:Z,input:J,parentToolUseId:Q})}serverToolInput($,Z){let J=Z;if(J&&typeof J==="object"&&!Array.isArray(J)&&Object.keys(J).length>0)return J;let Q=this.pendingServerToolInputs.findIndex((Y)=>Y.name===$);if(Q>=0){let[Y]=this.pendingServerToolInputs.splice(Q,1);return Y.input}return J}emitToolResultOnce($,Z,J,Q){if(this.emittedToolResultIds.has($))return;this.emittedToolResultIds.add($),this.emit("tool_result",{tool_use_id:$,content:Z,is_error:J,parentToolUseId:Q})}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 Q of J){if(!Q||typeof Q!=="object")continue;if(Q.type!=="tool_result"||typeof Q.tool_use_id!=="string")continue;let Y=$.tool_use_result,H=YZ(Q.content),W=Y&&typeof Y==="object"?[typeof Y.stdout==="string"?Y.stdout:"",typeof Y.stderr==="string"?Y.stderr:""].filter(Boolean).join(`
|
|
52
|
+
`):"",X=H||W;this.emitToolResultOnce(Q.tool_use_id,X,Q.is_error===!0||Y?.interrupted===!0,$.parent_tool_use_id??null)}}handleResultMessage($){if(typeof $.session_id==="string"&&$.session_id)this.sessionId=$.session_id;this.turnActive=!1;let Z=IV($.usage),J=$.modelUsage??$.model_usage,Q=mV(J);if(!Z&&!Q.usage)z(`claude-agent-process: result usage missing rootKeys=${Z6($).join(",")||"-"} usageKeys=${Z6($.usage).join(",")||"-"} modelUsageKeys=${Z6(J).join(",")||"-"}`);if(this.lastUsage=Z,Q.usage)this.cumulativeUsageFromResults=L4(Q.usage),this.lastTotalUsage=L4(Q.usage);else if(Z)this.cumulativeUsageFromResults=uV(this.cumulativeUsageFromResults,Z),this.lastTotalUsage=L4(this.cumulativeUsageFromResults);else this.lastTotalUsage=this.cumulativeUsageFromResults?L4(this.cumulativeUsageFromResults):null;if(Q.contextWindow!=null){let X=s3(this.opts.model,this.tokenSourceId),V=W2.get(X)??0;if(Q.contextWindow>V)W2.set(X,Q.contextWindow),z(`claude-agent-process: SDK contextWindow ${Q.contextWindow} (global max for ${X}, prev ${V||"-"})`);else if(Q.contextWindow<(W2.get(X)??0))z(`claude-agent-process: SDK contextWindow ${Q.contextWindow} ignored (global max ${W2.get(X)} locked for ${X})`);if(this.tokenSourceId)for(let[A,G]of Object.entries(J??{})){let _=G?.contextWindow;if(typeof _==="number"&&_>0)$6(this.tokenSourceId,A,_)}}this.lastContextWindow=W2.get(s3(this.opts.model,this.tokenSourceId))??Q.contextWindow??null;let Y=H6(this.opts.workDir,this.sessionId??""),H=cV(Y);if(this.lastContextTokens=t3(H)??(D4(Y)?t3(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";if(this.tokenSourceId&&$.is_error===!0){let X=String($.result??$.error??$.api_error_message??"");if(/context.?window|prompt is too long|exceeds?.*(?:context|token)|too many (?:input )?tokens/i.test(X)){let G=(this.lastModel??(this.opts.model?.trim()||"claude:default")).replace(/^claude:/,"");n3(this.tokenSourceId,G),z(`claude-agent-process: context window exceeded on ${G} — downgraded to 200K (no [1m] next spawn)`)}}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,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 VZ={};G1(VZ,{waitForTokenSourceModelRefresh:()=>U4,tokenSourceFactories:()=>O1,setDefaultTokenSource:()=>V6,scrubAnthropicEnv:()=>g0,resetTokenSourceRegistry:()=>z6,registerTokenSourceFactory:()=>Q0,registerTokenSource:()=>X6,refreshAllTokenSourceModels:()=>z2,pendingTokenSourceModelRefresh:()=>E1,listTokenSourcesByAgent:()=>XZ,listTokenSources:()=>I0,listEnabledTokenSourcesByAgent:()=>M4,getTokenSource:()=>Z$});function g0($){let Z={...$};for(let J of Zz)delete Z[J];return Z}function Q0($){HZ.set($.kind,$)}function O1(){return[...HZ.values()]}function X6($,Z){if(V2.set($.id,$),Z?.default||F4===null)F4=$.id}function Z$($){return $?V2.get($):void 0}function I0(){return[...V2.values()]}function XZ($){return I0().filter((Z)=>Z.agent===$)}function M4($){return XZ($).filter((Z)=>Z.enabled)}function V6($){if(V2.has($))F4=$}function z6(){V2.clear(),F4=null,WZ++}function z2(){let $=WZ;if(U1?.generation===$)return U1.promise;let Z=Promise.allSettled(I0().map(async(J)=>{await J.refreshModels(),z(`token-source ${J.id}: ${J.models.length} models loaded`)})).then(()=>{}).finally(()=>{if(U1?.promise===Z)U1=null});return U1={generation:$,promise:Z},Z}function E1(){return U1?.promise??null}async function U4(){let $;while($=E1())await $}var Zz,HZ,V2,F4=null,WZ=0,U1=null;var _$=N(()=>{h();Zz=["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL"];HZ=new Map;V2=new Map});function O4($){let Z=$.tokenSourceId?Z$($.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;if(Z&&J&&!Z.models.some((H)=>H.model===J))throw Error(`model is not present in token source ${Z.id}: ${J}`);let Q=Z&&J?Z.resolveSpawnModel(J):J;if(J&&!Q)throw Error(`model did not resolve: ${$.tokenSourceId??"default"}/${J}`);let Y=Z?(H)=>Z.spawnEnv(H):void 0;if($.provider==="claude"){if(QZ(),!d$($.effort))throw Error(`invalid Claude effort: ${$.effort??"MISS"}`);return{process:new W6({workDir:$.workDir,model:Q,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}:{},...$.profile?{profile:$.profile}:{},...Z?{settingSources:Z.settingSources??["project","local"]}:{},...$.managedSkillPluginPath?{managedSkillPluginPath:$.managedSkillPluginPath}:{},tokenSourceId:Z?.id??null,transformEnv:Y,hostEnv:$.hostEnv}),sourceRevision:Z?.spawnRevision??null}}if($.effort!==void 0&&!S$($.effort))throw Error(`invalid Codex effort: ${$.effort}`);return{process:new L1({workDir:$.workDir,model:Q,effort:$.effort,launch:$.launch,...$.developerInstructions?{appendSystemPrompt:$.developerInstructions}:{},tokenSourceId:Z?.id??null,transformEnv:Y,hostEnv:$.hostEnv,serviceName:$.serviceName}),sourceRevision:Z?.spawnRevision??null}}var A6=N(()=>{v0();j4();D1();_$()});function E4($,Z){return`http://${$==="0.0.0.0"?"127.0.0.1":$==="::"||$==="::1"?"[::1]":$}:${Z}`}async function G6($){let Z=await q6("feishu chat.get",()=>s.im.chat.get({path:{chat_id:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)T4("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 _6($,Z){let J=await q6("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)T4("feishu tasklist.create",J);let Q=J.data?.tasklist,Y=Q?.guid;if(!Y)throw Error("feishu tasklist.create returned no guid");return{guid:Y,name:Q?.name||$,url:Q?.url??"",createdAt:Q?.created_at}}async function K6($){let Z=await q6("feishu tasklist.delete",()=>s.task.v2.tasklist.delete({path:{tasklist_guid:$}}));if(Z.code&&Z.code!==0)T4("feishu tasklist.delete",Z)}function zZ($,Z){let J=Z&&typeof Z==="object"?Z:{},Q=J.response?.data&&typeof J.response.data==="object"?J.response.data:J.data&&typeof J.data==="object"?J.data:J,Y=Q.code??J.code,H=Q.msg??Q.message??J.msg??J.message??"unknown error",W=Q.error?.permission_violations??Q.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=${Y??"unknown"} msg=${H}${X?` missing_scopes=${X}`:""}`}async function q6($,Z){try{return await Z()}catch(J){T4($,J)}}function T4($,Z){throw Error(zZ($,Z))}var AZ=N(()=>{t()});var J$={};G1(J$,{writeAliveMarker:()=>P2,urgentApp:()=>l0,uploadImageKey:()=>c6,uploadAndSend:()=>m6,updateCard:()=>H0,unbindSessionChat:()=>N4,tempProjectName:()=>o$,tempChatName:()=>S6,setPendingConversationLaunchChecked:()=>D0,sendTextRaw:()=>x,sendText:()=>T,sendImage:()=>wZ,sendFile:()=>vZ,sendCard:()=>n,sanitizeSessionName:()=>F2,resolveProjectDir:()=>b4,replaceTurnAnchors:()=>I$,registerTempSessionLease:()=>F6,refreshChatList:()=>L2,readAliveMarker:()=>f6,provisionProject:()=>u6,projectProfile:()=>k1,preferredChatForSession:()=>Y$,loadTempSessionLeases:()=>j6,loadSessionTurnsMap:()=>T6,loadSessionResumeMap:()=>O6,loadSessionModelMap:()=>N6,loadSessionChatMap:()=>U6,listNormalChatIdsByName:()=>C4,isOpenAIChatGPTAuthenticated:()=>j2,hasTempSessionLease:()=>M6,getTurnAnchors:()=>q2,getTenantToken:()=>Y0,getSessionResumeRef:()=>p0,getSessionModelSelection:()=>b6,getSessionBranchBase:()=>B2,getPendingConversationLaunch:()=>R2,formatFeishuApiError:()=>zZ,findNormalChatIdByName:()=>f4,fetchChatOwnerOpenId:()=>G6,fetchChatName:()=>I6,ensureChatForSession:()=>w6,downloadAttachment:()=>D2,disbandChatForSessionExact:()=>g6,disbandChatForSession:()=>h6,deleteTasklistByGuid:()=>K6,deleteReaction:()=>j$,createTempChatForSession:()=>v6,createTasklistWithOwner:()=>_6,client:()=>s,clearSessionResumeChecked:()=>S1,clearSessionConversationState:()=>C6,chatNameCache:()=>H$,chatIdForSession:()=>N1,bindSessionToChat:()=>T1,bindSessionResumeChecked:()=>K2,bindSessionModelChecked:()=>x6,bindSessionModel:()=>y6,appendTurnAnchorChecked:()=>k6,addReaction:()=>T$,PROJECTS_ROOT:()=>EZ});import*as PZ from"@larksuiteoapi/node-sdk";import{execSync as LZ}from"node:child_process";import{randomUUID as D6}from"node:crypto";import{existsSync as Jz,mkdirSync as R6,readFileSync as m0,statSync as DZ,writeFileSync as jZ}from"node:fs";import{readFile as FZ}from"node:fs/promises";import{homedir as GZ}from"node:os";import{basename as c0,extname as Qz,isAbsolute as MZ,join as S4}from"node:path";function P6(){let $={};for(let[Z,J]of E$)$[Z]=J;X$(A8,$)}function j6(){E$.clear();try{let $=JSON.parse(m0(A8,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("lease file must contain an object");for(let[Z,J]of Object.entries($)){let Q=J;if(typeof Z!=="string"||!Z||Q.chatId!==Z||typeof Q.sessionName!=="string"||!o$(Q.sessionName)||typeof Q.createdAt!=="number"||!Number.isFinite(Q.createdAt)){z(`feishu: rejected malformed temp-session lease chat=${Z}`);continue}E$.set(Z,{chatId:Z,sessionName:Q.sessionName,createdAt:Q.createdAt})}z(`feishu: loaded ${E$.size} temporary-session leases`)}catch($){if($?.code!=="ENOENT")z(`feishu: load temp-session leases failed: ${$?.message??$}`)}}function F6($,Z){if(!o$($))throw Error(`refusing to lease non-temporary session name "${$}"`);if(!Z)throw Error("cannot lease a temporary session without chat_id");for(let Y of E$.values())if(Y.sessionName===$&&Y.chatId!==Z)throw Error(`temporary session name "${$}" is already leased to ${Y.chatId}`);let J=E$.get(Z),Q={sessionName:$,chatId:Z,createdAt:Date.now()};E$.set(Z,Q);try{P6()}catch(Y){if(J)E$.set(Z,J);else E$.delete(Z);throw Y}}function M6($,Z){let J=E$.get(Z);return J?.sessionName===$&&J.chatId===Z}function k1($){return w.projects[$]}function b4($){return k1($)?.cwd?.trim()||S4(EZ,$)}function u0($,Z={}){return fetch($,{...Z,signal:Z.signal??AbortSignal.timeout(Yz)})}async function Y0(){if(k4&&Date.now()<_Z)return k4;return B6??=(async()=>{let $=await u0("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({app_id:UZ,app_secret:OZ})}),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 k4=Z.tenant_access_token,_Z=Date.now()+Math.max(0,(Z.expire??7200)-60)*1000,k4})().finally(()=>{B6=null}),B6}function U6(){try{let $=JSON.parse(m0(W8,"utf8"));for(let[Z,J]of Object.entries($))if(typeof J==="string")Y$.set(Z,J);z(`feishu: loaded ${Y$.size} session→chat bindings`)}catch($){if($?.code!=="ENOENT")z(`feishu: load session-chat-map failed: ${$?.message??$}`)}}function TZ(){try{L6()}catch($){z(`feishu: save session-chat-map failed: ${$}`)}}function L6(){let $={};for(let[Z,J]of Y$)$[Z]=J;X$(W8,$)}function T1($,Z){if(Y$.get($)===Z)return;let J=Y$.get($);Y$.set($,Z),TZ(),z(`feishu: bound session "${$}" → ${Z}${J?` (was ${J})`:""}`)}function N4($){let Z=Y$.get($);if(!Z)return;Y$.delete($),TZ(),z(`feishu: unbound session "${$}" from ${Z}`)}function G2($,Z){let J=Q$.get($)??{};J[Z.provider]=Z,Q$.set($,J)}function KZ($,Z){if(!$||typeof $!=="object"||Array.isArray($))return null;let J=$,Q=J.provider==="claude"||J.provider==="codex"?J.provider:Z??null;if(!Q||Z&&Q!==Z)return null;let Y=typeof J.sessionId==="string"?J.sessionId.trim():typeof J.session_id==="string"?J.session_id.trim():"";if(!Y)return null;if(J.cwd===void 0||J.cwd===null)return{provider:Q,sessionId:Y,cwd:null};if(typeof J.cwd!=="string"||!MZ(J.cwd))return null;return{provider:Q,sessionId:Y,cwd:J.cwd}}function qZ($){let Z=$.sessionId.trim();if(!Z)throw Error("cannot bind an empty conversation session id");if($.provider!=="codex"&&$.provider!=="claude")throw Error(`cannot bind an unknown conversation provider: ${String($.provider)}`);if(typeof $.cwd!=="string"||!MZ($.cwd))throw Error(`cannot bind a conversation without an absolute cwd: ${String($.cwd)}`);return{provider:$.provider,sessionId:Z,cwd:$.cwd}}function Hz($,Z,J){if(typeof $!=="string")return qZ($);if(!Z)throw Error("cannot bind a conversation without a provider");return qZ({provider:Z,sessionId:$,cwd:J??null})}function O6(){try{let $=JSON.parse(m0(X8,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("resume map must contain an object");Q$.clear();for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){G2(Z,{provider:"codex",sessionId:J.trim(),cwd:null});continue}if(!J||typeof J!=="object"||Array.isArray(J))continue;let Q=J,Y=KZ(Q);if(Y){G2(Z,Y);continue}for(let H of["codex","claude"]){let W=Q[H];if(typeof W==="string"&&W.trim()){G2(Z,{provider:H,sessionId:W.trim(),cwd:null});continue}let X=KZ(W,H);if(X)G2(Z,X)}}z(`feishu: loaded ${Q$.size} session→resume bindings`)}catch($){if($?.code!=="ENOENT")z(`feishu: load session-resume-map failed: ${$?.message??$}`)}}function y4(){let $={};for(let[Z,J]of Q$){let Q={};if(J.codex)Q.codex={...J.codex};if(J.claude)Q.claude={...J.claude};$[Z]=Q}X$(X8,$)}function K2($,Z,J,Q){let Y=Hz(Z,J,Q),H=Q$.get($),W=H?{...H}:void 0,X=H?.[Y.provider];if(X?.sessionId===Y.sessionId&&X.cwd===Y.cwd)return;G2($,Y);try{y4()}catch(V){if(W)Q$.set($,W);else Q$.delete($);throw V}}function p0($,Z="codex"){let J=Q$.get($)?.[Z];return J?{...J}:null}function S1($,Z){let J=Q$.get($);if(!J||Z&&J[Z]===void 0)return;let Q={...J};if(!Z)Q$.delete($);else{let Y={...J};if(delete Y[Z],!Y.codex&&!Y.claude)Q$.delete($);else Q$.set($,Y)}try{y4()}catch(Y){throw Q$.set($,Q),Y}}function kZ($){if(!$||typeof $!=="object")return null;let Z=$;if(Z.provider!=="claude"&&Z.provider!=="codex")return null;let J=typeof Z.sessionId==="string"?Z.sessionId.trim():"";if(!J)return null;let Q;if(Z.cwd===void 0||Z.cwd===null)Q=null;else if(typeof Z.cwd==="string"&&Z.cwd.trim())Q=Z.cwd;else return null;return{provider:Z.provider,sessionId:J,cwd:Q}}function SZ($){if(!$||typeof $!=="object")return null;let Z=$,J=Z.source;if(!J||typeof J!=="object")return null;let Q=kZ(J),Y=typeof Z.id==="string"?Z.id.trim():"";if(!Y||!Q)return null;if(Z.provider==="claude"&&Z.kind==="assistant-message"&&Q.provider==="claude")return{provider:"claude",kind:"assistant-message",id:Y,source:{...Q,provider:"claude"}};if(Z.provider==="codex"&&Z.kind==="turn"&&Q.provider==="codex")return{provider:"codex",kind:"turn",id:Y,source:{...Q,provider:"codex"}};return null}function NZ($){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=kZ(Z.source);if(!J)return null;let Q=Z.kind==="resume"?{kind:"resume",source:J}:(()=>{if(!Object.prototype.hasOwnProperty.call(Z,"through"))return{kind:"fork",source:J};let Y=SZ(Z.through);return Y?{kind:"fork",source:J,through:Y}:null})();if(!Q)return null;try{G$(Q,J.provider)}catch{return null}return Q}function Wz($){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 Xz($,Z){if(!$||typeof $!=="object")return null;let J=$;if(typeof J.ts!=="number"||!Number.isFinite(J.ts))return null;let Q=Object.prototype.hasOwnProperty.call(J,"checkpoint"),Y=SZ(J.checkpoint);if(Q&&!Y)return null;if(!Y){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;Y={provider:"claude",kind:"assistant-message",id:H,source:{provider:"claude",sessionId:W,cwd:null}}}return{checkpoint:Y,preview:String(J.preview??""),ts:J.ts,writes:Wz(J.writes)}}function Vz($){if(!$||typeof $!=="object")return null;let Z=$,J=NZ(Z.launch);if(J?.kind!=="fork"||J.source.provider!=="claude"||J.source.cwd===null)return null;let Q=Z.previousSessionId,Y=Q===null?null:typeof Q==="string"&&Q.trim()?Q.trim():void 0;if(Y===void 0)return null;return{launch:{...J,source:{...J.source,provider:"claude"}},previousSessionId:Y}}function E6($){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 T6(){try{let $=JSON.parse(m0(V8,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("turns map must contain an object");i.clear();let Z=0,J=0;for(let[Q,Y]of Object.entries($)){let H,W,X=null;if(Array.isArray(Y))H=Y,W=null;else if(Y&&typeof Y==="object"&&!Array.isArray(Y)){let _=Y;if(!Array.isArray(_.anchors)||!Object.prototype.hasOwnProperty.call(_,"base")){J++;continue}if(H=_.anchors,_.base===null)W=null;else{let q=NZ(_.base);if(!q){J++;continue}W=q}if(Object.prototype.hasOwnProperty.call(_,"pendingLaunch")){let q=Vz(_.pendingLaunch);if(!q){J++;continue}X=q}}else{J++;continue}let V=Q$.get(Q),A=V?.claude!==void 0&&V.codex===void 0?"claude":null,G=[];for(let _ of H){let q=Xz(_,A);if(q)G.push(q);else J++}if(G.length||W!==null||X)i.set(Q,{base:W,anchors:G,...X?{pendingLaunch:X}:{}}),Z+=G.length}if(z(`feishu: loaded ${Z} turn anchors across ${i.size} sessions`),J>0)z(`feishu: rejected ${J} malformed turn anchors while loading`)}catch($){if($?.code!=="ENOENT")z(`feishu: load session-turns-map failed: ${$?.message??$}`)}}function _2(){let $={};for(let[Z,J]of i)$[Z]=J;X$(V8,$)}function k6($,Z){let J=i.get($),Q=[...J?.anchors??[],Z],Y=J?.base??null;if(Q.length>BZ){let H=Q.splice(0,Q.length-BZ),W=H[H.length-1].checkpoint;Y={kind:"fork",source:W.source,through:W}}i.set($,{base:Y,anchors:Q,...J?.pendingLaunch?{pendingLaunch:J.pendingLaunch}:{}});try{_2()}catch(H){if(J)i.set($,J);else i.delete($);throw H}}function q2($){return i.get($)?.anchors??[]}function B2($){return i.get($)?.base??null}function R2($){let Z=i.get($)?.pendingLaunch;return Z?E6(Z):null}function D0($,Z){if(Z){if(Z.launch.source.cwd===null)throw Error("pending conversation launch source cwd is missing");G$(Z.launch,"claude",Z.launch.source.cwd)}let J=i.get($),Q=J?.base??null,Y=J?.anchors.slice()??[];if(!Z&&Y.length===0&&Q===null)i.delete($);else i.set($,{base:Q,anchors:Y,...Z?{pendingLaunch:E6(Z)}:{}});try{_2()}catch(H){if(J)i.set($,J);else i.delete($);throw H}}function I$($,Z,J,Q){let Y=i.get($),H=Q===void 0?Y?.pendingLaunch:Q??void 0,W=H?E6(H):void 0;if(Z.length===0&&J===null&&!W)i.delete($);else i.set($,{base:J,anchors:Z.slice(),...W?{pendingLaunch:W}:{}});try{_2()}catch(X){if(Y)i.set($,Y);else i.delete($);throw X}}function o$($){return RZ.test($)?$.replace(RZ,""):null}function S6($,Z=[]){let J=new Date,Q=(X)=>String(X).padStart(2,"0"),Y=`${Q(J.getMonth()+1)}${Q(J.getDate())}-${Q(J.getHours())}${Q(J.getMinutes())}`,H=new Set([...H$.values(),...i.keys(),...Z]),W=`${$}*${Y}`;for(let X=2;H.has(W);X++)W=`${$}*${Y}-${X}`;return W}function N6(){try{let $=JSON.parse(m0(z8,"utf8"));for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){D$.set(Z,{provider:F1(J),model:J,effort:null});continue}if(!J||typeof J!=="object")continue;let{model:Q,provider:Y}=J,H=Y==="claude"||Y==="codex"?Y:typeof Q==="string"&&Q.trim()?F1(Q):"claude",W=typeof Q==="string"&&Q.trim()?Q:null;if(H==="claude"&&!W)continue;let{effort:X,tokenSourceId:V}=J,A=typeof V==="string"&&V.trim()?V.trim():null,G=H==="claude"?d$(X)?X:null:S$(X)?X:null;D$.set(Z,{provider:H,model:W,effort:G,...A?{tokenSourceId:A}:{}})}z(`feishu: loaded ${D$.size} session→model bindings`)}catch($){if($?.code!=="ENOENT")z(`feishu: load session-model-map failed: ${$?.message??$}`)}}function zz(){try{x4()}catch($){z(`feishu: save session-model-map failed: ${$}`)}}function x4(){let $={};for(let[Z,J]of D$)$[Z]=J;X$(z8,$)}function y6($,Z,J,Q,Y){let H=D$.get($);if(H?.provider===Z&&H.model===J&&H.effort===Q&&(H.tokenSourceId??null)===(Y??null))return;D$.set($,{provider:Z,model:J,effort:Q,...Y?{tokenSourceId:Y}:{}}),zz()}function x6($,Z,J,Q,Y){let H=D$.get($),W={provider:Z,model:J,effort:Q,...Y?{tokenSourceId:Y}:{}};if(H?.provider===Z&&H.model===J&&H.effort===Q&&(H.tokenSourceId??null)===(Y??null))return;D$.set($,W);try{x4()}catch(X){if(H)D$.set($,H);else D$.delete($);throw X}}function b6($){let Z=D$.get($);if(Z)return Z;let J=o$($);return J?D$.get(J)??null:null}function C6($){let Z=Y$.get($),J=Q$.get($),Q=D$.get($),Y=i.get($),H=[...E$.entries()].filter(([,W])=>W.sessionName===$);Y$.delete($),Q$.delete($),D$.delete($),i.delete($);for(let[W]of H)E$.delete(W);try{L6(),y4(),x4(),_2(),P6()}catch(W){if(Z)Y$.set($,Z);if(J)Q$.set($,J);if(Q)D$.set($,Q);if(Y)i.set($,Y);for(let[V,A]of H)E$.set(V,A);let X=[W];for(let V of[L6,y4,x4,_2,P6])try{V()}catch(A){X.push(A)}throw X.length===1?X[0]:AggregateError(X,`failed to clear and restore conversation state for ${$}`)}}function P2($){try{X$(r2,$)}catch(Z){z(`feishu: write alive marker failed: ${Z}`)}}function f6(){if(!Jz(r2))return[];try{let $=m0(r2,"utf8"),Z=JSON.parse($);return Array.isArray(Z)?Z.filter((J)=>typeof J==="string"):[]}catch($){return z(`feishu: read alive marker failed: ${$}`),[]}}function N1($){let Z=Y$.get($);if(Z){let Q=H$.get(Z);if(Q&&Q!==$)z(`feishu: chatIdForSession("${$}"): persisted binding ${Z} has cached name "${Q}", using persisted binding`);return Z}let J=[];for(let[Q,Y]of H$)if(Y===$)J.push(Q);if(J.length===1)return J[0];if(J.length>1)z(`feishu: chatIdForSession("${$}"): ${J.length} candidates with no binding — [${J.join(", ")}]`);return null}async function L2(){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)H$.set(J.chat_id,J.name);$=Z.data?.page_token}while($);z(`feishu: refreshed chat list — ${H$.size} groups`)}catch($){z(`feishu: refresh chat list failed: ${$}`)}}async function C4(){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 Q of J.data?.items??[]){if(!Q.chat_id||!Q.name)continue;if(Q.chat_status&&Q.chat_status!=="normal")continue;H$.set(Q.chat_id,Q.name);let Y=$.get(Q.name)??[];Y.push(Q.chat_id),$.set(Q.name,Y)}Z=J.data?.page_token}while(Z);return $}async function f4($){let Z=Y$.get($);if(Z&&H$.get(Z)===$){let H=await xZ(Z);if(H.name===$&&bZ(H.status))return Z;H$.delete(Z),N4($)}let Q=(await C4()).get($)??[];if(Q.length===0)return null;let Y=Y$.get($);if(Y&&Q.includes(Y))return Y;if(Q.length===1)return Q[0];throw Error(`multiple Feishu groups named "${$}": ${Q.join(", ")}`)}async function w6($,Z){if(!Z)throw Error("missing sender open_id; cannot add user to worktree group");let J=await f4($);if(J){let H=await Az(J,Z);return T1($,J),{chatId:J,created:!1,joined:H}}let Q=await s.im.chat.create({params:{user_id_type:"open_id",uuid:D6()},data:{name:$,user_id_list:[Z],group_message_type:"chat"}});if(Q.code&&Q.code!==0)throw Error(`feishu chat.create failed code=${Q.code} msg=${Q.msg}`);let Y=Q.data?.chat_id;if(!Y)throw Error("feishu chat.create returned no chat_id");return H$.set(Y,$),T1($,Y),{chatId:Y,created:!0,joined:!0}}async function v6($,Z){if(!Z)throw Error("missing sender open_id; cannot create temporary group");if(await f4($))throw Error(`temporary group name already exists: ${$}`);let Q=await s.im.chat.create({params:{user_id_type:"open_id",uuid:D6()},data:{name:$,user_id_list:[Z],group_message_type:"chat"}});if(Q.code&&Q.code!==0)throw Error(`feishu chat.create failed code=${Q.code} msg=${Q.msg}`);let Y=Q.data?.chat_id;if(!Y)throw Error("feishu chat.create returned no chat_id");return H$.set(Y,$),T1($,Y),{chatId:Y,created:!0,joined:!0}}async function h6($){let Z=await f4($);if(!Z)return N4($),{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(H$.delete(Z),Y$.get($)===Z)N4($);return{chatId:Z,disbanded:!0}}async function g6($,Z){if(!Z)throw Error("cannot disband a temporary session without an exact chat_id");let J=await xZ(Z);if(J.name!==$)throw Error(`refusing to delete chat ${Z}: expected name "${$}", got "${J.name??""}"`);if(!bZ(J.status))throw Error(`refusing to delete chat ${Z}: status=${J.status??"unknown"}`);let Q=await s.im.chat.delete({path:{chat_id:Z}});if(Q.code&&Q.code!==0)throw Error(`feishu chat.delete failed code=${Q.code} msg=${Q.msg}`);return H$.delete(Z),{chatId:Z,disbanded:!0}}async function Az($,Z){let J;do{let Y=await s.im.chatMembers.get({path:{chat_id:$},params:{member_id_type:"open_id",page_size:100,...J?{page_token:J}:{}}});if(Y.code&&Y.code!==0)throw Error(`feishu chatMembers.get failed code=${Y.code} msg=${Y.msg}`);for(let H of Y.data?.items??[])if(H.member_id===Z)return!1;J=Y.data?.page_token}while(J);let Q=await s.im.chatMembers.create({path:{chat_id:$},params:{member_id_type:"open_id"},data:{id_list:[Z]}});if(Q.code&&Q.code!==0)throw Error(`feishu chatMembers.create failed code=${Q.code} msg=${Q.msg}`);return!0}async function I6($){try{let Z=await Y0(),Q=await(await u0(`https://open.feishu.cn/open-apis/im/v1/chats/${encodeURIComponent($)}`,{headers:{Authorization:`Bearer ${Z}`}})).json();if(Q?.code!==0)return z(`feishu: fetchChatName ${$} code=${Q?.code} msg=${Q?.msg}`),null;let Y=Q.data?.name;if(typeof Y==="string"&&Y)return H$.set($,Y),z(`feishu: fetchChatName ${$} → "${Y}" (point lookup)`),Y;return z(`feishu: fetchChatName ${$} — chat has no name (unnamed group?)`),null}catch(Z){return z(`feishu: fetchChatName ${$} failed: ${Z}`),null}}async function yZ($,Z,J,Q){let Y=D6(),H=null;for(let W=0;W<A2.length;W++){if(A2[W]>0)await new Promise((X)=>setTimeout(X,A2[W]));try{let X=await s.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:Z,msg_type:J,content:Q,uuid:Y}});if(X?.code&&X.code!==0)return z(`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,z(`feishu: send${$==="text"?"Text":"Card"} attempt ${W+1}/${A2.length} chat=${Z} failed: ${X}`)}}return z(`feishu: send${$==="text"?"Text":"Card"} chat=${Z} EXHAUSTED ${A2.length} retries: ${H}`),null}async function xZ($){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 bZ($){return $===null||$==="normal"}async function T($,Z){return yZ("text",$,"text",JSON.stringify({text:Z}))}async function n($,Z){return yZ("card",$,"interactive",JSON.stringify(B0(Z)))}async function H0($,Z){let J=await s.im.v1.message.patch({path:{message_id:$},data:{content:JSON.stringify(B0(Z))}});if(J?.code&&J.code!==0)throw Error(`feishu message.patch failed code=${J.code} msg=${J.msg}`)}async function x($,Z){try{let J=await Y0(),Y=await(await u0("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(Y?.code!==0)return z(`feishu: sendTextRaw rejected chat=${$} code=${Y?.code} msg=${Y?.msg}`),null;return Y.data?.message_id??null}catch(J){return z(`feishu: sendTextRaw chat=${$} failed: ${J}`),null}}async function T$($,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 z(`feishu: addReaction ${Z} on ${$} failed: ${J}`),null}}async function j$($,Z){if(!$||!Z)return;try{await s.im.messageReaction.delete({path:{message_id:$,reaction_id:Z}})}catch(J){z(`feishu: deleteReaction ${Z} on ${$} failed: ${J}`)}}async function l0($,Z){if(!$){z("feishu: urgentApp skip — missing messageId");return}if(Z.length===0){z(`feishu: urgentApp skip — empty openIds (msg=${$})`);return}let J=await Y0(),Q=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/urgent_app?user_id_type=open_id`;try{let H=await(await u0(Q,{method:"PATCH",headers:{Authorization:`Bearer ${J}`,"Content-Type":"application/json"},body:JSON.stringify({user_id_list:Z})})).json();if(H?.code!==0){z(`feishu: urgentApp ${$} code=${H?.code} msg=${H?.msg}`);return}let W=H.data?.invalid_user_id_list??[],X=Z.length-W.length;z(`feishu: urgentApp ${$} ok — delivered=${X}${W.length?` invalid=${W.length}`:""}`)}catch(Y){z(`feishu: urgentApp ${$} failed: ${Y}`)}}async function D2($,Z,J,Q){try{let Y=await Y0(),H=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/resources/${Z}?type=${J}`,W=await u0(H,{headers:{Authorization:`Bearer ${Y}`}});if(!W.ok){z(`feishu: download ${J} HTTP ${W.status}: ${(await W.text()).slice(0,200)}`);return}let X=Buffer.from(await W.arrayBuffer());R6(G8,{recursive:!0});let V=Q?Q.replace(/[^a-zA-Z0-9._-]/g,"_"):`${Z.replace(/[^a-zA-Z0-9_-]/g,"_")}.png`,A=S4(G8,`${Date.now()}-${V}`);return jZ(A,X),z(`feishu: downloaded ${J} ${A} (${X.length}B)`),A}catch(Y){z(`feishu: download ${J} failed: ${Y instanceof Error?Y.message:Y}`);return}}function _z($){return Gz.has(Qz($).toLowerCase())}async function fZ($){let Z=await Y0(),J=new Blob([Uint8Array.from(await FZ($))]),Q=new FormData;Q.append("image_type","message"),Q.append("image",J,c0($));let H=await(await u0("https://open.feishu.cn/open-apis/im/v1/images",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Q})).json();if(H?.code!==0)return z(`feishu: uploadImage ${$} code=${H.code} msg=${H.msg}`),null;return H.data?.image_key??null}async function c6($){try{let Z=DZ($);if(!Z.isFile())return z(`feishu: uploadImageKey not a file — ${$}`),null;if(Z.size>CZ)return z(`feishu: uploadImageKey oversize — ${$} (${(Z.size/1024/1024).toFixed(1)} MB)`),null}catch(Z){return z(`feishu: uploadImageKey stat failed — ${$}: ${Z}`),null}return fZ($)}async function Kz($){let Z=await Y0(),J=new Blob([Uint8Array.from(await FZ($))]),Q=new FormData;Q.append("file_type","stream"),Q.append("file_name",c0($)),Q.append("file",J,c0($));let H=await(await u0("https://open.feishu.cn/open-apis/im/v1/files",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Q})).json();if(H?.code!==0)return z(`feishu: uploadFile ${$} code=${H.code} msg=${H.msg}`),null;return H.data?.file_key??null}async function wZ($,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 z(`feishu: sendImage rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return z(`feishu: sendImage failed chat=${$}: ${J}`),null}}async function vZ($,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 z(`feishu: sendFile rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return z(`feishu: sendFile failed chat=${$}: ${J}`),null}}async function m6($,Z){try{let Q=DZ(Z);if(!Q.isFile())return await T($,`❌ 出站文件: 路径不是文件 — ${Z}`),!1;if(Q.size>CZ)return await T($,`❌ 出站文件: ${c0(Z)} 超过 30 MB (${(Q.size/1024/1024).toFixed(1)} MB)`),!1}catch(Q){return await T($,`❌ 出站文件: 无法读取 ${Z} (${Q})`),!1}let J=_z(Z);try{if(J){let Q=await fZ(Z);if(!Q)return await T($,`❌ 出站图片上传失败: ${c0(Z)}`),!1;return await wZ($,Q)!=null}else{let Q=await Kz(Z);if(!Q)return await T($,`❌ 出站文件上传失败: ${c0(Z)}`),!1;return await vZ($,Q)!=null}}catch(Q){return z(`feishu: uploadAndSend ${Z} failed: ${Q}`),await T($,`❌ 出站文件异常: ${c0(Z)} — ${Q}`),!1}}function u6($){R6($,{recursive:!0}),z(`feishu: provisioned ${$}`);let Z=S4(GZ(),".codex","config.toml");try{R6(S4(GZ(),".codex"),{recursive:!0});let J="";try{J=m0(Z,"utf8")}catch{}let Q=`[projects.${JSON.stringify($)}]`;if(!J.includes(Q)){let Y=J.trimEnd();J=`${Y}${Y?`
|
|
53
53
|
|
|
54
54
|
`:""}${Q}
|
|
55
55
|
trust_level = "trusted"
|
|
56
|
-
`,LZ(Z,J)}}catch(J){z(`feishu: codex trust write failed for ${$}: ${J}`)}try{RZ("git init -q",{cwd:$,stdio:"ignore"})}catch{}}function D2(){try{let $=RZ(`"${e1()}" login status 2>&1`,{timeout:1e4}).toString();return/Logged in using ChatGPT/i.test($)}catch{return!1}}function j2($){return $.replace(/[^\w一-鿿\-\[\]\*]/g,"_").slice(0,64)}var FZ,MZ,UZ,E$,t,eV=15000,k4="",AZ=0,B6=null,Y$,Q$,J$,l,KZ=200,qZ,D$,z2,xZ=31457280,Wz;var r=N(()=>{U$();D1();v0();L$();h();h$();N$();P1();VZ();FZ=w.feishu.app_id,MZ=w.feishu.app_secret,UZ=w.runtime.projects_root,E$=new Map;t=new BZ.Client({appId:FZ,appSecret:MZ,disableTokenCache:!1});Y$=new Map,Q$=new Map;J$=new Map;l=new Map;qZ=/\*[0-9]{4}-[0-9]{4}(-[0-9]+)?$/;D$=new Map;z2=[0,1000,4000];Wz=new Set([".png",".jpg",".jpeg",".gif",".bmp",".webp"])});function p6($,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 vZ($,Z){if($!==300315)return!1;return/(?:duplicate\s+(?:element\s*)?id|code\s*1001\s*:\s*duplicate id)/i.test(Z?.message??"")}function W0($){let Z=c$.get($);if(!Z)Z={sequence:0,queue:Promise.resolve(),elementCount:0,deadElements:new Set},c$.set($,Z);return Z}function wZ($){K$.delete($),K$.add($);while(K$.size>Kz){let Z=K$.values().next().value;if(typeof Z!=="string")break;K$.delete(Z)}}function m$($,Z,J){K$.delete($),c$.delete($);let Q=W0($);Q.elementCount=Z,Q.onFailure=J,Q.writeDead=!1,Q.closing=!1}function l6($){return c$.get($)?.elementCount??0}function y1($,Z){return c$.get($)?.deadElements.has(Z)??!1}function hZ($,Z){c$.get($)?.deadElements.delete(Z)}function w4($){if(K$.has($))return;let Z=W0($);if(Z.closing)return;Z.writeDead=!0,V$($)}function v4($){let Z=W0($);return Z.sequence+=1,Z.sequence}function gZ($,Z){$.deadElements.add(Z)}async function F2($,Z,J){let Q=await Y0(),Y=await fetch(`${zz}${Z}`,{method:$,headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},...J?{body:JSON.stringify(J)}:{},signal:AbortSignal.timeout(Az)}),H=await Y.json();if(!Y.ok||H?.code!==0){let W=typeof H?.code==="number"?H.code:Y.status,X=Y.headers.get("x-tt-logid")??Y.headers.get("x-request-id")??Y.headers.get("request-id")??void 0,V=Error(`cardkit ${$} ${Z}: HTTP ${Y.status} code=${String(H?.code??"MISS")} msg=${H?.msg??"MISS"}${X?` log_id=${X}`:""}`);throw V.code=W,V.httpStatus=Y.status,V.logId=X,V}return H?.data}function qz($){return new Promise((Z)=>setTimeout(Z,$))}function Bz($){if(typeof $!=="object"||$===null)return!1;let Z=$.code;return Z===300309||Z===200850}async function Rz($){let Z=v4($);await F2("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify({config:{streaming_mode:!0}}),sequence:Z})}async function i6($,Z,J,Q,Y=!1,H={}){let W=(X)=>{let V=typeof X==="object"&&X!==null?X:null,A={cardId:$,operation:Z,...H,code:V?.code,httpStatus:V?.httpStatus,logId:V?.logId,message:X instanceof Error?X.message:String(X)};try{if(!Y)W0($).onFailure?.(A.code,A)}catch(G){z(`cardkit failure callback ${$}: ${G}`)}try{Q?.(A)}catch(G){z(`cardkit per-call failure callback ${$}: ${G}`)}};try{await J();return}catch(X){if(!Bz(X)){z(`cardkit ${Z} ${$}: ${X}`),W(X);return}z(`cardkit ${Z} ${$}: streaming closed (code=${X.code}) — reopening`)}try{await Rz($)}catch(X){z(`cardkit STREAMING_REOPEN_FAILED ${$}: ${X}`),W(X);return}try{await J()}catch(X){z(`cardkit ${Z} ${$} retry-after-reopen: ${X}`),W(X)}}function Pz($){return typeof $==="object"&&$!==null&&$.code===200740}async function a$($,Z={}){let J=Z.retryDelaysMs?.length?Z.retryDelaysMs:Gz,Q=null;for(let Y=0;Y<J.length;Y++){let H=J[Y]??0;if(H>0)await qz(H);try{let W=await F2("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(Q=W,!Pz(W)||Y===J.length-1)throw W;let X=J[Y+1]??0;z(`cardkit id_convert ${$}: empty result, retry ${Y+2}/${J.length} in ${X}ms`)}}throw Q}async function u$($){let Z=c$.get($);if(!Z)return;await Z.queue}function z$($,Z,J={},Q){if(K$.has($))return Promise.resolve();let Y=W0($);if(Y.closing||Y.writeDead)return Promise.resolve();let H=B0(Z),W=H.element_id;return Y.queue=Y.queue.then(()=>i6($,"addElement",async()=>{if(Y.writeDead)return;let X=v4($);if(await F2("POST",`/cards/${$}/elements`,{type:J.type??"append",...J.targetElementId?{target_element_id:J.targetElementId}:{},elements:JSON.stringify([H]),sequence:X}),Y.elementCount+=1,W)Y.deadElements.delete(W)},(X)=>{if(W)gZ(Y,W);Q?.(X.code,X)},!1,{elementId:W,targetElementId:J.targetElementId})),Y.queue}function o($,Z,J,Q,Y=!0){if(K$.has($))return Promise.resolve();let H=W0($);if(H.closing||H.writeDead||H.deadElements.has(Z))return Promise.resolve();let W=B0(J);return H.queue=H.queue.then(()=>i6($,`replaceElement ${Z}`,async()=>{if(H.writeDead||H.deadElements.has(Z))return;let X=v4($);await F2("PUT",`/cards/${$}/elements/${Z}`,{element:JSON.stringify(W),sequence:X})},(X)=>{if(Y&&p6(X.code,X))gZ(H,Z);Q?.(X.code,X)},!Y,{elementId:Z})),H.queue}async function F$($,Z,J,Q={}){if(K$.has($))return!1;let Y=W0($);if(Y.closing||Y.writeDead||Y.deadElements.has(Z))return!1;let H=!1;return await o($,Z,J,()=>{H=!0},Q.notifyCardFailure!==!1),!H&&!Y.writeDead&&!Y.deadElements.has(Z)}async function j0($,Z,J={}){return(await h4($,Z,J)).landed}async function h4($,Z,J={}){if(K$.has($))return{landed:!1};let Q=W0($);if(Q.closing||Q.writeDead)return{landed:!1};let Y=Z.element_id,H;return await z$($,Z,J,(W,X)=>{H=X}),{landed:!H&&!Q.writeDead&&!(Y&&Q.deadElements.has(Y)),...H?{failure:H}:{}}}function X0($,Z){if(K$.has($)||c$.get($)?.closing||c$.get($)?.writeDead)return;let J=(Z??"").replace(/\s+/g," ").trim();if(!J)return;let Q=i0.get($);if(!Q)Q={latest:J,lastSent:"",timer:null},i0.set($,Q);else Q.latest=J;if(Q.timer)return;Q.timer=setTimeout(()=>{let Y=i0.get($);if(!Y)return;if(K$.has($)){i0.delete($);return}if(Y.timer=null,Y.latest===Y.lastSent)return;let H=Y.latest;q$($,{config:{summary:{content:H}}}).then((W)=>{let X=i0.get($);if(W&&X===Y)X.lastSent=H})},_z)}function V$($){let Z=i0.get($);if(!Z)return;if(Z.timer)clearTimeout(Z.timer),Z.timer=null;i0.delete($)}function g4($,Z){return q$($,Z).then(()=>{})}async function q$($,Z){if(K$.has($))return!1;let J=W0($);if(J.closing||J.writeDead)return!1;let Q=!1,Y=!1;return J.queue=J.queue.then(()=>i6($,"patchSettings",async()=>{if(K$.has($)||J.writeDead)return;let H=v4($);await F2("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify(Z),sequence:H}),Q=!0},()=>{Y=!0},!0)),await J.queue,Q&&!Y&&!K$.has($)&&!J.writeDead}async function x$($){let Z=c$.get($);if(!Z){wZ($),V$($);return}if(Z.closing){await Z.queue;return}Z.closing=!0,V$($),await Z.queue,wZ($),c$.delete($)}var zz="https://open.feishu.cn/open-apis/cardkit/v1",Az=15000,Gz,c$,i0,_z=1500,K$,Kz=5000;var n0=N(()=>{r();h();N$();Gz=[0,250,750,1500];c$=new Map,i0=new Map;K$=new Set});function I4($){if(!$)return null;return typeof $.total_tokens==="number"&&Number.isFinite($.total_tokens)?$.total_tokens:null}function c4($){return typeof $==="number"&&Number.isFinite($)&&$>0?$:null}function Lz($,Z,J=12000){if(Z==null||Z<=0)return null;if(Z<=J)return 0;let Q=Z-J,Y=Math.max(0,$-J),H=Math.max(0,Q-Y);return Math.round(Math.min(100,Math.max(0,H/Q*100)))}function cZ($,Z,J){let Q=Lz($,Z,J??12000);if(Q==null)return null;return{used:Math.min(100,Math.max(0,100-Q)),remaining:Q}}function IZ($){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 m4($,Z){let J=IZ($);return Z!=null&&Z>0?`${J}/${IZ(Z)}`:`${J}/--`}function mZ($,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 p4($){return JSON.stringify({objective:$.objective,status:$.status,tokenBudget:$.tokenBudget})}function Dz($){switch($){case"pending":return"☐";case"inProgress":return"\uD83D\uDD04";case"completed":return"✅";default:return"·"}}function jz($,Z){return $.length>Z?$.slice(0,Z)+"…":$}function u4($){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 uZ($){switch($){case"active":return"进行中";case"paused":return"已暂停";case"blocked":return"受阻";case"usageLimited":return"额度受限";case"budgetLimited":return"预算受限";case"complete":return"已完成";default:return $}}function lZ($){let Z=$.filter((H)=>H.status==="completed").length,J=$.filter((H)=>H.status==="inProgress").length,Q=$.filter((H)=>H.status==="pending").length,Y=[`${$.length} 项`];if(J)Y.push(`${J} 进行中`);if(Z)Y.push(`${Z} 完成`);if(Q)Y.push(`${Q} 待办`);return Y.join(" · ")}function Fz($,Z=""){let J=Z.trim();if($.length===0)return J?"\uD83D\uDCCB 计划草稿":"\uD83D\uDCCB 计划更新";return`\uD83D\uDCCB 计划更新 · ${lZ($)}`}function iZ($){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 Q=Math.floor(Z/60),Y=Z%60;return Y?`${Q}h ${Y}m`:`${Q}h`}function n6($){return typeof $==="number"&&Number.isFinite($)?$:null}function Mz($){let Z=n6($.startedAtMs),J=n6($.completedAtMs);if(Z==null||J==null||J<Z)return"";return` · 耗时 ${iZ((J-Z)/1000)}`}function Uz($){let Z=n6($);return Z==null?null:u4(Z)}function Oz($,Z){if(!Z)return["压缩中..."];let J=[],Q=typeof $.trigger==="string"&&$.trigger.trim()?$.trigger.trim():"",Y=Uz($.preTokens),H=typeof $.sourceType==="string"&&$.sourceType.trim()?$.sourceType.trim():"";if(Q)J.push(`**触发**: ${Q}`);if(Y)J.push(`**压缩前**: ${Y} tokens`);if(H)J.push(`**来源**: ${H}`);return J.length>0?J:["压缩完成,无摘要内容"]}function d6($,Z,J){if($==null||!Number.isFinite($))return null;let Q=cZ($,Z,J);return Q?`${Q.used}% · ${m4($,Z)}`:"--"}function o6($){let Z=u4($?.input_tokens??Number.NaN),J=u4($?.cache_read_input_tokens??Number.NaN),Q=u4($?.output_tokens??Number.NaN);return`└ 入 ${Z} | 缓 ${J} | 出 ${Q}`}function M2($,Z,J){let Q=Z&&typeof Z==="object"?Z:{},Y=Q.phase==="end"||Q.phase==="event",H=Y?"✅":"⏳",W=Y?Mz(Q):"",X=`${H} \uD83D\uDEA8 上下文压缩 #${$+1}${W}`,V=Oz(Q,Y);return{tag:"collapsible_panel",element_id:J,header:{title:{tag:"plain_text",content:X}},expanded:!1,elements:[{tag:"markdown",content:V.join(`
|
|
57
|
-
`)}]}}function
|
|
58
|
-
`)}function a6($,Z,J="",Q){return{tag:"collapsible_panel",element_id:Q,header:{title:{tag:"plain_text",content:
|
|
59
|
-
`)}]}}function l4($){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}`}]:[],Q=$.userInputs??[],Y=`\uD83D\uDCE5 收到 (${Q.length}) ${$.directStart?"\uD83D\uDE80":`#${$.turn}`}`,H=Q.length>0?[{tag:"collapsible_panel",element_id:M.userInput,header:{title:{tag:"plain_text",content:Y}},expanded:!1,elements:Q.map((W)=>({tag:"markdown",content
|
|
60
|
-
`)});continue}if(W===J){if(H.push({tag:"markdown",content:`**\uD83E\uDD14 ${V}**`}),X.options.length>0)H.push(...
|
|
61
|
-
*— 由 ${_} 回答*`})}else if(X!==void 0&&J[X])G=`${Q} 等你确认 · ${X+1}/${H}`,A.push(...
|
|
56
|
+
`,jZ(Z,J)}}catch(J){z(`feishu: codex trust write failed for ${$}: ${J}`)}try{LZ("git init -q",{cwd:$,stdio:"ignore"})}catch{}}function j2(){try{let $=LZ(`"${$2()}" login status 2>&1`,{timeout:1e4}).toString();return/Logged in using ChatGPT/i.test($)}catch{return!1}}function F2($){return $.replace(/[^\w一-鿿\-\[\]\*]/g,"_").slice(0,64)}var UZ,OZ,EZ,E$,s,Yz=15000,k4="",_Z=0,B6=null,H$,Y$,Q$,i,BZ=200,RZ,D$,A2,CZ=31457280,Gz;var t=N(()=>{U$();D1();v0();L$();h();h$();N$();P1();AZ();UZ=w.feishu.app_id,OZ=w.feishu.app_secret,EZ=w.runtime.projects_root,E$=new Map;s=new PZ.Client({appId:UZ,appSecret:OZ,disableTokenCache:!1});H$=new Map,Y$=new Map;Q$=new Map;i=new Map;RZ=/\*[0-9]{4}-[0-9]{4}(-[0-9]+)?$/;D$=new Map;A2=[0,1000,4000];Gz=new Set([".png",".jpg",".jpeg",".gif",".bmp",".webp"])});function p6($,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 gZ($,Z){if($!==300315)return!1;return/(?:duplicate\s+(?:element\s*)?id|code\s*1001\s*:\s*duplicate id)/i.test(Z?.message??"")}function W0($){let Z=c$.get($);if(!Z)Z={sequence:0,queue:Promise.resolve(),elementCount:0,deadElements:new Set},c$.set($,Z);return Z}function hZ($){K$.delete($),K$.add($);while(K$.size>Lz){let Z=K$.values().next().value;if(typeof Z!=="string")break;K$.delete(Z)}}function m$($,Z,J){K$.delete($),c$.delete($);let Q=W0($);Q.elementCount=Z,Q.onFailure=J,Q.writeDead=!1,Q.closing=!1}function l6($){return c$.get($)?.elementCount??0}function y1($,Z){return c$.get($)?.deadElements.has(Z)??!1}function IZ($,Z){c$.get($)?.deadElements.delete(Z)}function w4($){if(K$.has($))return;let Z=W0($);if(Z.closing)return;Z.writeDead=!0,V$($)}function v4($){let Z=W0($);return Z.sequence+=1,Z.sequence}function cZ($,Z){$.deadElements.add(Z)}async function M2($,Z,J){let Q=await Y0(),Y=await fetch(`${qz}${Z}`,{method:$,headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},...J?{body:JSON.stringify(J)}:{},signal:AbortSignal.timeout(Bz)}),H=await Y.json();if(!Y.ok||H?.code!==0){let W=typeof H?.code==="number"?H.code:Y.status,X=Y.headers.get("x-tt-logid")??Y.headers.get("x-request-id")??Y.headers.get("request-id")??void 0,V=Error(`cardkit ${$} ${Z}: HTTP ${Y.status} code=${String(H?.code??"MISS")} msg=${H?.msg??"MISS"}${X?` log_id=${X}`:""}`);throw V.code=W,V.httpStatus=Y.status,V.logId=X,V}return H?.data}function Dz($){return new Promise((Z)=>setTimeout(Z,$))}function jz($){if(typeof $!=="object"||$===null)return!1;let Z=$.code;return Z===300309||Z===200850}async function Fz($){let Z=v4($);await M2("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify({config:{streaming_mode:!0}}),sequence:Z})}async function i6($,Z,J,Q,Y=!1,H={}){let W=(X)=>{let V=typeof X==="object"&&X!==null?X:null,A={cardId:$,operation:Z,...H,code:V?.code,httpStatus:V?.httpStatus,logId:V?.logId,message:X instanceof Error?X.message:String(X)};try{if(!Y)W0($).onFailure?.(A.code,A)}catch(G){z(`cardkit failure callback ${$}: ${G}`)}try{Q?.(A)}catch(G){z(`cardkit per-call failure callback ${$}: ${G}`)}};try{await J();return}catch(X){if(!jz(X)){z(`cardkit ${Z} ${$}: ${X}`),W(X);return}z(`cardkit ${Z} ${$}: streaming closed (code=${X.code}) — reopening`)}try{await Fz($)}catch(X){z(`cardkit STREAMING_REOPEN_FAILED ${$}: ${X}`),W(X);return}try{await J()}catch(X){z(`cardkit ${Z} ${$} retry-after-reopen: ${X}`),W(X)}}function Mz($){return typeof $==="object"&&$!==null&&$.code===200740}async function a$($,Z={}){let J=Z.retryDelaysMs?.length?Z.retryDelaysMs:Rz,Q=null;for(let Y=0;Y<J.length;Y++){let H=J[Y]??0;if(H>0)await Dz(H);try{let W=await M2("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(Q=W,!Mz(W)||Y===J.length-1)throw W;let X=J[Y+1]??0;z(`cardkit id_convert ${$}: empty result, retry ${Y+2}/${J.length} in ${X}ms`)}}throw Q}async function u$($){let Z=c$.get($);if(!Z)return;await Z.queue}function z$($,Z,J={},Q){if(K$.has($))return Promise.resolve();let Y=W0($);if(Y.closing||Y.writeDead)return Promise.resolve();let H=B0(Z),W=H.element_id;return Y.queue=Y.queue.then(()=>i6($,"addElement",async()=>{if(Y.writeDead)return;let X=v4($);if(await M2("POST",`/cards/${$}/elements`,{type:J.type??"append",...J.targetElementId?{target_element_id:J.targetElementId}:{},elements:JSON.stringify([H]),sequence:X}),Y.elementCount+=1,W)Y.deadElements.delete(W)},(X)=>{if(W)cZ(Y,W);Q?.(X.code,X)},!1,{elementId:W,targetElementId:J.targetElementId})),Y.queue}function o($,Z,J,Q,Y=!0){if(K$.has($))return Promise.resolve();let H=W0($);if(H.closing||H.writeDead||H.deadElements.has(Z))return Promise.resolve();let W=B0(J);return H.queue=H.queue.then(()=>i6($,`replaceElement ${Z}`,async()=>{if(H.writeDead||H.deadElements.has(Z))return;let X=v4($);await M2("PUT",`/cards/${$}/elements/${Z}`,{element:JSON.stringify(W),sequence:X})},(X)=>{if(Y&&p6(X.code,X))cZ(H,Z);Q?.(X.code,X)},!Y,{elementId:Z})),H.queue}async function F$($,Z,J,Q={}){if(K$.has($))return!1;let Y=W0($);if(Y.closing||Y.writeDead||Y.deadElements.has(Z))return!1;let H=!1;return await o($,Z,J,()=>{H=!0},Q.notifyCardFailure!==!1),!H&&!Y.writeDead&&!Y.deadElements.has(Z)}async function j0($,Z,J={}){return(await h4($,Z,J)).landed}async function h4($,Z,J={}){if(K$.has($))return{landed:!1};let Q=W0($);if(Q.closing||Q.writeDead)return{landed:!1};let Y=Z.element_id,H;return await z$($,Z,J,(W,X)=>{H=X}),{landed:!H&&!Q.writeDead&&!(Y&&Q.deadElements.has(Y)),...H?{failure:H}:{}}}function X0($,Z){if(K$.has($)||c$.get($)?.closing||c$.get($)?.writeDead)return;let J=(Z??"").replace(/\s+/g," ").trim();if(!J)return;let Q=i0.get($);if(!Q)Q={latest:J,lastSent:"",timer:null},i0.set($,Q);else Q.latest=J;if(Q.timer)return;Q.timer=setTimeout(()=>{let Y=i0.get($);if(!Y)return;if(K$.has($)){i0.delete($);return}if(Y.timer=null,Y.latest===Y.lastSent)return;let H=Y.latest;q$($,{config:{summary:{content:H}}}).then((W)=>{let X=i0.get($);if(W&&X===Y)X.lastSent=H})},Pz)}function V$($){let Z=i0.get($);if(!Z)return;if(Z.timer)clearTimeout(Z.timer),Z.timer=null;i0.delete($)}function g4($,Z){return q$($,Z).then(()=>{})}async function q$($,Z){if(K$.has($))return!1;let J=W0($);if(J.closing||J.writeDead)return!1;let Q=!1,Y=!1;return J.queue=J.queue.then(()=>i6($,"patchSettings",async()=>{if(K$.has($)||J.writeDead)return;let H=v4($);await M2("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify(Z),sequence:H}),Q=!0},()=>{Y=!0},!0)),await J.queue,Q&&!Y&&!K$.has($)&&!J.writeDead}async function x$($){let Z=c$.get($);if(!Z){hZ($),V$($);return}if(Z.closing){await Z.queue;return}Z.closing=!0,V$($),await Z.queue,hZ($),c$.delete($)}var qz="https://open.feishu.cn/open-apis/cardkit/v1",Bz=15000,Rz,c$,i0,Pz=1500,K$,Lz=5000;var n0=N(()=>{t();h();N$();Rz=[0,250,750,1500];c$=new Map,i0=new Map;K$=new Set});function I4($){if(!$)return null;return typeof $.total_tokens==="number"&&Number.isFinite($.total_tokens)?$.total_tokens:null}function c4($){return typeof $==="number"&&Number.isFinite($)&&$>0?$:null}function Uz($,Z,J=12000){if(Z==null||Z<=0)return null;if(Z<=J)return 0;let Q=Z-J,Y=Math.max(0,$-J),H=Math.max(0,Q-Y);return Math.round(Math.min(100,Math.max(0,H/Q*100)))}function uZ($,Z,J){let Q=Uz($,Z,J??12000);if(Q==null)return null;return{used:Math.min(100,Math.max(0,100-Q)),remaining:Q}}function mZ($){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 m4($,Z){let J=mZ($);return Z!=null&&Z>0?`${J}/${mZ(Z)}`:`${J}/--`}function pZ($,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 p4($){return JSON.stringify({objective:$.objective,status:$.status,tokenBudget:$.tokenBudget})}function Oz($){switch($){case"pending":return"☐";case"inProgress":return"\uD83D\uDD04";case"completed":return"✅";default:return"·"}}function Ez($,Z){return $.length>Z?$.slice(0,Z)+"…":$}function u4($){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 lZ($){switch($){case"active":return"进行中";case"paused":return"已暂停";case"blocked":return"受阻";case"usageLimited":return"额度受限";case"budgetLimited":return"预算受限";case"complete":return"已完成";default:return $}}function nZ($){let Z=$.filter((H)=>H.status==="completed").length,J=$.filter((H)=>H.status==="inProgress").length,Q=$.filter((H)=>H.status==="pending").length,Y=[`${$.length} 项`];if(J)Y.push(`${J} 进行中`);if(Z)Y.push(`${Z} 完成`);if(Q)Y.push(`${Q} 待办`);return Y.join(" · ")}function Tz($,Z=""){let J=Z.trim();if($.length===0)return J?"\uD83D\uDCCB 计划草稿":"\uD83D\uDCCB 计划更新";return`\uD83D\uDCCB 计划更新 · ${nZ($)}`}function dZ($){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 Q=Math.floor(Z/60),Y=Z%60;return Y?`${Q}h ${Y}m`:`${Q}h`}function n6($){return typeof $==="number"&&Number.isFinite($)?$:null}function kz($){let Z=n6($.startedAtMs),J=n6($.completedAtMs);if(Z==null||J==null||J<Z)return"";return` · 耗时 ${dZ((J-Z)/1000)}`}function Sz($){let Z=n6($);return Z==null?null:u4(Z)}function Nz($,Z){if(!Z)return["压缩中..."];let J=[],Q=typeof $.trigger==="string"&&$.trigger.trim()?$.trigger.trim():"",Y=Sz($.preTokens),H=typeof $.sourceType==="string"&&$.sourceType.trim()?$.sourceType.trim():"";if(Q)J.push(`**触发**: ${Q}`);if(Y)J.push(`**压缩前**: ${Y} tokens`);if(H)J.push(`**来源**: ${H}`);return J.length>0?J:["压缩完成,无摘要内容"]}function d6($,Z,J){if($==null||!Number.isFinite($))return null;let Q=uZ($,Z,J);return Q?`${Q.used}% · ${m4($,Z)}`:"--"}function o6($){let Z=u4($?.input_tokens??Number.NaN),J=u4($?.cache_read_input_tokens??Number.NaN),Q=u4($?.output_tokens??Number.NaN);return`└ 入 ${Z} | 缓 ${J} | 出 ${Q}`}function U2($,Z,J){let Q=Z&&typeof Z==="object"?Z:{},Y=Q.phase==="end"||Q.phase==="event",H=Y?"✅":"⏳",W=Y?kz(Q):"",X=`${H} \uD83D\uDEA8 上下文压缩 #${$+1}${W}`,V=Nz(Q,Y);return{tag:"collapsible_panel",element_id:J,header:{title:{tag:"plain_text",content:X}},expanded:!1,elements:[{tag:"markdown",content:V.join(`
|
|
57
|
+
`)}]}}function oZ($,Z,J=""){let Q=["**\uD83D\uDCCB 当前计划**"],Y=Z?.trim();if(Y)Q.push(""),Q.push(Y);if($.length>0){Q.push("");for(let H of $)Q.push(`- ${Oz(H.status)} ${H.step}`)}else{let H=J.trim();if(Q.push(""),H)Q.push("正在生成计划草稿..."),Q.push(""),Q.push(H);else Q.push("--")}return Q.join(`
|
|
58
|
+
`)}function a6($,Z,J="",Q){return{tag:"collapsible_panel",element_id:Q,header:{title:{tag:"plain_text",content:Tz($,J)}},expanded:!1,elements:[{tag:"markdown",content:oZ($,Z,J)}]}}function O2($,Z,J){let Q=$.length>0?`\uD83D\uDCCB 当前计划 · ${nZ($)}`:"\uD83D\uDCCB 当前计划";return{tag:"collapsible_panel",element_id:J,header:{title:{tag:"plain_text",content:Q}},expanded:!0,elements:[{tag:"markdown",content:oZ($,Z)}]}}function r6($,Z){let J=Number.isFinite($.tokensUsed)?String($.tokensUsed):"MISS",Q=$.tokenBudget==null?"":Number.isFinite($.tokenBudget)?` / ${$.tokenBudget}`:" / MISS",Y=[`**\uD83C\uDFAF 当前目标** · ${lZ($.status)}`,"",$.objective,"",`- 用量: ${J}${Q} tokens`,`- 用时: ${dZ($.timeUsedSeconds)}`];return{tag:"collapsible_panel",element_id:Z,header:{title:{tag:"plain_text",content:`\uD83C\uDFAF 目标更新 · ${lZ($.status)}: ${Ez($.objective,48)}`}},expanded:!1,elements:[{tag:"markdown",content:Y.join(`
|
|
59
|
+
`)}]}}function l4($){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}`}]:[],Q=$.userInputs??[],Y=`\uD83D\uDCE5 收到 (${Q.length}) ${$.directStart?"\uD83D\uDE80":`#${$.turn}`}`,H=Q.length>0?[{tag:"collapsible_panel",element_id:M.userInput,header:{title:{tag:"plain_text",content:Y}},expanded:!1,elements:Q.map((W)=>({tag:"markdown",content:$$(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:M.footer,content:$.initialFooter??"Waiting...(0s)"}]}}}function aZ($,Z,J){let Q=$.question.trim()||`问题 ${Z+1}`;return`${Z+1}/${J} · ${Q}`}function yz($,Z){if(!Z)return"?";return Z.customText??(Z.optionIdx!==void 0?$.options[Z.optionIdx]?.label:void 0)??"?"}function xz($,Z,J){let Q=[];for(let Y=0;Y<$.options.length;Y++){let H=$.options[Y],W=H.description?` · ${$$(H.description)}`:"";Q.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:Y}}],elements:[{tag:"markdown",content:`**${$$(H.label)}**${W}`}]})}return Q}function iZ($,Z,J,Q){if($.length===0)return null;let Y=$.length,H=[];for(let W=0;W<$.length;W++){let X=$[W];if(!X)continue;let V=aZ(X,W,Y),A=Q.get(W);if(A){let G=yz(X,A),_=[`**✅ ${V}**`,`**回答**:${G}`];H.push({tag:"markdown",content:_.join(`
|
|
60
|
+
`)});continue}if(W===J){if(H.push({tag:"markdown",content:`**\uD83E\uDD14 ${V}**`}),X.options.length>0)H.push(...xz(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 E2($,Z,J,Q="\uD83E\uDD14",Y){let H=J.length,W=Y?.answered??new Map,X=Y?.currentIdx,V=X===void 0&&W.size>0,A=[],G;if(V){G=`${Q} 已回答 · ${H}/${H}`,A.push(...iZ(J,Z,X,W)??[]);let _=[...W.values()].reverse().find((q)=>q.user)?.user;if(_)A.push({tag:"markdown",content:`
|
|
61
|
+
*— 由 ${_} 回答*`})}else if(X!==void 0&&J[X])G=`${Q} 等你确认 · ${X+1}/${H}`,A.push(...iZ(J,Z,X,W)??[]);else if(G=`${Q} 等你确认`,J[0])A.push({tag:"markdown",content:`**${aZ(J[0],0,H||1)}**`});return{tag:"collapsible_panel",element_id:M.tool($),header:{title:{tag:"plain_text",content:G}},expanded:!V,elements:A}}var rZ=N(()=>{N$()});import{isAbsolute as t6,relative as bz}from"node:path";function n4($){return $==="Bash"||$==="exec_command"||$.endsWith(".exec_command")}function d4($){return $==="write_stdin"||$.endsWith(".write_stdin")}function fz($){return n4($)||d4($)}function o4($){return $==="FileChange"||$==="fileChange"}function k2($){return $==="WebSearch"||$==="webSearch"}function a4($){return $==="WebFetch"||$==="webFetch"}function Q7($){return $==="MCP"}function r4($){return $==="ImageGeneration"||$==="imageGeneration"}function Y7($){return $==="Agent"||$==="Task"}function t4($){return $==="Read"}function s4($){return $==="Write"}function e4($){return $==="Edit"||$==="NotebookEdit"}function $9($){return $==="MultiEdit"}function H7($){return $==="Glob"||$==="Grep"||$==="LS"}function Z9($){return $==="TodoWrite"}function J9($){return $==="ExitPlanMode"}function Q9($){return $.startsWith(sZ)}function eZ($){return Q9($)?$.slice(sZ.length):$}function d0($){if(Q9($))return"服务端工具";if(o4($))return"文件变更";if(k2($))return"网页搜索";if(a4($))return"网页读取";if(r4($))return"图片生成";if(t4($))return"读取文件";if(s4($))return"写入文件";if(e4($)||$9($))return"编辑文件";if($==="Glob")return"匹配文件";if($==="Grep")return"搜索文件";if($==="LS")return"列目录";if(Z9($))return"更新待办";if(J9($))return"确认计划";if($==="Task")return"子任务";return fz($)?"Bash":$}function F0($,Z){let J=(Q,Y)=>Q.length>Y?Q.slice(0,Y)+"…":Q;if(Q9($))return J(wz($,Z),80);if(!Z||typeof Z!=="object")return"";if(n4($))return vz(Z);if(d4($))return hz(Z);if(o4($))return J(cz(Z),80);if(k2($))return J(RJ(Z),80);if(a4($))return J(dz(Z),80);if(Q7($))return J(az(Z),80);if(r4($))return J(tz(Z),80);if(Y7($))return J(sz(Z),80);if(t4($))return J(mz(Z),80);if(s4($))return J(uz(Z),80);if(e4($))return J(pz(Z),80);if($9($))return J(lz(Z),80);if(H7($))return J(iz($,Z),80);if(Z9($))return J(nz(Z),80);if(J9($))return J(S2(Z)||"提交计划",80);switch($){case"Skill":return J(String(Z.skill??""),80)}for(let Q of Object.values(Z))if(typeof Q==="string"&&Q)return J(Q,80);return""}function wz($,Z){let J=typeof Z?.tool==="string"&&Z.tool?Z.tool:eZ($),Q=S2(Z?.input);return Q?`${J}: ${Q}`:J}function vz($){let Z=(H,W)=>H.length>W?H.slice(0,W)+"…":H,J=ZJ($);if(J.description)return Z(J.description.replace(/\s+/g," "),80);let Q=J.command;if(!Q)return"";let Y=Q.split(/\r?\n/).map((H)=>H.trim()).filter(Boolean);if(Y.length<=1)return Z(Q.replace(/\s+/g," "),80);return`Shell 脚本 · ${Y.length} 行 · ${Z(R1(Q),46)}`}function $J($){let Z=typeof $?.chars==="string"?$.chars:"";if(Z==="")return"读取会话输出";if(Z==="\x03")return"中断会话";return"发送输入"}function hz($){let Z=$?.session_id??$?.sessionId,J=Z===void 0?"":` ${Z}`;return`${$J($)}${J}`}function ZJ($){let Z=String($?.command??$?.cmd??$?.script??""),J=String($?.description??$?.reason??"").trim(),Q=N8(Z);return{description:Q.description||J,command:Q.command}}function p$($,Z=""){let J="```";while($.includes(J))J+="`";return`${J}${Z}
|
|
62
62
|
${$}
|
|
63
|
-
${J}`}function V0($,Z=
|
|
63
|
+
${J}`}function V0($,Z=Cz,J=""){if($.length<=Z)return p$($,J);let Q=$.slice(0,Z).trimEnd();return[`_已截断: 仅显示前 ${Z} / ${$.length} 字符。_`,p$(`${Q}
|
|
64
64
|
... output 已截断 ...`,J)].join(`
|
|
65
|
-
`)}function
|
|
66
|
-
`)}function
|
|
67
|
-
`)}function
|
|
68
|
-
... diff 已截断 ...`:$}function
|
|
69
|
-
`):p$(JSON.stringify($??{},null,2).slice(0,2000))}let W=Q.map((A)=>Z7($7(A))).reduce(
|
|
70
|
-
`)}function M0($){return String($?.file_path??$?.path??$?.notebook_path??"")}function
|
|
71
|
-
`):b$($??{},2000)}function
|
|
72
|
-
`):b$($??{},2000)}function
|
|
73
|
-
`):b$($??{},2000)}function
|
|
74
|
-
`)}function
|
|
75
|
-
`)}function
|
|
76
|
-
`)}function W7($){if(!$)return null;try{let Z=JSON.parse($);return Z&&typeof Z==="object"?Z:null}catch{return null}}function X7($,Z){return W7(Z)??$?.action??{}}function V7($,Z){let J=X7($,Z),Q=Array.isArray(J?.queries)?J.queries.filter((H)=>typeof H==="string"&&H.length>0):[],Y=typeof J?.query==="string"&&J.query.length>0?J.query:typeof $?.query==="string"&&$.query.length>0?$.query:"";return Q.length>0?Q:Y?[Y]:[]}function z7($,Z){let J=X7($,Z);return String(J?.url??$?.url??"")}function
|
|
77
|
-
`)}function
|
|
78
|
-
`)}function
|
|
65
|
+
`)}function C($){return"`"+String($??"").replace(/`/g,"'")+"`"}function b$($,Z=3000){return p$(JSON.stringify($??null,null,2).slice(0,Z),"json")}function S2($){if(!$||typeof $!=="object")return"";let Z=$;for(let J of["query","prompt","path","file_path","url","name","id"]){let Q=Z[J];if(typeof Q==="string"&&Q.length>0)return Q}for(let J of Object.values(Z))if(typeof J==="string"&&J.length>0)return J;return""}function JJ($,Z,J){let Q=ZJ($),Y=Q.command,H=Q.description,W=[];if(H)W.push(`**目的**: ${H}`);let X=$?.cwd??$?.workdir;if(X)W.push(`**cwd**: ${C(X)}`);if($?.source)W.push(`**source**: ${C($.source)}`);if(W.length>0)W.push("");if(W.push("**命令**"),W.push(p$(Y||"(空命令)","bash")),J)W.push(""),W.push(J);if(Z!=null)W.push(""),W.push("---"),W.push("**output:**"),W.push(V0(Z));return W.join(`
|
|
66
|
+
`)}function QJ($,Z,J){let Q=[],Y=$?.session_id??$?.sessionId;if(Q.push(`**操作**: ${$J($)}`),Y!==void 0)Q.push(`**session**: ${C(Y)}`);if(typeof $?.chars==="string"&&$.chars.length>0){let H=$.chars==="\x03"?"^C":$.chars;Q.push(""),Q.push("**输入**"),Q.push(p$(H))}if(J)Q.push(""),Q.push(J);if(Z!=null)Q.push(""),Q.push("---"),Q.push("**output:**"),Q.push(V0(Z));return Q.join(`
|
|
67
|
+
`)}function YJ($){return Array.isArray($?.changes)?$.changes:[]}function HJ($){let Z=$?.cwd??$?.grantRoot;return typeof Z==="string"&&Z.length>0?Z:void 0}function T2($,Z){let J=String($??"");if(!J)return"(无 path)";if(Z&&t6(J)&&t6(Z)){let Q=bz(Z,J);if(Q&&!Q.startsWith("..")&&!t6(Q))return Q}return J}function gz($){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 WJ($){return $?.kind?.move_path??$?.kind?.movePath??$?.move_path??$?.movePath}function e6($){let Z=gz($);if(WJ($))return Z==="update"?"移动/修改":"移动";switch(Z){case"add":return"新增";case"delete":return"删除";case"update":return"修改";default:return"变更"}}function $7($){let Z=$?.diff??$?.unified_diff;return typeof Z==="string"?Z:""}function Z7($){let Z=0,J=0;for(let Q of $.split(/\r?\n/)){if(Q.startsWith("+++")||Q.startsWith("---"))continue;if(Q.startsWith("+"))Z++;if(Q.startsWith("-"))J++}return{added:Z,removed:J}}function XJ($,Z){return{added:$.added+Z.added,removed:$.removed+Z.removed}}function J7($){return $.added>0||$.removed>0?`+${$.added} -${$.removed}`:""}function Iz($){return $.length>1800?$.slice(0,1800)+`
|
|
68
|
+
... diff 已截断 ...`:$}function cz($){let Z=YJ($),J=HJ($);if(Z.length===0){let V=typeof $?.reason==="string"?$.reason.trim():"",A=$?.grantRoot?T2($.grantRoot):"";if(V&&A)return`${V} · ${A}`;return V||(A?`申请修改 ${A}`:"")}let Q=Z.map((V)=>Z7($7(V))).reduce(XJ,{added:0,removed:0}),Y=J7(Q),H=[...new Set(Z.map(e6))],W=T2(Z[0]?.path,J),X=Y?` · ${Y}`:"";if(Z.length===1)return`${H[0]} ${W}${X}`;return`${Z.length} 个文件 · ${H.join("/")} · ${W} 等${X}`}function VJ($,Z,J){let Q=YJ($),Y=HJ($),H=[];if(Q.length===0){let A=typeof $?.reason==="string"?$.reason.trim():"";if(A)H.push(`**原因**: ${A}`);if($?.grantRoot)H.push(`**范围**: ${C(T2($.grantRoot))}`);if(J)H.push(""),H.push(J);if(Z!=null)H.push(""),H.push("---"),H.push("**output:**"),H.push(p$(Z.slice(0,3000)));return H.length>0?H.join(`
|
|
69
|
+
`):p$(JSON.stringify($??{},null,2).slice(0,2000))}let W=Q.map((A)=>Z7($7(A))).reduce(XJ,{added:0,removed:0}),X=J7(W);if(H.push(`**文件**: ${Q.length} 个`),X)H.push(`**行数**: ${X}`);if($?.status)H.push(`**状态**: ${C($.status)}`);let V=Q.slice(0,5);for(let A of V){let G=$7(A),_=J7(Z7(G)),q=T2(A?.path,Y),B=_?`**${e6(A)}** ${C(q)} · ${_}`:`**${e6(A)}** ${C(q)}`;H.push(""),H.push(B);let R=WJ(A);if(R)H.push(`来自 ${C(T2(R,Y))}`);H.push(G?p$(Iz(G),"diff"):"_无 diff 内容_")}if(Q.length>V.length)H.push(""),H.push(`还有 ${Q.length-V.length} 个文件未展开显示。`);if(J)H.push(""),H.push(J);return H.join(`
|
|
70
|
+
`)}function M0($){return String($?.file_path??$?.path??$?.notebook_path??"")}function mz($){let Z=M0($),J=[$?.offset!=null?`offset ${$.offset}`:"",$?.limit!=null?`limit ${$.limit}`:""].filter(Boolean).join(" · ");return J&&Z?`${Z} · ${J}`:Z}function uz($){let Z=M0($),J=typeof $?.content==="string"?$.content:"",Q=J?J.split(/\r?\n/).length:0;return Z&&Q?`${Z} · ${Q} 行`:Z}function pz($){let Z=M0($),J=$?.replace_all?"全局替换":"替换";return Z?`${J} ${Z}`:J}function lz($){let Z=M0($),J=Array.isArray($?.edits)?$.edits.length:0,Q=J?` · ${J} 处`:"";return Z?`批量编辑 ${Z}${Q}`:`批量编辑${Q}`}function iz($,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 zJ($){switch($){case"pending":return"待办";case"in_progress":return"进行中";case"completed":return"完成";default:return String($??"未知")}}function nz($){let Z=Array.isArray($?.todos)?$.todos:[];if(Z.length===0)return"";let J=new Map;for(let Y of Z){let H=zJ(Y?.status);J.set(H,(J.get(H)??0)+1)}let Q=[...J.entries()].map(([Y,H])=>`${Y} ${H}`).join(" · ");return`${Z.length} 项${Q?` · ${Q}`:""}`}function dz($){let Z=String($?.url??""),J=typeof $?.prompt==="string"?$.prompt.trim():"";return Z&&J?`${Z} · ${J}`:Z||J}function b1($,Z){if(Z==null)return;$.push(""),$.push("---"),$.push("**结果**"),$.push(V0(Z,1200))}function AJ($,Z,J){let Q=[],Y=M0($);if(Y)Q.push(`**路径**: ${C(Y)}`);if($?.offset!=null)Q.push(`**offset**: ${C($.offset)}`);if($?.limit!=null)Q.push(`**limit**: ${C($.limit)}`);if(J)Q.push(""),Q.push(J);if(Z!=null)Q.push(""),Q.push("_内容已读取,未展开到群聊卡片。_");return Q.length>0?Q.join(`
|
|
71
|
+
`):b$($??{},2000)}function GJ($,Z,J){let Q=[],Y=M0($),H=typeof $?.content==="string"?$.content:"";if(Y)Q.push(`**路径**: ${C(Y)}`);if(H){let W=H.split(/\r?\n/).length;Q.push(`**内容**: ${W} 行 / ${H.length} 字符`),Q.push(V0(H,1200))}if(J)Q.push(""),Q.push(J);return b1(Q,Z),Q.length>0?Q.join(`
|
|
72
|
+
`):b$($??{},2000)}function _J($,Z,J){let Q=[],Y=M0($);if(Y)Q.push(`**路径**: ${C(Y)}`);if($?.cell_id)Q.push(`**cell**: ${C($.cell_id)}`);if($?.edit_mode)Q.push(`**模式**: ${C($.edit_mode)}`);if($?.replace_all)Q.push("**范围**: 全局替换");if(typeof $?.old_string==="string")Q.push(""),Q.push("**查找**"),Q.push(V0($.old_string,800));let H=typeof $?.new_string==="string"?$.new_string:typeof $?.new_source==="string"?$.new_source:"";if(H)Q.push(""),Q.push("**替换为**"),Q.push(V0(H,800));if(J)Q.push(""),Q.push(J);return b1(Q,Z),Q.length>0?Q.join(`
|
|
73
|
+
`):b$($??{},2000)}function KJ($,Z,J){let Q=[],Y=M0($),H=Array.isArray($?.edits)?$.edits:[];if(Y)Q.push(`**路径**: ${C(Y)}`);Q.push(`**编辑**: ${H.length} 处`);for(let[W,X]of H.slice(0,5).entries()){if(Q.push(""),Q.push(`**#${W+1}${X?.replace_all?" · 全局替换":""}**`),typeof X?.old_string==="string")Q.push("查找:"),Q.push(V0(X.old_string,500));if(typeof X?.new_string==="string")Q.push("替换为:"),Q.push(V0(X.new_string,500))}if(H.length>5)Q.push(""),Q.push(`还有 ${H.length-5} 处编辑未展开显示。`);if(J)Q.push(""),Q.push(J);return b1(Q,Z),Q.join(`
|
|
74
|
+
`)}function qJ($,Z,J,Q){let Y=[];if($==="Glob"){if(Y.push("**动作**: 匹配文件"),Z?.pattern)Y.push(`**pattern**: ${C(Z.pattern)}`);if(Z?.path)Y.push(`**path**: ${C(Z.path)}`)}else if($==="Grep"){if(Y.push("**动作**: 搜索文件"),Z?.pattern)Y.push(`**pattern**: ${C(Z.pattern)}`);if(Z?.path)Y.push(`**path**: ${C(Z.path)}`);if(Z?.glob)Y.push(`**glob**: ${C(Z.glob)}`);if(Z?.type)Y.push(`**type**: ${C(Z.type)}`);if(Z?.output_mode)Y.push(`**output**: ${C(Z.output_mode)}`)}else{if(Y.push("**动作**: 列目录"),Z?.path)Y.push(`**path**: ${C(Z.path)}`);if(Array.isArray(Z?.ignore)&&Z.ignore.length)Y.push(`**ignore**: ${Z.ignore.map(C).join(" ")}`)}if(Q)Y.push(""),Y.push(Q);return b1(Y,J),Y.join(`
|
|
75
|
+
`)}function BJ($,Z,J){let Q=Array.isArray($?.todos)?$.todos:[],Y=[`**待办**: ${Q.length} 项`];for(let H of Q.slice(0,12)){let W=zJ(H?.status),X=String(H?.content??H?.activeForm??"").trim()||"(空)";Y.push(`- ${W}: ${X}`)}if(Q.length>12)Y.push(`- 还有 ${Q.length-12} 项未显示`);if(J)Y.push(""),Y.push(J);return b1(Y,Z),Y.join(`
|
|
76
|
+
`)}function W7($){if(!$)return null;try{let Z=JSON.parse($);return Z&&typeof Z==="object"?Z:null}catch{return null}}function X7($,Z){return W7(Z)??$?.action??{}}function V7($,Z){let J=X7($,Z),Q=Array.isArray(J?.queries)?J.queries.filter((H)=>typeof H==="string"&&H.length>0):[],Y=typeof J?.query==="string"&&J.query.length>0?J.query:typeof $?.query==="string"&&$.query.length>0?$.query:"";return Q.length>0?Q:Y?[Y]:[]}function z7($,Z){let J=X7($,Z);return String(J?.url??$?.url??"")}function RJ($){let Z=V7($,null);if(Z.length===1)return Z[0];if(Z.length>1)return`${Z.length} 条查询 · ${Z[0]}`;let J=z7($,null);if(J)return J;let Q=$?.action?.type;return typeof Q==="string"&&Q!=="other"?Q:""}function oz($,Z){let J=V7($,Z);if(J.length===1)return J[0];if(J.length>1)return`${J.length} 条查询 · ${J[0]}`;let Q=z7($,Z);if(Q)return Q;return RJ($)}function PJ($,Z,J){let Q=X7($,Z),Y=V7($,Z),H=z7($,Z),W=[],X=typeof Q?.type==="string"?Q.type:"";if(X==="search"||Y.length>0){if(W.push("**动作**: 搜索"),Y.length>0){W.push(""),W.push("**查询**");for(let V of Y.slice(0,6))W.push(`- ${C(V)}`);if(Y.length>6)W.push(`- 还有 ${Y.length-6} 条未显示`)}}else if(X==="open_page"){if(W.push("**动作**: 打开页面"),H)W.push(`**URL**: ${C(H)}`)}else if(X==="find_in_page"){if(W.push("**动作**: 页内查找"),H)W.push(`**URL**: ${C(H)}`);if(Q?.pattern)W.push(`**关键词**: ${C(Q.pattern)}`)}else if(W.push(`**动作**: ${X?C(X):"网页搜索"}`),H)W.push(`**URL**: ${C(H)}`);if(J)W.push(""),W.push(J);if(W.length===1&&!Y.length&&!H&&Z!=null)W.push(""),W.push("---"),W.push("**output:**"),W.push(p$(Z.slice(0,3000),"json"));return W.join(`
|
|
77
|
+
`)}function LJ($,Z,J){let Q=["**动作**: 读取网页"];if($?.url)Q.push(`**URL**: ${C($.url)}`);if($?.prompt)Q.push(""),Q.push("**问题**"),Q.push(String($.prompt).slice(0,1200));if(J)Q.push(""),Q.push(J);return b1(Q,Z),Q.join(`
|
|
78
|
+
`)}function az($){let Z=String($?.server??""),J=String($?.tool??""),Q=Z&&J?`${Z}.${J}`:J||Z,Y=S2($?.arguments);return Y&&Q?`${Q}: ${Y}`:Q||Y}function DJ($,Z,J){let Q=[];if($?.server)Q.push(`**server**: ${C($.server)}`);if($?.tool)Q.push(`**tool**: ${C($.tool)}`);let Y=$?.arguments;if(Y&&typeof Y==="object"&&Object.keys(Y).length>0){if(Q.length>0)Q.push("");Q.push("**arguments**"),Q.push(b$(Y,2000))}if(J)Q.push(""),Q.push(J);if(Z!=null){let H=W7(Z);if(Q.push(""),Q.push("---"),Q.push("**结果**"),H&&Array.isArray(H.content)){let W=H.content.map((X)=>typeof X?.text==="string"?X.text:"").filter(Boolean);if(W.length>0)Q.push(W.join(`
|
|
79
79
|
`).slice(0,3000));if(H.structuredContent)Q.push(""),Q.push("**structuredContent**"),Q.push(b$(H.structuredContent,2000));if(W.length===0&&!H.structuredContent)Q.push(b$(H,3000))}else Q.push(H?b$(H,3000):p$(Z.slice(0,3000)))}return Q.length>0?Q.join(`
|
|
80
|
-
`):b$($??{},2000)}function
|
|
81
|
-
`)}function
|
|
82
|
-
`):b$($??{},2000)}function
|
|
83
|
-
`):b$($??{},2000)}function U0($,Z,J,Q,Y="⏳",H){let W=
|
|
80
|
+
`):b$($??{},2000)}function rz($,Z,J,Q){let Y=["**类型**: 模型服务端内置工具",`**tool**: ${C(typeof Z?.tool==="string"&&Z.tool?Z.tool:eZ($))}`],H=Z?.input;if(H&&typeof H==="object")if(Y.push(""),Y.push("**input**"),Object.keys(H).length>0)Y.push(b$(H,2000));else Y.push("_provider 未提供结构化 input_");else if(H!=null&&H!=="")Y.push(`**input**: ${C(H)}`);if(Q)Y.push(""),Y.push(Q);if(J!=null)Y.push(""),Y.push("---"),Y.push("**结果**"),Y.push(V0(J,3000));return Y.join(`
|
|
81
|
+
`)}function tz($){let Z=typeof $?.revisedPrompt==="string"?$.revisedPrompt:"",J=typeof $?.status==="string"?$.status:"";return Z||J}function jJ($,Z,J){let Q=[];if($?.status)Q.push(`**状态**: ${C($.status)}`);if($?.revisedPrompt){if(Q.length>0)Q.push("");Q.push("**提示词**"),Q.push(String($.revisedPrompt).slice(0,2000))}if(J)Q.push(""),Q.push(J);if(Z!=null&&Z.trim())Q.push(""),Q.push("---"),Q.push("**输出**"),Q.push(C(Z.trim()));return Q.length>0?Q.join(`
|
|
82
|
+
`):b$($??{},2000)}function sz($){let Z=typeof $?.tool==="string"?$.tool:"",J=typeof $?.prompt==="string"?$.prompt:"",Q=typeof $?.description==="string"?$.description:"",Y=typeof $?.subject==="string"?$.subject:"",H=Q||Y||J;return Z&&H?`${Z}: ${H}`:H||Z}function i4($,Z,J){let Q=[];if($?.tool)Q.push(`**tool**: ${C($.tool)}`);if($?.model)Q.push(`**model**: ${C($.model)}`);if($?.description)Q.push(`**描述**: ${$.description}`);if($?.subagent_type)Q.push(`**类型**: ${C($.subagent_type)}`);if($?.prompt){if(Q.length>0)Q.push("");Q.push("**prompt**"),Q.push(String($.prompt).slice(0,2000))}if(J)Q.push(""),Q.push(J);if(Z!=null){Q.push(""),Q.push("---"),Q.push("**状态**");let Y=W7(Z);Q.push(Y?b$(Y,3000):p$(Z.slice(0,3000)))}return Q.length>0?Q.join(`
|
|
83
|
+
`):b$($??{},2000)}function U0($,Z,J,Q,Y="⏳",H){let W=k2(Z)&&Q!=null?oz(J,Q):F0(Z,J),X=W.length>80?W.slice(0,80)+"…":W,V=d0(Z),A=X?`${Y} \uD83D\uDD27 ${V}: ${X}`:`${Y} \uD83D\uDD27 ${V}`,G=H?`
|
|
84
84
|
|
|
85
|
-
${H}`:"",_=n4(Z)
|
|
85
|
+
${H}`:"",_=n4(Z)?JJ(J,Q,H):d4(Z)?QJ(J,Q,H):Q9(Z)?rz(Z,J,Q,H):o4(Z)?VJ(J,Q,H):k2(Z)?PJ(J,Q,H):a4(Z)?LJ(J,Q,H):Q7(Z)?DJ(J,Q,H):r4(Z)?jJ(J,Q,H):t4(Z)?AJ(J,Q,H):s4(Z)?GJ(J,Q,H):e4(Z)?_J(J,Q,H):$9(Z)?KJ(J,Q,H):H7(Z)?qJ(Z,J,Q,H):Z9(Z)?BJ(J,Q,H):J9(Z)?i4({prompt:S2(J)||"提交计划"},Q,H):Y7(Z)?i4(J,Q,H):"```\n"+JSON.stringify(J??{},null,2).slice(0,2000)+"\n```"+G+(Q!=null?`
|
|
86
86
|
---
|
|
87
87
|
**output:**
|
|
88
88
|
\`\`\`
|
|
89
|
-
`+Q.slice(0,3000)+"\n```":"");return{tag:"collapsible_panel",element_id:M.tool($),header:{title:{tag:"plain_text",content:A}},expanded:!1,elements:[{tag:"markdown",content
|
|
90
|
-
`))}]}}function
|
|
91
|
-
`))}]}}function A7($,Z,J,Q){let Y=F0(Z,J),H=d0(Z),W=Y?`\uD83D\uDD10 等审批 · ${H}: ${Y}`:`\uD83D\uDD10 等审批 · ${H}`,X=n4(Z)
|
|
92
|
-
`).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(!
|
|
93
|
-
`)){let q=_.indexOf("=");if(q<=0)continue;A[_.slice(0,q)]=_.slice(q+1)}let G=A.Id??"";if(!
|
|
94
|
-
`)}function
|
|
95
|
-
`)}function C1($){return typeof $==="number"&&Number.isFinite($)?`${Math.round($)}%`:"MISS"}function
|
|
96
|
-
`);let Z=[];if($.cpu){let{cores:J,load1:Q,load5:Y,load15:H}=$.cpu;Z.push(`**负载** ${Q.toFixed(2)} / ${Y.toFixed(2)} / ${H.toFixed(2)} (${J}核)`)}else Z.push("**负载** _n/a_");if($.mem)Z.push(`**内存** ${$.mem.percent}% (${
|
|
97
|
-
`)}function
|
|
98
|
-
`)}function Y9($,Z=M.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:
|
|
99
|
-
`)}function H9($,Z=M.consoleCurrentModel){return{tag:"markdown",element_id:Z,content:
|
|
100
|
-
`)}function
|
|
101
|
-
选账号进入模型选择。`},...$.providers.map((Z)=>
|
|
102
|
-
${J}`}]},{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 R7($){return f1($.sessionName,
|
|
89
|
+
`+Q.slice(0,3000)+"\n```":"");return{tag:"collapsible_panel",element_id:M.tool($),header:{title:{tag:"plain_text",content:A}},expanded:!1,elements:[{tag:"markdown",content:$$(_)}]}}function N2($,Z){let J=Z.length,Q=Z.some((V)=>V.isError),Y=Z.every((V)=>V.output!==null),H=Q?"❌":Y?"✅":"⏳",W=J===1?(()=>{let V=tZ(Z[0]);return V?`${H} \uD83D\uDD27 编辑文件: ${V}`:`${H} \uD83D\uDD27 编辑文件`})():`${H} \uD83D\uDD27 编辑文件 · ${J} 次`,X=Z.map((V)=>{let A=tZ(V);return A?`\`${A}\``:"`(无 path)`"});return{tag:"collapsible_panel",element_id:M.tool($),header:{title:{tag:"plain_text",content:W}},expanded:!1,elements:[{tag:"markdown",content:$$(X.join(`
|
|
90
|
+
`))}]}}function tZ($){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 y2($,Z){let J=Z.length,Q=Z.some((V)=>V.isError),Y=Z.every((V)=>V.output!==null),H=Q?"❌":Y?"✅":"⏳",W=J===1?(()=>{let V=F0("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:M.tool($),header:{title:{tag:"plain_text",content:W}},expanded:!1,elements:[{tag:"markdown",content:$$(X.join(`
|
|
91
|
+
`))}]}}function A7($,Z,J,Q){let Y=F0(Z,J),H=d0(Z),W=Y?`\uD83D\uDD10 等审批 · ${H}: ${Y}`:`\uD83D\uDD10 等审批 · ${H}`,X=n4(Z)?JJ(J,null):d4(Z)?QJ(J,null):o4(Z)?VJ(J,null):k2(Z)?PJ(J,null):a4(Z)?LJ(J,null):Q7(Z)?DJ(J,null):r4(Z)?jJ(J,null):t4(Z)?AJ(J,null):s4(Z)?GJ(J,null):e4(Z)?_J(J,null):$9(Z)?KJ(J,null):H7(Z)?qJ(Z,J,null):Z9(Z)?BJ(J,null):J9(Z)?i4({prompt:S2(J)||"提交计划"},null):Y7(Z)?i4(J,null):"```\n"+JSON.stringify(J??{},null,2).slice(0,2000)+"\n```";return{tag:"collapsible_panel",element_id:M.tool($),header:{title:{tag:"plain_text",content:W}},expanded:!0,elements:[{tag:"markdown",content:X},{tag:"column_set",columns:[s6("✅ 允许","primary",Q,"allow"),s6("♾️ 始终允许","default",Q,"allow_always"),s6("❌ 拒绝","danger",Q,"deny")]}]}}function s6($,Z,J,Q){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:Q}}]}]}}var Cz=300,sZ="server_tool:";var FJ=N(()=>{N$();W4()});import{execFile as ez}from"node:child_process";import{readFileSync as G7,statfsSync as $A,statSync as MJ}from"node:fs";import{cpus as ZA,homedir as JA}from"node:os";import{promisify as QA}from"node:util";function HA(){try{let $=G7("/proc/loadavg","utf8").trim().split(/\s+/);return{cores:ZA().length,load1:parseFloat($[0]??"0"),load5:parseFloat($[1]??"0"),load15:parseFloat($[2]??"0")}}catch($){return z(`sysinfo: read /proc/loadavg failed: ${$}`),null}}function WA(){try{let $=G7("/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"),Q=Z("MemAvailable");if(!J)return null;let Y=Math.max(0,J-Q);return{totalBytes:J,availBytes:Q,usedBytes:Y,percent:Math.round(Y/J*100)}}catch($){return z(`sysinfo: read /proc/meminfo failed: ${$}`),null}}function UJ($,Z){try{let J=$A(Z,{bigint:!1}),Q=J.blocks*J.bsize,Y=J.bavail*J.bsize,H=Math.max(0,Q-Y);if(!Q)return null;return{label:$,path:Z,totalBytes:Q,availBytes:Y,usedBytes:H,percent:Math.round(H/Q*100)}}catch(J){return z(`sysinfo: statfs ${Z} failed: ${J}`),null}}function XA(){let $=[],Z=UJ("/","/");if(Z)$.push(Z);let J=JA();if(J&&J!=="/"){let Q=!1;try{let Y=MJ("/"),H=MJ(J);Q=Y.dev===H.dev}catch{}if(!Q){let Y=UJ("$HOME",J);if(Y)$.push(Y)}}return $}function VA(){try{let $=G7("/proc/uptime","utf8").trim().split(/\s+/);return parseFloat($[0]??"0")}catch{return null}}async function OJ($,Z=2000){try{let{stdout:J}=await YA("systemctl",["--user",...$],{timeout:Z,maxBuffer:4194304});return J}catch(J){return z(`sysinfo: systemctl ${$.join(" ")} failed: ${J}`),null}}function EJ($){return TJ.some((Z)=>$.startsWith(Z))&&$.endsWith(".service")}async function zA(){let $=await OJ(["list-units","--type=service","--all","--no-legend","--plain",...TJ.map((V)=>`${V}*`)]);if($===null)return{services:[],error:"systemctl 不可用"};let Z=$.split(`
|
|
92
|
+
`).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(!EJ(G))continue;J.push(G)}if(J.length===0)return{services:[],error:null};let Q=await OJ(["show",...J,"-p","Id","-p","ActiveState","-p","SubState","-p","ActiveEnterTimestampMonotonic","-p","StateChangeTimestampMonotonic"]);if(Q===null)return{services:[],error:"systemctl show 失败"};let Y=VA(),H=Q.split(/\n\s*\n/),W=[],X=(V)=>{let A=parseInt(V??"0",10);if(A<=0||Y===null)return null;return Math.max(0,Y-A/1e6)};for(let V of H){let A={};for(let _ of V.split(`
|
|
93
|
+
`)){let q=_.indexOf("=");if(q<=0)continue;A[_.slice(0,q)]=_.slice(q+1)}let G=A.Id??"";if(!EJ(G))continue;W.push({name:G.replace(/\.service$/,""),active:A.ActiveState??"unknown",sub:A.SubState??"",lastActiveAgoSec:X(A.ActiveEnterTimestampMonotonic),stateAgoSec:X(A.StateChangeTimestampMonotonic)})}return W.sort((V,A)=>V.name.localeCompare(A.name)),{services:W,error:null}}async function kJ(){if(process.platform==="win32")return{cpu:null,mem:null,disks:[],services:[],servicesError:"Windows: sysinfo 暂未支持"};let $=HA(),Z=WA(),J=XA(),{services:Q,error:Y}=await zA();return{cpu:$,mem:Z,disks:J,services:Q,servicesError:Y}}var YA,TJ,x2="cc-* / codex-*";var _7=N(()=>{h();YA=QA(ez),TJ=["cc-","codex-"]});function C2($,Z){return Z}function K7($){return{schema:"2.0",config:{update_multi:!0,streaming_mode:!0,summary:{content:$.status}},body:{elements:[{tag:"markdown",element_id:M.footer,content:C2($.title,$.status)}]}}}function SJ($){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 AA($){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 b2($){if($<60000)return`${Math.round($/1000)}s`;let Z=Math.floor($/60000);if(Z<60)return`${Z}m`;let J=Math.floor(Z/60),Q=Z%60;if(J<24)return`${J}h ${Q}m`;return`${Math.floor(J/24)}d ${J%24}h`}function z0($){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 yJ($){if($===void 0)return"**\uD83D\uDCCA 订阅额度** _加载中…_";switch($.state){case"no_credentials":return"**\uD83D\uDCCA Codex 额度** 未登录 ChatGPT — 运行 `codex login`";case"auth_failed":return"**\uD83D\uDCCA Codex 额度** 当前不是 ChatGPT 登录 — 请运行 `codex login`";case"rate_limited":return"**\uD83D\uDCCA Codex 额度** API 429 限流,稍后重试";case"network":return`**\uD83D\uDCCA Codex 额度** 拉取失败${$.reason?" — `"+$.reason+"`":""}`}let J=[$.subscriptionType?`**\uD83D\uDCCA Codex 额度** · ChatGPT ${$.subscriptionType}`:"**\uD83D\uDCCA Codex 额度**"];if($.fiveHour){let Q=[C1($.fiveHour.percent)];if($.fiveHour.resetsAt)Q.push(`重置 ${z0($.fiveHour.resetsAt)}`);J.push(` · ${NJ($.fiveHour.durationMins,"主窗口")} ${Q.join(" · ")}`)}if($.weekly){let Q=[C1($.weekly.percent)];if($.weekly.resetsAt)Q.push(`重置 ${z0($.weekly.resetsAt)}`);J.push(` · ${NJ($.weekly.durationMins,"次窗口")} ${Q.join(" · ")}`)}return J.length===1?"**\uD83D\uDCCA Codex 额度** _无数据_":J.join(`
|
|
94
|
+
`)}function KA($){if($===void 0)return"**\uD83D\uDCCA GLM 额度** _加载中…_";switch($.state){case"no_credentials":return"**\uD83D\uDCCA GLM 额度** 未配置 `ANTHROPIC_AUTH_TOKEN` — 检查 ~/.claude/settings.json";case"not_glm":return"**\uD83D\uDCCA GLM 额度** 非 GLM 后端 — ANTHROPIC_BASE_URL 不是 bigmodel / z.ai";case"rate_limited":return"**\uD83D\uDCCA GLM 额度** API 限流,稍后重试";case"network":return`**\uD83D\uDCCA GLM 额度** 拉取失败${$.reason?" — `"+$.reason+"`":""}`}let Z=$.level?$.level.charAt(0).toUpperCase()+$.level.slice(1):"",Q=[Z?`**\uD83D\uDCCA GLM 额度** · ${Z} 套餐`:"**\uD83D\uDCCA GLM 额度**"];if($.fiveHour){let Y=[C1($.fiveHour.percent)];if($.fiveHour.resetsAt)Y.push(`重置 ${z0($.fiveHour.resetsAt)}`);Q.push(` · 5h 窗口 ${Y.join(" · ")}`)}if($.weekly){let Y=[C1($.weekly.percent)];if($.weekly.resetsAt)Y.push(`重置 ${z0($.weekly.resetsAt)}`);Q.push(` · 周额度 ${Y.join(" · ")}`)}if($.monthly){let Y=[C1($.monthly.percent)];if(typeof $.monthly.used==="number"&&typeof $.monthly.total==="number")Y.push(`${$.monthly.used}/${$.monthly.total}`);if($.monthly.resetsAt)Y.push(`重置 ${z0($.monthly.resetsAt)}`);Q.push(` · 月度工具 ${Y.join(" · ")}`)}return Q.length===1?"**\uD83D\uDCCA GLM 额度** _无数据_":Q.join(`
|
|
95
|
+
`)}function C1($){return typeof $==="number"&&Number.isFinite($)?`${Math.round($)}%`:"MISS"}function NJ($,Z){if(!$||$<=0)return Z;if($%1440===0)return`${$/1440}d`;if($%60===0)return`${$/60}h`;return`${$}m`}function BA($){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 RA($){if(!$)return["**负载** _n/a_","**内存** _n/a_",`**服务** ${x2} _n/a_`].join(`
|
|
96
|
+
`);let Z=[];if($.cpu){let{cores:J,load1:Q,load5:Y,load15:H}=$.cpu;Z.push(`**负载** ${Q.toFixed(2)} / ${Y.toFixed(2)} / ${H.toFixed(2)} (${J}核)`)}else Z.push("**负载** _n/a_");if($.mem)Z.push(`**内存** ${$.mem.percent}% (${SJ($.mem.usedBytes)}/${SJ($.mem.totalBytes)})`);else Z.push("**内存** _n/a_");if($.servicesError)Z.push(`**服务** ${x2} _${$.servicesError}_`);else if($.services.length===0)Z.push(`**服务** ${x2} _无_`);else{Z.push(`**服务** ${x2} (${$.services.length})`);for(let J of $.services){let Q=qA[J.active]??"·",Y=J.lastActiveAgoSec,H=J.stateAgoSec,W=[J.active];if(J.active==="active"){if(H!=null)W.push(`已运行 ${b2(H*1000)}`)}else if(J.active==="inactive"||J.active==="failed"){if(Y!=null)W.push(`上次活跃 ${b2(Y*1000)}前`);else W.push("从未启动");if(H!=null){let X=J.active==="failed"?"已挂":"已停";W.push(`${X} ${b2(H*1000)}`)}}else if(H!=null)W.push(`已 ${b2(H*1000)}`);Z.push(` · ${Q} \`${J.name}\` · ${W.join(" · ")}`)}}return Z.join(`
|
|
97
|
+
`)}function PA($){let Z=$.peers??[];if(Z.length===0)return"_无_";return Z.map((J)=>{let Q=GA[J.status]??"·",Y=_A[J.status]??J.status,H=J.uptimeMs!=null&&J.uptimeMs>0?` · ${b2(J.uptimeMs)}`:"",W=J.isCurrent?" · 当前":"";return` · ${Q} \`${J.name}\` · ${Y}${H}${W}`}).join(`
|
|
98
|
+
`)}function Y9($,Z=M.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:PA($)}]}}function LA($){let Z=$.model?`${$.model}${$.effort?`/${$.effort}`:""}`:$.effort?`强度 ${$.effort}`:"未就绪";return[`**\uD83E\uDD16 当前模型${$.provider==="claude"?` (${D7($.provider)})`:""}** \`${Z}\``,...$.worktreeInstructionNotice?[$.worktreeInstructionNotice]:[]].join(`
|
|
99
|
+
`)}function H9($,Z=M.consoleCurrentModel){return{tag:"markdown",element_id:Z,content:LA($)}}function W9($,Z=M.consoleHost){let J=BA($);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:RA($)}]}}function DA($){if($===void 0)return"**\uD83D\uDCCA 额度** _加载中…_";switch($.state){case"no_credentials":return"**\uD83D\uDCCA 额度** 未配置凭据 — 检查 config.toml [token_source.*]";case"not_applicable":return"**\uD83D\uDCCA 额度** —(该来源无额度查询)";case"rate_limited":return"**\uD83D\uDCCA 额度** API 限流,稍后重试";case"network":return`**\uD83D\uDCCA 额度** 拉取失败${$.reason?" — `"+$.reason+"`":""}`}let J=[$.planLabel?`**\uD83D\uDCCA 额度** · ${$.planLabel}`:"**\uD83D\uDCCA 额度**"];for(let Q of $.windows){let Y=[C1(Q.percent)];if(typeof Q.used==="number"&&typeof Q.total==="number")Y.push(`${Q.used}/${Q.total}`);if(Q.resetsAt)Y.push(`重置 ${z0(Q.resetsAt)}`);J.push(` · ${Q.label} ${Y.join(" · ")}`)}return J.length===1&&!$.planLabel?"**\uD83D\uDCCA 额度** _无数据_":J.join(`
|
|
100
|
+
`)}function f2($){let Z=$.unifiedUsage!==void 0?DA($.unifiedUsage):$.provider==="claude"?KA($.glmUsage):yJ($.usage);return{tag:"markdown",element_id:M.consoleUsage,content:Z}}function xJ($,Z){return[H9($,Z),Y9($),W9($.sysinfo),f2($)]}function q7($){let{sessionName:Z,status:J}=$,Q=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:Q},body:{elements:xJ($)}}}function B7($){return f1($.sessionName,{tag:"collapsible_panel",element_id:M.modelPanel,header:{title:{tag:"plain_text",content:"选择账号"}},expanded:!0,elements:[{tag:"markdown",content:`当前: ${o0($.currentDisplay??"未选择")}
|
|
101
|
+
选账号进入模型选择。`},...$.providers.map((Z)=>jA(Z,$.panelId))]})}function jA($,Z){if(!$.enabled)return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`⚙️ **${r$($.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=[$.selected?"当前账号":"",`${$.modelCount} 个模型`].filter(Boolean).join(" · ");return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`**${r$($.display)}**
|
|
102
|
+
${J}`}]},{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 R7($){return f1($.sessionName,bJ($))}function P7($){return f1($.sessionName,A9($))}function X9($){return f1($.sessionName,CJ($),"green")}function f1($,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 bJ($){let Z=MA($.models,$.panelId);return{tag:"collapsible_panel",element_id:M.modelPanel,header:{title:{tag:"plain_text",content:"选择模型"}},expanded:!0,elements:[{tag:"markdown",content:[`当前: ${fJ($.currentModel,$.currentEffort)}`,"选模型进入 effort 选择。"].join(`
|
|
103
103
|
`)},...$.models.length?Z:[{tag:"markdown",content:"_未返回可用模型列表_"}],{tag:"button",text:{tag:"plain_text",content:"➕ 补录模型"},type:"default",width:"default",behaviors:[{type:"callback",value:{kind:"model_custom_prompt",panel_id:$.panelId,...$.models[0]?.sourceId?{source_id:$.models[0].sourceId}:{}}}]}]}}function V9($,Z="cancelled"){return f1($,{tag:"collapsible_panel",element_id:M.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:Z==="stale"?"_此补录面板已失效 — 当前等待中的补录未受影响_":"_已取消补录 — 列表未改动_"}]},"grey")}function L7($,Z,J){return f1($,{tag:"collapsible_panel",element_id:M.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:[`**直接回复模型名补录到 ${Z}**(列表外的模型,端点会先校验真伪)`,"_裸词命令(hi/stop/model 等)不受影响_"].join(`
|
|
104
|
-
`)},{tag:"button",text:{tag:"plain_text",content:"取消"},type:"default",width:"default",behaviors:[{type:"callback",value:{kind:"model_panel_cancel",panel_id:J}}]}]},"blue")}function z9($,Z,J){return{tag:"collapsible_panel",element_id:M.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:$?`✅ \`${Z}\` 已加入列表`:`❌ \`${Z}\` 未加入 — ${J}`}]}}function A9($){return{tag:"collapsible_panel",element_id:M.modelPanel,header:{title:{tag:"plain_text",content:"选择 effort"}},expanded:!0,elements:[{tag:"markdown",content:[`模型: ${
|
|
105
|
-
`)},...$.model.efforts.length?$.model.efforts.map((Z)=>
|
|
106
|
-
`)}]}}function
|
|
104
|
+
`)},{tag:"button",text:{tag:"plain_text",content:"取消"},type:"default",width:"default",behaviors:[{type:"callback",value:{kind:"model_panel_cancel",panel_id:J}}]}]},"blue")}function z9($,Z,J){return{tag:"collapsible_panel",element_id:M.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:$?`✅ \`${Z}\` 已加入列表`:`❌ \`${Z}\` 未加入 — ${J}`}]}}function A9($){return{tag:"collapsible_panel",element_id:M.modelPanel,header:{title:{tag:"plain_text",content:"选择 effort"}},expanded:!0,elements:[{tag:"markdown",content:[`模型: ${EA($.model)}`,`当前: ${fJ($.currentModel,$.currentEffort)}`].join(`
|
|
105
|
+
`)},...$.model.efforts.length?$.model.efforts.map((Z)=>UA($.model,Z,$.panelId,$.currentModel,$.currentEffort)):[{tag:"markdown",content:"_该模型未返回可用 effort_"}]]}}function CJ($){return{tag:"collapsible_panel",element_id:M.modelPanel,header:{title:{tag:"plain_text",content:"选择已保存"}},expanded:!0,elements:[{tag:"markdown",content:["**已保存**",o0(wJ($.model,$.effort,$.provider)),r$($.scope)].join(`
|
|
106
|
+
`)}]}}function FA($,Z){if($.enabled===!1)return[{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`⚙️ **${r$($.displayName)}** · 未配置
|
|
107
107
|
${r$($.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 J=$.displayName&&$.displayName!==$.model?`**${r$($.displayName)}**`:`**${o0($.model)}**`,Q=[$.isDefault?`${D7($.provider)} 默认`:"",$.selected?"当前模型":""].filter(Boolean),Y=$.description?`
|
|
108
|
-
`+r$(
|
|
109
|
-
`)+Y}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:$.selected?"primary":"default",behaviors:[{type:"callback",value:
|
|
110
|
-
`)}]},{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
|
|
108
|
+
`+r$(TA($.description,110)):"";return[{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:[J,o0($.model),Q.length?Q.join(" · "):""].filter(Boolean).join(`
|
|
109
|
+
`)+Y}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:$.selected?"primary":"default",behaviors:[{type:"callback",value:OA($,Z)}]}]}]}]}function MA($,Z){let J=[{title:"Codex",models:$.filter((H)=>(H.provider??"codex")==="codex")},{title:"Claude Code 后端",models:$.filter((H)=>H.provider==="claude")}].filter((H)=>H.models.length>0),Q=(H)=>H.flatMap((W)=>FA(W,Z));if(J.length<=1)return Q($);let Y=[];for(let H of J)Y.push({tag:"markdown",content:`**${H.title}**`}),Y.push(...Q(H.models));return Y}function UA($,Z,J,Q,Y){let H=Q===$.model&&Y===Z.effort,W=[Z.isDefault?"默认":"",H?"当前":""].filter(Boolean).join(" · ");return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:[`**${r$(Z.effort)}**`,W,Z.description?r$(Z.description):""].filter(Boolean).join(`
|
|
110
|
+
`)}]},{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 OA($,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 EA($){return $.displayName&&$.displayName!==$.model?`${r$($.displayName)} (${o0($.model)})`:o0($.model)}function fJ($,Z){return o0(wJ($,Z))}function wJ($,Z,J){let Q=J&&J!=="codex"?`${D7(J)} · `:"";if($&&Z)return`${Q}${$}/${Z}`;if($)return`${Q}${$}`;if(Z)return`${Q}${Z}`;return"未选择"}function D7($){return $==="claude"?"Claude":"Codex"}function TA($,Z){return $.length<=Z?$:$.slice(0,Z-1)+"…"}function r$($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function o0($){return"`"+$.replace(/`/g,"\\`")+"`"}function A0($){let Z=[];if(Z.push($.suffix??"✅"),$.durationSec)Z.push(`⏱ ${$.durationSec}s`);if($.outputTokens!=null&&$.outputTokens>0)Z.push(`\uD83D\uDCF6 ${AA($.outputTokens)}`);return{config:{streaming_mode:!1,summary:{content:Z.join(" · ")}}}}var GA,_A,qA;var vJ=N(()=>{_7();N$();GA={idle:"\uD83D\uDFE2",working:"⚙️",awaiting_permission:"\uD83D\uDD10",starting:"\uD83D\uDE80",stopped:"⚪"},_A={idle:"闲",working:"工作中",awaiting_permission:"等审批",starting:"启动中",stopped:"未运行"};qA={active:"\uD83D\uDFE2",activating:"\uD83D\uDE80",reloading:"\uD83D\uDD04",inactive:"⚪",deactivating:"\uD83D\uDFE1",failed:"❌"}});function j7($){let Z=NA($);return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:"\uD83C\uDF3F wt"},template:kA($.notice)},body:{elements:[...$.notice?[SA($.notice)]:[],...Z?[{tag:"markdown",content:Z}]:[],...$.entries.flatMap(yA)]}}}function kA($){if($?.type==="error")return"red";if($?.type==="success")return"green";return"turquoise"}function SA($){let Z=$.type==="error"?"red":$.type==="success"?"green":"grey";return{tag:"markdown",content:$.content.split(`
|
|
111
111
|
`).map((J)=>`<font color='${Z}'>${J||" "}</font>`).join(`
|
|
112
|
-
`)}}function
|
|
112
|
+
`)}}function NA($){let Z=$.hiddenMergedUnmountedCount??0;if(!$.entries.length&&Z===0)return`_无 work/* 分支。发 ${G9("wt name")} 创建。_`;if(Z>0)return`${Z}个已归档分支`;return""}function yA($){let Z=$.error?"出错":$.mounted&&$.dirtyCount&&$.dirtyCount>0?`有未提交改动 ${$.dirtyCount}`:$.state==="merged"?"已合并":$.state==="stale"?"两边都有新改动":$.mounted?"进行中":"未挂载",J=$.duplicateChatCount>1?`群重复 ${$.duplicateChatCount} 个`:$.chatId?"群正常":"无群",Q=[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`**${G9($.slug)}**
|
|
113
113
|
${Z} · ${J}
|
|
114
|
-
${G9($.branch)}`}]}];if($.mounted||$.chatId)Q.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:Q}]}function
|
|
114
|
+
${G9($.branch)}`}]}];if($.mounted||$.chatId)Q.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:Q}]}function w2($){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,G9($.branch),...$.body?[$.body]:[]].join(`
|
|
115
115
|
`)}]}}}function G9($){return"`"+$.replace(/`/g,"\\`")+"`"}function M7($){let Z=$.mode==="fork",J=Z?"分叉":"回退",Q=Z?"temp_fork_select":"temp_back_select",Y=Z?`\uD83D\uDCA1 选择一条「用户输入」,将在临时群从它**之前**创建独立对话分支;选中的输入本身不包含。
|
|
116
116
|
分支与本群共享 cwd 和磁盘文件;只分叉对话历史,不复制或回滚文件,原会话不动。`:`⚠️ 选择一条「用户输入」,将停止本群当前 turn 和后台任务,并从它**之前**创建后续对话分支;选中的输入本身不包含。
|
|
117
|
-
只回退对话历史,不会回滚 cwd 中的文件。`,H=[];if($.notice)H.push({tag:"markdown",content:
|
|
117
|
+
只回退对话历史,不会回滚 cwd 中的文件。`,H=[];if($.notice)H.push({tag:"markdown",content:xA($.notice)});if(!$.entries.length)H.push({tag:"markdown",content:"_当前会话还没有已完成的 turn,无法分叉/回退。_"});else{H.push({tag:"markdown",content:Y});for(let W of $.entries)H.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:5,elements:[{tag:"markdown",content:`**${T7(W.ts)}**
|
|
118
118
|
${O0(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:Q,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 U7($){let Z=[];if(!$.entries.length)Z.push({tag:"markdown",content:`_项目「${$.projectName}」没有可创建分支的历史会话。_`});else{Z.push({tag:"markdown",content:`\uD83D\uDCA1 选择一个历史会话,在**当前群**创建独立对话分支;源会话不动。
|
|
119
119
|
新分支共享当前 cwd 和磁盘文件;只分叉对话历史,不复制或回滚文件。`});for(let J of $.entries)Z.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:5,elements:[{tag:"markdown",content:`**${T7(J.ts)}**
|
|
120
120
|
${O0(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 O7($){let Z=$.entries.length===0?"(回退范围内未观察到 Write/Edit/FileChange 类文件变更)":$.entries.map((J)=>{let Q=J.body.length>800?J.body.slice(0,800)+`
|
|
@@ -126,82 +126,82 @@ ${Q}`}).join(`
|
|
|
126
126
|
`):$.bindingState==="unchanged"?[`${F7($.message)}`,"",`本群原绑定 ${O0(_9($.previousSessionId))};源会话未修改。`].join(`
|
|
127
127
|
`):[`${F7($.message)}`,"",`后端返回会话 ${O0(_9($.newSessionId))};当前绑定无法确认。`,"请发送 hi 或 rs 检查当前状态,不要把本卡视为成功回执。"].join(`
|
|
128
128
|
`);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:`${Q} ${$.bindingState==="changed"?"已从所选历史创建独立分支":$.bindingState==="prepared"?"已准备从所选历史创建独立分支":$.bindingState==="unchanged"?"历史分支创建失败":"分支结果需要确认"}`},{tag:"markdown",content:[`**所选历史 · ${Z}**`,`**${T7($.selectedTs)}**${H}`,O0(Y),`源会话 ${O0(_9($.sourceSessionId))}`].join(`
|
|
129
|
-
`)},{tag:"markdown",content:W}]}}}function T7($){let Z=new Date($),J=(Q)=>String(Q).padStart(2,"0");return`${J(Z.getMonth()+1)}-${J(Z.getDate())} ${J(Z.getHours())}:${J(Z.getMinutes())}`}function O0($){return"`"+
|
|
129
|
+
`)},{tag:"markdown",content:W}]}}}function T7($){let Z=new Date($),J=(Q)=>String(Q).padStart(2,"0");return`${J(Z.getMonth()+1)}-${J(Z.getDate())} ${J(Z.getHours())}:${J(Z.getMinutes())}`}function O0($){return"`"+hJ($.replace(/`/g,"\\`").replace(/\n/g," "))+"`"}function _9($){let Z=$?.trim()??"";if(!Z)return"MISS";return Z.length>13?`${Z.slice(0,8)}…${Z.slice(-4)}`:Z}function F7($){return hJ($).replace(/\\/g,"\\\\").replace(/([`*_{}\[\]()#+\-.!|>~])/g,"\\$1")}function hJ($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function xA($){let Z=$.type==="error"?"red":"grey";return $.content.split(`
|
|
130
130
|
`).map((J)=>`<font color='${Z}'>${J||" "}</font>`).join(`
|
|
131
|
-
`)}function
|
|
131
|
+
`)}function gJ($){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(`
|
|
132
132
|
---
|
|
133
|
-
`);return""}function k7($,Z){if(!Z||typeof Z!=="object")return[];if($==="FileChange"||$==="fileChange"){if(!Array.isArray(Z.changes))return[];return Z.changes.filter((Q)=>Q&&typeof Q==="object").map((Q)=>({tool:$,path:typeof Q.path==="string"&&Q.path?Q.path:"?",body:typeof Q.diff==="string"?Q.diff:typeof Q.unified_diff==="string"?Q.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:
|
|
133
|
+
`);return""}function k7($,Z){if(!Z||typeof Z!=="object")return[];if($==="FileChange"||$==="fileChange"){if(!Array.isArray(Z.changes))return[];return Z.changes.filter((Q)=>Q&&typeof Q==="object").map((Q)=>({tool:$,path:typeof Q.path==="string"&&Q.path?Q.path:"?",body:typeof Q.diff==="string"?Q.diff:typeof Q.unified_diff==="string"?Q.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:gJ(Z)}]}function N7($){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?[fA($.notice)]:[],{tag:"markdown",element_id:M.tasklistPanel,content:bA($)},CA($)]}}}function bA($){let Z=[`项目:${S7($.projectName)}`,`清单:${S7($.tasklistName)}`];if(!$.binding)return Z.push("","未启用"),Z.join(`
|
|
134
134
|
`);if(Z.push("","已启用"),Z.push(`GUID:${S7($.binding.guid)}`),$.binding.url)Z.push(`链接:${$.binding.url}`);if($.confirmDelete)Z.push(""),Z.push("<font color='red'>确认后会删除该清单以及清单内所有任务。</font>");return Z.join(`
|
|
135
|
-
`)}function
|
|
136
|
-
`).map((J)=>`<font color='${Z}'>${
|
|
137
|
-
`)}}function S7($){return"`"+$.replace(/`/g,"\\`")+"`"}function
|
|
135
|
+
`)}function CA($){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 fA($){let Z=$.type==="error"?"red":$.type==="success"?"green":"grey";return{tag:"markdown",content:$.content.split(`
|
|
136
|
+
`).map((J)=>`<font color='${Z}'>${wA(J)||" "}</font>`).join(`
|
|
137
|
+
`)}}function S7($){return"`"+$.replace(/`/g,"\\`")+"`"}function wA($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}var IJ=N(()=>{N$()});import{createHash as vA}from"node:crypto";function x7($){let Z=[{tag:"markdown",element_id:M.agentIdentityPanel,content:["**全局 Agent 身份**","每个 Token Source 的每个模型都是一个可直接执行任务的完整 Agent;具体约束完全来自主 Agent 传入的 prompt。",`目录第 ${$.page+1}/${$.totalPages} 页`].join(`
|
|
138
138
|
`)}];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)=>`- **${a0(J.display)}**:${a0(J.reason)}`).join(`
|
|
139
|
-
`)}]});return Z.push(...$.catalog.map(
|
|
140
|
-
`)}]}}function q9($){let Z=$.workers.filter((H)=>H.status==="completed").length,J=$.workers.filter((H)=>H.status==="failed").length,Q=$.workers.filter((H)=>H.status==="needs_input").length,Y=$.status==="completed"?"✅ Agent 完成":$.status==="failed"?"❌ Agent 失败":$.status==="cancelled"?"\uD83D\uDED1 Agent 已取消":$.status==="needs_input"?"❓ 等待主 Agent 输入":$.status==="queued"?"⏳ Agent 排队中":"⏳ Agent 运行中";return{tag:"markdown",element_id:M.agentRunFooter,content:`${Y} · 完成 ${Z}/${$.workers.length} · 等待 ${Q} · 失败 ${J}`}}function B9($){return`aw_${
|
|
139
|
+
`)}]});return Z.push(...$.catalog.map(IA),cA($)),{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:"\uD83E\uDDE0 agents"},template:"purple"},body:{elements:Z}}}function b7($){let Z=R9($.workers.length);return{schema:"2.0",config:{update_multi:!0,streaming_mode:!uA($.status),summary:{content:v2($)}},header:{title:{tag:"plain_text",content:`\uD83E\uDDE0 agent · depth ${$.depth}`},template:$.status==="failed"?"red":$.status==="completed"?"green":$.status==="needs_input"?"orange":"purple"},body:{elements:[{tag:"collapsible_panel",header:{title:{tag:"plain_text",content:$.parentKind==="follow_up"?"续跑 prompt":"任务 prompt"}},expanded:!1,elements:[{tag:"markdown",content:pA($.prompt)}]},...$.workers.map((J)=>K9(J,Z)),q9($)]}}}function K9($,Z=uJ){let J=mA($),Q=[`**${a0(J)}**`];if($.pendingInput){Q.push("","**等待主 Agent 回答**");for(let Y of $.pendingInput.questions)if(Q.push(`- ${a0(Y.question)}`),Y.options.length)Q.push(` 选项:${Y.options.map((H)=>t$(H.label)).join(" / ")}`);Q.push(`request: ${t$($.pendingInput.requestId)}`)}if($.output)Q.push("",lA($$($.output),Z));if($.error)Q.push("",`<font color='red'>${$$($.error)}</font>`);if(!$.output&&!$.error&&!$.pendingInput)Q.push("",$.status==="completed"?"_Agent 已完成,没有正文输出。_":"_等待结果…_");if($.steps.length){Q.push("","**最近动作**");for(let Y of $.steps.slice(-8)){let H=Y.phase==="completed"?"✓":Y.phase==="started"?"→":"·";Q.push(`- ${H} ${t$(Y.tool)} ${a0(mJ(Y.detail,180))}`)}}if(Q.push("",`${t$($.tokenSourceId)} · ${t$($.model)} · ${t$($.effort)}`),$.sessionId)Q.push(`session: ${t$($.sessionId)}`);return{tag:"collapsible_panel",element_id:B9($.identityId),header:{title:{tag:"plain_text",content:`${J} · ${mJ($.identityName,48)}`}},expanded:$.status==="failed"||$.status==="needs_input",elements:[{tag:"markdown",content:Q.join(`
|
|
140
|
+
`)}]}}function q9($){let Z=$.workers.filter((H)=>H.status==="completed").length,J=$.workers.filter((H)=>H.status==="failed").length,Q=$.workers.filter((H)=>H.status==="needs_input").length,Y=$.status==="completed"?"✅ Agent 完成":$.status==="failed"?"❌ Agent 失败":$.status==="cancelled"?"\uD83D\uDED1 Agent 已取消":$.status==="needs_input"?"❓ 等待主 Agent 输入":$.status==="queued"?"⏳ Agent 排队中":"⏳ Agent 运行中";return{tag:"markdown",element_id:M.agentRunFooter,content:`${Y} · 完成 ${Z}/${$.workers.length} · 等待 ${Q} · 失败 ${J}`}}function B9($){return`aw_${vA("sha256").update($).digest("hex").slice(0,16)}`}function R9($){let Z=Math.max(1,Math.floor($));return Math.min(uJ,Math.max(gA,Math.floor(hA/Z)))}function v2($){let Z=$.workers.filter((Q)=>Q.status==="completed").length;return`${$.status==="completed"?"✅":$.status==="failed"?"❌":$.status==="cancelled"?"\uD83D\uDED1":$.status==="needs_input"?"❓":"⏳"} agent · ${Z}/${$.workers.length} · depth ${$.depth}`}function IA($){let J=$.status==="ready"?"ready":`${$.status}: ${$.reason??"MISS"}`;return{tag:"markdown",content:[`**${a0($.displayName)}** ${$.sourceDefault?"· default":""}`,`${t$($.id)}
|
|
141
141
|
${t$($.model)} · 默认 ${t$($.defaultEffort)} · ${a0(J)}`].join(`
|
|
142
|
-
`)}}function
|
|
142
|
+
`)}}function cA($){return{tag:"column_set",columns:[y7("上一页",{kind:"agent_identity_page",panel_id:$.panelId,page:Math.max(0,$.page-1)}),y7("刷新",{kind:"agent_identity_page",panel_id:$.panelId,page:$.page}),y7("下一页",{kind:"agent_identity_page",panel_id:$.panelId,page:Math.min($.totalPages-1,$.page+1)})]}}function y7($,Z){return{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:$},type:"default",behaviors:[{type:"callback",value:Z}]}]}}function mA($){switch($.status){case"completed":return"✅ 完成";case"failed":return"❌ 失败";case"cancelled":return"\uD83D\uDED1 取消";case"needs_input":return"❓ 等待输入";case"running":return"⏳ 运行中";default:return"⏳ 排队中"}}function uA($){return $==="completed"||$==="failed"||$==="cancelled"}function pA($){let Z=$$($);if(Z.length<=cJ)return Z;let J="_卡片 prompt 预览已截断;完整 prompt 已原样交给 Agent 并持久化。_";return`${Z.slice(0,cJ-J.length-2)}
|
|
143
143
|
|
|
144
|
-
${J}`}function
|
|
144
|
+
${J}`}function lA($,Z){if($.length<=Z)return $;let J="_卡片输出已截断,完整结果由 CLI/API 返回。_";return`${$.slice(0,Math.max(0,Z-J.length-2))}
|
|
145
145
|
|
|
146
|
-
${J}`}function t$($){return"`"+$.replace(/`/g,"\\`")+"`"}function a0($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function
|
|
147
|
-
`)}function T0($,Z,J,Q){let Y=
|
|
148
|
-
`))>=0){let J=this.buf.slice(0,Z).trim();if(this.buf=this.buf.slice(Z+1),!J)continue;let Q;try{Q=JSON.parse(J)}catch{continue}if(!Object.prototype.hasOwnProperty.call(Q,"id"))continue;let Y=this.pending.get(Q.id);if(!Y)continue;if(this.pending.delete(Q.id),clearTimeout(Y.timer),Q.error)Y.reject(Error(JSON.stringify(Q.error)));else Y.resolve(Q.result)}}request($,Z,J=
|
|
149
|
-
`,(X)=>{if(!X)return;let V=this.pending.get(Q);if(!V)return;this.pending.delete(Q),clearTimeout(V.timer),V.reject(Error(`codex app-server write failed for ${$}: ${X.message}`))})}catch(X){this.pending.delete(Q),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((Q)=>setTimeout(()=>Q(!1),$))]))return;if(!this.proc.kill("SIGKILL"))throw Error("codex app-server rejected SIGKILL");if(!await Promise.race([this.exitPromise.then(()=>!0),new Promise((Q)=>setTimeout(()=>Q(!1),$))]))throw Error(`codex app-server did not exit after SIGKILL (${$}ms)`)}}function L9($,Z){return new Promise((J,Q)=>{let Y=setTimeout(()=>Q(Error(`timeout after ${Z}ms`)),Z);$.then((H)=>{clearTimeout(Y),J(H)},(H)=>{clearTimeout(Y),Q(H)})})}function
|
|
146
|
+
${J}`}function t$($){return"`"+$.replace(/`/g,"\\`")+"`"}function a0($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function mJ($,Z){let J=$.replace(/\s+/g," ").trim();return J.length<=Z?J:`${J.slice(0,Z-1)}…`}var cJ=1e4,hA=48000,uJ=8000,gA=512;var pJ=N(()=>{N$()});function t0($){return iA.has($)?$:null}function P9($){if(!$)return null;try{let Z=JSON.parse($);return Z&&typeof Z==="object"?Z:null}catch{return null}}function w1($){return String($?.taskId??$?.id??$?.task_id??"").trim()}function r0($){return String($?.subject??$?.content??"").trim()}function C7($){let Z=$?.status;return Z==="pending"||Z==="in_progress"||Z==="completed"||Z==="deleted"?Z:void 0}function nJ($){return`subj:${$}`}function lJ($){let Z=$.match(/#\s*(\d+)/);return Z?Z[1]:""}function aA($){let Z=r0($);if(!Z)return null;return{id:w1($)||nJ(Z),subject:Z,description:typeof $?.description==="string"?$.description:void 0,activeForm:typeof $?.activeForm==="string"?$.activeForm:void 0,status:C7($)??"pending"}}function f7($,Z,J,Q){if(Z==="TaskList"){let Y=P9(Q),H=Array.isArray(Y?.tasks)?Y.tasks:Array.isArray(Y)?Y:null;if(H===null)return $;let W=[];for(let X of H){let V=aA(X);if(V)W.push(V)}return W}if(Z==="TaskCreate"){let Y=Array.isArray(J?.tasks)?J.tasks:null;if(Y){let A=P9(Q),G=Array.isArray(A?.tasks)?A.tasks:Array.isArray(A)?A:null,_=$;return Y.forEach((q,B)=>{let R=r0(q);if(!R)return;let L=G?.[B],F=L&&w1(L)||lJ(Q??"");_=iJ(_,F,R,q)}),_}let H=P9(Q),W=H?.task??H,X=w1(W)||lJ(Q??""),V=r0(W)||r0(J);if(!V)return $;return iJ($,X,V,J)}if(Z==="TaskUpdate"){let Y=w1(J);if(!Y)return $;let H=C7(J);if(H==="deleted")return $.filter((X)=>X.id!==Y);let W=r0(J);if($.some((X)=>X.id===Y))return $.map((X)=>X.id===Y?{...X,...H?{status:H}:{},...W?{subject:W}:{},...typeof J?.activeForm==="string"?{activeForm:J.activeForm}:{}}:X);return $}if(Z==="TaskGet"){let Y=P9(Q),H=Y?.task??Y,W=w1(H)||w1(J);if(!W)return $;let X=$.find((G)=>G.id===W),V=r0(H)||X?.subject||r0(J);if(!V)return $;let A={id:W,subject:V,description:typeof H?.description==="string"?H.description:X?.description,activeForm:typeof H?.activeForm==="string"?H.activeForm:X?.activeForm,status:C7(H)??X?.status??"pending"};return X?$.map((G)=>G.id===W?A:G):[...$,A]}return $}function iJ($,Z,J,Q){let Y=Z||nJ(J),H={...typeof Q?.activeForm==="string"&&Q.activeForm?{activeForm:Q.activeForm}:{},...typeof Q?.description==="string"&&Q.description?{description:Q.description}:{}};if($.some((W)=>W.id===Y))return $.map((W)=>W.id===Y?{...W,id:Y,subject:J,...H}:W);return[...$,{id:Y,subject:J,status:"pending",...H}]}function w7($){let Z=$.filter((H)=>H.status!=="deleted");if(Z.length===0)return"空";let J=new Map;for(let H of Z){let W=dA[H.status];J.set(W,(J.get(W)??0)+1)}let Y=["进行中","待办","完成"].map((H)=>J.has(H)?`${H} ${J.get(H)}`:"").filter(Boolean).join(" · ");return`${Z.length} 项${Y?` · ${Y}`:""}`}function dJ($,Z){let J=$.filter((W)=>W.status!=="deleted"),Q=[`**待办**: ${J.length} 项`],Y=(W)=>{let X=parseInt(W,10);return Number.isNaN(X)?Number.MAX_SAFE_INTEGER:X},H=[...J].sort((W,X)=>{let V=Y(W.id)-Y(X.id);return V!==0?V:W.id.localeCompare(X.id)});for(let W of H.slice(0,12)){let X=oA[W.status],V=W.status==="in_progress"&&W.activeForm?W.activeForm:W.subject;Q.push(`- ${X} ${V||"(空)"}`)}if(H.length>12)Q.push(`- 还有 ${H.length-12} 项未显示`);if(Z)Q.push(""),Q.push(Z);return Q.join(`
|
|
147
|
+
`)}function T0($,Z,J,Q){let Y=nA[J.name],H=w7(Z),W=`${J.status} \uD83D\uDD27 ${Y}: ${H}`;return{tag:"collapsible_panel",element_id:M.tool($),header:{title:{tag:"plain_text",content:W}},expanded:!1,elements:[{tag:"markdown",content:dJ(Z,Q)}]}}function s0($){return{tag:"collapsible_panel",element_id:M.taskBoardLive,header:{title:{tag:"plain_text",content:`\uD83D\uDCCB 任务总览 · ${w7($)}`}},expanded:!0,elements:[{tag:"markdown",content:dJ($)}]}}var iA,nA,dA,oA;var oJ=N(()=>{N$();iA=new Set(["TaskCreate","TaskUpdate","TaskList","TaskGet"]);nA={TaskCreate:"创建任务",TaskUpdate:"更新任务",TaskList:"任务列表",TaskGet:"查看任务"},dA={pending:"待办",in_progress:"进行中",completed:"完成",deleted:"已删"},oA={pending:"⬜",in_progress:"\uD83D\uDD04",completed:"✅",deleted:"\uD83D\uDDD1️"}});var C$=N(()=>{N$();rZ();FJ();vJ();IJ();pJ();oJ();r8()});import{spawn as rA}from"node:child_process";class j9{proc;buf="";nextId=1;alive=!0;exitPromise;resolveExit;pending=new Map;constructor(){this.proc=rA($2(),["app-server","--listen","stdio://"],{stdio:["pipe","pipe","pipe"],shell:process.platform==="win32"}),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)z(`usage[codex stderr]: ${J}`)});let $=(Z)=>{if(!this.alive)return;this.alive=!1;for(let[J,Q]of this.pending)clearTimeout(Q.timer),Q.reject(Error(`${Z.message}; pending ${Q.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(`
|
|
148
|
+
`))>=0){let J=this.buf.slice(0,Z).trim();if(this.buf=this.buf.slice(Z+1),!J)continue;let Q;try{Q=JSON.parse(J)}catch{continue}if(!Object.prototype.hasOwnProperty.call(Q,"id"))continue;let Y=this.pending.get(Q.id);if(!Y)continue;if(this.pending.delete(Q.id),clearTimeout(Y.timer),Q.error)Y.reject(Error(JSON.stringify(Q.error)));else Y.resolve(Q.result)}}request($,Z,J=h2){let Q=this.nextId++;return new Promise((Y,H)=>{if(!this.alive){H(Error(`codex app-server is not alive; cannot request ${$}`));return}let W=setTimeout(()=>{if(!this.pending.delete(Q))return;H(Error(`codex app-server ${$} timed out after ${J}ms`))},J);this.pending.set(Q,{resolve:Y,reject:H,method:$,timer:W});try{this.proc.stdin.write(JSON.stringify({id:Q,method:$,params:Z})+`
|
|
149
|
+
`,(X)=>{if(!X)return;let V=this.pending.get(Q);if(!V)return;this.pending.delete(Q),clearTimeout(V.timer),V.reject(Error(`codex app-server write failed for ${$}: ${X.message}`))})}catch(X){this.pending.delete(Q),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((Q)=>setTimeout(()=>Q(!1),$))]))return;if(!this.proc.kill("SIGKILL"))throw Error("codex app-server rejected SIGKILL");if(!await Promise.race([this.exitPromise.then(()=>!0),new Promise((Q)=>setTimeout(()=>Q(!1),$))]))throw Error(`codex app-server did not exit after SIGKILL (${$}ms)`)}}function L9($,Z){return new Promise((J,Q)=>{let Y=setTimeout(()=>Q(Error(`timeout after ${Z}ms`)),Z);$.then((H)=>{clearTimeout(Y),J(H)},(H)=>{clearTimeout(Y),Q(H)})})}function tA($){return typeof $==="number"&&isFinite($)?Math.max(0,Math.min(100,$)):null}function D9($){if(!$)return null;return{percent:tA($.usedPercent),resetsAt:typeof $.resetsAt==="number"?new Date($.resetsAt*1000):null,durationMins:typeof $.windowDurationMins==="number"?$.windowDurationMins:null}}function sA($){let Z=D9($?.primary),J=D9($?.secondary),Q=(H)=>H?.durationMins!=null&&H.durationMins>0&&H.durationMins<=720,Y=(H)=>H?.durationMins!=null&&H.durationMins>720;if(Q(Z)&&Y(J))return{fiveHour:Z,weekly:J};if(Q(J)&&Y(Z))return{fiveHour:J,weekly:Z};if(Y(Z)&&!J)return{fiveHour:null,weekly:Z};if(Y(J)&&!Z)return{fiveHour:null,weekly:J};return{fiveHour:Z,weekly:J}}function eA($){let Z=$?.rateLimitsByLimitId,J=Z&&typeof Z==="object"?Object.entries(Z):$?.rateLimits?[[$.rateLimits.limitId??"codex",$.rateLimits]]:[],Q=[];for(let[Y,H]of J){let{fiveHour:W,weekly:X}=sA(H);if(!W&&!X)continue;Q.push({limitId:Y,limitName:H?.limitName??null,fiveHour:W,weekly:X})}return{buckets:Q,defaultLimitId:$?.rateLimits?.limitId??void 0}}function $G($){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 rJ($){let Z=$G($),J=e0?.state==="ok"?e0.buckets??[]:[],Q=J.filter((Y)=>aJ(Y.fiveHour,D9($?.primary))&&aJ(Y.weekly,D9($?.secondary)));if(J.length>0&&Q.length===0)z(`usage: rate-limit notification matches NO known bucket — possible relabel or new bucket, will resolve on next read. (${Z})`);else if($?.limitId&&Q.length===1&&Q[0].limitId!==$.limitId)z(`usage: rate-limit notification labeled limitId=${$.limitId} but content matches bucket ${Q[0].limitId} (known codex parser fallback relabels; ignoring notification payload)`)}function aJ($,Z){if(!$||!Z)return!$&&!Z;return $.percent===Z.percent&&$.durationMins===Z.durationMins&&$.resetsAt?.getTime()===Z.resetsAt?.getTime()}async function ZG(){let $=new j9;try{await L9($.request("initialize",{clientInfo:{name:"lodestar-usage",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}),h2);let J=(await L9($.request("account/read",{}),h2))?.account;if(!J)return{state:"no_credentials"};if(J.type!=="chatgpt")return{state:"auth_failed"};let Q=await L9($.request("account/rateLimits/read",{}),h2);return tJ(Q,J.planType)}catch(Z){return z(`usage: codex app-server usage failed: ${Z?.message??Z}`),{state:"network",reason:Z?.message??String(Z)}}finally{await $.close()}}function tJ($,Z){let{buckets:J,defaultLimitId:Q}=eA($),Y=J.find((H)=>H.limitId===Q)??J[0];if(!Y)return{state:"network",reason:"empty rate limit response"};return{state:"ok",subscriptionType:Z??Y.limitName??$?.rateLimits?.planType??"chatgpt",fiveHour:Y.fiveHour,weekly:Y.weekly,buckets:J,defaultLimitId:Y.limitId,fetchedAt:Date.now()}}function sJ(){return e0}async function F9(){if(v1)return v1;return v1=ZG().then(($)=>{if(v1=null,$.state==="network")return e0??$;return e0=$,$}).catch(($)=>{return z(`usage: fetchUsage threw: ${$}`),v1=null,e0??{state:"network",reason:String($)}}),v1}function eJ($){return v7??=L9($("account/rateLimits/read",{}),h2).then((Z)=>{let J=tJ(Z);if(J.state==="ok")e0=J;else z(`usage: refresh from connection: ${J.state==="network"?J.reason:J.state}`);return J}).catch((Z)=>{return z(`usage: refresh from connection failed: ${Z?.message??Z}`),null}).finally(()=>{v7=null}),v7}var h2=1e4,e0=null,v1=null,v7=null;var M9=N(()=>{D1();h()});import{readFileSync as JG}from"node:fs";import{homedir as QG}from"node:os";import{join as QQ}from"node:path";function YG(){return process.env.CLAUDE_CONFIG_DIR||QQ(QG(),".claude")}function g7(){try{let $=JG(QQ(YG(),"settings.json"),"utf8"),Z=JSON.parse($)?.env;return Z&&typeof Z==="object"?Z:{}}catch($){return z(`glm-usage: read settings.json env failed: ${$}`),{}}}function U9($){try{let Z=new URL($).hostname.toLowerCase();return Z==="open.bigmodel.cn"||Z==="dev.bigmodel.cn"||Z==="api.z.ai"}catch{return!1}}function HG($){try{let Z=new URL($);return`${Z.protocol}//${Z.host}`}catch{return null}}function WG($){let Z=HG($);return Z&&U9($)?Z:null}function ZQ($){return typeof $==="number"&&isFinite($)?Math.max(0,Math.min(100,$)):null}function JQ($){return typeof $==="number"&&isFinite($)&&$>0?new Date($):null}function XG($){let Z=Array.isArray($?.limits)?$.limits:[],J=Z.filter((G)=>G?.type==="TOKENS_LIMIT"),Q=J.find((G)=>G?.unit===3&&G?.number===5),Y=J.find((G)=>G?.unit===6&&G?.number===1),H=Z.find((G)=>G?.type==="TIME_LIMIT"),W=(G)=>G?{percent:ZQ(G.percentage),resetsAt:JQ(G.nextResetTime)}:null,X=W(Q),V=W(Y),A=H?{percent:ZQ(H.percentage),resetsAt:JQ(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:A,fetchedAt:Date.now()}}async function I7($,Z){let J=$&&Z?{ANTHROPIC_BASE_URL:$,ANTHROPIC_AUTH_TOKEN:Z}:g7(),Q=J.ANTHROPIC_AUTH_TOKEN,Y=J.ANTHROPIC_BASE_URL||"";if(!Q)return{state:"no_credentials"};let H=WG(Y);if(!H)return{state:"not_glm",baseUrl:Y||void 0};let W=`${H}/api/monitor/usage/quota/limit`,X=new AbortController,V=setTimeout(()=>X.abort(),$Q);try{let A=await fetch(W,{headers:{Authorization:Q,"Content-Type":"application/json","Accept-Language":"en-US,en"},signal:X.signal});if(A.status===429)return{state:"rate_limited"};if(!A.ok)return{state:"network",reason:`HTTP ${A.status}`};let G=await A.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 _=G?.data??G;return XG(_)}catch(A){let G=A?.name==="AbortError"?`timeout ${$Q}ms`:A?.message??String(A);return z(`glm-usage: quota/limit fetch failed: ${G}`),{state:"network",reason:G}}finally{clearTimeout(V)}}async function c7(){if(h1)return h1;return h1=I7().then(($)=>{if(h1=null,$.state==="network")return h7??$;return h7=$,$}).catch(($)=>{return z(`glm-usage: fetchGlmUsage threw: ${$}`),h1=null,h7??{state:"network",reason:String($)}}),h1}var $Q=1e4,h7=null,h1=null;var O9=N(()=>{h()});function YQ($){let Z=[];for(let J of $.matchAll(VG)){let Q=J[1]?.trim();if(Q)Z.push(Q)}return Z}function E9($,Z=process.platform){if(Z!=="win32")return $;let J=zG.exec($);if(!J)return $;return`${J[1].toUpperCase()}:\\`+$.slice(J[0].length).replace(/\//g,"\\")}var VG,zG;var m7=N(()=>{VG=/\[\[send:[ \t]*([^\n]*?)[ \t]*\]\]/g;zG=/^\/([a-zA-Z])\//});function XQ($){if(HQ.test($))return{marker:"start",body:$.replace(HQ,"")};if(WQ.test($))return{marker:"end",body:$.replace(WQ,"")};return{marker:"none",body:$}}var HQ,WQ;var VQ=N(()=>{HQ=/^>{3,}[ \t]?/,WQ=/^<{3,}[ \t]?/});async function zQ($,Z,J,Q,Y){let{marker:H,body:W}=XQ(Z);if(H==="start"){if($.multiMsgBuffer!==null&&$.multiMsgBuffer.length>0)p7($,"reopen");return $.multiMsgBuffer=[],u7($,W,J,Q,Y),!0}if(H==="end"){if($.multiMsgBuffer===null){if(W.trim()||J.length)return!1;return z(`session "${$.sessionName}": end marker without active multi-msg buffer, ignoring`),!0}u7($,W,J,Q,Y);let{multiMsgBuffer:X,multiMsgReactions:V}=$;return $.multiMsgBuffer=null,$.multiMsgReactions=new Map,await GG($,X,V),!0}if($.multiMsgBuffer!==null)return u7($,Z,J,Q,Y),!0;return!1}function u7($,Z,J,Q,Y){if(Z.trim()||J.length)$.multiMsgBuffer.push({text:Z,files:J,userOpenId:Q,msgId:Y});if(Y)AG($,Y)}function AG($,Z){$.multiMsgReactions.set(Z,""),(async()=>{let J=await T$(Z,"Pin");if(!J)return;if($.multiMsgReactions.has(Z))$.multiMsgReactions.set(Z,J);else j$(Z,J)})()}async function GG($,Z,J){for(let[W,X]of J)if(X)j$(W,X);let Q=Z.filter((W)=>W.text.trim()||W.files.length);if(Q.length===0){z(`session "${$.sessionName}": multi-msg flush with empty buffer, not sent`),await T($.chatId,"⚠️ 多条消息缓冲为空,未发送(只收到标记没有正文)。");return}let Y=Q.map((W)=>{return(W.files.length?W.files.map((V)=>`[file: ${V}]`).join(" ")+`
|
|
150
150
|
`:"")+W.text}).join(`
|
|
151
151
|
|
|
152
|
-
`),H=Q[Q.length-1];z(`session "${$.sessionName}": multi-msg flush ${Q.length} segment(s) → 1 turn`),await $.onUserMessage(Y,[],H.userOpenId,H.msgId)}function p7($,Z){if($.multiMsgBuffer===null)return;let J=$.multiMsgBuffer.length;z(`session "${$.sessionName}": clear multi-msg buffer (${Z}): ${J} segment(s)`);for(let[Q,Y]of $.multiMsgReactions){if(Y)j$(Q,Y);T$(Q,"CrossMark")}$.multiMsgBuffer=null,$.multiMsgReactions=new Map}var VQ=N(()=>{r();h();WQ()});import{mkdtemp as VG,rm as zG,writeFile as AG}from"node:fs/promises";import{createRequire as GG}from"node:module";import{tmpdir as _G}from"node:os";import{join as zQ}from"node:path";function jG($){let Z=KQ.get($);if(Z)return Z;let{liteAdaptor:J}=Z1("mathjax-full/js/adaptors/liteAdaptor.js"),{RegisterHTMLHandler:Q}=Z1("mathjax-full/js/handlers/html.js"),{mathjax:Y}=Z1("mathjax-full/js/mathjax.js"),{TeX:H}=Z1("mathjax-full/js/input/tex.js"),{AllPackages:W}=Z1("mathjax-full/js/input/tex/AllPackages.js"),{SVG:X}=Z1("mathjax-full/js/output/svg.js"),V=J({fontSize:$});Q(V);let A=Y.document("",{InputJax:new H({packages:W}),OutputJax:new X({fontCache:"none"})}),G={adaptor:V,doc:A};return KQ.set($,G),G}function qQ($,Z){let J=Number.parseFloat($??"");if(!Number.isFinite(J)||J<=0)throw Error(`MathJax SVG missing valid ${Z}`);return J}function FG($){return $.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function MG($,Z=n7,J=!0){try{let Q=Z*KG,{adaptor:Y,doc:H}=jG(Z),W=H.convert($,{display:J,em:Z,ex:Q,containerWidth:80*Z}),X=Y.outerHTML(W);if(/data-mjx-error=|mjx-merror/.test(X)){let M$=X.match(/data-mjx-error="([^"]+)"/)?.[1]??"MathJax parse error";throw Error(M$)}let V=X.indexOf("<svg"),A=X.lastIndexOf("</svg>");if(V<0||A<0)throw Error("MathJax returned no SVG");let G=X.slice(V,A+6),_=G.match(/^<svg\b[^>]*>/)?.[0];if(!_)throw Error("MathJax returned malformed SVG root");let q=qQ(_.match(/\bwidth="([\d.]+)ex"/)?.[1],"width"),B=qQ(_.match(/\bheight="([\d.]+)ex"/)?.[1],"height"),R=_.match(/\bviewBox="([^"]+)"/)?.[1];if(!R)throw Error("MathJax SVG missing viewBox");let L=R.trim().split(/[\s,]+/).map(Number);if(L.length!==4||L.some((M$)=>!Number.isFinite(M$))||L[2]<=0||L[3]<=0)throw Error("MathJax SVG has invalid viewBox");let[F,U,P,j]=L,k=/<text\b/.test(G)?LG:0,C=`${F} ${U} ${P+k} ${j}`,x=q*Q,c=k*(x/P),v=Math.max(1,Math.ceil(x+c)),g=Math.max(1,Math.ceil(B*Q)),O=qG-l7*2,T=Math.min(1,O/v),m=Math.max(1,Math.round(v*T)),u=Math.max(1,Math.round(g*T));if(T<1&&u<BG)throw Error(`formula would be unreadable after width cap (${m}x${u})`);let S=m+l7*2,y=u+GQ*2,n=G.slice(_.length,-6).replace(/currentColor/g,AQ).replace(/font-family="serif"/g,`font-family="${DG}"`);return{svg:[`<svg xmlns="http://www.w3.org/2000/svg" width="${S}" height="${y}" viewBox="0 0 ${S} ${y}" style="color:${AQ}">`,`<rect x="0" y="0" width="${S}" height="${y}" rx="6" fill="${LQ}"/>`,`<svg x="${l7}" y="${GQ}" width="${m}" height="${u}" viewBox="${FG(C)}" preserveAspectRatio="xMidYMid meet">`,n,"</svg>","</svg>"].join(""),width:S,height:y}}catch(Q){return z(`math-render: TeX→SVG failed for ${$.slice(0,80)}…: ${Q}`),null}}function UG($,Z=n7,J=!0){let Q=MG($,Z,J);if(!Q)return null;try{let{Resvg:Y}=Z1("@resvg/resvg-js"),W=new Y(Q.svg,{background:LQ,fitTo:{mode:"original"},shapeRendering:2,textRendering:1,font:{loadSystemFonts:!0,serifFamily:_Q,sansSerifFamily:_Q}}).render().asPng(),X=new DataView(W.buffer,W.byteOffset,W.byteLength),V=X.getUint32(16),A=X.getUint32(20);if(V!==Q.width||A!==Q.height)throw Error(`PNG dimensions ${V}x${A} != SVG ${Q.width}x${Q.height}`);return{png:W,width:V,height:A}}catch(Y){return z(`math-render: SVG→PNG failed for ${$.slice(0,80)}…: ${Y}`),null}}function OG($){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 BQ($,Z){let J=[],Q=(G,_,q)=>{let B=G[0],R=_.trim();if(!R)return;J.push({start:Z+G.index,end:Z+G.index+B.length,tex:R,raw:B,display:q})},Y,H=/(?<!\\)\$\$([\s\S]+?)(?<!\\)\$\$|\\\[([\s\S]+?)\\\]/g;while((Y=H.exec($))!==null)Q(Y,Y[1]??Y[2]??"",!0);let W=/\\\(([\s\S]+?)\\\)/g;while((Y=W.exec($))!==null)Q(Y,Y[1]??"",!1);let X=/(?<![\\$])\$(?!\$)([^$\n]+?)(?<![\\$])\$(?!\$)/g;while((Y=X.exec($))!==null){let G=(Y[1]??"").trim();if(OG(G))Q(Y,G,!1)}J.sort((G,_)=>G.start-_.start||_.end-G.end);let V=[],A=-1;for(let G of J){if(G.start<A)continue;V.push(G),A=G.end}return V}function DQ($){let Z=f8($),J=[],Q=0;for(let Y of Z){if(Q<Y.start)J.push(...BQ($.slice(Q,Y.start),Q));Q=Math.max(Q,Y.end)}if(Q<$.length)J.push(...BQ($.slice(Q),Q));return J}function EG($){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,Q)=>{if(RQ[Q])return RQ[Q];if(Q==="times")return"×";if(Q==="cdot")return"·";if(Q==="div")return"÷";if(Q==="pm")return"±";if(Q==="leq"||Q==="le")return"≤";if(Q==="geq"||Q==="ge")return"≥";if(Q==="neq"||Q==="ne")return"≠";if(Q==="approx")return"≈";if(Q==="sim")return"~";if(Q==="infty")return"∞";if(Q==="partial")return"∂";if(Q==="nabla")return"∇";if(Q==="sqrt")return"√";if(Q==="to")return"→";return J}),/\\/.test(Z))return null;if(Z=Z.replace(/([_^])\{([^{}]+)\}/g,(J,Q,Y)=>Y.length===1?`${Q}${Y}`:`${Q}(${Y})`),Z=Z.replace(/√\{([^{}]+)\}/g,"√($1)"),/[{}]/.test(Z))return null;return Z}function NG($){let Z=PQ.get($);if(Z!==void 0)return Z;return Z=kG++,PQ.set($,Z),Z}function yG($,Z){return`${PG}\x00${NG(Z)}\x00${$}`}function xG($){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 bG($,Z){let J=yG($,Z),Q=$1.get(J);if(Q)return Q;let Y=i7.get(J);if(Y)return Y;let H=(async()=>{let W=UG($,n7,!0);if(!W)return null;let X=null;try{X=await VG(zQ(_G(),"lodestar-math-"));let V=zQ(X,`formula-${xG($)}.png`);await AG(V,W.png);let A=await Z(V,{tex:$,width:W.width,height:W.height});if(!A)return z(`math-render: upload returned no image key for ${$.slice(0,80)}…`),null;let G={key:A,width:W.width,height:W.height};if($1.has(J))$1.delete(J);$1.set(J,G);while($1.size>SG){let _=$1.keys().next().value;if(typeof _!=="string")break;$1.delete(_)}return G}catch(V){return z(`math-render: upload failed for ${$.slice(0,80)}…: ${V}`),null}finally{if(X)try{await zG(X,{recursive:!0,force:!0})}catch(V){z(`math-render: temp cleanup failed for ${X}: ${V}`)}}})();i7.set(J,H);try{return await H}finally{i7.delete(J)}}function CG($,Z,J){let Q=$.width<=RG;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:Q?"crop_center":"fit_horizontal",...Q?{size:`${$.width}px ${$.height}px`}:{},preview:!1}}}async function jQ($,Z={}){let J=DQ($);if(!J.length)return{blocks:[{type:"markdown",text:$}],formulaCount:0,renderedImageCount:0};let Q=Z.uploader??TG,Y=await Promise.all(J.map(async(G)=>{if(!G.display){let _=EG(G.tex);if(_!==null)return{unicode:_,uploaded:null}}return{unicode:null,uploaded:await bG(G.tex,Q)}})),H=[],W="",X=0,V=0,A=()=>{if(!W)return;if(W.trim())H.push({type:"markdown",text:W});W=""};for(let G=0;G<J.length;G++){let _=J[G],q=Y[G];if(W+=$.slice(X,_.start),q.unicode!==null){W+=q.unicode,X=_.end;continue}let B=q.uploaded;if(!B){W+=_.raw,X=_.end;continue}A(),H.push(CG(B,_,V++)),X=_.end}if(W+=$.slice(X),A(),!H.length)H.push({type:"markdown",text:$});return{blocks:H,formulaCount:J.length,renderedImageCount:V}}function d7($){return DQ($).length>0}var Z1,KG=0.5,n7=22,AQ="#1F2329",LQ="#F7F8FA",l7=12,GQ=8,qG=720,BG=14,RG=278,PG="v4-native-cjk-tail-pad",LG=1100,_Q,DG="Noto Sans CJK SC, Noto Sans CJK JP, Microsoft YaHei, PingFang SC, Arial Unicode MS, sans-serif",KQ,RQ,TG=async($)=>{let{uploadImageKey:Z}=await Promise.resolve().then(() => (r(),Z$));return Z($)},PQ,kG=1,$1,i7,SG=512;var FQ=N(()=>{h();Z1=GG(import.meta.url),_Q=process.platform==="win32"?"Microsoft YaHei":process.platform==="darwin"?"PingFang SC":"Noto Sans CJK SC",KQ=new Map;RQ={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:"Ω"};PQ=new WeakMap,$1=new Map,i7=new Map});import{isAbsolute as wG}from"node:path";function B$($){if($?.planLiveInserted)return M.planLive;return $?.taskLiveInserted?M.taskBoardLive:M.footer}function vG($){return $==="ImageGeneration"||$==="imageGeneration"}function hG($,Z,J){if(J||!vG($))return null;let Q=E9(Z.trim());return wG(Q)?Q:null}function gG($){if($==="Read")return"read";if($==="Edit"||$==="MultiEdit"||$==="NotebookEdit")return"edit";return null}function MQ($,Z,J){return $==="read"?N2(Z,J):S2(Z,J)}function UQ($,Z,J,Q){if(!$.currentTurn)return;if($.maybeMidTurnRotate(),$.startWorkingFooter($.currentTurn),$.currentTurn.currentAssistantSegmentId)$.finalizeCurrentAssistantSegment();let Y=gG(J);if(Y&&$.currentTurn.openBatchI!==null){let V=$.currentTurn.openBatchI,A=$.currentTurn.toolBatches.get(V);if(A&&A.kind===Y){let G=A.items.length;A.items.push({toolUseId:Z,input:Q,output:null,isError:!1}),$.currentTurn.toolByUseId.set(Z,{i:V,name:J,input:Q,batchSlot:G});let _=Y==="read"?N2(V,A.items):S2(V,A.items);o($.currentTurn.cardId,M.tool(V),_),T9($.currentTurn,J,Q);return}}if(!Y)$.currentTurn.openBatchI=null;let H=t0(J);if(H){let V=$.currentTurn;if(H==="TaskCreate"&&!V.taskBoardResetThisTurn)$.taskBoard=[],V.taskBoardResetThisTurn=!0;if(!V.taskLiveInserted)V.taskLiveInserted=!0,z$(V.cardId,s0($.taskBoard),{type:"insert_before",targetElementId:M.footer});else o(V.cardId,M.taskBoardLive,s0($.taskBoard));let A=H==="TaskCreate";if(A)V.taskUpdateI=null;else V.taskCreateI=null;let G=(A?V.taskCreateI:V.taskUpdateI)===null;if(G)if(A)V.taskCreateI=V.toolCount++;else V.taskUpdateI=V.toolCount++;let _=A?V.taskCreateI:V.taskUpdateI;V.toolByUseId.set(Z,{i:_,name:J,input:Q});let q=T0(_,$.taskBoard,{name:H,status:"⏳"});G?z$(V.cardId,q,{type:"insert_before",targetElementId:B$(V)}):o(V.cardId,M.tool(_),q),T9(V,J,Q);return}$.currentTurn.taskCreateI=null,$.currentTurn.taskUpdateI=null;let W=$.currentTurn.toolCount++;if(Y){$.currentTurn.openBatchI=W;let V=[{toolUseId:Z,input:Q,output:null,isError:!1}];$.currentTurn.toolBatches.set(W,{kind:Y,items:V}),$.currentTurn.toolByUseId.set(Z,{i:W,name:J,input:Q,batchSlot:0});let A=Y==="read"?N2(W,V):S2(W,V);z$($.currentTurn.cardId,A,{type:"insert_before",targetElementId:B$($.currentTurn)}),T9($.currentTurn,J,Q);return}if($.currentTurn.toolByUseId.set(Z,{i:W,name:J,input:Q}),J==="AskUserQuestion"){let V=Array.isArray(Q?.questions)?Q.questions:[],A=V.length>0?0:void 0,G=new Map;$.pendingAsks.set(Z,{questions:V,i:W,answers:{},answered:G,currentIdx:A});let _=O2(W,Z,V,"\uD83E\uDD14",{currentIdx:A,answered:G});if(z$($.currentTurn.cardId,_,{type:"insert_before",targetElementId:B$($.currentTurn)}),$.currentTurn.userOpenId&&$.currentTurn.messageId){let q=$.currentTurn,B=V[0]?.question?.trim()??"",R=B.length>40?B.slice(0,40)+"…":B,L=V.length>1?`❓ 待回答 ${V.length} 题${R?`: ${R}`:""}`:R?`❓ ${R}`:"❓ 等你回答问题";(async()=>{V$(q.cardId),await g4(q.cardId,{config:{summary:{content:L}}}),await l0(q.messageId,[q.userOpenId])})()}return}let X=U0(W,J,Q,null,"⏳");z$($.currentTurn.cardId,X,{type:"insert_before",targetElementId:B$($.currentTurn)}),T9($.currentTurn,J,Q)}function T9($,Z,J){if(!$)return;let Q=F0(Z,J),Y=Q.length>80?Q.slice(0,80)+"…":Q,H=d0(Z),W=Y?`\uD83D\uDD27 ${H}: ${Y}`:`\uD83D\uDD27 ${H}`;X0($.cardId,W)}function OQ($,Z,J,Q){if(!$.currentTurn)return;let Y=$.currentTurn.toolByUseId.get(Z);if(!Y)return;let H=typeof J==="string"?J:Array.isArray(J)?J.map((A)=>A?.text??JSON.stringify(A)).join(`
|
|
153
|
-
`):JSON.stringify(J);Y.output=H,Y.isError=Q;let W=hG(Y.name,H,Q);if(W)$.sendOutboundPath(W,Y.name);if(Y.name==="AskUserQuestion"){k9($);return}if(Y.batchSlot!=null){let A=$.currentTurn.toolBatches.get(Y.i);if(A){let G=A.items[Y.batchSlot];if(G)G.output=H,G.isError=Q;let _=MQ(A.kind,Y.i,A.items);o($.currentTurn.cardId,M.tool(Y.i),_)}k9($);return}let X=t0(Y.name);if(X){IG($,Y,X,Y.input,H,Q,Y.resolvedNote);return}let V=U0(Y.i,Y.name,Y.input,H,Q?"❌":"✅",Y.resolvedNote);o($.currentTurn.cardId,M.tool(Y.i),V),k9($)}function IG($,Z,J,Q,Y,H,W){if(!$.currentTurn)return;if(!H)$.taskBoard=f7($.taskBoard,J,Q,Y);let X=T0(Z.i,$.taskBoard,{name:J,status:H?"❌":"✅"},W);if(o($.currentTurn.cardId,M.tool(Z.i),X),$.currentTurn.taskLiveInserted)o($.currentTurn.cardId,M.taskBoardLive,s0($.taskBoard));k9($)}function k9($){let Z=$.currentTurn;if(!Z)return;for(let J of Z.toolByUseId.values())if(J.output==null)return;$.startThinkingFooter(Z)}function o7($,Z,J,Q,Y){let H=$.currentTurn;if(!H)return;for(let[W,X]of Q){if(H.toolByUseId.has(W))continue;let V=X.batchSlot??null,A=X.input,G,_;if(V!=null){let U=Y.get(X.i)?.items[V];if(!U)continue;A=U.input,G=U.output,_=U.isError}else G=X.output??null,_=X.isError??!1;let q=G!=null,B=y1(Z,M.tool(X.i));if(q&&!B)continue;if(V!=null){let U=Y.get(X.i)?.kind;if(!U)continue;let P=H.toolCount++,j={toolUseId:W,input:A,output:G,isError:_};H.toolBatches.set(P,{kind:U,items:[j]}),H.toolByUseId.set(W,{...X,i:P,batchSlot:0}),z$(J,MQ(U,P,[j]),{type:"insert_before",targetElementId:B$(H)});continue}let R=t0(X.name);if(R){let U=R==="TaskCreate";if(U)H.taskUpdateI=null;else H.taskCreateI=null;let P=(U?H.taskCreateI:H.taskUpdateI)===null;if(P)if(U)H.taskCreateI=H.toolCount++;else H.taskUpdateI=H.toolCount++;let j=U?H.taskCreateI:H.taskUpdateI;H.toolByUseId.set(W,{...X,i:j});let k=!q?"⏳":_?"❌":"✅",C=T0(j,$.taskBoard,{name:R,status:k},X.resolvedNote);P?z$(J,C,{type:"insert_before",targetElementId:B$(H)}):o(J,M.tool(j),C);continue}let L=H.toolCount++;H.toolByUseId.set(W,{...X,i:L});let F=!q?"⏳":_?"❌":"✅";z$(J,U0(L,X.name,X.input,G,F,X.resolvedNote),{type:"insert_before",targetElementId:B$(H)})}}var EQ=N(()=>{m7();n0();C$();r()});function TQ($){return $.pendingAsks.size>0}async function kQ($,Z,J,Q){let Y=$.pendingAsks.entries().next();if(Y.done){z(`session "${$.sessionName}": onAskMessageAnswer with no pending — falling back to onUserMessage`),await $.onUserMessage(Z,[],J,Q);return}let[H,W]=Y.value;if(W.currentIdx===void 0){if(W.requestId){z(`session "${$.sessionName}": pending ask ${H} awaiting finalize — ignoring message`);return}z(`session "${$.sessionName}": pending ask ${H} orphaned (no can_use_tool) — dropping zombie, reprocessing as user message`),$.pendingAsks.delete(H),await $.onUserMessage(Z,[],J,Q);return}if(await a7($,H,W.currentIdx,Z,J)&&Q)T$(Q,"CheckMark")}async function SQ($,Z,J,Q,Y){let H=$.pendingAsks.get(Z);if(!H)return z(`session "${$.sessionName}": stray ask answer for ${Z}`),!1;if(J!==H.currentIdx)return z(`session "${$.sessionName}": stale ask click q=${J} current=${H.currentIdx}`),!1;return NQ($,Z,{optionIdx:Q,user:Y})}async function a7($,Z,J,Q,Y){let H=$.pendingAsks.get(Z);if(!H)return z(`session "${$.sessionName}": stray ask custom for ${Z}`),!1;let W=(Q??"").trim();if(!W)return z(`session "${$.sessionName}": empty custom answer, ignoring`),!1;if(J!==H.currentIdx)return z(`session "${$.sessionName}": stale ask custom q=${J} current=${H.currentIdx}`),!1;return NQ($,Z,{customText:W,user:Y})}function NQ($,Z,J){let Q=$.pendingAsks.get(Z);if(!Q||Q.currentIdx===void 0)return!1;let Y=Q.currentIdx,H=Q.questions[Y];if(!H)return z(`session "${$.sessionName}": advanceAsk currentIdx=${Y} out of range`),!1;let W;if(J.customText!==void 0)W=J.customText;else if(J.optionIdx!==void 0){let _=H.options?.[J.optionIdx];if(!_)return z(`session "${$.sessionName}": advanceAsk option ${J.optionIdx} out of range`),!1;W=_.label}else return z(`session "${$.sessionName}": advanceAsk with neither customText nor optionIdx`),!1;Q.answers[H.question]=W,Q.answered.set(Y,{optionIdx:J.optionIdx,customText:J.customText,user:J.user});let X=Q.questions.length,V=void 0;for(let _=Y+1;_<X;_++)if(!Q.answered.has(_)){V=_;break}Q.currentIdx=V;let A=$.currentTurn,G=A?.toolByUseId.get(Z);if(A&&G){let _=O2(G.i,Z,Q.questions,V===void 0?"✅":"\uD83E\uDD14",{currentIdx:V,answered:Q.answered});o(A.cardId,M.tool(G.i),_)}if(V===void 0)if(Q.requestId)r7($,Z);else z(`session "${$.sessionName}": ask ${Z} all answered, waiting for can_use_tool`);return!0}function r7($,Z){let J=$.pendingAsks.get(Z);if(!J||!J.requestId)return;let Q=$.currentTurn?.toolByUseId.get(Z),Y=Q?.input??{};if($.proc?.sendPermissionResponse(J.requestId,"allow",{updatedInput:{...Y,answers:J.answers}}),$.pendingPermissions.delete(J.requestId),Q)Q.output=JSON.stringify({answers:J.answers}),Q.isError=!1;if($.pendingAsks.delete(Z),$.pendingPermissions.size===0&&$.status==="awaiting_permission")$.status="working"}var t7=N(()=>{n0();C$();r();h()});async function yQ($,Z,J,Q){let Y=$.pendingPermissions.get(Z);if(!Y)return z(`session "${$.sessionName}": stray permission ${Z}`),{ok:!1,message:"此权限请求已失效或已处理"};let H=$.proc;if(!H)return z(`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:Y.permissionSuggestions}:void 0)}catch(A){return z(`session "${$.sessionName}": permission response ${Z} failed: ${A}`),{ok:!1,message:`权限决定发送失败: ${A instanceof Error?A.message:A}`}}$.pendingPermissions.delete(Z);let X=$.currentTurn,V=X?.toolByUseId.get(Y.toolUseId);if(X&&V){let A=t0(V.name);if(J==="deny"){let G=`\uD83D\uDEAB 已拒绝 by ${Q||"匿名"}`,_=A?T0(V.i,$.taskBoard,{name:A,status:"❌"},G):U0(V.i,V.name,V.input,G,"❌");o(X.cardId,M.tool(V.i),_)}else{let G=J==="allow_always"?"始终允许":"已允许";V.resolvedNote=`✅ **${G}** by ${Q||"匿名"}`;let _=A?T0(V.i,$.taskBoard,{name:A,status:"⏳"},V.resolvedNote):U0(V.i,V.name,V.input,null,"⏳",V.resolvedNote);o(X.cardId,M.tool(V.i),_)}}if(z(`session "${$.sessionName}": permission decision request=${Z} tool_use_id=${Y.toolUseId} decision=${J}`),$.pendingPermissions.size===0&&$.status==="awaiting_permission")$.status="working";return{ok:!0,message:J==="deny"?"已拒绝":J==="allow_always"?"已始终允许":"已允许"}}function xQ($,Z){let J=$.currentTurn;if(!J){z(`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 Q=Z.tool_use_id;if(!Q){z(`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 Y=J.toolByUseId.get(Q);if(!Y){z(`session "${$.sessionName}": can_use_tool for unknown tool_use_id=${Q} — auto-deny req=${Z.request_id}`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"unknown tool_use_id"});return}if(Y.name==="AskUserQuestion"){let W=$.pendingAsks.get(Q);if(!W){z(`session "${$.sessionName}": AskUserQuestion ${Q} 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:Q}),W.currentIdx===void 0)r7($,Q);return}$.status="awaiting_permission",$.pendingPermissions.set(Z.request_id,{toolUseId:Q,permissionSuggestions:Z.permission_suggestions}),z(`session "${$.sessionName}": can_use_tool request=${Z.request_id} tool_use_id=${Q} tool=${Y.name}`);let H=A7(Y.i,Y.name,Y.input,Z.request_id);if(o(J.cardId,M.tool(Y.i),H),J.userOpenId&&J.messageId){let W=F0(Y.name,Y.input),X=d0(Y.name),V=W&&W.length>30?W.slice(0,30)+"…":W,A=V?`\uD83D\uDD10 等审批: ${X} · ${V}`:`\uD83D\uDD10 等审批: ${X}`;(async()=>{V$(J.cardId),await g4(J.cardId,{config:{summary:{content:A}}}),await l0(J.messageId,[J.userOpenId])})()}}var bQ=N(()=>{n0();C$();r();h();t7()});function CQ($,Z=wQ){return new Promise((J,Q)=>{let Y=setTimeout(()=>Q(Error(`timeout ${Z}ms`)),Z);$.then((H)=>{clearTimeout(Y),J(H)},(H)=>{clearTimeout(Y),Q(H)})})}function fQ($){return typeof $==="string"&&pG.includes($)?$:null}async function vQ(){let $=new j9;try{await CQ($.request("initialize",{clientInfo:{name:"lodestar-models",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}));let Z=await CQ($.request("model/list",{})),J=Array.isArray(Z?.data)?Z.data:[],Q=[];for(let Y of J){if(!Y||Y.hidden||!Y.id)continue;let H=(Array.isArray(Y.supportedReasoningEfforts)?Y.supportedReasoningEfforts:[]).map((X)=>fQ(X?.reasoningEffort)).filter((X)=>X!==null);if(!H.length)continue;let W=fQ(Y.defaultReasoningEffort)??H[0];Q.push({model:String(Y.id),display:typeof Y.displayName==="string"&&Y.displayName?String(Y.displayName):String(Y.id),efforts:H,defaultEffort:W})}return Q}finally{await $.close()}}async function hQ($,Z){let J=new URL($),Q=J.pathname.replace(/\/+$/,""),Y=`${J.protocol}//${J.host}${Q}/v1/models`,H=await fetch(Y,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(wQ)});if(!H.ok)throw Error(`HTTP ${H.status}`);let W=await H.json();return(Array.isArray(W?.data)?W.data:[]).filter((V)=>V&&(V.display_name||V.id)).map((V)=>{let A=String(V.display_name||V.id);return{model:A,display:A,efforts:i$,defaultEffort:"max"}})}var wQ=1e4,pG,i$;var h2=N(()=>{M9();pG=["none","minimal","low","medium","high","xhigh","max","ultra"];i$=["max","xhigh","high","medium","low"]});import{existsSync as lG}from"node:fs";import{homedir as iG}from"node:os";import{join as gQ}from"node:path";function S9($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function nG($){if($.state!=="ok")return{state:$.state==="auth_failed"?"no_credentials":$.state==="no_credentials"?"no_credentials":$.state==="rate_limited"?"rate_limited":"network",windows:[]};let Z=[];if($.fiveHour)Z.push(S9($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(S9($.weekly,"weekly","周配额"));return{state:"ok",planLabel:$.subscriptionType,windows:Z,fetchedAt:$.fetchedAt}}function dG($){if($.state!=="ok"||!$.buckets?.length)return null;let Z=[];for(let J of $.buckets){let Q=J.limitId===$.defaultLimitId?J.limitName??"默认配额":J.limitName??J.limitId;if(J.fiveHour)Z.push(S9(J.fiveHour,"fiveHour",`${Q} 5h`));if(J.weekly)Z.push(S9(J.weekly,"weekly",`${Q} 周`))}return Z.length?Z:null}function oG(){let $=process.env.CODEX_HOME||gQ(iG(),".codex");return lG(gQ($,"auth.json"))}var IQ=N(()=>{U$();_$();M9();h2();h();Q0({kind:"codex-subscription",configSectionId:"codex-sub",build:($)=>{let Z=oG(),J=$.model?.trim()||void 0,Q=$.effort?.trim()||void 0,Y={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(!Y.enabled){Y.models=[],Y.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}Y.modelCatalogState={status:"loading",updatedAt:null};try{if(Y.models=await vQ(),Q)for(let H of Y.models)H.defaultEffort=Q;if(!J)Y.defaultModel=Y.models[0]?.model??"";Y.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(H){z(`codex-sub refreshModels MISS: ${H?.message??H}`),Y.models=[],Y.modelCatalogState={status:"failed",updatedAt:Date.now(),error:H?.message??String(H)}}},spawnEnv(H){let W=g0(H);return Object.assign(W,w.codex.env),W},resolveSpawnModel(H){return H},async readUsage(){let H=await F9(),W=nG(H),X=dG(H);if(X)W.windows=X;return W}};return Y}})});function rG($){let Z=new URL($),J=Z.pathname.replace(/\/+$/,"");return`${Z.protocol}//${Z.host}${J}/v1/messages`}async function N9($,Z,J){try{let Q=await fetch(rG($),{method:"POST",headers:{"Content-Type":"application/json",...Z},body:JSON.stringify({model:J,max_tokens:1,messages:[{role:"user",content:"hi"}]}),signal:AbortSignal.timeout(aG)});if(Q.ok)return"exists";if(Q.status===400){let Y=await Q.text();return Y.includes("1214")||Y.includes("不存在")||Y.includes("not exist")?"not_found":"no_verdict"}return z(`model-existence: ${J} HTTP ${Q.status}, no verdict`),"no_verdict"}catch(Q){return z(`model-existence: ${J} MISS (${Q?.message??Q})`),"no_verdict"}}var aG=15000;var s7=N(()=>{h()});function cQ($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function tG($){return{kind:"monthly",label:"月度工具",percent:$.percent,resetsAt:$.resetsAt,...$.used!=null?{used:$.used}:{},...$.total!=null?{total:$.total}:{}}}function sG($){return($??"").split(",").map((Z)=>Z.trim()).filter(Boolean)}function eG($){let Z=(J)=>{let Q=J.match(/(\d+(?:\.\d+)?)/);return Q?Number(Q[1]):-1};return[...$].sort((J,Q)=>Z(Q)-Z(J))[0]??""}function $_($){let Z={};for(let J of($??"").split(",")){let Q=J.indexOf("=");if(Q<=0)continue;let Y=J.slice(0,Q).trim().toLowerCase(),H=J.slice(Q+1).trim();if((Y==="opus"||Y==="sonnet"||Y==="haiku")&&H)Z[Y]=H}return Z}function Z_($){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(cQ($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(cQ($.weekly,"weekly","周额度"));if($.monthly)Z.push(tG($.monthly));return{state:"ok",planLabel:$.level?`${$.level} 套餐`:void 0,windows:Z,fetchedAt:$.fetchedAt}}var mQ=N(()=>{_$();O9();h2();P4();s7();h();Q0({kind:"glm-coding-plan",configSectionId:"glm",build:($,Z)=>{let J=$.base_url?.trim()||Z?.base_url?.trim()||"",Q=$.auth_token?.trim()||Z?.auth_token?.trim()||"",Y=!!(J&&Q)&&U9(J),H=$.model?.trim()||void 0,W=$_($.slots),X={id:"glm",kind:"glm-coding-plan",agent:"claude",display:$.display?.trim()||"GLM Coding Plan",enabled:Y,models:[],modelCatalogState:{status:Y?"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 hQ(J,Q),G=sG($.models).filter((_)=>!V.some((q)=>q.model.toLowerCase()===_.toLowerCase())).map((_)=>({model:_,display:_,efforts:i$,defaultEffort:"max"}));if(X.models=[...V,...G],!H)X.defaultModel=eG(X.models.map((_)=>_.model));for(let _ of X.models){let q=R4("glm",_.model);_.context1m=q!=null&&q>=1e6||void 0}X.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(V){z(`glm refreshModels MISS: ${V?.message??V}`),X.models=[],X.modelCatalogState={status:"failed",updatedAt:Date.now(),error:V?.message??String(V)}}},spawnEnv(V){let G={...g0(V)};if(G.ANTHROPIC_BASE_URL=J,G.ANTHROPIC_AUTH_TOKEN=Q,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 B4("glm",V)},async verifyModel(V){return N9(J,{Authorization:`Bearer ${Q}`},V)},async readUsage(){return Z_(await I7(J,Q))}};return X},setup:{commandSuffix:"glm",hint:($)=>`启用 ${$}:发送
|
|
152
|
+
`),H=Q[Q.length-1];z(`session "${$.sessionName}": multi-msg flush ${Q.length} segment(s) → 1 turn`),await $.onUserMessage(Y,[],H.userOpenId,H.msgId)}function p7($,Z){if($.multiMsgBuffer===null)return;let J=$.multiMsgBuffer.length;z(`session "${$.sessionName}": clear multi-msg buffer (${Z}): ${J} segment(s)`);for(let[Q,Y]of $.multiMsgReactions){if(Y)j$(Q,Y);T$(Q,"CrossMark")}$.multiMsgBuffer=null,$.multiMsgReactions=new Map}var AQ=N(()=>{t();h();VQ()});import{mkdtemp as KG,rm as qG,writeFile as BG}from"node:fs/promises";import{createRequire as RG}from"node:module";import{tmpdir as PG}from"node:os";import{join as GQ}from"node:path";function EG($){let Z=BQ.get($);if(Z)return Z;let{liteAdaptor:J}=Z1("mathjax-full/js/adaptors/liteAdaptor.js"),{RegisterHTMLHandler:Q}=Z1("mathjax-full/js/handlers/html.js"),{mathjax:Y}=Z1("mathjax-full/js/mathjax.js"),{TeX:H}=Z1("mathjax-full/js/input/tex.js"),{AllPackages:W}=Z1("mathjax-full/js/input/tex/AllPackages.js"),{SVG:X}=Z1("mathjax-full/js/output/svg.js"),V=J({fontSize:$});Q(V);let A=Y.document("",{InputJax:new H({packages:W}),OutputJax:new X({fontCache:"none"})}),G={adaptor:V,doc:A};return BQ.set($,G),G}function RQ($,Z){let J=Number.parseFloat($??"");if(!Number.isFinite(J)||J<=0)throw Error(`MathJax SVG missing valid ${Z}`);return J}function TG($){return $.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function kG($,Z=n7,J=!0){try{let Q=Z*LG,{adaptor:Y,doc:H}=EG(Z),W=H.convert($,{display:J,em:Z,ex:Q,containerWidth:80*Z}),X=Y.outerHTML(W);if(/data-mjx-error=|mjx-merror/.test(X)){let M$=X.match(/data-mjx-error="([^"]+)"/)?.[1]??"MathJax parse error";throw Error(M$)}let V=X.indexOf("<svg"),A=X.lastIndexOf("</svg>");if(V<0||A<0)throw Error("MathJax returned no SVG");let G=X.slice(V,A+6),_=G.match(/^<svg\b[^>]*>/)?.[0];if(!_)throw Error("MathJax returned malformed SVG root");let q=RQ(_.match(/\bwidth="([\d.]+)ex"/)?.[1],"width"),B=RQ(_.match(/\bheight="([\d.]+)ex"/)?.[1],"height"),R=_.match(/\bviewBox="([^"]+)"/)?.[1];if(!R)throw Error("MathJax SVG missing viewBox");let L=R.trim().split(/[\s,]+/).map(Number);if(L.length!==4||L.some((M$)=>!Number.isFinite(M$))||L[2]<=0||L[3]<=0)throw Error("MathJax SVG has invalid viewBox");let[F,U,P,j]=L,S=/<text\b/.test(G)?UG:0,b=`${F} ${U} ${P+S} ${j}`,y=q*Q,m=S*(y/P),v=Math.max(1,Math.ceil(y+m)),g=Math.max(1,Math.ceil(B*Q)),E=DG-l7*2,k=Math.min(1,E/v),u=Math.max(1,Math.round(v*k)),p=Math.max(1,Math.round(g*k));if(k<1&&p<jG)throw Error(`formula would be unreadable after width cap (${u}x${p})`);let a=u+l7*2,O=p+KQ*2,f=G.slice(_.length,-6).replace(/currentColor/g,_Q).replace(/font-family="serif"/g,`font-family="${OG}"`);return{svg:[`<svg xmlns="http://www.w3.org/2000/svg" width="${a}" height="${O}" viewBox="0 0 ${a} ${O}" style="color:${_Q}">`,`<rect x="0" y="0" width="${a}" height="${O}" rx="6" fill="${jQ}"/>`,`<svg x="${l7}" y="${KQ}" width="${u}" height="${p}" viewBox="${TG(b)}" preserveAspectRatio="xMidYMid meet">`,f,"</svg>","</svg>"].join(""),width:a,height:O}}catch(Q){return z(`math-render: TeX→SVG failed for ${$.slice(0,80)}…: ${Q}`),null}}function SG($,Z=n7,J=!0){let Q=kG($,Z,J);if(!Q)return null;try{let{Resvg:Y}=Z1("@resvg/resvg-js"),W=new Y(Q.svg,{background:jQ,fitTo:{mode:"original"},shapeRendering:2,textRendering:1,font:{loadSystemFonts:!0,serifFamily:qQ,sansSerifFamily:qQ}}).render().asPng(),X=new DataView(W.buffer,W.byteOffset,W.byteLength),V=X.getUint32(16),A=X.getUint32(20);if(V!==Q.width||A!==Q.height)throw Error(`PNG dimensions ${V}x${A} != SVG ${Q.width}x${Q.height}`);return{png:W,width:V,height:A}}catch(Y){return z(`math-render: SVG→PNG failed for ${$.slice(0,80)}…: ${Y}`),null}}function NG($){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 PQ($,Z){let J=[],Q=(G,_,q)=>{let B=G[0],R=_.trim();if(!R)return;J.push({start:Z+G.index,end:Z+G.index+B.length,tex:R,raw:B,display:q})},Y,H=/(?<!\\)\$\$([\s\S]+?)(?<!\\)\$\$|\\\[([\s\S]+?)\\\]/g;while((Y=H.exec($))!==null)Q(Y,Y[1]??Y[2]??"",!0);let W=/\\\(([\s\S]+?)\\\)/g;while((Y=W.exec($))!==null)Q(Y,Y[1]??"",!1);let X=/(?<![\\$])\$(?!\$)([^$\n]+?)(?<![\\$])\$(?!\$)/g;while((Y=X.exec($))!==null){let G=(Y[1]??"").trim();if(NG(G))Q(Y,G,!1)}J.sort((G,_)=>G.start-_.start||_.end-G.end);let V=[],A=-1;for(let G of J){if(G.start<A)continue;V.push(G),A=G.end}return V}function FQ($){let Z=f8($),J=[],Q=0;for(let Y of Z){if(Q<Y.start)J.push(...PQ($.slice(Q,Y.start),Q));Q=Math.max(Q,Y.end)}if(Q<$.length)J.push(...PQ($.slice(Q),Q));return J}function yG($){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,Q)=>{if(LQ[Q])return LQ[Q];if(Q==="times")return"×";if(Q==="cdot")return"·";if(Q==="div")return"÷";if(Q==="pm")return"±";if(Q==="leq"||Q==="le")return"≤";if(Q==="geq"||Q==="ge")return"≥";if(Q==="neq"||Q==="ne")return"≠";if(Q==="approx")return"≈";if(Q==="sim")return"~";if(Q==="infty")return"∞";if(Q==="partial")return"∂";if(Q==="nabla")return"∇";if(Q==="sqrt")return"√";if(Q==="to")return"→";return J}),/\\/.test(Z))return null;if(Z=Z.replace(/([_^])\{([^{}]+)\}/g,(J,Q,Y)=>Y.length===1?`${Q}${Y}`:`${Q}(${Y})`),Z=Z.replace(/√\{([^{}]+)\}/g,"√($1)"),/[{}]/.test(Z))return null;return Z}function fG($){let Z=DQ.get($);if(Z!==void 0)return Z;return Z=bG++,DQ.set($,Z),Z}function wG($,Z){return`${MG}\x00${fG(Z)}\x00${$}`}function vG($){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 hG($,Z){let J=wG($,Z),Q=$1.get(J);if(Q)return Q;let Y=i7.get(J);if(Y)return Y;let H=(async()=>{let W=SG($,n7,!0);if(!W)return null;let X=null;try{X=await KG(GQ(PG(),"lodestar-math-"));let V=GQ(X,`formula-${vG($)}.png`);await BG(V,W.png);let A=await Z(V,{tex:$,width:W.width,height:W.height});if(!A)return z(`math-render: upload returned no image key for ${$.slice(0,80)}…`),null;let G={key:A,width:W.width,height:W.height};if($1.has(J))$1.delete(J);$1.set(J,G);while($1.size>CG){let _=$1.keys().next().value;if(typeof _!=="string")break;$1.delete(_)}return G}catch(V){return z(`math-render: upload failed for ${$.slice(0,80)}…: ${V}`),null}finally{if(X)try{await qG(X,{recursive:!0,force:!0})}catch(V){z(`math-render: temp cleanup failed for ${X}: ${V}`)}}})();i7.set(J,H);try{return await H}finally{i7.delete(J)}}function gG($,Z,J){let Q=$.width<=FG;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:Q?"crop_center":"fit_horizontal",...Q?{size:`${$.width}px ${$.height}px`}:{},preview:!1}}}async function MQ($,Z={}){let J=FQ($);if(!J.length)return{blocks:[{type:"markdown",text:$}],formulaCount:0,renderedImageCount:0};let Q=Z.uploader??xG,Y=await Promise.all(J.map(async(G)=>{if(!G.display){let _=yG(G.tex);if(_!==null)return{unicode:_,uploaded:null}}return{unicode:null,uploaded:await hG(G.tex,Q)}})),H=[],W="",X=0,V=0,A=()=>{if(!W)return;if(W.trim())H.push({type:"markdown",text:W});W=""};for(let G=0;G<J.length;G++){let _=J[G],q=Y[G];if(W+=$.slice(X,_.start),q.unicode!==null){W+=q.unicode,X=_.end;continue}let B=q.uploaded;if(!B){W+=_.raw,X=_.end;continue}A(),H.push(gG(B,_,V++)),X=_.end}if(W+=$.slice(X),A(),!H.length)H.push({type:"markdown",text:$});return{blocks:H,formulaCount:J.length,renderedImageCount:V}}function d7($){return FQ($).length>0}var Z1,LG=0.5,n7=22,_Q="#1F2329",jQ="#F7F8FA",l7=12,KQ=8,DG=720,jG=14,FG=278,MG="v4-native-cjk-tail-pad",UG=1100,qQ,OG="Noto Sans CJK SC, Noto Sans CJK JP, Microsoft YaHei, PingFang SC, Arial Unicode MS, sans-serif",BQ,LQ,xG=async($)=>{let{uploadImageKey:Z}=await Promise.resolve().then(() => (t(),J$));return Z($)},DQ,bG=1,$1,i7,CG=512;var UQ=N(()=>{h();Z1=RG(import.meta.url),qQ=process.platform==="win32"?"Microsoft YaHei":process.platform==="darwin"?"PingFang SC":"Noto Sans CJK SC",BQ=new Map;LQ={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:"Ω"};DQ=new WeakMap,$1=new Map,i7=new Map});import{isAbsolute as cG}from"node:path";function B$($){if($?.planLiveInserted)return M.planLive;return $?.taskLiveInserted?M.taskBoardLive:M.footer}function mG($){return $==="ImageGeneration"||$==="imageGeneration"}function uG($,Z,J){if(J||!mG($))return null;let Q=E9(Z.trim());return cG(Q)?Q:null}function pG($){if($==="Read")return"read";if($==="Edit"||$==="MultiEdit"||$==="NotebookEdit")return"edit";return null}function OQ($,Z,J){return $==="read"?y2(Z,J):N2(Z,J)}function EQ($,Z,J,Q){if(!$.currentTurn)return;if($.maybeMidTurnRotate(),$.startWorkingFooter($.currentTurn),$.currentTurn.currentAssistantSegmentId)$.finalizeCurrentAssistantSegment();let Y=pG(J);if(Y&&$.currentTurn.openBatchI!==null){let V=$.currentTurn.openBatchI,A=$.currentTurn.toolBatches.get(V);if(A&&A.kind===Y){let G=A.items.length;A.items.push({toolUseId:Z,input:Q,output:null,isError:!1}),$.currentTurn.toolByUseId.set(Z,{i:V,name:J,input:Q,batchSlot:G});let _=Y==="read"?y2(V,A.items):N2(V,A.items);o($.currentTurn.cardId,M.tool(V),_),T9($.currentTurn,J,Q);return}}if(!Y)$.currentTurn.openBatchI=null;let H=t0(J);if(H){let V=$.currentTurn;if(H==="TaskCreate"&&!V.taskBoardResetThisTurn)$.taskBoard=[],V.taskBoardResetThisTurn=!0;if(!V.taskLiveInserted)V.taskLiveInserted=!0,z$(V.cardId,s0($.taskBoard),{type:"insert_before",targetElementId:M.footer});else o(V.cardId,M.taskBoardLive,s0($.taskBoard));let A=H==="TaskCreate";if(A)V.taskUpdateI=null;else V.taskCreateI=null;let G=(A?V.taskCreateI:V.taskUpdateI)===null;if(G)if(A)V.taskCreateI=V.toolCount++;else V.taskUpdateI=V.toolCount++;let _=A?V.taskCreateI:V.taskUpdateI;V.toolByUseId.set(Z,{i:_,name:J,input:Q});let q=T0(_,$.taskBoard,{name:H,status:"⏳"});G?z$(V.cardId,q,{type:"insert_before",targetElementId:B$(V)}):o(V.cardId,M.tool(_),q),T9(V,J,Q);return}$.currentTurn.taskCreateI=null,$.currentTurn.taskUpdateI=null;let W=$.currentTurn.toolCount++;if(Y){$.currentTurn.openBatchI=W;let V=[{toolUseId:Z,input:Q,output:null,isError:!1}];$.currentTurn.toolBatches.set(W,{kind:Y,items:V}),$.currentTurn.toolByUseId.set(Z,{i:W,name:J,input:Q,batchSlot:0});let A=Y==="read"?y2(W,V):N2(W,V);z$($.currentTurn.cardId,A,{type:"insert_before",targetElementId:B$($.currentTurn)}),T9($.currentTurn,J,Q);return}if($.currentTurn.toolByUseId.set(Z,{i:W,name:J,input:Q}),J==="AskUserQuestion"){let V=Array.isArray(Q?.questions)?Q.questions:[],A=V.length>0?0:void 0,G=new Map;$.pendingAsks.set(Z,{questions:V,i:W,answers:{},answered:G,currentIdx:A});let _=E2(W,Z,V,"\uD83E\uDD14",{currentIdx:A,answered:G});if(z$($.currentTurn.cardId,_,{type:"insert_before",targetElementId:B$($.currentTurn)}),$.currentTurn.userOpenId&&$.currentTurn.messageId){let q=$.currentTurn,B=V[0]?.question?.trim()??"",R=B.length>40?B.slice(0,40)+"…":B,L=V.length>1?`❓ 待回答 ${V.length} 题${R?`: ${R}`:""}`:R?`❓ ${R}`:"❓ 等你回答问题";(async()=>{V$(q.cardId),await g4(q.cardId,{config:{summary:{content:L}}}),await l0(q.messageId,[q.userOpenId])})()}return}let X=U0(W,J,Q,null,"⏳");z$($.currentTurn.cardId,X,{type:"insert_before",targetElementId:B$($.currentTurn)}),T9($.currentTurn,J,Q)}function T9($,Z,J){if(!$)return;let Q=F0(Z,J),Y=Q.length>80?Q.slice(0,80)+"…":Q,H=d0(Z),W=Y?`\uD83D\uDD27 ${H}: ${Y}`:`\uD83D\uDD27 ${H}`;X0($.cardId,W)}function TQ($,Z,J,Q){if(!$.currentTurn)return;let Y=$.currentTurn.toolByUseId.get(Z);if(!Y)return;let H=typeof J==="string"?J:Array.isArray(J)?J.map((A)=>A?.text??JSON.stringify(A)).join(`
|
|
153
|
+
`):JSON.stringify(J);Y.output=H,Y.isError=Q;let W=uG(Y.name,H,Q);if(W)$.sendOutboundPath(W,Y.name);if(Y.name==="AskUserQuestion"){k9($);return}if(Y.batchSlot!=null){let A=$.currentTurn.toolBatches.get(Y.i);if(A){let G=A.items[Y.batchSlot];if(G)G.output=H,G.isError=Q;let _=OQ(A.kind,Y.i,A.items);o($.currentTurn.cardId,M.tool(Y.i),_)}k9($);return}let X=t0(Y.name);if(X){lG($,Y,X,Y.input,H,Q,Y.resolvedNote);return}let V=U0(Y.i,Y.name,Y.input,H,Q?"❌":"✅",Y.resolvedNote);o($.currentTurn.cardId,M.tool(Y.i),V),k9($)}function lG($,Z,J,Q,Y,H,W){if(!$.currentTurn)return;if(!H)$.taskBoard=f7($.taskBoard,J,Q,Y);let X=T0(Z.i,$.taskBoard,{name:J,status:H?"❌":"✅"},W);if(o($.currentTurn.cardId,M.tool(Z.i),X),$.currentTurn.taskLiveInserted)o($.currentTurn.cardId,M.taskBoardLive,s0($.taskBoard));k9($)}function k9($){let Z=$.currentTurn;if(!Z)return;for(let J of Z.toolByUseId.values())if(J.output==null)return;$.startThinkingFooter(Z)}function o7($,Z,J,Q,Y){let H=$.currentTurn;if(!H)return;for(let[W,X]of Q){if(H.toolByUseId.has(W))continue;let V=X.batchSlot??null,A=X.input,G,_;if(V!=null){let U=Y.get(X.i)?.items[V];if(!U)continue;A=U.input,G=U.output,_=U.isError}else G=X.output??null,_=X.isError??!1;let q=G!=null,B=y1(Z,M.tool(X.i));if(q&&!B)continue;if(V!=null){let U=Y.get(X.i)?.kind;if(!U)continue;let P=H.toolCount++,j={toolUseId:W,input:A,output:G,isError:_};H.toolBatches.set(P,{kind:U,items:[j]}),H.toolByUseId.set(W,{...X,i:P,batchSlot:0}),z$(J,OQ(U,P,[j]),{type:"insert_before",targetElementId:B$(H)});continue}let R=t0(X.name);if(R){let U=R==="TaskCreate";if(U)H.taskUpdateI=null;else H.taskCreateI=null;let P=(U?H.taskCreateI:H.taskUpdateI)===null;if(P)if(U)H.taskCreateI=H.toolCount++;else H.taskUpdateI=H.toolCount++;let j=U?H.taskCreateI:H.taskUpdateI;H.toolByUseId.set(W,{...X,i:j});let S=!q?"⏳":_?"❌":"✅",b=T0(j,$.taskBoard,{name:R,status:S},X.resolvedNote);P?z$(J,b,{type:"insert_before",targetElementId:B$(H)}):o(J,M.tool(j),b);continue}let L=H.toolCount++;H.toolByUseId.set(W,{...X,i:L});let F=!q?"⏳":_?"❌":"✅";z$(J,U0(L,X.name,X.input,G,F,X.resolvedNote),{type:"insert_before",targetElementId:B$(H)})}}var kQ=N(()=>{m7();n0();C$();t()});function SQ($){return $.pendingAsks.size>0}async function NQ($,Z,J,Q){let Y=$.pendingAsks.entries().next();if(Y.done){z(`session "${$.sessionName}": onAskMessageAnswer with no pending — falling back to onUserMessage`),await $.onUserMessage(Z,[],J,Q);return}let[H,W]=Y.value;if(W.currentIdx===void 0){if(W.requestId){z(`session "${$.sessionName}": pending ask ${H} awaiting finalize — ignoring message`);return}z(`session "${$.sessionName}": pending ask ${H} orphaned (no can_use_tool) — dropping zombie, reprocessing as user message`),$.pendingAsks.delete(H),await $.onUserMessage(Z,[],J,Q);return}if(await a7($,H,W.currentIdx,Z,J)&&Q)T$(Q,"CheckMark")}async function yQ($,Z,J,Q,Y){let H=$.pendingAsks.get(Z);if(!H)return z(`session "${$.sessionName}": stray ask answer for ${Z}`),!1;if(J!==H.currentIdx)return z(`session "${$.sessionName}": stale ask click q=${J} current=${H.currentIdx}`),!1;return xQ($,Z,{optionIdx:Q,user:Y})}async function a7($,Z,J,Q,Y){let H=$.pendingAsks.get(Z);if(!H)return z(`session "${$.sessionName}": stray ask custom for ${Z}`),!1;let W=(Q??"").trim();if(!W)return z(`session "${$.sessionName}": empty custom answer, ignoring`),!1;if(J!==H.currentIdx)return z(`session "${$.sessionName}": stale ask custom q=${J} current=${H.currentIdx}`),!1;return xQ($,Z,{customText:W,user:Y})}function xQ($,Z,J){let Q=$.pendingAsks.get(Z);if(!Q||Q.currentIdx===void 0)return!1;let Y=Q.currentIdx,H=Q.questions[Y];if(!H)return z(`session "${$.sessionName}": advanceAsk currentIdx=${Y} out of range`),!1;let W;if(J.customText!==void 0)W=J.customText;else if(J.optionIdx!==void 0){let _=H.options?.[J.optionIdx];if(!_)return z(`session "${$.sessionName}": advanceAsk option ${J.optionIdx} out of range`),!1;W=_.label}else return z(`session "${$.sessionName}": advanceAsk with neither customText nor optionIdx`),!1;Q.answers[H.question]=W,Q.answered.set(Y,{optionIdx:J.optionIdx,customText:J.customText,user:J.user});let X=Q.questions.length,V=void 0;for(let _=Y+1;_<X;_++)if(!Q.answered.has(_)){V=_;break}Q.currentIdx=V;let A=$.currentTurn,G=A?.toolByUseId.get(Z);if(A&&G){let _=E2(G.i,Z,Q.questions,V===void 0?"✅":"\uD83E\uDD14",{currentIdx:V,answered:Q.answered});o(A.cardId,M.tool(G.i),_)}if(V===void 0)if(Q.requestId)r7($,Z);else z(`session "${$.sessionName}": ask ${Z} all answered, waiting for can_use_tool`);return!0}function r7($,Z){let J=$.pendingAsks.get(Z);if(!J||!J.requestId)return;let Q=$.currentTurn?.toolByUseId.get(Z),Y=Q?.input??{};if($.proc?.sendPermissionResponse(J.requestId,"allow",{updatedInput:{...Y,answers:J.answers}}),$.pendingPermissions.delete(J.requestId),Q)Q.output=JSON.stringify({answers:J.answers}),Q.isError=!1;if($.pendingAsks.delete(Z),$.pendingPermissions.size===0&&$.status==="awaiting_permission")$.status="working"}var t7=N(()=>{n0();C$();t();h()});async function bQ($,Z,J,Q){let Y=$.pendingPermissions.get(Z);if(!Y)return z(`session "${$.sessionName}": stray permission ${Z}`),{ok:!1,message:"此权限请求已失效或已处理"};let H=$.proc;if(!H)return z(`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:Y.permissionSuggestions}:void 0)}catch(A){return z(`session "${$.sessionName}": permission response ${Z} failed: ${A}`),{ok:!1,message:`权限决定发送失败: ${A instanceof Error?A.message:A}`}}$.pendingPermissions.delete(Z);let X=$.currentTurn,V=X?.toolByUseId.get(Y.toolUseId);if(X&&V){let A=t0(V.name);if(J==="deny"){let G=`\uD83D\uDEAB 已拒绝 by ${Q||"匿名"}`,_=A?T0(V.i,$.taskBoard,{name:A,status:"❌"},G):U0(V.i,V.name,V.input,G,"❌");o(X.cardId,M.tool(V.i),_)}else{let G=J==="allow_always"?"始终允许":"已允许";V.resolvedNote=`✅ **${G}** by ${Q||"匿名"}`;let _=A?T0(V.i,$.taskBoard,{name:A,status:"⏳"},V.resolvedNote):U0(V.i,V.name,V.input,null,"⏳",V.resolvedNote);o(X.cardId,M.tool(V.i),_)}}if(z(`session "${$.sessionName}": permission decision request=${Z} tool_use_id=${Y.toolUseId} decision=${J}`),$.pendingPermissions.size===0&&$.status==="awaiting_permission")$.status="working";return{ok:!0,message:J==="deny"?"已拒绝":J==="allow_always"?"已始终允许":"已允许"}}function CQ($,Z){let J=$.currentTurn;if(!J){z(`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 Q=Z.tool_use_id;if(!Q){z(`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 Y=J.toolByUseId.get(Q);if(!Y){z(`session "${$.sessionName}": can_use_tool for unknown tool_use_id=${Q} — auto-deny req=${Z.request_id}`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"unknown tool_use_id"});return}if(Y.name==="AskUserQuestion"){let W=$.pendingAsks.get(Q);if(!W){z(`session "${$.sessionName}": AskUserQuestion ${Q} 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:Q}),W.currentIdx===void 0)r7($,Q);return}$.status="awaiting_permission",$.pendingPermissions.set(Z.request_id,{toolUseId:Q,permissionSuggestions:Z.permission_suggestions}),z(`session "${$.sessionName}": can_use_tool request=${Z.request_id} tool_use_id=${Q} tool=${Y.name}`);let H=A7(Y.i,Y.name,Y.input,Z.request_id);if(o(J.cardId,M.tool(Y.i),H),J.userOpenId&&J.messageId){let W=F0(Y.name,Y.input),X=d0(Y.name),V=W&&W.length>30?W.slice(0,30)+"…":W,A=V?`\uD83D\uDD10 等审批: ${X} · ${V}`:`\uD83D\uDD10 等审批: ${X}`;(async()=>{V$(J.cardId),await g4(J.cardId,{config:{summary:{content:A}}}),await l0(J.messageId,[J.userOpenId])})()}}var fQ=N(()=>{n0();C$();t();h();t7()});function wQ($,Z=hQ){return new Promise((J,Q)=>{let Y=setTimeout(()=>Q(Error(`timeout ${Z}ms`)),Z);$.then((H)=>{clearTimeout(Y),J(H)},(H)=>{clearTimeout(Y),Q(H)})})}function vQ($){return typeof $==="string"&&oG.includes($)?$:null}async function gQ(){let $=new j9;try{await wQ($.request("initialize",{clientInfo:{name:"lodestar-models",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}));let Z=await wQ($.request("model/list",{})),J=Array.isArray(Z?.data)?Z.data:[],Q=[];for(let Y of J){if(!Y||Y.hidden||!Y.id)continue;let H=(Array.isArray(Y.supportedReasoningEfforts)?Y.supportedReasoningEfforts:[]).map((X)=>vQ(X?.reasoningEffort)).filter((X)=>X!==null);if(!H.length)continue;let W=vQ(Y.defaultReasoningEffort)??H[0];Q.push({model:String(Y.id),display:typeof Y.displayName==="string"&&Y.displayName?String(Y.displayName):String(Y.id),efforts:H,defaultEffort:W})}return Q}finally{await $.close()}}async function IQ($,Z){let J=new URL($),Q=J.pathname.replace(/\/+$/,""),Y=`${J.protocol}//${J.host}${Q}/v1/models`,H=await fetch(Y,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(hQ)});if(!H.ok)throw Error(`HTTP ${H.status}`);let W=await H.json();return(Array.isArray(W?.data)?W.data:[]).filter((V)=>V&&(V.display_name||V.id)).map((V)=>{let A=String(V.display_name||V.id);return{model:A,display:A,efforts:i$,defaultEffort:"max"}})}var hQ=1e4,oG,i$;var g2=N(()=>{M9();oG=["none","minimal","low","medium","high","xhigh","max","ultra"];i$=["max","xhigh","high","medium","low"]});import{existsSync as aG}from"node:fs";import{homedir as rG}from"node:os";import{join as cQ}from"node:path";function S9($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function tG($){if($.state!=="ok")return{state:$.state==="auth_failed"?"no_credentials":$.state==="no_credentials"?"no_credentials":$.state==="rate_limited"?"rate_limited":"network",windows:[]};let Z=[];if($.fiveHour)Z.push(S9($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(S9($.weekly,"weekly","周配额"));return{state:"ok",planLabel:$.subscriptionType,windows:Z,fetchedAt:$.fetchedAt}}function sG($){if($.state!=="ok"||!$.buckets?.length)return null;let Z=[];for(let J of $.buckets){let Q=J.limitId===$.defaultLimitId?J.limitName??"默认配额":J.limitName??J.limitId;if(J.fiveHour)Z.push(S9(J.fiveHour,"fiveHour",`${Q} 5h`));if(J.weekly)Z.push(S9(J.weekly,"weekly",`${Q} 周`))}return Z.length?Z:null}function eG(){let $=process.env.CODEX_HOME||cQ(rG(),".codex");return aG(cQ($,"auth.json"))}var mQ=N(()=>{U$();_$();M9();g2();h();Q0({kind:"codex-subscription",configSectionId:"codex-sub",build:($)=>{let Z=eG(),J=$.model?.trim()||void 0,Q=$.effort?.trim()||void 0,Y={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(!Y.enabled){Y.models=[],Y.modelCatalogState={status:"disabled",updatedAt:Date.now()};return}Y.modelCatalogState={status:"loading",updatedAt:null};try{if(Y.models=await gQ(),Q)for(let H of Y.models)H.defaultEffort=Q;if(!J)Y.defaultModel=Y.models[0]?.model??"";Y.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(H){z(`codex-sub refreshModels MISS: ${H?.message??H}`),Y.models=[],Y.modelCatalogState={status:"failed",updatedAt:Date.now(),error:H?.message??String(H)}}},spawnEnv(H){let W=g0(H);return Object.assign(W,w.codex.env),W},resolveSpawnModel(H){return H},async readUsage(){let H=await F9(),W=tG(H),X=sG(H);if(X)W.windows=X;return W}};return Y}})});function Z_($){let Z=new URL($),J=Z.pathname.replace(/\/+$/,"");return`${Z.protocol}//${Z.host}${J}/v1/messages`}async function N9($,Z,J){try{let Q=await fetch(Z_($),{method:"POST",headers:{"Content-Type":"application/json",...Z},body:JSON.stringify({model:J,max_tokens:1,messages:[{role:"user",content:"hi"}]}),signal:AbortSignal.timeout($_)});if(Q.ok)return"exists";if(Q.status===400){let Y=await Q.text();return Y.includes("1214")||Y.includes("不存在")||Y.includes("not exist")?"not_found":"no_verdict"}return z(`model-existence: ${J} HTTP ${Q.status}, no verdict`),"no_verdict"}catch(Q){return z(`model-existence: ${J} MISS (${Q?.message??Q})`),"no_verdict"}}var $_=15000;var s7=N(()=>{h()});function uQ($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function J_($){return{kind:"monthly",label:"月度工具",percent:$.percent,resetsAt:$.resetsAt,...$.used!=null?{used:$.used}:{},...$.total!=null?{total:$.total}:{}}}function Q_($){return($??"").split(",").map((Z)=>Z.trim()).filter(Boolean)}function Y_($){let Z=(J)=>{let Q=J.match(/(\d+(?:\.\d+)?)/);return Q?Number(Q[1]):-1};return[...$].sort((J,Q)=>Z(Q)-Z(J))[0]??""}function H_($){let Z={};for(let J of($??"").split(",")){let Q=J.indexOf("=");if(Q<=0)continue;let Y=J.slice(0,Q).trim().toLowerCase(),H=J.slice(Q+1).trim();if((Y==="opus"||Y==="sonnet"||Y==="haiku")&&H)Z[Y]=H}return Z}function W_($){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(uQ($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(uQ($.weekly,"weekly","周额度"));if($.monthly)Z.push(J_($.monthly));return{state:"ok",planLabel:$.level?`${$.level} 套餐`:void 0,windows:Z,fetchedAt:$.fetchedAt}}var pQ=N(()=>{_$();O9();g2();P4();s7();h();Q0({kind:"glm-coding-plan",configSectionId:"glm",build:($,Z)=>{let J=$.base_url?.trim()||Z?.base_url?.trim()||"",Q=$.auth_token?.trim()||Z?.auth_token?.trim()||"",Y=!!(J&&Q)&&U9(J),H=$.model?.trim()||void 0,W=H_($.slots),X={id:"glm",kind:"glm-coding-plan",agent:"claude",display:$.display?.trim()||"GLM Coding Plan",enabled:Y,models:[],modelCatalogState:{status:Y?"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 IQ(J,Q),G=Q_($.models).filter((_)=>!V.some((q)=>q.model.toLowerCase()===_.toLowerCase())).map((_)=>({model:_,display:_,efforts:i$,defaultEffort:"max"}));if(X.models=[...V,...G],!H)X.defaultModel=Y_(X.models.map((_)=>_.model));for(let _ of X.models){let q=R4("glm",_.model);_.context1m=q!=null&&q>=1e6||void 0}X.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(V){z(`glm refreshModels MISS: ${V?.message??V}`),X.models=[],X.modelCatalogState={status:"failed",updatedAt:Date.now(),error:V?.message??String(V)}}},spawnEnv(V){let G={...g0(V)};if(G.ANTHROPIC_BASE_URL=J,G.ANTHROPIC_AUTH_TOKEN=Q,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 B4("glm",V)},async verifyModel(V){return N9(J,{Authorization:`Bearer ${Q}`},V)},async readUsage(){return W_(await I7(J,Q))}};return X},setup:{commandSuffix:"glm",hint:($)=>`启用 ${$}:发送
|
|
154
154
|
\`\`\`
|
|
155
155
|
glm-setup <base_url> <token>
|
|
156
|
-
\`\`\``,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(!U9(Z))return null;let J=$.ANTHROPIC_AUTH_TOKEN?.trim()??"";return J?{base_url:Z,auth_token:J}:null}}})});var
|
|
156
|
+
\`\`\``,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(!U9(Z))return null;let J=$.ANTHROPIC_AUTH_TOKEN?.trim()??"";return J?{base_url:Z,auth_token:J}:null}}})});var lQ;var iQ=N(()=>{_$();g2();lQ=[{model:"fable",display:"Fable",efforts:i$,defaultEffort:"max"},{model:"opus",display:"Opus",efforts:i$,defaultEffort:"high"},{model:"sonnet",display:"Sonnet",efforts:i$,defaultEffort:"medium"},{model:"haiku",display:"Haiku",efforts:i$,defaultEffort:"medium"}];Q0({kind:"claude-native",build:($)=>{let Z={id:"claude-native",kind:"claude-native",agent:"claude",display:"Claude",enabled:!1,models:lQ,modelCatalogState:{status:"ready",updatedAt:Date.now()},defaultModel:"opus",settingSources:["user","project","local"],async refreshModels(){Z.models=lQ,Z.modelCatalogState={status:Z.enabled?"ready":"disabled",updatedAt:Date.now()}},spawnEnv(J){return J},resolveSpawnModel(J){return J},async readUsage(){return{state:"not_applicable",windows:[]}}};return Z}})});function V_($){return($??"").split(",").map((Z)=>Z.trim()).filter(Boolean)}function z_($){let Z=(J)=>{let Q=J.match(/(\d+(?:\.\d+)?)/);return Q?Number(Q[1]):-1};return[...$].sort((J,Q)=>Z(Q)-Z(J))[0]??""}function A_($){let Z={};for(let J of($??"").split(",")){let Q=J.indexOf("=");if(Q<=0)continue;let Y=J.slice(0,Q).trim().toLowerCase(),H=J.slice(Q+1).trim();if((Y==="opus"||Y==="sonnet"||Y==="haiku")&&H)Z[Y]=H}return Z}function G_($){try{return new URL($).hostname.toLowerCase()==="api.deepseek.com"}catch{return!1}}async function __($,Z){let J=new URL($).origin,Q=await fetch(`${J}/models`,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(1e4)});if(!Q.ok)throw Error(`HTTP ${Q.status}`);let Y=await Q.json();return(Array.isArray(Y?.data)?Y.data:[]).filter((W)=>W&&typeof W.id==="string"&&W.id).map((W)=>({model:W.id,display:W.id,efforts:i$,defaultEffort:"high"}))}async function q_($,Z){let J;try{J=new URL($).origin}catch{return{state:"network",windows:[],reason:"bad base_url"}}try{let Q=await fetch(`${J}/user/balance`,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(K_)});if(!Q.ok)return{state:"network",windows:[],reason:`HTTP ${Q.status}`};let Y=await Q.json(),W=(Array.isArray(Y?.balance_infos)?Y.balance_infos:[])[0],X=typeof W?.currency==="string"?W.currency:"",V=X==="CNY"?"¥":X==="USD"?"$":X?`${X} `:"",A=W?.total_balance;if(typeof A!=="string"&&typeof A!=="number")return{state:"ok",windows:[],planLabel:"余额 —(无明细)"};let G=Y?.is_available!==!1;return{state:"ok",windows:[],planLabel:G?`剩余 ${V}${A}`:`⚠️ 余额不足 ${V}${A}`}}catch(Q){return z(`deepseek readUsage MISS: ${Q?.message??Q}`),{state:"network",windows:[],reason:Q?.message??String(Q)}}}var X_="https://api.deepseek.com/anthropic",K_=1e4;var nQ=N(()=>{_$();g2();P4();s7();h();Q0({kind:"deepseek",configSectionId:"deepseek",build:($,Z)=>{let J=$.base_url?.trim()||Z?.base_url?.trim()||X_,Q=$.api_key?.trim()||Z?.api_key?.trim()||"",Y=!!Q,H=$.model?.trim()||void 0,W=A_($.slots),X={id:"deepseek",kind:"deepseek",agent:"claude",display:$.display?.trim()||"DeepSeek",enabled:Y,models:[],modelCatalogState:{status:Y?"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 __(J,Q),G=V_($.models).filter((_)=>!V.some((q)=>q.model.toLowerCase()===_.toLowerCase())).map((_)=>({model:_,display:_,efforts:i$,defaultEffort:"high"}));if(X.models=[...V,...G],!H)X.defaultModel=z_(X.models.map((_)=>_.model));for(let _ of X.models){let q=R4("deepseek",_.model);_.context1m=q!=null&&q>=1e6||void 0}X.modelCatalogState={status:"ready",updatedAt:Date.now()}}catch(V){z(`deepseek refreshModels MISS: ${V?.message??V}`),X.models=[],X.modelCatalogState={status:"failed",updatedAt:Date.now(),error:V?.message??String(V)}}},spawnEnv(V){let G={...g0(V)};if(G.ANTHROPIC_BASE_URL=J,G.ANTHROPIC_API_KEY=Q,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 B4("deepseek",V)},async verifyModel(V){return N9(J,{"x-api-key":Q},V)},async readUsage(){if(!Q)return{state:"no_credentials",windows:[]};return q_(J,Q)}};return X},setup:{commandSuffix:"deepseek",hint:($)=>`启用 ${$}:发送
|
|
157
157
|
\`\`\`
|
|
158
158
|
deepseek-setup <api_key>
|
|
159
159
|
\`\`\`
|
|
160
|
-
默认官方 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,Q=Z.length>=2?Z[1]:Z[0];return{config:{agent:"claude",...J?{base_url:J}:{},api_key:Q}}}},detect:{fromSettingsEnv($){let Z=$.ANTHROPIC_BASE_URL?.trim()??"";if(!
|
|
161
|
-
`)}async function y9($,Z){let J=
|
|
160
|
+
默认官方 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,Q=Z.length>=2?Z[1]:Z[0];return{config:{agent:"claude",...J?{base_url:J}:{},api_key:Q}}}},detect:{fromSettingsEnv($){let Z=$.ANTHROPIC_BASE_URL?.trim()??"";if(!G_(Z))return null;let J=$.ANTHROPIC_API_KEY?.trim()??"";return J?{base_url:Z,api_key:J}:null}}})});var oQ={};G1(oQ,{tokenSourceSpawnRevision:()=>dQ,buildTokenSourcesFromConfig:()=>e7});import{createHash as B_}from"node:crypto";function e7(){z6();let $=g7(),Z=O1().map((H)=>{let W=H.configSectionId?(w.token_sources??{})[H.configSectionId]??{}:{},X=H.detect?.fromSettingsEnv($)??null,V=H.build(W,X);return V.spawnRevision=dQ(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?"ready":"disabled",updatedAt:Date.now()}}for(let H of Z)X6(H);let Y=Z.find((H)=>H.enabled&&w.token_sources?.[H.id]?.default===!0)??Z.find((H)=>H.enabled);if(Y)V6(Y.id);return Z.length}function dQ($,Z,J){let Q=(Y)=>({agent:Y?.agent,auth:Y?.auth,base_url:Y?.base_url,auth_token:Y?.auth_token,api_key:Y?.api_key,bin:Y?.bin,model:Y?.model,effort:Y?.effort,slots:Y?.slots});return B_("sha256").update(JSON.stringify({kind:$,configured:Q(Z),detected:Q(J)})).digest("hex")}var $5=N(()=>{U$();_$();O9();mQ();pQ();iQ();nQ()});import{readFileSync as R_}from"node:fs";function P_($){return $.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}function L_($,Z){let J=[`[token_source.${$}]`],Q=(Y,H)=>{if(H&&H.length)J.push(`${Y} = "${P_(H)}"`)};if(Q("agent",Z.agent),Q("display",Z.display),Q("auth",Z.auth),Q("base_url",Z.base_url),Q("auth_token",Z.auth_token),Q("api_key",Z.api_key),Q("bin",Z.bin),Q("model",Z.model),Q("effort",Z.effort),Q("models",Z.models),Q("slots",Z.slots),Q("usage",Z.usage),Z.default)J.push('default = "true"');return J.join(`
|
|
161
|
+
`)}async function y9($,Z){let J=R_(P$,"utf8"),Q=`[token_source.${$}]`,Y=J.split(`
|
|
162
162
|
`),H=!1,W={},X=[];for(let _ of Y){let q=_.match(/^\s*(\[[^\]]+\])\s*(?:#.*)?$/)?.[1];if(q)H=q===Q;if(H){let B=_.match(/^\s*([A-Za-z_]+)\s*=\s*"([^"]*)"/);if(B)W[B[1]]=B[2]}else X.push(_)}let V={...W},A={...Z};for(let _ of Object.keys(A))if(A[_])V[_]=A[_];let G=V;while(X.length&&X[X.length-1]==="")X.pop();v$(P$,X.join(`
|
|
163
163
|
`)+`
|
|
164
164
|
|
|
165
|
-
`+
|
|
166
|
-
`),
|
|
167
|
-
⚠️ kill 状态卡片终态写入失败: ${D(B)}`)}}if(_&&!G)await
|
|
168
|
-
请重新发送 model 打开面板。`;if(!await b($.chatId,U))z(`model-custom: visible fallback send MISS (${L})`);return!1},V=(R)=>X(z9(!1,Y,R),`❌ ${Y?`模型 ${Y}`:"模型名"} 未加入:${R}。`);if(!H||!H.enabled||!H.verifyModel)return await V("账号不可用"),!0;if(!Y)return await V("模型名为空"),!0;if(H.models.some((R)=>R.model.toLowerCase()===Y.toLowerCase()))return await X(z9(!1,Y,"已在列表中"),`ℹ️ 模型 ${Y} 已在列表中,未重复加入。`),!0;let A=await H.verifyModel(Y);if(A==="not_found")return await V("端点确认不存在"),!0;if(A==="no_verdict")return await V("无法校验(端点无响应或凭据问题)"),!0;let G=[...E_(H.id),Y].join(",");try{await y8(y9(H.id,{models:G}),15000,"refreshModels")}catch(R){return z(`model-custom: config/refresh MISS (${D(R)})`),await V(`配置写入或模型刷新失败:${D(R)}`),!0}z(`model-custom: ${H.id} 补录 ${Y} by ${J}(端点校验通过,已持久化)`);let _=$$(H.id);if(!_||_.modelCatalogState?.status!=="ready")return await V(_?.modelCatalogState?.error??"刷新后的账号目录不可用"),!0;let q=tQ($,_),B=q.find((R)=>R.model===Y);if(!B)return await V("模型已验证,但刷新后的模型列表未返回该项"),!0;return $.modelPanels.set(Q.panelId,{models:q}),await X(A9({sessionName:$.sessionName,panelId:Q.panelId,currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:B}),`✅ 模型 ${Y} 已补录成功。`),!0}function E_($){return(w.token_sources[$]?.models??"").split(",").map((J)=>J.trim()).filter(Boolean)}async function JY($,Z=""){let J=Z.trim(),Q=$.modelCustomPrompt;if(!J||!Q||Q.panelId!==J)return{ok:!1,message:"此补录面板已失效",card:V9($.sessionName,"stale")};return $.modelCustomPrompt=null,{ok:!0,message:"已取消",card:V9($.sessionName)}}function T_($,Z){return Z?.provider==="claude"||Z?.provider==="codex"?Z.provider:F1($)}function k_($,Z){if($.currentTurn)return"当前 turn 不变,后续新 turn 使用。";if($.proc?.isAlive()&&$.proc.provider===Z)return Z==="codex"?"Codex 需重启进程生效(发 restart)。":"下一轮开始使用。";return`下次启动 ${J0(Z)} 时使用。`}async function QY($,Z,J="",Q="",Y=null){let H=Z.trim();if(!H)return await E($.chatId,`❌ ${"模型为空"}`),{ok:!1,message:"模型为空"};let W=T_(H,Y),X=$.modelPanels.get(J.trim())?.models.find((V)=>V.model===H&&(V.provider??"codex")===W);if(!X)return{ok:!1,message:"模型不在当前选项中,请重新发送 model"};if(X.enabled===!1)return{ok:!1,message:`${X.displayName} 未配置,请先点「启用」`};if(X.efforts.length===0)return{ok:!1,message:"模型未返回 effort"};return{ok:!0,message:"",card:P7({sessionName:$.sessionName,panelId:J.trim(),currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:X})}}async function YY($,Z,J,Q="",Y="",H=""){let W=Z.trim(),X=J.trim();if(!W)return{ok:!1,message:"模型为空"};let V=Q.trim(),A=$.modelPanels.get(V),G=H==="claude"||H==="codex"?H:A?.models.find((P)=>P.model===W)?.provider??F1(W);if(G==="claude"){if(!d$(X))return{ok:!1,message:"Claude reasoning effort 无效"}}else if(!S$(X))return{ok:!1,message:"Codex reasoning effort 无效"};let _=X,q=A?.models.find((P)=>P.model===W&&(P.provider??"codex")===G);if(!q||!q.efforts.some((P)=>P.effort===_))return{ok:!1,message:`${J0(G)} · ${W}/${_} 不在选项中`};let B=!!q.sourceId&&$.currentTokenSource()?.id!==q.sourceId;if($.currentProvider()===G&&!B&&$.currentModelLabel()===W&&$.currentEffortLabel()===_)return $.modelPanels.delete(V),{ok:!0,message:`当前已是 ${J0(G)} · ${W} / ${_}`,card:X9({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 后再切换到 ${J0(G)}`};let F=$.currentModelLabel()!==W||B,U=!!($.currentTurn||$.openingTurn||$.pendingUserMessageCount>0||$.pendingMidTurnMsgs.length>0);if(G==="claude"&&$.proc?.isAlive()&&$.proc.provider==="claude"&&F&&U)return{ok:!1,message:"当前 Claude turn 正在执行或排队;Claude 模型 profile 通过 env 生效,请等结束或 stop 后再切换"};try{if($.proc?.isAlive()&&$.proc.provider===G&&!B){let j=q.sourceId?$$(q.sourceId)?.resolveSpawnModel(W)??W:W;await y8($.proc.setModelSettings(j,_),20000,"thread/settings/update")}await $.applyModelSelectionUnlocked(G,W,_,q.sourceId);let P=k_($,G);return $.modelPanels.delete(V),{ok:!0,message:`已选择 ${J0(G)} · ${W} / ${_}`,card:X9({sessionName:$.sessionName,provider:G,model:W,effort:_,scope:P})}}catch(P){let j=`模型切换失败: ${D(P)}`;return z(`session "${$.sessionName}": set model settings failed: ${D(P)}`),await E($.chatId,`❌ ${j}`),{ok:!1,message:j}}}var HY=N(()=>{U$();_$();Z5();D1();v0();C$();n0();r();h()});import{createHash as N_}from"node:crypto";function y_($,Z){return`agent:${Buffer.from(`${$}\x00${Z}`,"utf8").toString("base64url")}`}function J1(){return x_(I0())}function x_($){let Z=[],J=[];for(let Q of $)b_(Q,Z,J);return{catalogGeneration:N_("sha256").update(JSON.stringify({identities:Z,sourceFailures:J})).digest("hex").slice(0,16),identities:Z,sourceFailures:J}}function b_($,Z,J){let Q=$.modelCatalogState?.status??(!$.enabled?"disabled":$.models.length>0?"ready":"idle");if(!$.enabled)J.push({tokenSourceId:$.id,display:$.display,status:"disabled",reason:"账号未启用"});else if(Q==="loading"||Q==="idle")J.push({tokenSourceId:$.id,display:$.display,status:"loading",reason:"模型目录正在刷新"});else if(Q==="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 Y of $.models)Z.push(C_($,Y,Q))}function C_($,Z,J){let Q="ready",Y;if(!$.enabled)Q="source_disabled",Y="所属 Token Source 未启用";else if(J==="loading"||J==="idle")Q="catalog_loading",Y="模型目录正在刷新";else if(J==="failed")Q="catalog_failed",Y=$.modelCatalogState?.error??"模型目录刷新失败";return{id:y_($.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:WY($.defaultModel)===WY(Z.model),status:Q,...Y?{reason:Y}:{},spawnRevision:$.spawnRevision}}function WY($){return $.replace(/\[1m\]$/i,"").toLowerCase()}var x9=N(()=>{_$()});import{randomUUID as f_}from"node:crypto";async function XY($,Z){if(!Z.trim()){await b($.chatId,"❌ 无法确认操作者身份,未打开 agents 面板");return}AY(),await E1();let J=`agents_${f_()}`;if(g2.set(J,{ownerOpenId:Z,page:0,createdAt:Date.now()}),!await i($.chatId,zY(J)))await b($.chatId,"❌ agents 面板发送失败")}function VY($,Z,J){let Q=h_($,J),Y=Number(Z);if(!Number.isInteger(Y))return g_("无效页码");let H=v_();return Q.page=Math.max(0,Math.min(H-1,Y)),Q.createdAt=Date.now(),{ok:!0,message:"已更新",card:zY($)}}function zY($){let Z=g2.get($);if(!Z)throw Error("Agent 身份面板已过期");let J=J1(),Q=Math.max(1,Math.ceil(J.identities.length/b9));Z.page=Math.min(Z.page,Q-1);let Y=Z.page*b9;return x7({panelId:$,page:Z.page,totalPages:Q,catalog:J.identities.slice(Y,Y+b9),failures:J.sourceFailures})}function v_(){return Math.max(1,Math.ceil(J1().identities.length/b9))}function h_($,Z){AY();let J=g2.get($);if(!J)throw Error("Agent 身份面板已过期,请重新发送 agents");if(!J.ownerOpenId||!Z||J.ownerOpenId!==Z)throw Error("只有打开该面板的用户可操作");return J}function g_($){return{ok:!1,message:$,card:E0({title:"agents",message:$,ok:!1})}}function AY(){let $=Date.now()-w_;for(let[Z,J]of g2)if(J.createdAt<$)g2.delete(Z)}var b9=8,w_=1800000,g2;var GY=N(()=>{C$();r();x9();_$();g2=new Map});var W5={};G1(W5,{withTasklistLifecycleLock:()=>v9,tasklistNameForProject:()=>w9,reconcileTasklistDeletions:()=>u_,isTasklistAlreadyDeletedError:()=>_Y,getTasklistBinding:()=>_0,enableTasklist:()=>Y5,deleteTasklistRemoteIdempotently:()=>KY,deleteTasklist:()=>H5});import{existsSync as c_,readFileSync as m_}from"node:fs";function w9($){return`${$}[lodestar]`}function _0($){let Z=G0.get($);return Z?g1(Z):null}async function v9($,Z){let J=C9.get($)??Promise.resolve(),Q,Y=new Promise((W)=>{Q=W}),H=J.catch(()=>{}).then(()=>Y);C9.set($,H),await J.catch(()=>{});try{return await Z()}finally{if(Q(),C9.get($)===H)C9.delete($)}}function _Y($){if($&&typeof $==="object"&&$.code===1470404)return!0;let Z=$ instanceof Error?$.message:String($);return/\bcode=1470404\b/.test(Z)}async function KY($,Z=K6){try{return await Z($),"deleted"}catch(J){if(_Y(J))return"already_deleted";throw J}}async function Y5($,Z){return await v9($,async()=>{let J=_0($);if(J?.deleting)throw Error(`tasklist deletion is pending for ${$}`);if(J)return J;let Q=w9($);if(Q.length>100)throw Error(`tasklist name is too long (${Q.length}/100): ${Q}`);let Y=await G6(Z),H=await _6(Q,Y),W={guid:H.guid,name:H.name,url:H.url,projectName:$,ownerOpenId:Y,createdAt:H.createdAt};return f9($,W),g1(W)})}async function H5($,Z){return await v9($,async()=>{let J=_0($);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},f9($,J);return await qY($,Z)})}async function qY($,Z){let J=_0($);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,f9($,J);try{if(await KY(Z)==="already_deleted")z(`tasklist: ${$} remote list ${Z} already deleted; finishing tombstone`);let Y=new Map(G0);return Y.delete($),BY(Y),G0.delete($),g1(J)}catch(Q){let Y=_0($);if(Y?.guid===Z&&Y.deleting)Y.deleting.lastError=Q instanceof Error?Q.message:String(Q),f9($,Y);throw Q}}async function u_(){let $=[...G0.entries()].filter(([,J])=>!!J.deleting).map(([J,Q])=>({projectName:J,guid:Q.guid})),Z=[];for(let J of $)try{await v9(J.projectName,()=>qY(J.projectName,J.guid)),z(`tasklist: reconciled pending deletion for ${J.projectName}`)}catch(Q){Z.push(`${J.projectName}: ${Q instanceof Error?Q.message:String(Q)}`)}if(Z.length)throw Error(`tasklist deletion reconcile failed: ${Z.join("; ")}`)}function p_(){if(!c_(d2))return;try{let $=JSON.parse(m_(d2,"utf8"));if(!$||typeof $!=="object")return;for(let[Z,J]of Object.entries($)){if(!J||typeof J!=="object")continue;let Q=J;if(typeof Q.guid!=="string"||!Q.guid||typeof Q.name!=="string"||!Q.name)continue;let Y={guid:Q.guid,name:Q.name,url:typeof Q.url==="string"?Q.url:"",projectName:Z,ownerOpenId:typeof Q.ownerOpenId==="string"?Q.ownerOpenId:"",createdAt:typeof Q.createdAt==="string"?Q.createdAt:void 0,deleting:l_(Q.deleting)};G0.set(Z,Y)}z(`tasklist: loaded ${G0.size} project bindings`)}catch($){z(`tasklist: load map failed: ${$}`)}}function l_($){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 f9($,Z){let J=new Map(G0);J.set($,g1(Z)),BY(J),G0.set($,g1(Z))}function BY($=G0){let Z={};for(let[J,Q]of $)Z[J]=g1(Q);X$(d2,Z)}function g1($){return JSON.parse(JSON.stringify($))}var G0,C9;var X5=N(()=>{L$();r();h();h$();G0=new Map,C9=new Map;p_()});function k0($,Z,J=!1){let Q=$.worktreeProjectName();return N7({projectName:Q,tasklistName:w9(Q),binding:_0(Q),notice:Z,confirmDelete:J})}async function RY($){if(!await i($.chatId,k0($)))await b($.chatId,"❌ task 面板发送失败")}async function PY($){let Z=$.worktreeProjectName();try{let J=_0(Z),Q=await Y5(Z,$.chatId),Y=J?"已启用":`已启用 ${Q.name}`;return{ok:!0,message:Y,card:k0($,{type:"success",content:`✅ ${Y}`})}}catch(J){let Q=`启用失败: ${D(J)}`;return z(`session "${$.sessionName}": tasklist enable failed: ${D(J)}`),{ok:!1,message:Q,card:k0($,{type:"error",content:`❌ ${Q}`})}}}function LY($,Z){let J=$.worktreeProjectName(),Q=_0(J),Y=Z.trim();if(!Q)return{ok:!1,message:"未启用",card:k0($,{type:"error",content:"❌ 未启用"})};if(Q.guid!==Y)return{ok:!1,message:"清单绑定已变化",card:k0($,{type:"error",content:"❌ 清单绑定已变化,请重新打开 task 面板"})};return{ok:!0,message:"请再次确认删除",card:k0($,{type:"error",content:"⚠️ 删除会删除所有清单内任务"},!0)}}async function DY($,Z){let J=$.worktreeProjectName(),Q=Z.trim();try{let H=`已删除 ${(await H5(J,Q)).name}`;return{ok:!0,message:H,card:k0($,{type:"success",content:`✅ ${H}`})}}catch(Y){let H=`删除失败: ${D(Y)}`;return z(`session "${$.sessionName}": tasklist delete failed: ${D(Y)}`),{ok:!1,message:H,card:k0($,{type:"error",content:`❌ ${H}`})}}}var jY=N(()=>{C$();r();h();X5()});var FY,MY,UY,OY;var EY=N(()=>{FY=["- 以 `[file: /abs/path]` 开头的文本表示该路径上挂着一个文件,相关时去读它。","- 在回复任意位置,独占一行写 `[[send: /abs/path]]` 即可把该文件作为单独一条消息送出。只在用户主动要文件、或你要交付最终产物时才发。"],MY=["- 判断是否该发文件:导出附件/数据集、用户明确要文件或下载物时,应先写到本机绝对路径,再用独占一行的 `[[send: /abs/path]]` 发给用户;短总结、普通说明、无需留存的正文答复不要为了发文件而发文件。","- 使用图片生成工具生成图片后,不要再补充说明文字或 `[[send: ...]]`;Lodestar 会根据工具返回的本机图片路径自动发给用户。若你用脚本或文件编辑生成图片,按上一条用 `[[send: /abs/path]]` 发出。","- 每次调用 Bash / shell 命令时,第一行都必须写 shell 注释 `# desc: <一句中文说明>`,再写真正命令。这个注释只给 Lodestar 卡片做摘要,不要依赖它改变命令行为。"],UY=[...FY,"- 当你有问题需要澄清时,使用 request_user_input 工具向用户提问;不要把多选题写成文本。",...MY].join(`
|
|
169
|
-
`),
|
|
170
|
-
`)});import{execFileSync as
|
|
171
|
-
`).map((H)=>H.trim()).filter(Boolean).filter((H)=>H.startsWith(I1)),Q=G5($),Y=[];for(let H of J){let W=H.slice(I1.length);if(!Y1(W))continue;let X=c1(Z,W),V=m1($,Z,W),A=Q.get(H)??null,G=!!A&&Q1(A),_=
|
|
172
|
-
`).filter(Boolean);q.statusLine=R[0]?.startsWith("## ")?R[0].slice(3):null,q.dirtyCount=R.filter((L)=>!L.startsWith("## ")).length}catch(B){q.error=_5(B)}Y.push(q)}return Y.sort((H,W)=>H.slug.localeCompare(W.slug))}function
|
|
165
|
+
`+L_($,G)+`
|
|
166
|
+
`),z3(),e7(),await z2()}var Z5=N(()=>{L$();U$();$5();_$();h$()});var J5={};G1(J5,{runTokenSourceSetup:()=>j_,onTokenSourceEnable:()=>D_});async function D_($,Z){let J=Z$(Z);if(!J){await T($.chatId,`❌ 未知 token source: ${Z}`);return}if(J.enabled){await T($.chatId,`${J.display} 已启用,发 \`model\` 选择。`);return}let Q=O1().find((Y)=>Y.setup?.commandSuffix===Z||Y.configSectionId===Z);if(Q?.setup)await T($.chatId,Q.setup.hint(J.display));else if(J.kind==="codex-subscription")await T($.chatId,`${J.display} 需要 ChatGPT 登录:在服务器执行 \`codex login\`,完成后按当前服务管理方式重启 daemon,或重发 \`model\` 刷新。`);else if(J.kind==="claude-native")await T($.chatId,`${J.display} 直接使用本机 Claude Code 配置,无需单独启用。`)}async function j_($,Z,J){let Q=O1().find((H)=>H.setup?.commandSuffix===Z);if(!Q?.setup||!Q.configSectionId){await T($.chatId,`❌ 未知或不可配置的 source: ${Z}`);return}let Y=Q.setup.parseArgs(J);if("error"in Y){await T($.chatId,Y.error);return}try{await y9(Q.configSectionId,Y.config);let H=Z$(Q.configSectionId);await T($.chatId,`✅ ${H?.display??Z} 已启用。发 \`model\` 重新选择。`)}catch(H){await T($.chatId,`❌ 启用失败: ${H?.message??H}`)}}var Q5=N(()=>{t();_$();Z5()});async function aQ($,Z,J=""){let Q=Z.trim().match(/^(?:wt|worktree)(?:\s+(.+))?$/i);if(Q)return await $.runWorktreeCommand((Q[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 Y=Z.trim().match(/^(\w+)-setup\s+([\s\S]+)$/i);if(Y){let{runTokenSourceSetup:W}=await Promise.resolve().then(() => (Q5(),J5));return await W($,Y[1].trim(),Y[2].trim()),!0}let H=F_.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(),A=X?await $.openStatusCard("hi",$.withModel(`\uD83D\uDE80 启动 ${V}`)):null,G=$.withModel(`\uD83D\uDE80 启动 ${V}`);if(!(X?await $.start({announce:!A,onStatus:(q)=>{G=q,$.setStatusCard(A,q)}}):!0))return await $.closeStatusCard(A,G.startsWith("❌")?G:"❌ 启动失败"),!0;if(A)return await $.replaceStatusCardWithConsole(A,$.withModel($.withWorktreeInstructionNotice(`✅ ${$.backendLabel()} 已就绪`))),!0;if(X)await $.closeStatusCard(A,$.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 T($.chatId,"⚪ 当前没有正在执行的 turn");return!0}z(`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)j$(X,V);T$(X,"CrossMark"),W.add(X)}for(let X of $.pendingMidTurnMsgs)if(X.msgId&&!W.has(X.msgId))T$(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()),A=X?`\uD83D\uDED1 停止 ${V}`:"⚪ session 当前未运行",G=await $.openStatusCard("kill",A,X?"red":"grey"),_=null,q=X?`✅ ${V} 已终止`:`⚪ ${V} 未运行`;try{await $.stop("已终止",{announce:!G,onStatus:(B)=>{$.setStatusCard(G,B)}})}catch(B){_=B,q=$.isRunning()?`❌ ${V} 未确认终止: ${D(B)};会话已阻断,请重试 kill/restart 或等待旧进程退出`:`❌ ${V} 停止收尾失败: ${D(B)}`}finally{try{await $.closeStatusCard(G,q)}catch(B){z(`session "${$.sessionName}": kill status card close failed: ${D(B)}`),await x($.chatId,`${q}
|
|
167
|
+
⚠️ kill 状态卡片终态写入失败: ${D(B)}`)}}if(_&&!G)await x($.chatId,q)}return!0;case"restart":if(!$.isRunning())return await $.showResumeList(J),!0;{let X=$.lastSessionId?A$($.lastSessionId):"",V=$.backendLabel($.proc?.provider??$.currentProvider()),A=$.isRunning()?$.withModel(`\uD83D\uDD01 重启 ${V}`):X?$.withModel(`\uD83D\uDD01 恢复上一会话 thread=${X}`):$.withModel(`\uD83D\uDD01 启动 ${V}`),G=await $.openStatusCard("restart",A),_=A,q=await $.restart(!0,{announce:!G,onStatus:(R)=>{_=R,$.setStatusCard(G,R)}}),B=q?_.startsWith("✅")?_:$.withWorktreeInstructionNotice(X?"✅ 已恢复上一会话":`✅ ${$.backendLabel()} 已就绪`):_.startsWith("❌")?_:"❌ 重启失败";await $.closeStatusCard(G,q?$.withModel(B):B)}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 T($.chatId,`⚪ session "${$.sessionName}" 当前未运行,clear 无效;用 \`hi\` 启动或 \`restart\` 恢复上一会话`);return!0}{let X=await $.openStatusCard("clear","\uD83E\uDDF9 清空并启动新会话","orange"),V="\uD83E\uDDF9 清空并启动新会话",A=await $.restart(!1,{announce:!X,onStatus:(G)=>{V=G,$.setStatusCard(X,G)}});await $.closeStatusCard(X,A?$.withModel($.withWorktreeInstructionNotice("✅ 已清空并启动新会话")):V.startsWith("❌")?V:"❌ 清空失败")}return!0}}var F_;var rQ=N(()=>{t();h();F_=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 O_($){let Z=!1,J=()=>{},Q=()=>{},Y=$.sessionId,H=()=>{$.off("context_compacted",V),$.off("exit",A),$.off("error",G)},W=(q)=>{if(Z)return;Z=!0,H(),J(q)},X=(q)=>{if(Z)return;Z=!0,H(),Q(q)},V=(q)=>{if(q.phase==="start")return;if(q.threadId&&Y&&q.threadId!==Y)return;W(q)},A=()=>X(Error(`${$.provider} process exited before context compaction completed`)),G=(q)=>X(q instanceof Error?q:Error(String(q))),_=new Promise((q,B)=>{J=q,Q=B});return $.on("context_compacted",V),$.once("exit",A),$.once("error",G),{promise:_,cancel(){if(Z)return;Z=!0,H()}}}function E_($,Z){let J=[],Q=new Set,Y=(X,V)=>{let A=V.threadId??Z;if(A&&X.threadId&&X.threadId!==A)return!1;if(V.turnId)return X.turnId===V.turnId;return!0},H=(X)=>{for(let V=J.length-1;V>=0;V--){let A=J[V];if(A&&Y(A,X))return A}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 A of[...Q])if(Y(V,A.notice))A.finish(V)};return $.on("token_usage",W),{waitFor(X,V){let A=H(X);if(A)return Promise.resolve(A);return new Promise((G)=>{let _=null,q={notice:X,finish:(B)=>{if(_)clearTimeout(_);Q.delete(q),G(B)}};_=setTimeout(()=>q.finish(null),V),Q.add(q)})},cancel(){$.off("token_usage",W);for(let X of[...Q])X.finish(null)}}}function T_($){if(!$)return" · \uD83E\uDDE0 MISS";let Z=I4($.usage);if(Z==null)return" · \uD83E\uDDE0 MISS";let J=c4($.contextWindow);return` · \uD83E\uDDE0 ${pZ(Z,J)} (${m4(Z,J)})`}async function tQ($){$.clearStaleIdleQueueState("compact");let Z=!$.currentTurn&&$.pendingUserMessageCount===0&&$.pendingMidTurnMsgs.length===0&&!$.openingTurn;if(!$.isRunning()||!$.proc){$.status="stopped",$.opts.onLifecycleChange?.();let A=await $.openStatusCard("compact","⚪ session 当前未运行","grey");if(A)await $.closeStatusCard(A,"⚪ 后端未运行,compact 无效");else await T($.chatId,`⚪ session "${$.sessionName}" 当前未运行,compact 无效;用 \`hi\` 启动或 \`restart\` 恢复上一会话`);return}if(!Z){let A=await $.openStatusCard("compact","⚠️ 当前 turn 正在执行","grey");if(A)await $.closeStatusCard(A,"⚠️ 先 stop 当前 turn,再 compact");else await T($.chatId,"⚠️ 当前 turn 正在执行,先 `stop` 后再 `compact`。");return}if($.manualContextCompactionPending){let A=await $.openStatusCard("compact","⏳ 上下文压缩已在进行中","grey");if(A)await $.closeStatusCard(A,"⏳ 上下文压缩已在进行中");else await T($.chatId,"⏳ 上下文压缩已在进行中。");return}let J=$.proc,Q=J.sessionId?A$(J.sessionId):"",Y=$.withModel(Q?`\uD83E\uDDE0 压缩上下文 thread=${Q}`:"\uD83E\uDDE0 压缩上下文…"),H=await $.openStatusCard("compact",Y,"orange"),W=async(A)=>{if(H)await $.closeStatusCard(H,A);else await T($.chatId,A)},X=O_(J),V=E_(J,J.sessionId);$.manualContextCompactionPending=!0;try{$.setStatusCard(H,$.withModel("\uD83E\uDDE0 发起上下文压缩")),await J.compactThread(),$.setStatusCard(H,$.withModel("⏳ 等待压缩完成事件"));let A=await X.promise,G=await V.waitFor(A,U_),_=A.threadId?` thread=${A$(A.threadId)}`:"";await W($.withModel(`✅ 上下文已压缩${_}${T_(G)}`))}catch(A){if(X.cancel(),A instanceof Q2)await W($.withModel(`ⓘ ${A.message}`));else await W(`❌ 上下文压缩失败: ${D(A)}`)}finally{V.cancel(),$.manualContextCompactionPending=!1}}var U_=1500;var sQ=N(()=>{v0();t()});import{randomUUID as S_}from"node:crypto";function N_($){let Z=$.currentTokenSource();return I0().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,selected:Z?.id===J.id}))}function eQ($,Z){let J=$.currentModelLabel(),Q=$.currentEffortLabel(),Y=$.currentTokenSource()?.id===Z.id;return Z.models.map((H)=>{let W=Y&&J===H.model;return{provider:Z.agent,sourceId:Z.id,model:H.model,displayName:H.display,description:Z.display,enabled:!0,isDefault:!1,selected:W,efforts:H.efforts.map((X)=>({effort:X,description:"",isDefault:X===H.defaultEffort,selected:W&&Q===X}))}})}async function $Y($){z2();let Z=S_(),J=N_($);if($.modelPanels.set(Z,{models:[]}),!await n($.chatId,B7({sessionName:$.sessionName,panelId:Z,currentDisplay:$.currentTokenSource()?.display??$.currentModelLabel(),providers:J})))$.modelPanels.delete(Z),await x($.chatId,"❌ 模型面板发送失败")}async function ZY($,Z,J=""){let Q=Z.trim(),Y=Z$(Q);if(!Y)return{ok:!1,message:`未知账号: ${Q}`};if(!Y.enabled)return{ok:!1,message:`${Y.display} 未配置,请先点「启用」`};let H=J.trim(),W=eQ($,Y);return $.modelPanels.set(H,{models:W}),{ok:!0,message:"",card:R7({sessionName:$.sessionName,panelId:H,currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),models:W})}}async function JY($,Z,J,Q=""){let Y=Z$(Z.trim());if(!Y)return{ok:!1,message:`未知账号: ${Z}`};if(!Y.enabled)return{ok:!1,message:`${Y.display} 未配置`};if(Y.agent!=="claude"||!Y.verifyModel)return{ok:!1,message:`${Y.display} 不支持手动补录模型`};let H=J.trim();if(!H)return{ok:!1,message:"补录面板缺少 panel_id,请重新发送 model"};return $.modelCustomPrompt={sourceId:Y.id,panelId:H,cardMessageId:Q},{ok:!0,message:"等待模型名",card:L7($.sessionName,Y.display,H)}}async function QY($,Z,J){let Q=$.modelCustomPrompt;if(!Q)return!1;$.modelCustomPrompt=null;let Y=Z.trim(),H=Z$(Q.sourceId),W=async(R)=>{if(!Q.cardMessageId)return!1;let L="",F=!1,U=!1;try{if(L=await a$(Q.cardMessageId),m$(L,1),F=await F$(L,M.modelPanel,R,{notifyCardFailure:!1}),!F)throw Error("model panel replace rejected");if(U=await q$(L,{config:{streaming_mode:!1}}),!U)throw Error("model panel streaming-off rejected")}catch(P){z(`model-custom: card update MISS (${P?.message??P})`)}finally{if(L){if(!U)try{U=await q$(L,{config:{streaming_mode:!1}})}catch(P){z(`model-custom: streaming-off retry MISS (${P?.message??P})`)}if(F&&U)try{await x$(L)}catch(P){z(`model-custom: card dispose MISS (${P?.message??P})`)}else z(`model-custom: retain card state after checked MISS mutation=${F} streamingOff=${U} card=${L.slice(0,12)}`)}}return F&&U},X=async(R,L)=>{if(await W(R))return!0;let U=`⚠️ 模型补录结果未能写回原卡。${L}
|
|
168
|
+
请重新发送 model 打开面板。`;if(!await x($.chatId,U))z(`model-custom: visible fallback send MISS (${L})`);return!1},V=(R)=>X(z9(!1,Y,R),`❌ ${Y?`模型 ${Y}`:"模型名"} 未加入:${R}。`);if(!H||!H.enabled||!H.verifyModel)return await V("账号不可用"),!0;if(!Y)return await V("模型名为空"),!0;if(H.models.some((R)=>R.model.toLowerCase()===Y.toLowerCase()))return await X(z9(!1,Y,"已在列表中"),`ℹ️ 模型 ${Y} 已在列表中,未重复加入。`),!0;let A=await H.verifyModel(Y);if(A==="not_found")return await V("端点确认不存在"),!0;if(A==="no_verdict")return await V("无法校验(端点无响应或凭据问题)"),!0;let G=[...y_(H.id),Y].join(",");try{await y8(y9(H.id,{models:G}),15000,"refreshModels")}catch(R){return z(`model-custom: config/refresh MISS (${D(R)})`),await V(`配置写入或模型刷新失败:${D(R)}`),!0}z(`model-custom: ${H.id} 补录 ${Y} by ${J}(端点校验通过,已持久化)`);let _=Z$(H.id);if(!_||_.modelCatalogState?.status!=="ready")return await V(_?.modelCatalogState?.error??"刷新后的账号目录不可用"),!0;let q=eQ($,_),B=q.find((R)=>R.model===Y);if(!B)return await V("模型已验证,但刷新后的模型列表未返回该项"),!0;return $.modelPanels.set(Q.panelId,{models:q}),await X(A9({sessionName:$.sessionName,panelId:Q.panelId,currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:B}),`✅ 模型 ${Y} 已补录成功。`),!0}function y_($){return(w.token_sources[$]?.models??"").split(",").map((J)=>J.trim()).filter(Boolean)}async function YY($,Z=""){let J=Z.trim(),Q=$.modelCustomPrompt;if(!J||!Q||Q.panelId!==J)return{ok:!1,message:"此补录面板已失效",card:V9($.sessionName,"stale")};return $.modelCustomPrompt=null,{ok:!0,message:"已取消",card:V9($.sessionName)}}function x_($,Z){return Z?.provider==="claude"||Z?.provider==="codex"?Z.provider:F1($)}function b_($,Z){if($.currentTurn)return"当前 turn 不变,后续新 turn 使用。";if($.proc?.isAlive()&&$.proc.provider===Z)return Z==="codex"?"Codex 需重启进程生效(发 restart)。":"下一轮开始使用。";return`下次启动 ${J0(Z)} 时使用。`}async function HY($,Z,J="",Q="",Y=null){let H=Z.trim();if(!H)return await T($.chatId,`❌ ${"模型为空"}`),{ok:!1,message:"模型为空"};let W=x_(H,Y),X=$.modelPanels.get(J.trim())?.models.find((V)=>V.model===H&&(V.provider??"codex")===W);if(!X)return{ok:!1,message:"模型不在当前选项中,请重新发送 model"};if(X.enabled===!1)return{ok:!1,message:`${X.displayName} 未配置,请先点「启用」`};if(X.efforts.length===0)return{ok:!1,message:"模型未返回 effort"};return{ok:!0,message:"",card:P7({sessionName:$.sessionName,panelId:J.trim(),currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:X})}}async function WY($,Z,J,Q="",Y="",H=""){let W=Z.trim(),X=J.trim();if(!W)return{ok:!1,message:"模型为空"};let V=Q.trim(),A=$.modelPanels.get(V),G=H==="claude"||H==="codex"?H:A?.models.find((P)=>P.model===W)?.provider??F1(W);if(G==="claude"){if(!d$(X))return{ok:!1,message:"Claude reasoning effort 无效"}}else if(!S$(X))return{ok:!1,message:"Codex reasoning effort 无效"};let _=X,q=A?.models.find((P)=>P.model===W&&(P.provider??"codex")===G);if(!q||!q.efforts.some((P)=>P.effort===_))return{ok:!1,message:`${J0(G)} · ${W}/${_} 不在选项中`};let B=!!q.sourceId&&$.currentTokenSource()?.id!==q.sourceId;if($.currentProvider()===G&&!B&&$.currentModelLabel()===W&&$.currentEffortLabel()===_)return $.modelPanels.delete(V),{ok:!0,message:`当前已是 ${J0(G)} · ${W} / ${_}`,card:X9({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 后再切换到 ${J0(G)}`};let F=$.currentModelLabel()!==W||B,U=!!($.currentTurn||$.openingTurn||$.pendingUserMessageCount>0||$.pendingMidTurnMsgs.length>0);if(G==="claude"&&$.proc?.isAlive()&&$.proc.provider==="claude"&&F&&U)return{ok:!1,message:"当前 Claude turn 正在执行或排队;Claude 模型 profile 通过 env 生效,请等结束或 stop 后再切换"};try{if($.proc?.isAlive()&&$.proc.provider===G&&!B){let j=q.sourceId?Z$(q.sourceId)?.resolveSpawnModel(W)??W:W;await y8($.proc.setModelSettings(j,_),20000,"thread/settings/update")}await $.applyModelSelectionUnlocked(G,W,_,q.sourceId);let P=b_($,G);return $.modelPanels.delete(V),{ok:!0,message:`已选择 ${J0(G)} · ${W} / ${_}`,card:X9({sessionName:$.sessionName,provider:G,model:W,effort:_,scope:P})}}catch(P){let j=`模型切换失败: ${D(P)}`;return z(`session "${$.sessionName}": set model settings failed: ${D(P)}`),await T($.chatId,`❌ ${j}`),{ok:!1,message:j}}}var XY=N(()=>{U$();_$();Z5();D1();v0();C$();n0();t();h()});import{createHash as f_}from"node:crypto";function w_($,Z){return`agent:${Buffer.from(`${$}\x00${Z}`,"utf8").toString("base64url")}`}function J1(){return v_(I0())}function v_($){let Z=[],J=[];for(let Q of $)h_(Q,Z,J);return{catalogGeneration:f_("sha256").update(JSON.stringify({identities:Z,sourceFailures:J})).digest("hex").slice(0,16),identities:Z,sourceFailures:J}}function h_($,Z,J){let Q=$.modelCatalogState?.status??(!$.enabled?"disabled":$.models.length>0?"ready":"idle");if(!$.enabled)J.push({tokenSourceId:$.id,display:$.display,status:"disabled",reason:"账号未启用"});else if(Q==="loading"||Q==="idle")J.push({tokenSourceId:$.id,display:$.display,status:"loading",reason:"模型目录正在刷新"});else if(Q==="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 Y of $.models)Z.push(g_($,Y,Q))}function g_($,Z,J){let Q="ready",Y;if(!$.enabled)Q="source_disabled",Y="所属 Token Source 未启用";else if(J==="loading"||J==="idle")Q="catalog_loading",Y="模型目录正在刷新";else if(J==="failed")Q="catalog_failed",Y=$.modelCatalogState?.error??"模型目录刷新失败";return{id:w_($.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:VY($.defaultModel)===VY(Z.model),status:Q,...Y?{reason:Y}:{},spawnRevision:$.spawnRevision}}function VY($){return $.replace(/\[1m\]$/i,"").toLowerCase()}var x9=N(()=>{_$()});import{randomUUID as I_}from"node:crypto";async function zY($,Z){if(!Z.trim()){await x($.chatId,"❌ 无法确认操作者身份,未打开 agents 面板");return}_Y(),await E1();let J=`agents_${I_()}`;if(I2.set(J,{ownerOpenId:Z,page:0,createdAt:Date.now()}),!await n($.chatId,GY(J)))await x($.chatId,"❌ agents 面板发送失败")}function AY($,Z,J){let Q=u_($,J),Y=Number(Z);if(!Number.isInteger(Y))return p_("无效页码");let H=m_();return Q.page=Math.max(0,Math.min(H-1,Y)),Q.createdAt=Date.now(),{ok:!0,message:"已更新",card:GY($)}}function GY($){let Z=I2.get($);if(!Z)throw Error("Agent 身份面板已过期");let J=J1(),Q=Math.max(1,Math.ceil(J.identities.length/b9));Z.page=Math.min(Z.page,Q-1);let Y=Z.page*b9;return x7({panelId:$,page:Z.page,totalPages:Q,catalog:J.identities.slice(Y,Y+b9),failures:J.sourceFailures})}function m_(){return Math.max(1,Math.ceil(J1().identities.length/b9))}function u_($,Z){_Y();let J=I2.get($);if(!J)throw Error("Agent 身份面板已过期,请重新发送 agents");if(!J.ownerOpenId||!Z||J.ownerOpenId!==Z)throw Error("只有打开该面板的用户可操作");return J}function p_($){return{ok:!1,message:$,card:E0({title:"agents",message:$,ok:!1})}}function _Y(){let $=Date.now()-c_;for(let[Z,J]of I2)if(J.createdAt<$)I2.delete(Z)}var b9=8,c_=1800000,I2;var KY=N(()=>{C$();t();x9();_$();I2=new Map});var W5={};G1(W5,{withTasklistLifecycleLock:()=>v9,tasklistNameForProject:()=>w9,reconcileTasklistDeletions:()=>d_,isTasklistAlreadyDeletedError:()=>qY,getTasklistBinding:()=>_0,enableTasklist:()=>Y5,deleteTasklistRemoteIdempotently:()=>BY,deleteTasklist:()=>H5});import{existsSync as i_,readFileSync as n_}from"node:fs";function w9($){return`${$}[lodestar]`}function _0($){let Z=G0.get($);return Z?g1(Z):null}async function v9($,Z){let J=C9.get($)??Promise.resolve(),Q,Y=new Promise((W)=>{Q=W}),H=J.catch(()=>{}).then(()=>Y);C9.set($,H),await J.catch(()=>{});try{return await Z()}finally{if(Q(),C9.get($)===H)C9.delete($)}}function qY($){if($&&typeof $==="object"&&$.code===1470404)return!0;let Z=$ instanceof Error?$.message:String($);return/\bcode=1470404\b/.test(Z)}async function BY($,Z=K6){try{return await Z($),"deleted"}catch(J){if(qY(J))return"already_deleted";throw J}}async function Y5($,Z){return await v9($,async()=>{let J=_0($);if(J?.deleting)throw Error(`tasklist deletion is pending for ${$}`);if(J)return J;let Q=w9($);if(Q.length>100)throw Error(`tasklist name is too long (${Q.length}/100): ${Q}`);let Y=await G6(Z),H=await _6(Q,Y),W={guid:H.guid,name:H.name,url:H.url,projectName:$,ownerOpenId:Y,createdAt:H.createdAt};return f9($,W),g1(W)})}async function H5($,Z){return await v9($,async()=>{let J=_0($);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},f9($,J);return await RY($,Z)})}async function RY($,Z){let J=_0($);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,f9($,J);try{if(await BY(Z)==="already_deleted")z(`tasklist: ${$} remote list ${Z} already deleted; finishing tombstone`);let Y=new Map(G0);return Y.delete($),PY(Y),G0.delete($),g1(J)}catch(Q){let Y=_0($);if(Y?.guid===Z&&Y.deleting)Y.deleting.lastError=Q instanceof Error?Q.message:String(Q),f9($,Y);throw Q}}async function d_(){let $=[...G0.entries()].filter(([,J])=>!!J.deleting).map(([J,Q])=>({projectName:J,guid:Q.guid})),Z=[];for(let J of $)try{await v9(J.projectName,()=>RY(J.projectName,J.guid)),z(`tasklist: reconciled pending deletion for ${J.projectName}`)}catch(Q){Z.push(`${J.projectName}: ${Q instanceof Error?Q.message:String(Q)}`)}if(Z.length)throw Error(`tasklist deletion reconcile failed: ${Z.join("; ")}`)}function o_(){if(!i_(o2))return;try{let $=JSON.parse(n_(o2,"utf8"));if(!$||typeof $!=="object")return;for(let[Z,J]of Object.entries($)){if(!J||typeof J!=="object")continue;let Q=J;if(typeof Q.guid!=="string"||!Q.guid||typeof Q.name!=="string"||!Q.name)continue;let Y={guid:Q.guid,name:Q.name,url:typeof Q.url==="string"?Q.url:"",projectName:Z,ownerOpenId:typeof Q.ownerOpenId==="string"?Q.ownerOpenId:"",createdAt:typeof Q.createdAt==="string"?Q.createdAt:void 0,deleting:a_(Q.deleting)};G0.set(Z,Y)}z(`tasklist: loaded ${G0.size} project bindings`)}catch($){z(`tasklist: load map failed: ${$}`)}}function a_($){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 f9($,Z){let J=new Map(G0);J.set($,g1(Z)),PY(J),G0.set($,g1(Z))}function PY($=G0){let Z={};for(let[J,Q]of $)Z[J]=g1(Q);X$(o2,Z)}function g1($){return JSON.parse(JSON.stringify($))}var G0,C9;var X5=N(()=>{L$();t();h();h$();G0=new Map,C9=new Map;o_()});function k0($,Z,J=!1){let Q=$.worktreeProjectName();return N7({projectName:Q,tasklistName:w9(Q),binding:_0(Q),notice:Z,confirmDelete:J})}async function LY($){if(!await n($.chatId,k0($)))await x($.chatId,"❌ task 面板发送失败")}async function DY($){let Z=$.worktreeProjectName();try{let J=_0(Z),Q=await Y5(Z,$.chatId),Y=J?"已启用":`已启用 ${Q.name}`;return{ok:!0,message:Y,card:k0($,{type:"success",content:`✅ ${Y}`})}}catch(J){let Q=`启用失败: ${D(J)}`;return z(`session "${$.sessionName}": tasklist enable failed: ${D(J)}`),{ok:!1,message:Q,card:k0($,{type:"error",content:`❌ ${Q}`})}}}function jY($,Z){let J=$.worktreeProjectName(),Q=_0(J),Y=Z.trim();if(!Q)return{ok:!1,message:"未启用",card:k0($,{type:"error",content:"❌ 未启用"})};if(Q.guid!==Y)return{ok:!1,message:"清单绑定已变化",card:k0($,{type:"error",content:"❌ 清单绑定已变化,请重新打开 task 面板"})};return{ok:!0,message:"请再次确认删除",card:k0($,{type:"error",content:"⚠️ 删除会删除所有清单内任务"},!0)}}async function FY($,Z){let J=$.worktreeProjectName(),Q=Z.trim();try{let H=`已删除 ${(await H5(J,Q)).name}`;return{ok:!0,message:H,card:k0($,{type:"success",content:`✅ ${H}`})}}catch(Y){let H=`删除失败: ${D(Y)}`;return z(`session "${$.sessionName}": tasklist delete failed: ${D(Y)}`),{ok:!1,message:H,card:k0($,{type:"error",content:`❌ ${H}`})}}}var MY=N(()=>{C$();t();h();X5()});var UY,OY,EY,TY;var kY=N(()=>{UY=["- 以 `[file: /abs/path]` 开头的文本表示该路径上挂着一个文件,相关时去读它。","- 在回复任意位置,独占一行写 `[[send: /abs/path]]` 即可把该文件作为单独一条消息送出。只在用户主动要文件、或你要交付最终产物时才发。"],OY=["- 判断是否该发文件:导出附件/数据集、用户明确要文件或下载物时,应先写到本机绝对路径,再用独占一行的 `[[send: /abs/path]]` 发给用户;短总结、普通说明、无需留存的正文答复不要为了发文件而发文件。","- 使用图片生成工具生成图片后,不要再补充说明文字或 `[[send: ...]]`;Lodestar 会根据工具返回的本机图片路径自动发给用户。若你用脚本或文件编辑生成图片,按上一条用 `[[send: /abs/path]]` 发出。","- 每次调用 Bash / shell 命令时,第一行都必须写 shell 注释 `# desc: <一句中文说明>`,再写真正命令。这个注释只给 Lodestar 卡片做摘要,不要依赖它改变命令行为。"],EY=[...UY,"- 当你有问题需要澄清时,使用 request_user_input 工具向用户提问;不要把多选题写成文本。",...OY].join(`
|
|
169
|
+
`),TY=[...UY,"- 当你有问题需要澄清时,使用 Claude Code 自带的 AskUserQuestion 工具向用户提问。",...OY].join(`
|
|
170
|
+
`)});import{execFileSync as t_}from"node:child_process";import{existsSync as Q1,readdirSync as s_,readFileSync as e_,realpathSync as V5,statSync as $K}from"node:fs";import{dirname as ZK,join as NY,resolve as g9}from"node:path";async function I9($,Z){let J=V5($),Q=process.platform==="win32"?J.toLowerCase():J,Y=h9.get(Q)??Promise.resolve(),H,W=new Promise((V)=>{H=V}),X=Y.catch(()=>{}).then(()=>W);h9.set(Q,X),await Y.catch(()=>{});try{return await Z()}finally{if(H(),h9.get(Q)===X)h9.delete(Q)}}function Y1($){let Z=$.trim();if(!JK.test(Z))return null;return Z}function yY($){return $.match(/^(.+)\[[^\[\]]+\]$/)?.[1]??$}function c1($,Z){return`${$}[${Z}]`}function xY($){return`${I1}${$}`}function m1($,Z,J){return NY(ZK($),c1(Z,J))}function bY($,Z,J){let Q=QK($,Z,J);if(!Q)return null;let Y=e_(Q.path,"utf8").trim();if(!Y)return null;return{path:Q.path,content:Y,slug:Q.slug}}function CY($,Z){A5($);let J=R$($,["for-each-ref","--format=%(refname:short)",`refs/heads/${I1}`]).split(`
|
|
171
|
+
`).map((H)=>H.trim()).filter(Boolean).filter((H)=>H.startsWith(I1)),Q=G5($),Y=[];for(let H of J){let W=H.slice(I1.length);if(!Y1(W))continue;let X=c1(Z,W),V=m1($,Z,W),A=Q.get(H)??null,G=!!A&&Q1(A),_=hY($,H,G),q={slug:W,chatName:X,branch:H,state:_,expectedPath:V,worktreePath:G?A:null,mounted:G,dirtyCount:null,statusLine:null,error:null};if(A&&Q1(A))try{let R=R$(A,["status","--porcelain=v1","--branch"]).split(`
|
|
172
|
+
`).filter(Boolean);q.statusLine=R[0]?.startsWith("## ")?R[0].slice(3):null,q.dirtyCount=R.filter((L)=>!L.startsWith("## ")).length}catch(B){q.error=_5(B)}Y.push(q)}return Y.sort((H,W)=>H.slug.localeCompare(W.slug))}function fY($,Z,J){let Q=Y1(J);if(!Q)throw Error(`invalid worktree name "${J}"`);A5($);let Y=xY(Q),H=c1(Z,Q),W=m1($,Z,Q),X=XK($,Y),V=G5($).get(Y)??null,A=X&&!V&&hY($,Y,!1)==="merged"?R$($,["rev-parse","HEAD"]).trim():null;if(V){if(g9(V)!==g9(W))throw Error(`branch ${Y} is already mounted at ${V}`);return vY(W,Y),{slug:Q,chatName:H,branch:Y,worktreePath:W,createdBranch:!1,createdWorktree:!1}}if(Q1(W)){if(!$K(W).isDirectory())throw Error(`${W} exists but is not a directory`);if(!X)throw Error(`${W} already exists while branch ${Y} does not`)}if(X){if(R$($,["worktree","add",W,Y]),A)R$(W,["rebase",A]);return{slug:Q,chatName:H,branch:Y,worktreePath:W,createdBranch:!1,createdWorktree:!0}}return R$($,["worktree","add","-b",Y,W,"HEAD"]),{slug:Q,chatName:H,branch:Y,worktreePath:W,createdBranch:!0,createdWorktree:!0}}function wY($,Z,J){let Q=z5($,Z,J);if(!Q1(Q.worktreePath))return Q;return R$($,["worktree","remove",Q.worktreePath]),{...Q,removedWorktree:!0}}function z5($,Z,J){let Q=Y1(J);if(!Q)throw Error(`invalid worktree name "${J}"`);A5($);let Y=xY(Q),H=c1(Z,Q),W=m1($,Z,Q),V=G5($).get(Y)??null??W;if(!Q1(V))return{slug:Q,chatName:H,branch:Y,worktreePath:V,removedWorktree:!1};vY(V,Y);let A=R$(V,["status","--porcelain=v1"]).split(`
|
|
173
173
|
`).filter(Boolean);if(A.length>0){let G=A.slice(0,8).join(`
|
|
174
174
|
`);throw Error(`worktree has uncommitted changes:
|
|
175
|
-
${G}`)}return{slug:Q,chatName:H,branch:Y,worktreePath:V,removedWorktree:!1}}function A5($){if(!Q1($))throw Error(`project directory does not exist: ${$}`);let Z=R$($,["rev-parse","--show-toplevel"]).trim();if(V5(Z)!==V5($))throw Error(`${$} is not the git repository root (${Z})`)}function
|
|
176
|
-
`)){if(Y.startsWith("worktree ")){Q=Y.slice(9);continue}if(Y.startsWith("branch refs/heads/")&&Q)Z.set(Y.slice(18),Q)}return Z}function R$($,Z){try{return
|
|
177
|
-
${Q}`:J}function
|
|
178
|
-
${J}`:Z}function
|
|
179
|
-
`)}async function
|
|
180
|
-
${H}`,card:
|
|
181
|
-
`),type:"success"}})}catch(W){H={ok:!1,message:`❌ 解散 ${J} 失败: ${D(W)}`,type:"error"}}return
|
|
182
|
-
`)){let H=Y.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(!Q&&W.type==="user"&&W.message){let X=OK(W.message);if(X)Q=X}}return Q.slice(0,80)}function OK($){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 rY($,Z,J){if(!J){await E($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let Q=DK($),Y=jK($),H=new Map,W=[];for(let G=0;G<Q.length;G++){let _=Q[G];if(G===0&&Y===null)continue;let q=R5(),B=G===0?Y:LK(Q[G-1].checkpoint);H.set(q,{kind:Z,launch:B,branchBase:Y,seedAnchors:Q.slice(0,G),writes:Q.slice(G).flatMap((R)=>R.writes)}),W.push({choiceId:q,preview:_.preview,ts:_.ts})}W.reverse();let X=aY($,Z,J,H),V=M7({projectName:m9($),panelId:X.id,mode:Z,entries:W}),A;try{A=await i($.chatId,V)}catch(G){throw p1($).delete(X.id),G}if(!A)p1($).delete(X.id),await b($.chatId,`❌ ${Z==="fork"?"fk":"bk"} 列表发送失败`)}function tY($,Z){return rY($,"fork",Z)}function sY($,Z){return rY($,"back",Z)}async function eY($,Z){if(!Z){await E($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let J;try{J=$.selectedProvider==="codex"?await $.listCodexConversations():FK($.workDir)}catch(V){await b($.chatId,`❌ 历史会话读取失败: ${V instanceof Error?V.message:V}`);return}let Q=new Map,Y=MK(J).map((V)=>{let A=R5();return Q.set(A,{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:A,preview:V.preview,ts:V.ts}}),H=aY($,"resume",Z,Q),W=U7({projectName:m9($),panelId:H.id,entries:Y}),X;try{X=await i($.chatId,W)}catch(V){throw p1($).delete(H.id),V}if(!X)p1($).delete(H.id),await b($.chatId,"❌ rs 历史列表发送失败")}async function $H($,Z){if(!Z){await E($.chatId,"❌ 找不到发起人,无法建临时群。");return}if(!$.opts.onCreateTempSession){await E($.chatId,"❌ 临时群能力未就绪(daemon 未注入回调)。");return}let J=dY(m9($));await E($.chatId,`\uD83D\uDE80 正在创建 ${J} · ${$.backendLabel()} 新会话。它与当前群共享工作目录;当前会话不受影响。`);let Q;try{Q=await $.opts.onCreateTempSession({chatName:J,userOpenId:Z,workDir:$.workDir,routing:$.conversationRouting(),launch:{kind:"fresh"},branchBase:{kind:"fresh"},seedAnchors:[]})}finally{oY(J)}if(!Q.ok){await E($.chatId,`❌ 建临时会话失败: ${Q.error??"未知"}`);return}await E($.chatId,`✅ 已创建 ${J}。临时群不会自动删除;在该群发送 bye 可停止并解散。`)}async function ZH($){if(!o$($.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 JH($,Z,J,Q){let Y=P5($,"fork",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:H,choice:W}=Y;try{if(W.kind!=="fork")return{ok:!1,message:"选择项类型不匹配"};if(!$.opts.onCreateTempSession)return{ok:!1,message:"临时群能力未就绪"};let X=dY(H.baseName);z(`session-temp: fork ${$.sessionName} → ${X} (${W.launch.kind})`),await E($.chatId,`\uD83D\uDD31 正在分叉到 ${X}…`);let V;try{V=await $.opts.onCreateTempSession({chatName:X,userOpenId:Q,workDir:H.workDir,routing:H.routing,launch:W.launch,branchBase:W.branchBase,seedAnchors:W.seedAnchors})}finally{oY(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{c9(H)}}async function QH($,Z,J,Q){let Y=P5($,"back",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:H,choice:W}=Y;try{if(W.kind!=="back")return{ok:!1,message:"选择项类型不匹配"};let X="";try{if(!await i($.chatId,O7({projectName:H.baseName,entries:W.writes})))X=";文件变更记录卡发送失败"}catch(G){X=`;文件变更记录卡发送失败: ${G instanceof Error?G.message:G}`}if(z(`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?` ${A$($.lastSessionId)}`:""};旧会话未删除,磁盘文件未回滚${X}`}}catch(X){return{ok:!1,message:`回退失败: ${X instanceof Error?X.message:X}`}}finally{c9(H)}}async function YH($,Z,J,Q){let Y=P5($,"resume",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:H,choice:W}=Y;if(W.kind!=="resume")throw c9(H),Error("resume panel contained a non-resume choice");let X=W.launch.source.sessionId,V=$.lastSessionId,A=(_,q)=>({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:q}),G=(_,q,B,R=null)=>({ok:_,message:q,resumePresentation:A(R,B)});try{if($.isRunning())return G(!1,"当前群已经启动了新进程;为避免误杀,请先停止后重新发送 rs","unchanged");if(W.sourceStatus==="active")return G(!1,"所选 Codex 会话仍在运行;请先在原位置停止后再创建完整分支","unchanged");if(z(`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 q=$.lastSessionId;if(!q)return G(!1,"历史分支已启动,但后端没有返回新会话 id","unknown");if(q===X||V&&q===V)return G(!1,"后端没有返回独立的新会话 id;为避免误判,本次不标记为恢复成功","unknown",q);return G(!0,"已创建并接入独立分支;源会话未修改","changed",q)}catch(_){return G(!1,`历史分支创建失败: ${_ instanceof Error?_.message:_}`,"unknown")}finally{c9(H)}}var KK=86400000,qK=1800000,BK=3600000,RK=40,nY,B5;var HH=N(()=>{r();C$();h();j4();X4();P1();nY=new WeakMap,B5=new Set});import{existsSync as WH}from"node:fs";import{randomBytes as TK,timingSafeEqual as kK}from"node:crypto";import{isAbsolute as SK}from"node:path";function D5($,Z=new Set){if($ instanceof G4)return $;if(!$||typeof $!=="object"&&typeof $!=="function"||Z.has($))return null;if(Z.add($),$ instanceof AggregateError)for(let J of $.errors){let Q=D5(J,Z);if(Q)return Q}if($ instanceof Error&&$.cause!==void 0)return D5($.cause,Z);return null}function NK($){return $.itemId||$.turnId||"__latest__"}function XH($){let Z=[];if($.itemId)Z.push(`item:${$.itemId}`);if($.turnId)Z.push(`turn:${$.threadId??$.sessionId??"-"}:${$.turnId}`);return Z}function yK($){let Z=null;for(let J of $.contextCompactionPending.keys())Z=J;return Z}function xK($,Z){if(!$)return Z;return{...$,...Z,phase:"end"}}function H1(){return w.runtime?.live_elapsed??"bucket"}function zH($,Z){return`${$} (${R0(Date.now()-Z,H1()).label})`}var bK="Thinking...",CK="Writing...",fK="Working...",L5=1e4,u9=120000,wK=50,c2=5,vK=256,p9=1e4,VH=250,W1;var AH=N(()=>{D1();r8();v0();U$();A6();_$();j4();n0();C$();r();h();L$();_7();M9();O9();m7();VQ();FQ();EQ();t7();bQ();oQ();rQ();HY();GY();jY();iY();HH();P1();W1=class W1{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;W1.all.add(this);let Q=b6($);this.selectedProvider=Q?.provider??"claude",this.selectedModel=Q?.model??null,this.selectedEffort=Q?.effort??null,this.selectedTokenSourceId=this.deriveTokenSourceId(Q);let Y=$$(this.selectedTokenSourceId);if(Y){if(this.selectedProvider=Y.agent,Y.id==="glm"&&this.selectedModel==="claude:glm")this.selectedModel=Y.defaultModel,this.selectedEffort="max";if(Y.id==="claude-native"&&this.selectedModel&&!Y.models.some((W)=>W.model===this.selectedModel))this.selectedModel=Y.defaultModel}if(this.selectedModel)z(`session "${$}": restored selected provider=${this.selectedProvider} model=${this.selectedModel} effort=${this.selectedEffort??"unset"}`);if(this.lastSessionRef=p0($,this.selectedProvider),this.lastSessionId=this.lastSessionRef?.sessionId??null,this.lastSessionId)z(`session "${$}": restored ${this.selectedProvider} lastSessionId=${this.lastSessionId}`);let H=B2($);if(H)if(this.selectedProvider!=="claude")I$($,[],null,null),z(`session "${$}": cleared pending Claude fork after provider changed`);else{G$(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,z(`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 gY(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 M4(J==="codex"?"codex":"claude")[0]?.id??null}currentTokenSource(){return $$(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=$$($.tokenSourceId);if(Z&&Z.agent!==$.provider)throw Error(`token source "${Z.id}" belongs to ${Z.agent}, not ${$.provider}`);if(this.selectedProvider!==$.provider)I$(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$.provider,this.selectedTokenSourceId=$.tokenSourceId,this.selectedModel=$.model,this.selectedEffort=$.effort,this.lastSessionRef=p0(this.sessionName,$.provider),this.lastSessionId=this.lastSessionRef?.sessionId??null,x6(this.sessionName,$.provider,$.model,$.effort,$.tokenSourceId)}async listCodexConversations(){if(this.selectedProvider!=="codex")throw Error("Codex history requested for a non-Codex session");if(!D2())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,Q=new L1({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Z?.id??null,transformEnv:J}),Y=null,H=null;try{Y=await Q.listConversations()}catch(X){H=X}let W=null;try{await Q.kill(2000)}catch(X){W=X}if(H&&W)throw AggregateError([H,W],`Codex history query and cleanup failed: ${D(H)}; ${D(W)}`);if(H)throw H;if(W)throw W;return Y??[]}async resolveLegacyResumeRef($){if($.cwd!==null)return $;if($.provider!==this.selectedProvider)throw Error(`legacy resume provider mismatch: ${$.provider} != ${this.selectedProvider}`);let Z;if($.provider==="claude"){let J=H6(this.workDir,$.sessionId);if(!WH(J))throw Error(`旧 Claude 会话不属于当前 cwd,或 transcript 不存在: ${A$($.sessionId)}`);Z={...$,cwd:this.workDir}}else{if(!D2())throw Error("Codex 未登录 ChatGPT 账号");let J=this.currentTokenSource();if(this.selectedTokenSourceId&&(!J||!J.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或选择其他账号`);let Q=J?.enabled?J:void 0,Y=new L1({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Q?.id??null,transformEnv:Q?(X)=>Q.spawnEnv(X):void 0}),H=null;try{Z=await Y.readConversationRef($.sessionId)}catch(X){H=X,Z=$}let W=null;try{await Y.kill(2000)}catch(X){W=X}if(H&&W)throw AggregateError([H,W],`Codex legacy resume lookup and cleanup failed: read=${D(H)}; cleanup=${D(W)}`);if(H)throw H;if(W)throw W}return G$({kind:"resume",source:Z},this.selectedProvider,this.workDir),_2(this.sessionName,Z),Z}hasRunningPeerSession($){return[...W1.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 S$(this.selectedEffort)?this.selectedEffort:$2}return $2}claudeEffortForSpawn(){return this.selectedProvider==="claude"&&d$(this.selectedEffort)?this.selectedEffort:P0}currentModelLabel(){return(this.selectedModel??this.currentTokenSource()?.defaultModel??this.proc?.lastModel??null)?.replace(/^claude:/i,"").replace(/\[1m\]$/i,"")??null}currentEffortLabel(){return this.selectedEffort??this.proc?.lastEffort??(this.selectedProvider==="claude"?P0:$2)}runtimeModelSelection(){let $=this.proc?.isAlive()?this.proc:null,Z=$?.provider??this.selectedProvider,J=!$||$.provider===this.selectedProvider,Q=($?.lastModel??(J?this.currentModelLabel():null))?.replace(/^claude:/i,"").replace(/\[1m\]$/i,"")??null,Y=$?.lastEffort??(J?this.currentEffortLabel():Z==="claude"?P0:$2);return{provider:Z,model:Q,effort:Y}}modelEffortLabel($=this.currentTurn??this.runtimeModelSelection()){let Z=$.provider==="claude"?$.model?.replace(/^claude:/i,"").replace(/\[1m\]$/i,""):$.model,J=Z?`${Z}/${$.effort}`:$.effort;return $.provider==="claude"?`${J0($.provider)} · ${J}`:J}withModel($,Z){let J=this.modelEffortLabel(Z);return $.includes(J)?$:`${$} · ${J}`}replaceFooterContent($,Z){return o($,M.footer,this.footerElement(Z),void 0,!1)}footerElement($){return{tag:"markdown",element_id:M.footer,content:$.trim()||" "}}modelLine($){return this.modelEffortLabel($)}backendLabel($=this.selectedProvider){return J0($)}pendingConversationLaunch=null;pendingConversationMaterialization=null;lastTurnUserPreview="";pendingCodexTurnAnchors=[];pendingMaterializationLaunch(){let $=this.pendingConversationMaterialization;if(!$)return null;if(G$($.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=TK(32).toString("base64url");let Z={LODESTAR_AGENT_URL:E4(w.notify.bind,w.notify.port),LODESTAR_AGENT_CAPABILITY:this.agentCapability,LODESTAR_AGENT_SESSION:this.sessionName},J=this.pendingConversationLaunch??this.pendingMaterializationLaunch()??($?{kind:"resume",source:$}:{kind:"fresh"});G$(J,this.selectedProvider,this.workDir);let Q=this.currentTokenSource();if(this.selectedTokenSourceId&&(!Q||!Q.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或在 model 面板选择其他账号`);let Y=Q?.enabled?Q:void 0,H=O4({provider:this.selectedProvider,workDir:this.workDir,tokenSourceId:Y?.id??null,model:Y?this.selectedModel??Y.defaultModel:this.modelForSpawn(),effort:this.selectedProvider==="claude"?this.claudeEffortForSpawn():this.effortForSpawn(),launch:J,developerInstructions:this.spawnDeveloperInstructions(),profile:k1(this.worktreeProjectName()),...process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"?{}:{managedSkillPluginPath:x0},hostEnv:Z});return this.procSourceRevisions.set(H.process,H.sourceRevision),H.process}async applyModelSelection($,Z,J,Q){await this.runLifecycle("apply-model-selection",()=>this.applyModelSelectionUnlocked($,Z,J,Q))}async applyModelSelectionUnlocked($,Z,J,Q){if(this.selectedProvider!==$)I$(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$,this.selectedTokenSourceId=Q??this.selectedTokenSourceId;let H=$$(this.selectedTokenSourceId);if(H)this.selectedModel=Z||null,this.selectedEffort=J??H.models.find((W)=>W.model===Z)?.defaultEffort??H.models[0]?.defaultEffort??null;else this.selectedModel=$==="codex"?null:Z,this.selectedEffort=$==="codex"?null:J;this.lastSessionRef=p0(this.sessionName,$),this.lastSessionId=this.lastSessionRef?.sessionId??null,y6(this.sessionName,$,this.selectedModel,this.selectedEffort,this.selectedTokenSourceId),await this.stopIdleMismatchedProcessUnlocked()}async stopIdleMismatchedProcess(){await this.runLifecycle("stop-idle-mismatched",()=>this.stopIdleMismatchedProcessUnlocked())}async stopIdleMismatchedProcessUnlocked(){if(!this.proc?.isAlive())return;let $=this.currentTokenSource(),Z=!this.procSourceRevisions.has(this.proc)||this.procSourceRevisions.get(this.proc)===($?.spawnRevision??null);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;z(`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 Q=await this.settleProcResumableState(J),Y=null;try{await J.kill(1000)}catch(X){Y=X}Q=await this.settleProcResumableState(J);let H=this.finishProcStop(J,Y);this.opts.onLifecycleChange?.();let W=[...!H?[Y??Error(this.blockedProcReason??"process stop unconfirmed")]:[],...Q?[Error(Q)]:[]];if(W.length===1)throw W[0];if(W.length>1)throw AggregateError(W,`idle process stop failed: ${W.map(D).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;z(`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),Q=null;try{await Z.kill(1000)}catch(W){Q=W}J=await this.settleProcResumableState(Z);let Y=this.finishProcStop(Z,Q);this.opts.onLifecycleChange?.();let H=[...!Y?[Q??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(D).join("; ")}`);return!0}startFooterTimer($,Z,J=(Q)=>Q){let Q=Date.now(),Y=Z,H=!1,W=()=>{if(H)return;this.replaceFooterContent($,J(zH(Y,Q)))},X=null,V=()=>{if(H)return;let{nextDelayMs:A}=R0(Date.now()-Q,H1());X=setTimeout(()=>{W(),V()},Math.max(1,Math.ceil(A)))};return W(),V(),{setStatus(A){Y=A,W()},stop(){if(H=!0,X)clearTimeout(X)},elapsedSec(){return((Date.now()-Q)/1000).toFixed(1)}}}async openStatusCard($,Z,J="blue"){let Q=Date.now(),Y=K7({sessionName:this.sessionName,title:$,status:zH(Z,Q),template:J}),H=await i(this.chatId,Y);if(!H)return z(`session "${this.sessionName}": status card send failed title=${$}`),await b(this.chatId,`❌ 创建状态卡片失败: ${$}`),null;let W;try{W=await a$(H)}catch(X){return z(`session "${this.sessionName}": status card id_convert failed title=${$}: ${X}`),await b(this.chatId,`❌ 状态卡片初始化失败: ${$}`),null}return m$(W,1),{cardId:W,title:$,timer:this.startFooterTimer(W,Z,(X)=>b2($,X))}}setStatusCard($,Z){$?.timer.setStatus(Z)}async closeStatusCard($,Z){if(!$)return;$.timer.stop();let J=$.timer.elapsedSec(),Q=b2($.title,`${Z} (${J}s)`);await u$($.cardId);let Y=await F$($.cardId,M.footer,this.footerElement(Q));V$($.cardId);let H=await q$($.cardId,A0({durationSec:J,suffix:Z}));if(Y&&H)await x$($.cardId);else{let W=`footer=${Y?"ok":"MISS"}, settings=${H?"ok":"MISS"}`;z(`session "${this.sessionName}": status card terminal transaction incomplete card=${$.cardId.slice(0,12)} ${W}`),await b(this.chatId,`⚠️ 状态卡片终态写入失败 (${W}):${Z}`)}}async runLifecycle($,Z){let J=this.lifecycleTail,Q;this.lifecycleTail=new Promise((H)=>{Q=H}),await J;let Y=++this.lifecycleSequence;z(`session "${this.sessionName}": lifecycle#${Y} ${$} begin`);try{return await Z()}finally{Q(),z(`session "${this.sessionName}": lifecycle#${Y} ${$} 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 Q,Y=new Promise((W)=>{Q=W}),H={token:++this.turnOpenSequence,proc:$,procEpoch:Z,sawResult:!1,terminalForcePush:!1,pendingCompactions:[],backendTurnStarted:J,done:Y,resolveDone:Q};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),Q=Buffer.from($);return J.length===Q.length&&kK(J,Q)}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?D(Z):"kill returned while process still reports alive",z(`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(Q){J=Q}return this.finishProcStop($,J)}async settleProcResumableState($){let Z=null,J=$.conversationMaterializationBarrier?.();if(J)try{await J}catch(H){Z=`Codex 会话落盘确认失败: ${D(H)}`}let Q=$.conversationMaterializationFailure?.();if(Q&&$.isConversationResumable?.()!==!0)Z=`Codex 会话落盘确认失败: ${D(Q)}`;let Y=this.persistResumableSessionId(!1,$,!1);return[Z,Y].filter(Boolean).join(";")||null}resetFreshConversationState(){this.turnCounter=0,this.pendingConversationMaterialization=null,I$(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,Q=this.blockedProcessMessage();if(Q){if(this.status="stopped",J?.(`❌ ${Q}`),Z)await E(this.chatId,`❌ ${Q}。请重试 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"&&!D2()){if(this.status="stopped",this.opts.onLifecycleChange?.(),J?.("❌ Codex 未登录 ChatGPT 账号"),Z)await E(this.chatId,"❌ Codex 未登录 ChatGPT 账号。\n请在服务器上运行 `codex login` 后再试。");return!1}if(!WH(this.workDir)){if(J?.(`\uD83C\uDD95 创建项目目录 ~/${this.sessionName}`),Z)await E(this.chatId,`\uD83C\uDD95 目录 ~/${this.sessionName} 不存在,正在创建…`);try{u6(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 Y;try{await U4(),Y=this.spawnAgent()}catch(G){let _=`${this.backendLabel()} 启动失败: ${D(G)}`;if(z(`session "${this.sessionName}": ${_}`),J?.(`❌ ${_}`),Z)await E(this.chatId,`❌ ${_}`);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}this.attachProc(Y);let H=this.backendLabel(),W=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(Y,VH):null;J?.(this.selectedProvider==="claude"?`⏳ 检查 ${H} 启动`:`⏳ 等待 ${H} init`);let X,V=null;try{if(Y.sendInitialize(),this.selectedProvider==="codex")X=Y.initializationPromise?.()}catch(G){X=void 0,V=G}let A=V?{state:"error",error:V}:this.selectedProvider==="claude"?await W:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(X),()=>{z(`session "${this.sessionName}": codex init still pending after ${L5/1000}s`),J?.(this.withModel(`⏳ 仍在等待 ${H} init 确认`))});if(A.state==="error"||A.state==="exit"){let G=A.error?D(A.error):A.state;z(`session "${this.sessionName}": ${this.selectedProvider} init failed: ${G}`);let q=await this.stopOwnedProc(Y,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,B=`❌ ${H} 启动失败: ${G}${q}`;if(J?.(B),Z)await E(this.chatId,B);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(A.state==="timeout"){z(`session "${this.sessionName}": ${this.selectedProvider} init wait timeout (${u9/1000}s)`);let _=await this.stopOwnedProc(Y,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,q=`❌ ${H} 启动超时: ${u9/1000} 秒内初始化事务未完成${_}`;if(J?.(q),Z)await E(this.chatId,q);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(this.proc!==Y||!Y.isAlive()){let G=`${H} 启动期间已退出`;if(z(`session "${this.sessionName}": ${G}`),J?.(`❌ ${G}`),Z)await E(this.chatId,`❌ ${G}`);return this.detachProc(Y),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(`
|
|
183
|
-
`))}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 Q=!1,Y=(X,V)=>{if(Q)return;Q=!0,clearTimeout(H),clearTimeout(W),J({state:X,error:V})},H=setTimeout(()=>{if(Q)return;try{Z?.()}catch(X){Y("error",X)}},L5),W=setTimeout(()=>{Y("timeout",Error(`codex init timed out after ${u9/1000}s`))},u9);$.then(()=>Y("init"),(X)=>Y("error",X))})}async waitForProcEarlyFailure($,Z){return await new Promise((J)=>{let Q=!1,Y=(A,G)=>{if(Q)return;Q=!0,clearTimeout(H),$.off("init",W),$.off("error",X),$.off("exit",V),J({state:A,error:G})},H=setTimeout(()=>Y("ready"),Z),W=()=>Y("init"),X=(A)=>Y("error",A),V=(A)=>Y("exit",A);$.once("init",W),$.once("error",X),$.once("exit",V)})}releaseAllReactions(){for(let[$,Z]of[...this.pendingReactionIds.entries(),...this.currentBatchReactionIds.entries()])if(Z)j$($,Z);this.pendingReactionIds=new Map,this.currentBatchReactionIds=new Map}clearStaleIdleQueueState($){if(this.initCount<1||this.currentTurn||this.openingTurn||this.pendingUserMessageCount===0)return;z(`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)j$(Z,J);this.pendingReactionIds=new Map}async stop($="已终止",Z={}){await this.runLifecycle("stop",()=>this.stopUnlocked($,Z))}async stopUnlocked($="已终止",Z={}){let J=Z.announce??!0,Q=Z.onStatus;if(await this.cancelAgentRuns($),!this.proc){if(this.status="stopped",this.opts.onLifecycleChange?.(),Q?.("⚪ session 当前未运行"),J)await E(this.chatId,`⚪ session "${this.sessionName}" 当前未运行`);return}let Y=this.proc,H=this.persistResumableSessionId(!1,Y,!1),W=null;if(Q?.(`\uD83D\uDED1 停止 ${this.backendLabel(this.proc.provider)}`),z(`session "${this.sessionName}": stop (${$})`),this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.currentTurn)this.closeTurnCard(`\uD83D\uDED1 ${$}`).catch((F)=>{z(`session "${this.sessionName}": stop current main-card close failed: ${D(F)}`)});let X=this.waitForTurnCloses().catch((F)=>z(`session "${this.sessionName}": stop main-card close failed: ${D(F)}`));this.beginProcStop(Y),this.status="stopped";let V=[];try{this.opts.onLifecycleChange?.()}catch(F){V.push(F),z(`session "${this.sessionName}": stop intent lifecycle write failed: ${D(F)}`)}let A=Y.conversationMaterializationBarrier?.();if(A){try{await A}catch(F){W=`Codex 会话落盘确认失败: ${D(F)}`}H=this.persistResumableSessionId(!1,Y,!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 Y.kill()}catch(F){G=F}let _=Y.conversationMaterializationFailure?.();if(_&&Y.isConversationResumable?.()!==!0)W=`Codex 会话落盘确认失败: ${D(_)}`;H=this.persistResumableSessionId(!1,Y,!1);let B=(await Promise.allSettled([this.resetBackgroundTasks(),X])).filter((F)=>F.status==="rejected").map((F)=>F.reason);for(let F of B)z(`session "${this.sessionName}": stop terminal cleanup failed: ${D(F)}`);let R=this.finishProcStop(Y,G);try{this.opts.onLifecycleChange?.()}catch(F){V.push(F),z(`session "${this.sessionName}": stop final lifecycle write failed: ${D(F)}`)}let L=[...G?[G]:[],...!R&&!G?[Error(this.blockedProcReason??"process stop unconfirmed")]:[],...B,...V,...H?[Error(H)]:[],...W&&Y.isConversationResumable?.()!==!0?[Error(W)]:[]];if(L.length===1)throw L[0];if(L.length>1)throw AggregateError(L,`stop failed: ${L.map(D).join("; ")}`);if(Q?.(`✅ ${$}`),J)await E(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 Q=Z.announce??!0,Y=Z.onStatus,H=this.status,W=null;if(!$&&!this.pendingConversationLaunch&&this.pendingConversationMaterialization)W=this.pendingConversationMaterialization,D0(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(O){let T=this.invalidateMissingCodexResume(V.sessionId,O,J),m=T?`❌ 旧会话不可恢复: ${D(O)};${T}`:`❌ 旧会话 cwd 校验失败: ${D(O)};请在进程已停时发送 rs 重新选择历史会话`;if(this.status=this.proc?.isAlive()?H:"stopped",Y?.(m),Q)await E(this.chatId,m);return!1}let A=V?.sessionId??null,G=X&&X.kind!=="fresh"?X.source.sessionId:A,_=G?A$(G):"",q=null,B=(O=this.proc)=>{if(!$||X||O?.provider!=="codex"||O.isConversationResumable?.()!==!0)return;q=this.persistResumableSessionId(!1,O,!1),V=this.lastSessionRef,A=V?.sessionId??null,G=A,_=G?A$(G):""},R=null;if(!Y&&Q&&$&&A){let O=this.proc?this.withModel(`\uD83D\uDD01 重启 ${this.backendLabel(this.proc.provider)}`):this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${_}`);if(R=await this.openStatusCard("restart",O),R)Y=(T)=>this.setStatusCard(R,T)}let L=Q&&!R,F=async(O)=>{if(R)await this.closeStatusCard(R,O)},U=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((O)=>{z(`session "${this.sessionName}": restart current main-card close failed: ${D(O)}`)});let P=this.waitForTurnCloses().catch((O)=>z(`session "${this.sessionName}": restart main-card close failed: ${D(O)}`)),j=null,k=null;if(this.proc){let O=this.proc;Y?.(`\uD83D\uDED1 停止当前 ${this.backendLabel(O.provider)}`),k=O,this.beginProcStop(O);let T=O.conversationMaterializationBarrier?.();if(T)try{await T}catch(u){q=`Codex 会话落盘确认失败: ${D(u)}`}if(B(O),$&&!X&&q&&!U&&O.isAlive()){if(this.stoppingProc===O)this.stoppingProc=null;this.status=H;let u=`❌ ${this.backendLabel(O.provider)} 恢复点尚未安全落盘,已保留当前进程: ${q}`;if(z(`session "${this.sessionName}": abort restart before kill: ${q}`),Y?.(u),L)await E(this.chatId,u);return await F(u),!1}try{await O.kill()}catch(u){j=u}let m=O.conversationMaterializationFailure?.();if(m&&O.isConversationResumable?.()!==!0)q=`Codex 会话落盘确认失败: ${D(m)}`;B(O)}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 x=(await Promise.allSettled([this.resetBackgroundTasks(),P])).filter((O)=>O.status==="rejected").map((O)=>O.reason);for(let O of x)z(`session "${this.sessionName}": restart terminal cleanup failed: ${D(O)}`);let c=k?this.finishProcStop(k,j):!0,v=[...j?[`kill=${D(j)}`]:[],...!c&&!j?[`kill=${this.blockedProcReason??"process stop unconfirmed"}`]:[],...x.map((O)=>`cleanup=${D(O)}`),...q?[`resume=${q}`]:[]];if(v.length>0&&W)try{D0(this.sessionName,W),this.pendingConversationMaterialization=W}catch(O){v.push(`pendingRestore=${D(O)}`)}if(v.length>0){let O=`❌ 旧 ${this.backendLabel()} 进程停止/清理失败: ${v.join("; ")}`;if(this.status="stopped",this.opts.onLifecycleChange?.(),Y?.(O),L)await E(this.chatId,O);return await F(O),!1}let g=X?.kind==="resume"||X?.kind==="fork";if($&&V||g){this.status="starting",this.usageTotalsSeedUnknown=!0,Y?.(this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${_}`));let O;try{await U4(),O=this.spawnAgent(V??void 0)}catch(W$){let M$=`❌ ${this.backendLabel()} 恢复失败: ${D(W$)}`;if(z(`session "${this.sessionName}": ${this.selectedProvider} resume failed before spawn: ${D(W$)}`),Y?.(M$),L)await E(this.chatId,M$);return this.status="stopped",this.opts.onLifecycleChange?.(),await F(M$),!1}this.attachProc(O);let T=this.backendLabel(),m=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(O,VH):null;Y?.(this.selectedProvider==="claude"?`⏳ 检查 ${T} 恢复启动`:`⏳ 等待 ${T} init 确认`);let u,S=null;try{if(O.sendInitialize(),this.selectedProvider==="codex")u=O.initializationPromise?.()}catch(W$){u=void 0,S=W$}let y=S?{state:"error",error:S}:this.selectedProvider==="claude"?await m:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(u),()=>{z(`session "${this.sessionName}": codex resume init still pending after ${L5/1000}s`),Y?.(this.withModel(`⏳ 仍在等待 ${T} init 确认 thread=${_}`))});if(y.state==="error"||y.state==="exit"||y.state==="timeout"){let W$=y.state==="error"?this.invalidateMissingCodexResume(G,y.error,J):null,M$=[y.error?D(y.error):y.state,W$].filter(Boolean).join(";");z(`session "${this.sessionName}": ${this.selectedProvider} resume failed: ${M$}`);let a1=await this.stopOwnedProc(O,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,A1=y.state==="timeout"?`❌ ${T} 恢复超时${a1}`:`❌ ${T} 恢复失败: ${M$}${a1}`;if(Y?.(A1),L)await E(this.chatId,A1);return this.status="stopped",this.opts.onLifecycleChange?.(),await F(A1),!1}if(this.proc!==O||!O.isAlive()){let W$=`❌ ${T} 恢复期间已退出`;if(z(`session "${this.sessionName}": ${this.selectedProvider} resume process exited before ready`),Y?.(W$),L)await E(this.chatId,W$);return this.detachProc(O),this.status="stopped",this.opts.onLifecycleChange?.(),await F(W$),!1}let n=this.withModel(this.withWorktreeInstructionNotice(this.selectedProvider==="claude"&&y.state==="ready"?`✅ 已准备恢复上一会话 thread=${_}`:`✅ 已恢复上一会话 thread=${_}`));if(Y?.(n),L)await E(this.chatId,n);this.status="idle",this.startedAt=Date.now(),this.opts.onLifecycleChange?.();try{await F(n)}catch(W$){z(`session "${this.sessionName}": restart succeeded but status-card close failed: ${D(W$)}`),await b(this.chatId,`⚠️ ${n}
|
|
184
|
-
状态卡收尾失败: ${D(W$)}`)}return!0}else{if($&&!X){if(Y?.("⚠️ 没有可恢复的上一会话,将以新会话启动"),L)await E(this.chatId,"⚠️ 没有可恢复的上一会话,将以新会话启动")}return this.resetFreshConversationState(),await this.startUnlocked({...Z,freshConversationStateAlreadyReset:!0})}}async startForked($,Z={}){return await this.runLifecycle("start-forked",async()=>{G$($,this.selectedProvider,this.workDir);let J=B2(this.sessionName),Q=this.selectedProvider==="claude"?{launch:$,previousSessionId:this.lastSessionId}:null;if(Q)D0(this.sessionName,Q),this.pendingConversationMaterialization=Q;this.pendingConversationLaunch=$;try{let Y=await this.startUnlocked(Z);if(!Y&&Q)D0(this.sessionName,J),this.pendingConversationMaterialization=J;return Y}catch(Y){if(!Q)throw Y;try{D0(this.sessionName,J),this.pendingConversationMaterialization=J}catch(H){throw AggregateError([Y,H],`fork start and pending-intent restore failed: ${D(Y)}; ${D(H)}`)}throw Y}finally{this.pendingConversationLaunch=null}})}async rollbackTo($,Z,J={}){return await this.runLifecycle("rollback",async()=>{G$($,this.selectedProvider,this.workDir);let Q=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,Y=this.proc,H=this.lastSessionId,W=this.lastSessionRef,X=K2(this.sessionName).slice(),V=q2(this.sessionName),A=B2(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,q=()=>{if(_)this.lastSessionId=null,this.lastSessionRef=null,S1(this.sessionName,"codex");else if(this.lastSessionId=H,this.lastSessionRef=W,W)_2(this.sessionName,W);else S1(this.sessionName,this.selectedProvider);I$(this.sessionName,X,V,A),this.pendingConversationMaterialization=A,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},B=!1;if(Q?.pendingLaunch)I$(this.sessionName,Q.anchors,Q.base,Q.pendingLaunch),this.pendingConversationMaterialization=Q.pendingLaunch,B=!0;this.pendingConversationLaunch=$;let R=(L)=>{_=W?.provider==="codex"&&W.sessionId===L};try{let L;try{L=$.kind==="fresh"?await this.restartUnlocked(!1,J,R):await this.restartUnlocked(!0,J,R)}catch(F){let U=null,P=this.proc&&this.proc!==Y?this.proc:null;if(P)try{await this.stopUnlocked("回滚启动事务失败",{announce:!1})}catch(x){U=x}let j=!P||this.proc!==P&&!P.isAlive();if(!j&&!U)U=Error("replacement process stop was not confirmed");let k=null;if(j)try{q()}catch(x){k=x}let C=[F,...U?[U]:[],...k?[k]:[]];if(C.length===1)throw F;throw AggregateError(C,`rollback launch and cleanup failed: ${C.map(D).join("; ")}`)}if(!L)return q(),!1;if(Q)try{if(!B)I$(this.sessionName,Q.anchors,Q.base,Q.pendingLaunch);this.pendingConversationMaterialization=Q.pendingLaunch}catch(F){let U=null,P=this.proc;try{await this.stopUnlocked("回滚分支状态持久化失败",{announce:!1})}catch(x){U=x}let j=!P||this.proc!==P&&!P.isAlive();if(!j&&!U)U=Error("replacement process stop was not confirmed");let k=null;if(j)try{q()}catch(x){k=x}let C=[F,...U?[U]:[],...k?[k]:[]];if(C.length===1)throw F;throw AggregateError(C,`rollback branch commit failed: ${C.map(D).join("; ")}`)}return L}finally{this.pendingConversationLaunch=null}})}dispose(){W1.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 Q=`拒绝了与当前会话不匹配的 checkpoint provider=${$.provider} source=${$.source.sessionId}`;return z(`session "${this.sessionName}": ${Q}`),this.lastTurnUserPreview="",Q}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((Y)=>Y.proc===Z).length>=64)return z(`session "${this.sessionName}": ${"Codex rollout 长期未确认,延迟 checkpoint 队列已满"} thread=${Z.sessionId}`),"Codex rollout 长期未确认,延迟 checkpoint 队列已满";return this.pendingCodexTurnAnchors.push({proc:Z,anchor:J}),z(`session "${this.sessionName}": defer Codex turn checkpoint until rollout confirmation thread=${Z.sessionId} checkpoint=${$.id}`),null}return this.appendTurnAnchor(J)}appendTurnAnchor($){try{return k6(this.sessionName,$),null}catch(Z){let J=`分叉 checkpoint 持久化失败: ${D(Z)}`;return z(`session "${this.sessionName}": ${J}`),J}}flushPendingCodexTurnAnchors($){let Z=null,J=[];for(let Q of this.pendingCodexTurnAnchors){if(Q.proc!==$||Z){J.push(Q);continue}if(Z=this.appendTurnAnchor(Q.anchor),Z)J.push(Q)}return this.pendingCodexTurnAnchors=J,Z}discardPendingCodexTurnAnchors($,Z){if($.provider!=="codex")return;let J=this.pendingCodexTurnAnchors.length;this.pendingCodexTurnAnchors=this.pendingCodexTurnAnchors.filter((Y)=>Y.proc!==$);let Q=J-this.pendingCodexTurnAnchors.length;if(Q>0)z(`session "${this.sessionName}": dropped ${Q} unmaterialized Codex checkpoint(s): ${Z}`)}collectTurnWrites(){let $=this.currentTurn;if(!$)return[];let Z=[];for(let J of $.toolByUseId.values())Z.push(...k7(J.name,J.input));return Z}worktreeProjectName(){return S0(this)}worktreeProjectDir(){return u1(this)}spawnDeveloperInstructions(){return IY(this)}delegatedAgentDeveloperInstructions($){return cY(this,$)}worktreeInstructionLoadedNotice(){return K5(this)}withWorktreeInstructionNotice($){return mY(this,$)}worktreeExtraInstruction(){return I2(this)}runWorktreeCommand($,Z){return uY(this,$,Z)}showWorktrees(){return q5(this)}showTasklistPanel(){return RY(this)}showAgentIdentityPanel($=""){return XY(this,$)}onAgentIdentityPage($,Z,J){return VY($,Z,J)}onTasklistEnable(){return PY(this)}onTasklistDeletePrompt($){return LY(this,$)}onTasklistDeleteConfirm($){return DY(this,$)}runCompactCommand(){return aQ(this)}showModelPanel(){return sQ(this)}onModelSelect($,Z="",J="",Q=null){return QY(this,$,Z,J,Q)}onModelEffortSelect($,Z,J="",Q="",Y=""){return this.runLifecycle("model-effort-select",()=>YY(this,$,Z,J,Q,Y))}onProviderSelect($,Z=""){return eQ(this,$,Z)}onModelPanelCancel($=""){return JY(this,$)}onModelCustomPrompt($,Z,J=""){return $Y(this,$,Z,J)}consumeModelCustomMessage($,Z){return ZY(this,$,Z)}onWorktreeDisband($){return lY(this,$)}showForkList($=""){return tY(this,$)}showBackList($=""){return sY(this,$)}showResumeList($=""){return eY(this,$)}runBtwCommand($){return $H(this,$)}runByeCommand(){return ZH(this)}onForkSelect($,Z,J=""){return JH(this,$,Z,J)}onBackSelect($,Z,J=""){return QH(this,$,Z,J)}onResumeSelect($,Z,J=""){return YH(this,$,Z,J)}runCommand($,Z=""){return dQ(this,$,Z)}async buildConsoleOpts($,Z){let J=await EJ(),Q=this.runtimeModelSelection();return{sessionName:this.sessionName,status:this.status,provider:Q.provider,model:Q.model??void 0,effort:Q.effort,worktreeInstructionNotice:this.worktreeInstructionLoadedNotice(),peers:[...W1.all].filter((Y)=>Y.isRunning()).map((Y)=>({...Y.peerSnapshot(),isCurrent:Y===this})),usage:$,glmUsage:Z,sysinfo:J}}async buildConsoleCard($){return q7(await this.buildConsoleOpts($))}async patchConsoleUsage($){let Z=await this.buildConsoleOpts(void 0),J=Z.provider??this.currentProvider(),Q=this.currentTokenSource(),Y=Q&&Q.agent===J&&Q.enabled?Q:this.selectedTokenSourceId?void 0:M4(J)[0];if(Y)Z.unifiedUsage=await Y.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 c7();else Z.usage=await F9();if(!await F$($,M.consoleUsage,C2(Z),{notifyCardFailure:!1}))throw Error("console usage element replace rejected")}async mutateStaticCard($,Z,J){let Q=!0;try{await J()}catch(H){Q=!1,z(`session "${this.sessionName}": ${Z} mutation failed: ${D(H)}`)}let Y=!1;try{Y=await q$($,{config:{streaming_mode:!1}})}catch(H){z(`session "${this.sessionName}": ${Z} streaming-off failed: ${D(H)}`)}if(!Q||!Y)return z(`session "${this.sessionName}": ${Z} state retained after checked MISS mutation=${Q} streamingOff=${Y} card=${$.slice(0,12)}`),!1;try{await x$($)}catch(H){return z(`session "${this.sessionName}": ${Z} dispose failed: ${D(H)}`),!1}return Q}patchConsoleUsageLater($){this.mutateStaticCard($,"console usage",()=>this.patchConsoleUsage($))}async replaceStatusCardWithConsole($,Z){$.timer.stop();let J=$.timer.elapsedSec(),Q=await this.buildConsoleOpts(void 0);await u$($.cardId);let Y=await F$($.cardId,M.footer,H9(Q,M.footer)),H=await j0($.cardId,Y9(Q),{type:"insert_after",targetElementId:M.footer}),W=await j0($.cardId,W9(Q.sysinfo),{type:"insert_after",targetElementId:M.consoleProjects}),X=await j0($.cardId,C2(Q),{type:"insert_after",targetElementId:M.consoleHost});if(!Y||!H||!W||!X){await b(this.chatId,"⚠️ 控制台卡片结构写入失败,请重新发送 hi。"),await this.mutateStaticCard($.cardId,"console structure",async()=>{});return}V$($.cardId),await q$($.cardId,A0({durationSec:J,suffix:Z})),this.patchConsoleUsageLater($.cardId)}async showConsole(){let $=await this.buildConsoleCard(void 0),Z=await i(this.chatId,$);if(!Z)return;(async()=>{let J="";try{J=await a$(Z),m$(J,4)}catch(Q){z(`session "${this.sessionName}": console card conversion failed: ${D(Q)}`);return}await this.mutateStaticCard(J,"console usage",()=>this.patchConsoleUsage(J))})().catch((J)=>z(`session "${this.sessionName}": console async update rejected: ${D(J)}`))}interrupt(){if(!this.proc)return;z(`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 Q=this.beginTurnOpen();try{let H=await this.openTurnCard(Q,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 u$(H.cardId),!V){this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),await this.closeTurnCard(X.startsWith("❌")?X:"❌ 启动失败",{forcePush:!0});return}let A=this.proc;if(!A?.isAlive()){await this.closeTurnCard(`❌ ${this.backendLabel()} 启动后已退出`,{forcePush:!0});return}this.startThinkingFooter(H),this.sendClaimedUserText(A,Z),this.status="working"}finally{this.releaseTurnOpen(Q)}}async onUserMessage($,Z=[],J="",Q=""){await this.runLifecycle("user-message",()=>this.onUserMessageUnlocked($,Z,J,Q))}async onUserMessageUnlocked($,Z,J,Q){let Y=this.blockedProcessMessage();if(Y){await E(this.chatId,`❌ ${Y}。请重试 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((A)=>`[file: ${A}]`).join(" ")+`
|
|
185
|
-
`:"")+$,V=(A)=>{this.pendingReactionIds.set(A,""),(async()=>{let G=await T$(A,"OneSecond");if(!G)return;if(this.pendingReactionIds.has(A))this.pendingReactionIds.set(A,G);else if(this.currentBatchReactionIds.has(A))this.currentBatchReactionIds.set(A,G);else j$(A,G)})().catch((G)=>{z(`session "${this.sessionName}": reaction tracking failed: ${D(G)}`)})};if(!this.isRunning()){if(this.openingTurn||this.currentTurn){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Q}),Q)V(Q);return}await this.startColdUserTurn($,X,J);return}if(this.currentTurn!==null){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Q}),Q)V(Q);return}if(!this.openingTurn&&this.initCount>=1){let A=this.proc,G=this.procEpoch,_=this.beginTurnOpen(A,G);try{this.pendingTurnInputs.push($);let q=await this.openTurnCard(_,J,"user_message");if(!q||this.currentTurn!==q)return;if(this.proc!==A||this.procEpoch!==G||!A.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel(A.provider)} 已退出`);return}this.sendClaimedUserText(A,X),this.status="working"}finally{this.releaseTurnOpen(_)}return}if(this.openingTurn||this.pendingUserMessageCount>0){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Q}),Q)V(Q);return}if(this.pendingTurnInputs.push($),this.sendClaimedUserText(this.proc,X),H&&Q)V(Q)}hasPendingAsk(){return TQ(this)}onMultiMessageInbound($,Z,J,Q){return XQ(this,$,Z,J,Q)}clearMultiMsgBuffer($){p7(this,$)}onAskMessageAnswer($,Z,J){return kQ(this,$,Z,J)}onAskAnswer($,Z,J,Q){return SQ(this,$,Z,J,Q)}onAskCustomAnswer($,Z,J,Q){return a7(this,$,Z,J,Q)}onPermissionDecision($,Z,J){return yQ(this,$,Z,J)}clearResumeBindingForFreshCodex($){if($.isConversationResumable?.())throw Error("fresh Codex thread was unexpectedly marked resumable during init");let Z=p0(this.sessionName,"codex");if(S1(this.sessionName,"codex"),this.selectedProvider==="codex")this.lastSessionRef=null,this.lastSessionId=null;if(Z)z(`session "${this.sessionName}": cleared pre-fresh Codex resume binding thread=${Z.sessionId}`)}invalidateMissingCodexResume($,Z,J){if(!$||this.selectedProvider!=="codex")return null;let Q=D5(Z);if(!Q||!["thread/read","thread/resume","thread/fork"].includes(Q.method)||Q.serverCode!==-32600||Q.serverMessage!==`no rollout found for thread id ${$}`)return null;let Y=p0(this.sessionName,"codex");if(!Y||Y.sessionId!==$)return null;try{S1(this.sessionName,"codex")}catch(W){let X=`已确认恢复点无 rollout,但作废失败: ${D(W)}`;return z(`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=${A$($)}`;return z(`session "${this.sessionName}": ${H} fullThread=${$}`),H}persistResumableSessionId($=!1,Z=this.proc,J=!0){let Q=Z?.provider==="claude"?this.pendingConversationMaterialization:null,Y=Z?.sessionId;if(!Z)return null;if(Z.provider==="codex"&&Z.isConversationResumable?.()!==!0)return null;if(!Y){if(!Q)return null;let X=Error("Claude pending fork did not provide a materialized session id");if(z(`session "${this.sessionName}": ${X.message}`),$)throw X;return X.message}let H={provider:Z.provider,sessionId:Y,cwd:this.workDir};if(Q&&(Y===Q.launch.source.sessionId||Q.previousSessionId!==null&&Y===Q.previousSessionId)){let X=Error(`Claude fork did not materialize an independent session id (${Y})`);if(z(`session "${this.sessionName}": ${X.message}`),$)throw X;return X.message}try{_2(this.sessionName,H)}catch(X){let V=`会话恢复点持久化失败: ${D(X)}`,A=this.resumePersistenceError!==V;if(this.resumePersistenceError=V,Z.provider===this.selectedProvider)this.lastSessionRef=H,this.lastSessionId=Y;if(z(`session "${this.sessionName}": ${V}`),$)throw X;if(A&&J)b(this.chatId,`⚠️ ${V};当前进程可继续,但 daemon 重启前请先解决本机状态目录写入问题。`);return V}if(Z.provider===this.selectedProvider)this.lastSessionRef=H,this.lastSessionId=Y;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)b(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 z(`session "${this.sessionName}": ${"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker"}`),"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker";try{return D0(this.sessionName,null),this.pendingConversationMaterialization=null,null}catch(J){let Q=`Claude 待生成分支标记清除失败: ${D(J)}`;return z(`session "${this.sessionName}": ${Q}`),Q}}bgStore(){return{active:this.backgroundTasks,pending:this.pendingBgTasks}}applyBgStore($){this.backgroundTasks=$.active,this.pendingBgTasks=$.pending}onMainThreadAdvance(){if(this.pendingBgTasks.length===0)return;this.applyBgStore(p8(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(!w0(this.backgroundTasks)){if(this.backgroundCard)this.settleBackgroundCard().catch((Z)=>{z(`session "${this.sessionName}": background settle failed: ${D(Z)}`)});return}if(!this.backgroundCard&&!this.openingBackground){this.openBackgroundCard().catch((Z)=>{z(`session "${this.sessionName}": background open failed: ${D(Z)}`)});return}this.scheduleBackgroundRefresh()}async openBackgroundCard(){let $=this.beginBackgroundOpen();if(!$)return;let Z=this.backgroundTasks.slice();try{let J=o8(Z,Date.now(),H1()),Q=await i(this.chatId,J);if(!Q){if(this.ownsBackgroundOpen($))z(`session "${this.sessionName}": background card send failed`);return}let Y;try{Y=await a$(Q)}catch(H){z(`session "${this.sessionName}": background card id_convert failed: ${H}`);return}if(m$(Y,Z.length),!this.ownsBackgroundOpen($)){await this.terminalizeSupersededCard(Y,"⚠️ 后台任务世代已切换,本卡已作废",!1);return}if(this.backgroundCard={messageId:Q,cardId:Y},this.backgroundDetailAdded=new Set(Z.map((H)=>H.id)),this.backgroundDetailAdding.clear(),z(`session "${this.sessionName}": background card opened cardId=${Y.slice(0,12)} tasks=${Z.length}`),!w0(this.backgroundTasks)){this.settleBackgroundCard().catch((H)=>{z(`session "${this.sessionName}": background settle-after-open failed: ${D(H)}`)});return}this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}finally{this.releaseBackgroundOpen($)}}startBackgroundRefreshTick(){if(this.backgroundRefreshTick)return;let $=()=>{if(this.migratingBackgroundCard||!this.backgroundCard||!w0(this.backgroundTasks))return;let Z=H1(),J=Date.now(),Q=1/0;for(let Y of this.backgroundTasks){if(y$(Y))continue;let H=R0(J-Y.startedAt,Z).nextDelayMs;if(H<Q)Q=H}if(!isFinite(Q))return;this.backgroundRefreshTick=setTimeout(()=>{this.refreshBackgroundCardFull(),$()},Math.max(1,Math.ceil(Q)))};$()}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=H1();for(let Q of this.backgroundTasks)if(!this.backgroundDetailAdded.has(Q.id)){if(this.backgroundDetailAdding.has(Q.id))continue;this.backgroundDetailAdding.add(Q.id),j0($.cardId,j1(Q,Z,J)).then((Y)=>{if(Y)this.backgroundDetailAdded.add(Q.id);else z(`session "${this.sessionName}": background panel add MISS task=${Q.id}`)}).finally(()=>{this.backgroundDetailAdding.delete(Q.id)})}else o($.cardId,Z2.panel(Q.id),j1(Q,Z,J));X0($.cardId,K4(this.backgroundTasks))}async resetBackgroundTasks(){if(this.invalidateBackgroundOpen(),this.backgroundTasks.some(($)=>!y$($))){let $=Date.now();this.backgroundTasks=this.backgroundTasks.map((Z)=>y$(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){z(`session "${this.sessionName}": background migration failed before settle; retry terminal snapshot: ${D(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 u$($.cardId),await H0($.messageId,q4(Z)),V$($.cardId),!await q$($.cardId,A0({suffix:"\uD83E\uDDED 后台任务已结束"})))throw Error("background history streaming-off rejected");if(await x$($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((Q)=>!y$(Q)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),z(`session "${this.sessionName}": background card settled cardId=${$.cardId.slice(0,12)} remaining=${this.backgroundTasks.length}`)}finally{if(this.settlingBackgroundCard=!1,this.backgroundCard===$&&w0(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 u$($.cardId),this.backgroundCard!==$)return;let Z=[...this.backgroundTasks],J=new Set(Z.filter(y$).map((H)=>H.id)),Q=J.size;if(Q>0)await H0($.messageId,q4(Z));else await H0($.messageId,a8());if(V$($.cardId),!await q$($.cardId,A0({suffix:"\uD83E\uDDED 已迁移至新卡"})))throw Error("background migration streaming-off rejected");if(await x$($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((H)=>!J.has(H.id)||!y$(H)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),z(`session "${this.sessionName}": background card migrated cardId=${$.cardId.slice(0,12)} terminal=${Q} active=${this.backgroundTasks.length}`)}startScheduledTurnCard($,Z,J,Q){if(this.proc!==$||this.procEpoch!==Z||!$.isAlive())return;if(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.bgResumePending)return;let Y;try{Y=this.beginTurnOpen($,Z,!0)}catch(W){z(`session "${this.sessionName}": scheduled turn-open ownership conflict: ${D(W)}`);return}let H=J.replace(/\s+/g," ").trim();this.lastTurnUserPreview=`⏰ ${H.slice(0,78)}`,z(`session "${this.sessionName}": scheduled wakeup prompt=${Q??"MISS"}`),(async()=>{try{let W=await this.openTurnCard(Y,"","scheduled_wakeup");if(this.proc!==$||this.procEpoch!==Z){if(z(`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(Y))return;if(this.bgResumeCardless=!0,Y.sawResult)Y.sawResult=!1,z(`session "${this.sessionName}": scheduled open failed after result — flushing orphan now`),this.flushOrphanAssistantToChat("scheduled open failed, result already arrived");else z(`session "${this.sessionName}": scheduled open failed — orphan text flush will cover the output`)}else if(Y.sawResult)Y.sawResult=!1,z(`session "${this.sessionName}": scheduled result raced card-open — closing freshly-opened card`),await this.closeTurnCard(Y.terminalSuffix,{forcePush:Y.terminalForcePush,hasFreshResult:!0}),this.status="idle";else this.status="working"}finally{this.releaseTurnOpen(Y)}})().catch((W)=>{z(`session "${this.sessionName}": scheduled turn-open handler failed: ${D(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 Q=()=>this.proc===$&&this.procEpoch===J,Y=!1,H=!1,W=(X,V)=>{$.on(X,(A)=>{if(!Q()){if(!Y)Y=!0,z(`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,z(`session "${this.sessionName}": ignore ${$.provider} event=${String(X)} while process stop is pending`);return}V(A)})};W("error",(X)=>{z(`session "${this.sessionName}": ${$.provider} process error: ${X}`)}),W("init",()=>{if($.provider==="codex"&&$.launchKind==="fresh")this.clearResumeBindingForFreshCodex($);else this.persistResumableSessionId(!0);if(this.initCount++,z(`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)z(`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 A=this.lastUserOpenId,G;try{G=this.beginTurnOpen($,J,!0)}catch(B){z(`session "${this.sessionName}": init turn-open ownership conflict: ${D(B)}`);return}if(this.bgResumePending=!1,X)this.pendingUserMessageCount=0,this.currentBatchReactionIds=this.pendingReactionIds,this.pendingReactionIds=new Map;let _=X?[...this.currentBatchReactionIds.keys()]:[],q=()=>{for(let B of _){let R=this.currentBatchReactionIds.get(B);if(this.currentBatchReactionIds.delete(B),R)j$(B,R)}};(async()=>{try{let B=await this.openTurnCard(G,A,X?"user_message":"bg_task_resume");if(!Q()){if(z(`session "${this.sessionName}": ${$.provider} became stale while opening turn card epoch=${J}`),B&&this.currentTurn===B)await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);q();return}if(!B||this.currentTurn!==B){if(!this.ownsTurnOpen(G)){q();return}if(G.sawResult&&G.terminalSuffix)b(this.chatId,G.terminalSuffix);if(X)z(`session "${this.sessionName}": init-path openTurnCard failed — sendInterrupt + release reactions`),this.proc?.sendInterrupt(),q();else if(this.bgResumeCardless=!0,G.sawResult)G.sawResult=!1,z(`session "${this.sessionName}": bg-resume openTurnCard failed, result already arrived — flushing orphan now`),this.flushOrphanAssistantToChat("bg-resume open failed, result already arrived");else z(`session "${this.sessionName}": bg-resume openTurnCard failed — orphan text flush will cover the output`)}else if(G.sawResult)G.sawResult=!1,z(`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((B)=>{z(`session "${this.sessionName}": init turn-open handler failed: ${D(B)}`)})}),W("scheduled_turn_input",({text:X,promptId:V})=>{if($.provider!=="claude")return;this.startScheduledTurnCard($,J,X,V)}),W("conversation_materialized",({session_id:X,source:V})=>{if($.provider!=="codex")return;if($.sessionId!==X){z(`session "${this.sessionName}": ignore mismatched Codex materialization session=${X} current=${$.sessionId??"MISS"} source=${V}`);return}z(`session "${this.sessionName}": Codex resume point materialized thread=${X} source=${V}`),this.persistResumableSessionId()}),W("conversation_materialization_failed",({session_id:X,source:V,error:A})=>{if($.provider!=="codex"||$.sessionId!==X)return;let G=`Codex 会话落盘确认失败,未写恢复点: ${D(A)}`,_=this.resumePersistenceError!==G;if(this.resumePersistenceError=G,z(`session "${this.sessionName}": ${G} thread=${X} source=${V}`),_)b(this.chatId,`⚠️ ${G}`)}),W("turn_started",()=>{if((this.currentTurn||this.openingTurn)&&this.pendingUserMessageCount>0)z(`session "${this.sessionName}": turn_started claimed eager input pendingCount=${this.pendingUserMessageCount}`),this.pendingUserMessageCount=0;this.persistResumableSessionId();let X=this.proc?.lastTotalUsage;if(this.usageTotalsSeedUnknown&&!X){this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;return}this.currentTurnUsageBaseline=X?{...X}: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")oJ(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:A,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(i8({active:this.backgroundTasks,pending:this.pendingBgTasks},G,X,V,A)),this.onBackgroundTaskChanged();return}if(UQ(this,X,V,A),!G)this.onMainThreadAdvance();if(!G&&(V==="Task"||V==="Agent"))this.lastMainTaskToolUseId=X}),W("tool_result",({tool_use_id:X,content:V,is_error:A,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(d8({active:this.backgroundTasks,pending:this.pendingBgTasks},G,X,V,A)),this.onBackgroundTaskChanged();return}OQ(this,X,V,A)}),W("can_use_tool",(X)=>{xQ(this,X)}),W("hook_callback",(X)=>{this.proc?.sendHookResponse(X.request_id,{})}),W("result",(X)=>{let V=this.persistResumableSessionId(),A=V?null:this.consumePendingConversationMaterialization(),G=[V,A].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;z(`session "${this.sessionName}": SDK result after user stop subtype=${j} isError=${k} — 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 q=this.pendingMidTurnMsgs.length>0,B=this.proc?.lastResult.is_error===!0,R=this.proc?.lastResult.subtype??"success",L,F=!1,U=this.proc?this.backendLabel(this.proc.provider):this.backendLabel(),P=[G,_].filter(Boolean).join(";")||null;if(P)L=`⚠️ ${P}`,F=!0;else if(q)L=B?`⚠️ ${U} ${R},用户已介入`:"\uD83D\uDCE8 转交新卡";else if(B)L=`⚠️ ${U} ${R}`,F=!0;if(this.openingTurnOwner)this.openingTurnOwner.terminalSuffix=L,this.openingTurnOwner.terminalForcePush=F;if(P&&!this.currentTurn&&!this.openingTurn)b(this.chatId,`⚠️ ${P}`);if(z(`session "${this.sessionName}": SDK result subtype=${R} isError=${B} midBuffer=${this.pendingMidTurnMsgs.length} forcePush=${F}`),this.closeTurnCard(L,{forcePush:F,hasFreshResult:!0}).catch((j)=>{z(`session "${this.sessionName}": result card close failed: ${D(j)}`)}),this.status="idle",q)this.drainMidTurnAndOpen().catch((j)=>{z(`session "${this.sessionName}": mid-turn drain failed: ${D(j)}`)})}),W("bg_task_started",(X)=>{let V=X.tool_use_id??this.lastMainTaskToolUseId??void 0;z(`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(c8(this.bgStore(),{...X,tool_use_id:V})),this.onBackgroundTaskChanged()}),W("bg_task_progress",(X)=>{this.applyBgStore(m8(this.bgStore(),X)),this.onBackgroundTaskChanged()}),W("bg_task_updated",(X)=>{this.applyBgStore(u8(this.bgStore(),X)),this.onBackgroundTaskChanged()}),W("bg_task_settled",(X)=>{if(z(`session "${this.sessionName}": bg_task_settled task=${X.task_id} status=${X.status}`),this.applyBgStore(l8(this.bgStore(),X)),this.onBackgroundTaskChanged(),$.provider==="claude"&&!this.currentTurn&&!this.openingTurn&&this.initCount>=1)this.bgResumePending=!0}),W("subagent_step",(X)=>{this.applyBgStore(n8(this.bgStore(),X.thread_id,X.item_id,X.tool,X.phase,X.brief)),this.onBackgroundTaskChanged()}),W("exit",({code:X,signal:V,expected:A})=>{if(z(`session "${this.sessionName}": ${$.provider} exited code=${X} signal=${V} expected=${A}`),this.stoppingProc===$||this.blockedProc===$){if(this.blockedProc===$){let R=$.conversationMaterializationFailure?.(),L=this.persistResumableSessionId(!1,$,!1),F=[R&&$.isConversationResumable?.()!==!0?`Codex 会话落盘确认失败: ${D(R)}`:null,L].filter(Boolean).join(";");if(F)b(this.chatId,`⚠️ 旧进程退出后的恢复状态收尾失败: ${F}`);this.discardPendingCodexTurnAnchors($,"blocked process finally exited")}z(`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((R)=>{z(`session "${this.sessionName}": cancel Agent runs after process exit failed: ${D(R)}`)});let G=this.backendLabel($.provider),_=`code=${X??"null"}, signal=${V??"null"}`,q=A?`\uD83D\uDED1 ${G} 已退出`:`⚠️ ${G} 异常退出 (${_})`;if(this.currentTurn)this.closeTurnCard(q).catch((R)=>{z(`session "${this.sessionName}": process-exit current main-card close failed: ${D(R)}`)});let B=this.waitForTurnCloses().catch((R)=>{z(`session "${this.sessionName}": process-exit main-card close failed: ${D(R)}`)});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 R=await Promise.allSettled([B,this.resetBackgroundTasks()]);for(let L of R)if(L.status==="rejected")z(`session "${this.sessionName}": process-exit terminal cleanup failed: ${D(L.reason)}`);if(!A)await E(this.chatId,`⚠️ ${G} 异常退出 (${_})。回复任意消息将重新启动。`)}).catch((R)=>{z(`session "${this.sessionName}": process-exit cleanup rejected: ${D(R)}`)})})}accumulateResultStats(){let $=this.proc?.lastResult;if(!$)return;let Z=this.currentTurnUsageBaselineKnown?T8(this.proc?.lastTotalUsage,this.currentTurnUsageBaseline):this.proc?.provider==="claude"&&$.usage?{...$.usage}:null;this.lastTurnUsage=Z,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;let J=k8(Z),Q=this.proc?.provider==="claude"?0:$.cost_delta_usd??0,Y=$.duration_ms??0;if(J!=null)this.cumStats.tokens+=J;this.cumStats.costUsd+=Q,this.cumStats.turns+=$.num_turns??1,this.lastTurnDelta={tokens:J,costUsd:Q,durationMs:Y}}currentContextTokens($=this.proc){if($?.provider==="claude")return $.lastContextTokens??null;let Z=$?.lastUsage;return I4(Z)}contextLimitForDisplay($=this.proc){return c4($?.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(Y){z(`session "${this.sessionName}": mid-turn open ownership conflict: ${D(Y)}`);return}let Q=this.pendingMidTurnMsgs;this.pendingMidTurnMsgs=[];try{for(let V of Q)if(this.pendingTurnInputs.push(V.text),V.msgId){let A=this.pendingReactionIds.get(V.msgId)??"";this.currentBatchReactionIds.set(V.msgId,A),this.pendingReactionIds.delete(V.msgId)}let Y=Q.map((V)=>V.wireText).join(`
|
|
175
|
+
${G}`)}return{slug:Q,chatName:H,branch:Y,worktreePath:V,removedWorktree:!1}}function A5($){if(!Q1($))throw Error(`project directory does not exist: ${$}`);let Z=R$($,["rev-parse","--show-toplevel"]).trim();if(V5(Z)!==V5($))throw Error(`${$} is not the git repository root (${Z})`)}function vY($,Z){let J=R$($,["rev-parse","--abbrev-ref","HEAD"]).trim();if(J!==Z)throw Error(`${$} is on ${J}, expected ${Z}`)}function QK($,Z,J){let Q=YK($);if(!Q?.startsWith(I1))return null;let Y=Q.slice(I1.length);if(!Y1(Y))throw Error(`invalid worktree branch "${Q}"`);let H=m1(Z,J,Y);if(g9($)!==g9(H))return null;let W=WK($,HK(Y));return W?{path:W,slug:Y}:null}function YK($){if(!Q1($))return null;try{return R$($,["branch","--show-current"]).trim()||null}catch(Z){if(VK(Z))return null;throw Z}}function HK($){return $.split("-",1)[0]??$}function WK($,Z){let J=`agents.${Z}.md`,Q=s_($).filter((Y)=>Y.toLowerCase()===J).sort();if(Q.length>1)throw Error(`multiple worktree instruction files match ${J}: ${Q.join(", ")}`);return Q[0]?NY($,Q[0]):null}function XK($,Z){try{return R$($,["show-ref","--verify","--quiet",`refs/heads/${Z}`]),!0}catch{return!1}}function hY($,Z,J){let Q=R$($,["rev-parse",Z]).trim(),Y=R$($,["rev-parse","HEAD"]).trim();if(Q===Y)return J?"active":"merged";if(SY($,Z,"HEAD"))return"merged";if(SY($,"HEAD",Z))return"active";return"stale"}function SY($,Z,J){try{return R$($,["merge-base","--is-ancestor",Z,J]),!0}catch{return!1}}function G5($){let Z=new Map,J=R$($,["worktree","list","--porcelain"]),Q="";for(let Y of J.split(`
|
|
176
|
+
`)){if(Y.startsWith("worktree ")){Q=Y.slice(9);continue}if(Y.startsWith("branch refs/heads/")&&Q)Z.set(Y.slice(18),Q)}return Z}function R$($,Z){try{return t_("git",Z,{cwd:$,encoding:"utf8",stdio:["ignore","pipe","pipe"]})}catch(J){throw Error(_5(J))}}function _5($){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 VK($){return/not a git repository/i.test(_5($))}var I1="work/",JK,h9;var gY=N(()=>{JK=/^[A-Za-z0-9][A-Za-z0-9._-]{0,62}$/,h9=new Map});function S0($){return yY(o$($.sessionName)??$.sessionName)}function u1($){return b4(S0($))}function cY($){let Z=o$($.sessionName)??$.sessionName,J=S0($),Q=b4(J);if(J===Z)return Q;let Y=Z.slice(J.length+1,-1);return m1(Q,J,Y)}function mY($,Z=$.currentProvider()){let J=Z==="claude"?TY:EY,Q=c2($);return Q?`${J}
|
|
177
|
+
${Q}`:J}function uY($,Z){return c2($)??""}function K5($){return c2($)?"已载入wt特殊约定":null}function pY($,Z){let J=K5($);return J?`${Z}
|
|
178
|
+
${J}`:Z}function c2($){let Z=S0($),J=bY($.workDir,u1($),Z);if(!J)return null;return[`你要把下面这份额外的工作树约定视为和AGENTS.md一样重要。来源文件:${J.path}`,"",`# Additional AGENTS.md instructions for ${$.workDir}`,"","<INSTRUCTIONS>",J.content,"</INSTRUCTIONS>"].join(`
|
|
179
|
+
`)}async function lY($,Z,J){if(!Z){await q5($);return}let Q=Y1(Z);if(!Q){await T($.chatId,"❌ 名称无效。用英文/数字/._-,最长 63。");return}if(!J){await T($.chatId,"❌ 找不到发起人,不能拉群。");return}let Y=S0($),H=u1($);try{await I9(H,async()=>{let W;try{W=fY(H,Y,Q)}catch(X){await T($.chatId,`❌ wt 失败: ${D(X)}`);return}try{let X=await w6(W.chatName,J),V=X.created?"已创建":X.joined?"已加入":"已在群内";if(!await n($.chatId,w2({slug:Q,branch:W.branch,status:V})))await x($.chatId,`❌ wt 卡片失败: ${Q}`);if(!await n(X.chatId,w2({slug:Q,branch:W.branch,status:"就绪",body:"开始吧。"})))await x(X.chatId,`❌ wt 卡片失败: ${Q}`)}catch(X){await T($.chatId,`❌ wt 已建,拉群失败: ${D(X)}`)}})}catch(W){await T($.chatId,`❌ wt 失败: ${D(W)}`)}}async function iY($,Z){let J=S0($),Q=u1($);return await I9(Q,async()=>{return await AK(J,Q,Z)})}async function AK($,Z,J){let Q=CY(Z,$),Y=Q.filter((X)=>X.state==="merged"&&!X.mounted).length,H=Q.filter((X)=>X.state!=="merged"||X.mounted),W=await C4();return j7({projectName:$,projectDir:Z,hiddenMergedUnmountedCount:Y,notice:J,entries:H.map((X)=>{let V=W.get(X.chatName)??[],A=Y$.get(X.chatName),G=A&&V.includes(A)?A: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 q5($){try{let Z=await iY($);if(!await n($.chatId,Z))await x($.chatId,"❌ wt 列表失败")}catch(Z){await T($.chatId,`❌ wt 列表失败: ${D(Z)}`)}}async function IY($,Z,J,Q){try{return{ok:Z,message:J,card:await iY($,{type:Q,content:J})}}catch(Y){let H=`列表刷新失败: ${D(Y)}`;return z(`session "${$.sessionName}": wt action panel refresh failed: ${D(Y)}`),{ok:!1,message:`${J}
|
|
180
|
+
${H}`,card:w2({slug:"wt",branch:"work/*",status:J,body:H,template:"red"})}}}async function nY($,Z){let J=Y1(Z);if(!J)return IY($,!1,"❌ 名称无效","error");let Q=S0($),Y=u1($),H;try{H=await I9(Y,async()=>{let W=c1(Q,J);if($.hasRunningPeerSession(W))return{ok:!1,message:`❌ 解散 ${J} 失败: Codex 正在运行,请先在 ${W} 群里 stop 或 kill。`,type:"error"};z5(Y,Q,J);let X=await h6(W),V=wY(Y,Q,J);return{ok:!0,message:[`✅ ${J} 已解散`,V.removedWorktree?"dir removed":"dir missing",X.disbanded?"group removed":"group missing",V.branch].join(`
|
|
181
|
+
`),type:"success"}})}catch(W){H={ok:!1,message:`❌ 解散 ${J} 失败: ${D(W)}`,type:"error"}}return IY($,H.ok,H.message,H.type)}var dY=N(()=>{kY();C$();t();h();gY()});import{closeSync as _K,openSync as KK,readSync as qK,readdirSync as BK,statSync as RK}from"node:fs";import{randomUUID as R5}from"node:crypto";import{join as PK}from"node:path";function m9($){return o$($.sessionName)??$.sessionName}function aY($){let Z=S6($,B5);return B5.add(Z),Z}function rY($){B5.delete($)}function p1($){let Z=oY.get($);if(!Z)Z=new Map,oY.set($,Z);let J=Date.now();for(let[Q,Y]of Z){let H=Y.status==="consumed"?jK:DK,W=Y.consumedAt??Y.createdAt;if(J-W>H)Z.delete(Q)}return Z}function MK($,Z){return $.provider===Z.provider&&$.tokenSourceId===Z.tokenSourceId&&$.model===Z.model&&$.effort===Z.effort}function tY($,Z,J,Q){let Y={id:R5(),mode:Z,requesterOpenId:J,provider:$.selectedProvider,sourceSessionId:$.lastSessionId,workDir:$.workDir,baseName:m9($),routing:$.conversationRouting(),createdAt:Date.now(),status:"open",choices:Q};return p1($).set(Y.id,Y),Y}function P5($,Z,J,Q,Y){let H=p1($).get(J);if(!H||H.mode!==Z)return{error:"这张选择卡已过期,请重新发送命令"};if(!Y||H.requesterOpenId!==Y)return{error:"只有打开这张选择卡的用户可以执行;请自行发送命令重新打开"};if(H.status!=="open")return{error:"这张选择卡已执行或正在处理,请勿重复点击"};if(H.provider!==$.selectedProvider||H.workDir!==$.workDir||H.sourceSessionId!==$.lastSessionId||!MK(H.routing,$.conversationRouting()))return{error:"这张卡对应的 provider、目录或源会话已经变化,请重新发送命令"};let W=H.choices.get(Q);if(!W)return{error:"无效的选择项,这张卡可能已过期"};return H.status="processing",{panel:H,choice:W}}function c9($){$.status="consumed",$.consumedAt=Date.now()}function UK($){return{kind:"fork",source:$.source,through:$}}function OK($){return q2($.sessionName).filter((Z)=>Z.checkpoint.provider===$.selectedProvider&&Z.checkpoint.source.cwd===$.workDir)}function EK($){let Z=B2($.sessionName);if(Z===null||Z.kind==="fresh")return Z;try{return G$(Z,$.selectedProvider,$.workDir),Z}catch{return null}}function TK($){let Z=Y6($),J;try{J=BK(Z)}catch(Y){if(Y?.code==="ENOENT")return[];throw Error(`读取 Claude 会话目录失败: ${Y?.message??Y}`)}let Q=[];for(let Y of J){if(!Y.endsWith(".jsonl"))continue;let H=Y.slice(0,-6);if(X4("claude",H))continue;let W=PK(Z,Y),X;try{X=RK(W).mtimeMs}catch(V){throw Error(`读取 Claude 会话元数据失败 (${Y}): ${V?.message??V}`)}Q.push({provider:"claude",sessionId:H,cwd:$,preview:SK(W),ts:X})}return Q.sort((Y,H)=>H.ts-Y.ts)}function kK($){let Z=$.slice().sort((Y,H)=>H.ts-Y.ts),J=Date.now()-LK,Q=Z.filter((Y)=>Y.ts>=J).length;return Z.slice(0,Math.min(FK,Math.max(10,Q)))}function SK($){let Z="",J=null;try{J=KK($,"r");let Y=Buffer.alloc(65536),H=qK(J,Y,0,65536,0);Z=Y.subarray(0,H).toString("utf8")}catch(Y){throw Error(`读取 Claude 会话摘要失败 (${$}): ${Y?.message??Y}`)}finally{if(J!==null)_K(J)}let Q="";for(let Y of Z.split(`
|
|
182
|
+
`)){let H=Y.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(!Q&&W.type==="user"&&W.message){let X=NK(W.message);if(X)Q=X}}return Q.slice(0,80)}function NK($){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 sY($,Z,J){if(!J){await T($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let Q=OK($),Y=EK($),H=new Map,W=[];for(let G=0;G<Q.length;G++){let _=Q[G];if(G===0&&Y===null)continue;let q=R5(),B=G===0?Y:UK(Q[G-1].checkpoint);H.set(q,{kind:Z,launch:B,branchBase:Y,seedAnchors:Q.slice(0,G),writes:Q.slice(G).flatMap((R)=>R.writes)}),W.push({choiceId:q,preview:_.preview,ts:_.ts})}W.reverse();let X=tY($,Z,J,H),V=M7({projectName:m9($),panelId:X.id,mode:Z,entries:W}),A;try{A=await n($.chatId,V)}catch(G){throw p1($).delete(X.id),G}if(!A)p1($).delete(X.id),await x($.chatId,`❌ ${Z==="fork"?"fk":"bk"} 列表发送失败`)}function eY($,Z){return sY($,"fork",Z)}function $H($,Z){return sY($,"back",Z)}async function ZH($,Z){if(!Z){await T($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let J;try{J=$.selectedProvider==="codex"?await $.listCodexConversations():TK($.workDir)}catch(V){await x($.chatId,`❌ 历史会话读取失败: ${V instanceof Error?V.message:V}`);return}let Q=new Map,Y=kK(J).map((V)=>{let A=R5();return Q.set(A,{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:A,preview:V.preview,ts:V.ts}}),H=tY($,"resume",Z,Q),W=U7({projectName:m9($),panelId:H.id,entries:Y}),X;try{X=await n($.chatId,W)}catch(V){throw p1($).delete(H.id),V}if(!X)p1($).delete(H.id),await x($.chatId,"❌ rs 历史列表发送失败")}async function JH($,Z){if(!Z){await T($.chatId,"❌ 找不到发起人,无法建临时群。");return}if(!$.opts.onCreateTempSession){await T($.chatId,"❌ 临时群能力未就绪(daemon 未注入回调)。");return}let J=aY(m9($));await T($.chatId,`\uD83D\uDE80 正在创建 ${J} · ${$.backendLabel()} 新会话。它与当前群共享工作目录;当前会话不受影响。`);let Q;try{Q=await $.opts.onCreateTempSession({chatName:J,userOpenId:Z,workDir:$.workDir,routing:$.conversationRouting(),launch:{kind:"fresh"},branchBase:{kind:"fresh"},seedAnchors:[]})}finally{rY(J)}if(!Q.ok){await T($.chatId,`❌ 建临时会话失败: ${Q.error??"未知"}`);return}await T($.chatId,`✅ 已创建 ${J}。临时群不会自动删除;在该群发送 bye 可停止并解散。`)}async function QH($){if(!o$($.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 YH($,Z,J,Q){let Y=P5($,"fork",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:H,choice:W}=Y;try{if(W.kind!=="fork")return{ok:!1,message:"选择项类型不匹配"};if(!$.opts.onCreateTempSession)return{ok:!1,message:"临时群能力未就绪"};let X=aY(H.baseName);z(`session-temp: fork ${$.sessionName} → ${X} (${W.launch.kind})`),await T($.chatId,`\uD83D\uDD31 正在分叉到 ${X}…`);let V;try{V=await $.opts.onCreateTempSession({chatName:X,userOpenId:Q,workDir:H.workDir,routing:H.routing,launch:W.launch,branchBase:W.branchBase,seedAnchors:W.seedAnchors})}finally{rY(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{c9(H)}}async function HH($,Z,J,Q){let Y=P5($,"back",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:H,choice:W}=Y;try{if(W.kind!=="back")return{ok:!1,message:"选择项类型不匹配"};let X="";try{if(!await n($.chatId,O7({projectName:H.baseName,entries:W.writes})))X=";文件变更记录卡发送失败"}catch(G){X=`;文件变更记录卡发送失败: ${G instanceof Error?G.message:G}`}if(z(`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?` ${A$($.lastSessionId)}`:""};旧会话未删除,磁盘文件未回滚${X}`}}catch(X){return{ok:!1,message:`回退失败: ${X instanceof Error?X.message:X}`}}finally{c9(H)}}async function WH($,Z,J,Q){let Y=P5($,"resume",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:H,choice:W}=Y;if(W.kind!=="resume")throw c9(H),Error("resume panel contained a non-resume choice");let X=W.launch.source.sessionId,V=$.lastSessionId,A=(_,q)=>({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:q}),G=(_,q,B,R=null)=>({ok:_,message:q,resumePresentation:A(R,B)});try{if($.isRunning())return G(!1,"当前群已经启动了新进程;为避免误杀,请先停止后重新发送 rs","unchanged");if(W.sourceStatus==="active")return G(!1,"所选 Codex 会话仍在运行;请先在原位置停止后再创建完整分支","unchanged");if(z(`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 q=$.lastSessionId;if(!q)return G(!1,"历史分支已启动,但后端没有返回新会话 id","unknown");if(q===X||V&&q===V)return G(!1,"后端没有返回独立的新会话 id;为避免误判,本次不标记为恢复成功","unknown",q);return G(!0,"已创建并接入独立分支;源会话未修改","changed",q)}catch(_){return G(!1,`历史分支创建失败: ${_ instanceof Error?_.message:_}`,"unknown")}finally{c9(H)}}var LK=86400000,DK=1800000,jK=3600000,FK=40,oY,B5;var XH=N(()=>{t();C$();h();j4();V4();P1();oY=new WeakMap,B5=new Set});import{existsSync as VH}from"node:fs";import{randomBytes as xK,timingSafeEqual as bK}from"node:crypto";import{isAbsolute as CK}from"node:path";function D5($,Z=new Set){if($ instanceof e1)return $;if(!$||typeof $!=="object"&&typeof $!=="function"||Z.has($))return null;if(Z.add($),$ instanceof AggregateError)for(let J of $.errors){let Q=D5(J,Z);if(Q)return Q}if($ instanceof Error&&$.cause!==void 0)return D5($.cause,Z);return null}function fK($){return $.itemId||$.turnId||"__latest__"}function zH($){let Z=[];if($.itemId)Z.push(`item:${$.itemId}`);if($.turnId)Z.push(`turn:${$.threadId??$.sessionId??"-"}:${$.turnId}`);return Z}function wK($){let Z=null;for(let J of $.contextCompactionPending.keys())Z=J;return Z}function vK($,Z){if(!$)return Z;return{...$,...Z,phase:"end"}}function H1(){return w.runtime?.live_elapsed??"bucket"}function GH($,Z){return`${$} (${R0(Date.now()-Z,H1()).label})`}var hK="Thinking...",gK="Writing...",IK="Working...",L5=1e4,u9=120000,cK=50,m2=5,mK=256,p9=1e4,AH=250,W1;var _H=N(()=>{D1();r8();v0();U$();A6();_$();j4();n0();C$();t();h();L$();_7();M9();O9();m7();AQ();UQ();kQ();t7();fQ();rQ();sQ();XY();KY();MY();dY();XH();P1();W1=class W1{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;W1.all.add(this);let Q=b6($);this.selectedProvider=Q?.provider??"claude",this.selectedModel=Q?.model??null,this.selectedEffort=Q?.effort??null,this.selectedTokenSourceId=this.deriveTokenSourceId(Q);let Y=Z$(this.selectedTokenSourceId);if(Y){if(this.selectedProvider=Y.agent,Y.id==="glm"&&this.selectedModel==="claude:glm")this.selectedModel=Y.defaultModel,this.selectedEffort="max";if(Y.id==="claude-native"&&this.selectedModel&&!Y.models.some((W)=>W.model===this.selectedModel))this.selectedModel=Y.defaultModel}if(this.selectedModel)z(`session "${$}": restored selected provider=${this.selectedProvider} model=${this.selectedModel} effort=${this.selectedEffort??"unset"}`);if(this.lastSessionRef=p0($,this.selectedProvider),this.lastSessionId=this.lastSessionRef?.sessionId??null,this.lastSessionId)z(`session "${$}": restored ${this.selectedProvider} lastSessionId=${this.lastSessionId}`);let H=R2($);if(H)if(this.selectedProvider!=="claude")I$($,[],null,null),z(`session "${$}": cleared pending Claude fork after provider changed`);else{G$(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,z(`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 cY(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 M4(J==="codex"?"codex":"claude")[0]?.id??null}currentTokenSource(){return Z$(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=Z$($.tokenSourceId);if(Z&&Z.agent!==$.provider)throw Error(`token source "${Z.id}" belongs to ${Z.agent}, not ${$.provider}`);if(this.selectedProvider!==$.provider)I$(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$.provider,this.selectedTokenSourceId=$.tokenSourceId,this.selectedModel=$.model,this.selectedEffort=$.effort,this.lastSessionRef=p0(this.sessionName,$.provider),this.lastSessionId=this.lastSessionRef?.sessionId??null,x6(this.sessionName,$.provider,$.model,$.effort,$.tokenSourceId)}async listCodexConversations(){if(this.selectedProvider!=="codex")throw Error("Codex history requested for a non-Codex session");if(!j2())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,Q=new L1({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Z?.id??null,transformEnv:J}),Y=null,H=null;try{Y=await Q.listConversations()}catch(X){H=X}let W=null;try{await Q.kill(2000)}catch(X){W=X}if(H&&W)throw AggregateError([H,W],`Codex history query and cleanup failed: ${D(H)}; ${D(W)}`);if(H)throw H;if(W)throw W;return Y??[]}async resolveLegacyResumeRef($){if($.cwd!==null)return $;if($.provider!==this.selectedProvider)throw Error(`legacy resume provider mismatch: ${$.provider} != ${this.selectedProvider}`);let Z;if($.provider==="claude"){let J=H6(this.workDir,$.sessionId);if(!VH(J))throw Error(`旧 Claude 会话不属于当前 cwd,或 transcript 不存在: ${A$($.sessionId)}`);Z={...$,cwd:this.workDir}}else{if(!j2())throw Error("Codex 未登录 ChatGPT 账号");let J=this.currentTokenSource();if(this.selectedTokenSourceId&&(!J||!J.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或选择其他账号`);let Q=J?.enabled?J:void 0,Y=new L1({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Q?.id??null,transformEnv:Q?(X)=>Q.spawnEnv(X):void 0}),H=null;try{Z=await Y.readConversationRef($.sessionId)}catch(X){H=X,Z=$}let W=null;try{await Y.kill(2000)}catch(X){W=X}if(H&&W)throw AggregateError([H,W],`Codex legacy resume lookup and cleanup failed: read=${D(H)}; cleanup=${D(W)}`);if(H)throw H;if(W)throw W}return G$({kind:"resume",source:Z},this.selectedProvider,this.workDir),K2(this.sessionName,Z),Z}hasRunningPeerSession($){return[...W1.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 S$(this.selectedEffort)?this.selectedEffort:Z2}return Z2}claudeEffortForSpawn(){return this.selectedProvider==="claude"&&d$(this.selectedEffort)?this.selectedEffort:P0}currentModelLabel(){return(this.selectedModel??this.currentTokenSource()?.defaultModel??this.proc?.lastModel??null)?.replace(/^claude:/i,"").replace(/\[1m\]$/i,"")??null}currentEffortLabel(){return this.selectedEffort??this.proc?.lastEffort??(this.selectedProvider==="claude"?P0:Z2)}runtimeModelSelection(){let $=this.proc?.isAlive()?this.proc:null,Z=$?.provider??this.selectedProvider,J=!$||$.provider===this.selectedProvider,Q=($?.lastModel??(J?this.currentModelLabel():null))?.replace(/^claude:/i,"").replace(/\[1m\]$/i,"")??null,Y=$?.lastEffort??(J?this.currentEffortLabel():Z==="claude"?P0:Z2);return{provider:Z,model:Q,effort:Y}}modelEffortLabel($=this.currentTurn??this.runtimeModelSelection()){let Z=$.provider==="claude"?$.model?.replace(/^claude:/i,"").replace(/\[1m\]$/i,""):$.model,J=Z?`${Z}/${$.effort}`:$.effort;return $.provider==="claude"?`${J0($.provider)} · ${J}`:J}withModel($,Z){let J=this.modelEffortLabel(Z);return $.includes(J)?$:`${$} · ${J}`}replaceFooterContent($,Z){return o($,M.footer,this.footerElement(Z),void 0,!1)}footerElement($){return{tag:"markdown",element_id:M.footer,content:$.trim()||" "}}modelLine($){return this.modelEffortLabel($)}backendLabel($=this.selectedProvider){return J0($)}pendingConversationLaunch=null;pendingConversationMaterialization=null;lastTurnUserPreview="";pendingCodexTurnAnchors=[];pendingMaterializationLaunch(){let $=this.pendingConversationMaterialization;if(!$)return null;if(G$($.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=xK(32).toString("base64url");let Z={LODESTAR_AGENT_URL:E4(w.notify.bind,w.notify.port),LODESTAR_AGENT_CAPABILITY:this.agentCapability,LODESTAR_AGENT_SESSION:this.sessionName},J=this.pendingConversationLaunch??this.pendingMaterializationLaunch()??($?{kind:"resume",source:$}:{kind:"fresh"});G$(J,this.selectedProvider,this.workDir);let Q=this.currentTokenSource();if(this.selectedTokenSourceId&&(!Q||!Q.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或在 model 面板选择其他账号`);let Y=Q?.enabled?Q:void 0,H=O4({provider:this.selectedProvider,workDir:this.workDir,tokenSourceId:Y?.id??null,model:Y?this.selectedModel??Y.defaultModel:this.modelForSpawn(),effort:this.selectedProvider==="claude"?this.claudeEffortForSpawn():this.effortForSpawn(),launch:J,developerInstructions:this.spawnDeveloperInstructions(),profile:k1(this.worktreeProjectName()),...process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"?{}:{managedSkillPluginPath:x0},hostEnv:Z});return this.procSourceRevisions.set(H.process,H.sourceRevision),H.process}async applyModelSelection($,Z,J,Q){await this.runLifecycle("apply-model-selection",()=>this.applyModelSelectionUnlocked($,Z,J,Q))}async applyModelSelectionUnlocked($,Z,J,Q){if(this.selectedProvider!==$)I$(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$,this.selectedTokenSourceId=Q??this.selectedTokenSourceId;let H=Z$(this.selectedTokenSourceId);if(H)this.selectedModel=Z||null,this.selectedEffort=J??H.models.find((W)=>W.model===Z)?.defaultEffort??H.models[0]?.defaultEffort??null;else this.selectedModel=$==="codex"?null:Z,this.selectedEffort=$==="codex"?null:J;this.lastSessionRef=p0(this.sessionName,$),this.lastSessionId=this.lastSessionRef?.sessionId??null,y6(this.sessionName,$,this.selectedModel,this.selectedEffort,this.selectedTokenSourceId),await this.stopIdleMismatchedProcessUnlocked()}async stopIdleMismatchedProcess(){await this.runLifecycle("stop-idle-mismatched",()=>this.stopIdleMismatchedProcessUnlocked())}async stopIdleMismatchedProcessUnlocked(){if(!this.proc?.isAlive())return;let $=this.currentTokenSource(),Z=!this.procSourceRevisions.has(this.proc)||this.procSourceRevisions.get(this.proc)===($?.spawnRevision??null);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;z(`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 Q=await this.settleProcResumableState(J),Y=null;try{await J.kill(1000)}catch(X){Y=X}Q=await this.settleProcResumableState(J);let H=this.finishProcStop(J,Y);this.opts.onLifecycleChange?.();let W=[...!H?[Y??Error(this.blockedProcReason??"process stop unconfirmed")]:[],...Q?[Error(Q)]:[]];if(W.length===1)throw W[0];if(W.length>1)throw AggregateError(W,`idle process stop failed: ${W.map(D).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;z(`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),Q=null;try{await Z.kill(1000)}catch(W){Q=W}J=await this.settleProcResumableState(Z);let Y=this.finishProcStop(Z,Q);this.opts.onLifecycleChange?.();let H=[...!Y?[Q??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(D).join("; ")}`);return!0}startFooterTimer($,Z,J=(Q)=>Q){let Q=Date.now(),Y=Z,H=!1,W=()=>{if(H)return;this.replaceFooterContent($,J(GH(Y,Q)))},X=null,V=()=>{if(H)return;let{nextDelayMs:A}=R0(Date.now()-Q,H1());X=setTimeout(()=>{W(),V()},Math.max(1,Math.ceil(A)))};return W(),V(),{setStatus(A){Y=A,W()},stop(){if(H=!0,X)clearTimeout(X)},elapsedSec(){return((Date.now()-Q)/1000).toFixed(1)}}}async openStatusCard($,Z,J="blue"){let Q=Date.now(),Y=K7({sessionName:this.sessionName,title:$,status:GH(Z,Q),template:J}),H=await n(this.chatId,Y);if(!H)return z(`session "${this.sessionName}": status card send failed title=${$}`),await x(this.chatId,`❌ 创建状态卡片失败: ${$}`),null;let W;try{W=await a$(H)}catch(X){return z(`session "${this.sessionName}": status card id_convert failed title=${$}: ${X}`),await x(this.chatId,`❌ 状态卡片初始化失败: ${$}`),null}return m$(W,1),{cardId:W,title:$,timer:this.startFooterTimer(W,Z,(X)=>C2($,X))}}setStatusCard($,Z){$?.timer.setStatus(Z)}async closeStatusCard($,Z){if(!$)return;$.timer.stop();let J=$.timer.elapsedSec(),Q=C2($.title,`${Z} (${J}s)`);await u$($.cardId);let Y=await F$($.cardId,M.footer,this.footerElement(Q));V$($.cardId);let H=await q$($.cardId,A0({durationSec:J,suffix:Z}));if(Y&&H)await x$($.cardId);else{let W=`footer=${Y?"ok":"MISS"}, settings=${H?"ok":"MISS"}`;z(`session "${this.sessionName}": status card terminal transaction incomplete card=${$.cardId.slice(0,12)} ${W}`),await x(this.chatId,`⚠️ 状态卡片终态写入失败 (${W}):${Z}`)}}async runLifecycle($,Z){let J=this.lifecycleTail,Q;this.lifecycleTail=new Promise((H)=>{Q=H}),await J;let Y=++this.lifecycleSequence;z(`session "${this.sessionName}": lifecycle#${Y} ${$} begin`);try{return await Z()}finally{Q(),z(`session "${this.sessionName}": lifecycle#${Y} ${$} 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 Q,Y=new Promise((W)=>{Q=W}),H={token:++this.turnOpenSequence,proc:$,procEpoch:Z,sawResult:!1,terminalForcePush:!1,pendingCompactions:[],backendTurnStarted:J,done:Y,resolveDone:Q};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),Q=Buffer.from($);return J.length===Q.length&&bK(J,Q)}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?D(Z):"kill returned while process still reports alive",z(`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(Q){J=Q}return this.finishProcStop($,J)}async settleProcResumableState($){let Z=null,J=$.conversationMaterializationBarrier?.();if(J)try{await J}catch(H){Z=`Codex 会话落盘确认失败: ${D(H)}`}let Q=$.conversationMaterializationFailure?.();if(Q&&$.isConversationResumable?.()!==!0)Z=`Codex 会话落盘确认失败: ${D(Q)}`;let Y=this.persistResumableSessionId(!1,$,!1);return[Z,Y].filter(Boolean).join(";")||null}resetFreshConversationState(){this.turnCounter=0,this.pendingConversationMaterialization=null,I$(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,Q=this.blockedProcessMessage();if(Q){if(this.status="stopped",J?.(`❌ ${Q}`),Z)await T(this.chatId,`❌ ${Q}。请重试 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"&&!j2()){if(this.status="stopped",this.opts.onLifecycleChange?.(),J?.("❌ Codex 未登录 ChatGPT 账号"),Z)await T(this.chatId,"❌ Codex 未登录 ChatGPT 账号。\n请在服务器上运行 `codex login` 后再试。");return!1}if(!VH(this.workDir)){if(J?.(`\uD83C\uDD95 创建项目目录 ~/${this.sessionName}`),Z)await T(this.chatId,`\uD83C\uDD95 目录 ~/${this.sessionName} 不存在,正在创建…`);try{u6(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 Y;try{await U4(),Y=this.spawnAgent()}catch(G){let _=`${this.backendLabel()} 启动失败: ${D(G)}`;if(z(`session "${this.sessionName}": ${_}`),J?.(`❌ ${_}`),Z)await T(this.chatId,`❌ ${_}`);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}this.attachProc(Y);let H=this.backendLabel(),W=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(Y,AH):null;J?.(this.selectedProvider==="claude"?`⏳ 检查 ${H} 启动`:`⏳ 等待 ${H} init`);let X,V=null;try{if(Y.sendInitialize(),this.selectedProvider==="codex")X=Y.initializationPromise?.()}catch(G){X=void 0,V=G}let A=V?{state:"error",error:V}:this.selectedProvider==="claude"?await W:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(X),()=>{z(`session "${this.sessionName}": codex init still pending after ${L5/1000}s`),J?.(this.withModel(`⏳ 仍在等待 ${H} init 确认`))});if(A.state==="error"||A.state==="exit"){let G=A.error?D(A.error):A.state;z(`session "${this.sessionName}": ${this.selectedProvider} init failed: ${G}`);let q=await this.stopOwnedProc(Y,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,B=`❌ ${H} 启动失败: ${G}${q}`;if(J?.(B),Z)await T(this.chatId,B);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(A.state==="timeout"){z(`session "${this.sessionName}": ${this.selectedProvider} init wait timeout (${u9/1000}s)`);let _=await this.stopOwnedProc(Y,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,q=`❌ ${H} 启动超时: ${u9/1000} 秒内初始化事务未完成${_}`;if(J?.(q),Z)await T(this.chatId,q);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(this.proc!==Y||!Y.isAlive()){let G=`${H} 启动期间已退出`;if(z(`session "${this.sessionName}": ${G}`),J?.(`❌ ${G}`),Z)await T(this.chatId,`❌ ${G}`);return this.detachProc(Y),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(`
|
|
183
|
+
`))}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 Q=!1,Y=(X,V)=>{if(Q)return;Q=!0,clearTimeout(H),clearTimeout(W),J({state:X,error:V})},H=setTimeout(()=>{if(Q)return;try{Z?.()}catch(X){Y("error",X)}},L5),W=setTimeout(()=>{Y("timeout",Error(`codex init timed out after ${u9/1000}s`))},u9);$.then(()=>Y("init"),(X)=>Y("error",X))})}async waitForProcEarlyFailure($,Z){return await new Promise((J)=>{let Q=!1,Y=(A,G)=>{if(Q)return;Q=!0,clearTimeout(H),$.off("init",W),$.off("error",X),$.off("exit",V),J({state:A,error:G})},H=setTimeout(()=>Y("ready"),Z),W=()=>Y("init"),X=(A)=>Y("error",A),V=(A)=>Y("exit",A);$.once("init",W),$.once("error",X),$.once("exit",V)})}releaseAllReactions(){for(let[$,Z]of[...this.pendingReactionIds.entries(),...this.currentBatchReactionIds.entries()])if(Z)j$($,Z);this.pendingReactionIds=new Map,this.currentBatchReactionIds=new Map}clearStaleIdleQueueState($){if(this.initCount<1||this.currentTurn||this.openingTurn||this.pendingUserMessageCount===0)return;z(`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)j$(Z,J);this.pendingReactionIds=new Map}async stop($="已终止",Z={}){await this.runLifecycle("stop",()=>this.stopUnlocked($,Z))}async stopUnlocked($="已终止",Z={}){let J=Z.announce??!0,Q=Z.onStatus;if(await this.cancelAgentRuns($),!this.proc){if(this.status="stopped",this.opts.onLifecycleChange?.(),Q?.("⚪ session 当前未运行"),J)await T(this.chatId,`⚪ session "${this.sessionName}" 当前未运行`);return}let Y=this.proc,H=this.persistResumableSessionId(!1,Y,!1),W=null;if(Q?.(`\uD83D\uDED1 停止 ${this.backendLabel(this.proc.provider)}`),z(`session "${this.sessionName}": stop (${$})`),this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.currentTurn)this.closeTurnCard(`\uD83D\uDED1 ${$}`).catch((F)=>{z(`session "${this.sessionName}": stop current main-card close failed: ${D(F)}`)});let X=this.waitForTurnCloses().catch((F)=>z(`session "${this.sessionName}": stop main-card close failed: ${D(F)}`));this.beginProcStop(Y),this.status="stopped";let V=[];try{this.opts.onLifecycleChange?.()}catch(F){V.push(F),z(`session "${this.sessionName}": stop intent lifecycle write failed: ${D(F)}`)}let A=Y.conversationMaterializationBarrier?.();if(A){try{await A}catch(F){W=`Codex 会话落盘确认失败: ${D(F)}`}H=this.persistResumableSessionId(!1,Y,!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 Y.kill()}catch(F){G=F}let _=Y.conversationMaterializationFailure?.();if(_&&Y.isConversationResumable?.()!==!0)W=`Codex 会话落盘确认失败: ${D(_)}`;H=this.persistResumableSessionId(!1,Y,!1);let B=(await Promise.allSettled([this.resetBackgroundTasks(),X])).filter((F)=>F.status==="rejected").map((F)=>F.reason);for(let F of B)z(`session "${this.sessionName}": stop terminal cleanup failed: ${D(F)}`);let R=this.finishProcStop(Y,G);try{this.opts.onLifecycleChange?.()}catch(F){V.push(F),z(`session "${this.sessionName}": stop final lifecycle write failed: ${D(F)}`)}let L=[...G?[G]:[],...!R&&!G?[Error(this.blockedProcReason??"process stop unconfirmed")]:[],...B,...V,...H?[Error(H)]:[],...W&&Y.isConversationResumable?.()!==!0?[Error(W)]:[]];if(L.length===1)throw L[0];if(L.length>1)throw AggregateError(L,`stop failed: ${L.map(D).join("; ")}`);if(Q?.(`✅ ${$}`),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 Q=Z.announce??!0,Y=Z.onStatus,H=this.status,W=null;if(!$&&!this.pendingConversationLaunch&&this.pendingConversationMaterialization)W=this.pendingConversationMaterialization,D0(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(E){let k=this.invalidateMissingCodexResume(V.sessionId,E,J),u=k?`❌ 旧会话不可恢复: ${D(E)};${k}`:`❌ 旧会话 cwd 校验失败: ${D(E)};请在进程已停时发送 rs 重新选择历史会话`;if(this.status=this.proc?.isAlive()?H:"stopped",Y?.(u),Q)await T(this.chatId,u);return!1}let A=V?.sessionId??null,G=X&&X.kind!=="fresh"?X.source.sessionId:A,_=G?A$(G):"",q=null,B=(E=this.proc)=>{if(!$||X||E?.provider!=="codex"||E.isConversationResumable?.()!==!0)return;q=this.persistResumableSessionId(!1,E,!1),V=this.lastSessionRef,A=V?.sessionId??null,G=A,_=G?A$(G):""},R=null;if(!Y&&Q&&$&&A){let E=this.proc?this.withModel(`\uD83D\uDD01 重启 ${this.backendLabel(this.proc.provider)}`):this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${_}`);if(R=await this.openStatusCard("restart",E),R)Y=(k)=>this.setStatusCard(R,k)}let L=Q&&!R,F=async(E)=>{if(R)await this.closeStatusCard(R,E)},U=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((E)=>{z(`session "${this.sessionName}": restart current main-card close failed: ${D(E)}`)});let P=this.waitForTurnCloses().catch((E)=>z(`session "${this.sessionName}": restart main-card close failed: ${D(E)}`)),j=null,S=null;if(this.proc){let E=this.proc;Y?.(`\uD83D\uDED1 停止当前 ${this.backendLabel(E.provider)}`),S=E,this.beginProcStop(E);let k=E.conversationMaterializationBarrier?.();if(k)try{await k}catch(p){q=`Codex 会话落盘确认失败: ${D(p)}`}if(B(E),$&&!X&&q&&!U&&E.isAlive()){if(this.stoppingProc===E)this.stoppingProc=null;this.status=H;let p=`❌ ${this.backendLabel(E.provider)} 恢复点尚未安全落盘,已保留当前进程: ${q}`;if(z(`session "${this.sessionName}": abort restart before kill: ${q}`),Y?.(p),L)await T(this.chatId,p);return await F(p),!1}try{await E.kill()}catch(p){j=p}let u=E.conversationMaterializationFailure?.();if(u&&E.isConversationResumable?.()!==!0)q=`Codex 会话落盘确认失败: ${D(u)}`;B(E)}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 y=(await Promise.allSettled([this.resetBackgroundTasks(),P])).filter((E)=>E.status==="rejected").map((E)=>E.reason);for(let E of y)z(`session "${this.sessionName}": restart terminal cleanup failed: ${D(E)}`);let m=S?this.finishProcStop(S,j):!0,v=[...j?[`kill=${D(j)}`]:[],...!m&&!j?[`kill=${this.blockedProcReason??"process stop unconfirmed"}`]:[],...y.map((E)=>`cleanup=${D(E)}`),...q?[`resume=${q}`]:[]];if(v.length>0&&W)try{D0(this.sessionName,W),this.pendingConversationMaterialization=W}catch(E){v.push(`pendingRestore=${D(E)}`)}if(v.length>0){let E=`❌ 旧 ${this.backendLabel()} 进程停止/清理失败: ${v.join("; ")}`;if(this.status="stopped",this.opts.onLifecycleChange?.(),Y?.(E),L)await T(this.chatId,E);return await F(E),!1}let g=X?.kind==="resume"||X?.kind==="fork";if($&&V||g){this.status="starting",this.usageTotalsSeedUnknown=!0,Y?.(this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${_}`));let E;try{await U4(),E=this.spawnAgent(V??void 0)}catch(I){let M$=`❌ ${this.backendLabel()} 恢复失败: ${D(I)}`;if(z(`session "${this.sessionName}": ${this.selectedProvider} resume failed before spawn: ${D(I)}`),Y?.(M$),L)await T(this.chatId,M$);return this.status="stopped",this.opts.onLifecycleChange?.(),await F(M$),!1}this.attachProc(E);let k=this.backendLabel(),u=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(E,AH):null;Y?.(this.selectedProvider==="claude"?`⏳ 检查 ${k} 恢复启动`:`⏳ 等待 ${k} init 确认`);let p,a=null;try{if(E.sendInitialize(),this.selectedProvider==="codex")p=E.initializationPromise?.()}catch(I){p=void 0,a=I}let O=a?{state:"error",error:a}:this.selectedProvider==="claude"?await u:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(p),()=>{z(`session "${this.sessionName}": codex resume init still pending after ${L5/1000}s`),Y?.(this.withModel(`⏳ 仍在等待 ${k} init 确认 thread=${_}`))});if(O.state==="error"||O.state==="exit"||O.state==="timeout"){let I=O.state==="error"?this.invalidateMissingCodexResume(G,O.error,J):null,M$=[O.error?D(O.error):O.state,I].filter(Boolean).join(";");z(`session "${this.sessionName}": ${this.selectedProvider} resume failed: ${M$}`);let a1=await this.stopOwnedProc(E,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,A1=O.state==="timeout"?`❌ ${k} 恢复超时${a1}`:`❌ ${k} 恢复失败: ${M$}${a1}`;if(Y?.(A1),L)await T(this.chatId,A1);return this.status="stopped",this.opts.onLifecycleChange?.(),await F(A1),!1}if(this.proc!==E||!E.isAlive()){let I=`❌ ${k} 恢复期间已退出`;if(z(`session "${this.sessionName}": ${this.selectedProvider} resume process exited before ready`),Y?.(I),L)await T(this.chatId,I);return this.detachProc(E),this.status="stopped",this.opts.onLifecycleChange?.(),await F(I),!1}let f=this.withModel(this.withWorktreeInstructionNotice(this.selectedProvider==="claude"&&O.state==="ready"?`✅ 已准备恢复上一会话 thread=${_}`:`✅ 已恢复上一会话 thread=${_}`));if(Y?.(f),L)await T(this.chatId,f);this.status="idle",this.startedAt=Date.now(),this.opts.onLifecycleChange?.();try{await F(f)}catch(I){z(`session "${this.sessionName}": restart succeeded but status-card close failed: ${D(I)}`),await x(this.chatId,`⚠️ ${f}
|
|
184
|
+
状态卡收尾失败: ${D(I)}`)}return!0}else{if($&&!X){if(Y?.("⚠️ 没有可恢复的上一会话,将以新会话启动"),L)await T(this.chatId,"⚠️ 没有可恢复的上一会话,将以新会话启动")}return this.resetFreshConversationState(),await this.startUnlocked({...Z,freshConversationStateAlreadyReset:!0})}}async startForked($,Z={}){return await this.runLifecycle("start-forked",async()=>{G$($,this.selectedProvider,this.workDir);let J=R2(this.sessionName),Q=this.selectedProvider==="claude"?{launch:$,previousSessionId:this.lastSessionId}:null;if(Q)D0(this.sessionName,Q),this.pendingConversationMaterialization=Q;this.pendingConversationLaunch=$;try{let Y=await this.startUnlocked(Z);if(!Y&&Q)D0(this.sessionName,J),this.pendingConversationMaterialization=J;return Y}catch(Y){if(!Q)throw Y;try{D0(this.sessionName,J),this.pendingConversationMaterialization=J}catch(H){throw AggregateError([Y,H],`fork start and pending-intent restore failed: ${D(Y)}; ${D(H)}`)}throw Y}finally{this.pendingConversationLaunch=null}})}async rollbackTo($,Z,J={}){return await this.runLifecycle("rollback",async()=>{G$($,this.selectedProvider,this.workDir);let Q=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,Y=this.proc,H=this.lastSessionId,W=this.lastSessionRef,X=q2(this.sessionName).slice(),V=B2(this.sessionName),A=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},_=!1,q=()=>{if(_)this.lastSessionId=null,this.lastSessionRef=null,S1(this.sessionName,"codex");else if(this.lastSessionId=H,this.lastSessionRef=W,W)K2(this.sessionName,W);else S1(this.sessionName,this.selectedProvider);I$(this.sessionName,X,V,A),this.pendingConversationMaterialization=A,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},B=!1;if(Q?.pendingLaunch)I$(this.sessionName,Q.anchors,Q.base,Q.pendingLaunch),this.pendingConversationMaterialization=Q.pendingLaunch,B=!0;this.pendingConversationLaunch=$;let R=(L)=>{_=W?.provider==="codex"&&W.sessionId===L};try{let L;try{L=$.kind==="fresh"?await this.restartUnlocked(!1,J,R):await this.restartUnlocked(!0,J,R)}catch(F){let U=null,P=this.proc&&this.proc!==Y?this.proc:null;if(P)try{await this.stopUnlocked("回滚启动事务失败",{announce:!1})}catch(y){U=y}let j=!P||this.proc!==P&&!P.isAlive();if(!j&&!U)U=Error("replacement process stop was not confirmed");let S=null;if(j)try{q()}catch(y){S=y}let b=[F,...U?[U]:[],...S?[S]:[]];if(b.length===1)throw F;throw AggregateError(b,`rollback launch and cleanup failed: ${b.map(D).join("; ")}`)}if(!L)return q(),!1;if(Q)try{if(!B)I$(this.sessionName,Q.anchors,Q.base,Q.pendingLaunch);this.pendingConversationMaterialization=Q.pendingLaunch}catch(F){let U=null,P=this.proc;try{await this.stopUnlocked("回滚分支状态持久化失败",{announce:!1})}catch(y){U=y}let j=!P||this.proc!==P&&!P.isAlive();if(!j&&!U)U=Error("replacement process stop was not confirmed");let S=null;if(j)try{q()}catch(y){S=y}let b=[F,...U?[U]:[],...S?[S]:[]];if(b.length===1)throw F;throw AggregateError(b,`rollback branch commit failed: ${b.map(D).join("; ")}`)}return L}finally{this.pendingConversationLaunch=null}})}dispose(){W1.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 Q=`拒绝了与当前会话不匹配的 checkpoint provider=${$.provider} source=${$.source.sessionId}`;return z(`session "${this.sessionName}": ${Q}`),this.lastTurnUserPreview="",Q}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((Y)=>Y.proc===Z).length>=64)return z(`session "${this.sessionName}": ${"Codex rollout 长期未确认,延迟 checkpoint 队列已满"} thread=${Z.sessionId}`),"Codex rollout 长期未确认,延迟 checkpoint 队列已满";return this.pendingCodexTurnAnchors.push({proc:Z,anchor:J}),z(`session "${this.sessionName}": defer Codex turn checkpoint until rollout confirmation thread=${Z.sessionId} checkpoint=${$.id}`),null}return this.appendTurnAnchor(J)}appendTurnAnchor($){try{return k6(this.sessionName,$),null}catch(Z){let J=`分叉 checkpoint 持久化失败: ${D(Z)}`;return z(`session "${this.sessionName}": ${J}`),J}}flushPendingCodexTurnAnchors($){let Z=null,J=[];for(let Q of this.pendingCodexTurnAnchors){if(Q.proc!==$||Z){J.push(Q);continue}if(Z=this.appendTurnAnchor(Q.anchor),Z)J.push(Q)}return this.pendingCodexTurnAnchors=J,Z}discardPendingCodexTurnAnchors($,Z){if($.provider!=="codex")return;let J=this.pendingCodexTurnAnchors.length;this.pendingCodexTurnAnchors=this.pendingCodexTurnAnchors.filter((Y)=>Y.proc!==$);let Q=J-this.pendingCodexTurnAnchors.length;if(Q>0)z(`session "${this.sessionName}": dropped ${Q} unmaterialized Codex checkpoint(s): ${Z}`)}collectTurnWrites(){let $=this.currentTurn;if(!$)return[];let Z=[];for(let J of $.toolByUseId.values())Z.push(...k7(J.name,J.input));return Z}worktreeProjectName(){return S0(this)}worktreeProjectDir(){return u1(this)}spawnDeveloperInstructions(){return mY(this)}delegatedAgentDeveloperInstructions($){return uY(this,$)}worktreeInstructionLoadedNotice(){return K5(this)}withWorktreeInstructionNotice($){return pY(this,$)}worktreeExtraInstruction(){return c2(this)}runWorktreeCommand($,Z){return lY(this,$,Z)}showWorktrees(){return q5(this)}showTasklistPanel(){return LY(this)}showAgentIdentityPanel($=""){return zY(this,$)}onAgentIdentityPage($,Z,J){return AY($,Z,J)}onTasklistEnable(){return DY(this)}onTasklistDeletePrompt($){return jY(this,$)}onTasklistDeleteConfirm($){return FY(this,$)}runCompactCommand(){return tQ(this)}showModelPanel(){return $Y(this)}onModelSelect($,Z="",J="",Q=null){return HY(this,$,Z,J,Q)}onModelEffortSelect($,Z,J="",Q="",Y=""){return this.runLifecycle("model-effort-select",()=>WY(this,$,Z,J,Q,Y))}onProviderSelect($,Z=""){return ZY(this,$,Z)}onModelPanelCancel($=""){return YY(this,$)}onModelCustomPrompt($,Z,J=""){return JY(this,$,Z,J)}consumeModelCustomMessage($,Z){return QY(this,$,Z)}onWorktreeDisband($){return nY(this,$)}showForkList($=""){return eY(this,$)}showBackList($=""){return $H(this,$)}showResumeList($=""){return ZH(this,$)}runBtwCommand($){return JH(this,$)}runByeCommand(){return QH(this)}onForkSelect($,Z,J=""){return YH(this,$,Z,J)}onBackSelect($,Z,J=""){return HH(this,$,Z,J)}onResumeSelect($,Z,J=""){return WH(this,$,Z,J)}runCommand($,Z=""){return aQ(this,$,Z)}async buildConsoleOpts($,Z){let J=await kJ(),Q=this.runtimeModelSelection();return{sessionName:this.sessionName,status:this.status,provider:Q.provider,model:Q.model??void 0,effort:Q.effort,worktreeInstructionNotice:this.worktreeInstructionLoadedNotice(),peers:[...W1.all].filter((Y)=>Y.isRunning()).map((Y)=>({...Y.peerSnapshot(),isCurrent:Y===this})),usage:$,glmUsage:Z,sysinfo:J}}async buildConsoleCard($){return q7(await this.buildConsoleOpts($))}async patchConsoleUsage($){let Z=await this.buildConsoleOpts(void 0),J=Z.provider??this.currentProvider(),Q=this.currentTokenSource(),Y=Q&&Q.agent===J&&Q.enabled?Q:this.selectedTokenSourceId?void 0:M4(J)[0];if(Y)Z.unifiedUsage=await Y.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 c7();else Z.usage=await F9();if(!await F$($,M.consoleUsage,f2(Z),{notifyCardFailure:!1}))throw Error("console usage element replace rejected")}async mutateStaticCard($,Z,J){let Q=!0;try{await J()}catch(H){Q=!1,z(`session "${this.sessionName}": ${Z} mutation failed: ${D(H)}`)}let Y=!1;try{Y=await q$($,{config:{streaming_mode:!1}})}catch(H){z(`session "${this.sessionName}": ${Z} streaming-off failed: ${D(H)}`)}if(!Q||!Y)return z(`session "${this.sessionName}": ${Z} state retained after checked MISS mutation=${Q} streamingOff=${Y} card=${$.slice(0,12)}`),!1;try{await x$($)}catch(H){return z(`session "${this.sessionName}": ${Z} dispose failed: ${D(H)}`),!1}return Q}patchConsoleUsageLater($){this.mutateStaticCard($,"console usage",()=>this.patchConsoleUsage($))}async replaceStatusCardWithConsole($,Z){$.timer.stop();let J=$.timer.elapsedSec(),Q=await this.buildConsoleOpts(void 0);await u$($.cardId);let Y=await F$($.cardId,M.footer,H9(Q,M.footer)),H=await j0($.cardId,Y9(Q),{type:"insert_after",targetElementId:M.footer}),W=await j0($.cardId,W9(Q.sysinfo),{type:"insert_after",targetElementId:M.consoleProjects}),X=await j0($.cardId,f2(Q),{type:"insert_after",targetElementId:M.consoleHost});if(!Y||!H||!W||!X){await x(this.chatId,"⚠️ 控制台卡片结构写入失败,请重新发送 hi。"),await this.mutateStaticCard($.cardId,"console structure",async()=>{});return}V$($.cardId),await q$($.cardId,A0({durationSec:J,suffix:Z})),this.patchConsoleUsageLater($.cardId)}async showConsole(){let $=await this.buildConsoleCard(void 0),Z=await n(this.chatId,$);if(!Z)return;(async()=>{let J="";try{J=await a$(Z),m$(J,4)}catch(Q){z(`session "${this.sessionName}": console card conversion failed: ${D(Q)}`);return}await this.mutateStaticCard(J,"console usage",()=>this.patchConsoleUsage(J))})().catch((J)=>z(`session "${this.sessionName}": console async update rejected: ${D(J)}`))}interrupt(){if(!this.proc)return;z(`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 Q=this.beginTurnOpen();try{let H=await this.openTurnCard(Q,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 u$(H.cardId),!V){this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),await this.closeTurnCard(X.startsWith("❌")?X:"❌ 启动失败",{forcePush:!0});return}let A=this.proc;if(!A?.isAlive()){await this.closeTurnCard(`❌ ${this.backendLabel()} 启动后已退出`,{forcePush:!0});return}this.startThinkingFooter(H),this.sendClaimedUserText(A,Z),this.status="working"}finally{this.releaseTurnOpen(Q)}}async onUserMessage($,Z=[],J="",Q=""){await this.runLifecycle("user-message",()=>this.onUserMessageUnlocked($,Z,J,Q))}async onUserMessageUnlocked($,Z,J,Q){let Y=this.blockedProcessMessage();if(Y){await T(this.chatId,`❌ ${Y}。请重试 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((A)=>`[file: ${A}]`).join(" ")+`
|
|
185
|
+
`:"")+$,V=(A)=>{this.pendingReactionIds.set(A,""),(async()=>{let G=await T$(A,"OneSecond");if(!G)return;if(this.pendingReactionIds.has(A))this.pendingReactionIds.set(A,G);else if(this.currentBatchReactionIds.has(A))this.currentBatchReactionIds.set(A,G);else j$(A,G)})().catch((G)=>{z(`session "${this.sessionName}": reaction tracking failed: ${D(G)}`)})};if(!this.isRunning()){if(this.openingTurn||this.currentTurn){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Q}),Q)V(Q);return}await this.startColdUserTurn($,X,J);return}if(this.currentTurn!==null){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Q}),Q)V(Q);return}if(!this.openingTurn&&this.initCount>=1){let A=this.proc,G=this.procEpoch,_=this.beginTurnOpen(A,G);try{this.pendingTurnInputs.push($);let q=await this.openTurnCard(_,J,"user_message");if(!q||this.currentTurn!==q)return;if(this.proc!==A||this.procEpoch!==G||!A.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel(A.provider)} 已退出`);return}this.sendClaimedUserText(A,X),this.status="working"}finally{this.releaseTurnOpen(_)}return}if(this.openingTurn||this.pendingUserMessageCount>0){if(this.pendingMidTurnMsgs.push({text:$,wireText:X,userOpenId:J,msgId:Q}),Q)V(Q);return}if(this.pendingTurnInputs.push($),this.sendClaimedUserText(this.proc,X),H&&Q)V(Q)}hasPendingAsk(){return SQ(this)}onMultiMessageInbound($,Z,J,Q){return zQ(this,$,Z,J,Q)}clearMultiMsgBuffer($){p7(this,$)}onAskMessageAnswer($,Z,J){return NQ(this,$,Z,J)}onAskAnswer($,Z,J,Q){return yQ(this,$,Z,J,Q)}onAskCustomAnswer($,Z,J,Q){return a7(this,$,Z,J,Q)}onPermissionDecision($,Z,J){return bQ(this,$,Z,J)}clearResumeBindingForFreshCodex($){if($.isConversationResumable?.())throw Error("fresh Codex thread was unexpectedly marked resumable during init");let Z=p0(this.sessionName,"codex");if(S1(this.sessionName,"codex"),this.selectedProvider==="codex")this.lastSessionRef=null,this.lastSessionId=null;if(Z)z(`session "${this.sessionName}": cleared pre-fresh Codex resume binding thread=${Z.sessionId}`)}invalidateMissingCodexResume($,Z,J){if(!$||this.selectedProvider!=="codex")return null;let Q=D5(Z);if(!Q||!["thread/read","thread/resume","thread/fork"].includes(Q.method)||Q.serverCode!==-32600||Q.serverMessage!==`no rollout found for thread id ${$}`)return null;let Y=p0(this.sessionName,"codex");if(!Y||Y.sessionId!==$)return null;try{S1(this.sessionName,"codex")}catch(W){let X=`已确认恢复点无 rollout,但作废失败: ${D(W)}`;return z(`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=${A$($)}`;return z(`session "${this.sessionName}": ${H} fullThread=${$}`),H}persistResumableSessionId($=!1,Z=this.proc,J=!0){let Q=Z?.provider==="claude"?this.pendingConversationMaterialization:null,Y=Z?.sessionId;if(!Z)return null;if(Z.provider==="codex"&&Z.isConversationResumable?.()!==!0)return null;if(!Y){if(!Q)return null;let X=Error("Claude pending fork did not provide a materialized session id");if(z(`session "${this.sessionName}": ${X.message}`),$)throw X;return X.message}let H={provider:Z.provider,sessionId:Y,cwd:this.workDir};if(Q&&(Y===Q.launch.source.sessionId||Q.previousSessionId!==null&&Y===Q.previousSessionId)){let X=Error(`Claude fork did not materialize an independent session id (${Y})`);if(z(`session "${this.sessionName}": ${X.message}`),$)throw X;return X.message}try{K2(this.sessionName,H)}catch(X){let V=`会话恢复点持久化失败: ${D(X)}`,A=this.resumePersistenceError!==V;if(this.resumePersistenceError=V,Z.provider===this.selectedProvider)this.lastSessionRef=H,this.lastSessionId=Y;if(z(`session "${this.sessionName}": ${V}`),$)throw X;if(A&&J)x(this.chatId,`⚠️ ${V};当前进程可继续,但 daemon 重启前请先解决本机状态目录写入问题。`);return V}if(Z.provider===this.selectedProvider)this.lastSessionRef=H,this.lastSessionId=Y;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)x(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 z(`session "${this.sessionName}": ${"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker"}`),"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker";try{return D0(this.sessionName,null),this.pendingConversationMaterialization=null,null}catch(J){let Q=`Claude 待生成分支标记清除失败: ${D(J)}`;return z(`session "${this.sessionName}": ${Q}`),Q}}bgStore(){return{active:this.backgroundTasks,pending:this.pendingBgTasks}}applyBgStore($){this.backgroundTasks=$.active,this.pendingBgTasks=$.pending}onMainThreadAdvance(){if(this.pendingBgTasks.length===0)return;this.applyBgStore(p8(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(!w0(this.backgroundTasks)){if(this.backgroundCard)this.settleBackgroundCard().catch((Z)=>{z(`session "${this.sessionName}": background settle failed: ${D(Z)}`)});return}if(!this.backgroundCard&&!this.openingBackground){this.openBackgroundCard().catch((Z)=>{z(`session "${this.sessionName}": background open failed: ${D(Z)}`)});return}this.scheduleBackgroundRefresh()}async openBackgroundCard(){let $=this.beginBackgroundOpen();if(!$)return;let Z=this.backgroundTasks.slice();try{let J=o8(Z,Date.now(),H1()),Q=await n(this.chatId,J);if(!Q){if(this.ownsBackgroundOpen($))z(`session "${this.sessionName}": background card send failed`);return}let Y;try{Y=await a$(Q)}catch(H){z(`session "${this.sessionName}": background card id_convert failed: ${H}`);return}if(m$(Y,Z.length),!this.ownsBackgroundOpen($)){await this.terminalizeSupersededCard(Y,"⚠️ 后台任务世代已切换,本卡已作废",!1);return}if(this.backgroundCard={messageId:Q,cardId:Y},this.backgroundDetailAdded=new Set(Z.map((H)=>H.id)),this.backgroundDetailAdding.clear(),z(`session "${this.sessionName}": background card opened cardId=${Y.slice(0,12)} tasks=${Z.length}`),!w0(this.backgroundTasks)){this.settleBackgroundCard().catch((H)=>{z(`session "${this.sessionName}": background settle-after-open failed: ${D(H)}`)});return}this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}finally{this.releaseBackgroundOpen($)}}startBackgroundRefreshTick(){if(this.backgroundRefreshTick)return;let $=()=>{if(this.migratingBackgroundCard||!this.backgroundCard||!w0(this.backgroundTasks))return;let Z=H1(),J=Date.now(),Q=1/0;for(let Y of this.backgroundTasks){if(y$(Y))continue;let H=R0(J-Y.startedAt,Z).nextDelayMs;if(H<Q)Q=H}if(!isFinite(Q))return;this.backgroundRefreshTick=setTimeout(()=>{this.refreshBackgroundCardFull(),$()},Math.max(1,Math.ceil(Q)))};$()}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=H1();for(let Q of this.backgroundTasks)if(!this.backgroundDetailAdded.has(Q.id)){if(this.backgroundDetailAdding.has(Q.id))continue;this.backgroundDetailAdding.add(Q.id),j0($.cardId,j1(Q,Z,J)).then((Y)=>{if(Y)this.backgroundDetailAdded.add(Q.id);else z(`session "${this.sessionName}": background panel add MISS task=${Q.id}`)}).finally(()=>{this.backgroundDetailAdding.delete(Q.id)})}else o($.cardId,J2.panel(Q.id),j1(Q,Z,J));X0($.cardId,K4(this.backgroundTasks))}async resetBackgroundTasks(){if(this.invalidateBackgroundOpen(),this.backgroundTasks.some(($)=>!y$($))){let $=Date.now();this.backgroundTasks=this.backgroundTasks.map((Z)=>y$(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){z(`session "${this.sessionName}": background migration failed before settle; retry terminal snapshot: ${D(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 u$($.cardId),await H0($.messageId,q4(Z)),V$($.cardId),!await q$($.cardId,A0({suffix:"\uD83E\uDDED 后台任务已结束"})))throw Error("background history streaming-off rejected");if(await x$($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((Q)=>!y$(Q)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),z(`session "${this.sessionName}": background card settled cardId=${$.cardId.slice(0,12)} remaining=${this.backgroundTasks.length}`)}finally{if(this.settlingBackgroundCard=!1,this.backgroundCard===$&&w0(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 u$($.cardId),this.backgroundCard!==$)return;let Z=[...this.backgroundTasks],J=new Set(Z.filter(y$).map((H)=>H.id)),Q=J.size;if(Q>0)await H0($.messageId,q4(Z));else await H0($.messageId,a8());if(V$($.cardId),!await q$($.cardId,A0({suffix:"\uD83E\uDDED 已迁移至新卡"})))throw Error("background migration streaming-off rejected");if(await x$($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((H)=>!J.has(H.id)||!y$(H)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),z(`session "${this.sessionName}": background card migrated cardId=${$.cardId.slice(0,12)} terminal=${Q} active=${this.backgroundTasks.length}`)}startScheduledTurnCard($,Z,J,Q){if(this.proc!==$||this.procEpoch!==Z||!$.isAlive())return;if(this.currentTurn||this.openingTurn||this.pendingUserMessageCount>0||this.bgResumePending)return;let Y;try{Y=this.beginTurnOpen($,Z,!0)}catch(W){z(`session "${this.sessionName}": scheduled turn-open ownership conflict: ${D(W)}`);return}let H=J.replace(/\s+/g," ").trim();this.lastTurnUserPreview=`⏰ ${H.slice(0,78)}`,z(`session "${this.sessionName}": scheduled wakeup prompt=${Q??"MISS"}`),(async()=>{try{let W=await this.openTurnCard(Y,"","scheduled_wakeup");if(this.proc!==$||this.procEpoch!==Z){if(z(`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(Y))return;if(this.bgResumeCardless=!0,Y.sawResult)Y.sawResult=!1,z(`session "${this.sessionName}": scheduled open failed after result — flushing orphan now`),this.flushOrphanAssistantToChat("scheduled open failed, result already arrived");else z(`session "${this.sessionName}": scheduled open failed — orphan text flush will cover the output`)}else if(Y.sawResult)Y.sawResult=!1,z(`session "${this.sessionName}": scheduled result raced card-open — closing freshly-opened card`),await this.closeTurnCard(Y.terminalSuffix,{forcePush:Y.terminalForcePush,hasFreshResult:!0}),this.status="idle";else this.status="working"}finally{this.releaseTurnOpen(Y)}})().catch((W)=>{z(`session "${this.sessionName}": scheduled turn-open handler failed: ${D(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 Q=()=>this.proc===$&&this.procEpoch===J,Y=!1,H=!1,W=(X,V)=>{$.on(X,(A)=>{if(!Q()){if(!Y)Y=!0,z(`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,z(`session "${this.sessionName}": ignore ${$.provider} event=${String(X)} while process stop is pending`);return}V(A)})};W("error",(X)=>{z(`session "${this.sessionName}": ${$.provider} process error: ${X}`)}),W("init",()=>{if($.provider==="codex"&&$.launchKind==="fresh")this.clearResumeBindingForFreshCodex($);else this.persistResumableSessionId(!0);if(this.initCount++,z(`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)z(`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 A=this.lastUserOpenId,G;try{G=this.beginTurnOpen($,J,!0)}catch(B){z(`session "${this.sessionName}": init turn-open ownership conflict: ${D(B)}`);return}if(this.bgResumePending=!1,X)this.pendingUserMessageCount=0,this.currentBatchReactionIds=this.pendingReactionIds,this.pendingReactionIds=new Map;let _=X?[...this.currentBatchReactionIds.keys()]:[],q=()=>{for(let B of _){let R=this.currentBatchReactionIds.get(B);if(this.currentBatchReactionIds.delete(B),R)j$(B,R)}};(async()=>{try{let B=await this.openTurnCard(G,A,X?"user_message":"bg_task_resume");if(!Q()){if(z(`session "${this.sessionName}": ${$.provider} became stale while opening turn card epoch=${J}`),B&&this.currentTurn===B)await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);q();return}if(!B||this.currentTurn!==B){if(!this.ownsTurnOpen(G)){q();return}if(G.sawResult&&G.terminalSuffix)x(this.chatId,G.terminalSuffix);if(X)z(`session "${this.sessionName}": init-path openTurnCard failed — sendInterrupt + release reactions`),this.proc?.sendInterrupt(),q();else if(this.bgResumeCardless=!0,G.sawResult)G.sawResult=!1,z(`session "${this.sessionName}": bg-resume openTurnCard failed, result already arrived — flushing orphan now`),this.flushOrphanAssistantToChat("bg-resume open failed, result already arrived");else z(`session "${this.sessionName}": bg-resume openTurnCard failed — orphan text flush will cover the output`)}else if(G.sawResult)G.sawResult=!1,z(`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((B)=>{z(`session "${this.sessionName}": init turn-open handler failed: ${D(B)}`)})}),W("scheduled_turn_input",({text:X,promptId:V})=>{if($.provider!=="claude")return;this.startScheduledTurnCard($,J,X,V)}),W("conversation_materialized",({session_id:X,source:V})=>{if($.provider!=="codex")return;if($.sessionId!==X){z(`session "${this.sessionName}": ignore mismatched Codex materialization session=${X} current=${$.sessionId??"MISS"} source=${V}`);return}z(`session "${this.sessionName}": Codex resume point materialized thread=${X} source=${V}`),this.persistResumableSessionId()}),W("conversation_materialization_failed",({session_id:X,source:V,error:A})=>{if($.provider!=="codex"||$.sessionId!==X)return;let G=`Codex 会话落盘确认失败,未写恢复点: ${D(A)}`,_=this.resumePersistenceError!==G;if(this.resumePersistenceError=G,z(`session "${this.sessionName}": ${G} thread=${X} source=${V}`),_)x(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)z(`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")rJ(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:A,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(i8({active:this.backgroundTasks,pending:this.pendingBgTasks},G,X,V,A)),this.onBackgroundTaskChanged();return}if(EQ(this,X,V,A),!G)this.onMainThreadAdvance();if(!G&&(V==="Task"||V==="Agent"))this.lastMainTaskToolUseId=X}),W("tool_result",({tool_use_id:X,content:V,is_error:A,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(d8({active:this.backgroundTasks,pending:this.pendingBgTasks},G,X,V,A)),this.onBackgroundTaskChanged();return}TQ(this,X,V,A)}),W("can_use_tool",(X)=>{CQ(this,X)}),W("hook_callback",(X)=>{this.proc?.sendHookResponse(X.request_id,{})}),W("result",(X)=>{let V=this.persistResumableSessionId(),A=V?null:this.consumePendingConversationMaterialization(),G=[V,A].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",S=this.proc?.lastResult.is_error===!0;z(`session "${this.sessionName}": SDK result after user stop subtype=${j} isError=${S} — 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 q=this.pendingMidTurnMsgs.length>0,B=this.proc?.lastResult.is_error===!0,R=this.proc?.lastResult.subtype??"success",L,F=!1,U=this.proc?this.backendLabel(this.proc.provider):this.backendLabel(),P=[G,_].filter(Boolean).join(";")||null;if(P)L=`⚠️ ${P}`,F=!0;else if(q)L=B?`⚠️ ${U} ${R},用户已介入`:"\uD83D\uDCE8 转交新卡";else if(B)L=`⚠️ ${U} ${R}`,F=!0;if(this.openingTurnOwner)this.openingTurnOwner.terminalSuffix=L,this.openingTurnOwner.terminalForcePush=F;if(P&&!this.currentTurn&&!this.openingTurn)x(this.chatId,`⚠️ ${P}`);if(z(`session "${this.sessionName}": SDK result subtype=${R} isError=${B} midBuffer=${this.pendingMidTurnMsgs.length} forcePush=${F}`),this.closeTurnCard(L,{forcePush:F,hasFreshResult:!0}).catch((j)=>{z(`session "${this.sessionName}": result card close failed: ${D(j)}`)}),this.status="idle",q)this.drainMidTurnAndOpen().catch((j)=>{z(`session "${this.sessionName}": mid-turn drain failed: ${D(j)}`)})}),W("bg_task_started",(X)=>{let V=X.tool_use_id??this.lastMainTaskToolUseId??void 0;z(`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(c8(this.bgStore(),{...X,tool_use_id:V})),this.onBackgroundTaskChanged()}),W("bg_task_progress",(X)=>{this.applyBgStore(m8(this.bgStore(),X)),this.onBackgroundTaskChanged()}),W("bg_task_updated",(X)=>{this.applyBgStore(u8(this.bgStore(),X)),this.onBackgroundTaskChanged()}),W("bg_task_settled",(X)=>{if(z(`session "${this.sessionName}": bg_task_settled task=${X.task_id} status=${X.status}`),this.applyBgStore(l8(this.bgStore(),X)),this.onBackgroundTaskChanged(),$.provider==="claude"&&!this.currentTurn&&!this.openingTurn&&this.initCount>=1)this.bgResumePending=!0}),W("subagent_step",(X)=>{this.applyBgStore(n8(this.bgStore(),X.thread_id,X.item_id,X.tool,X.phase,X.brief)),this.onBackgroundTaskChanged()}),W("exit",({code:X,signal:V,expected:A})=>{if(z(`session "${this.sessionName}": ${$.provider} exited code=${X} signal=${V} expected=${A}`),this.stoppingProc===$||this.blockedProc===$){if(this.blockedProc===$){let R=$.conversationMaterializationFailure?.(),L=this.persistResumableSessionId(!1,$,!1),F=[R&&$.isConversationResumable?.()!==!0?`Codex 会话落盘确认失败: ${D(R)}`:null,L].filter(Boolean).join(";");if(F)x(this.chatId,`⚠️ 旧进程退出后的恢复状态收尾失败: ${F}`);this.discardPendingCodexTurnAnchors($,"blocked process finally exited")}z(`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((R)=>{z(`session "${this.sessionName}": cancel Agent runs after process exit failed: ${D(R)}`)});let G=this.backendLabel($.provider),_=`code=${X??"null"}, signal=${V??"null"}`,q=A?`\uD83D\uDED1 ${G} 已退出`:`⚠️ ${G} 异常退出 (${_})`;if(this.currentTurn)this.closeTurnCard(q).catch((R)=>{z(`session "${this.sessionName}": process-exit current main-card close failed: ${D(R)}`)});let B=this.waitForTurnCloses().catch((R)=>{z(`session "${this.sessionName}": process-exit main-card close failed: ${D(R)}`)});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 R=await Promise.allSettled([B,this.resetBackgroundTasks()]);for(let L of R)if(L.status==="rejected")z(`session "${this.sessionName}": process-exit terminal cleanup failed: ${D(L.reason)}`);if(!A)await T(this.chatId,`⚠️ ${G} 异常退出 (${_})。回复任意消息将重新启动。`)}).catch((R)=>{z(`session "${this.sessionName}": process-exit cleanup rejected: ${D(R)}`)})})}accumulateResultStats(){let $=this.proc?.lastResult;if(!$)return;let Z=this.currentTurnUsageBaselineKnown?T8(this.proc?.lastTotalUsage,this.currentTurnUsageBaseline):this.proc?.provider==="claude"&&$.usage?{...$.usage}:null;this.lastTurnUsage=Z,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;let J=k8(Z),Q=this.proc?.provider==="claude"?0:$.cost_delta_usd??0,Y=$.duration_ms??0;if(J!=null)this.cumStats.tokens+=J;this.cumStats.costUsd+=Q,this.cumStats.turns+=$.num_turns??1,this.lastTurnDelta={tokens:J,costUsd:Q,durationMs:Y}}currentContextTokens($=this.proc){if($?.provider==="claude")return $.lastContextTokens??null;let Z=$?.lastUsage;return I4(Z)}contextLimitForDisplay($=this.proc){return c4($?.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(Y){z(`session "${this.sessionName}": mid-turn open ownership conflict: ${D(Y)}`);return}let Q=this.pendingMidTurnMsgs;this.pendingMidTurnMsgs=[];try{for(let V of Q)if(this.pendingTurnInputs.push(V.text),V.msgId){let A=this.pendingReactionIds.get(V.msgId)??"";this.currentBatchReactionIds.set(V.msgId,A),this.pendingReactionIds.delete(V.msgId)}let Y=Q.map((V)=>V.wireText).join(`
|
|
186
186
|
|
|
187
|
-
`),W=Q[Q.length-1]?.userOpenId??this.lastUserOpenId,X=await this.openTurnCard(J,W,"user_message");if(!X||this.currentTurn!==X){for(let V of Q){if(!V.msgId)continue;let A=this.currentBatchReactionIds.get(V.msgId);if(this.currentBatchReactionIds.delete(V.msgId),A)j$(V.msgId,A)}this.status="idle";return}if(this.proc!==$||this.procEpoch!==Z||!$.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);for(let V of Q){if(!V.msgId)continue;let A=this.currentBatchReactionIds.get(V.msgId);if(this.currentBatchReactionIds.delete(V.msgId),A)j$(V.msgId,A)}this.status="stopped";return}try{this.sendClaimedUserText($,Y)}catch(V){z(`session "${this.sessionName}": mid-turn sendUserText failed after card open: ${V}`),await this.closeTurnCard(`❌ ${this.backendLabel($.provider)} 接收消息失败`),await b(this.chatId,`❌ ${this.backendLabel($.provider)} 接收消息失败: ${D(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 Q=J?await F$($,M.footer,this.footerElement(Z)):!0;V$($);let Y=await q$($,A0({suffix:Z}));if(Q&&Y){await x$($);return}let H=`footer=${Q?"ok":"MISS"}, settings=${Y?"ok":"MISS"}`;z(`session "${this.sessionName}": superseded card terminal transaction incomplete card=${$.slice(0,12)} ${H}`),await b(this.chatId,`⚠️ 已作废卡片未能正常关闭 (${H})。`)}rebuildBackgroundAfterTurnOpenFailure(){if(!this.pendingRebuildBackgroundCard)return;if(this.pendingRebuildBackgroundCard=!1,this.backgroundTasks.length===0)return;this.openBackgroundCard().catch(($)=>{z(`session "${this.sessionName}": background rebuild after turn-open failure failed: ${D($)}`)})}async openTurnCard($,Z,J,Q={}){if(!this.ownsTurnOpen($))return null;if(this.bgResumePending=!1,this.backgroundCard&&w0(this.backgroundTasks))try{await this.migrateBackgroundCard(),this.pendingRebuildBackgroundCard=!0}catch(R){z(`session "${this.sessionName}": background migrate failed (non-blocking): ${R}`),this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(!this.ownsTurnOpen($))return null;let Y=++this.turnCounter,H=this.pendingTurnInputs;this.pendingTurnInputs=[],this.lastTurnUserPreview=H[0]?.slice(0,80)??this.lastTurnUserPreview,z(`session "${this.sessionName}": openTurnCard turn=${Y} trigger=${J} inputs=${H.length}`);let W=this.runtimeModelSelection(),X=this.withModel(Q.initialFooter??"Waiting...(0s)",W),V=l4({sessionName:this.sessionName,turn:Y,provider:W.provider,model:W.model??void 0,effort:W.effort,kind:J,userInputs:H,initialFooter:X,directStart:Q.directStart}),A=await i(this.chatId,V);if(!A){if(!this.ownsTurnOpen($))return null;if(z(`session "${this.sessionName}": openTurnCard sendCard EXHAUSTED retries — surfacing via raw text`),J==="user_message")await b(this.chatId,`❌ 创建对话卡片失败 (Feishu SDK 重试 3 次后仍连不上)。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);return this.rebuildBackgroundAfterTurnOpenFailure(),null}let G;try{G=await a$(A)}catch(R){if(z(`session "${this.sessionName}": id_convert failed: ${R}`),J==="user_message"&&this.ownsTurnOpen($))await b(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 m$(G,_),await this.terminalizeSupersededCard(G,"⚠️ 会话已切换,本卡已作废",!0),null;let q={cardId:G,...W,messageId:A,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,cardWriteFailureNotified:!1,rotateGivenUp:!1,outboundSeenPaths:new Set,outboundSentPaths:new Set};if(m$(G,_,(R,L)=>{this.onCardWriteFailure(q,G,R,L)}),this.currentTurn=q,Q.startThinking!==!1)this.startThinkingFooter(q);if($.pendingCompactions.length>0){let R=$.pendingCompactions.splice(0);z(`session "${this.sessionName}": replay ${R.length} context compaction event(s) buffered during card open`);for(let L of R)this.handleContextCompacted(L)}let B=this.takeOrphanAssistantText();if(B)this.appendAssistant(B),this.finalizeCurrentAssistantSegment();if(this.pendingRebuildBackgroundCard){if(this.pendingRebuildBackgroundCard=!1,this.backgroundTasks.length>0)this.openBackgroundCard().catch((R)=>{z(`session "${this.sessionName}": background rebuild failed: ${D(R)}`)})}return q}maybeMidTurnRotate(){let $=this.currentTurn;if(!$)return;if($.rotateGivenUp)return;if($.rotating)return;if(l6($.cardId)<wK)return;this.startMidTurnRotate($)}onCardWriteFailure($,Z,J,Q){let Y=this.currentTurn;if(Y!==$){z(`session "${this.sessionName}": ignore stale card failure card=${Z.slice(0,12)} code=${J??"n/a"} (turn owner changed)`);return}if(Y.cardId!==Z){z(`session "${this.sessionName}": ignore retired-card failure card=${Z.slice(0,12)} current=${Y.cardId.slice(0,12)} code=${J??"n/a"}`);return}if(Y.rotating)return;if(Y.rotateGivenUp)return;if(!p6(J,Q)){let H=Q?.operation??"unknown operation",W=Q?.elementId?` element=${Q.elementId}`:"";if(z(`session "${this.sessionName}": non-capacity card write failure card=${Z.slice(0,12)} operation=${H}${W} code=${J??"n/a"} — not rotating`),!Y.cardWriteFailureNotified)Y.cardWriteFailureNotified=!0,b(this.chatId,`⚠️ 对话卡片有一项写入失败(code=${J??"MISS"}, ${H})。未识别为卡片容量超限,未自动换卡;其余输出继续处理。`);return}if(Y.failureRotateCount>=c2){Y.rotateGivenUp=!0,this.stopFooterStatus(Y),w4(Y.cardId),z(`session "${this.sessionName}": failure-rotate cap (${c2}) hit — giving up, rest of turn is log-only`),b(this.chatId,`⚠️ 本轮已因卡片容量超限换卡 ${c2} 次,现停止继续换卡;本轮后续输出仅日志可见。`);return}z(`session "${this.sessionName}": confirmed card capacity limit (${J}) on card=${Y.cardId.slice(0,8)}… — rotating to fresh card`),Y.failureRotateCount++,this.startMidTurnRotate(Y)}startMidTurnRotate($){if($.rotating)return;$.rotateCount++;let{cardId:Z,toolByUseId:J,toolBatches:Q}=$,Y={value:null},H=(W,X)=>{if(!Y.value)Y.value={code:W,failure:X}};$.rotating=(async()=>{try{z(`session "${this.sessionName}": mid-turn rotate triggered card=${Z.slice(0,8)}… elementCount=${l6(Z)}`);let W=l4({sessionName:this.sessionName,turn:this.turnCounter,provider:$.provider,model:$.model??void 0,effort:$.effort,kind:"card_full",userInputs:[]}),X=await i(this.chatId,W);if(!X){if(z(`session "${this.sessionName}": mid-turn rotate sendCard EXHAUSTED — staying on old card,subsequent adds will drop`),this.currentTurn===$)$.rotateGivenUp=!0,this.stopFooterStatus($),w4($.cardId);await b(this.chatId,"⚠️ 卡片容量超出飞书上限,本轮后续输出仅日志可见(开新卡失败)。");return}let V;try{V=await a$(X)}catch(B){if(z(`session "${this.sessionName}": mid-turn rotate id_convert failed: ${B}`),this.currentTurn===$)$.rotateGivenUp=!0,this.stopFooterStatus($),w4($.cardId),await b(this.chatId,"⚠️ 新对话卡已发送,但 Card Kit 初始化失败;已停止继续换卡,本轮后续输出仅日志可见。");return}m$(V,2,(B,R)=>{if($.rotating){H(B,R);return}this.onCardWriteFailure($,V,B,R)});let A=$.assistantWriteInflight?.get(Z);if(A?.size)await Promise.allSettled([...A]);this.stopFooterStatus($),$.cardId=V,$.messageId=X,$.toolCount=0,$.toolByUseId=new Map,$.toolBatches=new Map,$.openBatchI=null,$.planUpdateCount=0,$.goalUpdateCount=0;let G=$.currentAssistantSegmentId,_=($.currentAssistantText??"").trim(),q=$.segmentTexts;if($.assistantSegmentCount=0,$.currentAssistantSegmentId=null,$.currentAssistantText="",$.segmentTexts=new Map,_)this.startWritingFooter($);else this.startThinkingFooter($);if($.taskLiveInserted)z$($.cardId,s0(this.taskBoard),{type:"insert_before",targetElementId:M.footer});if($.planLiveInserted)z$($.cardId,U2($.planSteps,$.planExplanation,M.planLive),{type:"insert_before",targetElementId:$.taskLiveInserted?M.taskBoardLive:M.footer});for(let B of $.contextCompactionPending.values()){if(B.cardId!==Z)continue;B.cardId=V,B.created=!1,B.createFailure=void 0;let R=M.contextCompact(B.i);B.createPromise=h4(V,M2(B.i,B.notice,R),{type:"insert_before",targetElementId:B$($)}).then((L)=>{if(B.cardId===V)B.created=L.landed,B.createFailure=L.failure;return L.landed})}for(let[B,R]of q){if(G&&_&&B===G)continue;if(!y1(Z,B))continue;let L=$.assistantSegmentCount++,F=M.assistant(L);$.segmentTexts.set(F,R),await this.addCompletedAssistantSegment($,F,R)}if(o7(this,Z,V,J,Q),await u$(Z),o7(this,Z,V,J,Q),G&&_){let B=$.assistantSegmentCount++,R=M.assistant(B);$.currentAssistantSegmentId=R,$.currentAssistantText=_,$.segmentTexts.set(R,_)}try{let B=$.mathRenderInflight?.get(Z);if(B?.size)await Promise.allSettled([...B]);await u$(Z);let R=$.mathRendered?.get(Z);for(let[P,j]of q){if(G&&_&&P===G)continue;if(y1(Z,P))continue;if(R?.has(P))continue;await o(Z,P,this.completedAssistantElement(P,j))}let L=$.contextCompactCount>0?` · \uD83D\uDEA8 压缩×${$.contextCompactCount}`:"",F=await F$(Z,M.footer,this.footerElement(this.withModel(`\uD83D\uDCE8 已续至下一张卡 ↓${L}`)),{notifyCardFailure:!1});V$(Z);let U=await q$(Z,A0({suffix:"\uD83D\uDCE8 转下一张"}));if(F&&U)await x$(Z);else z(`session "${this.sessionName}": rotate old-card terminal MISS footer=${F} settings=${U}`),await b(this.chatId,`⚠️ 上一张对话卡未能正常关闭 (footer=${F?"ok":"MISS"}, settings=${U?"ok":"MISS"}),本轮输出已续到新卡。`)}catch(B){z(`session "${this.sessionName}": mid-turn rotate close-old failed: ${B}`)}z(`session "${this.sessionName}": mid-turn rotate done old=${Z.slice(0,8)}… new=${V.slice(0,8)}…`)}finally{$.rotating=null;let W=Y.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=M.planUpdate($.planUpdateCount++);z$(Z,a6($.planSteps,$.planExplanation,"",J),{type:"insert_before",targetElementId:B$($)})}addGoalUpdateOnCurrentTurn($){let Z=this.currentTurn;if(!Z)return;this.maybeMidTurnRotate();let J=M.goalUpdate(Z.goalUpdateCount++);z$(Z.cardId,r6($,J),{type:"insert_before",targetElementId:B$(Z)})}addGoalClearedOnCurrentTurn(){let $=this.currentTurn;if(!$)return;this.maybeMidTurnRotate();let Z=M.goalUpdate($.goalUpdateCount++);z$($.cardId,{tag:"markdown",element_id:Z,content:`**\uD83C\uDFAF 当前目标**
|
|
187
|
+
`),W=Q[Q.length-1]?.userOpenId??this.lastUserOpenId,X=await this.openTurnCard(J,W,"user_message");if(!X||this.currentTurn!==X){for(let V of Q){if(!V.msgId)continue;let A=this.currentBatchReactionIds.get(V.msgId);if(this.currentBatchReactionIds.delete(V.msgId),A)j$(V.msgId,A)}this.status="idle";return}if(this.proc!==$||this.procEpoch!==Z||!$.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);for(let V of Q){if(!V.msgId)continue;let A=this.currentBatchReactionIds.get(V.msgId);if(this.currentBatchReactionIds.delete(V.msgId),A)j$(V.msgId,A)}this.status="stopped";return}try{this.sendClaimedUserText($,Y)}catch(V){z(`session "${this.sessionName}": mid-turn sendUserText failed after card open: ${V}`),await this.closeTurnCard(`❌ ${this.backendLabel($.provider)} 接收消息失败`),await x(this.chatId,`❌ ${this.backendLabel($.provider)} 接收消息失败: ${D(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 Q=J?await F$($,M.footer,this.footerElement(Z)):!0;V$($);let Y=await q$($,A0({suffix:Z}));if(Q&&Y){await x$($);return}let H=`footer=${Q?"ok":"MISS"}, settings=${Y?"ok":"MISS"}`;z(`session "${this.sessionName}": superseded card terminal transaction incomplete card=${$.slice(0,12)} ${H}`),await x(this.chatId,`⚠️ 已作废卡片未能正常关闭 (${H})。`)}rebuildBackgroundAfterTurnOpenFailure(){if(!this.pendingRebuildBackgroundCard)return;if(this.pendingRebuildBackgroundCard=!1,this.backgroundTasks.length===0)return;this.openBackgroundCard().catch(($)=>{z(`session "${this.sessionName}": background rebuild after turn-open failure failed: ${D($)}`)})}async openTurnCard($,Z,J,Q={}){if(!this.ownsTurnOpen($))return null;if(this.bgResumePending=!1,this.backgroundCard&&w0(this.backgroundTasks))try{await this.migrateBackgroundCard(),this.pendingRebuildBackgroundCard=!0}catch(R){z(`session "${this.sessionName}": background migrate failed (non-blocking): ${R}`),this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(!this.ownsTurnOpen($))return null;let Y=++this.turnCounter,H=this.pendingTurnInputs;this.pendingTurnInputs=[],this.lastTurnUserPreview=H[0]?.slice(0,80)??this.lastTurnUserPreview,z(`session "${this.sessionName}": openTurnCard turn=${Y} trigger=${J} inputs=${H.length}`);let W=this.runtimeModelSelection(),X=this.withModel(Q.initialFooter??"Waiting...(0s)",W),V=l4({sessionName:this.sessionName,turn:Y,provider:W.provider,model:W.model??void 0,effort:W.effort,kind:J,userInputs:H,initialFooter:X,directStart:Q.directStart}),A=await n(this.chatId,V);if(!A){if(!this.ownsTurnOpen($))return null;if(z(`session "${this.sessionName}": openTurnCard sendCard EXHAUSTED retries — surfacing via raw text`),J==="user_message")await x(this.chatId,`❌ 创建对话卡片失败 (Feishu SDK 重试 3 次后仍连不上)。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);return this.rebuildBackgroundAfterTurnOpenFailure(),null}let G;try{G=await a$(A)}catch(R){if(z(`session "${this.sessionName}": id_convert failed: ${R}`),J==="user_message"&&this.ownsTurnOpen($))await x(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 m$(G,_),await this.terminalizeSupersededCard(G,"⚠️ 会话已切换,本卡已作废",!0),null;let q={cardId:G,...W,messageId:A,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,cardWriteFailureNotified:!1,rotateGivenUp:!1,outboundSeenPaths:new Set,outboundSentPaths:new Set};if(m$(G,_,(R,L)=>{this.onCardWriteFailure(q,G,R,L)}),this.currentTurn=q,Q.startThinking!==!1)this.startThinkingFooter(q);if($.pendingCompactions.length>0){let R=$.pendingCompactions.splice(0);z(`session "${this.sessionName}": replay ${R.length} context compaction event(s) buffered during card open`);for(let L of R)this.handleContextCompacted(L)}let B=this.takeOrphanAssistantText();if(B)this.appendAssistant(B),this.finalizeCurrentAssistantSegment();if(this.pendingRebuildBackgroundCard){if(this.pendingRebuildBackgroundCard=!1,this.backgroundTasks.length>0)this.openBackgroundCard().catch((R)=>{z(`session "${this.sessionName}": background rebuild failed: ${D(R)}`)})}return q}maybeMidTurnRotate(){let $=this.currentTurn;if(!$)return;if($.rotateGivenUp)return;if($.rotating)return;if(l6($.cardId)<cK)return;this.startMidTurnRotate($)}onCardWriteFailure($,Z,J,Q){let Y=this.currentTurn;if(Y!==$){z(`session "${this.sessionName}": ignore stale card failure card=${Z.slice(0,12)} code=${J??"n/a"} (turn owner changed)`);return}if(Y.cardId!==Z){z(`session "${this.sessionName}": ignore retired-card failure card=${Z.slice(0,12)} current=${Y.cardId.slice(0,12)} code=${J??"n/a"}`);return}if(Y.rotating)return;if(Y.rotateGivenUp)return;if(!p6(J,Q)){let H=Q?.operation??"unknown operation",W=Q?.elementId?` element=${Q.elementId}`:"";if(z(`session "${this.sessionName}": non-capacity card write failure card=${Z.slice(0,12)} operation=${H}${W} code=${J??"n/a"} — not rotating`),!Y.cardWriteFailureNotified)Y.cardWriteFailureNotified=!0,x(this.chatId,`⚠️ 对话卡片有一项写入失败(code=${J??"MISS"}, ${H})。未识别为卡片容量超限,未自动换卡;其余输出继续处理。`);return}if(Y.failureRotateCount>=m2){Y.rotateGivenUp=!0,this.stopFooterStatus(Y),w4(Y.cardId),z(`session "${this.sessionName}": failure-rotate cap (${m2}) hit — giving up, rest of turn is log-only`),x(this.chatId,`⚠️ 本轮已因卡片容量超限换卡 ${m2} 次,现停止继续换卡;本轮后续输出仅日志可见。`);return}z(`session "${this.sessionName}": confirmed card capacity limit (${J}) on card=${Y.cardId.slice(0,8)}… — rotating to fresh card`),Y.failureRotateCount++,this.startMidTurnRotate(Y)}startMidTurnRotate($){if($.rotating)return;$.rotateCount++;let{cardId:Z,toolByUseId:J,toolBatches:Q}=$,Y={value:null},H=(W,X)=>{if(!Y.value)Y.value={code:W,failure:X}};$.rotating=(async()=>{try{z(`session "${this.sessionName}": mid-turn rotate triggered card=${Z.slice(0,8)}… elementCount=${l6(Z)}`);let W=l4({sessionName:this.sessionName,turn:this.turnCounter,provider:$.provider,model:$.model??void 0,effort:$.effort,kind:"card_full",userInputs:[]}),X=await n(this.chatId,W);if(!X){if(z(`session "${this.sessionName}": mid-turn rotate sendCard EXHAUSTED — staying on old card,subsequent adds will drop`),this.currentTurn===$)$.rotateGivenUp=!0,this.stopFooterStatus($),w4($.cardId);await x(this.chatId,"⚠️ 卡片容量超出飞书上限,本轮后续输出仅日志可见(开新卡失败)。");return}let V;try{V=await a$(X)}catch(B){if(z(`session "${this.sessionName}": mid-turn rotate id_convert failed: ${B}`),this.currentTurn===$)$.rotateGivenUp=!0,this.stopFooterStatus($),w4($.cardId),await x(this.chatId,"⚠️ 新对话卡已发送,但 Card Kit 初始化失败;已停止继续换卡,本轮后续输出仅日志可见。");return}m$(V,2,(B,R)=>{if($.rotating){H(B,R);return}this.onCardWriteFailure($,V,B,R)});let A=$.assistantWriteInflight?.get(Z);if(A?.size)await Promise.allSettled([...A]);this.stopFooterStatus($),$.cardId=V,$.messageId=X,$.toolCount=0,$.toolByUseId=new Map,$.toolBatches=new Map,$.openBatchI=null,$.planUpdateCount=0,$.goalUpdateCount=0;let G=$.currentAssistantSegmentId,_=($.currentAssistantText??"").trim(),q=$.segmentTexts;if($.assistantSegmentCount=0,$.currentAssistantSegmentId=null,$.currentAssistantText="",$.segmentTexts=new Map,_)this.startWritingFooter($);else this.startThinkingFooter($);if($.taskLiveInserted)z$($.cardId,s0(this.taskBoard),{type:"insert_before",targetElementId:M.footer});if($.planLiveInserted)z$($.cardId,O2($.planSteps,$.planExplanation,M.planLive),{type:"insert_before",targetElementId:$.taskLiveInserted?M.taskBoardLive:M.footer});for(let B of $.contextCompactionPending.values()){if(B.cardId!==Z)continue;B.cardId=V,B.created=!1,B.createFailure=void 0;let R=M.contextCompact(B.i);B.createPromise=h4(V,U2(B.i,B.notice,R),{type:"insert_before",targetElementId:B$($)}).then((L)=>{if(B.cardId===V)B.created=L.landed,B.createFailure=L.failure;return L.landed})}for(let[B,R]of q){if(G&&_&&B===G)continue;if(!y1(Z,B))continue;let L=$.assistantSegmentCount++,F=M.assistant(L);$.segmentTexts.set(F,R),await this.addCompletedAssistantSegment($,F,R)}if(o7(this,Z,V,J,Q),await u$(Z),o7(this,Z,V,J,Q),G&&_){let B=$.assistantSegmentCount++,R=M.assistant(B);$.currentAssistantSegmentId=R,$.currentAssistantText=_,$.segmentTexts.set(R,_)}try{let B=$.mathRenderInflight?.get(Z);if(B?.size)await Promise.allSettled([...B]);await u$(Z);let R=$.mathRendered?.get(Z);for(let[P,j]of q){if(G&&_&&P===G)continue;if(y1(Z,P))continue;if(R?.has(P))continue;await o(Z,P,this.completedAssistantElement(P,j))}let L=$.contextCompactCount>0?` · \uD83D\uDEA8 压缩×${$.contextCompactCount}`:"",F=await F$(Z,M.footer,this.footerElement(this.withModel(`\uD83D\uDCE8 已续至下一张卡 ↓${L}`)),{notifyCardFailure:!1});V$(Z);let U=await q$(Z,A0({suffix:"\uD83D\uDCE8 转下一张"}));if(F&&U)await x$(Z);else z(`session "${this.sessionName}": rotate old-card terminal MISS footer=${F} settings=${U}`),await x(this.chatId,`⚠️ 上一张对话卡未能正常关闭 (footer=${F?"ok":"MISS"}, settings=${U?"ok":"MISS"}),本轮输出已续到新卡。`)}catch(B){z(`session "${this.sessionName}": mid-turn rotate close-old failed: ${B}`)}z(`session "${this.sessionName}": mid-turn rotate done old=${Z.slice(0,8)}… new=${V.slice(0,8)}…`)}finally{$.rotating=null;let W=Y.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=M.planUpdate($.planUpdateCount++);z$(Z,a6($.planSteps,$.planExplanation,"",J),{type:"insert_before",targetElementId:B$($)})}addGoalUpdateOnCurrentTurn($){let Z=this.currentTurn;if(!Z)return;this.maybeMidTurnRotate();let J=M.goalUpdate(Z.goalUpdateCount++);z$(Z.cardId,r6($,J),{type:"insert_before",targetElementId:B$(Z)})}addGoalClearedOnCurrentTurn(){let $=this.currentTurn;if(!$)return;this.maybeMidTurnRotate();let Z=M.goalUpdate($.goalUpdateCount++);z$($.cardId,{tag:"markdown",element_id:Z,content:`**\uD83C\uDFAF 当前目标**
|
|
188
188
|
|
|
189
|
-
已清除`},{type:"insert_before",targetElementId:B$($)})}handleContextCompacted($){let Z=XH($);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;z(`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<p9){z(`session "${this.sessionName}": late anonymous manual compaction duplicate ignored`);return}let J=this.currentTurn,Q=$.itemId?`item:${$.itemId}`:void 0,Y=Z.find((P)=>P.startsWith("turn:")),H=Q??Y,W=H?this.contextCompactionReceipts.get(H):void 0;if(Q&&!W&&$.phase!=="start"&&Y){let P=this.contextCompactionReceipts.get(Y);if(!P?.hasItemAlias&&P?.completed&&Date.now()-P.completedAt<p9||!P?.hasItemAlias&&P?.completionKey&&J?.contextCompactionCompleting.has(P.completionKey))H=Y,W=P,P.hasItemAlias=!0,this.contextCompactionReceipts.delete(Q),this.contextCompactionReceipts.set(Q,P)}if(!J){if(this.openingTurnOwner?.backendTurnStarted){this.openingTurnOwner.pendingCompactions.push($),z(`session "${this.sessionName}": buffer context compaction ${$.phase??"event"} while turn card opens`);return}if(Z.length>0)this.rememberContextCompactionReceipt(Z,null,$.phase!=="start");z(`session "${this.sessionName}": context compaction ${$.phase??"event"} with no current turn thread=${$.threadId??"-"} turn=${$.turnId??"-"} item=${$.itemId??"-"}`);return}if(H&&W?.completed){z(`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),z(`session "${this.sessionName}": late context compaction ${$.phase??"event"} ignored receipt=${H} (turn owner changed)`);return}if(H&&W?.completionKey&&J.contextCompactionCompleting.has(W.completionKey)){z(`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__")){z(`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<p9){z(`session "${this.sessionName}": identified context compaction duplicate ignored after anonymous completion`);return}if($.phase==="start"){let P=NK($);if(J.contextCompactionPending.has(P)||J.contextCompactionCompleted.has(P)){z(`session "${this.sessionName}": duplicate context compaction start ignored key=${P}`);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++,k=J.cardId,C=M.contextCompact(j),x={i:j,cardId:k,notice:$,created:!1,createFailure:void 0,createPromise:Promise.resolve(!1)};x.createPromise=h4(k,M2(j,$,C),{type:"insert_before",targetElementId:B$(J)}).then((c)=>{if(x.cardId===k)x.created=c.landed,x.createFailure=c.failure;return c.landed}),J.contextCompactionPending.set(P,x),z(`session "${this.sessionName}": context compaction start #${j+1} key=${P}`),X0(J.cardId,`\uD83D\uDEA8 压缩×${J.contextCompactCount}`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionCompleting.size>0){z(`session "${this.sessionName}": anonymous context compaction duplicate ignored while completion writes`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionPending.size===0&&Date.now()-J.lastContextCompactionCompletedAt<p9){z(`session "${this.sessionName}": immediate anonymous context compaction duplicate ignored`);return}let V=$.itemId||$.turnId;if(V&&J.contextCompactionCompleted.has(V)){z(`session "${this.sessionName}": duplicate context compaction completion ignored key=${V}`);return}let A=$.itemId?J.contextCompactionPending.has($.itemId)?$.itemId:null:yK(J),G=A?J.contextCompactionPending.get(A):void 0,_=A??V??"__anonymous__";if(J.contextCompactionCompleting.has(_)){z(`session "${this.sessionName}": context compaction completion already writing key=${_}`);return}if(this.startWorkingFooter(J),J.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();J.openBatchI=null,this.maybeMidTurnRotate();let q=xK(G?.notice,$),B=J.contextCompactionEndOnly.get(_),R=G?.i??B??J.contextCompactCount++;if(!G&&B===void 0)J.contextCompactionEndOnly.set(_,R);J.contextCompactionCompleting.add(_);let L=[...new Set([...XH(G?.notice??{}),...Z])];if(L.length>0)this.rememberContextCompactionReceipt(L,X,!1,_);let F=M.contextCompact(R),U=M2(R,q,F);z(`session "${this.sessionName}": context compaction completion write #${R+1} key=${_}`),(async()=>{let P=!1;if(!G)for(let j=0;j<c2+2;j++){let k=J.cardId;if(P=await j0(k,U,{type:"insert_before",targetElementId:B$(J)}),P)break;let C=J.rotating;if(C){await C;continue}if(J.cardId!==k)continue;break}else for(let j=0;j<c2+2;j++){let k=G.cardId;if(await G.createPromise,G.cardId!==k)continue;if(G.created)P=await F$(k,F,U);else{if(vZ(G.createFailure?.code,G.createFailure))hZ(k,F),P=await F$(k,F,U,{notifyCardFailure:!1});if(!P)P=await j0(k,U,{type:"insert_before",targetElementId:B$(J)})}if(G.cardId!==k)continue;if(P){G.created=!0;break}let C=J.rotating;if(C){await C;continue}if(G.cardId!==k)continue;break}if(J.contextCompactionCompleting.delete(_),!P){z(`session "${this.sessionName}": context compaction completion write MISS #${R+1} key=${_}`);return}if(A&&J.contextCompactionPending.get(A)===G)J.contextCompactionPending.delete(A);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(([,k])=>k.completionKey===_).map(([k])=>k);this.rememberContextCompactionReceipt([...new Set([...L,...j])],null,!0)}z(`session "${this.sessionName}": context compaction completed #${R+1} key=${_}`)})().catch((P)=>{J.contextCompactionCompleting.delete(_),z(`session "${this.sessionName}": context compaction completion transaction failed: ${D(P)}`)}),X0(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,Q){let Y={ownerId:J?null:Z,completed:J,completedAt:J?Date.now():0,...J||!Q?{}:{completionKey:Q},hasItemAlias:$.some((H)=>H.startsWith("item:"))};for(let H of $)this.contextCompactionReceipts.delete(H),this.contextCompactionReceipts.set(H,Y);while(this.contextCompactionReceipts.size>vK){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){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))z(`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?M.taskBoardLive:M.footer;Z.planLiveInserted=!0,z$(Z.cardId,U2(Z.planSteps,Z.planExplanation,M.planLive),{type:"insert_before",targetElementId:J})}else o(Z.cardId,M.planLive,U2(Z.planSteps,Z.planExplanation,M.planLive));this.addPlanSnapshotOnCurrentTurn()}handlePlanDelta($){if(typeof $.delta!=="string"||!$.delta){z(`session "${this.sessionName}": item/plan/delta missing delta text`);return}if(typeof $.itemId!=="string"||!$.itemId)z(`session "${this.sessionName}": item/plan/delta missing itemId`)}handleThreadGoalUpdated($){if(!$||typeof $.objective!=="string"){z(`session "${this.sessionName}": thread/goal/updated missing objective`);return}if($.tokenBudget!=null&&typeof $.tokenBudget!=="number")z(`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&&p4(Z)===p4(J))return;let Q=this.currentTurn;if(Q){if(this.startWorkingFooter(Q),Q.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();Q.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=M.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 Y=this.cleanAssistantTextForDisplay(Z.currentAssistantText).slice(0,40);X0(Z.cardId,Y)}takeOrphanAssistantText(){let $=[...this.orphanAssistantSegments];if(this.orphanAssistantCurrent.trim())$.push(this.orphanAssistantCurrent);return this.orphanAssistantSegments=[],this.orphanAssistantCurrent="",$.join(`
|
|
189
|
+
已清除`},{type:"insert_before",targetElementId:B$($)})}handleContextCompacted($){let Z=zH($);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;z(`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<p9){z(`session "${this.sessionName}": late anonymous manual compaction duplicate ignored`);return}let J=this.currentTurn,Q=$.itemId?`item:${$.itemId}`:void 0,Y=Z.find((P)=>P.startsWith("turn:")),H=Q??Y,W=H?this.contextCompactionReceipts.get(H):void 0;if(Q&&!W&&$.phase!=="start"&&Y){let P=this.contextCompactionReceipts.get(Y);if(!P?.hasItemAlias&&P?.completed&&Date.now()-P.completedAt<p9||!P?.hasItemAlias&&P?.completionKey&&J?.contextCompactionCompleting.has(P.completionKey))H=Y,W=P,P.hasItemAlias=!0,this.contextCompactionReceipts.delete(Q),this.contextCompactionReceipts.set(Q,P)}if(!J){if(this.openingTurnOwner?.backendTurnStarted){this.openingTurnOwner.pendingCompactions.push($),z(`session "${this.sessionName}": buffer context compaction ${$.phase??"event"} while turn card opens`);return}if(Z.length>0)this.rememberContextCompactionReceipt(Z,null,$.phase!=="start");z(`session "${this.sessionName}": context compaction ${$.phase??"event"} with no current turn thread=${$.threadId??"-"} turn=${$.turnId??"-"} item=${$.itemId??"-"}`);return}if(H&&W?.completed){z(`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),z(`session "${this.sessionName}": late context compaction ${$.phase??"event"} ignored receipt=${H} (turn owner changed)`);return}if(H&&W?.completionKey&&J.contextCompactionCompleting.has(W.completionKey)){z(`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__")){z(`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<p9){z(`session "${this.sessionName}": identified context compaction duplicate ignored after anonymous completion`);return}if($.phase==="start"){let P=fK($);if(J.contextCompactionPending.has(P)||J.contextCompactionCompleted.has(P)){z(`session "${this.sessionName}": duplicate context compaction start ignored key=${P}`);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++,S=J.cardId,b=M.contextCompact(j),y={i:j,cardId:S,notice:$,created:!1,createFailure:void 0,createPromise:Promise.resolve(!1)};y.createPromise=h4(S,U2(j,$,b),{type:"insert_before",targetElementId:B$(J)}).then((m)=>{if(y.cardId===S)y.created=m.landed,y.createFailure=m.failure;return m.landed}),J.contextCompactionPending.set(P,y),z(`session "${this.sessionName}": context compaction start #${j+1} key=${P}`),X0(J.cardId,`\uD83D\uDEA8 压缩×${J.contextCompactCount}`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionCompleting.size>0){z(`session "${this.sessionName}": anonymous context compaction duplicate ignored while completion writes`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionPending.size===0&&Date.now()-J.lastContextCompactionCompletedAt<p9){z(`session "${this.sessionName}": immediate anonymous context compaction duplicate ignored`);return}let V=$.itemId||$.turnId;if(V&&J.contextCompactionCompleted.has(V)){z(`session "${this.sessionName}": duplicate context compaction completion ignored key=${V}`);return}let A=$.itemId?J.contextCompactionPending.has($.itemId)?$.itemId:null:wK(J),G=A?J.contextCompactionPending.get(A):void 0,_=A??V??"__anonymous__";if(J.contextCompactionCompleting.has(_)){z(`session "${this.sessionName}": context compaction completion already writing key=${_}`);return}if(this.startWorkingFooter(J),J.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();J.openBatchI=null,this.maybeMidTurnRotate();let q=vK(G?.notice,$),B=J.contextCompactionEndOnly.get(_),R=G?.i??B??J.contextCompactCount++;if(!G&&B===void 0)J.contextCompactionEndOnly.set(_,R);J.contextCompactionCompleting.add(_);let L=[...new Set([...zH(G?.notice??{}),...Z])];if(L.length>0)this.rememberContextCompactionReceipt(L,X,!1,_);let F=M.contextCompact(R),U=U2(R,q,F);z(`session "${this.sessionName}": context compaction completion write #${R+1} key=${_}`),(async()=>{let P=!1;if(!G)for(let j=0;j<m2+2;j++){let S=J.cardId;if(P=await j0(S,U,{type:"insert_before",targetElementId:B$(J)}),P)break;let b=J.rotating;if(b){await b;continue}if(J.cardId!==S)continue;break}else for(let j=0;j<m2+2;j++){let S=G.cardId;if(await G.createPromise,G.cardId!==S)continue;if(G.created)P=await F$(S,F,U);else{if(gZ(G.createFailure?.code,G.createFailure))IZ(S,F),P=await F$(S,F,U,{notifyCardFailure:!1});if(!P)P=await j0(S,U,{type:"insert_before",targetElementId:B$(J)})}if(G.cardId!==S)continue;if(P){G.created=!0;break}let b=J.rotating;if(b){await b;continue}if(G.cardId!==S)continue;break}if(J.contextCompactionCompleting.delete(_),!P){z(`session "${this.sessionName}": context compaction completion write MISS #${R+1} key=${_}`);return}if(A&&J.contextCompactionPending.get(A)===G)J.contextCompactionPending.delete(A);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(([,S])=>S.completionKey===_).map(([S])=>S);this.rememberContextCompactionReceipt([...new Set([...L,...j])],null,!0)}z(`session "${this.sessionName}": context compaction completed #${R+1} key=${_}`)})().catch((P)=>{J.contextCompactionCompleting.delete(_),z(`session "${this.sessionName}": context compaction completion transaction failed: ${D(P)}`)}),X0(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,Q){let Y={ownerId:J?null:Z,completed:J,completedAt:J?Date.now():0,...J||!Q?{}:{completionKey:Q},hasItemAlias:$.some((H)=>H.startsWith("item:"))};for(let H of $)this.contextCompactionReceipts.delete(H),this.contextCompactionReceipts.set(H,Y);while(this.contextCompactionReceipts.size>mK){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){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))z(`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?M.taskBoardLive:M.footer;Z.planLiveInserted=!0,z$(Z.cardId,O2(Z.planSteps,Z.planExplanation,M.planLive),{type:"insert_before",targetElementId:J})}else o(Z.cardId,M.planLive,O2(Z.planSteps,Z.planExplanation,M.planLive));this.addPlanSnapshotOnCurrentTurn()}handlePlanDelta($){if(typeof $.delta!=="string"||!$.delta){z(`session "${this.sessionName}": item/plan/delta missing delta text`);return}if(typeof $.itemId!=="string"||!$.itemId)z(`session "${this.sessionName}": item/plan/delta missing itemId`)}handleThreadGoalUpdated($){if(!$||typeof $.objective!=="string"){z(`session "${this.sessionName}": thread/goal/updated missing objective`);return}if($.tokenBudget!=null&&typeof $.tokenBudget!=="number")z(`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&&p4(Z)===p4(J))return;let Q=this.currentTurn;if(Q){if(this.startWorkingFooter(Q),Q.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();Q.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=M.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 Y=this.cleanAssistantTextForDisplay(Z.currentAssistantText).slice(0,40);X0(Z.cardId,Y)}takeOrphanAssistantText(){let $=[...this.orphanAssistantSegments];if(this.orphanAssistantCurrent.trim())$.push(this.orphanAssistantCurrent);return this.orphanAssistantSegments=[],this.orphanAssistantCurrent="",$.join(`
|
|
190
190
|
|
|
191
|
-
`).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;z(`session "${this.sessionName}": flushing ${J.length} chars of orphan assistant text (${$})`),
|
|
191
|
+
`).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;z(`session "${this.sessionName}": flushing ${J.length} chars of orphan assistant text (${$})`),T(this.chatId,`\uD83D\uDCC4 后台轮输出(未能建卡,纯文本兜底):
|
|
192
192
|
|
|
193
|
-
${J}`)}completedAssistantElement($,Z){if(d7(Z))return this.mathAssistantContainer($,[{type:"markdown",text:Z}]);return{tag:"markdown",element_id:$,content:this.cleanAssistantTextForDisplay(Z).trim()||" "}}mathAssistantContainer($,Z){let J=Z.map((Q)=>Q.type==="markdown"?{tag:"markdown",content:this.cleanAssistantTextForDisplay(Q.text).trim()||" "}:{...Q.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,Q){let Y=await
|
|
193
|
+
${J}`)}completedAssistantElement($,Z){if(d7(Z))return this.mathAssistantContainer($,[{type:"markdown",text:Z}]);return{tag:"markdown",element_id:$,content:this.cleanAssistantTextForDisplay(Z).trim()||" "}}mathAssistantContainer($,Z){let J=Z.map((Q)=>Q.type==="markdown"?{tag:"markdown",content:this.cleanAssistantTextForDisplay(Q.text).trim()||" "}:{...Q.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,Q){let Y=await MQ(Q);if(!await F$(Z,J,this.mathAssistantContainer(J,Y.blocks),{notifyCardFailure:!1})){z(`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),z(`session "${this.sessionName}": math rendered ${J} (${Y.renderedImageCount} img, ${Y.blocks.length} blocks)`)}addCompletedAssistantSegment($,Z,J){let Q=$.cardId,Y=B$($),H=(async()=>{if(!await j0(Q,this.completedAssistantElement(Z,J),{type:"insert_before",targetElementId:Y}))return z(`session "${this.sessionName}": assistant segment ${Z} raw write failed on card=${Q}`),!1;if(d7(J)){let X=this.replaceSegmentWithMathImgs($,Q,Z,J).catch((V)=>z(`session "${this.sessionName}": math render ${Z} failed: ${V}`));$.mathRenderInflight??=new Map,$.mathRenderInflight.get(Q)??$.mathRenderInflight.set(Q,new Set),$.mathRenderInflight.get(Q).add(X),X.finally(()=>$.mathRenderInflight?.get(Q)?.delete(X))}return!0})();return $.assistantWriteInflight??=new Map,$.assistantWriteInflight.get(Q)??$.assistantWriteInflight.set(Q,new Set),$.assistantWriteInflight.get(Q).add(H),H.finally(()=>$.assistantWriteInflight?.get(Q)?.delete(H)),H}async sendAssistantTextFallback($,Z){let J=$.trim();if(!J)return;let Q=`⚠️ 对话卡片正文写入失败(${Z}),以下为 agent 原始回复:
|
|
194
194
|
|
|
195
|
-
${J}`;if(!await
|
|
196
|
-
${L}`:R,U=await F$(H,M.footer,this.footerElement(F));V$(H);let P=await q$(H,A0({durationSec:Y,outputTokens:J.hasFreshResult?$.lastTurnUsage?.output_tokens:void 0,suffix:Z}));if(U&&P)await x$(H);else{let j=`footer=${U?"ok":"MISS"}, settings=${P?"ok":"MISS"}`;z(`session "${this.sessionName}": terminal card transaction incomplete card=${H.slice(0,12)} ${j}`),await
|
|
195
|
+
${J}`;if(!await T(this.chatId,Q))z(`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($.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 YQ($))this.sendOutboundPath(Z,"send marker")}cleanAssistantTextForDisplay($){return $$($)}sendOutboundPath($,Z){let J=E9($.trim());if(!J)return;let Q=this.currentTurn;if(Q?.outboundSeenPaths.has(J))return;if(Q?.outboundSeenPaths.add(J),!CK(J)){z(`session "${this.sessionName}": ignore non-absolute outbound path from ${Z}: ${J}`);return}Q?.outboundSentPaths.add(J),z(`session "${this.sessionName}": outbound send from ${Z}: ${J}`),m6(this.chatId,J)}startFooterStatus($,Z){if($.rotateGivenUp)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 Q=()=>{if($.footerStatusLabel!==Z)return;let{label:H}=R0(Date.now()-$.footerStatusStartedAt,H1());this.replaceFooterContent($.cardId,this.withModel(`${Z} (${H})`))},Y=()=>{if($.footerStatusLabel!==Z)return;let{nextDelayMs:H}=R0(Date.now()-$.footerStatusStartedAt,H1());$.footerStatusHandle=setTimeout(()=>{Q(),Y()},Math.max(1,Math.ceil(H)))};Q(),Y()}startThinkingFooter($){this.startFooterStatus($,hK)}startWritingFooter($){this.startFooterStatus($,gK)}startWorkingFooter($){this.startFooterStatus($,IK)}stopFooterStatus($){if(!$)return;if($.footerStatusHandle)clearTimeout($.footerStatusHandle);$.footerStatusHandle=null,$.footerStatusStartedAt=0,$.footerStatusLabel=null}async footerUsageSuffix($,Z,J,Q,Y){if(J&&(!Q||!Q.enabled||Q.agent!==$))return"";if(Q?.agent===$&&Q.enabled&&$==="claude"){let W=await Q.readUsage(),X=W.windows.find((A)=>A.kind==="fiveHour"),V=W.windows.find((A)=>A.kind==="weekly");if(X||V)return this.fmtDualWindowSuffix(X??null,V??null);return W.state==="ok"&&W.planLabel?` | ${W.planLabel}`:""}if($==="codex"){let W=Z?.isAlive()&&Z.provider==="codex"&&Z.readRateLimits?Z:null,V=(W?await eJ(()=>W.readRateLimits()):null)??Y;return V?.state==="ok"?this.fmtDualWindowSuffix(V.fiveHour??null,V.weekly??null):""}let H=await c7();return H.state==="ok"?this.fmtDualWindowSuffix(H.fiveHour??null,H.weekly??null):""}fmtDualWindowSuffix($,Z){let J=(W)=>W.resetsAt&&W.resetsAt.getTime()>Date.now()?z0(W.resetsAt):"",Q=(W)=>{if(W?.percent==null)return null;let X=J(W);return X?`${X}·${Math.round(W.percent)}%`:`${Math.round(W.percent)}%`},Y=Q($),H=Q(Z);if(Y&&H)return` | ${Y}·[${H}]`;if(Y)return` | ${Y}`;if(H)return` | [${H}]`;return""}waitForTurnCloses(){let $=[...this.turnCloseInflight];if($.length===0)return Promise.resolve();return Promise.allSettled($).then((Z)=>{let J=Z.filter((Q)=>Q.status==="rejected").map((Q)=>Q.reason);if(J.length===1)throw J[0];if(J.length>1)throw AggregateError(J,`turn close failed: ${J.map(D).join("; ")}`)})}releaseTurnCloseReactions($){for(let[Z,J]of[...$.currentBatchReactionIds.entries(),...$.pendingReactionIds.entries()])if(J)j$(Z,J)}closeTurnCard($,Z={}){let J=this.currentTurn;if(!J)return this.waitForTurnCloses();this.currentTurn=null,this.stopFooterStatus(J);let Q=this.proc,Y={turn:J,proc:Q,procEpoch:this.procEpoch,contextTokens:this.currentContextTokens(Q),contextLimit:this.contextLimitForDisplay(Q),lastTurnDelta:this.lastTurnDelta?{...this.lastTurnDelta}:null,lastTurnUsage:this.lastTurnUsage?{...this.lastTurnUsage}:null,tokenSourceId:this.selectedTokenSourceId,tokenSource:this.currentTokenSource(),codexUsage:sJ(),currentBatchReactionIds:this.currentBatchReactionIds,pendingReactionIds:this.pendingReactionIds};this.currentBatchReactionIds=new Map,this.pendingReactionIds=new Map;let H=this.finishTurnCardClose(Y,$,Z).finally(()=>this.releaseTurnCloseReactions(Y));return this.turnCloseInflight.add(H),H.then(()=>{this.turnCloseInflight.delete(H)},()=>{this.turnCloseInflight.delete(H)}),H}async finishTurnCardClose($,Z,J={}){let{turn:Q}=$;if(Q.rotating)await Q.rotating;this.stopFooterStatus(Q);let Y=((Date.now()-Q.startedAt)/1000).toFixed(1),H=Q.cardId,W=Q.segmentTexts;await u$(H);let X=new Map;if(Q.currentAssistantSegmentId&&Q.currentAssistantText.trim()){let{currentAssistantSegmentId:j,currentAssistantText:S}=Q;if(!await this.addCompletedAssistantSegment(Q,j,S))X.set(j,S);Q.currentAssistantSegmentId=null,Q.currentAssistantText=""}let V=Q.assistantWriteInflight?.get(H);if(V?.size)await Promise.allSettled([...V]);let A=Q.mathRenderInflight?.get(H);if(A?.size)await Promise.allSettled([...A]);let G=Q.mathRendered?.get(H);for(let[j,S]of W){if(y1(H,j)){X.set(j,S);continue}if(G?.has(j))continue;await o(H,j,this.completedAssistantElement(j,S))}if(Q.rotateGivenUp)for(let[j,S]of W)X.set(j,S);let _=Z?Z:"✅",q=[`${_} ⏱ ${Y}s`];if(J.hasFreshResult){let{contextTokens:j,contextLimit:S}=$,b=Q.provider==="claude",y=d6(j,S,b?0:void 0);if(y)q.push(`\uD83E\uDDE0 ${y}`);let m=$.lastTurnDelta?.costUsd??0;if(m>0)q.push(`\uD83D\uDCB0 $${m.toFixed(3)}`)}if(Q.contextCompactCount>0)q.push(`\uD83D\uDEA8 压缩×${Q.contextCompactCount}`);if(Q.outboundSentPaths.size>0)q.push(`\uD83D\uDCCE ${Q.outboundSentPaths.size}`);let B=this.modelLine(Q);if(B)q.push(B);let R=q.join(" | "),L=J.hasFreshResult?o6($.lastTurnUsage)+(Q.rotateGivenUp?"":await this.footerUsageSuffix(Q.provider,$.proc,$.tokenSourceId,$.tokenSource,$.codexUsage)):"",F=L?`${R}
|
|
196
|
+
${L}`:R,U=await F$(H,M.footer,this.footerElement(F));V$(H);let P=await q$(H,A0({durationSec:Y,outputTokens:J.hasFreshResult?$.lastTurnUsage?.output_tokens:void 0,suffix:Z}));if(U&&P)await x$(H);else{let j=`footer=${U?"ok":"MISS"}, settings=${P?"ok":"MISS"}`;z(`session "${this.sessionName}": terminal card transaction incomplete card=${H.slice(0,12)} ${j}`),await x(this.chatId,`⚠️ 对话卡片终态写入失败 (${j})。本轮已结束: ${_}`)}for(let j of X.values())await this.sendAssistantTextFallback(j,"CardKit 元素未落地");if((J.forcePush||!Z)&&Q.userOpenId&&Q.messageId&&!Q.rotateGivenUp)l0(Q.messageId,[Q.userOpenId])}}});function f$($){return{card:{type:"raw",data:$}}}import{readFileSync as uK}from"node:fs";function RH($){return j5.has($)}function PH($){j5.add($)}function LH($){j5.delete($)}function u2(){try{let $={};for(let[Z,J]of s$)$[Z]=J;X$(l9,$)}catch($){throw z(`notify-callbacks: save failed (${l9}): ${$}`),$}}function DH(){let $;try{$=uK(l9,"utf8")}catch{return}try{let Z=JSON.parse($),J=Date.now()-BH,Q=0;for(let Y of Object.values(Z)){if(!Y||typeof Y!=="object")continue;if(typeof Y.notifyId!=="string"||typeof Y.callbackUrl!=="string")continue;if(typeof Y.createdAt!=="number"||Y.createdAt<J){Q++;continue}s$.set(Y.notifyId,Y)}if(z(`notify-callbacks: loaded ${s$.size} registration(s)${Q?`, dropped ${Q} stale`:""}`),Q>0)u2()}catch(Z){z(`notify-callbacks: load failed (${l9}): ${Z}`)}}function jH($){let Z=Date.now();if(Z-qH>=pK)iK(Z),qH=Z;s$.set($.notifyId,$),u2()}function i9($){return s$.get($)}function F5($,Z,J){let Q=s$.get($);if(!Q)throw Error(`notify registration not found: ${$}`);let Y={resolvedAt:Q.resolvedAt,resolvedBy:Q.resolvedBy,unknownAt:Q.unknownAt,unknownBy:Q.unknownBy,unknownReason:Q.unknownReason};Q.resolvedAt=Date.now(),Q.resolvedBy={buttonId:Z,openId:J},delete Q.unknownAt,delete Q.unknownBy,delete Q.unknownReason;try{u2()}catch(H){if(Y.resolvedAt===void 0)delete Q.resolvedAt;else Q.resolvedAt=Y.resolvedAt;if(Y.resolvedBy===void 0)delete Q.resolvedBy;else Q.resolvedBy=Y.resolvedBy;if(Y.unknownAt===void 0)delete Q.unknownAt;else Q.unknownAt=Y.unknownAt;if(Y.unknownBy===void 0)delete Q.unknownBy;else Q.unknownBy=Y.unknownBy;if(Y.unknownReason===void 0)delete Q.unknownReason;else Q.unknownReason=Y.unknownReason;throw H}}function lK($,Z,J,Q){let Y=s$.get($);if(!Y)throw Error(`notify registration not found: ${$}`);delete Y.resolvedAt,delete Y.resolvedBy,Y.unknownAt=Date.now(),Y.unknownBy={buttonId:Z,openId:J},Y.unknownReason=Q,u2()}function FH($,Z,J){try{return F5($,Z,J),{state:"complete"}}catch(Q){let H=`resolved tombstone persistence failed: ${Q instanceof Error?Q.message:String(Q)}`;try{lK($,Z,J,H)}catch(W){let X=W instanceof Error?W.message:String(W);H+=`; unknown tombstone persistence also failed: ${X}`;let V=s$.get($);if(V)V.unknownReason=H}return{state:"unknown",detail:H}}}function iK($=Date.now()){let Z=$-BH,J=0;for(let[Q,Y]of s$)if(typeof Y.createdAt!=="number"||Y.createdAt<Z)s$.delete(Q),J++;if(J>0)u2();return J}async function MH($,Z,J){let Q={notify_id:$.notifyId,message_id:$.messageId,chat_id:$.chatId,project:$.project,button:{id:Z.id,text:Z.text,type:Z.type},operator:{open_id:J},timestamp:Math.floor(Date.now()/1000)},Y=new AbortController,H=setTimeout(()=>Y.abort(),KH);try{let W=await fetch($.callbackUrl,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(Q),signal:Y.signal});if(W.status>=200&&W.status<300){let V;try{let A=(await W.text()).trim();if(A.startsWith("{")){let G=JSON.parse(A),_=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(A)V=A.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 UH($){let Z=!!$.resolvedAt,J=!!$.unknownAt,Q=$.resolvedBy?.buttonId??$.unknownBy?.buttonId,Y=Q?$.buttons.find((H)=>H.id===Q):void 0;return{notify_id:$.notifyId,project:$.project,message_id:$.messageId,resolved:Z,unknown:J,...Z?{button:Y?{id:Y.id,text:Y.text,type:Y.type}:{id:Q},resolved_at:$.resolvedAt,resolved_by:$.resolvedBy?.openId??null}:{},...J?{button:Y?{id:Y.id,text:Y.text,type:Y.type}:{id:Q},unknown_at:$.unknownAt,unknown_by:$.unknownBy?.openId??null,unknown_reason:$.unknownReason}:{}}}var BH=604800000,KH=2500,s$,qH,pK=86400000,j5,l9;var M5=N(()=>{h();L$();h$();s$=new Map,qH=Date.now(),j5=new Set;l9=n5});import{createServer as nK}from"node:http";import{randomUUID as dK}from"node:crypto";function TH($){let Z=$.level==="error"?"red":$.level==="warn"?"yellow":"blue",J=$.level==="error"?"❌":$.level==="warn"?"⚠️":"\uD83D\uDD14",Q=!!($.buttons?.length&&$.notifyId),Y=new Date,H=`${String(Y.getHours()).padStart(2,"0")}:${String(Y.getMinutes()).padStart(2,"0")}`,W=[];for(let X of $.images??[])if(X.key)W.push({tag:"img",img_key:X.key,alt:{tag:"plain_text",content:"screenshot"}});else W.push({tag:"markdown",content:`<font color='red'>\uD83D\uDCF7 图片上传失败: ${X.src}</font>`});if(W.push({tag:"markdown",content:v8($.text??"")||"_(空消息)_"}),$.resolution){let X=$.resolution,V;if(X.status==="processing")V=`<font color='blue'>⏳ 已选择:${X.text} · 推送中…</font>`;else if(X.status==="failed")V=`<font color='red'>⚠️ 已选:${X.text} · 回调失败:${X.detail??"未知"} · ${H}</font>`;else if(X.status==="delivered")V=`<font color='green'>✅ 已选择:${X.text} · 反馈已送达 · ${H}</font>`;else if(X.status==="unknown")V=`<font color='red'>⚠️ 已选择:${X.text} · 外部回调已成功,但本地确认状态未知,禁止自动重试 · ${H}</font>`;else V=`<font color='green'>✅ 已选择:${X.text} · ${H}</font>`;if(W.push({tag:"markdown",content:V}),X.status==="delivered"&&X.reply)W.push({tag:"markdown",content:$$(X.reply)})}if(Q&&(!$.resolution||$.resolution.status==="failed"))W.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:1,elements:$.buttons.map((X)=>({tag:"button",text:{tag:"plain_text",content:X.text},type:X.type,behaviors:[{type:"callback",value:{kind:"notify_callback",notify_id:$.notifyId,button_id:X.id}}]}))}]});return W.push({tag:"hr"}),W.push({tag:"markdown",content:`<font color='grey'>via notify · ${H}</font>`}),{schema:"2.0",config:Q?{update_multi:!0}:{},header:{title:{tag:"plain_text",content:`${J} ${$.title}`},template:Z},body:{elements:W}}}function tK($){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 Q of $){if(!Q||typeof Q!=="object")return{error:"each button must be an object"};let Y=String(Q.id??"").trim(),H=String(Q.text??"").trim();if(!rK.test(Y))return{error:`button id "${Y.slice(0,32)}" invalid (need ^[A-Za-z0-9_-]{1,64}$)`};if(!H)return{error:`button "${Y}" missing text`};if(H.length>OH)return{error:`button "${Y}" text > ${OH} chars`};if(Z.has(Y))return{error:`button id "${Y}" duplicated`};Z.add(Y);let W=String(Q.type??"default").toLowerCase(),X=aK.has(W)?W:"default";J.push({id:Y,text:H,type:X})}return{buttons:J}}function sK($){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 Q=J.hostname.replace(/^\[|]$/g,"");if(Q!=="127.0.0.1"&&Q!=="localhost"&&Q!=="::1")return{error:`"callback" must be loopback (本机内), got "${J.hostname}"`};return{url:Z}}function kH($){try{let Z=nK((J,Q)=>{let Y=new URL(J.url??"/",`http://${J.headers.host??"localhost"}`);($.extraHandler?$.extraHandler(J,Q,Y).then((W)=>W?void 0:EH(J,Q)):EH(J,Q)).catch((W)=>{if(z(`notify: handler crash: ${W?.message??W}`),!Q.headersSent)Q.statusCode=500,Q.setHeader("content-type","text/plain; charset=utf-8"),Q.end("internal error");else try{Q.end()}catch{}})});Z.on("error",(J)=>{z(`notify: server bind failed (${$.bind}:${$.port}): ${J.message}`)}),Z.listen($.port,$.bind,()=>{z(`notify: HTTP listening at http://${$.bind}:${$.port}/notify`)})}catch(Z){z(`notify: server bind failed (${$.bind}:${$.port}): ${Z}`)}}async function EH($,Z){let J=new URL($.url??"/",`http://${$.headers.host??"localhost"}`),Q=(E,k)=>{Z.statusCode=E,Z.setHeader("content-type","text/plain; charset=utf-8"),Z.end(k)},Y=(E,k)=>{Z.statusCode=E,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify(k))};if($.method==="GET"&&J.pathname==="/")return Q(200,`lodestar notify
|
|
197
197
|
`+`POST /notify body={project,text,title?,level?,images?,buttons?,callback?} → push card to group
|
|
198
198
|
`+`GET /notify/result/<notify_id> → poll a button card's resolution (pull mode, no callback server)
|
|
199
199
|
`+`GET /agents/identities; POST/GET/DELETE /agents/runs[/<id>] → capability-protected delegated Agents
|
|
200
200
|
`+`levels: info|warn|error (default info); images=[/abs/*.png] uploaded + embedded
|
|
201
201
|
`+`buttons:[{id,text,type?}] (any count, one per row); callback=http://127.0.0.1:PORT/path optional (push) — omit to poll
|
|
202
|
-
`);if($.method==="GET"&&J.pathname.startsWith("/notify/result/")){let
|
|
203
|
-
`;for(let[H,W]of[[J,Y],[Q,$.body]])try{let X=O5(H)?E5(H,"utf8"):null;if(X===W)continue;v$(H,W),z(`skill: ${X===null?"installed":"updated"} ${H}`)}catch(X){z(`skill: Claude plugin sync failed (${H}): ${X}`)}}function
|
|
204
|
-
name: ${
|
|
202
|
+
`);if($.method==="GET"&&J.pathname.startsWith("/notify/result/")){let E=decodeURIComponent(J.pathname.slice(15)).trim();if(!E)return Q(400,"missing notify_id in path");let k=i9(E);if(!k)return Y(404,{error:"unknown notify_id",notify_id:E});return Y(200,UH(k))}if($.method!=="POST"||J.pathname!=="/notify")return Q(405,"use POST /notify");let H="";for await(let E of $)H+=E.toString();let W={};try{W=JSON.parse(H)}catch{return Q(400,"bad json")}let X=String(W.project??"").trim(),V=String(W.text??""),A=String(W.title??"").trim(),G=String(W.level??"info").toLowerCase();if(!X)return Q(400,'missing "project"');if(!V)return Q(400,'missing "text"');let{buttons:_,error:q}=tK(W.buttons);if(q)return Q(400,q);let{url:B,error:R}=sK(W.callback);if(R)return Q(400,R);let L=!!(_&&_.length),F=B??"",U=oK.has(G)?G:"info",P=A||X,j=F2(X),S=N1(j);if(!S)return z(`notify: project "${X}" (sanitized "${j}") has no chat binding → 404`),Q(404,`project "${X}" not bound — send any message in that Feishu group at least once after the daemon started, then retry`);let b=Array.isArray(W.images)?W.images:[],y=[];for(let E of b){let k=String(E??"").trim();if(!k)continue;let u=await c6(k);y.push({key:u??"",src:k})}let m=L?`nf_${dK()}`:"",v=TH({title:P,text:V,level:U,images:y,buttons:_,notifyId:m}),g=await n(S,v);if(!g)return z(`notify: sendCard failed → 502 (project="${X}" chat=${S.slice(0,8)}…)`),Q(502,"feishu sendCard failed (see daemon log)");if(L&&m){let E={notifyId:m,callbackUrl:F,chatId:S,messageId:g,project:X,title:P,text:V,level:U,imageKeys:y,buttons:_,createdAt:Date.now()};jH(E)}z(`notify: → ${X} (${S.slice(0,8)}…) level=${U} bytes=${V.length} images=${y.length} buttons=${_?.length??0} push=${L&&!!F?1:0} msg=${g}`),Y(200,{ok:!0,chat_id:S,message_id:g,...m?{notify_id:m}:{}})}function n9($,Z){return TH({title:$.title,text:$.text,level:$.level,images:$.imageKeys,buttons:$.buttons,notifyId:$.notifyId,resolution:Z})}var oK,aK,rK,OH=64;var U5=N(()=>{h();t();N$();M5();oK=new Set(["info","warn","error"]),aK=new Set(["default","primary","danger"]),rK=/^[A-Za-z0-9_-]{1,64}$/});import{existsSync as O5,readFileSync as E5,rmSync as eK}from"node:fs";import{homedir as d9}from"node:os";import{join as e$}from"node:path";function o9($,Z){if(process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"){z(`skill: sync disabled, skip ${$.name}`);return}let J=Z??[e$(d9(),".codex","skills"),e$(d9(),".claude","skills")];for(let Q of J){let Y=e$(Q,$.name,"SKILL.md");try{let H=O5(Y)?E5(Y,"utf8"):null;if(H===$.body)continue;v$(Y,$.body),z(`skill: ${H===null?"installed":"updated"} ${Y}`)}catch(H){z(`skill: sync failed (${Y}): ${H}`)}}if(!Z)$q($,x0)}function $q($,Z){if(process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"){z(`skill: sync disabled, skip Claude plugin ${$.name}`);return}let J=e$(Z,".claude-plugin","plugin.json"),Q=e$(Z,"skills",$.name,"SKILL.md"),Y=JSON.stringify({name:"lodestar-managed",description:"Lodestar daemon-managed Skills for Claude Agent SDK sessions",version:"1.0.0",author:{name:"Lodestar"}},null,2)+`
|
|
203
|
+
`;for(let[H,W]of[[J,Y],[Q,$.body]])try{let X=O5(H)?E5(H,"utf8"):null;if(X===W)continue;v$(H,W),z(`skill: ${X===null?"installed":"updated"} ${H}`)}catch(X){z(`skill: Claude plugin sync failed (${H}): ${X}`)}}function SH($,Z){if(process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"){z(`skill: sync disabled, skip removal ${$}`);return}let Q=(Z??[e$(d9(),".codex","skills"),e$(d9(),".claude","skills")]).map((Y)=>e$(Y,$));if(!Z)Q.push(e$(x0,"skills",$));for(let Y of Q){let H=e$(Y,"SKILL.md");if(!O5(H))continue;try{let W=E5(H,"utf8");if(!(W.includes(`name: ${$}`)||W.includes(`name: "${$}"`))){z(`skill: obsolete path preserved because ownership is unclear ${H}`);continue}eK(Y,{recursive:!0,force:!1}),z(`skill: removed obsolete ${Y}`)}catch(W){z(`skill: obsolete removal failed (${Y}): ${W}`)}}}var T5=N(()=>{h();h$();L$()});function Zq($){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`---
|
|
204
|
+
name: ${NH}
|
|
205
205
|
description: ${JSON.stringify(Z)}
|
|
206
206
|
---
|
|
207
207
|
|
|
@@ -369,12 +369,12 @@ Notes:
|
|
|
369
369
|
Hand-edits will be overwritten — set
|
|
370
370
|
\`LODESTAR_DISABLE_SKILL_SYNC=1\` and restart the daemon if you want
|
|
371
371
|
to maintain the file yourself.
|
|
372
|
-
`}function
|
|
372
|
+
`}function yH(){o9({name:NH,body:Zq(w.notify.port)})}var NH="feishu-notify";var xH=N(()=>{U$();T5()});function fH($){let Z=Z$($.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:Q}=O4({provider:$.identity.provider,workDir:$.workDir,tokenSourceId:$.identity.tokenSourceId,model:$.identity.model,effort:$.effort,launch:J,developerInstructions:$.developerInstructions,profile:$.profile,managedSkillPluginPath:$.managedSkillPluginPath,hostEnv:$.hostEnv,serviceName:"lodestar-agent"});return Jq(Q,$.prompt,$.callbacks)}function Jq($,Z,J={},Q=E3){let Y="",H=!1,W=null,X=!1,V=null,A=null,G,_,q=Date.now(),B=new Promise((O,f)=>{G=O,_=f}),R=()=>{if(A)clearTimeout(A);A=null},L=()=>{R(),A=setTimeout(()=>{P(Error(`delegated agent timed out after ${bH/1000}s`))},bH)},F=(O)=>{if(!O)return null;try{return Q($.provider,O),J.onSession?.(O),null}catch(f){return f instanceof Error?f:Error(String(f))}},U=()=>{$.off("assistant_text",j),$.off("tool_use",b),$.off("tool_result",y),$.off("subagent_step",m),$.off("can_use_tool",v),$.off("hook_callback",g),$.off("init",E),$.off("error",k),$.off("turn_retry",u),$.off("result",p),$.off("exit",a)},P=async(O,f)=>{if(X)return;X=!0,R(),U();let I=F($.sessionId),M$=null;try{await $.kill(3000)}catch(Y8){M$=Y8 instanceof Error?Y8:Error(String(Y8))}let Q8=O??I??M$;if(Q8){_(Q8);return}let a1=$.sessionId;if(!a1){_(Error("delegated agent completed without a native session id"));return}let A1=Y.trim(),u5=Hq(f?.checkpoint,$);G({output:H?`${A1}
|
|
373
373
|
|
|
374
|
-
[delegated agent output truncated at ${xH} chars]`:a1,outputTruncated:H,sessionId:Q8,...A1?{checkpointId:A1}:{},durationMs:Date.now()-q,usage:$.lastUsage?{...$.lastUsage}:null})},j=(S)=>{if(S?.parentToolUseId||typeof S?.text!=="string"||H)return;let y=xH-Y.length;if(S.text.length>y){Y+=S.text.slice(0,Math.max(0,y)),H=!0;return}Y+=S.text},k=(S)=>{try{J.onProgress?.(S)}catch(y){P(y instanceof Error?y:Error(String(y)))}},C=(S)=>k({at:new Date().toISOString(),phase:"started",tool:String(S?.name??"tool"),detail:""}),x=(S)=>k({at:new Date().toISOString(),phase:"completed",tool:S?.is_error?"tool error":"tool result",detail:""}),c=(S)=>k({at:new Date().toISOString(),phase:S?.phase??"info",tool:String(S?.tool??"subagent"),detail:""}),v=(S)=>{if(S.tool_name!=="AskUserQuestion"){try{$.sendPermissionResponse(S.request_id,"allow",{updatedInput:S.input??{}})}catch(n){P(n instanceof Error?n:Error(String(n)))}return}if(V){P(Error("delegated agent emitted multiple simultaneous input requests"));return}let y;try{y=sK(S)}catch(n){P(n instanceof Error?n:Error(String(n)));return}V={request:y,originalInput:S.input??{}},R();try{J.onNeedsInput?.(y)}catch(n){P(n instanceof Error?n:Error(String(n)))}},g=(S)=>{try{$.sendHookResponse(String(S.request_id),{})}catch(y){P(y instanceof Error?y:Error(String(y)))}},O=(S)=>{let y=F(S?.session_id??$.sessionId);if(y)P(y)},T=(S)=>{W=S instanceof Error?S:Error(String(S))},m=(S)=>{let y=S?.is_error?Error(String(S.error??S.subtype??$.lastResult.subtype??"delegated agent failed")):void 0;P(y,S)},u=(S)=>{if(X)return;let y=`code=${S?.code??"null"} signal=${S?.signal??"null"}`;P(W??Error(`delegated agent exited before result (${y})`))};$.on("assistant_text",j),$.on("tool_use",C),$.on("tool_result",x),$.on("subagent_step",c),$.on("can_use_tool",v),$.on("hook_callback",g),$.on("init",O),$.on("error",T),$.on("result",m),$.on("exit",u),L();try{$.sendInitialize(),$.sendUserText(Z)}catch(S){P(S instanceof Error?S:Error(String(S)))}return{done:B,pendingInput:()=>V?.request??null,answer(S,y){if(!V)throw Error("delegated agent is not waiting for input");if(V.request.requestId!==S)throw Error(`delegated agent input request mismatch: expected ${V.request.requestId}`);let n=V;$.sendPermissionResponse(S,"allow",{updatedInput:{...n.originalInput,answers:y}}),V=null,L()},async cancel(S="delegated agent cancelled"){await P(Error(S)),await B.catch(()=>{})}}}function sK($){let Z=$.input??{},Q=(Array.isArray(Z.questions)?Z.questions:[Z]).map((Y,H)=>eK(Y,H));if(Q.length===0)throw Error("delegated agent input request contains no questions");return{requestId:String($.request_id),...$.tool_use_id?{toolUseId:$.tool_use_id}:{},questions:Q}}function eK($,Z){let J=$&&typeof $==="object"?$:{question:$},Q=String(J.question??J.prompt??J.title??"").trim();if(!Q)throw Error(`delegated agent input question ${Z+1} is empty`);let Y=String(J.id??Q),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:Y,...J.header?{header:String(J.header)}:{},question:Q,options:H}}function $q($,Z){if(typeof $?.id==="string"&&$.id)return $.id;if(Z.provider==="codex"&&typeof Z.lastCompletedTurnId==="string"&&Z.lastCompletedTurnId)return Z.lastCompletedTurnId;if(Z.provider==="claude"&&Z.lastAssistantUuid)return Z.lastAssistantUuid;return}var yH=1800000,xH=2000000;var CH=N(()=>{A6();X4();_$()});import{createHash as Zq,randomBytes as Jq,randomUUID as Qq}from"node:crypto";import{existsSync as Yq,readdirSync as Hq,readFileSync as lH}from"node:fs";import{join as r9}from"node:path";class k5{deps;runs=new Map;capabilities=new Map;activeTurns=0;slotWaiters=[];cancellationEpochBySession=new Map;startingWorkers=0;startingRunsBySession=new Map;startingRunsBySubtree=new Map;constructor($=Wq){this.deps=$;this.loadDurableRuns()}rootPrincipal($){return{kind:"session",session:$,depth:-1}}principalForCapability($){return this.capabilities.get($)??null}async startRun($,Z){let J=$.kind==="session"?0:$.depth+1;if(J>wH)throw Error(`delegation depth ${J} exceeds ${wH}`);let Q=this.reserveCapacity($,Z.identityIds.length);try{return await this.createRun($.session,Z,{depth:J,cancellationEpoch:this.currentCancellationEpoch($.session),...$.kind==="worker"?{parentRunId:$.runId,parentKind:"delegate"}:{}})}finally{Q()}}async followUp($,Z,J){let Q=this.requireMutableDescendant($,Z);if(!K0(Q.snapshot.status))throw Error("agent follow-up requires a terminal source run");let Y=mH(Q.snapshot,J.identityId);if(!Y.sessionId)throw Error(`${Y.identityName} has no resumable native session id`);let H=J.effort??Y.effort,W=this.reserveCapacity($,1);try{return await this.createRun($.session,{identityIds:[Y.identityId],prompt:J.prompt,effort:H},{parentRunId:Q.snapshot.runId,parentKind:"follow_up",depth:Q.snapshot.depth,cancellationEpoch:this.currentCancellationEpoch($.session),resumeByIdentity:new Map([[Y.identityId,Y.sessionId]])})}finally{W()}}async answer($,Z,J){let Q=this.requireMutableDescendant($,Z),Y=mH(Q.snapshot,J.identityId);if(Y.status!=="needs_input"||!Y.pendingInput)throw Error(`${Y.identityName} is not waiting for input`);if(Y.pendingInput.requestId!==J.requestId)throw Error(`input request mismatch: expected ${Y.pendingInput.requestId}`);let H=Q.handles.get(Y.identityId);if(!H)throw Error("waiting agent process is no longer alive; start a follow-up run");return H.answer(J.requestId,J.answers),Y.status="running",delete Y.pendingInput,delete Y.queuedReason,this.refreshNonterminalStatus(Q),this.persist(Q),await this.updateWorkerCard(Q,Y),u2(Q.snapshot)}getRun($,Z){return u2(this.requireAccessibleRun($,Z).snapshot)}async cancelRun($,Z,J="agent run cancelled"){let Q=this.requireMutableDescendant($,Z);if(!this.treeHasActiveRun(Q))return!1;return await this.cancelTree(Q,J),!0}async cancelSessionRuns($,Z,J){this.bumpCancellationEpoch($,Z);let Q=[...this.runs.values()].filter((Y)=>Y.snapshot.sessionName===$&&Y.snapshot.chatId===Z&&!Y.snapshot.parentRunId&&this.treeHasActiveRun(Y));await Promise.allSettled(Q.map((Y)=>this.cancelTree(Y,J)))}async shutdown($){let Z=new Set([...this.runs.values()].map((Y)=>`${Y.snapshot.sessionName}\x00${Y.snapshot.chatId}`));for(let Y of Z){let[H,W]=Y.split("\x00");this.bumpCancellationEpoch(H,W)}let J=[...this.runs.values()].filter((Y)=>!Y.snapshot.parentRunId&&this.treeHasActiveRun(Y));await Promise.allSettled(J.map((Y)=>this.cancelTree(Y,$)));let Q=[...this.runs.values()].flatMap((Y)=>[...Y.handles.values()]);await Promise.allSettled(Q.map((Y)=>Y.cancel($)))}async createRun($,Z,J){this.pruneRuns();let Q;if(J.parentRunId){if(Q=this.runs.get(J.parentRunId),!Q)throw Error(`parent agent run not found: ${J.parentRunId}`);if(this.assertSameSession(Q,$),J.parentKind==="delegate"&&(Q.cancelled||Q.finalizing||K0(Q.snapshot.status)))throw Error(`parent agent run is no longer accepting children: ${J.parentRunId}`)}let Y=this.deps.getCatalog(),H=Z.identityIds.map((B)=>{let R=Y.identities.find((L)=>L.id===B);if(!R)throw Error(`agent identity not found: ${B}`);if(R.status!=="ready")throw Error(`${R.displayName}: ${R.reason??R.status}`);return R}),W=H.map((B)=>Xq(B,Vq(B,Z.effort),J.resumeByIdentity?.get(B.id))),X=`agent_${Qq()}`,V={runId:X,sessionName:$.sessionName,chatId:$.chatId,workDir:$.workDir,prompt:Z.prompt,...J.parentRunId?{parentRunId:J.parentRunId}:{},...J.parentKind?{parentKind:J.parentKind}:{},depth:J.depth,status:"queued",workers:W,createdAt:new Date().toISOString()},A=await this.deps.sendCard($.chatId,b7(V));if(!A)throw Error("agent card creation failed; delegated agents were not started");let G;try{G=await this.deps.convertMessageToCard(A)}catch(B){throw await this.deps.sendTextRaw($.chatId,`❌ agent 卡片初始化失败,Agent 未启动: ${w$(B)}`),B}V.cardMessageId=A,this.deps.recordCardCreated(G,W.length+2,(B)=>{z(`agent: card write failed run=${X} code=${B??"MISS"}`)});let _={snapshot:V,session:$,cardId:G,handles:new Map,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)Q?.children.add(X);if(this.currentCancellationEpoch($)!==J.cancellationEpoch||J.parentKind==="delegate"&&!!Q&&(Q.cancelled||Q.finalizing||K0(Q.snapshot.status))){_.cancelled=!0;let B="Agent run was invalidated by parent or Session cancellation before launch";for(let R of _.snapshot.workers)R.status="cancelled",R.error=B,R.finishedAt=new Date().toISOString();return this.persist(_),await this.finalizeRun(_,"cancelled",B),u2(_.snapshot)}this.persist(_);for(let B of H){let R=J.resumeByIdentity?.get(B.id);this.executeWorker(_,B,Z.prompt,R).catch((L)=>{z(`agent: run=${X} worker=${B.id} crashed: ${w$(L)}`)})}return u2(V)}async executeWorker($,Z,J,Q){let Y=$.snapshot.workers.find((W)=>W.identityId===Z.id);if(await this.acquireSlot(()=>{Y.queuedReason=`等待全局并发槽位 (${fH})`,this.persist($),this.updateWorkerCard($,Y)}),$.cancelled){this.releaseSlot();return}let H="";try{if(H=Jq(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),Y.status="running",Y.startedAt=new Date().toISOString(),delete Y.queuedReason,this.refreshNonterminalStatus($),this.persist($),await this.updateWorkerCard($,Y),$.cancelled)return;let W=this.deps.startWorker({identity:Z,effort:Y.effort,workDir:$.snapshot.workDir,prompt:J,resumeSessionId:Q,developerInstructions:$.session.delegatedAgentDeveloperInstructions(Z.provider),profile:Gq(k1($.session.worktreeProjectName())),...process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"?{}:{managedSkillPluginPath:x0},hostEnv:{LODESTAR_AGENT_URL:E4(w.notify.bind,w.notify.port),LODESTAR_AGENT_CAPABILITY:H,LODESTAR_AGENT_SESSION:$.snapshot.sessionName},callbacks:{onNeedsInput:(V)=>{if($.cancelled)return;Y.status="needs_input",Y.pendingInput=V,this.refreshNonterminalStatus($),this.persist($),this.updateWorkerCard($,Y)},onProgress:(V)=>this.recordStep($,Y,V),onSession:(V)=>{if(Y.sessionId===V)return;Y.sessionId=V,this.persist($)}}});$.handles.set(Z.id,W);let X=await W.done;if($.cancelled)return;this.clearProgressTimer($,Z.id),Y.status="completed",Y.output=X.output,Y.outputTruncated=X.outputTruncated,Y.sessionId=X.sessionId,Y.checkpointId=X.checkpointId,Y.durationMs=X.durationMs,Y.usage=X.usage,Y.finishedAt=new Date().toISOString(),delete Y.pendingInput,this.persist($),await this.updateWorkerCard($,Y)}catch(W){if(!$.cancelled){if(this.clearProgressTimer($,Z.id),Y.status="failed",Y.error=w$(W),Y.finishedAt=new Date().toISOString(),Y.startedAt)Y.durationMs=Date.now()-Date.parse(Y.startedAt);delete Y.pendingInput,this.persist($),await this.updateWorkerCard($,Y)}}finally{if($.handles.delete(Z.id),H)this.capabilities.delete(H);$.capabilityByIdentity.delete(Z.id),this.releaseSlot(),this.recomputeRun($)}}recordStep($,Z,J){if($.cancelled||$.finalizing||$.finalized||a9(Z.status))return;if(Z.steps.push(J),Z.steps.length>hH)Z.steps.splice(0,Z.steps.length-hH);if($.progressTimers.has(Z.identityId))return;let Q=setTimeout(()=>{$.progressTimers.delete(Z.identityId),this.updateWorkerCard($,Z)},250);$.progressTimers.set(Z.identityId,Q)}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((Q)=>Q.status==="needs_input"||Q.status==="running"||Q.status==="queued")){this.refreshNonterminalStatus($),this.persist($);return}let J=Z.some((Q)=>Q.status==="failed")?"failed":"completed";this.finalizeRun($,J,J==="failed"?"一个或多个 Agent 失败":void 0).catch((Q)=>{$.finalizing=!1,$.finalized=!1,$.snapshot.status="failed",$.snapshot.error=`Agent terminal persistence failed: ${w$(Q)}`,z(`agent: terminal finalization failed run=${$.snapshot.runId}: ${w$(Q)}`),this.deps.sendTextRaw($.snapshot.chatId,`❌ agent ${$.snapshot.runId} 收尾失败: ${w$(Q)}`).catch((Y)=>z(`agent: terminal failure delivery failed: ${w$(Y)}`))})}async cancelTree($,Z){let J=!K0($.snapshot.status)&&!$.cancelled;if(J){$.cancelled=!0;for(let Q of[...$.progressTimers.keys()])this.clearProgressTimer($,Q);for(let Q of $.capabilityByIdentity.values())this.capabilities.delete(Q);$.capabilityByIdentity.clear()}while(!0){let Q=[...$.children].map((Y)=>this.runs.get(Y)).filter((Y)=>!!Y&&this.treeHasActiveRun(Y));if(Q.length===0)break;await Promise.allSettled(Q.map((Y)=>this.cancelTree(Y,Z)))}if(!J)return;await Promise.allSettled([...$.handles.values()].map((Q)=>Q.cancel(Z)));for(let Q of $.snapshot.workers)if(!a9(Q.status))Q.status="cancelled",Q.error=Z,Q.finishedAt=new Date().toISOString(),delete Q.pendingInput;await this.finalizeRun($,"cancelled",Z)}async finalizeRun($,Z,J){if($.finalized||$.finalizing)return;$.finalizing=!0;for(let Q of[...$.progressTimers.keys()])this.clearProgressTimer($,Q);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,M.agentRunFooter,q9($.snapshot)))this.recordPresentationError($,"agent footer update MISS");if(!await this.deps.patchSettingsChecked($.cardId,{config:{streaming_mode:!1,summary:{content:w2($.snapshot)}}}))this.recordPresentationError($,"agent terminal settings update MISS");await this.deps.flush($.cardId),await this.deps.dispose($.cardId)}}catch(Q){this.recordPresentationError($,`agent card finalization failed: ${w$(Q)}`)}if($.finalizing=!1,this.persist($),$.finalized=!0,$.snapshot.presentationErrors?.length)await this.deps.sendTextRaw($.snapshot.chatId,`⚠️ agent ${$.snapshot.runId} 结果已保存,但卡片有 ${$.snapshot.presentationErrors.length} 个呈现错误。`).catch((Q)=>z(`agent: warning delivery failed run=${$.snapshot.runId}: ${w$(Q)}`))}async updateWorkerCard($,Z){if(!$.cardId||$.finalized)return;try{if(!await this.deps.replaceElementChecked($.cardId,B9(Z.identityId),K9(Z,R9($.snapshot.workers.length))))this.recordPresentationError($,`agent worker card MISS: ${Z.identityName}`);this.deps.patchSummaryThrottled($.cardId,w2($.snapshot))}catch(J){this.recordPresentationError($,`agent worker card update failed (${Z.identityName}): ${w$(J)}`)}}recordPresentationError($,Z){let J=$.snapshot.presentationErrors??[];if(!J.includes(Z))J.push(Z);$.snapshot.presentationErrors=J,z(`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 Q=Zq("sha256").update(J.identityId).digest("hex").slice(0,16);J.outputArtifact=`${$.snapshot.runId}.${Q}.output.txt`}this.persistTextArtifact($,J.outputArtifact,J.output)}let Z=u2($.snapshot);Z.prompt="";for(let J of Z.workers)J.output="";this.deps.writeArtifact(r9(y0,`${$.snapshot.runId}.json`),Z)}persistTextArtifact($,Z,J){if($.persistedArtifacts.has(Z))return;iH(Z),this.deps.writeTextArtifact(r9(y0,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(!K0($.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),Q=[...this.runs.values()].filter((V)=>this.sessionKey(V.snapshot.sessionName,V.snapshot.chatId)===J&&!K0(V.snapshot.status)).length,Y=this.startingRunsBySession.get(J)??0;if(Q+Y>=gH)throw Error(`Session has reached ${gH} active Agent runs`);if([...this.runs.values()].reduce((V,A)=>V+A.snapshot.workers.filter((G)=>!a9(G.status)).length,0)+this.startingWorkers+Z>cH)throw Error(`global Agent worker limit ${cH} would be exceeded`);let W=$.kind==="worker"?$.runId:null;if(W){let V=[...this.runs.values()].filter((G)=>!K0(G.snapshot.status)&&this.isRunInSubtree(G,W)).length,A=this.startingRunsBySubtree.get(W)??0;if(V+A>=IH)throw Error(`Agent subtree has reached ${IH} active runs`)}if(this.startingWorkers+=Z,this.startingRunsBySession.set(J,Y+1),W)this.startingRunsBySubtree.set(W,(this.startingRunsBySubtree.get(W)??0)+1);let X=!1;return()=>{if(X)return;if(X=!0,this.startingWorkers=Math.max(0,this.startingWorkers-Z),pH(this.startingRunsBySession,J),W)pH(this.startingRunsBySubtree,W)}}isRunInSubtree($,Z){let J=$;while(J){if(J.snapshot.runId===Z)return!0;J=J.snapshot.parentRunId?this.runs.get(J.snapshot.parentRunId):void 0}return!1}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<fH)return this.activeTurns++,Promise.resolve();return $(),new Promise((Z)=>this.slotWaiters.push(Z))}releaseSlot(){let $=this.slotWaiters.shift();if($){$();return}this.activeTurns=Math.max(0,this.activeTurns-1)}loadDurableRuns(){for(let $ of this.deps.loadArtifacts()){if(!K0($.status)){$.status="failed",$.error="daemon restarted before this Agent run reached a terminal state",$.finishedAt=new Date().toISOString();for(let J of $.workers)if(!a9(J.status))J.status="failed",J.error=$.error,J.finishedAt=$.finishedAt,delete J.pendingInput}let Z={snapshot:$,session:null,cardId:null,handles:new Map,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<=vH)return;let $=[...this.runs.values()].filter((Z)=>K0(Z.snapshot.status)&&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<=vH)break;if(this.runs.delete(Z.snapshot.runId),Z.snapshot.parentRunId)this.runs.get(Z.snapshot.parentRunId)?.children.delete(Z.snapshot.runId)}}}function Xq($,Z,J){return{identityId:$.id,identityName:$.displayName,tokenSourceId:$.tokenSourceId,provider:$.provider,model:$.model,effort:Z,status:"queued",output:"",...J?{sessionId:J}:{},steps:[]}}function Vq($,Z){let J=Z??$.defaultEffort;if(!$.supportedEfforts.includes(J))throw Error(`${$.displayName} does not support effort ${J}`);return J}function mH($,Z){if(Z){let J=$.workers.find((Q)=>Q.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 K0($){return $==="completed"||$==="failed"||$==="cancelled"}function a9($){return $==="completed"||$==="failed"||$==="cancelled"}function u2($){return JSON.parse(JSON.stringify($))}function zq(){if(!Yq(y0))return[];let $=[];for(let Z of Hq(y0).filter((J)=>J.endsWith(".json")).sort()){let J=r9(y0,Z),Q;try{Q=JSON.parse(lH(J,"utf8"))}catch(Y){throw Error(`agent run artifact is unreadable (${J}): ${w$(Y)}`)}if(!Aq(Q))throw Error(`agent run artifact is invalid: ${J}`);_q(Q,J),$.push(Q)}return $}function Aq($){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 w$($){return $ instanceof Error?$.message:String($)}function Gq($){return $?{...$,tools:void 0,strictMcp:!1,loadProjectMcp:!0}:{strictMcp:!1,loadProjectMcp:!0}}function _q($,Z){if($.promptArtifact)$.prompt=uH($.promptArtifact,`prompt for ${Z}`);for(let J of $.workers)if(J.outputArtifact)J.output=uH(J.outputArtifact,`output for ${Z}`)}function uH($,Z){iH($);try{return lH(r9(y0,$),"utf8")}catch(J){throw Error(`${Z} is unreadable (${$}): ${w$(J)}`)}}function iH($){if(!/^[A-Za-z0-9._-]+$/.test($))throw Error(`invalid Agent artifact name: ${$}`)}function pH($,Z){let J=($.get(Z)??0)-1;if(J>0)$.set(Z,J);else $.delete(Z)}var fH=8,wH=8,vH=512,hH=50,gH=64,IH=32,cH=128,Wq;var nH=N(()=>{n0();C$();r();U$();x9();CH();L$();h$();h();Wq={getCatalog:J1,startWorker:bH,sendCard:i,sendTextRaw:b,convertMessageToCard:a$,recordCardCreated:m$,replaceElementChecked:F$,patchSummaryThrottled:X0,flush:u$,cancelSummary:V$,patchSettingsChecked:q$,dispose:x$,writeArtifact:X$,writeTextArtifact:v$,loadArtifacts:zq}});function dH($){let Z=S5($,"agent run request"),J=Array.isArray(Z.identity_ids)?Z.identity_ids.map(String):Array.isArray(Z.identityIds)?Z.identityIds.map(String):[],Q=[...new Set(J.map((W)=>W.trim()).filter(Boolean))];if(Q.length===0)throw Error("agent run requires at least one identity_id");if(Q.length>64)throw Error("agent run supports at most 64 identities");let Y=rH(Z.prompt,'agent run requires "prompt"'),H=p2(Z.effort);return{identityIds:Q,prompt:Y,...H?{effort:H}:{}}}function oH($){let Z=S5($,"agent follow-up request"),J=rH(Z.prompt,'agent follow-up requires "prompt"'),Q=p2(Z.identity_id??Z.identityId),Y=p2(Z.effort);return{prompt:J,...Q?{identityId:Q}:{},...Y?{effort:Y}:{}}}function aH($){let Z=S5($,"agent answer request"),J=p2(Z.identity_id??Z.identityId),Q=p2(Z.request_id??Z.requestId);if(!Q)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 Y={};for(let[H,W]of Object.entries(Z.answers)){if(!H.trim())throw Error("agent answer contains an empty question key");Y[H]=String(W)}if(Object.keys(Y).length===0)throw Error("agent answer requires at least one answer");return{requestId:Q,answers:Y,...J?{identityId:J}:{}}}function S5($,Z){if(!$||typeof $!=="object"||Array.isArray($))throw Error(`${Z} must be an object`);return $}function rH($,Z){let J=String($??"");if(!J.trim())throw Error(Z);if(J.length>800000)throw Error("agent prompt exceeds 800000 chars");return J}function p2($){return(typeof $==="string"?$.trim():"")||void 0}async function eH($,Z,J,Q){if(J.pathname!=="/agents"&&!J.pathname.startsWith("/agents/"))return!1;let Y=(G,_)=>{return Z.statusCode=G,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify(_)),!0},H=Bq($.headers.authorization);if(!H)return Y(401,{error:"missing bearer capability"});let W=Kq(Q,H);if(!W)return Y(403,{error:"invalid or stale agent capability"});if($.method==="GET"&&J.pathname==="/agents/identities")return await E1(),Y(200,Rq(J1()));if($.method==="POST"&&J.pathname==="/agents/runs")try{let G=await Q.service.startRun(W,dH(await N5($)));return Y(202,t9(G))}catch(G){return Y(409,{error:sH(G)})}let X=J.pathname.match(/^\/agents\/runs\/([^/]+)(?:\/(follow-up|answer))?$/);if(!X)return Y(405,{error:"unsupported agent endpoint"});let V=qq(X[1]);if(!V)return Y(400,{error:"invalid agent run id encoding"});let A=X[2];try{if(!A&&$.method==="GET")return Y(200,t9(Q.service.getRun(W,V)));if(!A&&$.method==="DELETE"){let G=await Q.service.cancelRun(W,V,"cancelled by agent client");return Y(G?200:409,G?{ok:!0,run_id:V}:{error:"agent run is already terminal",run_id:V})}if(A==="follow-up"&&$.method==="POST"){let G=await Q.service.followUp(W,V,oH(await N5($)));return Y(202,t9(G))}if(A==="answer"&&$.method==="POST"){let G=await Q.service.answer(W,V,aH(await N5($)));return Y(200,t9(G))}}catch(G){return Y(409,{error:sH(G)})}return Y(405,{error:"unsupported agent endpoint"})}function Kq($,Z){let J=$.authorizeSession(Z);if(J)return $.service.rootPrincipal(J);return $.service.principalForCapability(Z)}function qq($){try{return decodeURIComponent($)}catch{return null}}function Bq($){return $?.match(/^Bearer\s+(.+)$/i)?.[1]?.trim()??""}async function N5($){let Z="";for await(let J of $)if(Z+=J.toString(),Buffer.byteLength(Z)>tH)throw Error(`request body exceeds ${tH} bytes`);try{return JSON.parse(Z||"{}")}catch{throw Error("bad json")}}function Rq($){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 t9($){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 sH($){return $ instanceof Error?$.message:String($)}var tH=4194304;var $W=N(()=>{x9();_$()});function Pq(){return["---",`name: ${ZW}`,`description: ${JSON.stringify("Call a configured identity as its corresponding Agent through Lodestar for implementation, debugging, research, planning, review, testing, or parallel work. Use whenever the user asks to call another model, AI, or Agent, or when the main Agent deliberately delegates a task.")}`,"---","","# 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.","","## Required workflow","","1. 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.","4. For the same prompt sent to several 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(`
|
|
375
|
-
`)}function
|
|
374
|
+
[delegated agent output truncated at ${CH} chars]`:A1,outputTruncated:H,sessionId:a1,...u5?{checkpointId:u5}:{},durationMs:Date.now()-q,usage:$.lastUsage?{...$.lastUsage}:null})},j=(O)=>{if(O?.parentToolUseId||typeof O?.text!=="string"||H)return;let f=CH-Y.length;if(O.text.length>f){Y+=O.text.slice(0,Math.max(0,f)),H=!0;return}Y+=O.text},S=(O)=>{try{J.onProgress?.(O)}catch(f){P(f instanceof Error?f:Error(String(f)))}},b=(O)=>S({at:new Date().toISOString(),phase:"started",tool:String(O?.name??"tool"),detail:""}),y=(O)=>S({at:new Date().toISOString(),phase:"completed",tool:O?.is_error?"tool error":"tool result",detail:""}),m=(O)=>S({at:new Date().toISOString(),phase:O?.phase??"info",tool:String(O?.tool??"subagent"),detail:""}),v=(O)=>{if(O.tool_name!=="AskUserQuestion"){try{$.sendPermissionResponse(O.request_id,"allow",{updatedInput:O.input??{}})}catch(I){P(I instanceof Error?I:Error(String(I)))}return}if(V){P(Error("delegated agent emitted multiple simultaneous input requests"));return}let f;try{f=Qq(O)}catch(I){P(I instanceof Error?I:Error(String(I)));return}V={request:f,originalInput:O.input??{}},R();try{J.onNeedsInput?.(f)}catch(I){P(I instanceof Error?I:Error(String(I)))}},g=(O)=>{try{$.sendHookResponse(String(O.request_id),{})}catch(f){P(f instanceof Error?f:Error(String(f)))}},E=(O)=>{let f=F(O?.session_id??$.sessionId);if(f)P(f)},k=(O)=>{W=O instanceof Error?O:Error(String(O))},u=(O)=>{if(O.phase==="waiting")R();else if(!V)L();S({at:new Date().toISOString(),phase:"info",tool:"Codex 容量重试",detail:O.phase==="waiting"?`${O.message} · ${O.delayMs/1000}s 后重试 #${O.attempt}`:`正在重试 #${O.attempt}`})},p=(O)=>{let f=O?.is_error?Error(String(O.error??O.subtype??$.lastResult.subtype??"delegated agent failed")):void 0;P(f,O)},a=(O)=>{if(X)return;let f=`code=${O?.code??"null"} signal=${O?.signal??"null"}`;P(W??Error(`delegated agent exited before result (${f})`))};$.on("assistant_text",j),$.on("tool_use",b),$.on("tool_result",y),$.on("subagent_step",m),$.on("can_use_tool",v),$.on("hook_callback",g),$.on("init",E),$.on("error",k),$.on("turn_retry",u),$.on("result",p),$.on("exit",a),L();try{$.sendInitialize(),$.sendUserText(Z)}catch(O){P(O instanceof Error?O:Error(String(O)))}return{done:B,pendingInput:()=>V?.request??null,answer(O,f){if(!V)throw Error("delegated agent is not waiting for input");if(V.request.requestId!==O)throw Error(`delegated agent input request mismatch: expected ${V.request.requestId}`);let I=V;$.sendPermissionResponse(O,"allow",{updatedInput:{...I.originalInput,answers:f}}),V=null,L()},async cancel(O="delegated agent cancelled"){await P(Error(O)),await B.catch(()=>{})}}}function Qq($){let Z=$.input??{},Q=(Array.isArray(Z.questions)?Z.questions:[Z]).map((Y,H)=>Yq(Y,H));if(Q.length===0)throw Error("delegated agent input request contains no questions");return{requestId:String($.request_id),...$.tool_use_id?{toolUseId:$.tool_use_id}:{},questions:Q}}function Yq($,Z){let J=$&&typeof $==="object"?$:{question:$},Q=String(J.question??J.prompt??J.title??"").trim();if(!Q)throw Error(`delegated agent input question ${Z+1} is empty`);let Y=String(J.id??Q),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:Y,...J.header?{header:String(J.header)}:{},question:Q,options:H}}function Hq($,Z){if(typeof $?.id==="string"&&$.id)return $.id;if(Z.provider==="codex"&&typeof Z.lastCompletedTurnId==="string"&&Z.lastCompletedTurnId)return Z.lastCompletedTurnId;if(Z.provider==="claude"&&Z.lastAssistantUuid)return Z.lastAssistantUuid;return}var bH=1800000,CH=2000000;var wH=N(()=>{A6();V4();_$()});import{createHash as Wq,randomBytes as Xq,randomUUID as Vq}from"node:crypto";import{existsSync as zq,readdirSync as Aq,readFileSync as nH}from"node:fs";import{join as r9}from"node:path";class k5{deps;runs=new Map;capabilities=new Map;activeTurns=0;slotWaiters=[];cancellationEpochBySession=new Map;startingWorkers=0;startingRunsBySession=new Map;startingRunsBySubtree=new Map;constructor($=Gq){this.deps=$;this.loadDurableRuns()}rootPrincipal($){return{kind:"session",session:$,depth:-1}}principalForCapability($){return this.capabilities.get($)??null}async startRun($,Z){let J=$.kind==="session"?0:$.depth+1;if(J>hH)throw Error(`delegation depth ${J} exceeds ${hH}`);let Q=this.reserveCapacity($,Z.identityIds.length);try{return await this.createRun($.session,Z,{depth:J,cancellationEpoch:this.currentCancellationEpoch($.session),...$.kind==="worker"?{parentRunId:$.runId,parentKind:"delegate"}:{}})}finally{Q()}}async followUp($,Z,J){let Q=this.requireMutableDescendant($,Z);if(!K0(Q.snapshot.status))throw Error("agent follow-up requires a terminal source run");let Y=pH(Q.snapshot,J.identityId);if(!Y.sessionId)throw Error(`${Y.identityName} has no resumable native session id`);let H=J.effort??Y.effort,W=this.reserveCapacity($,1);try{return await this.createRun($.session,{identityIds:[Y.identityId],prompt:J.prompt,effort:H},{parentRunId:Q.snapshot.runId,parentKind:"follow_up",depth:Q.snapshot.depth,cancellationEpoch:this.currentCancellationEpoch($.session),resumeByIdentity:new Map([[Y.identityId,Y.sessionId]])})}finally{W()}}async answer($,Z,J){let Q=this.requireMutableDescendant($,Z),Y=pH(Q.snapshot,J.identityId);if(Y.status!=="needs_input"||!Y.pendingInput)throw Error(`${Y.identityName} is not waiting for input`);if(Y.pendingInput.requestId!==J.requestId)throw Error(`input request mismatch: expected ${Y.pendingInput.requestId}`);let H=Q.handles.get(Y.identityId);if(!H)throw Error("waiting agent process is no longer alive; start a follow-up run");return H.answer(J.requestId,J.answers),Y.status="running",delete Y.pendingInput,delete Y.queuedReason,this.refreshNonterminalStatus(Q),this.persist(Q),await this.updateWorkerCard(Q,Y),p2(Q.snapshot)}getRun($,Z){return p2(this.requireAccessibleRun($,Z).snapshot)}async cancelRun($,Z,J="agent run cancelled"){let Q=this.requireMutableDescendant($,Z);if(!this.treeHasActiveRun(Q))return!1;return await this.cancelTree(Q,J),!0}async cancelSessionRuns($,Z,J){this.bumpCancellationEpoch($,Z);let Q=[...this.runs.values()].filter((Y)=>Y.snapshot.sessionName===$&&Y.snapshot.chatId===Z&&!Y.snapshot.parentRunId&&this.treeHasActiveRun(Y));await Promise.allSettled(Q.map((Y)=>this.cancelTree(Y,J)))}async shutdown($){let Z=new Set([...this.runs.values()].map((Y)=>`${Y.snapshot.sessionName}\x00${Y.snapshot.chatId}`));for(let Y of Z){let[H,W]=Y.split("\x00");this.bumpCancellationEpoch(H,W)}let J=[...this.runs.values()].filter((Y)=>!Y.snapshot.parentRunId&&this.treeHasActiveRun(Y));await Promise.allSettled(J.map((Y)=>this.cancelTree(Y,$)));let Q=[...this.runs.values()].flatMap((Y)=>[...Y.handles.values()]);await Promise.allSettled(Q.map((Y)=>Y.cancel($)))}async createRun($,Z,J){this.pruneRuns();let Q;if(J.parentRunId){if(Q=this.runs.get(J.parentRunId),!Q)throw Error(`parent agent run not found: ${J.parentRunId}`);if(this.assertSameSession(Q,$),J.parentKind==="delegate"&&(Q.cancelled||Q.finalizing||K0(Q.snapshot.status)))throw Error(`parent agent run is no longer accepting children: ${J.parentRunId}`)}let Y=this.deps.getCatalog(),H=Z.identityIds.map((B)=>{let R=Y.identities.find((L)=>L.id===B);if(!R)throw Error(`agent identity not found: ${B}`);if(R.status!=="ready")throw Error(`${R.displayName}: ${R.reason??R.status}`);return R}),W=H.map((B)=>_q(B,Kq(B,Z.effort),J.resumeByIdentity?.get(B.id))),X=`agent_${Vq()}`,V={runId:X,sessionName:$.sessionName,chatId:$.chatId,workDir:$.workDir,prompt:Z.prompt,...J.parentRunId?{parentRunId:J.parentRunId}:{},...J.parentKind?{parentKind:J.parentKind}:{},depth:J.depth,status:"queued",workers:W,createdAt:new Date().toISOString()},A=await this.deps.sendCard($.chatId,b7(V));if(!A)throw Error("agent card creation failed; delegated agents were not started");let G;try{G=await this.deps.convertMessageToCard(A)}catch(B){throw await this.deps.sendTextRaw($.chatId,`❌ agent 卡片初始化失败,Agent 未启动: ${w$(B)}`),B}V.cardMessageId=A,this.deps.recordCardCreated(G,W.length+2,(B)=>{z(`agent: card write failed run=${X} code=${B??"MISS"}`)});let _={snapshot:V,session:$,cardId:G,handles:new Map,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)Q?.children.add(X);if(this.currentCancellationEpoch($)!==J.cancellationEpoch||J.parentKind==="delegate"&&!!Q&&(Q.cancelled||Q.finalizing||K0(Q.snapshot.status))){_.cancelled=!0;let B="Agent run was invalidated by parent or Session cancellation before launch";for(let R of _.snapshot.workers)R.status="cancelled",R.error=B,R.finishedAt=new Date().toISOString();return this.persist(_),await this.finalizeRun(_,"cancelled",B),p2(_.snapshot)}this.persist(_);for(let B of H){let R=J.resumeByIdentity?.get(B.id);this.executeWorker(_,B,Z.prompt,R).catch((L)=>{z(`agent: run=${X} worker=${B.id} crashed: ${w$(L)}`)})}return p2(V)}async executeWorker($,Z,J,Q){let Y=$.snapshot.workers.find((W)=>W.identityId===Z.id);if(await this.acquireSlot(()=>{Y.queuedReason=`等待全局并发槽位 (${vH})`,this.persist($),this.updateWorkerCard($,Y)}),$.cancelled){this.releaseSlot();return}let H="";try{if(H=Xq(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),Y.status="running",Y.startedAt=new Date().toISOString(),delete Y.queuedReason,this.refreshNonterminalStatus($),this.persist($),await this.updateWorkerCard($,Y),$.cancelled)return;let W=this.deps.startWorker({identity:Z,effort:Y.effort,workDir:$.snapshot.workDir,prompt:J,resumeSessionId:Q,developerInstructions:$.session.delegatedAgentDeveloperInstructions(Z.provider),profile:Rq(k1($.session.worktreeProjectName())),...process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"?{}:{managedSkillPluginPath:x0},hostEnv:{LODESTAR_AGENT_URL:E4(w.notify.bind,w.notify.port),LODESTAR_AGENT_CAPABILITY:H,LODESTAR_AGENT_SESSION:$.snapshot.sessionName},callbacks:{onNeedsInput:(V)=>{if($.cancelled)return;Y.status="needs_input",Y.pendingInput=V,this.refreshNonterminalStatus($),this.persist($),this.updateWorkerCard($,Y)},onProgress:(V)=>this.recordStep($,Y,V),onSession:(V)=>{if(Y.sessionId===V)return;Y.sessionId=V,this.persist($)}}});$.handles.set(Z.id,W);let X=await W.done;if($.cancelled)return;this.clearProgressTimer($,Z.id),Y.status="completed",Y.output=X.output,Y.outputTruncated=X.outputTruncated,Y.sessionId=X.sessionId,Y.checkpointId=X.checkpointId,Y.durationMs=X.durationMs,Y.usage=X.usage,Y.finishedAt=new Date().toISOString(),delete Y.pendingInput,this.persist($),await this.updateWorkerCard($,Y)}catch(W){if(!$.cancelled){if(this.clearProgressTimer($,Z.id),Y.status="failed",Y.error=w$(W),Y.finishedAt=new Date().toISOString(),Y.startedAt)Y.durationMs=Date.now()-Date.parse(Y.startedAt);delete Y.pendingInput,this.persist($),await this.updateWorkerCard($,Y)}}finally{if($.handles.delete(Z.id),H)this.capabilities.delete(H);$.capabilityByIdentity.delete(Z.id),this.releaseSlot(),this.recomputeRun($)}}recordStep($,Z,J){if($.cancelled||$.finalizing||$.finalized||a9(Z.status))return;if(Z.steps.push(J),Z.steps.length>IH)Z.steps.splice(0,Z.steps.length-IH);if($.progressTimers.has(Z.identityId))return;let Q=setTimeout(()=>{$.progressTimers.delete(Z.identityId),this.updateWorkerCard($,Z)},250);$.progressTimers.set(Z.identityId,Q)}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((Q)=>Q.status==="needs_input"||Q.status==="running"||Q.status==="queued")){this.refreshNonterminalStatus($),this.persist($);return}let J=Z.some((Q)=>Q.status==="failed")?"failed":"completed";this.finalizeRun($,J,J==="failed"?"一个或多个 Agent 失败":void 0).catch((Q)=>{$.finalizing=!1,$.finalized=!1,$.snapshot.status="failed",$.snapshot.error=`Agent terminal persistence failed: ${w$(Q)}`,z(`agent: terminal finalization failed run=${$.snapshot.runId}: ${w$(Q)}`),this.deps.sendTextRaw($.snapshot.chatId,`❌ agent ${$.snapshot.runId} 收尾失败: ${w$(Q)}`).catch((Y)=>z(`agent: terminal failure delivery failed: ${w$(Y)}`))})}async cancelTree($,Z){let J=!K0($.snapshot.status)&&!$.cancelled;if(J){$.cancelled=!0;for(let Q of[...$.progressTimers.keys()])this.clearProgressTimer($,Q);for(let Q of $.capabilityByIdentity.values())this.capabilities.delete(Q);$.capabilityByIdentity.clear()}while(!0){let Q=[...$.children].map((Y)=>this.runs.get(Y)).filter((Y)=>!!Y&&this.treeHasActiveRun(Y));if(Q.length===0)break;await Promise.allSettled(Q.map((Y)=>this.cancelTree(Y,Z)))}if(!J)return;await Promise.allSettled([...$.handles.values()].map((Q)=>Q.cancel(Z)));for(let Q of $.snapshot.workers)if(!a9(Q.status))Q.status="cancelled",Q.error=Z,Q.finishedAt=new Date().toISOString(),delete Q.pendingInput;await this.finalizeRun($,"cancelled",Z)}async finalizeRun($,Z,J){if($.finalized||$.finalizing)return;$.finalizing=!0;for(let Q of[...$.progressTimers.keys()])this.clearProgressTimer($,Q);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,M.agentRunFooter,q9($.snapshot)))this.recordPresentationError($,"agent footer update MISS");if(!await this.deps.patchSettingsChecked($.cardId,{config:{streaming_mode:!1,summary:{content:v2($.snapshot)}}}))this.recordPresentationError($,"agent terminal settings update MISS");await this.deps.flush($.cardId),await this.deps.dispose($.cardId)}}catch(Q){this.recordPresentationError($,`agent card finalization failed: ${w$(Q)}`)}if($.finalizing=!1,this.persist($),$.finalized=!0,$.snapshot.presentationErrors?.length)await this.deps.sendTextRaw($.snapshot.chatId,`⚠️ agent ${$.snapshot.runId} 结果已保存,但卡片有 ${$.snapshot.presentationErrors.length} 个呈现错误。`).catch((Q)=>z(`agent: warning delivery failed run=${$.snapshot.runId}: ${w$(Q)}`))}async updateWorkerCard($,Z){if(!$.cardId||$.finalized)return;try{if(!await this.deps.replaceElementChecked($.cardId,B9(Z.identityId),K9(Z,R9($.snapshot.workers.length))))this.recordPresentationError($,`agent worker card MISS: ${Z.identityName}`);this.deps.patchSummaryThrottled($.cardId,v2($.snapshot))}catch(J){this.recordPresentationError($,`agent worker card update failed (${Z.identityName}): ${w$(J)}`)}}recordPresentationError($,Z){let J=$.snapshot.presentationErrors??[];if(!J.includes(Z))J.push(Z);$.snapshot.presentationErrors=J,z(`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 Q=Wq("sha256").update(J.identityId).digest("hex").slice(0,16);J.outputArtifact=`${$.snapshot.runId}.${Q}.output.txt`}this.persistTextArtifact($,J.outputArtifact,J.output)}let Z=p2($.snapshot);Z.prompt="";for(let J of Z.workers)J.output="";this.deps.writeArtifact(r9(y0,`${$.snapshot.runId}.json`),Z)}persistTextArtifact($,Z,J){if($.persistedArtifacts.has(Z))return;dH(Z),this.deps.writeTextArtifact(r9(y0,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(!K0($.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),Q=[...this.runs.values()].filter((V)=>this.sessionKey(V.snapshot.sessionName,V.snapshot.chatId)===J&&!K0(V.snapshot.status)).length,Y=this.startingRunsBySession.get(J)??0;if(Q+Y>=cH)throw Error(`Session has reached ${cH} active Agent runs`);if([...this.runs.values()].reduce((V,A)=>V+A.snapshot.workers.filter((G)=>!a9(G.status)).length,0)+this.startingWorkers+Z>uH)throw Error(`global Agent worker limit ${uH} would be exceeded`);let W=$.kind==="worker"?$.runId:null;if(W){let V=[...this.runs.values()].filter((G)=>!K0(G.snapshot.status)&&this.isRunInSubtree(G,W)).length,A=this.startingRunsBySubtree.get(W)??0;if(V+A>=mH)throw Error(`Agent subtree has reached ${mH} active runs`)}if(this.startingWorkers+=Z,this.startingRunsBySession.set(J,Y+1),W)this.startingRunsBySubtree.set(W,(this.startingRunsBySubtree.get(W)??0)+1);let X=!1;return()=>{if(X)return;if(X=!0,this.startingWorkers=Math.max(0,this.startingWorkers-Z),iH(this.startingRunsBySession,J),W)iH(this.startingRunsBySubtree,W)}}isRunInSubtree($,Z){let J=$;while(J){if(J.snapshot.runId===Z)return!0;J=J.snapshot.parentRunId?this.runs.get(J.snapshot.parentRunId):void 0}return!1}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<vH)return this.activeTurns++,Promise.resolve();return $(),new Promise((Z)=>this.slotWaiters.push(Z))}releaseSlot(){let $=this.slotWaiters.shift();if($){$();return}this.activeTurns=Math.max(0,this.activeTurns-1)}loadDurableRuns(){for(let $ of this.deps.loadArtifacts()){if(!K0($.status)){$.status="failed",$.error="daemon restarted before this Agent run reached a terminal state",$.finishedAt=new Date().toISOString();for(let J of $.workers)if(!a9(J.status))J.status="failed",J.error=$.error,J.finishedAt=$.finishedAt,delete J.pendingInput}let Z={snapshot:$,session:null,cardId:null,handles:new Map,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<=gH)return;let $=[...this.runs.values()].filter((Z)=>K0(Z.snapshot.status)&&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<=gH)break;if(this.runs.delete(Z.snapshot.runId),Z.snapshot.parentRunId)this.runs.get(Z.snapshot.parentRunId)?.children.delete(Z.snapshot.runId)}}}function _q($,Z,J){return{identityId:$.id,identityName:$.displayName,tokenSourceId:$.tokenSourceId,provider:$.provider,model:$.model,effort:Z,status:"queued",output:"",...J?{sessionId:J}:{},steps:[]}}function Kq($,Z){let J=Z??$.defaultEffort;if(!$.supportedEfforts.includes(J))throw Error(`${$.displayName} does not support effort ${J}`);return J}function pH($,Z){if(Z){let J=$.workers.find((Q)=>Q.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 K0($){return $==="completed"||$==="failed"||$==="cancelled"}function a9($){return $==="completed"||$==="failed"||$==="cancelled"}function p2($){return JSON.parse(JSON.stringify($))}function qq(){if(!zq(y0))return[];let $=[];for(let Z of Aq(y0).filter((J)=>J.endsWith(".json")).sort()){let J=r9(y0,Z),Q;try{Q=JSON.parse(nH(J,"utf8"))}catch(Y){throw Error(`agent run artifact is unreadable (${J}): ${w$(Y)}`)}if(!Bq(Q))throw Error(`agent run artifact is invalid: ${J}`);Pq(Q,J),$.push(Q)}return $}function Bq($){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 w$($){return $ instanceof Error?$.message:String($)}function Rq($){return $?{...$,tools:void 0,strictMcp:!1,loadProjectMcp:!0}:{strictMcp:!1,loadProjectMcp:!0}}function Pq($,Z){if($.promptArtifact)$.prompt=lH($.promptArtifact,`prompt for ${Z}`);for(let J of $.workers)if(J.outputArtifact)J.output=lH(J.outputArtifact,`output for ${Z}`)}function lH($,Z){dH($);try{return nH(r9(y0,$),"utf8")}catch(J){throw Error(`${Z} is unreadable (${$}): ${w$(J)}`)}}function dH($){if(!/^[A-Za-z0-9._-]+$/.test($))throw Error(`invalid Agent artifact name: ${$}`)}function iH($,Z){let J=($.get(Z)??0)-1;if(J>0)$.set(Z,J);else $.delete(Z)}var vH=8,hH=8,gH=512,IH=50,cH=64,mH=32,uH=128,Gq;var oH=N(()=>{n0();C$();t();U$();x9();wH();L$();h$();h();Gq={getCatalog:J1,startWorker:fH,sendCard:n,sendTextRaw:x,convertMessageToCard:a$,recordCardCreated:m$,replaceElementChecked:F$,patchSummaryThrottled:X0,flush:u$,cancelSummary:V$,patchSettingsChecked:q$,dispose:x$,writeArtifact:X$,writeTextArtifact:v$,loadArtifacts:qq}});function aH($){let Z=S5($,"agent run request"),J=Array.isArray(Z.identity_ids)?Z.identity_ids.map(String):Array.isArray(Z.identityIds)?Z.identityIds.map(String):[],Q=[...new Set(J.map((W)=>W.trim()).filter(Boolean))];if(Q.length===0)throw Error("agent run requires at least one identity_id");if(Q.length>64)throw Error("agent run supports at most 64 identities");let Y=sH(Z.prompt,'agent run requires "prompt"'),H=l2(Z.effort);return{identityIds:Q,prompt:Y,...H?{effort:H}:{}}}function rH($){let Z=S5($,"agent follow-up request"),J=sH(Z.prompt,'agent follow-up requires "prompt"'),Q=l2(Z.identity_id??Z.identityId),Y=l2(Z.effort);return{prompt:J,...Q?{identityId:Q}:{},...Y?{effort:Y}:{}}}function tH($){let Z=S5($,"agent answer request"),J=l2(Z.identity_id??Z.identityId),Q=l2(Z.request_id??Z.requestId);if(!Q)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 Y={};for(let[H,W]of Object.entries(Z.answers)){if(!H.trim())throw Error("agent answer contains an empty question key");Y[H]=String(W)}if(Object.keys(Y).length===0)throw Error("agent answer requires at least one answer");return{requestId:Q,answers:Y,...J?{identityId:J}:{}}}function S5($,Z){if(!$||typeof $!=="object"||Array.isArray($))throw Error(`${Z} must be an object`);return $}function sH($,Z){let J=String($??"");if(!J.trim())throw Error(Z);if(J.length>800000)throw Error("agent prompt exceeds 800000 chars");return J}function l2($){return(typeof $==="string"?$.trim():"")||void 0}async function ZW($,Z,J,Q){if(J.pathname!=="/agents"&&!J.pathname.startsWith("/agents/"))return!1;let Y=(G,_)=>{return Z.statusCode=G,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify(_)),!0},H=jq($.headers.authorization);if(!H)return Y(401,{error:"missing bearer capability"});let W=Lq(Q,H);if(!W)return Y(403,{error:"invalid or stale agent capability"});if($.method==="GET"&&J.pathname==="/agents/identities")return await E1(),Y(200,Fq(J1()));if($.method==="POST"&&J.pathname==="/agents/runs")try{let G=await Q.service.startRun(W,aH(await N5($)));return Y(202,t9(G))}catch(G){return Y(409,{error:$W(G)})}let X=J.pathname.match(/^\/agents\/runs\/([^/]+)(?:\/(follow-up|answer))?$/);if(!X)return Y(405,{error:"unsupported agent endpoint"});let V=Dq(X[1]);if(!V)return Y(400,{error:"invalid agent run id encoding"});let A=X[2];try{if(!A&&$.method==="GET")return Y(200,t9(Q.service.getRun(W,V)));if(!A&&$.method==="DELETE"){let G=await Q.service.cancelRun(W,V,"cancelled by agent client");return Y(G?200:409,G?{ok:!0,run_id:V}:{error:"agent run is already terminal",run_id:V})}if(A==="follow-up"&&$.method==="POST"){let G=await Q.service.followUp(W,V,rH(await N5($)));return Y(202,t9(G))}if(A==="answer"&&$.method==="POST"){let G=await Q.service.answer(W,V,tH(await N5($)));return Y(200,t9(G))}}catch(G){return Y(409,{error:$W(G)})}return Y(405,{error:"unsupported agent endpoint"})}function Lq($,Z){let J=$.authorizeSession(Z);if(J)return $.service.rootPrincipal(J);return $.service.principalForCapability(Z)}function Dq($){try{return decodeURIComponent($)}catch{return null}}function jq($){return $?.match(/^Bearer\s+(.+)$/i)?.[1]?.trim()??""}async function N5($){let Z="";for await(let J of $)if(Z+=J.toString(),Buffer.byteLength(Z)>eH)throw Error(`request body exceeds ${eH} bytes`);try{return JSON.parse(Z||"{}")}catch{throw Error("bad json")}}function Fq($){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 t9($){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 $W($){return $ instanceof Error?$.message:String($)}var eH=4194304;var JW=N(()=>{x9();_$()});function Mq(){return["---",`name: ${QW}`,`description: ${JSON.stringify("Call a configured identity as its corresponding Agent through Lodestar for implementation, debugging, research, planning, review, testing, or parallel work. Use only for delegation to a different model or Agent. Self-calls MUST use your own Agent's native delegation capabilities and MUST NOT use this Skill.")}`,"---","","# 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.","","## Hard rule: native Agent capabilities for self-calls","","- When calling yourself or your own model/Agent, you MUST 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 rule applies at every delegation depth and within multi-model tasks:"," handle self-calls natively and include only other models/Agents in this Skill.","- 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.","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(`
|
|
375
|
+
`)}function YW(){SH("lodestar-consult"),o9({name:QW,body:Mq()})}var QW="lodestar-agent";var HW=N(()=>{T5()});import{chmodSync as Uq,existsSync as y5,readFileSync as VW,unlinkSync as Oq}from"node:fs";import{homedir as Eq}from"node:os";import{basename as Tq,dirname as kq,join as N0,resolve as Sq}from"node:path";function Nq($={}){let Z=Sq($.daemonEntry??process.argv[1]??""),J=$.runtime??process.execPath,Q=$.exists??y5,Y=kq(Z),H=N0(Y,"src","agent-cli.ts"),W=N0(Y,"lodestar-agent.js"),X=N0(Y,"dist","lodestar-agent.js"),A=/^bun(?:\.exe)?$/i.test(Tq(J))?[H,W,X]:[W,X],G=A.find(Q);if(!G)throw Error(`lodestar-agent entry not found beside daemon: ${A.join(", ")}`);return{runtime:J,entry:G}}function zW($={}){let Z=$.platform??process.platform,J=$.env??process.env,Q=$.targetDir??xq(Z,$.homeDir??Eq(),$.localAppData??process.env.LOCALAPPDATA),Y=$.launch??Nq(),H=N0(Q,Z==="win32"?"lodestar-agent.cmd":"lodestar-agent"),W=Z==="win32"?`@"${XW(Y.runtime)}" "${XW(Y.entry)}" %*\r
|
|
376
376
|
`:`#!/bin/sh
|
|
377
|
-
exec ${
|
|
378
|
-
`,X=y5(H)?WW(H,"utf8"):null;if(X!==W)e5(H,W),z(`command: ${X===null?"installed":"updated"} ${H}`);else Lq(H,448);return kq(J,Q,Z),Eq(Q,Z),H}function Eq($,Z){let J=N0($,Z==="win32"?"lodestar-consult.cmd":"lodestar-consult");if(!y5(J))return;try{let Q=WW(J,"utf8");if(!Q.includes("lodestar-consult")&&!Q.includes("consult-cli")){z(`command: obsolete path preserved because ownership is unclear ${J}`);return}Dq(J),z(`command: removed obsolete ${J}`)}catch(Q){z(`command: obsolete removal failed (${J}): ${Q}`)}}function Tq($,Z,J){if($==="win32")return N0(J??N0(Z,"AppData","Local"),"Lodestar","bin");return N0(Z,".local","bin")}function kq($,Z,J){let Q=J==="win32"?Object.keys($).find((X)=>X.toLowerCase()==="path")??"Path":"PATH",Y=J==="win32"?";":":",H=$[Q]??"",W=(X)=>J==="win32"?X.toLowerCase():X;if(H.split(Y).some((X)=>W(X)===W(Z)))return;$[Q]=H?`${Z}${Y}${H}`:Z}function YW($){return`'${$.replaceAll("'",`'"'"'`)}'`}function HW($){return $.replaceAll('"','""')}var VW=N(()=>{h();h$()});function zW($,Z,J){return $>0&&Z-$>J}function AW($){let Z=$==="media"?"视频":$==="image"?"图片":"文件";return`❌ 收到的${Z}下载失败,未转交给 Agent。备注:可能是${Z}超过飞书消息资源 100 MB 下载上限。`}function x5($){return typeof $==="string"&&$.length>0?$:void 0}function GW($,Z){if(!Z||typeof Z!=="object")return null;let J=Z;if($==="image"){let W=x5(J.image_key);return W?{key:W,type:"image",displayText:""}:null}if($!=="file"&&$!=="media")return null;let Q=x5(J.file_key);if(!Q)return null;let Y=x5(J.file_name);return{key:Q,type:"file",...Y?{name:Y}:{},displayText:Y?`(${$==="media"?"video":"file"}: ${Y})`:""}}function _W($,Z){return $.add(Z),Z.then(()=>{$.delete(Z)},()=>{$.delete(Z)}),Z}async function KW($){while(!0){let Z=[...$()];if(Z.length===0)return;await Promise.allSettled(Z)}}function Nq($){let Z=$?.action?.value??{},J=String(Z.kind??"");if(!J)return"无效操作";if(!Sq.has(J))return`不支持的操作: ${J}`;if(J!=="notify_callback"&&!String($?.context?.open_chat_id??""))return"回调缺少 chat_id,操作未执行";if(J!=="notify_callback"&&!String($?.context?.open_message_id??""))return"回调缺少原卡 message_id,操作未执行";if(J==="permission"&&!["allow","allow_always","deny"].includes(String(Z.decision??"")))return"无效的权限决定,操作未执行";return null}class C5{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 Y=(this.tails.get(J)??Promise.resolve()).then(Z),H;return H=Y.then(()=>{},()=>{}).finally(()=>{if(this.tails.get(J)===H)this.tails.delete(J)}),this.tails.set(J,H),{accepted:!0,completion:Y}}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 qW($){let Z=$.now??Date.now;return{accept(J){let Q=Z();return $.actor.tryEnqueue($.key(J),()=>$.execute(J,Q))}}}class f5{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 b5($){if(Array.isArray($))return`[${$.map(b5).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)}:${b5(J)}`).join(",")}}`}function yq($){let Z=$?.action?.value??{},J=String(Z?.kind??"unknown"),Q=String($?.context?.open_chat_id??""),Y=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"notify_callback":H={notify_id:Z.notify_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`${Q}\x00${Y}\x00${J}\x00${b5(H)}`}function xq($){let Z=String($?.event_id??$?.header?.event_id??$?.event?.event_id??"");return{...Z?{deliveryKey:`event\x00${Z}`}:{},businessKey:`semantic\x00${yq($)}`}}function bq(){return new Promise(($)=>setTimeout($,0))}function s9($,Z,J){if(Z.deliveryKey)$.complete(Z.deliveryKey);if(J)$.complete(Z.businessKey);else $.fail(Z.businessKey)}function BW($){let Z=$.afterAck??bq,J=(Y)=>{try{$.onBackgroundError?.(Y)}catch{}},Q=async(Y)=>{try{await Y()}catch(H){J(H)}};return{accept(Y){if(!$.actor.isAccepting())return $.responses.closed(Y);let H=Nq(Y);if(H)return $.responses.invalid(Y,H);let W=xq(Y),X=W.deliveryKey?[W.deliveryKey,W.businessKey]:[W.businessKey],V=$.deduper.claimAll(X);if(V==="inflight")return $.responses.inflight(Y);if(V==="completed")return $.responses.completed(Y);let A=$.actor.tryEnqueue($.scope(Y),async()=>{try{await Z()}catch(q){$.deduper.failAll(X),J(q);return}let G;try{G=await $.execute(Y)}catch(q){$.deduper.completeAll(X),await Q(()=>$.presentExecutionFailure(Y,q));return}await Q(async()=>{try{await $.present(Y,G)}catch(q){await $.presentPresentationFailure(Y,q)}});let _;try{_=$.completion(Y,G)}catch(q){s9($.deduper,W,!1),J(q);return}if(_){let q=_.then((B)=>{s9($.deduper,W,B==="complete")},(B)=>{s9($.deduper,W,!1),J(B)});$.track(q);return}s9($.deduper,W,$.businessSucceeded(Y,G))});if(!A.accepted)return $.deduper.failAll(X),$.responses.closed(Y);return $.track(A.completion),A.completion.catch(J),$.responses.accepted(Y)}}}var Sq;var RW=N(()=>{Sq=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","notify_callback"])});function q0($){return $ instanceof Error?$.message:String($)}function PW($,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 LW($){let Z=(Y,H)=>{let W=$.registry.get(Y);if(W&&W.sessionName!==H)throw Error(`chat ${Y} is already owned by session "${W.sessionName}", not "${H}"`);if(!W)W=$.createSession(H,Y),$.registry.set(Y,W);return W};return{sessionFor:Z,createTempSession:async(Y)=>{let H;try{if(G$(Y.launch,Y.routing.provider,Y.workDir),Y.launch.kind==="resume")throw Error("temporary groups must start fresh or fork; resume is not allowed");if(H=await $.ensureChatForSession(Y.chatName,Y.userOpenId),!H.created)return{ok:!1,chatId:H.chatId,error:"临时会话必须使用新群;既有群保留,未执行加入、启动或删除"}}catch(X){let V=q0(X);return $.log(`temp-session: create "${Y.chatName}" failed: ${V}`),{ok:!1,error:V}}let W=async()=>{let X=null;try{if($.registerTempSessionLease(Y.chatName,H.chatId),X=Z(H.chatId,Y.chatName),X.isRunning())return{ok:!1,error:`${Y.chatName} 已有会话在跑,先 bye 解散再重试`};if(X.workDir!==Y.workDir)throw Error(`临时群 cwd 不匹配: source=${Y.workDir} target=${X.workDir}`);if(X.applyConversationRouting(Y.routing),!(Y.launch.kind==="fork"?await X.startForked(Y.launch,{announce:!1}):await X.start({announce:!1})))throw Error(`${X.backendLabel()} 启动失败`);return $.replaceTurnAnchors(Y.chatName,Y.seedAnchors??[],Y.branchBase),{ok:!0,chatId:H.chatId}}catch(V){let A=q0(V);if($.log(`temp-session: initialize "${Y.chatName}" failed: ${A}`),X)try{await X.stop("临时群启动失败清理",{announce:!1})}catch(_){let q=q0(_);return $.log(`temp-session: failed-create stop "${Y.chatName}" failed: ${q}`),{ok:!1,chatId:H.chatId,error:`${A};无法确认 Session 已停止,临时群/session 仍保留: ${q}`}}if(!H.created)return{ok:!1,error:`${A};既有群保留,未执行删除`};let G;try{let _=await $.disbandChatForSessionExact(Y.chatName,H.chatId);G=PW(Y.chatName,H.chatId,_)}catch(_){let q=q0(_);return $.log(`temp-session: create cleanup "${Y.chatName}" failed: ${q}`),{ok:!1,chatId:H.chatId,error:`${A};自动解散失败,临时群/session 仍保留: ${q}`}}try{$.registry.delete(G),X?.dispose(),$.clearSessionConversationState(Y.chatName)}catch(_){let q=q0(_);return $.log(`temp-session: local cleanup "${Y.chatName}" failed: ${q}`),{ok:!1,error:`${A};临时群已确认解散,但本地状态清理失败: ${q}`}}return{ok:!1,error:`${A};本次新建的临时群已确认解散`}}};try{return $.runExclusive?await $.runExclusive(H.chatId,W):await W()}catch(X){let V=q0(X);return $.log(`temp-session: target actor "${Y.chatName}" failed: ${V}`),{ok:!1,chatId:H.chatId,error:`${V};临时群/session 仍保留`}}},disbandTempSession:async(Y,H)=>{let W=$.chatIdForSession(Y);if(!H||W!==H){let A=`临时群 chat_id 已变化: expected=${H||"-"} bound=${W??"-"}`;return $.log(`temp-session: disband identity rejected "${Y}": ${A}`),{ok:!1,error:`${A};未执行停止或删群`}}if(!$.hasTempSessionLease(Y,H)){let A=`群 ${H} 没有 Lodestar 临时会话 lease,拒绝解散`;return $.log(`temp-session: disband lease rejected "${Y}": ${A}`),{ok:!1,error:`${A};未执行停止或删群`}}let X=$.registry.get(W);try{if(X)await X.stop("bye 解散",{announce:!1})}catch(A){let G=q0(A);return $.log(`temp-session: stop before disband "${Y}" failed: ${G}`),{ok:!1,error:`${G};无法确认 Session 已停止,未执行删群`}}let V;try{let A=await $.disbandChatForSessionExact(Y,W);V=PW(Y,W,A)}catch(A){let G=q0(A);return $.log(`temp-session: disband "${Y}" failed: ${G}`),{ok:!1,error:`${G};临时群/session 仍保留`}}try{return $.registry.delete(V),X?.dispose(),$.clearSessionConversationState(Y),{ok:!0}}catch(A){let G=q0(A);return $.log(`temp-session: local cleanup after disband "${Y}" failed: ${G}`),{ok:!1,error:`临时群已确认解散,但本地状态清理失败: ${G}`}}}}}var DW=N(()=>{P1()});var JB={};import*as d1 from"@larksuiteoapi/node-sdk";import{chmodSync as Cq,existsSync as v5,mkdirSync as fq,readFileSync as wq,unlinkSync as Z8,writeFileSync as vq}from"node:fs";import{dirname as hq}from"node:path";function o1($,Z){if(X1=Math.max(X1,Z),e9)return e9;g5=!0,i2.close(),h5=c5();try{R2(h5)}catch(J){z(`shutdown alive marker write failed: ${J}`),X1=1}return e9=(async()=>{z(`${$}: staged shutdown begin sessions=${n1.size}`);try{let J=(async()=>{await KW(()=>[...i2.pending(),...UW]);let W=await Promise.allSettled([I5.shutdown(`daemon ${$}`)]),X=await Promise.allSettled([...n1.values()].map((V)=>V.stop(`daemon ${$}`,{announce:!1})));return[...W,...X]})(),Q=null,Y=new Promise((W)=>{Q=setTimeout(()=>W("deadline"),FW)}),H=await Promise.race([J.then((W)=>{for(let X of W)if(X.status==="rejected")X1=1,z(`shutdown session stop failed: ${X.reason}`);return"stopped"}),Y]);if(Q)clearTimeout(Q);if(H==="deadline")X1=1,z(`${$}: shutdown deadline ${FW}ms reached; forcing exit`);else z(`${$}: all sessions stopped`)}catch(J){z(`${$}: staged shutdown failed: ${J}`),X1=1}finally{MW(),process.exit(X1)}})(),e9}function OW($){return _W(UW,$)}function EW($,Z="ws"){if(g5)return z(`${Z}: reject inbound message: daemon shutdown in progress`),!1;let J=String($?.message?.chat_id??""),Q=Iq.accept($);if(!Q.accepted)return z(`${Z}: reject inbound message${J?"":" without chat_id"}: actor ${Q.reason}`),!1;return Q.completion.catch((Y)=>{z(`${Z}: handleMessage rejected chat=${J.slice(0,8)}…: ${Y}`)}),!0}function c5(){let $=new Set;for(let Z of n1.values())if(Z.shouldRevive())$.add(Z.sessionName);for(let Z of l2)$.add(Z);return[...$]}function $8(){R2(c5())}function TW($,Z){return m5.sessionFor($,Z)}async function cq($){return await m5.createTempSession($)}async function mq($,Z){return await m5.disbandTempSession($,Z)}async function uq(){let $=[...new Set(f6())];if($.length===0)return;l2=new Set($),z(`revive: ${$.length} session(s) marked alive on shutdown: ${$.join(", ")}`);try{await Promise.all($.map(async(Z)=>{let J=N1(Z);if(!J){z(`revive: no chatId binding for "${Z}", skip`),l2.delete(Z),$8();return}let Q=TW(J,Z);try{if(await Q.restart(!0))z(`revive: spawned "${Z}" (chat ${J.slice(0,8)}…)`);else z(`revive: "${Z}" did not start`)}catch(Y){z(`revive: restart "${Z}" failed: ${Y}`)}finally{l2.delete(Z),$8()}}))}finally{l2.clear(),$8()}}function pq($){let Z=[],J=[],Q=[],Y=typeof $?.title==="string"?$.title.trim():"";if(Y)Q.push(`# ${Y}`);let H=Array.isArray($?.content)?$.content:[];for(let W of H){if(!Array.isArray(W))continue;let X=[];for(let A of W){if(!A||typeof A!=="object")continue;switch(A.tag){case"text":{let G=String(A.text??""),_=Array.isArray(A.style)?A.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(A.href??""),_=String(A.text??G);X.push(`[${_}](${G})`);break}case"at":{let G=String(A.user_name??A.user_id??"");X.push(`@${G}`);break}case"code_inline":X.push(`\`${String(A.text??"")}\``);break;case"hr":X.push("---");break;case"img":if(A.image_key)Z.push(String(A.image_key));break;case"media":if(A.file_key)J.push({key:String(A.file_key),name:A.file_name});break;case"emotion":break;default:if(typeof A.text==="string")X.push(A.text)}}let V=X.join("");if(V.trim())Q.push(V)}return{markdown:Q.join(`
|
|
377
|
+
exec ${WW(Y.runtime)} ${WW(Y.entry)} "$@"
|
|
378
|
+
`,X=y5(H)?VW(H,"utf8"):null;if(X!==W)$3(H,W),z(`command: ${X===null?"installed":"updated"} ${H}`);else Uq(H,448);return bq(J,Q,Z),yq(Q,Z),H}function yq($,Z){let J=N0($,Z==="win32"?"lodestar-consult.cmd":"lodestar-consult");if(!y5(J))return;try{let Q=VW(J,"utf8");if(!Q.includes("lodestar-consult")&&!Q.includes("consult-cli")){z(`command: obsolete path preserved because ownership is unclear ${J}`);return}Oq(J),z(`command: removed obsolete ${J}`)}catch(Q){z(`command: obsolete removal failed (${J}): ${Q}`)}}function xq($,Z,J){if($==="win32")return N0(J??N0(Z,"AppData","Local"),"Lodestar","bin");return N0(Z,".local","bin")}function bq($,Z,J){let Q=J==="win32"?Object.keys($).find((X)=>X.toLowerCase()==="path")??"Path":"PATH",Y=J==="win32"?";":":",H=$[Q]??"",W=(X)=>J==="win32"?X.toLowerCase():X;if(H.split(Y).some((X)=>W(X)===W(Z)))return;$[Q]=H?`${Z}${Y}${H}`:Z}function WW($){return`'${$.replaceAll("'",`'"'"'`)}'`}function XW($){return $.replaceAll('"','""')}var AW=N(()=>{h();h$()});function GW($,Z,J){return $>0&&Z-$>J}function _W($){let Z=$==="media"?"视频":$==="image"?"图片":"文件";return`❌ 收到的${Z}下载失败,未转交给 Agent。备注:可能是${Z}超过飞书消息资源 100 MB 下载上限。`}function x5($){return typeof $==="string"&&$.length>0?$:void 0}function KW($,Z){if(!Z||typeof Z!=="object")return null;let J=Z;if($==="image"){let W=x5(J.image_key);return W?{key:W,type:"image",displayText:""}:null}if($!=="file"&&$!=="media")return null;let Q=x5(J.file_key);if(!Q)return null;let Y=x5(J.file_name);return{key:Q,type:"file",...Y?{name:Y}:{},displayText:Y?`(${$==="media"?"video":"file"}: ${Y})`:""}}function qW($,Z){return $.add(Z),Z.then(()=>{$.delete(Z)},()=>{$.delete(Z)}),Z}async function BW($){while(!0){let Z=[...$()];if(Z.length===0)return;await Promise.allSettled(Z)}}function fq($){let Z=$?.action?.value??{},J=String(Z.kind??"");if(!J)return"无效操作";if(!Cq.has(J))return`不支持的操作: ${J}`;if(J!=="notify_callback"&&!String($?.context?.open_chat_id??""))return"回调缺少 chat_id,操作未执行";if(J!=="notify_callback"&&!String($?.context?.open_message_id??""))return"回调缺少原卡 message_id,操作未执行";if(J==="permission"&&!["allow","allow_always","deny"].includes(String(Z.decision??"")))return"无效的权限决定,操作未执行";return null}class C5{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 Y=(this.tails.get(J)??Promise.resolve()).then(Z),H;return H=Y.then(()=>{},()=>{}).finally(()=>{if(this.tails.get(J)===H)this.tails.delete(J)}),this.tails.set(J,H),{accepted:!0,completion:Y}}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 RW($){let Z=$.now??Date.now;return{accept(J){let Q=Z();return $.actor.tryEnqueue($.key(J),()=>$.execute(J,Q))}}}class f5{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 b5($){if(Array.isArray($))return`[${$.map(b5).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)}:${b5(J)}`).join(",")}}`}function wq($){let Z=$?.action?.value??{},J=String(Z?.kind??"unknown"),Q=String($?.context?.open_chat_id??""),Y=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"notify_callback":H={notify_id:Z.notify_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`${Q}\x00${Y}\x00${J}\x00${b5(H)}`}function vq($){let Z=String($?.event_id??$?.header?.event_id??$?.event?.event_id??"");return{...Z?{deliveryKey:`event\x00${Z}`}:{},businessKey:`semantic\x00${wq($)}`}}function hq(){return new Promise(($)=>setTimeout($,0))}function s9($,Z,J){if(Z.deliveryKey)$.complete(Z.deliveryKey);if(J)$.complete(Z.businessKey);else $.fail(Z.businessKey)}function PW($){let Z=$.afterAck??hq,J=(Y)=>{try{$.onBackgroundError?.(Y)}catch{}},Q=async(Y)=>{try{await Y()}catch(H){J(H)}};return{accept(Y){if(!$.actor.isAccepting())return $.responses.closed(Y);let H=fq(Y);if(H)return $.responses.invalid(Y,H);let W=vq(Y),X=W.deliveryKey?[W.deliveryKey,W.businessKey]:[W.businessKey],V=$.deduper.claimAll(X);if(V==="inflight")return $.responses.inflight(Y);if(V==="completed")return $.responses.completed(Y);let A=$.actor.tryEnqueue($.scope(Y),async()=>{try{await Z()}catch(q){$.deduper.failAll(X),J(q);return}let G;try{G=await $.execute(Y)}catch(q){$.deduper.completeAll(X),await Q(()=>$.presentExecutionFailure(Y,q));return}await Q(async()=>{try{await $.present(Y,G)}catch(q){await $.presentPresentationFailure(Y,q)}});let _;try{_=$.completion(Y,G)}catch(q){s9($.deduper,W,!1),J(q);return}if(_){let q=_.then((B)=>{s9($.deduper,W,B==="complete")},(B)=>{s9($.deduper,W,!1),J(B)});$.track(q);return}s9($.deduper,W,$.businessSucceeded(Y,G))});if(!A.accepted)return $.deduper.failAll(X),$.responses.closed(Y);return $.track(A.completion),A.completion.catch(J),$.responses.accepted(Y)}}}var Cq;var LW=N(()=>{Cq=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","notify_callback"])});function q0($){return $ instanceof Error?$.message:String($)}function DW($,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 jW($){let Z=(Y,H)=>{let W=$.registry.get(Y);if(W&&W.sessionName!==H)throw Error(`chat ${Y} is already owned by session "${W.sessionName}", not "${H}"`);if(!W)W=$.createSession(H,Y),$.registry.set(Y,W);return W};return{sessionFor:Z,createTempSession:async(Y)=>{let H;try{if(G$(Y.launch,Y.routing.provider,Y.workDir),Y.launch.kind==="resume")throw Error("temporary groups must start fresh or fork; resume is not allowed");if(H=await $.ensureChatForSession(Y.chatName,Y.userOpenId),!H.created)return{ok:!1,chatId:H.chatId,error:"临时会话必须使用新群;既有群保留,未执行加入、启动或删除"}}catch(X){let V=q0(X);return $.log(`temp-session: create "${Y.chatName}" failed: ${V}`),{ok:!1,error:V}}let W=async()=>{let X=null;try{if($.registerTempSessionLease(Y.chatName,H.chatId),X=Z(H.chatId,Y.chatName),X.isRunning())return{ok:!1,error:`${Y.chatName} 已有会话在跑,先 bye 解散再重试`};if(X.workDir!==Y.workDir)throw Error(`临时群 cwd 不匹配: source=${Y.workDir} target=${X.workDir}`);if(X.applyConversationRouting(Y.routing),!(Y.launch.kind==="fork"?await X.startForked(Y.launch,{announce:!1}):await X.start({announce:!1})))throw Error(`${X.backendLabel()} 启动失败`);return $.replaceTurnAnchors(Y.chatName,Y.seedAnchors??[],Y.branchBase),{ok:!0,chatId:H.chatId}}catch(V){let A=q0(V);if($.log(`temp-session: initialize "${Y.chatName}" failed: ${A}`),X)try{await X.stop("临时群启动失败清理",{announce:!1})}catch(_){let q=q0(_);return $.log(`temp-session: failed-create stop "${Y.chatName}" failed: ${q}`),{ok:!1,chatId:H.chatId,error:`${A};无法确认 Session 已停止,临时群/session 仍保留: ${q}`}}if(!H.created)return{ok:!1,error:`${A};既有群保留,未执行删除`};let G;try{let _=await $.disbandChatForSessionExact(Y.chatName,H.chatId);G=DW(Y.chatName,H.chatId,_)}catch(_){let q=q0(_);return $.log(`temp-session: create cleanup "${Y.chatName}" failed: ${q}`),{ok:!1,chatId:H.chatId,error:`${A};自动解散失败,临时群/session 仍保留: ${q}`}}try{$.registry.delete(G),X?.dispose(),$.clearSessionConversationState(Y.chatName)}catch(_){let q=q0(_);return $.log(`temp-session: local cleanup "${Y.chatName}" failed: ${q}`),{ok:!1,error:`${A};临时群已确认解散,但本地状态清理失败: ${q}`}}return{ok:!1,error:`${A};本次新建的临时群已确认解散`}}};try{return $.runExclusive?await $.runExclusive(H.chatId,W):await W()}catch(X){let V=q0(X);return $.log(`temp-session: target actor "${Y.chatName}" failed: ${V}`),{ok:!1,chatId:H.chatId,error:`${V};临时群/session 仍保留`}}},disbandTempSession:async(Y,H)=>{let W=$.chatIdForSession(Y);if(!H||W!==H){let A=`临时群 chat_id 已变化: expected=${H||"-"} bound=${W??"-"}`;return $.log(`temp-session: disband identity rejected "${Y}": ${A}`),{ok:!1,error:`${A};未执行停止或删群`}}if(!$.hasTempSessionLease(Y,H)){let A=`群 ${H} 没有 Lodestar 临时会话 lease,拒绝解散`;return $.log(`temp-session: disband lease rejected "${Y}": ${A}`),{ok:!1,error:`${A};未执行停止或删群`}}let X=$.registry.get(W);try{if(X)await X.stop("bye 解散",{announce:!1})}catch(A){let G=q0(A);return $.log(`temp-session: stop before disband "${Y}" failed: ${G}`),{ok:!1,error:`${G};无法确认 Session 已停止,未执行删群`}}let V;try{let A=await $.disbandChatForSessionExact(Y,W);V=DW(Y,W,A)}catch(A){let G=q0(A);return $.log(`temp-session: disband "${Y}" failed: ${G}`),{ok:!1,error:`${G};临时群/session 仍保留`}}try{return $.registry.delete(V),X?.dispose(),$.clearSessionConversationState(Y),{ok:!0}}catch(A){let G=q0(A);return $.log(`temp-session: local cleanup after disband "${Y}" failed: ${G}`),{ok:!1,error:`临时群已确认解散,但本地状态清理失败: ${G}`}}}}}var FW=N(()=>{P1()});var XB={};import*as d1 from"@larksuiteoapi/node-sdk";import{chmodSync as gq,existsSync as v5,mkdirSync as Iq,readFileSync as cq,unlinkSync as Z8,writeFileSync as mq}from"node:fs";import{dirname as uq}from"node:path";function o1($,Z){if(X1=Math.max(X1,Z),e9)return e9;g5=!0,n2.close(),h5=c5();try{P2(h5)}catch(J){z(`shutdown alive marker write failed: ${J}`),X1=1}return e9=(async()=>{z(`${$}: staged shutdown begin sessions=${n1.size}`);try{let J=(async()=>{await BW(()=>[...n2.pending(),...EW]);let W=await Promise.allSettled([I5.shutdown(`daemon ${$}`)]),X=await Promise.allSettled([...n1.values()].map((V)=>V.stop(`daemon ${$}`,{announce:!1})));return[...W,...X]})(),Q=null,Y=new Promise((W)=>{Q=setTimeout(()=>W("deadline"),UW)}),H=await Promise.race([J.then((W)=>{for(let X of W)if(X.status==="rejected")X1=1,z(`shutdown session stop failed: ${X.reason}`);return"stopped"}),Y]);if(Q)clearTimeout(Q);if(H==="deadline")X1=1,z(`${$}: shutdown deadline ${UW}ms reached; forcing exit`);else z(`${$}: all sessions stopped`)}catch(J){z(`${$}: staged shutdown failed: ${J}`),X1=1}finally{OW(),process.exit(X1)}})(),e9}function TW($){return qW(EW,$)}function kW($,Z="ws"){if(g5)return z(`${Z}: reject inbound message: daemon shutdown in progress`),!1;let J=String($?.message?.chat_id??""),Q=lq.accept($);if(!Q.accepted)return z(`${Z}: reject inbound message${J?"":" without chat_id"}: actor ${Q.reason}`),!1;return Q.completion.catch((Y)=>{z(`${Z}: handleMessage rejected chat=${J.slice(0,8)}…: ${Y}`)}),!0}function c5(){let $=new Set;for(let Z of n1.values())if(Z.shouldRevive())$.add(Z.sessionName);for(let Z of i2)$.add(Z);return[...$]}function $8(){P2(c5())}function SW($,Z){return m5.sessionFor($,Z)}async function iq($){return await m5.createTempSession($)}async function nq($,Z){return await m5.disbandTempSession($,Z)}async function dq(){let $=[...new Set(f6())];if($.length===0)return;i2=new Set($),z(`revive: ${$.length} session(s) marked alive on shutdown: ${$.join(", ")}`);try{await Promise.all($.map(async(Z)=>{let J=N1(Z);if(!J){z(`revive: no chatId binding for "${Z}", skip`),i2.delete(Z),$8();return}let Q=SW(J,Z);try{if(await Q.restart(!0))z(`revive: spawned "${Z}" (chat ${J.slice(0,8)}…)`);else z(`revive: "${Z}" did not start`)}catch(Y){z(`revive: restart "${Z}" failed: ${Y}`)}finally{i2.delete(Z),$8()}}))}finally{i2.clear(),$8()}}function oq($){let Z=[],J=[],Q=[],Y=typeof $?.title==="string"?$.title.trim():"";if(Y)Q.push(`# ${Y}`);let H=Array.isArray($?.content)?$.content:[];for(let W of H){if(!Array.isArray(W))continue;let X=[];for(let A of W){if(!A||typeof A!=="object")continue;switch(A.tag){case"text":{let G=String(A.text??""),_=Array.isArray(A.style)?A.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(A.href??""),_=String(A.text??G);X.push(`[${_}](${G})`);break}case"at":{let G=String(A.user_name??A.user_id??"");X.push(`@${G}`);break}case"code_inline":X.push(`\`${String(A.text??"")}\``);break;case"hr":X.push("---");break;case"img":if(A.image_key)Z.push(String(A.image_key));break;case"media":if(A.file_key)J.push({key:String(A.file_key),name:A.file_name});break;case"emotion":break;default:if(typeof A.text==="string")X.push(A.text)}}let V=X.join("");if(V.trim())Q.push(V)}return{markdown:Q.join(`
|
|
379
379
|
|
|
380
|
-
`),imageKeys:Z,fileKeys:J}}async function iq($,Z=Date.now()){let J=$?.message;if(!J)return;let Y=($?.sender?.sender_id??$?.event?.sender?.sender_id??J?.sender?.sender_id)?.open_id??"",H=J.message_id;if(H&&l1.has(H))return;if(H){if(l1.add(H),l1.size>200){let P=[...l1];l1.clear();for(let j of P.slice(-100))l1.add(j)}}let W=Number(J.create_time??0);if(zW(W,Z,lq)){if(z(`drop stale message ${H} ageAtReceipt=${Math.round((Z-W)/1000)}s`),H)T$(H,"CrossMark");return}let X=J.chat_id,V={};try{V=JSON.parse(J.content??"{}")}catch{}let A=J.message_type==="text"?V.text??"":"";if(typeof A==="string"&&A.startsWith("[DEBUG]")){try{vq(r2,JSON.stringify({chat_id:X,sender_open_id:Y,seeded_at:new Date().toISOString(),seeded_msg_id:H??""},null,2)),z(`debug: seeded inject context chat=${X.slice(0,8)}… sender=${Y.slice(0,8)}…`)}catch(j){z(`debug: seed context failed: ${j}`)}let P=A.slice(7);V.text=P,J.content=JSON.stringify(V)}let G=Y$.get(X);if(!G)await P2(),G=Y$.get(X);if(!G)G=await I6(X)??void 0;if(!G){z(`unknown chat ${X}, dropping message`),await E(X,"❌ 无法识别群名。请确认:① 机器人已被拉进本群;② 群已设置名称(未命名群拿不到群名,无法映射项目目录)。设置后再发一条消息即可。");return}let _=j2(G);T1(_,X);let q=TW(X,_),B={};try{B=JSON.parse(J.content??"{}")}catch{}let R=J.message_type,L="",F=[];if(R==="text")L=(B.text??"").trim();else if(R==="post"){let P=pq(B);L=P.markdown.trim();for(let j of P.imageKeys){let k=await L2(J.message_id,j,"image");if(k)F.push(k)}for(let j of P.fileKeys){let k=await L2(J.message_id,j.key,"file",j.name);if(k)F.push(k)}}if(R==="text"&&L){if(await q.runCommand(L,Y))return}if(R==="text"&&L&&await q.consumeModelCustomMessage(L,Y))return;if(R==="text"&&L&&q.hasPendingAsk()){await q.onAskMessageAnswer(L,Y,H??"");return}let U=GW(R,B);if(U){let P=await L2(J.message_id,U.key,U.type,U.name);if(!P){await E(X,AW(R));return}if(F.push(P),!L&&U.displayText)L=U.displayText}if(!L&&F.length===0){z(`drop empty message ${H} type=${R}`);return}if(await q.onMultiMessageInbound(L,F,Y,H??""))return;await q.onUserMessage(L||"(empty)",F,Y,H??"")}function J8($){return{permission:"权限决定",menu:"菜单选择",provider_select:"账号选择",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:"通知反馈"}[$]??$}function nq($){return $?.card?.type==="raw"&&$.card.data&&typeof $.card.data==="object"?$.card.data:null}function H$($,Z,J){return{...$,__businessOk:Z,...J?{__businessMessage:J}:{}}}function V1($,Z){return{...Z,__cardActionMessageId:$.messageId,__cardActionChatId:$.chatId}}function i1($){return H$($.card?f$($.card):{toast:{type:$.ok?"success":"error",content:$.message}},$.ok)}async function z1($,Z){if(!$){z(`card-action: cannot send receipt without chat_id: ${Z}`);return}if(!await b($,Z))z(`card-action: visible receipt MISS chat=${$.slice(0,8)}… text=${Z.slice(0,120)}`)}async function dq($,Z){let J=String($?.action?.value?.kind??"unknown"),Q=J8(J),Y=String(Z?.__cardActionChatId??$?.__cardActionChatId??$?.context?.open_chat_id??""),H=String(Z?.__cardActionMessageId??$?.context?.open_message_id??""),W=nq(Z),X=Z?.__businessOk===!1&&typeof Z?.__businessMessage==="string"?` 业务失败: ${Z.__businessMessage.replace(/\s+/g," ").trim().slice(0,300)}。`:"";if(W&&H)try{await H0(H,W);return}catch(B){z(`card-action: ${J} original-card update failed: ${B instanceof Error?B.message:B}`),await z1(Y,`⚠️ ${Q}已处理,但原卡更新失败。${X}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":"请重新打开操作面板。"}`);return}if(W){await z1(Y,`⚠️ ${Q}已处理,但回调缺少原卡 message_id,无法更新。${X}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":""}`);return}if(J==="notify_callback"&&Z?.__cardActionCompletion)return;let V=Z?.toast,A=typeof V?.content==="string"&&V.content.trim()?V.content.trim():`${Q}已完成`,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 z1(Y,`${_?"❌":"✅"} ${Q}: ${A}`)}async function oq($,Z){let J=String($?.action?.value?.kind??"unknown"),Q=Z instanceof Error?Z.message:String(Z);await z1(String($?.__cardActionChatId??$?.context?.open_chat_id??""),`❌ ${J8(J)}失败: ${Q}`)}function rq($){return aq.accept($)}async function tq($){let Z=$?.action,J=Z?.value;if(!J?.kind)return;let Q=$?.context?.open_chat_id??"",Y=$?.operator?.open_id??"";if(J.kind==="notify_callback")return await sq(J,Q,Y);let H=n1.get(Q);if(!H)return H$({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,Y);return H$({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})`),H$(f$(E0({title:"\uD83D\uDCCB 菜单选择",message:`已选择第 ${W+1} 项`,ok:!0})),!0)}catch(X){let V=X instanceof Error?X.message:String(X);return H$(f$(E0({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 i1(W)}case"model_select":{let W=await H.onModelSelect(String(J.model??""),String(J.panel_id??""),Y,J);return i1(W)}case"model_custom_prompt":{let W=await H.onModelCustomPrompt(String(J.source_id??""),String(J.panel_id??""),String($?.context?.open_message_id??""));return i1(W)}case"model_panel_cancel":{let W=await H.onModelPanelCancel(String(J.panel_id??""));return i1(W)}case"model_effort_select":{let W=await H.onModelEffortSelect(String(J.model??""),String(J.effort??""),String(J.panel_id??""),Y,String(J.provider??""));return i1(W)}case"ask":{if(J.custom){let V=(Z?.form_value??Z?.input??{})?.custom_answer??Z?.input_value??"",A=await H.onAskCustomAnswer(J.tool_use_id,J.question_idx??0,V,Y);return H$({toast:{type:A?"success":"error",content:A?"已回答":V.trim()?"问题已失效或答案未被接受":"请输入答案"}},A)}let W=await H.onAskAnswer(J.tool_use_id,J.question_idx??0,J.option_idx,Y);return H$({toast:{type:W?"success":"error",content:W?"已回答":"问题已失效或选项无效"}},W)}case"worktree_disband":{let W=await H.onWorktreeDisband(String(J.slug??""));return H$(f$(W.card),W.ok)}case"temp_fork_select":{let W=await H.onForkSelect(String(J.panel_id??""),String(J.choice_id??""),Y);return H$(W.replaceCard===!1?{toast:{type:"error",content:W.message}}:f$(E0({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??""),Y);return H$(W.replaceCard===!1?{toast:{type:"error",content:W.message}}:f$(E0({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??""),Y);if(W.replaceCard===!1)return H$({toast:{type:"error",content:W.message}},W.ok);if(!W.resumePresentation)throw Error("rs selection result missing trusted presentation snapshot");return H$(f$(E7({...W.resumePresentation,message:W.message,ok:W.ok})),W.ok,W.message)}case"tasklist_enable":{let W=await H.onTasklistEnable();return H$(f$(W.card),W.ok)}case"tasklist_delete_prompt":{let W=H.onTasklistDeletePrompt(String(J.guid??""));return H$(f$(W.card),W.ok)}case"tasklist_delete_confirm":{let W=await H.onTasklistDeleteConfirm(String(J.guid??""));return H$(f$(W.card),W.ok)}case"token_source_enable":{let{onTokenSourceEnable:W}=await Promise.resolve().then(() => (Q5(),J5));return await W(H,String(J.source_id??"")),{toast:{type:"info",content:"已处理"}}}case"agent_identity_page":return i1(H.onAgentIdentityPage(String(J.panel_id??""),J.page,Y))}return{toast:{type:"info",content:"unknown action"}}}async function sq($,Z,J){let Q=String($?.notify_id??""),Y=String($?.button_id??"");if(!Q)return{toast:{type:"error",content:"回调缺少 notify_id"}};let H=i9(Q);if(!H)return z(`notify-callback: notify_id=${Q.slice(0,12)}… not found (expired or pre-restart)`),{toast:{type:"error",content:"通知已过期或已移除"}};if(H.unknownAt)return V1(H,H$({toast:{type:"error",content:`外部回调可能已成功,但本地确认状态未知,已禁止自动重试${H.unknownReason?`: ${H.unknownReason}`:""}`}},!0));if(H.resolvedAt)return V1(H,{toast:{type:"info",content:"已处理过"}});if(qH(Q))return V1(H,{toast:{type:"info",content:"处理中…"}});let W=H.buttons.find((A)=>A.id===Y);if(!W)return z(`notify-callback: notify_id=${Q.slice(0,12)}… unknown button_id="${Y}"`),V1(H,H$({toast:{type:"error",content:"未知按钮"}},!1));if(!H.callbackUrl){try{F5(H.notifyId,W.id,J)}catch(A){return V1(H,H$({toast:{type:"error",content:`保存反馈结果失败: ${A instanceof Error?A.message:A}`}},!1))}return z(`notify-callback: notify_id=${Q.slice(0,12)}… resolved button="${Y}" by=${J.slice(0,8)}… (no callback, pull/display)`),V1(H,{...f$(n9(H,{status:"done",buttonId:W.id,text:W.text,operatorOpenId:J}))})}BH(H.notifyId);let X=OW(eq(H,W,J));X.catch((A)=>{z(`notify-callback: notify_id=${H.notifyId.slice(0,12)}… phase-2 rejected: ${A instanceof Error?A.message:A}`)});let V=X.then((A)=>A==="retry"?"retry":"complete").catch(()=>"retry");return V1(H,{toast:{type:"info",content:`⏳ 已选择:${W.text} · 推送中…`},__cardActionCompletion:V})}async function eq($,Z,J){try{let Q=n9($,{status:"processing",buttonId:Z.id,text:Z.text,operatorOpenId:J});try{await H0($.messageId,Q)}catch(X){z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-1 (processing) updateCard failed: ${X instanceof Error?X.message:X}`)}let Y=await jH($,Z,J),H=Y.ok?"complete":"retry",W;if(Y.ok){let X=DH($.notifyId,Z.id,J);if(X.state==="complete")W={status:"delivered",buttonId:Z.id,text:Z.text,operatorOpenId:J,reply:Y.reply};else{H="unknown",W={status:"unknown",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:X.detail},z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… callback succeeded but tombstone is UNKNOWN: ${X.detail}`);try{await z1($.chatId,`⚠️ 通知反馈的外部回调已成功,但本地确认状态未知;为避免重复副作用,已禁止自动重试。${X.detail}`)}catch(V){z(`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:Y.detail};try{let X=n9($,W);await H0($.messageId,X)}catch(X){z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-2 (final) presentation failed: ${X instanceof Error?X.message:X}`);try{await z1($.chatId,`⚠️ 通知反馈${H==="retry"?"失败且结果卡更新失败,可重新点击":"已执行,但结果卡更新失败"}: ${X instanceof Error?X.message:X}`)}catch(V){z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… final fallback receipt failed: ${V instanceof Error?V.message:V}`)}}return z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… button="${Z.id}" ${H==="complete"?"delivered":H==="unknown"?"unknown/non-retryable":`failed: ${Y.detail}`} by=${J.slice(0,8)}…`),H}finally{RH($.notifyId)}}function w5($){return $.map((Z)=>typeof Z==="string"?Z:JSON.stringify(Z)).join(" ")}function $B(){if(process.platform==="win32"){z("debug: inject socket skipped on Windows (dev-only feature)");return}if(typeof Bun>"u"){z("debug: inject socket skipped (Bun runtime only — npm/Node build does not include it)");return}try{if(v5(b0))Z8(b0)}catch{}try{Bun.serve({unix:b0,fetch:async($)=>{if($.method!=="POST")return new Response("use POST",{status:405});if(g5)return new Response("daemon shutdown in progress",{status:503});let Z={};try{Z=await $.json()}catch{return new Response("bad json",{status:400})}if(!v5(r2))return new Response("no debug context yet — send `[DEBUG]hi` from Feishu first",{status:412});let J={};try{J=JSON.parse(wq(r2,"utf8"))}catch(X){return new Response(`ctx read failed: ${X}`,{status:500})}let Q=String(Z.text??"");if(!Q)return new Response("text required",{status:400});let Y=`【自动化测试】:${Q}`,H=await E(J.chat_id,Y);if(!H)return new Response("sendText failed — see daemon log",{status:502});let W={sender:{sender_id:{open_id:J.sender_open_id}},message:{message_id:H,chat_id:J.chat_id,message_type:"text",content:JSON.stringify({text:Q}),create_time:String(Date.now())}};if(z(`debug: inject text=${JSON.stringify(Q).slice(0,80)} msg_id=${H}`),!EW(W,"debug"))return new Response("daemon shutdown in progress",{status:503});return new Response(JSON.stringify({ok:!0,msg_id:H}),{headers:{"content-type":"application/json"}})}});try{Cq(b0,384)}catch{}z(`debug: inject socket listening at ${b0}`)}catch($){z(`debug: socket bind failed: ${$}`)}}async function ZB(){z(`lodestar-daemon: pid ${process.pid} starting`);let{buildTokenSourcesFromConfig:$}=await Promise.resolve().then(() => ($5(),nQ));$();let{refreshAllTokenSourceModels:Z}=await Promise.resolve().then(() => (_$(),WZ));await Z(),j6(),U6(),O6(),T6(),N6(),await P2(),setInterval(()=>{P2()},1800000);let{reconcileTasklistDeletions:J}=await Promise.resolve().then(() => (X5(),W5));try{await J()}catch(T){z(`tasklist deletion reconcile failed: ${T instanceof Error?T.message:T}`)}let Q,Y=Date.now(),H=0,W=!1,X=null,V=1500,A=90000,G=600000,_=3,q=null,B=0,R="",L=!1,F=(T)=>{z(`[ws] rebuild requested before WS init — ${T}`)},U=(T,m=0,u=!1)=>{let S=Date.now()+m;if(q){if(L||=u,S>=B){z(`[ws] rebuild already scheduled — ${T}`);return}clearTimeout(q)}B=S,R=T,L=u,q=setTimeout(()=>{let y=R,n=L;q=null,B=0,R="",L=!1,F(y,n)},m)},P={error:(T)=>z(`[ws-sdk error] ${w5(T)}`),warn:(T)=>{let m=w5(T);if(z(`[ws-sdk warn] ${m}`),m.includes("no pong/inbound"))U("ping-timeout: SDK liveness watchdog fired",2000,Date.now()-Y<G)},info:(T)=>z(`[ws-sdk] ${w5(T)}`),debug:(T)=>{},trace:(T)=>{}},j=new d1.EventDispatcher({}),k=()=>{if(Y=Date.now(),H=0,X)clearTimeout(X),X=null};j.register({"im.message.receive_v1":async(T)=>{if(k(),!EW(T))throw Error("daemon shutdown in progress")}}),j.register({"card.action.trigger":async(T)=>{return k(),rq(T)}});let C=()=>new d1.WSClient({appId:w.feishu.app_id,appSecret:w.feishu.app_secret,loggerLevel:d1.LoggerLevel.info,logger:P,wsConfig:{pingTimeout:60},handshakeTimeoutMs:1e4,onReconnecting:()=>z("[ws] reconnecting — WS lost, SDK is retrying"),onReconnected:()=>c(),onError:(T)=>F(`SDK onError: ${T?.message??T}`)});F=(T,m=!1)=>{if(W){z(`[ws] rebuild skipped (already rebuilding) — ${T}`);return}if(q)clearTimeout(q),q=null,B=0;W=!0,H++,z(`[ws] rebuild #${H} (fresh WSClient) — ${T}`);let u=Q;try{u?.close({force:!0})}catch(S){z(`[ws] rebuild: old close failed: ${S}`)}if(Q=C(),Q.start({eventDispatcher:j}).catch((S)=>{z(`[ws] rebuild start failed: ${S}`),U(`fresh client start failed: ${S}`,V,m)}),W=!1,m)x()};let x=()=>{if(X)clearTimeout(X);let T=Date.now();X=setTimeout(()=>{if(X=null,Y>=T){H=0;return}if(H>=_){z(`[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}F(`verify: no event ${Math.round((Date.now()-T)/1000)}s after rebuild`,!0)},A)},c=()=>{let T=Date.now()-Y<G;z("[ws] reconnected — swapping in a fresh WSClient (cluster-routing precaution; "+`recentlyActive=${T})`),H=0,U("post-reconnect precaution",V,T)};Q=C(),Q.start({eventDispatcher:j}).catch((T)=>{z(`[ws] initial start failed: ${T}`),U(`initial start failed: ${T}`,V,!1)}),z(`lodestar-daemon: WS start requested, watching ${Y$.size} groups`);let v=15000,g=2,O=0;setInterval(()=>{let{state:T}=Q.getConnectionStatus();if(T==="connected"){O=0;return}if(T==="failed"||T==="idle"){O=0,F(`watchdog: state=${T}`);return}if(O++,z(`[ws] watchdog: state=${T} (${O}/${g})`),O>=g)O=0,F(`watchdog: stuck in '${T}' ~${Math.round(v*g/1000)}s`)},v),$B(),PH(),EH({bind:w.notify.bind,port:w.notify.port,extraHandler:(T,m,u)=>eH(T,m,u,{service:I5,authorizeSession:(S)=>{for(let y of n1.values())if(y.acceptsAgentCapability(S))return y;return null}})}),XW(),SH(),JW(),await uq()}var jW=!1,g5=!1,e9=null,X1=0,h5=null,FW=15000,MW=()=>{if(jW)return;jW=!0;try{let $=h5??c5();if(R2($),$.length>0)z(`alive marker: [${$.join(", ")}]`)}catch($){z(`alive marker write failed: ${$}`)}try{Z8(k$)}catch{}try{Z8(b0)}catch{}},n1,I5,l2,i2,gq,UW,Iq,m5,lq=30000,l1,aq;var kW=N(()=>{AH();r();C$();M5();U5();U5();NH();nH();$W();QW();VW();U$();h();L$();_8();RW();DW();{let $=t2(k$);if($.state==="exit")console.error(`lodestar-daemon: already running (pid ${$.pid})`),process.exit(1);if(v5(k$))try{Z8(k$)}catch{}}fq(hq(k$),{recursive:!0});o5(k$);process.on("exit",MW);process.on("SIGTERM",()=>{o1("SIGTERM",0)});process.on("SIGINT",()=>{o1("SIGINT",0)});if(process.platform==="win32")process.on("SIGBREAK",()=>{o1("SIGBREAK",0)});process.on("unhandledRejection",($)=>{z(`unhandledRejection: ${$ instanceof Error?$.stack??$.message:$}`),o1("unhandledRejection",1)});process.on("uncaughtException",($)=>{z(`uncaughtException: ${$.stack??$.message}`),o1("uncaughtException",1)});n1=new Map,I5=new k5,l2=new Set,i2=new C5,gq=new f5(30000),UW=new Set,Iq=qW({actor:i2,key:($)=>String($?.message?.chat_id??""),execute:($,Z)=>iq($,Z)});m5=LW({registry:n1,createSession:($,Z)=>new W1($,Z,{onLifecycleChange:$8,onCreateTempSession:cq,onDisbandTempSession:mq,onCancelAgentRuns:(J,Q,Y)=>I5.cancelSessionRuns(J,Q,Y)}),ensureChatForSession:v6,disbandChatForSessionExact:g6,chatIdForSession:N1,clearSessionConversationState:C6,registerTempSessionLease:F6,hasTempSessionLease:M6,replaceTurnAnchors:I$,runExclusive:($,Z)=>i2.enqueue($,Z),log:z});l1=new Set;aq=BW({actor:i2,deduper:gq,scope:($)=>{if(String($?.action?.value?.kind??"").startsWith("agent_identity_"))return"__agent_identities_global__";return String($?.context?.open_chat_id??"")||"__notify_global__"},execute:tq,present:dq,presentExecutionFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");z(`handleCardAction ${J}: ${Z instanceof Error?Z.stack??Z.message:Z}`),await oq($,Z)},presentPresentationFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");z(`card-action presentation ${J}: ${Z instanceof Error?Z.message:Z}`),await z1(String($?.context?.open_chat_id??""),`⚠️ ${J8(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:($)=>{OW($)},onBackgroundError:($)=>{z(`card-action background: ${$ instanceof Error?$.stack??$.message:$}`)},responses:{accepted:($)=>({toast:{type:"info",content:`⏳ ${J8(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}})}});ZB().catch(($)=>{z(`boot fatal: ${$}`),o1("boot fatal",1)})});L$();_8();import{existsSync as SW,unlinkSync as QB}from"node:fs";var n$={reset:"\x1B[0m",bold:"\x1B[1m",yellow:"\x1B[33m",green:"\x1B[32m",red:"\x1B[31m"};async function YB(){if(!SW(P$)){if(process.stdin.isTTY){console.log(),console.log(`${n$.bold}${n$.yellow}Lodestar: 未找到配置, 启动安装向导...${n$.reset}`);let{runSetup:Z}=await Promise.resolve().then(() => (Y3(),Q3));await Z();return}console.error(`${n$.red}Lodestar: 未找到配置 ${P$}${n$.reset}`),console.error(`请在交互式 cmd / PowerShell 里运行 ${n$.green}lodestar-setup${n$.reset} 完成首次配置 (或直接运行 ${n$.green}lodestar-daemon${n$.reset} 也会触发同一个向导)。`),process.exit(1)}let $=t2(k$);if($.state==="exit")console.error(`${n$.yellow}Lodestar: 已经有一个 daemon 在运行 (pid ${$.pid})${n$.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(` • 误判 / 已经死了: 手删 ${k$} 后再跑`),process.exit(1);if(SW(k$))try{QB(k$)}catch{}await Promise.resolve().then(() => (kW(),JB))}YB().catch(($)=>{console.error("lodestar fatal:",$?.message??$),process.exit(1)});
|
|
380
|
+
`),imageKeys:Z,fileKeys:J}}async function rq($,Z=Date.now()){let J=$?.message;if(!J)return;let Y=($?.sender?.sender_id??$?.event?.sender?.sender_id??J?.sender?.sender_id)?.open_id??"",H=J.message_id;if(H&&l1.has(H))return;if(H){if(l1.add(H),l1.size>200){let P=[...l1];l1.clear();for(let j of P.slice(-100))l1.add(j)}}let W=Number(J.create_time??0);if(GW(W,Z,aq)){if(z(`drop stale message ${H} ageAtReceipt=${Math.round((Z-W)/1000)}s`),H)T$(H,"CrossMark");return}let X=J.chat_id,V={};try{V=JSON.parse(J.content??"{}")}catch{}let A=J.message_type==="text"?V.text??"":"";if(typeof A==="string"&&A.startsWith("[DEBUG]")){try{mq(t2,JSON.stringify({chat_id:X,sender_open_id:Y,seeded_at:new Date().toISOString(),seeded_msg_id:H??""},null,2)),z(`debug: seeded inject context chat=${X.slice(0,8)}… sender=${Y.slice(0,8)}…`)}catch(j){z(`debug: seed context failed: ${j}`)}let P=A.slice(7);V.text=P,J.content=JSON.stringify(V)}let G=H$.get(X);if(!G)await L2(),G=H$.get(X);if(!G)G=await I6(X)??void 0;if(!G){z(`unknown chat ${X}, dropping message`),await T(X,"❌ 无法识别群名。请确认:① 机器人已被拉进本群;② 群已设置名称(未命名群拿不到群名,无法映射项目目录)。设置后再发一条消息即可。");return}let _=F2(G);T1(_,X);let q=SW(X,_),B={};try{B=JSON.parse(J.content??"{}")}catch{}let R=J.message_type,L="",F=[];if(R==="text")L=(B.text??"").trim();else if(R==="post"){let P=oq(B);L=P.markdown.trim();for(let j of P.imageKeys){let S=await D2(J.message_id,j,"image");if(S)F.push(S)}for(let j of P.fileKeys){let S=await D2(J.message_id,j.key,"file",j.name);if(S)F.push(S)}}if(R==="text"&&L){if(await q.runCommand(L,Y))return}if(R==="text"&&L&&await q.consumeModelCustomMessage(L,Y))return;if(R==="text"&&L&&q.hasPendingAsk()){await q.onAskMessageAnswer(L,Y,H??"");return}let U=KW(R,B);if(U){let P=await D2(J.message_id,U.key,U.type,U.name);if(!P){await T(X,_W(R));return}if(F.push(P),!L&&U.displayText)L=U.displayText}if(!L&&F.length===0){z(`drop empty message ${H} type=${R}`);return}if(await q.onMultiMessageInbound(L,F,Y,H??""))return;await q.onUserMessage(L||"(empty)",F,Y,H??"")}function J8($){return{permission:"权限决定",menu:"菜单选择",provider_select:"账号选择",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:"通知反馈"}[$]??$}function tq($){return $?.card?.type==="raw"&&$.card.data&&typeof $.card.data==="object"?$.card.data:null}function W$($,Z,J){return{...$,__businessOk:Z,...J?{__businessMessage:J}:{}}}function V1($,Z){return{...Z,__cardActionMessageId:$.messageId,__cardActionChatId:$.chatId}}function i1($){return W$($.card?f$($.card):{toast:{type:$.ok?"success":"error",content:$.message}},$.ok)}async function z1($,Z){if(!$){z(`card-action: cannot send receipt without chat_id: ${Z}`);return}if(!await x($,Z))z(`card-action: visible receipt MISS chat=${$.slice(0,8)}… text=${Z.slice(0,120)}`)}async function sq($,Z){let J=String($?.action?.value?.kind??"unknown"),Q=J8(J),Y=String(Z?.__cardActionChatId??$?.__cardActionChatId??$?.context?.open_chat_id??""),H=String(Z?.__cardActionMessageId??$?.context?.open_message_id??""),W=tq(Z),X=Z?.__businessOk===!1&&typeof Z?.__businessMessage==="string"?` 业务失败: ${Z.__businessMessage.replace(/\s+/g," ").trim().slice(0,300)}。`:"";if(W&&H)try{await H0(H,W);return}catch(B){z(`card-action: ${J} original-card update failed: ${B instanceof Error?B.message:B}`),await z1(Y,`⚠️ ${Q}已处理,但原卡更新失败。${X}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":"请重新打开操作面板。"}`);return}if(W){await z1(Y,`⚠️ ${Q}已处理,但回调缺少原卡 message_id,无法更新。${X}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":""}`);return}if(J==="notify_callback"&&Z?.__cardActionCompletion)return;let V=Z?.toast,A=typeof V?.content==="string"&&V.content.trim()?V.content.trim():`${Q}已完成`,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 z1(Y,`${_?"❌":"✅"} ${Q}: ${A}`)}async function eq($,Z){let J=String($?.action?.value?.kind??"unknown"),Q=Z instanceof Error?Z.message:String(Z);await z1(String($?.__cardActionChatId??$?.context?.open_chat_id??""),`❌ ${J8(J)}失败: ${Q}`)}function ZB($){return $B.accept($)}async function JB($){let Z=$?.action,J=Z?.value;if(!J?.kind)return;let Q=$?.context?.open_chat_id??"",Y=$?.operator?.open_id??"";if(J.kind==="notify_callback")return await QB(J,Q,Y);let H=n1.get(Q);if(!H)return W$({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,Y);return W$({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})`),W$(f$(E0({title:"\uD83D\uDCCB 菜单选择",message:`已选择第 ${W+1} 项`,ok:!0})),!0)}catch(X){let V=X instanceof Error?X.message:String(X);return W$(f$(E0({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 i1(W)}case"model_select":{let W=await H.onModelSelect(String(J.model??""),String(J.panel_id??""),Y,J);return i1(W)}case"model_custom_prompt":{let W=await H.onModelCustomPrompt(String(J.source_id??""),String(J.panel_id??""),String($?.context?.open_message_id??""));return i1(W)}case"model_panel_cancel":{let W=await H.onModelPanelCancel(String(J.panel_id??""));return i1(W)}case"model_effort_select":{let W=await H.onModelEffortSelect(String(J.model??""),String(J.effort??""),String(J.panel_id??""),Y,String(J.provider??""));return i1(W)}case"ask":{if(J.custom){let V=(Z?.form_value??Z?.input??{})?.custom_answer??Z?.input_value??"",A=await H.onAskCustomAnswer(J.tool_use_id,J.question_idx??0,V,Y);return W$({toast:{type:A?"success":"error",content:A?"已回答":V.trim()?"问题已失效或答案未被接受":"请输入答案"}},A)}let W=await H.onAskAnswer(J.tool_use_id,J.question_idx??0,J.option_idx,Y);return W$({toast:{type:W?"success":"error",content:W?"已回答":"问题已失效或选项无效"}},W)}case"worktree_disband":{let W=await H.onWorktreeDisband(String(J.slug??""));return W$(f$(W.card),W.ok)}case"temp_fork_select":{let W=await H.onForkSelect(String(J.panel_id??""),String(J.choice_id??""),Y);return W$(W.replaceCard===!1?{toast:{type:"error",content:W.message}}:f$(E0({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??""),Y);return W$(W.replaceCard===!1?{toast:{type:"error",content:W.message}}:f$(E0({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??""),Y);if(W.replaceCard===!1)return W$({toast:{type:"error",content:W.message}},W.ok);if(!W.resumePresentation)throw Error("rs selection result missing trusted presentation snapshot");return W$(f$(E7({...W.resumePresentation,message:W.message,ok:W.ok})),W.ok,W.message)}case"tasklist_enable":{let W=await H.onTasklistEnable();return W$(f$(W.card),W.ok)}case"tasklist_delete_prompt":{let W=H.onTasklistDeletePrompt(String(J.guid??""));return W$(f$(W.card),W.ok)}case"tasklist_delete_confirm":{let W=await H.onTasklistDeleteConfirm(String(J.guid??""));return W$(f$(W.card),W.ok)}case"token_source_enable":{let{onTokenSourceEnable:W}=await Promise.resolve().then(() => (Q5(),J5));return await W(H,String(J.source_id??"")),{toast:{type:"info",content:"已处理"}}}case"agent_identity_page":return i1(H.onAgentIdentityPage(String(J.panel_id??""),J.page,Y))}return{toast:{type:"info",content:"unknown action"}}}async function QB($,Z,J){let Q=String($?.notify_id??""),Y=String($?.button_id??"");if(!Q)return{toast:{type:"error",content:"回调缺少 notify_id"}};let H=i9(Q);if(!H)return z(`notify-callback: notify_id=${Q.slice(0,12)}… not found (expired or pre-restart)`),{toast:{type:"error",content:"通知已过期或已移除"}};if(H.unknownAt)return V1(H,W$({toast:{type:"error",content:`外部回调可能已成功,但本地确认状态未知,已禁止自动重试${H.unknownReason?`: ${H.unknownReason}`:""}`}},!0));if(H.resolvedAt)return V1(H,{toast:{type:"info",content:"已处理过"}});if(RH(Q))return V1(H,{toast:{type:"info",content:"处理中…"}});let W=H.buttons.find((A)=>A.id===Y);if(!W)return z(`notify-callback: notify_id=${Q.slice(0,12)}… unknown button_id="${Y}"`),V1(H,W$({toast:{type:"error",content:"未知按钮"}},!1));if(!H.callbackUrl){try{F5(H.notifyId,W.id,J)}catch(A){return V1(H,W$({toast:{type:"error",content:`保存反馈结果失败: ${A instanceof Error?A.message:A}`}},!1))}return z(`notify-callback: notify_id=${Q.slice(0,12)}… resolved button="${Y}" by=${J.slice(0,8)}… (no callback, pull/display)`),V1(H,{...f$(n9(H,{status:"done",buttonId:W.id,text:W.text,operatorOpenId:J}))})}PH(H.notifyId);let X=TW(YB(H,W,J));X.catch((A)=>{z(`notify-callback: notify_id=${H.notifyId.slice(0,12)}… phase-2 rejected: ${A instanceof Error?A.message:A}`)});let V=X.then((A)=>A==="retry"?"retry":"complete").catch(()=>"retry");return V1(H,{toast:{type:"info",content:`⏳ 已选择:${W.text} · 推送中…`},__cardActionCompletion:V})}async function YB($,Z,J){try{let Q=n9($,{status:"processing",buttonId:Z.id,text:Z.text,operatorOpenId:J});try{await H0($.messageId,Q)}catch(X){z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-1 (processing) updateCard failed: ${X instanceof Error?X.message:X}`)}let Y=await MH($,Z,J),H=Y.ok?"complete":"retry",W;if(Y.ok){let X=FH($.notifyId,Z.id,J);if(X.state==="complete")W={status:"delivered",buttonId:Z.id,text:Z.text,operatorOpenId:J,reply:Y.reply};else{H="unknown",W={status:"unknown",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:X.detail},z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… callback succeeded but tombstone is UNKNOWN: ${X.detail}`);try{await z1($.chatId,`⚠️ 通知反馈的外部回调已成功,但本地确认状态未知;为避免重复副作用,已禁止自动重试。${X.detail}`)}catch(V){z(`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:Y.detail};try{let X=n9($,W);await H0($.messageId,X)}catch(X){z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-2 (final) presentation failed: ${X instanceof Error?X.message:X}`);try{await z1($.chatId,`⚠️ 通知反馈${H==="retry"?"失败且结果卡更新失败,可重新点击":"已执行,但结果卡更新失败"}: ${X instanceof Error?X.message:X}`)}catch(V){z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… final fallback receipt failed: ${V instanceof Error?V.message:V}`)}}return z(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… button="${Z.id}" ${H==="complete"?"delivered":H==="unknown"?"unknown/non-retryable":`failed: ${Y.detail}`} by=${J.slice(0,8)}…`),H}finally{LH($.notifyId)}}function w5($){return $.map((Z)=>typeof Z==="string"?Z:JSON.stringify(Z)).join(" ")}function HB(){if(process.platform==="win32"){z("debug: inject socket skipped on Windows (dev-only feature)");return}if(typeof Bun>"u"){z("debug: inject socket skipped (Bun runtime only — npm/Node build does not include it)");return}try{if(v5(b0))Z8(b0)}catch{}try{Bun.serve({unix:b0,fetch:async($)=>{if($.method!=="POST")return new Response("use POST",{status:405});if(g5)return new Response("daemon shutdown in progress",{status:503});let Z={};try{Z=await $.json()}catch{return new Response("bad json",{status:400})}if(!v5(t2))return new Response("no debug context yet — send `[DEBUG]hi` from Feishu first",{status:412});let J={};try{J=JSON.parse(cq(t2,"utf8"))}catch(X){return new Response(`ctx read failed: ${X}`,{status:500})}let Q=String(Z.text??"");if(!Q)return new Response("text required",{status:400});let Y=`【自动化测试】:${Q}`,H=await T(J.chat_id,Y);if(!H)return new Response("sendText failed — see daemon log",{status:502});let W={sender:{sender_id:{open_id:J.sender_open_id}},message:{message_id:H,chat_id:J.chat_id,message_type:"text",content:JSON.stringify({text:Q}),create_time:String(Date.now())}};if(z(`debug: inject text=${JSON.stringify(Q).slice(0,80)} msg_id=${H}`),!kW(W,"debug"))return new Response("daemon shutdown in progress",{status:503});return new Response(JSON.stringify({ok:!0,msg_id:H}),{headers:{"content-type":"application/json"}})}});try{gq(b0,384)}catch{}z(`debug: inject socket listening at ${b0}`)}catch($){z(`debug: socket bind failed: ${$}`)}}async function WB(){z(`lodestar-daemon: pid ${process.pid} starting`);let{buildTokenSourcesFromConfig:$}=await Promise.resolve().then(() => ($5(),oQ));$();let{refreshAllTokenSourceModels:Z}=await Promise.resolve().then(() => (_$(),VZ));await Z(),j6(),U6(),O6(),T6(),N6(),await L2(),setInterval(()=>{L2()},1800000);let{reconcileTasklistDeletions:J}=await Promise.resolve().then(() => (X5(),W5));try{await J()}catch(k){z(`tasklist deletion reconcile failed: ${k instanceof Error?k.message:k}`)}let Q,Y=Date.now(),H=0,W=!1,X=null,V=1500,A=90000,G=600000,_=3,q=null,B=0,R="",L=!1,F=(k)=>{z(`[ws] rebuild requested before WS init — ${k}`)},U=(k,u=0,p=!1)=>{let a=Date.now()+u;if(q){if(L||=p,a>=B){z(`[ws] rebuild already scheduled — ${k}`);return}clearTimeout(q)}B=a,R=k,L=p,q=setTimeout(()=>{let O=R,f=L;q=null,B=0,R="",L=!1,F(O,f)},u)},P={error:(k)=>z(`[ws-sdk error] ${w5(k)}`),warn:(k)=>{let u=w5(k);if(z(`[ws-sdk warn] ${u}`),u.includes("no pong/inbound"))U("ping-timeout: SDK liveness watchdog fired",2000,Date.now()-Y<G)},info:(k)=>z(`[ws-sdk] ${w5(k)}`),debug:(k)=>{},trace:(k)=>{}},j=new d1.EventDispatcher({}),S=()=>{if(Y=Date.now(),H=0,X)clearTimeout(X),X=null};j.register({"im.message.receive_v1":async(k)=>{if(S(),!kW(k))throw Error("daemon shutdown in progress")}}),j.register({"card.action.trigger":async(k)=>{return S(),ZB(k)}});let b=()=>new d1.WSClient({appId:w.feishu.app_id,appSecret:w.feishu.app_secret,loggerLevel:d1.LoggerLevel.info,logger:P,wsConfig:{pingTimeout:60},handshakeTimeoutMs:1e4,onReconnecting:()=>z("[ws] reconnecting — WS lost, SDK is retrying"),onReconnected:()=>m(),onError:(k)=>F(`SDK onError: ${k?.message??k}`)});F=(k,u=!1)=>{if(W){z(`[ws] rebuild skipped (already rebuilding) — ${k}`);return}if(q)clearTimeout(q),q=null,B=0;W=!0,H++,z(`[ws] rebuild #${H} (fresh WSClient) — ${k}`);let p=Q;try{p?.close({force:!0})}catch(a){z(`[ws] rebuild: old close failed: ${a}`)}if(Q=b(),Q.start({eventDispatcher:j}).catch((a)=>{z(`[ws] rebuild start failed: ${a}`),U(`fresh client start failed: ${a}`,V,u)}),W=!1,u)y()};let y=()=>{if(X)clearTimeout(X);let k=Date.now();X=setTimeout(()=>{if(X=null,Y>=k){H=0;return}if(H>=_){z(`[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}F(`verify: no event ${Math.round((Date.now()-k)/1000)}s after rebuild`,!0)},A)},m=()=>{let k=Date.now()-Y<G;z("[ws] reconnected — swapping in a fresh WSClient (cluster-routing precaution; "+`recentlyActive=${k})`),H=0,U("post-reconnect precaution",V,k)};Q=b(),Q.start({eventDispatcher:j}).catch((k)=>{z(`[ws] initial start failed: ${k}`),U(`initial start failed: ${k}`,V,!1)}),z(`lodestar-daemon: WS start requested, watching ${H$.size} groups`);let v=15000,g=2,E=0;setInterval(()=>{let{state:k}=Q.getConnectionStatus();if(k==="connected"){E=0;return}if(k==="failed"||k==="idle"){E=0,F(`watchdog: state=${k}`);return}if(E++,z(`[ws] watchdog: state=${k} (${E}/${g})`),E>=g)E=0,F(`watchdog: stuck in '${k}' ~${Math.round(v*g/1000)}s`)},v),HB(),DH(),kH({bind:w.notify.bind,port:w.notify.port,extraHandler:(k,u,p)=>ZW(k,u,p,{service:I5,authorizeSession:(a)=>{for(let O of n1.values())if(O.acceptsAgentCapability(a))return O;return null}})}),zW(),yH(),YW(),await dq()}var MW=!1,g5=!1,e9=null,X1=0,h5=null,UW=15000,OW=()=>{if(MW)return;MW=!0;try{let $=h5??c5();if(P2($),$.length>0)z(`alive marker: [${$.join(", ")}]`)}catch($){z(`alive marker write failed: ${$}`)}try{Z8(k$)}catch{}try{Z8(b0)}catch{}},n1,I5,i2,n2,pq,EW,lq,m5,aq=30000,l1,$B;var NW=N(()=>{_H();t();C$();M5();U5();U5();xH();oH();JW();HW();AW();U$();h();L$();_8();LW();FW();{let $=s2(k$);if($.state==="exit")console.error(`lodestar-daemon: already running (pid ${$.pid})`),process.exit(1);if(v5(k$))try{Z8(k$)}catch{}}Iq(uq(k$),{recursive:!0});a5(k$);process.on("exit",OW);process.on("SIGTERM",()=>{o1("SIGTERM",0)});process.on("SIGINT",()=>{o1("SIGINT",0)});if(process.platform==="win32")process.on("SIGBREAK",()=>{o1("SIGBREAK",0)});process.on("unhandledRejection",($)=>{z(`unhandledRejection: ${$ instanceof Error?$.stack??$.message:$}`),o1("unhandledRejection",1)});process.on("uncaughtException",($)=>{z(`uncaughtException: ${$.stack??$.message}`),o1("uncaughtException",1)});n1=new Map,I5=new k5,i2=new Set,n2=new C5,pq=new f5(30000),EW=new Set,lq=RW({actor:n2,key:($)=>String($?.message?.chat_id??""),execute:($,Z)=>rq($,Z)});m5=jW({registry:n1,createSession:($,Z)=>new W1($,Z,{onLifecycleChange:$8,onCreateTempSession:iq,onDisbandTempSession:nq,onCancelAgentRuns:(J,Q,Y)=>I5.cancelSessionRuns(J,Q,Y)}),ensureChatForSession:v6,disbandChatForSessionExact:g6,chatIdForSession:N1,clearSessionConversationState:C6,registerTempSessionLease:F6,hasTempSessionLease:M6,replaceTurnAnchors:I$,runExclusive:($,Z)=>n2.enqueue($,Z),log:z});l1=new Set;$B=PW({actor:n2,deduper:pq,scope:($)=>{if(String($?.action?.value?.kind??"").startsWith("agent_identity_"))return"__agent_identities_global__";return String($?.context?.open_chat_id??"")||"__notify_global__"},execute:JB,present:sq,presentExecutionFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");z(`handleCardAction ${J}: ${Z instanceof Error?Z.stack??Z.message:Z}`),await eq($,Z)},presentPresentationFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");z(`card-action presentation ${J}: ${Z instanceof Error?Z.message:Z}`),await z1(String($?.context?.open_chat_id??""),`⚠️ ${J8(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:($)=>{TW($)},onBackgroundError:($)=>{z(`card-action background: ${$ instanceof Error?$.stack??$.message:$}`)},responses:{accepted:($)=>({toast:{type:"info",content:`⏳ ${J8(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}})}});WB().catch(($)=>{z(`boot fatal: ${$}`),o1("boot fatal",1)})});L$();_8();import{existsSync as yW,unlinkSync as VB}from"node:fs";var n$={reset:"\x1B[0m",bold:"\x1B[1m",yellow:"\x1B[33m",green:"\x1B[32m",red:"\x1B[31m"};async function zB(){if(!yW(P$)){if(process.stdin.isTTY){console.log(),console.log(`${n$.bold}${n$.yellow}Lodestar: 未找到配置, 启动安装向导...${n$.reset}`);let{runSetup:Z}=await Promise.resolve().then(() => (H3(),Y3));await Z();return}console.error(`${n$.red}Lodestar: 未找到配置 ${P$}${n$.reset}`),console.error(`请在交互式 cmd / PowerShell 里运行 ${n$.green}lodestar-setup${n$.reset} 完成首次配置 (或直接运行 ${n$.green}lodestar-daemon${n$.reset} 也会触发同一个向导)。`),process.exit(1)}let $=s2(k$);if($.state==="exit")console.error(`${n$.yellow}Lodestar: 已经有一个 daemon 在运行 (pid ${$.pid})${n$.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(` • 误判 / 已经死了: 手删 ${k$} 后再跑`),process.exit(1);if(yW(k$))try{VB(k$)}catch{}await Promise.resolve().then(() => (NW(),XB))}zB().catch(($)=>{console.error("lodestar fatal:",$?.message??$),process.exit(1)});
|