@leviyuan/lodestar 0.15.0 → 0.15.1
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 +169 -170
- package/package.json +1 -1
package/dist/lodestar.js
CHANGED
|
@@ -1,39 +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
|
-
${
|
|
7
|
-
${
|
|
8
|
-
`)}function
|
|
9
|
-
${
|
|
10
|
-
`)}function
|
|
11
|
-
`),{path:J}}catch(Z){return{error:Z?.message??String(Z)}}}function
|
|
12
|
-
${
|
|
2
|
+
var _H=Object.defineProperty;var BH=($)=>$;function LH($,Z){this[$]=BH.bind(null,Z)}var q2=($,Z)=>{for(var J in Z)_H($,J,{get:Z[J],enumerable:!0,configurable:!0,set:LH.bind(Z,J)})};var T=($,Z)=>()=>($&&(Z=$($=0)),Z);import{homedir as FH}from"node:os";import{join as i}from"node:path";function x3($,Z,J){if($)return $;if(Z)return i(Z,"lodestar");return J}function UH(){if(T3)return i(process.env.APPDATA??i(P8,"AppData","Roaming"),"Lodestar");return i(P8,".config","lodestar")}function DH(){if(T3)return i(process.env.LOCALAPPDATA??i(P8,"AppData","Local"),"Lodestar");return i(P8,".local","share","lodestar")}var P8,T3,CZ,o,U$,C$,D1,NZ,yZ,SZ,kZ,wZ,A8,C3,N3,M8,bZ,v0,O8;var m$=T(()=>{P8=FH(),T3=process.platform==="win32";CZ=x3(process.env.LODESTAR_CONFIG_DIR,process.env.XDG_CONFIG_HOME,UH()),o=x3(process.env.LODESTAR_DATA_DIR,process.env.XDG_DATA_HOME,DH()),U$=process.env.LODESTAR_CONFIG??i(CZ,"config.toml"),C$=i(o,"daemon.pid"),D1=i(o,"daemon.log"),NZ=i(o,"session-chat-map.json"),yZ=i(o,"session-resume-map.json"),SZ=i(o,"session-turns-map.json"),kZ=i(o,"session-model-map.json"),wZ=i(o,"temp-session-leases.json"),A8=i(o,"tasklist-map.json"),C3=i(o,"context-window-cache.json"),N3=i(o,"notify-callbacks.json"),M8=i(o,"alive-on-shutdown.json"),bZ=i(o,"inbox"),v0=i(o,"debug.sock"),O8=i(o,"debug-context.json")});import{execSync as y3}from"node:child_process";import{readFileSync as S3,writeFileSync as PH}from"node:fs";function AH(){return process.argv[1]??`pid:${process.pid}`}function MH($){try{if(process.platform==="linux")return S3(`/proc/${$}/cmdline`,"utf8").replace(/\0/g," ").trim();if(process.platform==="darwin")return y3(`ps -p ${$} -o args=`,{encoding:"utf8",timeout:2000}).trim();if(process.platform==="win32")return y3(`powershell -NoProfile -Command "(Get-CimInstance Win32_Process -Filter 'ProcessId=${$}').CommandLine"`,{encoding:"utf8",timeout:5000}).trim()||null;return null}catch{return null}}function OH($,Z){if(!Number.isFinite($)||$<=0||!Z)return!1;let J=MH($);if(!J)return!1;if(process.platform==="win32")return J.toLowerCase().includes(Z.toLowerCase());return J.includes(Z)}function j8($){let Z="";try{Z=S3($,"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(OH(Q,Y))return{state:"exit",pid:Q};return{state:"continue"}}function k3($){PH($,`${process.pid}
|
|
4
|
+
${AH()}`)}var vZ=()=>{};import{chmodSync as jH,closeSync as fZ,fsyncSync as w3,mkdirSync as RH,openSync as b3,renameSync as EH,unlinkSync as TH,writeFileSync as xH}from"node:fs";import{randomUUID as CH}from"node:crypto";import{dirname as f3}from"node:path";function yH($){let Z=f3($);RH(Z,{recursive:!0,mode:NH})}function P1($,Z){yH($);let J=`${$}.${process.pid}.${CH()}.tmp`,Q=null;try{Q=b3(J,"wx",v3),xH(Q,Z),w3(Q),fZ(Q),Q=null,EH(J,$);try{jH($,v3)}catch{}if(process.platform!=="win32"){let Y=null;try{Y=b3(f3($),"r"),w3(Y)}catch{}finally{if(Y!==null)try{fZ(Y)}catch{}}}}catch(Y){if(Q!==null)try{fZ(Q)}catch{}try{TH(J)}catch{}throw Y}}function O$($,Z){P1($,JSON.stringify(Z,null,2)+`
|
|
5
|
+
`)}var v3=384,NH=448;var f0=()=>{};var m3={};q2(m3,{runSetup:()=>iH});import{execSync as SH,spawn as M1}from"node:child_process";import{existsSync as T8,mkdirSync as g3,readFileSync as kH}from"node:fs";import{createInterface as wH}from"node:readline/promises";import{delimiter as bH,dirname as vH,join as x8}from"node:path";import{homedir as fH}from"node:os";import{fileURLToPath as hH}from"node:url";async function h0($,Z={}){while(!0){let J=Z.default?`${_.dim} [${Z.default}]${_.reset}`:"",Q=(await A1.question(`${_.cyan}? ${_.reset}${$}${J}
|
|
6
|
+
${_.green}>${_.reset} `)).trim();if(!Q&&Z.default!==void 0)return Z.default;if(!Q&&Z.required){console.log(`${_.red}必填,请重新输入${_.reset}`);continue}return Q}}function IH($){let Z="═".repeat(58);console.log(`
|
|
7
|
+
${_.bold}${_.cyan}╔${Z}╗${_.reset}`),console.log(`${_.bold}${_.cyan}║ ${$.padEnd(54)} ║${_.reset}`),console.log(`${_.bold}${_.cyan}╚${Z}╝${_.reset}
|
|
8
|
+
`)}function R8($,Z,J){console.log(`
|
|
9
|
+
${_.bold}${_.yellow}[${$}/${Z}] ${J}${_.reset}
|
|
10
|
+
`)}function hZ($){return $.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}function E8($){let Z=process.env.PATH??"";if(!Z)return null;let J=process.platform==="win32"?[`${$}.cmd`,`${$}.bat`,`${$}.exe`,$]:[$];for(let Q of Z.split(bH)){if(!Q)continue;for(let Y of J){let V=x8(Q,Y);if(T8(V))return V}}return null}function h3($){let Z=process.platform==="win32"?"npm.cmd":"npm";return new Promise((J)=>{let Q=M1(Z,["install","-g",`${$}@latest`],{stdio:"inherit",shell:process.platform==="win32"});Q.on("exit",(Y)=>J(Y===0)),Q.on("error",()=>J(!1))})}function I3($){try{let Z=SH(`"${$}" login status 2>&1`,{timeout:1e4}).toString();return/Logged in using ChatGPT/i.test(Z)}catch{return!1}}async function gH($){return new Promise((Z)=>{let J=M1($,["login"],{stdio:"inherit",shell:process.platform==="win32"});J.on("exit",(Q)=>Z(Q===0)),J.on("error",()=>Z(!1))})}function mH(){return process.env.CLAUDE_CONFIG_DIR||x8(fH(),".claude")}async function cH($){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((q)=>typeof q?.display_name==="string"&&q.display_name?q.display_name:String(q?.id??"")).filter(Boolean);if(!Q.length)return null;let Y=(q)=>{let B=q.match(/(\d+(?:\.\d+)?)/);return B?Number(B[1]):-1},V=(q)=>q.replace(/-Turbo|-Air$/i,""),H=[...Q.filter((q)=>!/-Turbo|-Air/i.test(q))].sort((q,B)=>Y(B)-Y(q)),W=H[0],z=H[H.length-1],G={};if(W)G.ANTHROPIC_DEFAULT_OPUS_MODEL=`${W}[1m]`,G.ANTHROPIC_DEFAULT_SONNET_MODEL=`${W}[1m]`;if(z&&V(z)!==V(W))G.ANTHROPIC_DEFAULT_HAIKU_MODEL=z;return Object.keys(G).length?G:null}catch{return null}}async function uH($){try{let Z=mH();g3(Z,{recursive:!0});let J=x8(Z,"settings.json"),Q={};if(T8(J)){let H=kH(J,"utf8");try{let W=JSON.parse(H);if(!W||typeof W!=="object"||Array.isArray(W))return{error:`${J} 内容不是 JSON 对象, 拒绝覆盖, 请手动检查`};Q=W}catch{return{error:`${J} 解析失败 (JSON 语法错), 拒绝覆盖, 请手动修复后重跑`}}}let Y=Q.env&&typeof Q.env==="object"&&!Array.isArray(Q.env)?Q.env:{},V={ANTHROPIC_AUTH_TOKEN:$,ANTHROPIC_BASE_URL:"https://open.bigmodel.cn/api/anthropic",API_TIMEOUT_MS:"3000000",CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:"1"},X=await cH($);if(X)Object.assign(V,X);return Q.env={...Y,...V},P1(J,JSON.stringify(Q,null,2)+`
|
|
11
|
+
`),{path:J}}catch(Z){return{error:Z?.message??String(Z)}}}function pH($){try{if(process.platform==="win32")M1(process.env.ComSpec??"cmd.exe",["/c","start",'""',$],{detached:!0,stdio:"ignore",windowsHide:!0}).unref();else if(process.platform==="darwin")M1("open",[$],{detached:!0,stdio:"ignore"}).unref();else M1("xdg-open",[$],{detached:!0,stdio:"ignore"}).unref()}catch{}}async function lH($,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 dH(){try{let $=vH(hH(import.meta.url)),Z=x8($,"lodestar.js");if(!T8(Z))return{error:`找不到 daemon bundle: ${Z}`};let J=M1(process.execPath,[Z],{detached:!0,stdio:"ignore",windowsHide:!0});return J.unref(),{pid:J.pid}}catch($){return{error:$?.message??String($)}}}async function iH(){if(!process.stdin.isTTY)console.error(`${_.red}lodestar-setup: stdin 不是 TTY,无法交互式输入。${_.reset}`),console.error("请直接在 cmd / PowerShell / Terminal 里跑,不要 pipe 或重定向 stdin。"),process.exit(1);if(T8(U$)){if(console.log(`${_.yellow}发现已有配置: ${U$}${_.reset}`),(await h0("覆盖? (y/N)",{default:"n"})).toLowerCase()!=="y"){console.log("已取消"),A1.close();return}}IH("Lodestar 安装向导"),console.log("Lodestar 把 Feishu (飞书) 群聊接到 AI agent。"),console.log("默认后端是 Claude Code; Codex 是可选第二后端, 群里发 model 一键切换。"),console.log("每个群对应一个项目目录, agent 在那里跑、能读写文件。"),console.log(),console.log(`${_.yellow}⚠ Claude 官方限制:${_.reset}`),console.log(` ${_.bold}Claude 订阅 (Pro/Max OAuth 登录) 不支持本项目${_.reset},`),console.log(" 必须走 API 方式 —— 推荐 GLM Coding Plan, 或自备 Anthropic API key。"),console.log(),console.log("本向导依次做 4 件事:"),console.log(` ${_.dim}1) 确保 Claude Code CLI 已装好${_.reset}`),console.log(` ${_.dim}2) GLM Coding Plan API key (推荐, 可选) + Codex (可选)${_.reset}`),console.log(` ${_.dim}3) Feishu 自建应用 (含权限 / 事件 / 发版 + 凭据测试)${_.reset}`),console.log(` ${_.dim}4) 工作目录, 自动启动 daemon${_.reset}`),console.log(),await A1.question(`${_.dim}按 Enter 开始 (Ctrl+C 退出)...${_.reset}`),R8(1,4,"准备 Claude Code CLI");let $=E8("claude");if($)console.log(`${_.green}✓ claude CLI 已就位${_.reset}: ${_.dim}${$}${_.reset}`);else{if(console.log(`${_.yellow}未在 PATH 找到 claude CLI, 自动安装...${_.reset}`),console.log(`${_.dim}运行: npm install -g @anthropic-ai/claude-code@latest${_.reset}`),console.log(),!await h3("@anthropic-ai/claude-code"))console.error(`
|
|
12
|
+
${_.red}安装失败。${_.reset}`),console.error("请手动运行后再开向导:"),console.error(` ${_.cyan}npm install -g @anthropic-ai/claude-code@latest${_.reset}`),console.error(` ${_.cyan}lodestar-setup${_.reset}`),A1.close(),process.exit(1);$=E8("claude"),console.log(`${_.green}✓ 安装完成${_.reset}: ${_.dim}${$??"(应该装好了, 但 PATH 找不到 — 重开终端再试)"}${_.reset}`)}console.log(),console.log(`${_.dim}下一步可选配 GLM Coding Plan 自动写入路由; 不配则用本机 Claude Code 现有配置。${_.reset}`),console.log(`${_.dim}记住: 别用 \`claude\` 走订阅 OAuth 登录 —— 订阅不支持本项目, 要用 API key。${_.reset}`),R8(2,4,"GLM Coding Plan (推荐, 可选)"),console.log("GLM Coding Plan 给 Claude Code 接 GLM 系列模型 (支持 1M token 上下文, 中文友好)。"),console.log("订阅后在智谱开放平台拿一个 API key, 粘到下面 —— 向导自动写进 ~/.claude/settings.json。"),console.log(` ${_.dim}拿 key: https://open.bigmodel.cn → 控制台 → API Keys${_.reset}`),console.log(` ${_.dim}不给也行: 以本机 Claude Code 现有配置启动 (确保是 API key 方式, 非订阅)。${_.reset}`),console.log();let Z=await h0("GLM API key (直接回车跳过)",{});if(Z){let B=await uH(Z);if("path"in B)console.log(`${_.green}✓ GLM 路由已写入${_.reset}: ${_.dim}${B.path}${_.reset}`),console.log(`${_.dim}模型 slots 按端点当前列表自动选取(最新一代 opus/sonnet, 1M ctx)${_.reset}`);else console.log(`${_.red}✗ 写入失败:${_.reset} ${B.error}`),console.log(`${_.dim}跳过 GLM 配置, 以本机 Claude Code 现有配置启动。${_.reset}`)}else console.log(`${_.dim}已跳过 GLM, 以本机 Claude Code 现有配置启动。${_.reset}`);if(console.log(),console.log(`${_.bold}Codex (可选第二后端)${_.reset}`),console.log(` ${_.dim}想用 Codex 的话, 登录 ChatGPT 订阅即可, 模型/effort 走 ~/.codex/config.toml, 群里发 model 切换。${_.reset}`),(await h0("现在顺便配置 Codex 后端吗?",{default:"n"})).toLowerCase()==="y"){let B=E8("codex");if(!B){if(console.log(`${_.dim}未找到 codex CLI, 安装 @openai/codex...${_.reset}`),await h3("@openai/codex"))B=E8("codex")}if(B&&I3(B))console.log(`${_.green}✓ Codex 已登录 ChatGPT${_.reset}`);else if(B)if(console.log(`${_.dim}启动 \`codex login\`...${_.reset}`),await gH(B)&&I3(B))console.log(`${_.green}✓ Codex 已登录 ChatGPT${_.reset}`);else console.log(`${_.yellow}Codex 登录未完成 — 不影响默认 Claude 后端; 需要时随时跑 codex login。${_.reset}`);else console.log(`${_.yellow}Codex 安装失败 — 不影响默认 Claude 后端; 需要时手动 npm i -g @openai/codex。${_.reset}`)}else console.log(`${_.dim}已跳过 Codex (需要时随时跑 codex login, 群里发 model 切)。${_.reset}`);R8(3,4,"Feishu 自建应用");let Q="https://open.feishu.cn/app";console.log("打开飞书开放平台 (浏览器):"),console.log(` ${_.cyan}${Q}${_.reset}`),pH(Q),console.log(`${_.dim}(如果浏览器没自动开, 复制上面 URL 粘到浏览器)${_.reset}`),console.log(),console.log(`${_.bold}详细操作步骤:${_.reset}`),console.log(),console.log(` ${_.bold}① 创建应用${_.reset}`),console.log(` 点 "创建企业自建应用", 填名字 (如 ${_.dim}Lodestar${_.reset}), logo 随意。`),console.log(),console.log(` ${_.bold}② 添加机器人能力${_.reset}`),console.log(` 左侧菜单 "${_.cyan}添加应用能力${_.reset}" → 找到 "机器人" → 点 "${_.bold}添加${_.reset}" 按钮。`),console.log(),console.log(` ${_.bold}③ 申请权限 (左侧 "${_.cyan}权限管理${_.reset}" → "${_.bold}开通权限${_.reset}")${_.reset}`),console.log(` ${_.yellow}缺一个都会让 daemon 启动后默默丢消息, 一定要全开。${_.reset}`),console.log(` ${_.dim}消息类:${_.reset}`),console.log(` • ${_.bold}im:message:send_as_bot${_.reset} ${_.dim}# 以机器人身份发消息${_.reset}`),console.log(` • ${_.bold}im:message${_.reset} ${_.dim}# 接收/操作消息 (核心)${_.reset}`),console.log(` • ${_.bold}im:chat${_.reset} ${_.dim}# 读/写群信息 (匹配群名 ↔ 项目目录)${_.reset}`),console.log(` • ${_.bold}im:chat:create${_.reset} ${_.dim}# wt: 自动创建 worktree 群${_.reset}`),console.log(` • ${_.bold}im:chat:delete${_.reset} ${_.dim}# wt: 解散 worktree 群${_.reset}`),console.log(` • ${_.bold}im:chat.members:read${_.reset} ${_.dim}# wt: 判断发起人是否已在群内${_.reset}`),console.log(` • ${_.bold}im:chat.members:write_only${_.reset} ${_.dim}# wt: 把发起人拉进已有 worktree 群${_.reset}`),console.log(` • ${_.bold}im:resource${_.reset} ${_.dim}# 上传/下载附件 (图文双向)${_.reset}`),console.log(` • ${_.bold}im:message.urgent${_.reset} ${_.dim}# 加急推送 (锁屏通知 / Ask)${_.reset}`),console.log(` • ${_.bold}im:message.group_msg${_.reset} ${_.dim}# 敏感: 接收群里所有消息${_.reset}`),console.log(` ${_.dim}└ 关键: 没它机器人只收 @ 自己的消息, 拿不到群里其他对话, 一定要开${_.reset}`),console.log(` ${_.dim}└ 敏感权限要走审批: 申请时填用途, 个人开发者通常秒过${_.reset}`),console.log(` • ${_.bold}im:message.group_at_msg:readonly${_.reset} ${_.dim}# 读 @ 机器人消息 (兜底)${_.reset}`),console.log(` ${_.dim}卡片类 (Card Kit):${_.reset}`),console.log(` • ${_.bold}cardkit:card:read${_.reset} ${_.dim}# 读卡片状态${_.reset}`),console.log(` • ${_.bold}cardkit:card:write${_.reset} ${_.dim}# 创建/更新卡片 (流式渲染核心)${_.reset}`),console.log(),console.log(` ${_.bold}④ 订阅事件 (左侧 "${_.cyan}事件与回调${_.reset}", 拆两个子页:)${_.reset}`),console.log(` ${_.dim}a)${_.reset} ${_.bold}事件配置${_.reset} 页:`),console.log(` ${_.yellow}• "订阅方式" → 选 "长连接" → 点保存${_.reset}`),console.log(` • 添加事件: ${_.bold}im.message.receive_v1${_.reset} ${_.dim}# 收群消息${_.reset}`),console.log(` ${_.dim}b)${_.reset} ${_.bold}回调配置${_.reset} 页:`),console.log(` ${_.yellow}• "订阅方式" → 选 "长连接" → 点保存${_.reset}`),console.log(` • 添加事件: ${_.bold}card.action.trigger${_.reset} ${_.dim}# 卡片按钮点击回调${_.reset}`),console.log(),console.log(` ${_.bold}⑤ 发布版本${_.reset}`),console.log(` 页面顶部 "${_.bold}创建版本${_.reset}" → 滚到底点 "${_.bold}保存${_.reset}" → 弹框点 "${_.bold}发布${_.reset}"。`),console.log(` ${_.yellow}没发版的应用收不到任何事件 — 这步九成新手会忘!${_.reset}`),console.log(),console.log(` ${_.bold}⑥ 拿凭据${_.reset}`),console.log(` 左侧 "凭证与基础信息" → 顶部 ${_.bold}App ID${_.reset} (${_.dim}cli_...${_.reset}) 和 ${_.bold}App Secret${_.reset}, 待会粘到下面。`),console.log(),console.log(` ${_.bold}⑦ 把机器人拉进群${_.reset}`),console.log(" 想用的飞书群 → 群设置 → 群机器人 → 添加机器人 → 选你的应用。"),console.log(` ${_.yellow}群名要等于 projects_root 下的项目目录名${_.reset} (下一步设, 默认是用户主目录)。`),console.log();let Y="",V="";while(!0){Y=await h0("App ID (以 cli_ 开头)",{required:!0}),V=await h0("App Secret",{required:!0}),console.log(`${_.dim}测试中... (调 tenant_access_token endpoint)${_.reset}`);let B=await lH(Y,V);if(B.ok){console.log(`${_.green}✓ Feishu 凭据测试通过${_.reset}`);break}if(console.log(`${_.red}✗ 测试失败:${_.reset} ${B.error}`),console.log(`${_.dim}最常见原因: app_id / app_secret 抄错, 或应用还没 "发布上线" (步骤 ⑤)。${_.reset}`),console.log(),(await h0("重新填? (Y/n)",{default:"y"})).toLowerCase()==="n")console.log(`${_.yellow}已取消, 配置未写盘。${_.reset}`),A1.close(),process.exit(1)}R8(4,4,"工作目录 + 启动"),console.log("每个 Feishu 群对应 projects_root 下同名的目录。"),console.log();let X=process.platform==="win32"?process.env.USERPROFILE??"C:\\Users\\Default":process.env.HOME??"/root",H=await h0("projects_root",{default:X});g3(CZ,{recursive:!0});let W=["# Lodestar config — generated by `lodestar-setup`","# Edit by hand or re-run setup to overwrite.","","[feishu]",`app_id = "${hZ(Y)}"`,`app_secret = "${hZ(V)}"`,"","[runtime]",`projects_root = "${hZ(H)}"`,""];P1(U$,W.join(`
|
|
13
13
|
`)),console.log(`
|
|
14
|
-
${
|
|
15
|
-
${
|
|
16
|
-
`)){let Y=
|
|
14
|
+
${_.green}${_.bold}✓ 配置已写入${_.reset}`),console.log(` ${_.cyan}${U$}${_.reset}`),console.log(`
|
|
15
|
+
${_.bold}启动 daemon...${_.reset}`);let z=dH(),G=process.platform==="win32"?"\\":"/",q=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(z.pid)console.log(`${_.green}✓ daemon 已在后台启动${_.reset} (pid ${z.pid})`),console.log(),console.log(`${_.bold}最后一步: 在 Feishu 验证${_.reset}`),console.log(" ① 把机器人拉进任意飞书群"),console.log(` ② 群名 = ${_.cyan}${H}${G}<群名>${_.reset} 下的目录名 (新群第一条消息会自动建)`),console.log(" ③ 在群里发任意一条消息, 默认由 Claude 接管"),console.log(` ${_.dim}(群里发 model 可选择已配置账号、动态模型和 effort)${_.reset}`),console.log(),console.log("日志 (按日滚动, 保留近 7 天):"),console.log(` ${_.cyan}${q}${_.reset}`),console.log(),console.log(`${_.dim}若长期跑后台, Linux 配 systemd --user,macOS 配 launchd,Windows 配任务计划程序。${_.reset}`);else console.log(`${_.yellow}启动失败: ${z.error}${_.reset}`),console.log(`手动运行: ${_.cyan}lodestar-daemon${_.reset}`);console.log(),A1.close()}var _,A1;var c3=T(()=>{m$();f0();_={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",green:"\x1B[32m",yellow:"\x1B[33m",cyan:"\x1B[36m",red:"\x1B[31m"},A1=wH({input:process.stdin,output:process.stdout})});import{readFileSync as nH}from"node:fs";import{homedir as p3}from"node:os";function u3($){return $.replace(/^~(?=\/|$)/,p3())}function oH($){let Z={_:{}},J="_";for(let Q of $.split(`
|
|
16
|
+
`)){let Y=rH(Q).trim();if(!Y)continue;let V=Y.match(/^\[([^\]]+)\]$/);if(V){J=V[1].trim(),Z[J]??={};continue}let X=Y.match(/^([\w.-]+)\s*=\s*(.+)$/);if(X){let H=X[2].trim(),W=H.startsWith('"')&&H.endsWith('"'),z=H.startsWith("'")&&H.endsWith("'");if(W||z){if(H=H.slice(1,-1),W)H=H.replace(/\\([\\"])/g,"$1")}Z[J][X[1]]=H}}return Z}function rH($){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 l3(){let $;try{$=nH(U$,"utf8")}catch(D){throw process.stderr.write(`lodestar: cannot read config at ${U$}
|
|
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
|
-
`),
|
|
23
|
-
`;if(process.stderr.write(J),!
|
|
22
|
+
`),D}let Z=oH($),J=Z.feishu?.app_id,Q=Z.feishu?.app_secret;if(!J||!Q)throw Error(`lodestar: ${U$} is missing [feishu].app_id / [feishu].app_secret`);let Y=u3(Z.runtime?.projects_root??p3()),V=(Z.runtime?.live_elapsed??"bucket").trim().toLowerCase();if(V!=="bucket"&&V!=="second")throw Error(`lodestar: [runtime].live_elapsed must be "bucket" or "second", got "${Z.runtime?.live_elapsed}"`);let X=V,H=Z.notify?.bind??"127.0.0.1",W=Z.notify?.port??"9876";if(!/^\d+$/.test(W.trim()))throw Error(`lodestar: [notify].port must be an integer, got "${W}"`);let z=Number.parseInt(W,10);if(!Number.isFinite(z)||z<=0||z>65535)throw Error(`lodestar: [notify].port must be 1..65535, got "${W}"`);let G=(D)=>{let P=Z[D]??{},M={};for(let[x,y]of Object.entries(P))if(typeof y==="string"&&y.length>0)M[x]=y;return M},q=()=>{let D={};for(let[P,M]of Object.entries(Z)){if(!P.startsWith("claude.models."))continue;let y=P.slice(14).trim();if(!y)continue;let N={};for(let[m,h]of Object.entries(M)){if(typeof h!=="string"||h.length===0)continue;let w=m.trim();if(w==="display_name"||w==="description"||w==="model")N[w]=h}D[y]=N}return D},B=()=>{let D={},P="projects.";for(let[M,x]of Object.entries(Z)){if(!M.startsWith("projects."))continue;let y=M.slice(9).trim();if(!y)continue;let N={};for(let[m,h]of Object.entries(x)){if(typeof h!=="string"||h.length===0)continue;switch(m.trim()){case"cwd":N.cwd=h;break;case"setting_sources":N.settingSources=h;break;case"strict_mcp":N.strictMcp=h==="true";break;case"tools":N.tools=h;break;case"load_project_mcp":N.loadProjectMcp=h==="true";break}}D[y]=N}return D},L=()=>{let D={},P="token_source.";for(let[M,x]of Object.entries(Z)){if(!M.startsWith("token_source."))continue;let y=M.slice(13).trim();if(!y)continue;let N={};for(let[m,h]of Object.entries(x)){if(typeof h!=="string"||h.length===0)continue;let w=m.trim();if(w==="default")N.default=h==="true";else if(w==="agent"||w==="display"||w==="auth"||w==="base_url"||w==="auth_token"||w==="api_key"||w==="bin"||w==="model"||w==="effort"||w==="models"||w==="slots"||w==="usage")N[w]=h}D[y]=N}return D},F=G("codex.env"),U=G("claude.env"),R=Z.claude?.bin?u3(Z.claude.bin):void 0;return{feishu:{app_id:J,app_secret:Q},runtime:{projects_root:Y,live_elapsed:X},notify:{bind:H,port:z},codex:{env:F},claude:{bin:R,env:U,models:q()},projects:B(),token_sources:L()}}function d3(){f.token_sources=l3().token_sources}var f;var N$=T(()=>{m$();f=l3()});import{appendFileSync as o3,mkdirSync as aH,readdirSync as tH,unlinkSync as r3,existsSync as i3,statSync as sH,renameSync as eH,readFileSync as $W}from"node:fs";import{join as a3}from"node:path";function mZ($="development"){return $!=="test"}function t3($){let Z=$.getFullYear(),J=String($.getMonth()+1).padStart(2,"0"),Q=String($.getDate()).padStart(2,"0");return`${Z}-${J}-${Q}`}function s3($,Z=o){return a3(Z,`${IZ}${t3($)}${gZ}`)}function JW($){if(!$.startsWith(IZ)||!$.endsWith(gZ))return null;let Z=$.slice(IZ.length,$.length-gZ.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 e3($,Z=new Date,J=ZW){let Q;try{Q=tH($)}catch{return 0}let Y=new Date(Z.getFullYear(),Z.getMonth(),Z.getDate()),V=0;for(let X of Q){let H=JW(X);if(!H)continue;if(Math.round((Y.getTime()-H.getTime())/86400000)<J)continue;try{r3(a3($,X)),V++}catch{}}return V}function QW($=new Date){try{if(!i3(D1))return;let Z=sH(D1);if(!Z.isFile()||Z.size===0)return;let J=s3(Z.mtime);if(i3(J)){o3(J,$W(D1)),r3(D1);return}eH(D1,J)}catch{}}function K($){let Z=new Date,J=`[${Z.toISOString()}] ${$}
|
|
23
|
+
`;if(process.stderr.write(J),!mZ())return;try{let Q=t3(Z);if(n3!==Q)n3=Q,e3(o,Z);o3(s3(Z),J)}catch{}}var ZW=7,IZ="daemon-",gZ=".log",n3=null;var v=T(()=>{m$();if(mZ())try{aH(o,{recursive:!0})}catch{}if(mZ()){try{QW()}catch{}try{e3(o)}catch{}}});function r($){return typeof $==="string"&&$?$:void 0}function I($){return $!=null&&typeof $==="object"?$:null}function V0($){if($==null||$==="")return"-";return String($).replace(/\s+/g," ").slice(0,300)}function C8($){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 VW($){let Z=$.slice(0,pZ),J=$.length>Z.length?`,...+${$.length-Z.length}`:"";return`[${Z.join(",")}${J}]`}function XW($){let Z=I($);if(!Z)return null;let J=I(Z.event),Q=I(Z.payload);return I(Z.item)??I(Z.responseItem)??I(Z.rawItem)??I(J?.item)??I(J?.responseItem)??I(J?.rawItem)??I(Q?.item)??I(Q?.responseItem)??I(Q?.rawItem)??(_2(Z.type)?Z:null)??(J&&_2(J.type)?J:null)??(Q&&_2(Q.type)?Q:null)}function HW($){let Z=[],J=new WeakSet,Q=(Y,V,X)=>{if(Z.length>=pZ||X>6)return;if(Array.isArray(Y)){if(V)Z.push(`${V}[]`);if(Y.length>0)Q(Y[0],V?`${V}[]`:"[]",X+1);return}if(Y==null||typeof Y!=="object")return;if(J.has(Y))return;J.add(Y);for(let H of Object.keys(Y)){if(Z.length>=pZ)return;let W=V?`${V}.${H}`:H;Z.push(W),Q(Y[H],W,X+1)}};return Q($,"",0),Z}function lZ($){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>uZ)return`${Y.slice(0,uZ)}...<truncated ${Y.length-uZ} 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>cZ)return`${J.slice(0,cZ)}...<truncated ${J.length-cZ} chars>`;return J}function j$($,Z){let J=I(Z),Q=J?I(J.params):null,Y=J?I(J.item)??I(Q?.item):null,V=J?r(J.method)??"-":"-";K([`codex-process: APP_SERVER_UNHANDLED_${$}`,`method=${V0(V)}`,`rootKeys=${C8(J)}`,`itemKeys=${C8(Y)}`,`payload=${lZ(Z)}`].join(" "))}function dZ($,Z,J){let Q=I(Z),Y=XW(Z),V=[`phase=${V0(J.phase??"event")}`,`method=${V0($)}`,`sourceMethod=${V0(J.sourceMethod)}`,`sourceType=${V0(J.sourceType)}`,`sessionId=${V0(J.sessionId)}`,`threadId=${V0(J.threadId)}`,`turnId=${V0(J.turnId)}`,`itemId=${V0(J.itemId)}`].join(" ");if(K(`codex-process: CONTEXT_COMPACTION_EVENT ${V} rootKeys=${C8(Q)} itemKeys=${C8(Y)}`),K(`codex-process: CONTEXT_COMPACTION_PATHS ${V} paths=${VW(HW(Z))}`),Y)K(`codex-process: CONTEXT_COMPACTION_ITEM ${V} item=${lZ(Y)}`);K(`codex-process: CONTEXT_COMPACTION_PAYLOAD ${V} payload=${lZ(Z)}`)}function _2($){if(typeof $!=="string")return null;return YW.has($)?$:null}function WW($,Z){if(Z==="item/started")return"start";if(Z==="item/completed"||Z==="rawResponseItem/completed")return"end";if($==="compacted")return"start";if($==="context_compacted"||$7.has(Z))return"end";return"event"}function iZ($,Z){return Z7($,I(Z)??{})}function nZ($){let Z=I($);if(!Z)return null;let J=r(Z.method)??r(Z.type)??"raw_message";return Z7(J,Z)}function Z7($,Z){let J=I(Z.payload),Q=[Z,I(Z.event),J,I(Z.item),I(Z.responseItem),I(Z.rawItem)].filter((W)=>W!=null),Y=null;for(let W of Q)if(Y=_2(W.type),Y)break;if(!$7.has($)&&!Y)return null;let V=I(Z.item)??I(Z.responseItem)??I(Z.rawItem),X=Y==="compacted"&&J?J:V&&_2(V.type)?V:Z,H=I(X.item)??I(X.responseItem)??I(X.rawItem)??V??{};return{...X,threadId:r(X.threadId)??r(X.thread_id)??r(Z.threadId)??r(Z.thread_id),turnId:r(X.turnId)??r(X.turn_id)??r(Z.turnId)??r(Z.turn_id),itemId:r(X.itemId)??r(X.item_id)??r(H.id)??r(H.itemId)??r(H.item_id),timestamp:r(Z.timestamp)??r(X.timestamp),recordType:r(Z.type),phase:WW(Y,$),sourceMethod:$,sourceType:Y??$}}var $7,YW,cZ=200000,uZ=50000,pZ=400;var oZ=T(()=>{v();$7=new Set(["thread/compacted","context/compacted","context_compacted","contextCompacted"]),YW=new Set(["compacted","compaction","compaction_trigger","context_compacted","context_compaction","contextCompaction","ContextCompaction"])});function B2($){return $!=null&&typeof $==="object"?$:null}function X0($){return typeof $==="number"&&Number.isFinite($)?$:void 0}function J7($){return Object.values($).some((Z)=>typeof Z==="number"&&Number.isFinite(Z))}function N8($,Z){return $?X0($[Z]):void 0}function O1($){let Z=B2($);if(!Z)return null;let J=B2(Z.inputTokensDetails)??B2(Z.input_tokens_details),Q=B2(Z.outputTokensDetails)??B2(Z.output_tokens_details),Y={total_tokens:X0(Z.totalTokens??Z.total_tokens),input_tokens:X0(Z.inputTokens??Z.input_tokens),output_tokens:X0(Z.outputTokens??Z.output_tokens),reasoning_output_tokens:X0(Z.reasoningOutputTokens??Z.reasoning_output_tokens??N8(Q,"reasoningTokens")??N8(Q,"reasoning_tokens")),cache_creation_input_tokens:X0(Z.cacheCreationInputTokens??Z.cache_creation_input_tokens),cache_read_input_tokens:X0(Z.cachedInputTokens??Z.cached_input_tokens??Z.cacheReadInputTokens??Z.cache_read_input_tokens??N8(J,"cachedTokens")??N8(J,"cached_tokens"))};return J7(Y)?Y:null}function rZ($,Z){let J=(Y)=>{let V=X0($?.[Y]),X=X0(Z?.[Y]);if(V===void 0&&X===void 0)return;return Math.max(0,(V??0)-(X??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 J7(Q)?Q:null}function aZ($){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 Q7($){let Z=$.trim();if(Z.length<2)return Z;let J=y8[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 sZ($){let Z=KW(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(),V=Y?Z.split(`
|
|
25
25
|
`).slice(1).join(`
|
|
26
|
-
`).trimStart():Z;return{description:Y,command:V||Z}}function
|
|
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
|
|
29
|
-
`).replace(/\s*"\s*'\$\(([^)]*)\)'/g,(X,
|
|
30
|
-
`)}var
|
|
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){K(`codex-process: bad json: ${J.slice(0,200)} (${Y})`);continue}try{this.handleMessage(Q)}catch(Y){K(`codex-process: dispatch error: ${JSON.stringify(Q).slice(0,200)} (${Y})`)}}}
|
|
32
|
-
`))>=0){let J=this.stderrBuf.slice(0,Z);if(this.stderrBuf=this.stderrBuf.slice(Z+1),J.trim())K(`codex-process[stderr]: ${J}`)}}handleMessage($){if(Object.prototype.hasOwnProperty.call($,"id")&&!$.method){let J=this.pending.get($.id);if(!J){K(`codex-process: response for unknown id=${$.id}`);return}if(this.pending.delete($.id),clearTimeout(J.timeout),$.error)J.reject(Error(typeof $.error==="string"?$.error:JSON.stringify($.error)));else J.resolve($.result);return}if(Object.prototype.hasOwnProperty.call($,"id")&&$.method){this.handleServerRequest($);return}if($.method){this.handleNotification($.method,$.params??{});return}let Z=bZ($);if(Z){let J=this.withSessionId(Z);kZ(Z.sourceMethod??"raw_message",$,J),this.emit("context_compacted",J);return}f$("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=wZ($,Z);if(J){let Q=this.withSessionId(J);kZ($,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(l$(Q?.effort))this.lastEffort=Q.effort;return}case"thread/tokenUsage/updated":{let Q=L1(Z.tokenUsage?.last);if(Q)this.lastUsage=Q,this.lastResult.usage=this.lastUsage;else K("codex-process: tokenUsage notification missing last breakdown");this.lastTotalUsage=L1(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":{this.recordTurnStarted(Z.turn,Z.threadId??this.sessionId,"turn/started notification");return}case"turn/completed":{this.flushRolloutImageGenerations();let Q=Z.turn??{},Y=typeof Q.id==="string"&&Q.id?Q.id:null;if(Y)this.markTurnStartTerminal(Y),this.rememberFinishedTurn(Y);else f$("TURN_COMPLETED_MISSING_ID",{method:$,params:Z});let V=Q.status,X=V==="failed"||!!Q.error,z=V==="completed"&&!X&&!!Y;this.lastCompletedTurnId=z?Y:null;let H=X?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:H,is_error:X},this.currentTurnId=null,this.emit("result",{subtype:H,is_error:X,duration_ms:this.lastResult.duration_ms,usage:this.lastUsage,turn_id:Y,checkpoint:z&&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 K("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});else f$("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":{K(`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":{K(`codex-process: ${$}: ${Z.summary??Z.message??JSON.stringify(Z).slice(0,200)}`);return}case"error":{K(`codex-process: server error: ${JSON.stringify(Z).slice(0,500)}`),this.emit("error",Error(Z.message??Z.summary??"codex app-server error"));return}}f$("NOTIFICATION",{method:$,params:Z}),this.emit("raw",{method:$,params:Z})}handleItemStarted($){let Z=$?.item;if(!Z?.id){f$("ITEM_STARTED_MISSING_ID",{method:"item/started",params:$});return}if(this.feedCollabItem(Z,"started",$))return;let J=uZ(Z,this.opts.workDir);if(!J){f$("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){f$("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});return}if(this.feedCollabItem(Z,"completed",$))return;let J=r3(Z,this.opts.workDir,this.sessionId??void 0);if(!J){f$("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)??Z.slice(0,8)}),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"?uZ($,this.opts.workDir):r3($,this.opts.workDir,this.sessionId??void 0);if(!Y)return;let V="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:MH(Y.name,Y.input,V)})}feedCollabItem($,Z,J){if($.type==="subAgentActivity"){let Q=typeof $.agentThreadId==="string"?$.agentThreadId:"";if(!Q)return!0;if($.kind==="started"&&!this.collabAgentNames.has(Q)){let Y=E8($.agentPath,Q);this.collabAgentNames.set(Q,Y),this.emit("bg_task_started",{task_id:Q,task_type:"local_agent",description:Y}),this.emit("bg_task_updated",{task_id:Q,patch:{is_backgrounded:!0}})}else if($.kind==="started"){let Y=this.collabAgentNames.get(Q),V=E8($.agentPath,Q);if(Y!==V&&!this.collabAgentSettled.has(Q))this.collabAgentNames.set(Q,V),this.emit("bg_task_started",{task_id:Q,task_type:"local_agent",description:V})}else if($.kind==="interrupted")this.emit("bg_task_updated",{task_id:Q,patch:{status:"paused"}});return!0}if($.type==="collabAgentToolCall"){let Q=$.agentsStates;if(Q&&typeof Q==="object")for(let[Y,V]of Object.entries(Q))this.translateAgentState(Y,V,$);if($.tool==="closeAgent"&&Z==="completed"&&$.status!=="failed"){let Y=e3($);for(let V of Y){if(this.collabAgentSettled.has(V))continue;if(this.collabAgentSettled.add(V),!this.collabAgentNames.has(V))this.collabAgentNames.set(V,E8(null,V));this.emit("bg_task_settled",{task_id:V,status:"stopped"})}}if($.tool==="spawnAgent"){if(Z==="started")this.emit("tool_use",{id:$.id,name:"Agent",input:{tool:"spawnAgent",prompt:o3($.prompt),description:OH($),model:typeof $.model==="string"?$.model:void 0}});else if($.status!=="inProgress")this.emit("tool_result",{tool_use_id:$.id,content:RH($),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 V=this.collabAgentNames.get($)??E8(null,$);this.emit("bg_task_started",{task_id:$,task_type:"local_agent",description:V}),this.emit("bg_task_updated",{task_id:$,patch:{is_backgrounded:!0}})}if(!this.collabAgentNames.has($)){this.collabAgentNames.set($,"子 agent");let X={task_id:$,task_type:"local_agent",description:"子 agent",prompt:o3(J.prompt)};this.emit("bg_task_started",X);let z={task_id:$,patch:{is_backgrounded:!0}};this.emit("bg_task_updated",z)}if(Q==="running"||Q==="pendingInit"||Q==="interrupted"){let V={task_id:$,patch:{status:Q==="pendingInit"?"pending":Q==="interrupted"?"paused":"running"}};this.emit("bg_task_updated",V);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 l3("utf8"),this.emittedImageGenerationIds.clear(),!this.sessionId)return;let $=d3(this.sessionId);if(!$)return;this.rolloutFilePath=$;try{this.rolloutReadOffset=mZ($).size,K(`codex-process: image generation rollout scan primed ${$} offset=${this.rolloutReadOffset}`)}catch(Z){K(`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??d3(this.sessionId);if(!$){K(`codex-process: image generation rollout file not found for thread=${this.sessionId}`);return}this.rolloutFilePath=$;let Z;try{let Y=mZ($).size;if(Y<=this.rolloutReadOffset)return;let V=Y-this.rolloutReadOffset;Z=Buffer.allocUnsafe(V);let X=VH($,"r"),z=0;try{while(z<V){let H=zH(X,Z,z,V-z,this.rolloutReadOffset+z);if(H===0)break;z+=H}}finally{QH(X)}Z=Z.subarray(0,z),this.rolloutReadOffset+=z}catch(Y){K(`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(`
|
|
33
|
-
`)?"":Q.pop()??"";for(let Y of Q){if(!Y.trim())continue;let V;try{V=JSON.parse(Y)}catch(H){K(`codex-process: image generation rollout JSON parse failed ${$}: ${H instanceof Error?H.message:H}`);continue}let X=V?.payload,z=X?.type;if(z!=="image_generation_end"&&z!=="image_generation_call")continue;this.emitRolloutImageGeneration(X)}}emitRolloutImageGeneration($){let Z=typeof $?.call_id==="string"?$.call_id:typeof $?.id==="string"?$.id:"";if(!Z||this.emittedImageGenerationIds.has(Z))return;let J=t3($,this.sessionId??void 0);if(!J)return;let Q=$?.status==="failed",Y=$?.status==="generating"&&WH(J)?"completed":$?.status;this.emittedImageGenerationIds.add(Z),this.emit("tool_use",{id:Z,name:"ImageGeneration",input:{status:Y,revisedPrompt:a3($)}}),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((V)=>({label:V.label,description:V.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:f$("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 K(`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($)+`
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
`).trimStart():Z;return{description:Y,command:V||Z}}function j1($,Z=60){let{description:J,command:Q}=sZ($);if(J)return J;return zW(Q).replace(/\s+/g," ").trim().slice(0,Z)}function zW($){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 KW($){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=qW(J[1]);return tZ(Y||Z)}let Q=GW(Z);if(Q)return Q;return tZ(Z)}function GW($){let Z=$.match(/^("[^"]*"|'[^']*'|“[^”]*”|\S+)\s+([\s\S]*)$/);if(!Z)return null;let J=Q7(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 V=Y[1].toLowerCase();if(V==="-command"||V==="-c")return tZ(Q7(Y[2]));if(Q=Y[2],V==="-executionpolicy"||V==="-inputformat"||V==="-outputformat")Q=Q.replace(/^(?:"[^"]*"|'[^']*'|\S+)\s+/,"")}return null}function qW($){let Z=$.trim();if(Z.length<2)return Z;let J=y8[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 tZ($){let Z=$.trim(),J=Z[0];if(!y8[J])return Z;let Q=Z.slice(1);if(!/^#\s*(?:desc|dec|description|说明|目的|用途)\s*[::]/i.test(Q)&&!_W(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,(X,H)=>` $(${H})`)}function _W($,Z){let J=y8[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 y8;var S8=T(()=>{y8={'"':'"',"'":"'","“":"”"}});function j($){return $ instanceof Error?$.message:String($)}function z$($){return $.length<=16?$:`${$.slice(0,8)}…${$.slice(-4)}`}async function eZ($,Z,J){let Q=null;try{return await Promise.race([$,new Promise((Y,V)=>{Q=setTimeout(()=>V(Error(`${J} timed out after ${Z/1000}s`)),Z)})])}finally{if(Q)clearTimeout(Q)}}import{isAbsolute as Y7}from"node:path";function BW($){return $.kind==="fresh"?null:$.source.provider}function K$($,Z,J){let Q=BW($);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"||!Y7($.source.cwd)))throw Error(`conversation launch source cwd is not absolute: ${String($.source.cwd)}`);if($.kind!=="fresh"&&J!==void 0){if(!Y7(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 R1=()=>{};import{spawn as LW}from"node:child_process";import{closeSync as FW,existsSync as b8,mkdirSync as UW,openSync as DW,readdirSync as PW,readSync as AW,statSync as w8,writeFileSync as MW}from"node:fs";import{homedir as I0}from"node:os";import{delimiter as $6,isAbsolute as V7,join as c$}from"node:path";import{EventEmitter as OW}from"node:events";import{StringDecoder as X7}from"node:string_decoder";function H0(){if(process.platform!=="win32"){let $=c$(I0(),".local","npm-global","bin","codex");if(b8($))return $;let Z=c$(I0(),".local","bin","codex");if(b8(Z))return Z}return jW()??"codex"}function jW(){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($6)){if(!J)continue;for(let Q of Z){let Y=c$(J,Q);if(b8(Y))return Y}}return null}function RW(){if(process.platform==="win32")return process.env.PATH??"";return[...new Set([c$(I0(),".local","npm-global","bin"),c$(I0(),".local","bin"),c$(I0(),".bun","bin"),...(process.env.PATH??"").split($6),"/usr/local/bin","/usr/bin","/bin"].filter(Boolean))].join($6)}function s$($){return typeof $==="string"&&CW.includes($)}function NW($){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 V=typeof Q==="object"&&Q&&typeof Q.description==="string"?Q.description:"";J.push({reasoningEffort:Y,description:V})}return J}function Z6($,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:q7($)}}}return null}function q7($){let Z=$?.revisedPrompt??$?.revised_prompt;return typeof Z==="string"&&Z?Z:void 0}function W7($){if(!$||!b8(H7))return null;let Z=null,J=[H7];while(J.length){let Q=J.pop(),Y;try{Y=PW(Q,{withFileTypes:!0})}catch(V){K(`codex-process: cannot scan Codex session dir ${Q}: ${V instanceof Error?V.message:V}`);continue}for(let V of Y){let X=c$(Q,V.name);if(V.isDirectory()){J.push(X);continue}if(!V.isFile())continue;if(!V.name.startsWith("rollout-")||!V.name.endsWith(`${$}.jsonl`))continue;try{let H=w8(X).mtimeMs;if(!Z||H>Z.mtimeMs)Z={path:X,mtimeMs:H}}catch(H){K(`codex-process: cannot stat Codex rollout ${X}: ${H instanceof Error?H.message:H}`)}}}return Z?.path??null}function _7($,Z,J=EW){let Q=$?.savedPath??$?.saved_path;if(typeof Q==="string"&&Q)return Q;let Y=$?.result;if(typeof Y==="string"){let V=yW($,Z,J);if(V)return V;if(Y.length>2048){let X=B7($);return K(`codex-process: image generation inline result could not be decoded id=${X} 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 V=Y.savedPath??Y.saved_path??Y.path;if(typeof V==="string"&&V)return V;return JSON.stringify(Y,null,2)}return""}function yW($,Z,J){let Q=$?.result;if(typeof Q!=="string")return null;let Y=SW(Q);if(!Y)return null;let V=z7(Z??"unknown-thread"),X=z7(B7($)),H=c$(J,V),W=c$(H,`${X}.${Y.ext}`);try{return UW(H,{recursive:!0}),MW(W,Y.buffer),W}catch(z){return K(`codex-process: failed to write image generation result ${W}: ${z instanceof Error?z.message:z}`),null}}function B7($){let Z=$?.callId??$?.call_id??$?.id;return typeof Z==="string"&&Z?Z:`image-${Date.now()}`}function z7($){let Z=$.trim().replace(/[^a-zA-Z0-9_.-]/g,"_").replace(/^_+|_+$/g,"");return Z?Z.slice(0,140):"unknown"}function SW($){let Z=$.trim(),J=Z,Q=null,Y=Z.match(/^data:image\/([a-zA-Z0-9.+-]+);base64,(.*)$/s);if(Y)Q=wW(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 V=J.padEnd(Math.ceil(J.length/4)*4,"="),X;try{X=Buffer.from(V,"base64")}catch{return null}if(X.length<12)return null;let H=kW(X)??Q;if(!H)return null;return{buffer:X,ext:H}}function kW($){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 wW($){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 K7($,Z,J){let Q=Z6($,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:_7($,J),isError:$.status==="failed"}}return null}function k8($,Z){if(typeof $==="string"&&$){let J=$.split("/").filter(Boolean).pop();if(J)return J}return z$(Z)}function G7($){if(typeof $!=="string"||!$)return;if($.startsWith("gAAAA")&&!/[一-鿿]/.test($))return"(继承主线程历史的密文任务书)";return $}function bW($,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 j1(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 L7($){return(Array.isArray($.receiverThreadIds)?$.receiverThreadIds:[]).filter((J)=>typeof J==="string"&&!!J)}function vW($){let Z=L7($);return Z.length>0?`派生 ${Z.length} 个子 agent`:"派生子 agent"}function fW($){let Z=$.agentsStates;if(!Z||typeof Z!=="object")return"";let J=[];for(let[Q,Y]of Object.entries(Z)){let V=Y,X=typeof V?.status==="string"?V.status:"unknown";J.push(`${z$(Q)}: ${X}`)}return J.join(`
|
|
30
|
+
`)}var H7,EW,TW=30000,xW=5000,CW,L2="xhigh",v8,F2;var E1=T(()=>{N$();v();oZ();S8();R1();oZ();H7=c$(I0(),".codex","sessions"),EW=c$(I0(),".codex","generated_images"),CW=["none","minimal","low","medium","high","xhigh","max","ultra"];v8=class v8 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"}};F2=class F2 extends OW{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;rolloutFilePath=null;rolloutReadOffset=0;rolloutLineRemainder="";rolloutDecoder=new X7("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;constructor($){super();this.on("error",()=>{}),this.exitPromise=new Promise((Y)=>{this.resolveExit=Y}),this.opts=$,this.tokenSourceId=$.tokenSourceId??null,this.launchKind=($.launch??{kind:"fresh"}).kind;let Z=H0(),J=["app-server","--listen","stdio://"];K(`codex-process: spawn ${Z} app-server (cwd=${$.workDir})`);let Q={...process.env,NPM_CONFIG_LOGLEVEL:"error",PATH:RW(),...f.codex.env};this.proc=LW(Z,J,{cwd:$.workDir,stdio:["pipe","pipe","pipe"],shell:process.platform==="win32",env:$.transformEnv?$.transformEnv(Q):Q}),this.proc.stdout.on("data",(Y)=>this.onStdout(Y)),this.proc.stderr.on("data",(Y)=>this.onStderr(Y)),this.proc.stdin.on("error",(Y)=>this.handleStdinError(Y)),this.proc.on("exit",(Y,V)=>this.handleChildExit(Y,V)),this.proc.on("close",(Y,V)=>this.handleChildClose(Y,V)),this.proc.on("error",(Y)=>this.handleChildProcessError(Y))}handleStdinError($){let Z=$ instanceof Error?$:Error(String($));if(K(`codex-process: stdin failed: ${Z.message}`),!this.expectedExit)this.emit("error",Z)}handleChildExit($,Z){if(!this.alive){K(`codex-process: duplicate exit ignored code=${$} signal=${Z}`);return}this.alive=!1,this.childExitCode=$,this.childExitSignal=Z,K(`codex-process: OS exit code=${$} signal=${Z}; awaiting stdio close`)}handleChildClose($,Z){this.alive=!1,this.flushStdoutTail(),this.flushStderrTail(),this.rejectPendingRequests((V,X)=>Error(`codex app-server closed before ${X.method} response (id=${V})`)),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($){K(`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.serverRequests.clear(),J=!0;if(this.emit("error",$),J)K(`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(),K(`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
|
+
`))>=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){K(`codex-process: bad json: ${J.slice(0,200)} (${Y})`);continue}try{this.handleMessage(Q)}catch(Y){K(`codex-process: dispatch error: ${JSON.stringify(Q).slice(0,200)} (${Y})`)}}}flushStdoutTail(){if(!this.stdoutBuf)return;this.onStdout(Buffer.from(`
|
|
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())K(`codex-process[stderr]: ${J}`)}}flushStderrTail(){let $=this.stderrBuf;if(this.stderrBuf="",$.trim())K(`codex-process[stderr]: ${$}`)}handleMessage($){if(Object.prototype.hasOwnProperty.call($,"id")&&!$.method){let J=this.pending.get($.id);if(!J){K(`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 v8(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=nZ($);if(Z){let J=this.withSessionId(Z);dZ(Z.sourceMethod??"raw_message",$,J),this.emit("context_compacted",J);return}j$("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=iZ($,Z);if(J){let Q=this.withSessionId(J);dZ($,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=O1(Z.tokenUsage?.last);if(Q)this.lastUsage=Q,this.lastResult.usage=this.lastUsage;else K("codex-process: tokenUsage notification missing last breakdown");this.lastTotalUsage=O1(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){j$("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){j$("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)){K(`codex-process: duplicate turn/completed ignored turn=${Y}`);return}if(this.currentTurnId&&this.currentTurnId!==Y){this.markTurnStartTerminal(Y),this.rememberFinishedTurn(Y),K(`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 j$("TURN_COMPLETED_MISSING_ID",{method:$,params:Z});let V=Q.status,X=V==="failed"||!!Q.error,H=V==="completed"&&!X&&!!Y;this.lastCompletedTurnId=H?Y:null;let W=X?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:W,is_error:X},this.currentTurnId=null,this.emit("result",{subtype:W,is_error:X,duration_ms:this.lastResult.duration_ms,usage:this.lastUsage,turn_id:Y,checkpoint:H&&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 K("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});else j$("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":{K(`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":{K(`codex-process: ${$}: ${Z.summary??Z.message??JSON.stringify(Z).slice(0,200)}`);return}case"error":{K(`codex-process: server error: ${JSON.stringify(Z).slice(0,500)}`),this.emit("error",Error(Z.message??Z.summary??"codex app-server error"));return}}j$("NOTIFICATION",{method:$,params:Z}),this.emit("raw",{method:$,params:Z})}handleItemStarted($){let Z=$?.item;if(!Z?.id){j$("ITEM_STARTED_MISSING_ID",{method:"item/started",params:$});return}if(this.feedCollabItem(Z,"started",$))return;let J=Z6(Z,this.opts.workDir);if(!J){j$("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){j$("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});return}if(this.feedCollabItem(Z,"completed",$))return;let J=K7(Z,this.opts.workDir,this.sessionId??void 0);if(!J){j$("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)??z$(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"?Z6($,this.opts.workDir):K7($,this.opts.workDir,this.sessionId??void 0);if(!Y)return;let V="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:bW(Y.name,Y.input,V)})}feedCollabItem($,Z,J){if($.type==="subAgentActivity"){let Q=typeof $.agentThreadId==="string"?$.agentThreadId:"";if(!Q)return!0;if($.kind==="started"&&!this.collabAgentNames.has(Q)){let Y=k8($.agentPath,Q);this.collabAgentNames.set(Q,Y),this.emit("bg_task_started",{task_id:Q,task_type:"local_agent",description:Y}),this.emit("bg_task_updated",{task_id:Q,patch:{is_backgrounded:!0}})}else if($.kind==="started"){let Y=this.collabAgentNames.get(Q),V=k8($.agentPath,Q);if(Y!==V&&!this.collabAgentSettled.has(Q))this.collabAgentNames.set(Q,V),this.emit("bg_task_started",{task_id:Q,task_type:"local_agent",description:V})}else if($.kind==="interrupted")this.emit("bg_task_updated",{task_id:Q,patch:{status:"paused"}});return!0}if($.type==="collabAgentToolCall"){let Q=$.agentsStates;if(Q&&typeof Q==="object")for(let[Y,V]of Object.entries(Q))this.translateAgentState(Y,V,$);if($.tool==="closeAgent"&&Z==="completed"&&$.status!=="failed"){let Y=L7($);for(let V of Y){if(this.collabAgentSettled.has(V))continue;if(this.collabAgentSettled.add(V),!this.collabAgentNames.has(V))this.collabAgentNames.set(V,k8(null,V));this.emit("bg_task_settled",{task_id:V,status:"stopped"})}}if($.tool==="spawnAgent"){if(Z==="started")this.emit("tool_use",{id:$.id,name:"Agent",input:{tool:"spawnAgent",prompt:G7($.prompt),description:vW($),model:typeof $.model==="string"?$.model:void 0}});else if($.status!=="inProgress")this.emit("tool_result",{tool_use_id:$.id,content:fW($),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 V=this.collabAgentNames.get($)??k8(null,$);this.emit("bg_task_started",{task_id:$,task_type:"local_agent",description:V}),this.emit("bg_task_updated",{task_id:$,patch:{is_backgrounded:!0}})}if(!this.collabAgentNames.has($)){this.collabAgentNames.set($,"子 agent");let X={task_id:$,task_type:"local_agent",description:"子 agent",prompt:G7(J.prompt)};this.emit("bg_task_started",X);let H={task_id:$,patch:{is_backgrounded:!0}};this.emit("bg_task_updated",H)}if(Q==="running"||Q==="pendingInit"||Q==="interrupted"){let V={task_id:$,patch:{status:Q==="pendingInit"?"pending":Q==="interrupted"?"paused":"running"}};this.emit("bg_task_updated",V);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 X7("utf8"),this.emittedImageGenerationIds.clear(),!this.sessionId)return;let $=W7(this.sessionId);if(!$)return;this.rolloutFilePath=$;try{this.rolloutReadOffset=w8($).size,K(`codex-process: image generation rollout scan primed ${$} offset=${this.rolloutReadOffset}`)}catch(Z){K(`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??W7(this.sessionId);if(!$){K(`codex-process: image generation rollout file not found for thread=${this.sessionId}`);return}this.rolloutFilePath=$;let Z;try{let Y=w8($).size;if(Y<=this.rolloutReadOffset)return;let V=Y-this.rolloutReadOffset;Z=Buffer.allocUnsafe(V);let X=DW($,"r"),H=0;try{while(H<V){let W=AW(X,Z,H,V-H,this.rolloutReadOffset+H);if(W===0)break;H+=W}}finally{FW(X)}Z=Z.subarray(0,H),this.rolloutReadOffset+=H}catch(Y){K(`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 V;try{V=JSON.parse(Y)}catch(W){K(`codex-process: image generation rollout JSON parse failed ${$}: ${W instanceof Error?W.message:W}`);continue}let X=V?.payload,H=X?.type;if(H!=="image_generation_end"&&H!=="image_generation_call")continue;this.emitRolloutImageGeneration(X)}}emitRolloutImageGeneration($){let Z=typeof $?.call_id==="string"?$.call_id:typeof $?.id==="string"?$.id:"";if(!Z||this.emittedImageGenerationIds.has(Z))return;let J=_7($,this.sessionId??void 0);if(!J)return;let Q=$?.status==="failed",Y=$?.status==="generating"&&V7(J)?"completed":$?.status;this.emittedImageGenerationIds.add(Z),this.emit("tool_use",{id:Z,name:"ImageGeneration",input:{status:Y,revisedPrompt:q7($)}}),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((V)=>({label:V.label,description:V.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:j$("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 K(`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=TW){let Q=++this.requestCounter;return new Promise((Y,V)=>{let X=setTimeout(()=>{let W=this.pending.get(Q);if(!W)return;this.pending.delete(Q),W.reject(Error(`codex app-server ${$} request timed out after ${J}ms (id=${Q})`))},Math.max(0,J)),H={resolve:Y,reject:V,method:$,timeout:X};this.pending.set(Q,H),this.write({id:Q,method:$,params:Z},(W)=>{if(this.pending.get(Q)!==H)return;this.pending.delete(Q),clearTimeout(X),V(Error(`codex app-server ${$} request write failed (id=${Q}): ${W.message}`,{cause:W}))})})}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(($)=>{K(`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 V=typeof Y.cwd==="string"?Y.cwd:typeof Q?.cwd==="string"?Q.cwd:null;if(V!==this.opts.workDir)throw Error(`codex app-server ${J} returned cwd=${V??"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 X=typeof Y.path==="string"&&Y.path?Y.path:null;if(!X||!V7(X)||!X.endsWith(`${Y.id}.jsonl`))throw Error(`codex app-server ${J} returned invalid thread.path=${X??"MISS"}`);if(this.sessionId=Y.id,this.conversationRolloutPath=X,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;K(`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,K(`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,K(`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},xW))?.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=w8(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(K$($,"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:"lodestar"}}sendUserText($,Z=[]){let J=Z.length?Z.map((Y)=>`[file: ${Y}]`).join(" ")+`
|
|
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:NW(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 V of Q.data){if(typeof V?.id!=="string"||!V.id||typeof V.preview!=="string"||typeof V.updatedAt!=="number"||!Number.isFinite(V.updatedAt)||typeof V.cwd!=="string"||V.cwd!==this.opts.workDir)throw Error("thread/list returned an invalid thread summary");let X=typeof V.status==="string"?V.status:typeof V.status?.type==="string"?V.status.type:void 0;$.push({provider:"codex",sessionId:V.id,cwd:V.cwd,preview:V.preview,ts:V.updatedAt*1000,...X?{status:X}:{}})}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 injectThreadItems($){if(!Array.isArray($)||$.length===0)return;if(!this.readyPromise)this.sendInitialize();if(await this.readyPromise,!this.sessionId)throw Error("codex thread not initialized");await this.request("thread/inject_items",{threadId:this.sessionId,items:$})}async setModelSettings($,Z){K("codex-process: setModelSettings no-op (codex model/effort governed by ~/.codex/config.toml)")}async setModel($){K("codex-process: setModel no-op (codex model governed by ~/.codex/config.toml)")}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)){K(`codex-process: ignored stale turn/start failure generation=${Z.generation}`);return}this.turnStartOwner=null;let J=$ instanceof Error?$.message:String($);K(`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 V=this.currentTurnId!==Y;if(this.currentTurnId=Y,!V)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,approvalPolicy:"never",sandboxPolicy:{type:"dangerFullAccess"}});this.recordTurnStarted(Q?.turn,this.sessionId,"turn/start response",J)}catch(Q){if(!this.ownsTurnStartFailure(J)){K(`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(($)=>K(`codex-process: interrupt failed: ${$}`))}sendPermissionResponse($,Z,J){let Q=this.serverRequests.get(String($));if(!Q){K(`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 V=J?.updatedInput?.answers??{},X={};for(let H of Q.params?.questions??[]){let W=V[H.question]??V[H.id];if(W!==void 0)X[H.id]={answers:[String(W)]}}this.respond($,{answers:X});return}default:j$("APPROVAL_RESPONSE_UNSUPPORTED",{requestId:$,method:Q.method,params:Q.params,decision:Z,payload:J}),this.respondError($,J?.denyMessage??"unsupported approval request")}}sendToolResult($,Z,J=!1){K("codex-process: sendToolResult ignored; Codex app-server server requests are answered via sendPermissionResponse")}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,K(`codex-process: SIGTERM (timeout=${$}ms)`);let Z=[];if(this.sendSignal("SIGTERM",Z),await this.waitForExit($))return;if(K(`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 K(`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=(V)=>{if(J)return;J=!0,clearTimeout(Y),Z(V)},Y=setTimeout(()=>Q(!1),Math.max(0,$));this.exitPromise.then(()=>Q(!0))})}}});function hW($){return $.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function J6($){let Z=[],J=/^(?: {0,3})(`{3,}|~{3,})[^\n]*(?:\n|$)/gm,Q=0;while(Q<$.length){J.lastIndex=Q;let H=J.exec($);if(!H)break;let W=H[1],z=new RegExp(`^(?: {0,3})${hW(W[0])}{${W.length},}[ \\t]*(?:\\n|$)`,"gm");z.lastIndex=H.index+H[0].length;let G=z.exec($),q=G?G.index+G[0].length:$.length;Z.push({start:H.index,end:q}),Q=q}let Y=[...Z],V=[],X=0;for(let H of Z){if(X<H.start)V.push({start:X,end:H.start});X=H.end}if(X<$.length)V.push({start:X,end:$.length});for(let H of V){let W=$.slice(H.start,H.end),z=/(`+)[^\n]*?\1/g,G;while((G=z.exec(W))!==null)Y.push({start:H.start+G.index,end:H.start+G.index+G[0].length})}return Y.sort((H,W)=>H.start-W.start)}function Q6($,Z){if(!$)return $;let J=J6($);if(!J.length)return Z($);let Q="",Y=0;for(let V of J){if(V.start>Y)Q+=Z($.slice(Y,V.start));Q+=$.slice(V.start,V.end),Y=Math.max(Y,V.end)}if(Y<$.length)Q+=Z($.slice(Y));return Q}function IW($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function F7($){return $.replace(/!\[([^\]]*)\]\(([^)]*)\)/g,(J,Q,Y)=>{let V=Y.trim();return Q.trim()?`\uD83D\uDDBC️ ${Q.trim()} (${V})`:`\uD83D\uDDBC️ ${V}`}).replace(/!\[/g,"\uD83D\uDDBC️ [")}function P0($){if(Array.isArray($))return $.map((Q)=>P0(Q));if($==null||typeof $!=="object")return $;let Z=$,J={};for(let[Q,Y]of Object.entries(Z))J[Q]=P0(Y);if(Z.tag==="markdown"&&typeof Z.content==="string")J.content=Y6(Z.content);return J}function D$($){return Q6($,(Z)=>gW(F7(IW(Z))))}function gW($){return $.replace(/\\\[([\s\S]*?)\\\]/g,(Z,J)=>`
|
|
37
38
|
\`\`\`
|
|
38
39
|
${J.trim()}
|
|
39
40
|
\`\`\`
|
|
@@ -41,172 +42,170 @@ ${J.trim()}
|
|
|
41
42
|
\`\`\`
|
|
42
43
|
${J.trim()}
|
|
43
44
|
\`\`\`
|
|
44
|
-
`).replace(/\\\(([\s\S]*?)\\\)/g,(Z,J)=>`\`${J.trim()}\``).replace(/\$([^$\n]+)\$/g,(Z,J)=>/\\|\^|_|=/.test(J)?`\`${J.trim()}\``:Z)}function
|
|
45
|
-
`):"_(暂无执行记录)_")}function
|
|
46
|
-
`);for(let Q=J.length-1;Q>=0;Q--){let Y=J[Q].trim();if(!Y)continue;try{let V=JSON.parse(Y);if(V?.type==="assistant"&&V?.message?.usage){let X=V.message.usage;if((X.input_tokens??0)+(X.cache_read_input_tokens??0)+(X.cache_creation_input_tokens??0)+(X.output_tokens??0)>0)return X}}catch{}}return null}function
|
|
47
|
-
`);return $==null?"":JSON.stringify($,null,2)}function
|
|
48
|
-
`)}}catch{}return Z}function
|
|
45
|
+
`).replace(/\\\(([\s\S]*?)\\\)/g,(Z,J)=>`\`${J.trim()}\``).replace(/\$([^$\n]+)\$/g,(Z,J)=>/\\|\^|_|=/.test(J)?`\`${J.trim()}\``:Z)}function Y6($){return Q6($,F7)}var O;var y$=T(()=>{O={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",agyPrompt:"agy_prompt",agyStats:"agy_stats",agyResult:"agy_result",agyForward:"agy_forward",agyRepo:"agy_repo",tasklistPanel:"tasklist_panel"}});function U7($){let Z=2166136261;for(let J=0;J<$.length;J++)Z^=$.charCodeAt(J),Z=Math.imul(Z,16777619);return(Z>>>0).toString(36)}function mW($,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 D7($){return $==="workflow"||$==="monitor"}function S$($){return $.status==="completed"||$.status==="failed"||$.status==="killed"}function A0($){return $.some((Z)=>!S$(Z))}function W6($,Z,J=Date.now()){let Q=mW(Z.task_type,Z.subagent_type),Y=$.active.some((H)=>H.id===Z.task_id),V=$.pending.some((H)=>H.id===Z.task_id);if(Y||V){let H=(W)=>({...W,type:Q,toolUseId:Z.tool_use_id??W.toolUseId,description:Z.description||W.description,subagentType:Z.subagent_type??W.subagentType,workflowName:Z.workflow_name??W.workflowName,prompt:Z.prompt??W.prompt});return{active:Y?$.active.map((W)=>W.id===Z.task_id?H(W):W):$.active,pending:V?$.pending.map((W)=>W.id===Z.task_id?H(W):W):$.pending}}let X={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:[],...D7(Q)?{isBackgrounded:!0}:{}};return D7(Q)?{active:[...$.active,X],pending:$.pending}:{active:$.active,pending:[...$.pending,X]}}function z6($,Z){let J=$.active.some((V)=>V.id===Z.task_id),Q=$.pending.some((V)=>V.id===Z.task_id);if(!J&&!Q)return $;let Y=(V)=>({...V,description:Z.description??V.description,subagentType:Z.subagent_type??V.subagentType,usage:Z.usage??V.usage,lastToolName:Z.last_tool_name??V.lastToolName,summary:Z.summary??V.summary,status:V.status==="pending"?"running":V.status});return{active:J?$.active.map((V)=>V.id===Z.task_id?Y(V):V):$.active,pending:Q?$.pending.map((V)=>V.id===Z.task_id?Y(V):V):$.pending}}function K6($,Z){let J=$.pending.findIndex((X)=>X.id===Z.task_id),Q=Z.patch;if(Q.is_backgrounded===!0&&J>=0){let X=$.pending[J],H={...X,isBackgrounded:!0,status:Q.status??X.status,description:Q.description??X.description,error:Q.error??X.error,endTime:Q.end_time??X.endTime};return{active:[...$.active,H],pending:$.pending.filter((W)=>W.id!==Z.task_id)}}let Y=$.active.some((X)=>X.id===Z.task_id),V=J>=0;if(Y||V){let X=(H)=>({...H,status:Q.status??H.status,description:Q.description??H.description,error:Q.error??H.error,isBackgrounded:Q.is_backgrounded??H.isBackgrounded,endTime:Q.end_time??H.endTime});return{active:Y?$.active.map((H)=>H.id===Z.task_id?X(H):H):$.active,pending:V?$.pending.map((H)=>H.id===Z.task_id?X(H):H):$.pending}}return $}function G6($){if($.pending.length===0)return $;return{active:[...$.active,...$.pending.map((Z)=>({...Z,isBackgrounded:!0}))],pending:[]}}function q6($,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 f8($){let Z=0,J=0;for(let Q=$.length-1;Q>=0;Q--)if(Z+=$[Q].brief.length+5,Z>cW){J=Q+1;break}return J===0?$:$.slice(J)}function uW($,Z){let J=(Q)=>typeof Q==="string"?Q:"";switch($){case"Bash":return j1(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 pW($,Z){let J=($??"").replace(/\s+/g," ").trim();return Z?`❌ ${J.slice(0,80)}`:J.slice(0,80)}function _6($,Z,J,Q,Y){if(!Z)return $;let V=$.active.some((W)=>W.toolUseId===Z),X=$.pending.some((W)=>W.toolUseId===Z);if(!V&&!X)return $;let H=(W)=>W.map((z)=>z.toolUseId===Z?{...z,steps:f8([...z.steps,{toolUseId:J,tool:Q,brief:`${Q} ${uW(Q,Y)}`.trim()}])}:z);return{active:V?H($.active):$.active,pending:X?H($.pending):$.pending}}function B6($,Z,J,Q,Y,V){let X=$.active.some((z)=>z.id===Z),H=$.pending.some((z)=>z.id===Z);if(!X&&!H)return $;let W=(z)=>z.map((G)=>{if(G.id!==Z)return G;if(Y==="started")return{...G,steps:f8([...G.steps,{toolUseId:J,tool:Q,brief:`${Q} ${V}`.trim()}])};let q=!1,B=G.steps.map((L)=>{if(q||L.toolUseId!==J)return L;return q=!0,{...L,brief:V?`${L.brief} ${V}`:L.brief}});if(!q&&V)B.push({toolUseId:J,tool:Q,brief:`${Q} ${V}`.trim()});return{...G,steps:f8(B)}});return{active:X?W($.active):$.active,pending:H?W($.pending):$.pending}}function L6($,Z,J,Q,Y){if(!Z)return $;let V=$.active.some((W)=>W.toolUseId===Z),X=$.pending.some((W)=>W.toolUseId===Z);if(!V&&!X)return $;let H=(W)=>W.map((z)=>{if(z.toolUseId!==Z)return z;let G=!1,q=z.steps.map((B)=>{if(G||B.toolUseId!==J)return B;return G=!0,{...B,brief:`${B.brief} → ${pW(Q,Y)}`}});return{...z,steps:f8(q)}});return{active:V?H($.active):$.active,pending:X?H($.pending):$.pending}}function V6($){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 M7($){let Z=Number.isFinite($)?Math.max(0,$):0;for(let V of iW)if(Z<V.limit)return{label:V.label,nextDelayMs:V.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 M0($,Z="bucket"){if(Z==="second"){let J=Number.isFinite($)?Math.max(0,$):0;if(J>=X6){let Q=Math.floor((J-X6)/P7),Y=X6+(Q+1)*P7;return{label:`${10+Q*5}m+`,nextDelayMs:Y-J}}return{label:`${Math.floor(J/1000)}s`,nextDelayMs:A7}}return M7($)}function nW($){return $.subagentType??$.workflowName??dW[$.type]}function H6($){if($.usage?.duration_ms)return $.usage.duration_ms;if($.endTime&&$.endTime>$.startedAt)return $.endTime-$.startedAt;return 0}function oW($,Z,J="bucket"){let Q=(Y)=>M0(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`✅ 用时 ${V6(H6($))}`;case"failed":return`❌ 失败 ${V6(H6($))}`;case"killed":return`\uD83D\uDC80 已终止 ${V6(H6($))}`}}function O7($){let Z=$.filter((Q)=>!S$(Q)).length,J=$.length-Z;if(Z>0)return`${Z} 进行中${J?` · ${J} 已结束`:""}`;return J?`${J} 已结束`:"空"}function h8($){return`\uD83E\uDDED 后台任务 · ${O7($)}`}function rW($){let Z=[];if($.error)Z.push(`⚠ ${$.error}`);if(S$($)&&$.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 D$(Z.length>0?Z.join(`
|
|
46
|
+
`):"_(暂无执行记录)_")}function T1($,Z=Date.now(),J="bucket"){return{tag:"collapsible_panel",element_id:U2.panel($.id),header:{title:{tag:"plain_text",content:`${lW[$.type]} ${nW($)} · ${$.description||"(无描述)"} — ${oW($,Z,J)}`}},expanded:!1,elements:[{tag:"markdown",element_id:U2.body($.id),content:rW($)}]}}function F6($,Z=Date.now(),J="bucket"){return{schema:"2.0",config:{streaming_mode:!0,summary:{content:h8($)}},body:{elements:$.map((Q)=>T1(Q,Z,J))}}}function I8($,Z=Date.now(),J="bucket"){let Q=$.filter(S$);return{schema:"2.0",config:{streaming_mode:!1,summary:{content:`\uD83E\uDDED 后台任务(历史) · ${Q.length} 已结束`}},body:{elements:Q.map((Y)=>T1(Y,Z,J))}}}function U6(){return{schema:"2.0",config:{streaming_mode:!1,summary:{content:"↪ 后台任务进行中"}},body:{elements:[{tag:"markdown",element_id:"bg_marker",content:"↪ 本轮后台任务仍在进行,进度已迁至最新卡片"}]}}}var U2,cW=1000,lW,dW,iW,A7=1000,X6=600000,P7=300000;var D6=T(()=>{y$();S8();U2={panel:($)=>`bg_${U7($)}`,body:($)=>`bgb_${U7($)}`};lW={subagent:"\uD83D\uDFE2",shell:"⚙️",monitor:"\uD83D\uDCE1",workflow:"\uD83D\uDD01",unknown:"\uD83D\uDD39"},dW={subagent:"子agent",shell:"shell",monitor:"监控",workflow:"工作流",unknown:"任务"};iW=[{limit:30000,label:"<30s"},{limit:60000,label:"<1m"},{limit:180000,label:"<3m"},{limit:300000,label:"<5m"},{limit:600000,label:"<10m"}]});function j0($){return typeof $==="string"&&aW.includes($)}function x1($){return $?.startsWith("claude:")?"claude":"codex"}function W0($){return $==="claude"?"Claude":"Codex"}var aW,O0="max",D2;var C1=T(()=>{aW=["low","medium","high","xhigh","max"];D2=class D2 extends Error{constructor($="上下文窗口充足,无需压缩"){super($);this.name="NothingToCompactError"}}});var T7={};q2(T7,{tokenSourceFactories:()=>N1,setDefaultTokenSource:()=>A6,scrubAnthropicEnv:()=>g0,resetTokenSourceRegistry:()=>M6,registerTokenSourceFactory:()=>z0,registerTokenSource:()=>P6,refreshAllTokenSourceModels:()=>m0,listTokenSourcesByAgent:()=>E7,listTokenSources:()=>O2,listEnabledTokenSourcesByAgent:()=>g8,getTokenSource:()=>Y$,defaultTokenSourceId:()=>sW});function g0($){let Z={...$};for(let J of tW)delete Z[J];return Z}function z0($){j7.set($.kind,$)}function N1(){return[...j7.values()]}function P6($,Z){if(M2.set($.id,$),Z?.default||A2===null)A2=$.id}function Y$($){return $?M2.get($):void 0}function O2(){return[...M2.values()]}function E7($){return O2().filter((Z)=>Z.agent===$)}function g8($){return E7($).filter((Z)=>Z.enabled)}function sW(){return A2}function A6($){if(M2.has($))A2=$}function M6(){M2.clear(),A2=null,R7++}function m0(){let $=R7;if(P2?.generation===$)return P2.promise;let Z=Promise.allSettled(O2().map(async(J)=>{await J.refreshModels(),K(`token-source ${J.id}: ${J.models.length} models loaded`)})).then(()=>{}).finally(()=>{if(P2?.promise===Z)P2=null});return P2={generation:$,promise:Z},Z}var tW,j7,M2,A2=null,R7=0,P2=null;var k$=T(()=>{v();tW=["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","ANTHROPIC_DEFAULT_OPUS_MODEL","ANTHROPIC_DEFAULT_SONNET_MODEL","ANTHROPIC_DEFAULT_HAIKU_MODEL"];j7=new Map;M2=new Map});import{exec as eW}from"node:child_process";function C7(){eW(`systemctl --user stop ${x7}.timer ${x7}.service 2>/dev/null`,()=>{})}var x7="cc-feishu-rollback-watchdog";var N7=()=>{};function $z($){return{...y7[$]??{},...f.claude.models[$]??{}}}function Zz($){let Z=$z($);return{key:`claude:${$}`,name:$,displayName:Z.display_name?.trim()||`Claude Code · ${$}`,description:Z.description?.trim()||`使用 ${$} 路由运行 Claude Code 后端。`,sdkModel:Z.model?.trim()||"opus"}}function Jz(){return[...new Set([...Object.keys(y7),...Object.keys(f.claude.models)])].map(Zz).filter((Z)=>Z!==null)}function Qz($){if(!$?.startsWith("claude:"))return null;let Z=$.slice(7);if(!Z||Z==="default")return null;return Jz().find((J)=>J.name===Z||J.key===$)??null}function R0($){return $.startsWith("claude:")?$:`claude:${$}`}function O6($){if(!$)return"opus";let Z=Qz($);if(Z)return Z.sdkModel;let J=$.startsWith("claude:")?$.slice(7):$;return J==="default"?"opus":J}var y7;var S7=T(()=>{N$();y7={glm:{display_name:"Claude Code · GLM",description:"使用 GLM 路由,适合中文交流和通用编码任务。"}}});import{existsSync as Yz,readFileSync as Vz}from"node:fs";function j6(){return process.env.LODESTAR_DATA_DIR?`${process.env.LODESTAR_DATA_DIR.replace(/\/+$/,"")}/context-window-cache.json`:C3}function R2(){if(j2!==null)return j2;try{j2=Yz(j6())?JSON.parse(Vz(j6(),"utf8")):{}}catch($){K(`context-window-observe: cache read MISS (${$?.message??$}), starting fresh`),j2={}}return j2??{}}function Wz(){try{O$(j6(),R2())}catch($){K(`context-window-observe: cache write MISS (${$?.message??$})`)}}function R6($,Z){return`${$}:${Z.replace(/\[1m\]$/,"")}`}function E6($,Z,J){if(!Number.isFinite(J)||J<=0)return;let Q=R6($,Z),Y=R2()[Q];if(Y===J)return;R2()[Q]=J,Wz(),K(`context-window-observe: ${Q} → ${J} (prev ${Y??"-"})`)}function k7($,Z){E6($,Z,Hz)}function m8($,Z){if(!Z)return;if(Z.endsWith("[1m]"))return Z;let J=R2()[R6($,Z)];return J!=null&&J<Xz?Z:`${Z}[1m]`}function c8($,Z){return R2()[R6($,Z)]}var Xz=1e6,Hz=200000,j2=null;var u8=T(()=>{m$();v();f0()});import{existsSync as l8,readFileSync as m7}from"node:fs";import{homedir as T2}from"node:os";import{spawn as zz}from"cross-spawn";import{delimiter as w7,join as c0,posix as Kz,win32 as Gz}from"node:path";import{EventEmitter as qz}from"node:events";import{query as _z}from"@anthropic-ai/claude-agent-sdk";function Bz($){return $==="win32"?";":":"}function x6($,...Z){return $==="win32"?Gz.join(...Z):Kz.join(...Z)}function b7($){let Z=$.toLowerCase();return Z.endsWith(".cmd")||Z.endsWith(".bat")}function v7($){let Z=zz($.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 u7($={}){let Z=$.platform??process.platform,J=$.exists??l8,Q=$.homeDir??T2();if(Z!=="win32"){let V=[x6(Z,Q,".local","npm-global","bin","claude"),x6(Z,Q,".local","bin","claude")];for(let X of V)if(J(X))return X}let Y=Fz($);if(Y)return Y;return null}function p7(){u7()}function Lz($={}){let Z=$.platform??process.platform,J=$.configuredBin===void 0?f.claude.bin:$.configuredBin;if(J){if(!($.exists??l8)(J))throw Error(`lodestar: [claude].bin not found: ${J} (config.toml)`);if(Z==="win32"&&b7(J))return{pathToClaudeCodeExecutable:J,spawnClaudeCodeProcess:v7,description:`windows-shell-shim:${J}`};return{pathToClaudeCodeExecutable:J,description:`config:${J}`}}let Q=u7($);if(!Q)return{description:"sdk-default"};if(Z==="win32"&&b7(Q))return{pathToClaudeCodeExecutable:Q,spawnClaudeCodeProcess:v7,description:`windows-shell-shim:${Q}`};return{description:"sdk-default"}}function Fz($={}){let Z=$.platform??process.platform,J=$.pathEnv??process.env.PATH??"";if(!J)return null;let Q=$.exists??l8,Y=Z==="win32"?["claude.exe","claude.cmd","claude.bat","claude"]:["claude"];for(let V of J.split(Bz(Z))){if(!V)continue;for(let X of Y){let H=x6(Z,V,X);if(Q(H))return H}}return null}function f7(){if(process.platform==="win32")return process.env.PATH??"";let $=[c0(T2(),".local","npm-global","bin"),c0(T2(),".local","bin"),c0(T2(),".bun","bin"),...(process.env.PATH??"").split(w7),"/usr/local/bin","/usr/bin","/bin"];return[...new Set($.filter(Boolean))].join(w7)}function Uz($){let Z=O1($);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 h7($){if(!$)return null;let Z=($.input_tokens??0)+($.cache_read_input_tokens??0)+($.cache_creation_input_tokens??0);return Z>0?Z:null}function N6($){let Z=$.replace(/[^a-zA-Z0-9]/g,"-"),J=process.env.CLAUDE_CONFIG_DIR||c0(T2(),".claude");return c0(J,"projects",Z)}function y6($,Z){return c0(N6($),`${Z}.jsonl`)}function Dz($){let Z;try{Z=m7($,"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 V=JSON.parse(Y);if(V?.type==="assistant"&&V?.message?.usage){let X=V.message.usage;if((X.input_tokens??0)+(X.cache_read_input_tokens??0)+(X.cache_creation_input_tokens??0)+(X.output_tokens??0)>0)return X}}catch{}}return null}function I7($,Z){let J=Z?.trim()||"no-source",Q=$&&$.trim()?$:"claude:default";return`${J}:${Q}`}function Pz($){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 V=Y;Z.input_tokens=(Z.input_tokens??0)+y1(V.inputTokens??V.input_tokens),Z.output_tokens=(Z.output_tokens??0)+y1(V.outputTokens??V.output_tokens),Z.reasoning_output_tokens=(Z.reasoning_output_tokens??0)+y1(V.reasoningOutputTokens??V.reasoning_output_tokens),Z.cache_read_input_tokens=(Z.cache_read_input_tokens??0)+y1(V.cacheReadInputTokens??V.cache_read_input_tokens),Z.cache_creation_input_tokens=(Z.cache_creation_input_tokens??0)+y1(V.cacheCreationInputTokens??V.cache_creation_input_tokens);let X=y1(V.contextWindow??V.context_window);if(X>0)J=Math.max(J??0,X)}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 p8($){return{...$}}function T6($){if(!$||typeof $!=="object")return[];return Object.keys($).slice(0,20)}function Az($,Z){let J=$?{...$}:{},Q=(Y)=>{let V=Z[Y];if(typeof V!=="number"||!Number.isFinite(V))return;J[Y]=(J[Y]??0)+V};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 y1($){return typeof $==="number"&&Number.isFinite($)?$:0}function l7($){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 Mz($){let Z=l7($);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 Oz($){return`server_tool:${$}`}function jz($){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 Rz($){let Z=$.trim();return Z.includes("Built-in Tool:")||Z.startsWith("**Output:**")&&Z.includes("_result")}function Ez($){let Z=$.supportedEffortLevels&&$.supportedEffortLevels.length>0?$.supportedEffortLevels:[O0];return{id:R0($.value),model:R0($.value),displayName:$.displayName||R0($.value),description:$.description||"Claude Agent SDK backend",hidden:!1,isDefault:!1,supportedReasoningEfforts:Z.map((J)=>({reasoningEffort:J,description:""})),defaultReasoningEffort:Z.includes(O0)?O0:Z[0]}}function xz($){if(!$?.settingSources)return[...g7];let Z=$.settingSources.split(",").map((J)=>J.trim()).filter(Boolean);return Z.length?Z:[...g7]}function Cz($){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 Nz($){let Z=c0($,".mcp.json"),J;try{J=m7(Z,"utf8")}catch(Q){if(Q.code!=="ENOENT")K(`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;K(`claude-agent-process: project .mcp.json has no mcpServers object at ${Z}`);return}catch(Q){K(`claude-agent-process: project .mcp.json parse failed at ${Z}: ${Q}`);return}}function yz($){let Z=$.questions;return(Array.isArray(Z)?Z:Z&&typeof Z==="object"?[Z]:[$]).map((Q)=>Sz(Q)).filter((Q)=>Q!==null)}function Sz($){let Z=$&&typeof $==="object"?$:{question:$},J=C6(Z.question,Z.prompt,Z.title,Z.message,Z.text,Z.label);if(!J)return null;if(!J.trim())return null;let Q=kz(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 kz($){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=C6(Q.label,Q.value,Q.text,Q.title);if(!Y?.trim())continue;let V=C6(Q.description,Q.detail,Q.preview);Z.push(V?{label:Y,description:V}:{label:Y})}return Z}function C6(...$){for(let Z of $)if(typeof Z==="string")return Z;return}var c7,E2,Tz="default",g7,S6;var k6=T(()=>{N$();v();C1();S7();u8();c7=class c7{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($))}};E2=new Map;g7=["project","local"];S6=class S6 extends qz{provider="claude";tokenSourceId;opts;input=new c7;query=null;abortController=new AbortController;alive=!0;expectedExit=!1;exitPromise;resolveExit;started=!1;pendingPermissions=new Map;pendingInjectedContext=[];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?R0($.model):null}sendInitialize(){if(this.started)return;this.started=!0;let $=O6(this.opts.model),Z=this.opts.profile;if(Z)K(`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??xz(Z),Q=Cz(Z),Y=Z?.strictMcp===!0,V=Z?.loadProjectMcp!==!1?Nz(this.opts.workDir):void 0;try{let X=Lz();K(`claude-agent-process: spawn SDK query model=${$??"default"} effort=${this.opts.effort} cwd=${this.opts.workDir} executable=${X.description}`),this.query=_z({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:Tz,env:this.opts.transformEnv?this.opts.transformEnv({...process.env,PATH:f7(),...f.claude.env}):{...process.env,PATH:f7(),...f.claude.env},settingSources:[...J],tools:Q,...Y?{strictMcpConfig:!0}:{},...V?{mcpServers:V}:{},toolConfig:{askUserQuestion:{previewFormat:"markdown"}},canUseTool:(H,W,z)=>this.canUseTool(H,W,z),includePartialMessages:!1,systemPrompt:{type:"preset",preset:"claude_code",...this.opts.appendSystemPrompt?{append:this.opts.appendSystemPrompt}:{}},stderr:(H)=>{let W=H.trim();if(W)K(`claude-agent-process[stderr]: ${W}`)}}})}catch(X){let H=X instanceof Error?X:Error(String(X));this.emit("error",H),this.finishExit(1,null);return}this.readLoop(this.query)}sendUserText($,Z=[]){if(!this.alive){K("claude-agent-process: sendUserText ignored on dead process");return}if(!this.started)this.sendInitialize();let J=Z.length?Z.map((Y)=>`[file: ${Y}]`).join(" ")+`
|
|
49
50
|
|
|
50
51
|
`:"",Q=this.pendingInjectedContext.length?this.pendingInjectedContext.splice(0).join(`
|
|
51
52
|
|
|
52
53
|
`)+`
|
|
53
54
|
|
|
54
|
-
`:"";try{this.input.push({type:"user",session_id:this.sessionId??"",message:{role:"user",content:[{type:"text",text:Q+J+$}]},parent_tool_use_id:null,priority:"now"})}catch(Y){let V=Y instanceof Error?Y:Error(String(Y));K(`claude-agent-process: sendUserText failed: ${V.message}`),this.failTurnStart(V)}}sendInterrupt(){this.query?.interrupt().catch(($)=>K(`claude-agent-process: interrupt failed: ${$}`))}sendPermissionResponse($,Z,J){let Q=this.pendingPermissions.get(String($));if(!Q){K(`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??""})}sendToolResult($,Z,J=!1){K("claude-agent-process: sendToolResult ignored; Claude Agent SDK executes built-in tools internally")}sendHookResponse($,Z={}){K("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 K(`claude-agent-process: kill failed: ${J.message}`),J}if(Z){let J=Error(`claude Agent SDK close failed: ${Z.message}`,{cause:Z});throw K(`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(
|
|
55
|
-
`))}canUseTool($,Z,J){if($!=="AskUserQuestion")return Promise.resolve({behavior:"allow",updatedInput:Z});let Q=
|
|
56
|
-
`):"",X=Y||V;this.emitToolResultOnce(J.tool_use_id,X,J.is_error===!0||Q?.interrupted===!0,$.parent_tool_use_id??null)}}handleResultMessage($){if(typeof $.session_id==="string"&&$.session_id)this.sessionId=$.session_id;this.turnActive=!1;let Z=VW($.usage),J=$.modelUsage??$.model_usage,Q=zW(J);if(!Z&&!Q.usage)K(`claude-agent-process: result usage missing rootKeys=${_6($).join(",")||"-"} usageKeys=${_6($.usage).join(",")||"-"} modelUsageKeys=${_6(J).join(",")||"-"}`);if(this.lastUsage=Z,Q.usage)this.cumulativeUsageFromResults=b8(Q.usage),this.lastTotalUsage=b8(Q.usage);else if(Z)this.cumulativeUsageFromResults=HW(this.cumulativeUsageFromResults,Z),this.lastTotalUsage=b8(this.cumulativeUsageFromResults);else this.lastTotalUsage=this.cumulativeUsageFromResults?b8(this.cumulativeUsageFromResults):null;if(Q.contextWindow!=null){let z=R7(this.opts.model,this.tokenSourceId),H=U2.get(z)??0;if(Q.contextWindow>H)U2.set(z,Q.contextWindow),K(`claude-agent-process: SDK contextWindow ${Q.contextWindow} (global max for ${z}, prev ${H||"-"})`);else if(Q.contextWindow<(U2.get(z)??0))K(`claude-agent-process: SDK contextWindow ${Q.contextWindow} ignored (global max ${U2.get(z)} locked for ${z})`);if(this.tokenSourceId)for(let[W,G]of Object.entries(J??{})){let _=G?.contextWindow;if(typeof _==="number"&&_>0)G6(this.tokenSourceId,W,_)}}this.lastContextWindow=U2.get(R7(this.opts.model,this.tokenSourceId))??Q.contextWindow??null;let Y=F6(this.opts.workDir,this.sessionId??""),V=XW(Y);if(this.lastContextTokens=O7(V)??(v8(Y)?O7(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 X=typeof $.subtype==="string"?$.subtype:$.is_error?"error":"success";if(this.tokenSourceId&&$.is_error===!0){let z=String($.result??$.error??$.api_error_message??"");if(/context.?window|prompt is too long|exceeds?.*(?:context|token)|too many (?:input )?tokens/i.test(z)){let G=(this.lastModel??(this.opts.model?.trim()||"claude:default")).replace(/^claude:/,"");D7(this.tokenSourceId,G),K(`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:X,is_error:$.is_error===!0||X!=="success"},this.emit("result",{subtype:X,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})}}});import{randomUUID as MW}from"node:crypto";async function P6($){let Z=await z$("feishu chat.get",()=>b.im.chat.get({path:{chat_id:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)Y$("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 A6($,Z){let J=await z$("feishu tasklist.create",()=>b.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)Y$("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 M6($){let Z=await z$("feishu tasklist.delete",()=>b.task.v2.tasklist.delete({path:{tasklist_guid:$}}));if(Z.code&&Z.code!==0)Y$("feishu tasklist.delete",Z)}async function A2($){let Z=[],J;do{let Q=await z$("feishu section.list",()=>b.task.v2.section.list({params:{resource_type:"tasklist",resource_id:$,page_size:50,...J?{page_token:J}:{}}}));if(Q.code&&Q.code!==0)Y$("feishu section.list",Q);for(let Y of Q.data?.items??[]){if(!Y.guid||!Y.name)continue;Z.push({guid:Y.guid,name:Y.name,isDefault:Y.is_default})}J=Q.data?.has_more?Q.data?.page_token:void 0}while(J);return Z}async function O6($){let Z=await z$("feishu section.create",()=>b.task.v2.section.create({data:{resource_type:"tasklist",resource_id:$.tasklistGuid,name:$.name,...$.insertAfter?{insert_after:$.insertAfter}:{}}}));if(Z.code&&Z.code!==0)Y$("feishu section.create",Z);let J=Z.data?.section?.guid;if(!J)throw Error(`feishu section.create returned no guid for "${$.name}"`);return J}async function f8($){let Z=await z$("feishu section.get",()=>b.task.v2.section.get({path:{section_guid:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)Y$("feishu section.get",Z);let J=Z.data?.section;if(!J?.guid)throw Error(`feishu section.get returned no section: ${$}`);return{guid:J.guid,name:J.name??"",isDefault:J.is_default,tasklistGuid:J.tasklist?.guid}}async function R6($,Z){let J=await z$("feishu section.patch",()=>b.task.v2.section.patch({path:{section_guid:$},params:{user_id_type:"open_id"},data:{section:{name:Z},update_fields:["name"]}}));if(J.code&&J.code!==0)Y$("feishu section.patch",J);let Q=J.data?.section;if(!Q?.guid)throw Error(`feishu section.patch returned no section: ${$}`);return{guid:Q.guid,name:Q.name??"",isDefault:Q.is_default,tasklistGuid:Q.tasklist?.guid}}async function j6($){let Z=await z$("feishu section.delete",()=>b.task.v2.section.delete({path:{section_guid:$}}));if(Z.code&&Z.code!==0)Y$("feishu section.delete",Z)}async function V0($,Z){let J=[],Q;do{let Y=await z$("feishu section.tasks",()=>b.task.v2.section.tasks({path:{section_guid:$},params:{page_size:50,...typeof Z==="boolean"?{completed:Z}:{},...Q?{page_token:Q}:{}}}));if(Y.code&&Y.code!==0)Y$("feishu section.tasks",Y);for(let V of Y.data?.items??[]){if(!V.guid)continue;J.push({guid:V.guid,summary:V.summary??"",completedAt:V.completed_at,subtaskCount:V.subtask_count})}Q=Y.data?.has_more?Y.data?.page_token:void 0}while(Q);return J}async function E6($,Z){let J=[],Q;do{let Y=await z$("feishu tasklist.tasks",()=>b.task.v2.tasklist.tasks({path:{tasklist_guid:$},params:{page_size:50,user_id_type:"open_id",...typeof Z==="boolean"?{completed:Z}:{},...Q?{page_token:Q}:{}}}));if(Y.code&&Y.code!==0)Y$("feishu tasklist.tasks",Y);for(let V of Y.data?.items??[]){if(!V.guid)continue;J.push({guid:V.guid,summary:V.summary??"",completedAt:V.completed_at,subtaskCount:V.subtask_count})}Q=Y.data?.has_more?Y.data?.page_token:void 0}while(Q);return J}async function T6($){let Z=`lodestar-default-section-discovery-${Date.now()}-${MW().slice(0,8)}`,J="";try{let Q=await z$("feishu task.create",()=>b.task.v2.task.create({params:{user_id_type:"open_id"},data:{summary:Z,tasklists:[{tasklist_guid:$}]}}));if(Q.code&&Q.code!==0)Y$("feishu task.create",Q);let Y=Q.data?.task;if(J=Y?.guid??"",!Y||!J)throw Error("feishu task.create returned no guid during default section discovery");let V=Y.tasklists?.find((H)=>H.tasklist_guid===$)?.section_guid;if(V)return V;let z=(await M2(J)).tasklists?.find((H)=>H.tasklist_guid===$)?.section_guid;if(!z)throw Error(`failed to discover default section guid for tasklist ${$}`);return z}finally{if(J)await N7(J)}}async function N7($){let Z=await z$("feishu task.delete",()=>b.task.v2.task.delete({path:{task_guid:$}}));if(Z.code&&Z.code!==0)Y$("feishu task.delete",Z)}async function M2($){let Z=await z$("feishu task.get",()=>b.task.v2.task.get({path:{task_guid:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)Y$("feishu task.get",Z);let J=Z.data?.task;if(!J)throw Error(`feishu task.get returned no task: ${$}`);return J}async function x6($){let Z=[],J;do{let Q=await z$("feishu comment.list",()=>b.task.v2.comment.list({params:{resource_type:"task",resource_id:$,direction:"asc",page_size:50,user_id_type:"open_id",...J?{page_token:J}:{}}}));if(Q.code&&Q.code!==0)Y$("feishu comment.list",Q);for(let Y of Q.data?.items??[]){if(!Y.id)continue;Z.push({id:Y.id,content:Y.content??"",createdAt:Y.created_at,updatedAt:Y.updated_at,creator:Y.creator})}J=Q.data?.has_more?Q.data?.page_token:void 0}while(J);return Z}async function P0($,Z){let J=await z$("feishu comment.create",()=>b.task.v2.comment.create({data:{resource_type:"task",resource_id:$,content:Z},params:{user_id_type:"open_id"}}));if(J.code&&J.code!==0)Y$("feishu comment.create",J);let Q=J.data?.comment?.id;if(!Q)throw Error(`feishu comment.create returned no id for task ${$}`);return Q}async function O2($,Z,J){let Q=await z$("feishu task.addTasklist",()=>b.task.v2.task.addTasklist({path:{task_guid:$},data:{tasklist_guid:Z,section_guid:J},params:{user_id_type:"open_id"}}));if(Q.code&&Q.code!==0)Y$("feishu task.addTasklist",Q)}function S7($,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,V=Q.msg??Q.message??J.msg??J.message??"unknown error",X=Q.error?.permission_violations??Q.permission_violations??J.error?.permission_violations,z=Array.isArray(X)?X.map((H)=>H?.scope??H?.subject??H?.name??H).filter(Boolean).join(", "):"";return`${$} failed code=${Y??"unknown"} msg=${V}${z?` missing_scopes=${z}`:""}`}async function z$($,Z){try{return await Z()}catch(J){Y$($,J)}}function Y$($,Z){throw Error(S7($,Z))}var k7=E(()=>{d()});var o={};V2(o,{writeAliveMarker:()=>C2,urgentApp:()=>g0,uploadImageKey:()=>$9,uploadAndSend:()=>Z9,updateCard:()=>z0,unbindSessionChat:()=>m8,truncateTurnAnchors:()=>wW,tempProjectName:()=>d$,tempChatName:()=>u6,setSessionBranchBase:()=>vW,setPendingConversationLaunchChecked:()=>A0,sendTextRaw:()=>C,sendText:()=>A,sendImage:()=>VJ,sendFile:()=>XJ,sendCard:()=>p,seedTurnAnchors:()=>bW,sanitizeSessionName:()=>k2,resolveProjectDir:()=>I0,replaceTurnAnchors:()=>y$,registerTempSessionLease:()=>b6,refreshChatList:()=>N2,readAliveMarker:()=>r6,provisionProject:()=>J9,projectProfile:()=>u8,preferredChatForSession:()=>$$,patchTasklistSectionName:()=>R6,moveTaskToSection:()=>O2,loadTempSessionLeases:()=>w6,loadSessionTurnsMap:()=>m6,loadSessionResumeMap:()=>I6,loadSessionModelMap:()=>p6,loadSessionChatMap:()=>f6,listTasklistTasks:()=>E6,listTasklistSections:()=>A2,listTaskComments:()=>x6,listSectionTasks:()=>V0,listNormalChatIdsByName:()=>l8,isOpenAIChatGPTAuthenticated:()=>S2,hasTempSessionLease:()=>v6,getTurnAnchors:()=>x1,getTenantToken:()=>X0,getTasklistSection:()=>f8,getTask:()=>M2,getSessionResumeRef:()=>T2,getSessionResume:()=>xW,getSessionModelSelection:()=>d6,getSessionModel:()=>IW,getSessionBranchBase:()=>x2,getPendingConversationLaunch:()=>y2,formatFeishuApiError:()=>S7,findNormalChatIdByName:()=>i8,fetchChatOwnerOpenId:()=>P6,fetchChatName:()=>e6,ensureChatForSession:()=>o6,downloadAttachment:()=>C1,discoverTasklistDefaultSectionGuid:()=>T6,disbandChatForSessionExact:()=>s6,disbandChatForSession:()=>t6,deleteTasklistSection:()=>j6,deleteTasklistByGuid:()=>M6,deleteTaskByGuid:()=>N7,deleteReaction:()=>B$,createTempChatForSession:()=>a6,createTasklistWithOwner:()=>A6,createTasklistSection:()=>O6,client:()=>b,clearTurnAnchors:()=>fW,clearTempSessionLease:()=>jW,clearSessionResumeChecked:()=>h6,clearSessionResume:()=>yW,clearSessionModelSelection:()=>hW,clearSessionConversationState:()=>n6,chatNameCache:()=>Z$,chatIdForSession:()=>y1,bindSessionToChat:()=>E1,bindSessionResumeChecked:()=>E2,bindSessionResume:()=>TW,bindSessionModelChecked:()=>i6,bindSessionModel:()=>l6,appendTurnAnchorChecked:()=>p8,appendTurnAnchor:()=>kW,addTaskComment:()=>P0,addReaction:()=>P$,PROJECTS_ROOT:()=>n7});import*as g7 from"@larksuiteoapi/node-sdk";import{execSync as m7}from"node:child_process";import{randomUUID as k6}from"node:crypto";import{existsSync as OW,mkdirSync as C6,readFileSync as f0,statSync as c7,writeFileSync as u7}from"node:fs";import{readFile as p7}from"node:fs/promises";import{homedir as w7}from"node:os";import{basename as v0,extname as RW,isAbsolute as l7,join as h8}from"node:path";function g8(){let $={};for(let[Z,J]of H$)$[Z]=J;U$(AZ,$)}function w6(){H$.clear();try{let $=JSON.parse(f0(AZ,"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"||!d$(Q.sessionName)||typeof Q.createdAt!=="number"||!Number.isFinite(Q.createdAt)){K(`feishu: rejected malformed temp-session lease chat=${Z}`);continue}H$.set(Z,{chatId:Z,sessionName:Q.sessionName,createdAt:Q.createdAt})}K(`feishu: loaded ${H$.size} temporary-session leases`)}catch($){if($?.code!=="ENOENT")K(`feishu: load temp-session leases failed: ${$?.message??$}`)}}function b6($,Z){if(!d$($))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 H$.values())if(Y.sessionName===$&&Y.chatId!==Z)throw Error(`temporary session name "${$}" is already leased to ${Y.chatId}`);let J=H$.get(Z),Q={sessionName:$,chatId:Z,createdAt:Date.now()};H$.set(Z,Q);try{g8()}catch(Y){if(J)H$.set(Z,J);else H$.delete(Z);throw Y}}function v6($,Z){let J=H$.get(Z);return J?.sessionName===$&&J.chatId===Z}function jW($,Z){let J=[...H$.entries()].filter(([Q,Y])=>Y.sessionName===$&&(!Z||Q===Z));if(!J.length)return;for(let[Q]of J)H$.delete(Q);try{g8()}catch(Q){for(let[Y,V]of J)H$.set(Y,V);throw Q}}function u8($){return f.projects[$]}function I0($){return u8($)?.cwd?.trim()||h8(n7,$)}function h0($,Z={}){return fetch($,{...Z,signal:Z.signal??AbortSignal.timeout(EW)})}async function X0(){if(I8&&Date.now()<b7)return I8;return y6??=(async()=>{let $=await h0("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({app_id:i7,app_secret:d7})}),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 I8=Z.tenant_access_token,b7=Date.now()+Math.max(0,(Z.expire??7200)-60)*1000,I8})().finally(()=>{y6=null}),y6}function f6(){try{let $=JSON.parse(f0(FZ,"utf8"));for(let[Z,J]of Object.entries($))if(typeof J==="string")$$.set(Z,J);K(`feishu: loaded ${$$.size} session→chat bindings`)}catch($){if($?.code!=="ENOENT")K(`feishu: load session-chat-map failed: ${$?.message??$}`)}}function r7(){try{N6()}catch($){K(`feishu: save session-chat-map failed: ${$}`)}}function N6(){let $={};for(let[Z,J]of $$)$[Z]=J;U$(FZ,$)}function E1($,Z){if($$.get($)===Z)return;let J=$$.get($);$$.set($,Z),r7(),K(`feishu: bound session "${$}" → ${Z}${J?` (was ${J})`:""}`)}function m8($){let Z=$$.get($);if(!Z)return;$$.delete($),r7(),K(`feishu: unbound session "${$}" from ${Z}`)}function j1($,Z){let J=u.get($)??{};J[Z.provider]=Z,u.set($,J)}function v7($,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"||!l7(J.cwd))return null;return{provider:Q,sessionId:Y,cwd:J.cwd}}function f7($){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"||!l7($.cwd))throw Error(`cannot bind a conversation without an absolute cwd: ${String($.cwd)}`);return{provider:$.provider,sessionId:Z,cwd:$.cwd}}function o7($,Z,J){if(typeof $!=="string")return f7($);if(!Z)throw Error("cannot bind a conversation without a provider");return f7({provider:Z,sessionId:$,cwd:J??null})}function I6(){try{let $=JSON.parse(f0(DZ,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("resume map must contain an object");u.clear();for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){j1(Z,{provider:"codex",sessionId:J.trim(),cwd:null});continue}if(!J||typeof J!=="object"||Array.isArray(J))continue;let Q=J,Y=v7(Q);if(Y){j1(Z,Y);continue}for(let V of["codex","claude"]){let X=Q[V];if(typeof X==="string"&&X.trim()){j1(Z,{provider:V,sessionId:X.trim(),cwd:null});continue}let z=v7(X,V);if(z)j1(Z,z)}}K(`feishu: loaded ${u.size} session→resume bindings`)}catch($){if($?.code!=="ENOENT")K(`feishu: load session-resume-map failed: ${$?.message??$}`)}}function S6(){try{j2()}catch($){K(`feishu: save session-resume-map failed: ${$}`)}}function j2(){let $={};for(let[Z,J]of u){let Q={};if(J.codex)Q.codex={...J.codex};if(J.claude)Q.claude={...J.claude};$[Z]=Q}U$(DZ,$)}function TW($,Z,J,Q){let Y=o7(Z,J,Q),V=u.get($)?.[Y.provider];if(V?.sessionId===Y.sessionId&&V.cwd===Y.cwd)return;j1($,Y),S6()}function E2($,Z,J,Q){let Y=o7(Z,J,Q),V=u.get($),X=V?{...V}:void 0,z=V?.[Y.provider];if(z?.sessionId===Y.sessionId&&z.cwd===Y.cwd)return;j1($,Y);try{j2()}catch(H){if(X)u.set($,X);else u.delete($);throw H}}function xW($,Z="codex"){return u.get($)?.[Z]?.sessionId??null}function T2($,Z="codex"){let J=u.get($)?.[Z];return J?{...J}:null}function yW($,Z){let J=u.get($);if(!J)return;if(!Z){u.delete($),S6();return}if(J[Z]===void 0)return;if(delete J[Z],!J.codex&&!J.claude)u.delete($);S6()}function h6($,Z){let J=u.get($);if(!J||Z&&J[Z]===void 0)return;let Q={...J};if(!Z)u.delete($);else{let Y={...J};if(delete Y[Z],!Y.codex&&!Y.claude)u.delete($);else u.set($,Y)}try{j2()}catch(Y){throw u.set($,Q),Y}}function a7($){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 t7($){if(!$||typeof $!=="object")return null;let Z=$,J=Z.source;if(!J||typeof J!=="object")return null;let Q=a7(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 s7($){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=a7(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=t7(Z.through);return Y?{kind:"fork",source:J,through:Y}:null})();if(!Q)return null;try{X$(Q,J.provider)}catch{return null}return Q}function CW($){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 NW($,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=t7(J.checkpoint);if(Q&&!Y)return null;if(!Y){if(Z!=="claude")return null;let V=typeof J.uuid==="string"?J.uuid.trim():"",X=typeof J.sid==="string"?J.sid.trim():"";if(!V||!X)return null;Y={provider:"claude",kind:"assistant-message",id:V,source:{provider:"claude",sessionId:X,cwd:null}}}return{checkpoint:Y,preview:String(J.preview??""),ts:J.ts,writes:CW(J.writes)}}function SW($){if(!$||typeof $!=="object")return null;let Z=$,J=s7(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 g6($){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 m6(){try{let $=JSON.parse(f0(UZ,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("turns map must contain an object");h.clear();let Z=0,J=0;for(let[Q,Y]of Object.entries($)){let V,X,z=null;if(Array.isArray(Y))V=Y,X=null;else if(Y&&typeof Y==="object"&&!Array.isArray(Y)){let _=Y;if(!Array.isArray(_.anchors)||!Object.prototype.hasOwnProperty.call(_,"base")){J++;continue}if(V=_.anchors,_.base===null)X=null;else{let B=s7(_.base);if(!B){J++;continue}X=B}if(Object.prototype.hasOwnProperty.call(_,"pendingLaunch")){let B=SW(_.pendingLaunch);if(!B){J++;continue}z=B}}else{J++;continue}let H=u.get(Q),W=H?.claude!==void 0&&H.codex===void 0?"claude":null,G=[];for(let _ of V){let B=NW(_,W);if(B)G.push(B);else J++}if(G.length||X!==null||z)h.set(Q,{base:X,anchors:G,...z?{pendingLaunch:z}:{}}),Z+=G.length}if(K(`feishu: loaded ${Z} turn anchors across ${h.size} sessions`),J>0)K(`feishu: rejected ${J} malformed turn anchors while loading`)}catch($){if($?.code!=="ENOENT")K(`feishu: load session-turns-map failed: ${$?.message??$}`)}}function c6(){try{T1()}catch($){K(`feishu: save session-turns-map failed: ${$}`)}}function T1(){let $={};for(let[Z,J]of h)$[Z]=J;U$(UZ,$)}function kW($,Z){try{p8($,Z)}catch(J){K(`feishu: append turn anchor failed: ${J}`)}}function p8($,Z){let J=h.get($),Q=[...J?.anchors??[],Z],Y=J?.base??null;if(Q.length>I7){let V=Q.splice(0,Q.length-I7),X=V[V.length-1].checkpoint;Y={kind:"fork",source:X.source,through:X}}h.set($,{base:Y,anchors:Q,...J?.pendingLaunch?{pendingLaunch:J.pendingLaunch}:{}});try{T1()}catch(V){if(J)h.set($,J);else h.delete($);throw V}}function x1($){return h.get($)?.anchors??[]}function x2($){return h.get($)?.base??null}function y2($){let Z=h.get($)?.pendingLaunch;return Z?g6(Z):null}function A0($,Z){if(Z){if(Z.launch.source.cwd===null)throw Error("pending conversation launch source cwd is missing");X$(Z.launch,"claude",Z.launch.source.cwd)}let J=h.get($),Q=J?.base??null,Y=J?.anchors.slice()??[];if(!Z&&Y.length===0&&Q===null)h.delete($);else h.set($,{base:Q,anchors:Y,...Z?{pendingLaunch:g6(Z)}:{}});try{T1()}catch(V){if(J)h.set($,J);else h.delete($);throw V}}function wW($,Z){let J=h.get($);if(!J||J.anchors.length<=Z)return;h.set($,{...J,anchors:J.anchors.slice(0,Z)}),c6()}function bW($,Z){if(Z.length===0)return;h.set($,{base:null,anchors:Z.slice()}),c6()}function y$($,Z,J,Q){let Y=h.get($),V=Q===void 0?Y?.pendingLaunch:Q??void 0,X=V?g6(V):void 0;if(Z.length===0&&J===null&&!X)h.delete($);else h.set($,{base:J,anchors:Z.slice(),...X?{pendingLaunch:X}:{}});try{T1()}catch(z){if(Y)h.set($,Y);else h.delete($);throw z}}function vW($,Z){y$($,x1($),Z)}function fW($){if(!h.has($))return;h.delete($),c6()}function d$($){return h7.test($)?$.replace(h7,""):null}function u6($,Z=[]){let J=new Date,Q=(z)=>String(z).padStart(2,"0"),Y=`${Q(J.getMonth()+1)}${Q(J.getDate())}-${Q(J.getHours())}${Q(J.getMinutes())}`,V=new Set([...Z$.values(),...h.keys(),...Z]),X=`${$}*${Y}`;for(let z=2;V.has(X);z++)X=`${$}*${Y}-${z}`;return X}function p6(){try{let $=JSON.parse(f0(PZ,"utf8"));for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){e.set(Z,{provider:A1(J),model:J,effort:null});continue}if(!J||typeof J!=="object")continue;let{model:Q,provider:Y}=J,V=Y==="claude"||Y==="codex"?Y:typeof Q==="string"&&Q.trim()?A1(Q):"claude",X=typeof Q==="string"&&Q.trim()?Q:null;if(V==="claude"&&!X)continue;let{effort:z,tokenSourceId:H}=J,W=typeof H==="string"&&H.trim()?H.trim():null,G=V==="claude"?D0(z)?z:null:l$(z)?z:null;e.set(Z,{provider:V,model:X,effort:G,...W?{tokenSourceId:W}:{}})}K(`feishu: loaded ${e.size} session→model bindings`)}catch($){if($?.code!=="ENOENT")K(`feishu: load session-model-map failed: ${$?.message??$}`)}}function e7(){try{c8()}catch($){K(`feishu: save session-model-map failed: ${$}`)}}function c8(){let $={};for(let[Z,J]of e)$[Z]=J;U$(PZ,$)}function l6($,Z,J,Q,Y){let V=e.get($);if(V?.provider===Z&&V.model===J&&V.effort===Q&&(V.tokenSourceId??null)===(Y??null))return;e.set($,{provider:Z,model:J,effort:Q,...Y?{tokenSourceId:Y}:{}}),e7()}function i6($,Z,J,Q,Y){let V=e.get($),X={provider:Z,model:J,effort:Q,...Y?{tokenSourceId:Y}:{}};if(V?.provider===Z&&V.model===J&&V.effort===Q&&(V.tokenSourceId??null)===(Y??null))return;e.set($,X);try{c8()}catch(z){if(V)e.set($,V);else e.delete($);throw z}}function d6($){let Z=e.get($);if(Z)return Z;let J=d$($);return J?e.get(J)??null:null}function IW($){return e.get($)?.model??null}function hW($){if(!e.has($))return;e.delete($),e7()}function n6($){let Z=$$.get($),J=u.get($),Q=e.get($),Y=h.get($),V=[...H$.entries()].filter(([,X])=>X.sessionName===$);$$.delete($),u.delete($),e.delete($),h.delete($);for(let[X]of V)H$.delete(X);try{N6(),j2(),c8(),T1(),g8()}catch(X){if(Z)$$.set($,Z);if(J)u.set($,J);if(Q)e.set($,Q);if(Y)h.set($,Y);for(let[H,W]of V)H$.set(H,W);let z=[X];for(let H of[N6,j2,c8,T1,g8])try{H()}catch(W){z.push(W)}throw z.length===1?z[0]:AggregateError(z,`failed to clear and restore conversation state for ${$}`)}}function C2($){try{U$(B8,$)}catch(Z){K(`feishu: write alive marker failed: ${Z}`)}}function r6(){if(!OW(B8))return[];try{let $=f0(B8,"utf8"),Z=JSON.parse($);return Array.isArray(Z)?Z.filter((J)=>typeof J==="string"):[]}catch($){return K(`feishu: read alive marker failed: ${$}`),[]}}function y1($){let Z=$$.get($);if(Z){let Q=Z$.get(Z);if(Q&&Q!==$)K(`feishu: chatIdForSession("${$}"): persisted binding ${Z} has cached name "${Q}", using persisted binding`);return Z}let J=[];for(let[Q,Y]of Z$)if(Y===$)J.push(Q);if(J.length===1)return J[0];if(J.length>1)K(`feishu: chatIdForSession("${$}"): ${J.length} candidates with no binding — [${J.join(", ")}]`);return null}async function N2(){try{let $;do{let Z=await b.im.chat.list({params:{page_size:100,...$?{page_token:$}:{}}});for(let J of Z.data?.items??[])if(J.chat_id&&J.name)Z$.set(J.chat_id,J.name);$=Z.data?.page_token}while($);K(`feishu: refreshed chat list — ${Z$.size} groups`)}catch($){K(`feishu: refresh chat list failed: ${$}`)}}async function l8(){let $=new Map,Z;do{let J=await b.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;Z$.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 i8($){let Z=$$.get($);if(Z&&Z$.get(Z)===$){let V=await ZJ(Z);if(V.name===$&&JJ(V.status))return Z;Z$.delete(Z),m8($)}let Q=(await l8()).get($)??[];if(Q.length===0)return null;let 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 o6($,Z){if(!Z)throw Error("missing sender open_id; cannot add user to worktree group");let J=await i8($);if(J){let V=await gW(J,Z);return E1($,J),{chatId:J,created:!1,joined:V}}let Q=await b.im.chat.create({params:{user_id_type:"open_id",uuid:k6()},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 Z$.set(Y,$),E1($,Y),{chatId:Y,created:!0,joined:!0}}async function a6($,Z){if(!Z)throw Error("missing sender open_id; cannot create temporary group");if(await i8($))throw Error(`temporary group name already exists: ${$}`);let Q=await b.im.chat.create({params:{user_id_type:"open_id",uuid:k6()},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 Z$.set(Y,$),E1($,Y),{chatId:Y,created:!0,joined:!0}}async function t6($){let Z=await i8($);if(!Z)return m8($),{chatId:null,disbanded:!1};let J=await b.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(Z$.delete(Z),$$.get($)===Z)m8($);return{chatId:Z,disbanded:!0}}async function s6($,Z){if(!Z)throw Error("cannot disband a temporary session without an exact chat_id");let J=await ZJ(Z);if(J.name!==$)throw Error(`refusing to delete chat ${Z}: expected name "${$}", got "${J.name??""}"`);if(!JJ(J.status))throw Error(`refusing to delete chat ${Z}: status=${J.status??"unknown"}`);let Q=await b.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 Z$.delete(Z),{chatId:Z,disbanded:!0}}async function gW($,Z){let J;do{let Y=await b.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 V of Y.data?.items??[])if(V.member_id===Z)return!1;J=Y.data?.page_token}while(J);let Q=await b.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 e6($){try{let Z=await X0(),Q=await(await h0(`https://open.feishu.cn/open-apis/im/v1/chats/${encodeURIComponent($)}`,{headers:{Authorization:`Bearer ${Z}`}})).json();if(Q?.code!==0)return K(`feishu: fetchChatName ${$} code=${Q?.code} msg=${Q?.msg}`),null;let Y=Q.data?.name;if(typeof Y==="string"&&Y)return Z$.set($,Y),K(`feishu: fetchChatName ${$} → "${Y}" (point lookup)`),Y;return K(`feishu: fetchChatName ${$} — chat has no name (unnamed group?)`),null}catch(Z){return K(`feishu: fetchChatName ${$} failed: ${Z}`),null}}async function $J($,Z,J,Q){let Y=k6(),V=null;for(let X=0;X<R2.length;X++){if(R2[X]>0)await new Promise((z)=>setTimeout(z,R2[X]));try{let z=await b.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:Z,msg_type:J,content:Q,uuid:Y}});if(z?.code&&z.code!==0)return K(`feishu: send${$==="text"?"Text":"Card"} rejected chat=${Z} code=${z.code} msg=${z.msg}`),null;return z?.data?.message_id??null}catch(z){V=z,K(`feishu: send${$==="text"?"Text":"Card"} attempt ${X+1}/${R2.length} chat=${Z} failed: ${z}`)}}return K(`feishu: send${$==="text"?"Text":"Card"} chat=${Z} EXHAUSTED ${R2.length} retries: ${V}`),null}async function ZJ($){let Z=await b.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 JJ($){return $===null||$==="normal"}async function A($,Z){return $J("text",$,"text",JSON.stringify({text:Z}))}async function p($,Z){return $J("card",$,"interactive",JSON.stringify(Z))}async function z0($,Z){let J=await b.im.v1.message.patch({path:{message_id:$},data:{content:JSON.stringify(Z)}});if(J?.code&&J.code!==0)throw Error(`feishu message.patch failed code=${J.code} msg=${J.msg}`)}async function C($,Z){try{let J=await X0(),Y=await(await h0("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 K(`feishu: sendTextRaw rejected chat=${$} code=${Y?.code} msg=${Y?.msg}`),null;return Y.data?.message_id??null}catch(J){return K(`feishu: sendTextRaw chat=${$} failed: ${J}`),null}}async function P$($,Z){if(!$)return null;try{return(await b.im.messageReaction.create({path:{message_id:$},data:{reaction_type:{emoji_type:Z}}}))?.data?.reaction_id??null}catch(J){return K(`feishu: addReaction ${Z} on ${$} failed: ${J}`),null}}async function B$($,Z){if(!$||!Z)return;try{await b.im.messageReaction.delete({path:{message_id:$,reaction_id:Z}})}catch(J){K(`feishu: deleteReaction ${Z} on ${$} failed: ${J}`)}}async function g0($,Z){if(!$){K("feishu: urgentApp skip — missing messageId");return}if(Z.length===0){K(`feishu: urgentApp skip — empty openIds (msg=${$})`);return}let J=await X0(),Q=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/urgent_app?user_id_type=open_id`;try{let V=await(await h0(Q,{method:"PATCH",headers:{Authorization:`Bearer ${J}`,"Content-Type":"application/json"},body:JSON.stringify({user_id_list:Z})})).json();if(V?.code!==0){K(`feishu: urgentApp ${$} code=${V?.code} msg=${V?.msg}`);return}let X=V.data?.invalid_user_id_list??[],z=Z.length-X.length;K(`feishu: urgentApp ${$} ok — delivered=${z}${X.length?` invalid=${X.length}`:""}`)}catch(Y){K(`feishu: urgentApp ${$} failed: ${Y}`)}}async function C1($,Z,J,Q){try{let Y=await X0(),V=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/resources/${Z}?type=${J}`,X=await h0(V,{headers:{Authorization:`Bearer ${Y}`}});if(!X.ok){K(`feishu: download ${J} HTTP ${X.status}: ${(await X.text()).slice(0,200)}`);return}let z=Buffer.from(await X.arrayBuffer());C6(MZ,{recursive:!0});let H=Q?Q.replace(/[^a-zA-Z0-9._-]/g,"_"):`${Z.replace(/[^a-zA-Z0-9_-]/g,"_")}.png`,W=h8(MZ,`${Date.now()}-${H}`);return u7(W,z),K(`feishu: downloaded ${J} ${W} (${z.length}B)`),W}catch(Y){K(`feishu: download ${J} failed: ${Y instanceof Error?Y.message:Y}`);return}}function cW($){return mW.has(RW($).toLowerCase())}async function YJ($){let Z=await X0(),J=new Blob([Uint8Array.from(await p7($))]),Q=new FormData;Q.append("image_type","message"),Q.append("image",J,v0($));let V=await(await h0("https://open.feishu.cn/open-apis/im/v1/images",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Q})).json();if(V?.code!==0)return K(`feishu: uploadImage ${$} code=${V.code} msg=${V.msg}`),null;return V.data?.image_key??null}async function $9($){try{let Z=c7($);if(!Z.isFile())return K(`feishu: uploadImageKey not a file — ${$}`),null;if(Z.size>QJ)return K(`feishu: uploadImageKey oversize — ${$} (${(Z.size/1024/1024).toFixed(1)} MB)`),null}catch(Z){return K(`feishu: uploadImageKey stat failed — ${$}: ${Z}`),null}return YJ($)}async function uW($){let Z=await X0(),J=new Blob([Uint8Array.from(await p7($))]),Q=new FormData;Q.append("file_type","stream"),Q.append("file_name",v0($)),Q.append("file",J,v0($));let V=await(await h0("https://open.feishu.cn/open-apis/im/v1/files",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Q})).json();if(V?.code!==0)return K(`feishu: uploadFile ${$} code=${V.code} msg=${V.msg}`),null;return V.data?.file_key??null}async function VJ($,Z){try{let J=await b.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 K(`feishu: sendImage rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return K(`feishu: sendImage failed chat=${$}: ${J}`),null}}async function XJ($,Z){try{let J=await b.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 K(`feishu: sendFile rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return K(`feishu: sendFile failed chat=${$}: ${J}`),null}}async function Z9($,Z){try{let Q=c7(Z);if(!Q.isFile())return await A($,`❌ 出站文件: 路径不是文件 — ${Z}`),!1;if(Q.size>QJ)return await A($,`❌ 出站文件: ${v0(Z)} 超过 30 MB (${(Q.size/1024/1024).toFixed(1)} MB)`),!1}catch(Q){return await A($,`❌ 出站文件: 无法读取 ${Z} (${Q})`),!1}let J=cW(Z);try{if(J){let Q=await YJ(Z);if(!Q)return await A($,`❌ 出站图片上传失败: ${v0(Z)}`),!1;return await VJ($,Q)!=null}else{let Q=await uW(Z);if(!Q)return await A($,`❌ 出站文件上传失败: ${v0(Z)}`),!1;return await XJ($,Q)!=null}}catch(Q){return K(`feishu: uploadAndSend ${Z} failed: ${Q}`),await A($,`❌ 出站文件异常: ${v0(Z)} — ${Q}`),!1}}function J9($){C6($,{recursive:!0}),K(`feishu: provisioned ${$}`);let Z=h8(w7(),".codex","config.toml");try{C6(h8(w7(),".codex"),{recursive:!0});let J="";try{J=f0(Z,"utf8")}catch{}let Q=`[projects.${JSON.stringify($)}]`;if(!J.includes(Q)){let Y=J.trimEnd();J=`${Y}${Y?`
|
|
55
|
+
`:"";try{this.input.push({type:"user",session_id:this.sessionId??"",message:{role:"user",content:[{type:"text",text:Q+J+$}]},parent_tool_use_id:null,priority:"now"})}catch(Y){let V=Y instanceof Error?Y:Error(String(Y));K(`claude-agent-process: sendUserText failed: ${V.message}`),this.failTurnStart(V)}}sendInterrupt(){this.query?.interrupt().catch(($)=>K(`claude-agent-process: interrupt failed: ${$}`))}sendPermissionResponse($,Z,J){let Q=this.pendingPermissions.get(String($));if(!Q){K(`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??""})}sendToolResult($,Z,J=!1){K("claude-agent-process: sendToolResult ignored; Claude Agent SDK executes built-in tools internally")}sendHookResponse($,Z={}){K("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 K(`claude-agent-process: kill failed: ${J.message}`),J}if(Z){let J=Error(`claude Agent SDK close failed: ${Z.message}`,{cause:Z});throw K(`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(Ez)}async setModelSettings($,Z){let J=O6($);if(!j0(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?R0($):"claude:default",this.lastEffort=Z}async setModel($){await this.setModelSettings($,this.opts.effort)}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",V),this.off("exit",X),this.off("error",H)},Y=()=>{if(J)return;J=!0,Q(),$()},V=(W)=>{if(J)return;if((W?.text??"").includes("Not enough messages to compact"))J=!0,Q(),Z(new D2)},X=()=>{if(J)return;J=!0,Q(),Z(Error("claude thread exited during /compact"))},H=(W)=>{if(J)return;J=!0,Q(),Z(W instanceof Error?W:Error(String(W)))};this.on("context_compacted",Y),this.on("assistant_text",V),this.once("exit",X),this.once("error",H)})}async injectThreadItems($){if(!Array.isArray($)||$.length===0)return;this.pendingInjectedContext.push(["Host-injected prior tool context for this continuation:",JSON.stringify($,null,2)].join(`
|
|
56
|
+
`))}canUseTool($,Z,J){if($!=="AskUserQuestion")return Promise.resolve({behavior:"allow",updatedInput:Z});let Q=yz(Z);if(Q.length===0)return K("claude-agent-process: AskUserQuestion 无有效 questions — allow 原样"),Promise.resolve({behavior:"allow",updatedInput:Z});let Y={...Z,questions:Q},V=`claude_perm_${++this.requestCounter}`,X=J.toolUseID||V,H={request_id:V,tool_name:"AskUserQuestion",input:Y,tool_use_id:X},W=new Promise((z)=>{let G=(B)=>{J.signal.removeEventListener("abort",q),z(B)},q=()=>{if(!this.pendingPermissions.delete(V))return;G({behavior:"deny",message:"aborted"})};J.signal.addEventListener("abort",q,{once:!0}),this.pendingPermissions.set(V,{kind:"dialog",resolve:G,request:H})});return this.emitToolUseOnce(X,"AskUserQuestion",Y,null),this.emit("can_use_tool",H),W}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){K(`claude-agent-process: read loop stopped after requested shutdown: ${J.message}`),this.finishExit(null,null);return}K(`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(),K(`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=(V)=>{if(J)return;J=!0,clearTimeout(Y),Z(V)},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:K(`claude-agent-process: unhandled message type=${Z.type??"unknown"} subtype=${Z.subtype??""}`)}}handleSystemMessage($){switch($.subtype){case"init":if(typeof $.model==="string"&&$.model)this.lastModel=R0($.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":K(`claude-agent-process: api retry attempt=${$.attempt}/${$.max_retries} status=${$.error_status} error=${$.error}`);return;case"permission_denied":K(`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){K("claude-agent-process: task_notification missing task_id");return}if($.status!=="completed"&&$.status!=="failed"&&$.status!=="stopped"){K(`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:K(`claude-agent-process: unhandled system subtype=${String($.subtype??"unknown")}`);return}}handleAssistantMessage($){let Z=$.message;if(typeof $.uuid==="string")this.lastAssistantUuid=$.uuid;if(typeof Z?.model==="string"&&Z.model)this.lastModel=R0(Z.model);let J=Array.isArray(Z?.content)?Z.content:[];for(let Q of J){if(!Q||typeof Q!=="object")continue;if(Q.type==="text"&&typeof Q.text==="string"&&Q.text.length>0){let Y=jz(Q.text);if(Y){if(this.pendingServerToolInputs.push(Y),this.pendingServerToolInputs.length>20)this.pendingServerToolInputs.shift()}if(Rz(Q.text))continue;let V=$.uuid??Z?.id;this.emit("assistant_text",{uuid:V,text:Q.text}),this.emit("assistant_block_stop",{index:V})}else if(Q.type==="tool_use"&&typeof Q.id==="string"&&typeof Q.name==="string")this.emitToolUseOnce(Q.id,Q.name,Q.input??{},$.parent_tool_use_id??null);else if(Q.type==="server_tool_use"&&typeof Q.id==="string"&&typeof Q.name==="string")this.emitToolUseOnce(Q.id,Oz(Q.name),{tool:Q.name,input:this.serverToolInput(Q.name,Q.input??{})},$.parent_tool_use_id??null);else if(Q.type==="tool_result"&&typeof Q.tool_use_id==="string")this.emitToolResultOnce(Q.tool_use_id,Mz(Q.content),Q.is_error===!0,$.parent_tool_use_id??null)}}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=Array.isArray($.message?.content)?$.message.content:[];for(let J of Z){if(!J||typeof J!=="object")continue;if(J.type!=="tool_result"||typeof J.tool_use_id!=="string")continue;let Q=$.tool_use_result,Y=l7(J.content),V=Q&&typeof Q==="object"?[typeof Q.stdout==="string"?Q.stdout:"",typeof Q.stderr==="string"?Q.stderr:""].filter(Boolean).join(`
|
|
57
|
+
`):"",X=Y||V;this.emitToolResultOnce(J.tool_use_id,X,J.is_error===!0||Q?.interrupted===!0,$.parent_tool_use_id??null)}}handleResultMessage($){if(typeof $.session_id==="string"&&$.session_id)this.sessionId=$.session_id;this.turnActive=!1;let Z=Uz($.usage),J=$.modelUsage??$.model_usage,Q=Pz(J);if(!Z&&!Q.usage)K(`claude-agent-process: result usage missing rootKeys=${T6($).join(",")||"-"} usageKeys=${T6($.usage).join(",")||"-"} modelUsageKeys=${T6(J).join(",")||"-"}`);if(this.lastUsage=Z,Q.usage)this.cumulativeUsageFromResults=p8(Q.usage),this.lastTotalUsage=p8(Q.usage);else if(Z)this.cumulativeUsageFromResults=Az(this.cumulativeUsageFromResults,Z),this.lastTotalUsage=p8(this.cumulativeUsageFromResults);else this.lastTotalUsage=this.cumulativeUsageFromResults?p8(this.cumulativeUsageFromResults):null;if(Q.contextWindow!=null){let H=I7(this.opts.model,this.tokenSourceId),W=E2.get(H)??0;if(Q.contextWindow>W)E2.set(H,Q.contextWindow),K(`claude-agent-process: SDK contextWindow ${Q.contextWindow} (global max for ${H}, prev ${W||"-"})`);else if(Q.contextWindow<(E2.get(H)??0))K(`claude-agent-process: SDK contextWindow ${Q.contextWindow} ignored (global max ${E2.get(H)} locked for ${H})`);if(this.tokenSourceId)for(let[z,G]of Object.entries(J??{})){let q=G?.contextWindow;if(typeof q==="number"&&q>0)E6(this.tokenSourceId,z,q)}}this.lastContextWindow=E2.get(I7(this.opts.model,this.tokenSourceId))??Q.contextWindow??null;let Y=y6(this.opts.workDir,this.sessionId??""),V=Dz(Y);if(this.lastContextTokens=h7(V)??(l8(Y)?h7(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 X=typeof $.subtype==="string"?$.subtype:$.is_error?"error":"success";if(this.tokenSourceId&&$.is_error===!0){let H=String($.result??$.error??$.api_error_message??"");if(/context.?window|prompt is too long|exceeds?.*(?:context|token)|too many (?:input )?tokens/i.test(H)){let G=(this.lastModel??(this.opts.model?.trim()||"claude:default")).replace(/^claude:/,"");k7(this.tokenSourceId,G),K(`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:X,is_error:$.is_error===!0||X!=="success"},this.emit("result",{subtype:X,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})}}});import{randomUUID as wz}from"node:crypto";async function w6($){let Z=await G$("feishu chat.get",()=>b.im.chat.get({path:{chat_id:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)V$("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 b6($,Z){let J=await G$("feishu tasklist.create",()=>b.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)V$("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 v6($){let Z=await G$("feishu tasklist.delete",()=>b.task.v2.tasklist.delete({path:{tasklist_guid:$}}));if(Z.code&&Z.code!==0)V$("feishu tasklist.delete",Z)}async function x2($){let Z=[],J;do{let Q=await G$("feishu section.list",()=>b.task.v2.section.list({params:{resource_type:"tasklist",resource_id:$,page_size:50,...J?{page_token:J}:{}}}));if(Q.code&&Q.code!==0)V$("feishu section.list",Q);for(let Y of Q.data?.items??[]){if(!Y.guid||!Y.name)continue;Z.push({guid:Y.guid,name:Y.name,isDefault:Y.is_default})}J=Q.data?.has_more?Q.data?.page_token:void 0}while(J);return Z}async function f6($){let Z=await G$("feishu section.create",()=>b.task.v2.section.create({data:{resource_type:"tasklist",resource_id:$.tasklistGuid,name:$.name,...$.insertAfter?{insert_after:$.insertAfter}:{}}}));if(Z.code&&Z.code!==0)V$("feishu section.create",Z);let J=Z.data?.section?.guid;if(!J)throw Error(`feishu section.create returned no guid for "${$.name}"`);return J}async function d8($){let Z=await G$("feishu section.get",()=>b.task.v2.section.get({path:{section_guid:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)V$("feishu section.get",Z);let J=Z.data?.section;if(!J?.guid)throw Error(`feishu section.get returned no section: ${$}`);return{guid:J.guid,name:J.name??"",isDefault:J.is_default,tasklistGuid:J.tasklist?.guid}}async function h6($,Z){let J=await G$("feishu section.patch",()=>b.task.v2.section.patch({path:{section_guid:$},params:{user_id_type:"open_id"},data:{section:{name:Z},update_fields:["name"]}}));if(J.code&&J.code!==0)V$("feishu section.patch",J);let Q=J.data?.section;if(!Q?.guid)throw Error(`feishu section.patch returned no section: ${$}`);return{guid:Q.guid,name:Q.name??"",isDefault:Q.is_default,tasklistGuid:Q.tasklist?.guid}}async function I6($){let Z=await G$("feishu section.delete",()=>b.task.v2.section.delete({path:{section_guid:$}}));if(Z.code&&Z.code!==0)V$("feishu section.delete",Z)}async function K0($,Z){let J=[],Q;do{let Y=await G$("feishu section.tasks",()=>b.task.v2.section.tasks({path:{section_guid:$},params:{page_size:50,...typeof Z==="boolean"?{completed:Z}:{},...Q?{page_token:Q}:{}}}));if(Y.code&&Y.code!==0)V$("feishu section.tasks",Y);for(let V of Y.data?.items??[]){if(!V.guid)continue;J.push({guid:V.guid,summary:V.summary??"",completedAt:V.completed_at,subtaskCount:V.subtask_count})}Q=Y.data?.has_more?Y.data?.page_token:void 0}while(Q);return J}async function g6($,Z){let J=[],Q;do{let Y=await G$("feishu tasklist.tasks",()=>b.task.v2.tasklist.tasks({path:{tasklist_guid:$},params:{page_size:50,user_id_type:"open_id",...typeof Z==="boolean"?{completed:Z}:{},...Q?{page_token:Q}:{}}}));if(Y.code&&Y.code!==0)V$("feishu tasklist.tasks",Y);for(let V of Y.data?.items??[]){if(!V.guid)continue;J.push({guid:V.guid,summary:V.summary??"",completedAt:V.completed_at,subtaskCount:V.subtask_count})}Q=Y.data?.has_more?Y.data?.page_token:void 0}while(Q);return J}async function m6($){let Z=`lodestar-default-section-discovery-${Date.now()}-${wz().slice(0,8)}`,J="";try{let Q=await G$("feishu task.create",()=>b.task.v2.task.create({params:{user_id_type:"open_id"},data:{summary:Z,tasklists:[{tasklist_guid:$}]}}));if(Q.code&&Q.code!==0)V$("feishu task.create",Q);let Y=Q.data?.task;if(J=Y?.guid??"",!Y||!J)throw Error("feishu task.create returned no guid during default section discovery");let V=Y.tasklists?.find((W)=>W.tasklist_guid===$)?.section_guid;if(V)return V;let H=(await C2(J)).tasklists?.find((W)=>W.tasklist_guid===$)?.section_guid;if(!H)throw Error(`failed to discover default section guid for tasklist ${$}`);return H}finally{if(J)await d7(J)}}async function d7($){let Z=await G$("feishu task.delete",()=>b.task.v2.task.delete({path:{task_guid:$}}));if(Z.code&&Z.code!==0)V$("feishu task.delete",Z)}async function C2($){let Z=await G$("feishu task.get",()=>b.task.v2.task.get({path:{task_guid:$},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)V$("feishu task.get",Z);let J=Z.data?.task;if(!J)throw Error(`feishu task.get returned no task: ${$}`);return J}async function c6($){let Z=[],J;do{let Q=await G$("feishu comment.list",()=>b.task.v2.comment.list({params:{resource_type:"task",resource_id:$,direction:"asc",page_size:50,user_id_type:"open_id",...J?{page_token:J}:{}}}));if(Q.code&&Q.code!==0)V$("feishu comment.list",Q);for(let Y of Q.data?.items??[]){if(!Y.id)continue;Z.push({id:Y.id,content:Y.content??"",createdAt:Y.created_at,updatedAt:Y.updated_at,creator:Y.creator})}J=Q.data?.has_more?Q.data?.page_token:void 0}while(J);return Z}async function E0($,Z){let J=await G$("feishu comment.create",()=>b.task.v2.comment.create({data:{resource_type:"task",resource_id:$,content:Z},params:{user_id_type:"open_id"}}));if(J.code&&J.code!==0)V$("feishu comment.create",J);let Q=J.data?.comment?.id;if(!Q)throw Error(`feishu comment.create returned no id for task ${$}`);return Q}async function N2($,Z,J){let Q=await G$("feishu task.addTasklist",()=>b.task.v2.task.addTasklist({path:{task_guid:$},data:{tasklist_guid:Z,section_guid:J},params:{user_id_type:"open_id"}}));if(Q.code&&Q.code!==0)V$("feishu task.addTasklist",Q)}function i7($,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,V=Q.msg??Q.message??J.msg??J.message??"unknown error",X=Q.error?.permission_violations??Q.permission_violations??J.error?.permission_violations,H=Array.isArray(X)?X.map((W)=>W?.scope??W?.subject??W?.name??W).filter(Boolean).join(", "):"";return`${$} failed code=${Y??"unknown"} msg=${V}${H?` missing_scopes=${H}`:""}`}async function G$($,Z){try{return await Z()}catch(J){V$($,J)}}function V$($,Z){throw Error(i7($,Z))}var n7=T(()=>{n()});var a={};q2(a,{writeAliveMarker:()=>v2,urgentApp:()=>n0,uploadImageKey:()=>_9,uploadAndSend:()=>B9,updateCard:()=>q0,unbindSessionChat:()=>r8,truncateTurnAnchors:()=>dz,tempProjectName:()=>e$,tempChatName:()=>Z9,setSessionBranchBase:()=>nz,setPendingConversationLaunchChecked:()=>T0,sendTextRaw:()=>C,sendText:()=>E,sendImage:()=>AJ,sendFile:()=>MJ,sendCard:()=>l,seedTurnAnchors:()=>iz,sanitizeSessionName:()=>I2,resolveProjectDir:()=>l0,replaceTurnAnchors:()=>w$,registerTempSessionLease:()=>o6,refreshChatList:()=>f2,readAliveMarker:()=>H9,provisionProject:()=>L9,projectProfile:()=>t8,preferredChatForSession:()=>$$,patchTasklistSectionName:()=>h6,moveTaskToSection:()=>N2,loadTempSessionLeases:()=>n6,loadSessionTurnsMap:()=>e6,loadSessionResumeMap:()=>t6,loadSessionModelMap:()=>J9,loadSessionChatMap:()=>a6,listTasklistTasks:()=>g6,listTasklistSections:()=>x2,listTaskComments:()=>c6,listSectionTasks:()=>K0,listNormalChatIdsByName:()=>e8,isOpenAIChatGPTAuthenticated:()=>h2,hasTempSessionLease:()=>r6,getTurnAnchors:()=>v1,getTenantToken:()=>G0,getTasklistSection:()=>d8,getTask:()=>C2,getSessionResumeRef:()=>i0,getSessionResume:()=>gz,getSessionModelSelection:()=>V9,getSessionModel:()=>rz,getSessionBranchBase:()=>w2,getPendingConversationLaunch:()=>b2,formatFeishuApiError:()=>i7,findNormalChatIdByName:()=>$4,fetchChatOwnerOpenId:()=>w6,fetchChatName:()=>q9,ensureChatForSession:()=>W9,downloadAttachment:()=>h1,discoverTasklistDefaultSectionGuid:()=>m6,disbandChatForSessionExact:()=>G9,disbandChatForSession:()=>K9,deleteTasklistSection:()=>I6,deleteTasklistByGuid:()=>v6,deleteTaskByGuid:()=>d7,deleteReaction:()=>P$,createTempChatForSession:()=>z9,createTasklistWithOwner:()=>b6,createTasklistSection:()=>f6,client:()=>b,clearTurnAnchors:()=>oz,clearTempSessionLease:()=>fz,clearSessionResumeChecked:()=>b1,clearSessionResume:()=>mz,clearSessionModelSelection:()=>az,clearSessionConversationState:()=>X9,chatNameCache:()=>Z$,chatIdForSession:()=>f1,bindSessionToChat:()=>k1,bindSessionResumeChecked:()=>k2,bindSessionResume:()=>Iz,bindSessionModelChecked:()=>Y9,bindSessionModel:()=>Q9,appendTurnAnchorChecked:()=>s8,appendTurnAnchor:()=>lz,addTaskComment:()=>E0,addReaction:()=>R$,PROJECTS_ROOT:()=>WJ});import*as $J from"@larksuiteoapi/node-sdk";import{execSync as ZJ}from"node:child_process";import{randomUUID as i6}from"node:crypto";import{existsSync as bz,mkdirSync as p6,readFileSync as p0,statSync as JJ,writeFileSync as QJ}from"node:fs";import{readFile as YJ}from"node:fs/promises";import{homedir as o7}from"node:os";import{basename as u0,extname as vz,isAbsolute as VJ,join as n8}from"node:path";function o8(){let $={};for(let[Z,J]of q$)$[Z]=J;O$(wZ,$)}function n6(){q$.clear();try{let $=JSON.parse(p0(wZ,"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"||!e$(Q.sessionName)||typeof Q.createdAt!=="number"||!Number.isFinite(Q.createdAt)){K(`feishu: rejected malformed temp-session lease chat=${Z}`);continue}q$.set(Z,{chatId:Z,sessionName:Q.sessionName,createdAt:Q.createdAt})}K(`feishu: loaded ${q$.size} temporary-session leases`)}catch($){if($?.code!=="ENOENT")K(`feishu: load temp-session leases failed: ${$?.message??$}`)}}function o6($,Z){if(!e$($))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 q$.values())if(Y.sessionName===$&&Y.chatId!==Z)throw Error(`temporary session name "${$}" is already leased to ${Y.chatId}`);let J=q$.get(Z),Q={sessionName:$,chatId:Z,createdAt:Date.now()};q$.set(Z,Q);try{o8()}catch(Y){if(J)q$.set(Z,J);else q$.delete(Z);throw Y}}function r6($,Z){let J=q$.get(Z);return J?.sessionName===$&&J.chatId===Z}function fz($,Z){let J=[...q$.entries()].filter(([Q,Y])=>Y.sessionName===$&&(!Z||Q===Z));if(!J.length)return;for(let[Q]of J)q$.delete(Q);try{o8()}catch(Q){for(let[Y,V]of J)q$.set(Y,V);throw Q}}function t8($){return f.projects[$]}function l0($){return t8($)?.cwd?.trim()||n8(WJ,$)}function d0($,Z={}){return fetch($,{...Z,signal:Z.signal??AbortSignal.timeout(hz)})}async function G0(){if(i8&&Date.now()<r7)return i8;return u6??=(async()=>{let $=await d0("https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({app_id:XJ,app_secret:HJ})}),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 i8=Z.tenant_access_token,r7=Date.now()+Math.max(0,(Z.expire??7200)-60)*1000,i8})().finally(()=>{u6=null}),u6}function a6(){try{let $=JSON.parse(p0(NZ,"utf8"));for(let[Z,J]of Object.entries($))if(typeof J==="string")$$.set(Z,J);K(`feishu: loaded ${$$.size} session→chat bindings`)}catch($){if($?.code!=="ENOENT")K(`feishu: load session-chat-map failed: ${$?.message??$}`)}}function zJ(){try{l6()}catch($){K(`feishu: save session-chat-map failed: ${$}`)}}function l6(){let $={};for(let[Z,J]of $$)$[Z]=J;O$(NZ,$)}function k1($,Z){if($$.get($)===Z)return;let J=$$.get($);$$.set($,Z),zJ(),K(`feishu: bound session "${$}" → ${Z}${J?` (was ${J})`:""}`)}function r8($){let Z=$$.get($);if(!Z)return;$$.delete($),zJ(),K(`feishu: unbound session "${$}" from ${Z}`)}function S1($,Z){let J=p.get($)??{};J[Z.provider]=Z,p.set($,J)}function a7($,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"||!VJ(J.cwd))return null;return{provider:Q,sessionId:Y,cwd:J.cwd}}function t7($){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"||!VJ($.cwd))throw Error(`cannot bind a conversation without an absolute cwd: ${String($.cwd)}`);return{provider:$.provider,sessionId:Z,cwd:$.cwd}}function KJ($,Z,J){if(typeof $!=="string")return t7($);if(!Z)throw Error("cannot bind a conversation without a provider");return t7({provider:Z,sessionId:$,cwd:J??null})}function t6(){try{let $=JSON.parse(p0(yZ,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("resume map must contain an object");p.clear();for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){S1(Z,{provider:"codex",sessionId:J.trim(),cwd:null});continue}if(!J||typeof J!=="object"||Array.isArray(J))continue;let Q=J,Y=a7(Q);if(Y){S1(Z,Y);continue}for(let V of["codex","claude"]){let X=Q[V];if(typeof X==="string"&&X.trim()){S1(Z,{provider:V,sessionId:X.trim(),cwd:null});continue}let H=a7(X,V);if(H)S1(Z,H)}}K(`feishu: loaded ${p.size} session→resume bindings`)}catch($){if($?.code!=="ENOENT")K(`feishu: load session-resume-map failed: ${$?.message??$}`)}}function d6(){try{S2()}catch($){K(`feishu: save session-resume-map failed: ${$}`)}}function S2(){let $={};for(let[Z,J]of p){let Q={};if(J.codex)Q.codex={...J.codex};if(J.claude)Q.claude={...J.claude};$[Z]=Q}O$(yZ,$)}function Iz($,Z,J,Q){let Y=KJ(Z,J,Q),V=p.get($)?.[Y.provider];if(V?.sessionId===Y.sessionId&&V.cwd===Y.cwd)return;S1($,Y),d6()}function k2($,Z,J,Q){let Y=KJ(Z,J,Q),V=p.get($),X=V?{...V}:void 0,H=V?.[Y.provider];if(H?.sessionId===Y.sessionId&&H.cwd===Y.cwd)return;S1($,Y);try{S2()}catch(W){if(X)p.set($,X);else p.delete($);throw W}}function gz($,Z="codex"){return p.get($)?.[Z]?.sessionId??null}function i0($,Z="codex"){let J=p.get($)?.[Z];return J?{...J}:null}function mz($,Z){let J=p.get($);if(!J)return;if(!Z){p.delete($),d6();return}if(J[Z]===void 0)return;if(delete J[Z],!J.codex&&!J.claude)p.delete($);d6()}function b1($,Z){let J=p.get($);if(!J||Z&&J[Z]===void 0)return;let Q={...J};if(!Z)p.delete($);else{let Y={...J};if(delete Y[Z],!Y.codex&&!Y.claude)p.delete($);else p.set($,Y)}try{S2()}catch(Y){throw p.set($,Q),Y}}function GJ($){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 qJ($){if(!$||typeof $!=="object")return null;let Z=$,J=Z.source;if(!J||typeof J!=="object")return null;let Q=GJ(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 _J($){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=GJ(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=qJ(Z.through);return Y?{kind:"fork",source:J,through:Y}:null})();if(!Q)return null;try{K$(Q,J.provider)}catch{return null}return Q}function cz($){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 uz($,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=qJ(J.checkpoint);if(Q&&!Y)return null;if(!Y){if(Z!=="claude")return null;let V=typeof J.uuid==="string"?J.uuid.trim():"",X=typeof J.sid==="string"?J.sid.trim():"";if(!V||!X)return null;Y={provider:"claude",kind:"assistant-message",id:V,source:{provider:"claude",sessionId:X,cwd:null}}}return{checkpoint:Y,preview:String(J.preview??""),ts:J.ts,writes:cz(J.writes)}}function pz($){if(!$||typeof $!=="object")return null;let Z=$,J=_J(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 s6($){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 e6(){try{let $=JSON.parse(p0(SZ,"utf8"));if(!$||typeof $!=="object"||Array.isArray($))throw Error("turns map must contain an object");g.clear();let Z=0,J=0;for(let[Q,Y]of Object.entries($)){let V,X,H=null;if(Array.isArray(Y))V=Y,X=null;else if(Y&&typeof Y==="object"&&!Array.isArray(Y)){let q=Y;if(!Array.isArray(q.anchors)||!Object.prototype.hasOwnProperty.call(q,"base")){J++;continue}if(V=q.anchors,q.base===null)X=null;else{let B=_J(q.base);if(!B){J++;continue}X=B}if(Object.prototype.hasOwnProperty.call(q,"pendingLaunch")){let B=pz(q.pendingLaunch);if(!B){J++;continue}H=B}}else{J++;continue}let W=p.get(Q),z=W?.claude!==void 0&&W.codex===void 0?"claude":null,G=[];for(let q of V){let B=uz(q,z);if(B)G.push(B);else J++}if(G.length||X!==null||H)g.set(Q,{base:X,anchors:G,...H?{pendingLaunch:H}:{}}),Z+=G.length}if(K(`feishu: loaded ${Z} turn anchors across ${g.size} sessions`),J>0)K(`feishu: rejected ${J} malformed turn anchors while loading`)}catch($){if($?.code!=="ENOENT")K(`feishu: load session-turns-map failed: ${$?.message??$}`)}}function $9(){try{w1()}catch($){K(`feishu: save session-turns-map failed: ${$}`)}}function w1(){let $={};for(let[Z,J]of g)$[Z]=J;O$(SZ,$)}function lz($,Z){try{s8($,Z)}catch(J){K(`feishu: append turn anchor failed: ${J}`)}}function s8($,Z){let J=g.get($),Q=[...J?.anchors??[],Z],Y=J?.base??null;if(Q.length>s7){let V=Q.splice(0,Q.length-s7),X=V[V.length-1].checkpoint;Y={kind:"fork",source:X.source,through:X}}g.set($,{base:Y,anchors:Q,...J?.pendingLaunch?{pendingLaunch:J.pendingLaunch}:{}});try{w1()}catch(V){if(J)g.set($,J);else g.delete($);throw V}}function v1($){return g.get($)?.anchors??[]}function w2($){return g.get($)?.base??null}function b2($){let Z=g.get($)?.pendingLaunch;return Z?s6(Z):null}function T0($,Z){if(Z){if(Z.launch.source.cwd===null)throw Error("pending conversation launch source cwd is missing");K$(Z.launch,"claude",Z.launch.source.cwd)}let J=g.get($),Q=J?.base??null,Y=J?.anchors.slice()??[];if(!Z&&Y.length===0&&Q===null)g.delete($);else g.set($,{base:Q,anchors:Y,...Z?{pendingLaunch:s6(Z)}:{}});try{w1()}catch(V){if(J)g.set($,J);else g.delete($);throw V}}function dz($,Z){let J=g.get($);if(!J||J.anchors.length<=Z)return;g.set($,{...J,anchors:J.anchors.slice(0,Z)}),$9()}function iz($,Z){if(Z.length===0)return;g.set($,{base:null,anchors:Z.slice()}),$9()}function w$($,Z,J,Q){let Y=g.get($),V=Q===void 0?Y?.pendingLaunch:Q??void 0,X=V?s6(V):void 0;if(Z.length===0&&J===null&&!X)g.delete($);else g.set($,{base:J,anchors:Z.slice(),...X?{pendingLaunch:X}:{}});try{w1()}catch(H){if(Y)g.set($,Y);else g.delete($);throw H}}function nz($,Z){w$($,v1($),Z)}function oz($){if(!g.has($))return;g.delete($),$9()}function e$($){return e7.test($)?$.replace(e7,""):null}function Z9($,Z=[]){let J=new Date,Q=(H)=>String(H).padStart(2,"0"),Y=`${Q(J.getMonth()+1)}${Q(J.getDate())}-${Q(J.getHours())}${Q(J.getMinutes())}`,V=new Set([...Z$.values(),...g.keys(),...Z]),X=`${$}*${Y}`;for(let H=2;V.has(X);H++)X=`${$}*${Y}-${H}`;return X}function J9(){try{let $=JSON.parse(p0(kZ,"utf8"));for(let[Z,J]of Object.entries($)){if(typeof J==="string"&&J.trim()){e.set(Z,{provider:x1(J),model:J,effort:null});continue}if(!J||typeof J!=="object")continue;let{model:Q,provider:Y}=J,V=Y==="claude"||Y==="codex"?Y:typeof Q==="string"&&Q.trim()?x1(Q):"claude",X=typeof Q==="string"&&Q.trim()?Q:null;if(V==="claude"&&!X)continue;let{effort:H,tokenSourceId:W}=J,z=typeof W==="string"&&W.trim()?W.trim():null,G=V==="claude"?j0(H)?H:null:s$(H)?H:null;e.set(Z,{provider:V,model:X,effort:G,...z?{tokenSourceId:z}:{}})}K(`feishu: loaded ${e.size} session→model bindings`)}catch($){if($?.code!=="ENOENT")K(`feishu: load session-model-map failed: ${$?.message??$}`)}}function BJ(){try{a8()}catch($){K(`feishu: save session-model-map failed: ${$}`)}}function a8(){let $={};for(let[Z,J]of e)$[Z]=J;O$(kZ,$)}function Q9($,Z,J,Q,Y){let V=e.get($);if(V?.provider===Z&&V.model===J&&V.effort===Q&&(V.tokenSourceId??null)===(Y??null))return;e.set($,{provider:Z,model:J,effort:Q,...Y?{tokenSourceId:Y}:{}}),BJ()}function Y9($,Z,J,Q,Y){let V=e.get($),X={provider:Z,model:J,effort:Q,...Y?{tokenSourceId:Y}:{}};if(V?.provider===Z&&V.model===J&&V.effort===Q&&(V.tokenSourceId??null)===(Y??null))return;e.set($,X);try{a8()}catch(H){if(V)e.set($,V);else e.delete($);throw H}}function V9($){let Z=e.get($);if(Z)return Z;let J=e$($);return J?e.get(J)??null:null}function rz($){return e.get($)?.model??null}function az($){if(!e.has($))return;e.delete($),BJ()}function X9($){let Z=$$.get($),J=p.get($),Q=e.get($),Y=g.get($),V=[...q$.entries()].filter(([,X])=>X.sessionName===$);$$.delete($),p.delete($),e.delete($),g.delete($);for(let[X]of V)q$.delete(X);try{l6(),S2(),a8(),w1(),o8()}catch(X){if(Z)$$.set($,Z);if(J)p.set($,J);if(Q)e.set($,Q);if(Y)g.set($,Y);for(let[W,z]of V)q$.set(W,z);let H=[X];for(let W of[l6,S2,a8,w1,o8])try{W()}catch(z){H.push(z)}throw H.length===1?H[0]:AggregateError(H,`failed to clear and restore conversation state for ${$}`)}}function v2($){try{O$(M8,$)}catch(Z){K(`feishu: write alive marker failed: ${Z}`)}}function H9(){if(!bz(M8))return[];try{let $=p0(M8,"utf8"),Z=JSON.parse($);return Array.isArray(Z)?Z.filter((J)=>typeof J==="string"):[]}catch($){return K(`feishu: read alive marker failed: ${$}`),[]}}function f1($){let Z=$$.get($);if(Z){let Q=Z$.get(Z);if(Q&&Q!==$)K(`feishu: chatIdForSession("${$}"): persisted binding ${Z} has cached name "${Q}", using persisted binding`);return Z}let J=[];for(let[Q,Y]of Z$)if(Y===$)J.push(Q);if(J.length===1)return J[0];if(J.length>1)K(`feishu: chatIdForSession("${$}"): ${J.length} candidates with no binding — [${J.join(", ")}]`);return null}async function f2(){try{let $;do{let Z=await b.im.chat.list({params:{page_size:100,...$?{page_token:$}:{}}});for(let J of Z.data?.items??[])if(J.chat_id&&J.name)Z$.set(J.chat_id,J.name);$=Z.data?.page_token}while($);K(`feishu: refreshed chat list — ${Z$.size} groups`)}catch($){K(`feishu: refresh chat list failed: ${$}`)}}async function e8(){let $=new Map,Z;do{let J=await b.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;Z$.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 $4($){let Z=$$.get($);if(Z&&Z$.get(Z)===$){let V=await FJ(Z);if(V.name===$&&UJ(V.status))return Z;Z$.delete(Z),r8($)}let Q=(await e8()).get($)??[];if(Q.length===0)return null;let 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 W9($,Z){if(!Z)throw Error("missing sender open_id; cannot add user to worktree group");let J=await $4($);if(J){let V=await tz(J,Z);return k1($,J),{chatId:J,created:!1,joined:V}}let Q=await b.im.chat.create({params:{user_id_type:"open_id",uuid:i6()},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 Z$.set(Y,$),k1($,Y),{chatId:Y,created:!0,joined:!0}}async function z9($,Z){if(!Z)throw Error("missing sender open_id; cannot create temporary group");if(await $4($))throw Error(`temporary group name already exists: ${$}`);let Q=await b.im.chat.create({params:{user_id_type:"open_id",uuid:i6()},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 Z$.set(Y,$),k1($,Y),{chatId:Y,created:!0,joined:!0}}async function K9($){let Z=await $4($);if(!Z)return r8($),{chatId:null,disbanded:!1};let J=await b.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(Z$.delete(Z),$$.get($)===Z)r8($);return{chatId:Z,disbanded:!0}}async function G9($,Z){if(!Z)throw Error("cannot disband a temporary session without an exact chat_id");let J=await FJ(Z);if(J.name!==$)throw Error(`refusing to delete chat ${Z}: expected name "${$}", got "${J.name??""}"`);if(!UJ(J.status))throw Error(`refusing to delete chat ${Z}: status=${J.status??"unknown"}`);let Q=await b.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 Z$.delete(Z),{chatId:Z,disbanded:!0}}async function tz($,Z){let J;do{let Y=await b.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 V of Y.data?.items??[])if(V.member_id===Z)return!1;J=Y.data?.page_token}while(J);let Q=await b.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 q9($){try{let Z=await G0(),Q=await(await d0(`https://open.feishu.cn/open-apis/im/v1/chats/${encodeURIComponent($)}`,{headers:{Authorization:`Bearer ${Z}`}})).json();if(Q?.code!==0)return K(`feishu: fetchChatName ${$} code=${Q?.code} msg=${Q?.msg}`),null;let Y=Q.data?.name;if(typeof Y==="string"&&Y)return Z$.set($,Y),K(`feishu: fetchChatName ${$} → "${Y}" (point lookup)`),Y;return K(`feishu: fetchChatName ${$} — chat has no name (unnamed group?)`),null}catch(Z){return K(`feishu: fetchChatName ${$} failed: ${Z}`),null}}async function LJ($,Z,J,Q){let Y=i6(),V=null;for(let X=0;X<y2.length;X++){if(y2[X]>0)await new Promise((H)=>setTimeout(H,y2[X]));try{let H=await b.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:Z,msg_type:J,content:Q,uuid:Y}});if(H?.code&&H.code!==0)return K(`feishu: send${$==="text"?"Text":"Card"} rejected chat=${Z} code=${H.code} msg=${H.msg}`),null;return H?.data?.message_id??null}catch(H){V=H,K(`feishu: send${$==="text"?"Text":"Card"} attempt ${X+1}/${y2.length} chat=${Z} failed: ${H}`)}}return K(`feishu: send${$==="text"?"Text":"Card"} chat=${Z} EXHAUSTED ${y2.length} retries: ${V}`),null}async function FJ($){let Z=await b.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 UJ($){return $===null||$==="normal"}async function E($,Z){return LJ("text",$,"text",JSON.stringify({text:Z}))}async function l($,Z){return LJ("card",$,"interactive",JSON.stringify(P0(Z)))}async function q0($,Z){let J=await b.im.v1.message.patch({path:{message_id:$},data:{content:JSON.stringify(P0(Z))}});if(J?.code&&J.code!==0)throw Error(`feishu message.patch failed code=${J.code} msg=${J.msg}`)}async function C($,Z){try{let J=await G0(),Y=await(await d0("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 K(`feishu: sendTextRaw rejected chat=${$} code=${Y?.code} msg=${Y?.msg}`),null;return Y.data?.message_id??null}catch(J){return K(`feishu: sendTextRaw chat=${$} failed: ${J}`),null}}async function R$($,Z){if(!$)return null;try{return(await b.im.messageReaction.create({path:{message_id:$},data:{reaction_type:{emoji_type:Z}}}))?.data?.reaction_id??null}catch(J){return K(`feishu: addReaction ${Z} on ${$} failed: ${J}`),null}}async function P$($,Z){if(!$||!Z)return;try{await b.im.messageReaction.delete({path:{message_id:$,reaction_id:Z}})}catch(J){K(`feishu: deleteReaction ${Z} on ${$} failed: ${J}`)}}async function n0($,Z){if(!$){K("feishu: urgentApp skip — missing messageId");return}if(Z.length===0){K(`feishu: urgentApp skip — empty openIds (msg=${$})`);return}let J=await G0(),Q=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/urgent_app?user_id_type=open_id`;try{let V=await(await d0(Q,{method:"PATCH",headers:{Authorization:`Bearer ${J}`,"Content-Type":"application/json"},body:JSON.stringify({user_id_list:Z})})).json();if(V?.code!==0){K(`feishu: urgentApp ${$} code=${V?.code} msg=${V?.msg}`);return}let X=V.data?.invalid_user_id_list??[],H=Z.length-X.length;K(`feishu: urgentApp ${$} ok — delivered=${H}${X.length?` invalid=${X.length}`:""}`)}catch(Y){K(`feishu: urgentApp ${$} failed: ${Y}`)}}async function h1($,Z,J,Q){try{let Y=await G0(),V=`https://open.feishu.cn/open-apis/im/v1/messages/${$}/resources/${Z}?type=${J}`,X=await d0(V,{headers:{Authorization:`Bearer ${Y}`}});if(!X.ok){K(`feishu: download ${J} HTTP ${X.status}: ${(await X.text()).slice(0,200)}`);return}let H=Buffer.from(await X.arrayBuffer());p6(bZ,{recursive:!0});let W=Q?Q.replace(/[^a-zA-Z0-9._-]/g,"_"):`${Z.replace(/[^a-zA-Z0-9_-]/g,"_")}.png`,z=n8(bZ,`${Date.now()}-${W}`);return QJ(z,H),K(`feishu: downloaded ${J} ${z} (${H.length}B)`),z}catch(Y){K(`feishu: download ${J} failed: ${Y instanceof Error?Y.message:Y}`);return}}function ez($){return sz.has(vz($).toLowerCase())}async function PJ($){let Z=await G0(),J=new Blob([Uint8Array.from(await YJ($))]),Q=new FormData;Q.append("image_type","message"),Q.append("image",J,u0($));let V=await(await d0("https://open.feishu.cn/open-apis/im/v1/images",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Q})).json();if(V?.code!==0)return K(`feishu: uploadImage ${$} code=${V.code} msg=${V.msg}`),null;return V.data?.image_key??null}async function _9($){try{let Z=JJ($);if(!Z.isFile())return K(`feishu: uploadImageKey not a file — ${$}`),null;if(Z.size>DJ)return K(`feishu: uploadImageKey oversize — ${$} (${(Z.size/1024/1024).toFixed(1)} MB)`),null}catch(Z){return K(`feishu: uploadImageKey stat failed — ${$}: ${Z}`),null}return PJ($)}async function $K($){let Z=await G0(),J=new Blob([Uint8Array.from(await YJ($))]),Q=new FormData;Q.append("file_type","stream"),Q.append("file_name",u0($)),Q.append("file",J,u0($));let V=await(await d0("https://open.feishu.cn/open-apis/im/v1/files",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:Q})).json();if(V?.code!==0)return K(`feishu: uploadFile ${$} code=${V.code} msg=${V.msg}`),null;return V.data?.file_key??null}async function AJ($,Z){try{let J=await b.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 K(`feishu: sendImage rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return K(`feishu: sendImage failed chat=${$}: ${J}`),null}}async function MJ($,Z){try{let J=await b.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 K(`feishu: sendFile rejected chat=${$} code=${J.code} msg=${J.msg}`),null;return J?.data?.message_id??null}catch(J){return K(`feishu: sendFile failed chat=${$}: ${J}`),null}}async function B9($,Z){try{let Q=JJ(Z);if(!Q.isFile())return await E($,`❌ 出站文件: 路径不是文件 — ${Z}`),!1;if(Q.size>DJ)return await E($,`❌ 出站文件: ${u0(Z)} 超过 30 MB (${(Q.size/1024/1024).toFixed(1)} MB)`),!1}catch(Q){return await E($,`❌ 出站文件: 无法读取 ${Z} (${Q})`),!1}let J=ez(Z);try{if(J){let Q=await PJ(Z);if(!Q)return await E($,`❌ 出站图片上传失败: ${u0(Z)}`),!1;return await AJ($,Q)!=null}else{let Q=await $K(Z);if(!Q)return await E($,`❌ 出站文件上传失败: ${u0(Z)}`),!1;return await MJ($,Q)!=null}}catch(Q){return K(`feishu: uploadAndSend ${Z} failed: ${Q}`),await E($,`❌ 出站文件异常: ${u0(Z)} — ${Q}`),!1}}function L9($){p6($,{recursive:!0}),K(`feishu: provisioned ${$}`);let Z=n8(o7(),".codex","config.toml");try{p6(n8(o7(),".codex"),{recursive:!0});let J="";try{J=p0(Z,"utf8")}catch{}let Q=`[projects.${JSON.stringify($)}]`;if(!J.includes(Q)){let Y=J.trimEnd();J=`${Y}${Y?`
|
|
57
58
|
|
|
58
59
|
`:""}${Q}
|
|
59
60
|
trust_level = "trusted"
|
|
60
|
-
`,u7(Z,J)}}catch(J){K(`feishu: codex trust write failed for ${$}: ${J}`)}try{m7("git init -q",{cwd:$,stdio:"ignore"})}catch{}}function S2(){try{let $=m7(`"${J0()}" login status 2>&1`,{timeout:1e4}).toString();return/Logged in using ChatGPT/i.test($)}catch{return!1}}function k2($){return $.replace(/[^\w一-鿿\-\[\]\*]/g,"_").slice(0,64)}var i7,d7,n7,H$,b,EW=15000,I8="",b7=0,y6=null,Z$,$$,u,h,I7=200,h7,e,R2,QJ=31457280,mW;var d=E(()=>{E$();U1();M1();v$();v();C0();D1();k7();i7=f.feishu.app_id,d7=f.feishu.app_secret,n7=f.runtime.projects_root,H$=new Map;b=new g7.Client({appId:i7,appSecret:d7,disableTokenCache:!1});Z$=new Map,$$=new Map;u=new Map;h=new Map;h7=/\*[0-9]{4}-[0-9]{4}(-[0-9]+)?$/;e=new Map;R2=[0,1000,4000];mW=new Set([".png",".jpg",".jpeg",".gif",".bmp",".webp"])});function HJ($){return $===300305||$===300315}function H0($){let Z=n$.get($);if(!Z)Z={sequence:0,queue:Promise.resolve(),elementCount:0,deadElements:new Set},n$.set($,Z);return Z}function zJ($){W$.delete($),W$.add($);while(W$.size>nW){let Z=W$.values().next().value;if(typeof Z!=="string")break;W$.delete(Z)}}function h$($,Z,J){W$.delete($),n$.delete($);let Q=H0($);Q.elementCount=Z,Q.onFailure=J,Q.writeDead=!1,Q.closing=!1}function Q9($){return n$.get($)?.elementCount??0}function N1($,Z){return n$.get($)?.deadElements.has(Z)??!1}function WJ($){if(W$.has($))return;let Z=H0($);if(Z.closing)return;Z.writeDead=!0,V$($)}function d8($){let Z=H0($);return Z.sequence+=1,Z.sequence}function rW($,Z){$.deadElements.add(Z)}async function w2($,Z,J){let Q=await X0(),Y=await fetch(`${pW}${Z}`,{method:$,headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},...J?{body:JSON.stringify(J)}:{},signal:AbortSignal.timeout(lW)}),V=await Y.json();if(!Y.ok||V?.code!==0){let X=typeof V?.code==="number"?V.code:Y.status,z=Error(`cardkit ${$} ${Z}: HTTP ${Y.status} code=${String(V?.code??"MISS")} msg=${V?.msg??"MISS"}`);throw z.code=X,z}return V?.data}function oW($){return new Promise((Z)=>setTimeout(Z,$))}function aW($){if(typeof $!=="object"||$===null)return!1;let Z=$.code;return Z===300309||Z===200850}async function tW($){let Z=d8($);await w2("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify({config:{streaming_mode:!0}}),sequence:Z})}async function Y9($,Z,J,Q,Y=!1){let V=(X)=>{try{if(!Y)H0($).onFailure?.(X)}catch(z){K(`cardkit failure callback ${$}: ${z}`)}try{Q?.(X)}catch(z){K(`cardkit per-call failure callback ${$}: ${z}`)}};try{await J();return}catch(X){if(!aW(X)){K(`cardkit ${Z} ${$}: ${X}`),V(X?.code);return}K(`cardkit ${Z} ${$}: streaming closed (code=${X.code}) — reopening`)}try{await tW($)}catch(X){K(`cardkit STREAMING_REOPEN_FAILED ${$}: ${X}`),V(X?.code);return}try{await J()}catch(X){K(`cardkit ${Z} ${$} retry-after-reopen: ${X}`),V(X?.code)}}function sW($){return typeof $==="object"&&$!==null&&$.code===200740}async function r$($,Z={}){let J=Z.retryDelaysMs?.length?Z.retryDelaysMs:iW,Q=null;for(let Y=0;Y<J.length;Y++){let V=J[Y]??0;if(V>0)await oW(V);try{let X=await w2("POST","/cards/id_convert",{message_id:$});if(typeof X?.card_id!=="string"||!X.card_id)throw Error("cardkit POST /cards/id_convert: missing card_id");return X.card_id}catch(X){if(Q=X,!sW(X)||Y===J.length-1)throw X;let z=J[Y+1]??0;K(`cardkit id_convert ${$}: empty result, retry ${Y+2}/${J.length} in ${z}ms`)}}throw Q}async function o$($){let Z=n$.get($);if(!Z)return;await Z.queue}function a($,Z,J={},Q){if(W$.has($))return Promise.resolve();let Y=H0($);if(Y.closing||Y.writeDead)return Promise.resolve();let V=Z.element_id;return Y.queue=Y.queue.then(()=>Y9($,"addElement",async()=>{if(Y.writeDead)return;let X=d8($);await w2("POST",`/cards/${$}/elements`,{type:J.type??"append",...J.targetElementId?{target_element_id:J.targetElementId}:{},elements:JSON.stringify([Z]),sequence:X}),Y.elementCount+=1},(X)=>{if(V)rW(Y,V);Q?.(X)})),Y.queue}function c($,Z,J,Q,Y=!0){if(W$.has($))return Promise.resolve();let V=H0($);if(V.closing||V.writeDead||V.deadElements.has(Z))return Promise.resolve();return V.queue=V.queue.then(()=>Y9($,`replaceElement ${Z}`,async()=>{if(V.writeDead||V.deadElements.has(Z))return;let X=d8($);await w2("PUT",`/cards/${$}/elements/${Z}`,{element:JSON.stringify(J),sequence:X})},Q,!Y)),V.queue}async function L$($,Z,J,Q={}){if(W$.has($))return!1;let Y=H0($);if(Y.closing||Y.writeDead||Y.deadElements.has(Z))return!1;let V=!1;return await c($,Z,J,()=>{V=!0},Q.notifyCardFailure!==!1),!V&&!Y.writeDead&&!Y.deadElements.has(Z)}async function S1($,Z,J={}){if(W$.has($))return!1;let Q=H0($);if(Q.closing||Q.writeDead)return!1;let Y=Z.element_id,V=!1;return await a($,Z,J,()=>{V=!0}),!V&&!Q.writeDead&&!(Y&&Q.deadElements.has(Y))}function c0($,Z){if(W$.has($)||n$.get($)?.closing||n$.get($)?.writeDead)return;let J=(Z??"").replace(/\s+/g," ").trim();if(!J)return;let Q=m0.get($);if(!Q)Q={latest:J,lastSent:"",timer:null},m0.set($,Q);else Q.latest=J;if(Q.timer)return;Q.timer=setTimeout(()=>{let Y=m0.get($);if(!Y)return;if(W$.has($)){m0.delete($);return}if(Y.timer=null,Y.latest===Y.lastSent)return;let V=Y.latest;K$($,{config:{summary:{content:V}}}).then((X)=>{let z=m0.get($);if(X&&z===Y)z.lastSent=V})},dW)}function V$($){let Z=m0.get($);if(!Z)return;if(Z.timer)clearTimeout(Z.timer),Z.timer=null;m0.delete($)}function n8($,Z){return K$($,Z).then(()=>{})}async function K$($,Z){if(W$.has($))return!1;let J=H0($);if(J.closing||J.writeDead)return!1;let Q=!1,Y=!1;return J.queue=J.queue.then(()=>Y9($,"patchSettings",async()=>{if(W$.has($)||J.writeDead)return;let V=d8($);await w2("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify(Z),sequence:V}),Q=!0},()=>{Y=!0},!0)),await J.queue,Q&&!Y&&!W$.has($)&&!J.writeDead}async function C$($){let Z=n$.get($);if(!Z){zJ($),V$($);return}if(Z.closing){await Z.queue;return}Z.closing=!0,V$($),await Z.queue,zJ($),n$.delete($)}var pW="https://open.feishu.cn/open-apis/cardkit/v1",lW=15000,iW,n$,m0,dW=1500,W$,nW=5000;var u0=E(()=>{d();v();iW=[0,250,750,1500];n$=new Map,m0=new Map;W$=new Set});function r8($){if(!$)return null;return typeof $.total_tokens==="number"&&Number.isFinite($.total_tokens)?$.total_tokens:null}function o8($){return typeof $==="number"&&Number.isFinite($)&&$>0?$:null}function eW($,Z,J=12000){if(Z==null||Z<=0)return null;if(Z<=J)return 0;let Q=Z-J,Y=Math.max(0,$-J),V=Math.max(0,Q-Y);return Math.round(Math.min(100,Math.max(0,V/Q*100)))}function GJ($,Z,J){let Q=eW($,Z,J??12000);if(Q==null)return null;return{used:Math.min(100,Math.max(0,100-Q)),remaining:Q}}function KJ($){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 a8($,Z){let J=KJ($);return Z!=null&&Z>0?`${J}/${KJ(Z)}`:`${J}/--`}function _J($,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))}%`}import{isAbsolute as V9,relative as $K}from"node:path";function s8($){return $==="Bash"||$==="exec_command"||$.endsWith(".exec_command")}function e8($){return $==="write_stdin"||$.endsWith(".write_stdin")}function JK($){return s8($)||e8($)}function $4($){return $==="FileChange"||$==="fileChange"}function v2($){return $==="WebSearch"||$==="webSearch"}function Z4($){return $==="WebFetch"||$==="webFetch"}function G9($){return $==="MCP"}function J4($){return $==="ImageGeneration"||$==="imageGeneration"}function _9($){return $==="Agent"||$==="Task"}function Q4($){return $==="Read"}function Y4($){return $==="Write"}function V4($){return $==="Edit"||$==="NotebookEdit"}function X4($){return $==="MultiEdit"}function q9($){return $==="Glob"||$==="Grep"||$==="LS"}function z4($){return $==="TodoWrite"}function H4($){return $==="ExitPlanMode"}function W4($){return $.startsWith(BJ)}function LJ($){return W4($)?$.slice(BJ.length):$}function p0($){if(W4($))return"服务端工具";if($4($))return"文件变更";if(v2($))return"网页搜索";if(Z4($))return"网页读取";if(J4($))return"图片生成";if(Q4($))return"读取文件";if(Y4($))return"写入文件";if(V4($)||X4($))return"编辑文件";if($==="Glob")return"匹配文件";if($==="Grep")return"搜索文件";if($==="LS")return"列目录";if(z4($))return"更新待办";if(H4($))return"确认计划";if($==="Task")return"子任务";return JK($)?"Bash":$}function K0($,Z){let J=(Q,Y)=>Q.length>Y?Q.slice(0,Y)+"…":Q;if(W4($))return J(QK($,Z),80);if(!Z||typeof Z!=="object")return"";if(s8($))return YK(Z);if(e8($))return VK(Z);if($4($))return J(HK(Z),80);if(v2($))return J(kJ(Z),80);if(Z4($))return J(LK(Z),80);if(G9($))return J(DK(Z),80);if(J4($))return J(PK(Z),80);if(_9($))return J(AK(Z),80);if(Q4($))return J(WK(Z),80);if(Y4($))return J(KK(Z),80);if(V4($))return J(GK(Z),80);if(X4($))return J(_K(Z),80);if(q9($))return J(qK($,Z),80);if(z4($))return J(BK(Z),80);if(H4($))return J(f2(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 QK($,Z){let J=typeof Z?.tool==="string"&&Z.tool?Z.tool:LJ($),Q=f2(Z?.input);return Q?`${J}: ${Q}`:J}function YK($){let Z=(V,X)=>V.length>X?V.slice(0,X)+"…":V,J=DJ($);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((V)=>V.trim()).filter(Boolean);if(Y.length<=1)return Z(Q.replace(/\s+/g," "),80);return`Shell 脚本 · ${Y.length} 行 · ${Z(F1(Q),46)}`}function FJ($){let Z=typeof $?.chars==="string"?$.chars:"";if(Z==="")return"读取会话输出";if(Z==="\x03")return"中断会话";return"发送输入"}function VK($){let Z=$?.session_id??$?.sessionId,J=Z===void 0?"":` ${Z}`;return`${FJ($)}${J}`}function DJ($){let Z=String($?.command??$?.cmd??$?.script??""),J=String($?.description??$?.reason??"").trim(),Q=gZ(Z);return{description:Q.description||J,command:Q.command}}function g$($,Z=""){let J="```";while($.includes(J))J+="`";return`${J}${Z}
|
|
61
|
+
`,QJ(Z,J)}}catch(J){K(`feishu: codex trust write failed for ${$}: ${J}`)}try{ZJ("git init -q",{cwd:$,stdio:"ignore"})}catch{}}function h2(){try{let $=ZJ(`"${H0()}" login status 2>&1`,{timeout:1e4}).toString();return/Logged in using ChatGPT/i.test($)}catch{return!1}}function I2($){return $.replace(/[^\w一-鿿\-\[\]\*]/g,"_").slice(0,64)}var XJ,HJ,WJ,q$,b,hz=15000,i8="",r7=0,u6=null,Z$,$$,p,g,s7=200,e7,e,y2,DJ=31457280,sz;var n=T(()=>{N$();E1();C1();m$();v();f0();y$();R1();n7();XJ=f.feishu.app_id,HJ=f.feishu.app_secret,WJ=f.runtime.projects_root,q$=new Map;b=new $J.Client({appId:XJ,appSecret:HJ,disableTokenCache:!1});Z$=new Map,$$=new Map;p=new Map;g=new Map;e7=/\*[0-9]{4}-[0-9]{4}(-[0-9]+)?$/;e=new Map;y2=[0,1000,4000];sz=new Set([".png",".jpg",".jpeg",".gif",".bmp",".webp"])});function jJ($,Z){if($===300305)return!0;if($!==300315)return!1;let J=Z?.message??"";return/(?:code\s*[:=]\s*300305\b|number of card components[^\n.]{0,60}exceed)/i.test(J)}function RJ($,Z){if($!==300315)return!1;return/(?:duplicate\s+(?:element\s*)?id|code\s*1001\s*:\s*duplicate id)/i.test(Z?.message??"")}function _0($){let Z=u$.get($);if(!Z)Z={sequence:0,queue:Promise.resolve(),elementCount:0,deadElements:new Set},u$.set($,Z);return Z}function OJ($){_$.delete($),_$.add($);while(_$.size>VK){let Z=_$.values().next().value;if(typeof Z!=="string")break;_$.delete(Z)}}function p$($,Z,J){_$.delete($),u$.delete($);let Q=_0($);Q.elementCount=Z,Q.onFailure=J,Q.writeDead=!1,Q.closing=!1}function F9($){return u$.get($)?.elementCount??0}function I1($,Z){return u$.get($)?.deadElements.has(Z)??!1}function EJ($,Z){u$.get($)?.deadElements.delete(Z)}function Z4($){if(_$.has($))return;let Z=_0($);if(Z.closing)return;Z.writeDead=!0,X$($)}function J4($){let Z=_0($);return Z.sequence+=1,Z.sequence}function XK($,Z){$.deadElements.add(Z)}async function g2($,Z,J){let Q=await G0(),Y=await fetch(`${ZK}${Z}`,{method:$,headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},...J?{body:JSON.stringify(J)}:{},signal:AbortSignal.timeout(JK)}),V=await Y.json();if(!Y.ok||V?.code!==0){let X=typeof V?.code==="number"?V.code:Y.status,H=Y.headers.get("x-tt-logid")??Y.headers.get("x-request-id")??Y.headers.get("request-id")??void 0,W=Error(`cardkit ${$} ${Z}: HTTP ${Y.status} code=${String(V?.code??"MISS")} msg=${V?.msg??"MISS"}${H?` log_id=${H}`:""}`);throw W.code=X,W.httpStatus=Y.status,W.logId=H,W}return V?.data}function HK($){return new Promise((Z)=>setTimeout(Z,$))}function WK($){if(typeof $!=="object"||$===null)return!1;let Z=$.code;return Z===300309||Z===200850}async function zK($){let Z=J4($);await g2("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify({config:{streaming_mode:!0}}),sequence:Z})}async function U9($,Z,J,Q,Y=!1,V={}){let X=(H)=>{let W=typeof H==="object"&&H!==null?H:null,z={cardId:$,operation:Z,...V,code:W?.code,httpStatus:W?.httpStatus,logId:W?.logId,message:H instanceof Error?H.message:String(H)};try{if(!Y)_0($).onFailure?.(z.code,z)}catch(G){K(`cardkit failure callback ${$}: ${G}`)}try{Q?.(z)}catch(G){K(`cardkit per-call failure callback ${$}: ${G}`)}};try{await J();return}catch(H){if(!WK(H)){K(`cardkit ${Z} ${$}: ${H}`),X(H);return}K(`cardkit ${Z} ${$}: streaming closed (code=${H.code}) — reopening`)}try{await zK($)}catch(H){K(`cardkit STREAMING_REOPEN_FAILED ${$}: ${H}`),X(H);return}try{await J()}catch(H){K(`cardkit ${Z} ${$} retry-after-reopen: ${H}`),X(H)}}function KK($){return typeof $==="object"&&$!==null&&$.code===200740}async function $0($,Z={}){let J=Z.retryDelaysMs?.length?Z.retryDelaysMs:QK,Q=null;for(let Y=0;Y<J.length;Y++){let V=J[Y]??0;if(V>0)await HK(V);try{let X=await g2("POST","/cards/id_convert",{message_id:$});if(typeof X?.card_id!=="string"||!X.card_id)throw Error("cardkit POST /cards/id_convert: missing card_id");return X.card_id}catch(X){if(Q=X,!KK(X)||Y===J.length-1)throw X;let H=J[Y+1]??0;K(`cardkit id_convert ${$}: empty result, retry ${Y+2}/${J.length} in ${H}ms`)}}throw Q}async function l$($){let Z=u$.get($);if(!Z)return;await Z.queue}function H$($,Z,J={},Q){if(_$.has($))return Promise.resolve();let Y=_0($);if(Y.closing||Y.writeDead)return Promise.resolve();let V=P0(Z),X=V.element_id;return Y.queue=Y.queue.then(()=>U9($,"addElement",async()=>{if(Y.writeDead)return;let H=J4($);if(await g2("POST",`/cards/${$}/elements`,{type:J.type??"append",...J.targetElementId?{target_element_id:J.targetElementId}:{},elements:JSON.stringify([V]),sequence:H}),Y.elementCount+=1,X)Y.deadElements.delete(X)},(H)=>{if(X)XK(Y,X);Q?.(H.code,H)},!1,{elementId:X,targetElementId:J.targetElementId})),Y.queue}function u($,Z,J,Q,Y=!0){if(_$.has($))return Promise.resolve();let V=_0($);if(V.closing||V.writeDead||V.deadElements.has(Z))return Promise.resolve();let X=P0(J);return V.queue=V.queue.then(()=>U9($,`replaceElement ${Z}`,async()=>{if(V.writeDead||V.deadElements.has(Z))return;let H=J4($);await g2("PUT",`/cards/${$}/elements/${Z}`,{element:JSON.stringify(X),sequence:H})},(H)=>Q?.(H.code,H),!Y,{elementId:Z})),V.queue}async function W$($,Z,J,Q={}){if(_$.has($))return!1;let Y=_0($);if(Y.closing||Y.writeDead||Y.deadElements.has(Z))return!1;let V=!1;return await u($,Z,J,()=>{V=!0},Q.notifyCardFailure!==!1),!V&&!Y.writeDead&&!Y.deadElements.has(Z)}async function x0($,Z,J={}){return(await Q4($,Z,J)).landed}async function Q4($,Z,J={}){if(_$.has($))return{landed:!1};let Q=_0($);if(Q.closing||Q.writeDead)return{landed:!1};let Y=Z.element_id,V;return await H$($,Z,J,(X,H)=>{V=H}),{landed:!V&&!Q.writeDead&&!(Y&&Q.deadElements.has(Y)),...V?{failure:V}:{}}}function r0($,Z){if(_$.has($)||u$.get($)?.closing||u$.get($)?.writeDead)return;let J=(Z??"").replace(/\s+/g," ").trim();if(!J)return;let Q=o0.get($);if(!Q)Q={latest:J,lastSent:"",timer:null},o0.set($,Q);else Q.latest=J;if(Q.timer)return;Q.timer=setTimeout(()=>{let Y=o0.get($);if(!Y)return;if(_$.has($)){o0.delete($);return}if(Y.timer=null,Y.latest===Y.lastSent)return;let V=Y.latest;B$($,{config:{summary:{content:V}}}).then((X)=>{let H=o0.get($);if(X&&H===Y)H.lastSent=V})},YK)}function X$($){let Z=o0.get($);if(!Z)return;if(Z.timer)clearTimeout(Z.timer),Z.timer=null;o0.delete($)}function Y4($,Z){return B$($,Z).then(()=>{})}async function B$($,Z){if(_$.has($))return!1;let J=_0($);if(J.closing||J.writeDead)return!1;let Q=!1,Y=!1;return J.queue=J.queue.then(()=>U9($,"patchSettings",async()=>{if(_$.has($)||J.writeDead)return;let V=J4($);await g2("PATCH",`/cards/${$}/settings`,{settings:JSON.stringify(Z),sequence:V}),Q=!0},()=>{Y=!0},!0)),await J.queue,Q&&!Y&&!_$.has($)&&!J.writeDead}async function b$($){let Z=u$.get($);if(!Z){OJ($),X$($);return}if(Z.closing){await Z.queue;return}Z.closing=!0,X$($),await Z.queue,OJ($),u$.delete($)}var ZK="https://open.feishu.cn/open-apis/cardkit/v1",JK=15000,QK,u$,o0,YK=1500,_$,VK=5000;var a0=T(()=>{n();v();y$();QK=[0,250,750,1500];u$=new Map,o0=new Map;_$=new Set});function V4($){if(!$)return null;return typeof $.total_tokens==="number"&&Number.isFinite($.total_tokens)?$.total_tokens:null}function X4($){return typeof $==="number"&&Number.isFinite($)&&$>0?$:null}function GK($,Z,J=12000){if(Z==null||Z<=0)return null;if(Z<=J)return 0;let Q=Z-J,Y=Math.max(0,$-J),V=Math.max(0,Q-Y);return Math.round(Math.min(100,Math.max(0,V/Q*100)))}function xJ($,Z,J){let Q=GK($,Z,J??12000);if(Q==null)return null;return{used:Math.min(100,Math.max(0,100-Q)),remaining:Q}}function TJ($){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 H4($,Z){let J=TJ($);return Z!=null&&Z>0?`${J}/${TJ(Z)}`:`${J}/--`}function CJ($,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))}%`}import{isAbsolute as D9,relative as qK}from"node:path";function z4($){return $==="Bash"||$==="exec_command"||$.endsWith(".exec_command")}function K4($){return $==="write_stdin"||$.endsWith(".write_stdin")}function BK($){return z4($)||K4($)}function G4($){return $==="FileChange"||$==="fileChange"}function c2($){return $==="WebSearch"||$==="webSearch"}function q4($){return $==="WebFetch"||$==="webFetch"}function R9($){return $==="MCP"}function _4($){return $==="ImageGeneration"||$==="imageGeneration"}function E9($){return $==="Agent"||$==="Task"}function B4($){return $==="Read"}function L4($){return $==="Write"}function F4($){return $==="Edit"||$==="NotebookEdit"}function U4($){return $==="MultiEdit"}function T9($){return $==="Glob"||$==="Grep"||$==="LS"}function D4($){return $==="TodoWrite"}function P4($){return $==="ExitPlanMode"}function A4($){return $.startsWith(yJ)}function SJ($){return A4($)?$.slice(yJ.length):$}function t0($){if(A4($))return"服务端工具";if(G4($))return"文件变更";if(c2($))return"网页搜索";if(q4($))return"网页读取";if(_4($))return"图片生成";if(B4($))return"读取文件";if(L4($))return"写入文件";if(F4($)||U4($))return"编辑文件";if($==="Glob")return"匹配文件";if($==="Grep")return"搜索文件";if($==="LS")return"列目录";if(D4($))return"更新待办";if(P4($))return"确认计划";if($==="Task")return"子任务";return BK($)?"Bash":$}function L0($,Z){let J=(Q,Y)=>Q.length>Y?Q.slice(0,Y)+"…":Q;if(A4($))return J(LK($,Z),80);if(!Z||typeof Z!=="object")return"";if(z4($))return FK(Z);if(K4($))return UK(Z);if(G4($))return J(AK(Z),80);if(c2($))return J(oJ(Z),80);if(q4($))return J(xK(Z),80);if(R9($))return J(NK(Z),80);if(_4($))return J(SK(Z),80);if(E9($))return J(kK(Z),80);if(B4($))return J(MK(Z),80);if(L4($))return J(OK(Z),80);if(F4($))return J(jK(Z),80);if(U4($))return J(RK(Z),80);if(T9($))return J(EK($,Z),80);if(D4($))return J(TK(Z),80);if(P4($))return J(u2(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 LK($,Z){let J=typeof Z?.tool==="string"&&Z.tool?Z.tool:SJ($),Q=u2(Z?.input);return Q?`${J}: ${Q}`:J}function FK($){let Z=(V,X)=>V.length>X?V.slice(0,X)+"…":V,J=wJ($);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((V)=>V.trim()).filter(Boolean);if(Y.length<=1)return Z(Q.replace(/\s+/g," "),80);return`Shell 脚本 · ${Y.length} 行 · ${Z(j1(Q),46)}`}function kJ($){let Z=typeof $?.chars==="string"?$.chars:"";if(Z==="")return"读取会话输出";if(Z==="\x03")return"中断会话";return"发送输入"}function UK($){let Z=$?.session_id??$?.sessionId,J=Z===void 0?"":` ${Z}`;return`${kJ($)}${J}`}function wJ($){let Z=String($?.command??$?.cmd??$?.script??""),J=String($?.description??$?.reason??"").trim(),Q=sZ(Z);return{description:Q.description||J,command:Q.command}}function d$($,Z=""){let J="```";while($.includes(J))J+="`";return`${J}${Z}
|
|
61
62
|
${$}
|
|
62
|
-
${J}`}function
|
|
63
|
+
${J}`}function B0($,Z=_K,J=""){if($.length<=Z)return d$($,J);let Q=$.slice(0,Z).trimEnd();return[`_已截断: 仅显示前 ${Z} / ${$.length} 字符。_`,d$(`${Q}
|
|
63
64
|
... output 已截断 ...`,J)].join(`
|
|
64
|
-
`)}function S($){return"`"+String($??"").replace(/`/g,"'")+"`"}function
|
|
65
|
-
`)}function
|
|
66
|
-
`)}function
|
|
67
|
-
... diff 已截断 ...`:$}function
|
|
68
|
-
`):
|
|
69
|
-
`)}function
|
|
70
|
-
`):
|
|
71
|
-
`):
|
|
72
|
-
`):
|
|
73
|
-
`)}function
|
|
74
|
-
`)}function
|
|
75
|
-
`)}function
|
|
76
|
-
`)}function
|
|
77
|
-
`)}function
|
|
78
|
-
`).slice(0,3000));if(V.structuredContent)Q.push(""),Q.push("**structuredContent**"),Q.push(
|
|
79
|
-
`):
|
|
80
|
-
`)}function
|
|
81
|
-
`):
|
|
82
|
-
`):
|
|
83
|
-
|
|
84
|
-
${V}`:"",
|
|
65
|
+
`)}function S($){return"`"+String($??"").replace(/`/g,"'")+"`"}function v$($,Z=3000){return d$(JSON.stringify($??null,null,2).slice(0,Z),"json")}function u2($){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 bJ($,Z,J){let Q=wJ($),Y=Q.command,V=Q.description,X=[];if(V)X.push(`**目的**: ${V}`);let H=$?.cwd??$?.workdir;if(H)X.push(`**cwd**: ${S(H)}`);if($?.source)X.push(`**source**: ${S($.source)}`);if(X.length>0)X.push("");if(X.push("**命令**"),X.push(d$(Y||"(空命令)","bash")),J)X.push(""),X.push(J);if(Z!=null)X.push(""),X.push("---"),X.push("**output:**"),X.push(B0(Z));return X.join(`
|
|
66
|
+
`)}function vJ($,Z,J){let Q=[],Y=$?.session_id??$?.sessionId;if(Q.push(`**操作**: ${kJ($)}`),Y!==void 0)Q.push(`**session**: ${S(Y)}`);if(typeof $?.chars==="string"&&$.chars.length>0){let V=$.chars==="\x03"?"^C":$.chars;Q.push(""),Q.push("**输入**"),Q.push(d$(V))}if(J)Q.push(""),Q.push(J);if(Z!=null)Q.push(""),Q.push("---"),Q.push("**output:**"),Q.push(B0(Z));return Q.join(`
|
|
67
|
+
`)}function fJ($){return Array.isArray($?.changes)?$.changes:[]}function hJ($){let Z=$?.cwd??$?.grantRoot;return typeof Z==="string"&&Z.length>0?Z:void 0}function m2($,Z){let J=String($??"");if(!J)return"(无 path)";if(Z&&D9(J)&&D9(Z)){let Q=qK(Z,J);if(Q&&!Q.startsWith("..")&&!D9(Q))return Q}return J}function DK($){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 IJ($){return $?.kind?.move_path??$?.kind?.movePath??$?.move_path??$?.movePath}function A9($){let Z=DK($);if(IJ($))return Z==="update"?"移动/修改":"移动";switch(Z){case"add":return"新增";case"delete":return"删除";case"update":return"修改";default:return"变更"}}function M9($){let Z=$?.diff??$?.unified_diff;return typeof Z==="string"?Z:""}function O9($){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 gJ($,Z){return{added:$.added+Z.added,removed:$.removed+Z.removed}}function j9($){return $.added>0||$.removed>0?`+${$.added} -${$.removed}`:""}function PK($){return $.length>1800?$.slice(0,1800)+`
|
|
68
|
+
... diff 已截断 ...`:$}function AK($){let Z=fJ($),J=hJ($);if(Z.length===0){let W=typeof $?.reason==="string"?$.reason.trim():"",z=$?.grantRoot?m2($.grantRoot):"";if(W&&z)return`${W} · ${z}`;return W||(z?`申请修改 ${z}`:"")}let Q=Z.map((W)=>O9(M9(W))).reduce(gJ,{added:0,removed:0}),Y=j9(Q),V=[...new Set(Z.map(A9))],X=m2(Z[0]?.path,J),H=Y?` · ${Y}`:"";if(Z.length===1)return`${V[0]} ${X}${H}`;return`${Z.length} 个文件 · ${V.join("/")} · ${X} 等${H}`}function mJ($,Z,J){let Q=fJ($),Y=hJ($),V=[];if(Q.length===0){let z=typeof $?.reason==="string"?$.reason.trim():"";if(z)V.push(`**原因**: ${z}`);if($?.grantRoot)V.push(`**范围**: ${S(m2($.grantRoot))}`);if(J)V.push(""),V.push(J);if(Z!=null)V.push(""),V.push("---"),V.push("**output:**"),V.push(d$(Z.slice(0,3000)));return V.length>0?V.join(`
|
|
69
|
+
`):d$(JSON.stringify($??{},null,2).slice(0,2000))}let X=Q.map((z)=>O9(M9(z))).reduce(gJ,{added:0,removed:0}),H=j9(X);if(V.push(`**文件**: ${Q.length} 个`),H)V.push(`**行数**: ${H}`);if($?.status)V.push(`**状态**: ${S($.status)}`);let W=Q.slice(0,5);for(let z of W){let G=M9(z),q=j9(O9(G)),B=m2(z?.path,Y),L=q?`**${A9(z)}** ${S(B)} · ${q}`:`**${A9(z)}** ${S(B)}`;V.push(""),V.push(L);let F=IJ(z);if(F)V.push(`来自 ${S(m2(F,Y))}`);V.push(G?d$(PK(G),"diff"):"_无 diff 内容_")}if(Q.length>W.length)V.push(""),V.push(`还有 ${Q.length-W.length} 个文件未展开显示。`);if(J)V.push(""),V.push(J);return V.join(`
|
|
70
|
+
`)}function C0($){return String($?.file_path??$?.path??$?.notebook_path??"")}function MK($){let Z=C0($),J=[$?.offset!=null?`offset ${$.offset}`:"",$?.limit!=null?`limit ${$.limit}`:""].filter(Boolean).join(" · ");return J&&Z?`${Z} · ${J}`:Z}function OK($){let Z=C0($),J=typeof $?.content==="string"?$.content:"",Q=J?J.split(/\r?\n/).length:0;return Z&&Q?`${Z} · ${Q} 行`:Z}function jK($){let Z=C0($),J=$?.replace_all?"全局替换":"替换";return Z?`${J} ${Z}`:J}function RK($){let Z=C0($),J=Array.isArray($?.edits)?$.edits.length:0,Q=J?` · ${J} 处`:"";return Z?`批量编辑 ${Z}${Q}`:`批量编辑${Q}`}function EK($,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 cJ($){switch($){case"pending":return"待办";case"in_progress":return"进行中";case"completed":return"完成";default:return String($??"未知")}}function TK($){let Z=Array.isArray($?.todos)?$.todos:[];if(Z.length===0)return"";let J=new Map;for(let Y of Z){let V=cJ(Y?.status);J.set(V,(J.get(V)??0)+1)}let Q=[...J.entries()].map(([Y,V])=>`${Y} ${V}`).join(" · ");return`${Z.length} 项${Q?` · ${Q}`:""}`}function xK($){let Z=String($?.url??""),J=typeof $?.prompt==="string"?$.prompt.trim():"";return Z&&J?`${Z} · ${J}`:Z||J}function m1($,Z){if(Z==null)return;$.push(""),$.push("---"),$.push("**结果**"),$.push(B0(Z,1200))}function uJ($,Z,J){let Q=[],Y=C0($);if(Y)Q.push(`**路径**: ${S(Y)}`);if($?.offset!=null)Q.push(`**offset**: ${S($.offset)}`);if($?.limit!=null)Q.push(`**limit**: ${S($.limit)}`);if(J)Q.push(""),Q.push(J);if(Z!=null)Q.push(""),Q.push("_内容已读取,未展开到群聊卡片。_");return Q.length>0?Q.join(`
|
|
71
|
+
`):v$($??{},2000)}function pJ($,Z,J){let Q=[],Y=C0($),V=typeof $?.content==="string"?$.content:"";if(Y)Q.push(`**路径**: ${S(Y)}`);if(V){let X=V.split(/\r?\n/).length;Q.push(`**内容**: ${X} 行 / ${V.length} 字符`),Q.push(B0(V,1200))}if(J)Q.push(""),Q.push(J);return m1(Q,Z),Q.length>0?Q.join(`
|
|
72
|
+
`):v$($??{},2000)}function lJ($,Z,J){let Q=[],Y=C0($);if(Y)Q.push(`**路径**: ${S(Y)}`);if($?.cell_id)Q.push(`**cell**: ${S($.cell_id)}`);if($?.edit_mode)Q.push(`**模式**: ${S($.edit_mode)}`);if($?.replace_all)Q.push("**范围**: 全局替换");if(typeof $?.old_string==="string")Q.push(""),Q.push("**查找**"),Q.push(B0($.old_string,800));let V=typeof $?.new_string==="string"?$.new_string:typeof $?.new_source==="string"?$.new_source:"";if(V)Q.push(""),Q.push("**替换为**"),Q.push(B0(V,800));if(J)Q.push(""),Q.push(J);return m1(Q,Z),Q.length>0?Q.join(`
|
|
73
|
+
`):v$($??{},2000)}function dJ($,Z,J){let Q=[],Y=C0($),V=Array.isArray($?.edits)?$.edits:[];if(Y)Q.push(`**路径**: ${S(Y)}`);Q.push(`**编辑**: ${V.length} 处`);for(let[X,H]of V.slice(0,5).entries()){if(Q.push(""),Q.push(`**#${X+1}${H?.replace_all?" · 全局替换":""}**`),typeof H?.old_string==="string")Q.push("查找:"),Q.push(B0(H.old_string,500));if(typeof H?.new_string==="string")Q.push("替换为:"),Q.push(B0(H.new_string,500))}if(V.length>5)Q.push(""),Q.push(`还有 ${V.length-5} 处编辑未展开显示。`);if(J)Q.push(""),Q.push(J);return m1(Q,Z),Q.join(`
|
|
74
|
+
`)}function iJ($,Z,J,Q){let Y=[];if($==="Glob"){if(Y.push("**动作**: 匹配文件"),Z?.pattern)Y.push(`**pattern**: ${S(Z.pattern)}`);if(Z?.path)Y.push(`**path**: ${S(Z.path)}`)}else if($==="Grep"){if(Y.push("**动作**: 搜索文件"),Z?.pattern)Y.push(`**pattern**: ${S(Z.pattern)}`);if(Z?.path)Y.push(`**path**: ${S(Z.path)}`);if(Z?.glob)Y.push(`**glob**: ${S(Z.glob)}`);if(Z?.type)Y.push(`**type**: ${S(Z.type)}`);if(Z?.output_mode)Y.push(`**output**: ${S(Z.output_mode)}`)}else{if(Y.push("**动作**: 列目录"),Z?.path)Y.push(`**path**: ${S(Z.path)}`);if(Array.isArray(Z?.ignore)&&Z.ignore.length)Y.push(`**ignore**: ${Z.ignore.map(S).join(" ")}`)}if(Q)Y.push(""),Y.push(Q);return m1(Y,J),Y.join(`
|
|
75
|
+
`)}function nJ($,Z,J){let Q=Array.isArray($?.todos)?$.todos:[],Y=[`**待办**: ${Q.length} 项`];for(let V of Q.slice(0,12)){let X=cJ(V?.status),H=String(V?.content??V?.activeForm??"").trim()||"(空)";Y.push(`- ${X}: ${H}`)}if(Q.length>12)Y.push(`- 还有 ${Q.length-12} 项未显示`);if(J)Y.push(""),Y.push(J);return m1(Y,Z),Y.join(`
|
|
76
|
+
`)}function x9($){if(!$)return null;try{let Z=JSON.parse($);return Z&&typeof Z==="object"?Z:null}catch{return null}}function C9($,Z){return x9(Z)??$?.action??{}}function N9($,Z){let J=C9($,Z),Q=Array.isArray(J?.queries)?J.queries.filter((V)=>typeof V==="string"&&V.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 y9($,Z){let J=C9($,Z);return String(J?.url??$?.url??"")}function oJ($){let Z=N9($,null);if(Z.length===1)return Z[0];if(Z.length>1)return`${Z.length} 条查询 · ${Z[0]}`;let J=y9($,null);if(J)return J;let Q=$?.action?.type;return typeof Q==="string"&&Q!=="other"?Q:""}function CK($,Z){let J=N9($,Z);if(J.length===1)return J[0];if(J.length>1)return`${J.length} 条查询 · ${J[0]}`;let Q=y9($,Z);if(Q)return Q;return oJ($)}function rJ($,Z,J){let Q=C9($,Z),Y=N9($,Z),V=y9($,Z),X=[],H=typeof Q?.type==="string"?Q.type:"";if(H==="search"||Y.length>0){if(X.push("**动作**: 搜索"),Y.length>0){X.push(""),X.push("**查询**");for(let W of Y.slice(0,6))X.push(`- ${S(W)}`);if(Y.length>6)X.push(`- 还有 ${Y.length-6} 条未显示`)}}else if(H==="open_page"){if(X.push("**动作**: 打开页面"),V)X.push(`**URL**: ${S(V)}`)}else if(H==="find_in_page"){if(X.push("**动作**: 页内查找"),V)X.push(`**URL**: ${S(V)}`);if(Q?.pattern)X.push(`**关键词**: ${S(Q.pattern)}`)}else if(X.push(`**动作**: ${H?S(H):"网页搜索"}`),V)X.push(`**URL**: ${S(V)}`);if(J)X.push(""),X.push(J);if(X.length===1&&!Y.length&&!V&&Z!=null)X.push(""),X.push("---"),X.push("**output:**"),X.push(d$(Z.slice(0,3000),"json"));return X.join(`
|
|
77
|
+
`)}function aJ($,Z,J){let Q=["**动作**: 读取网页"];if($?.url)Q.push(`**URL**: ${S($.url)}`);if($?.prompt)Q.push(""),Q.push("**问题**"),Q.push(String($.prompt).slice(0,1200));if(J)Q.push(""),Q.push(J);return m1(Q,Z),Q.join(`
|
|
78
|
+
`)}function NK($){let Z=String($?.server??""),J=String($?.tool??""),Q=Z&&J?`${Z}.${J}`:J||Z,Y=u2($?.arguments);return Y&&Q?`${Q}: ${Y}`:Q||Y}function tJ($,Z,J){let Q=[];if($?.server)Q.push(`**server**: ${S($.server)}`);if($?.tool)Q.push(`**tool**: ${S($.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(v$(Y,2000))}if(J)Q.push(""),Q.push(J);if(Z!=null){let V=x9(Z);if(Q.push(""),Q.push("---"),Q.push("**结果**"),V&&Array.isArray(V.content)){let X=V.content.map((H)=>typeof H?.text==="string"?H.text:"").filter(Boolean);if(X.length>0)Q.push(X.join(`
|
|
79
|
+
`).slice(0,3000));if(V.structuredContent)Q.push(""),Q.push("**structuredContent**"),Q.push(v$(V.structuredContent,2000));if(X.length===0&&!V.structuredContent)Q.push(v$(V,3000))}else Q.push(V?v$(V,3000):d$(Z.slice(0,3000)))}return Q.length>0?Q.join(`
|
|
80
|
+
`):v$($??{},2000)}function yK($,Z,J,Q){let Y=["**类型**: 模型服务端内置工具",`**tool**: ${S(typeof Z?.tool==="string"&&Z.tool?Z.tool:SJ($))}`],V=Z?.input;if(V&&typeof V==="object")if(Y.push(""),Y.push("**input**"),Object.keys(V).length>0)Y.push(v$(V,2000));else Y.push("_provider 未提供结构化 input_");else if(V!=null&&V!=="")Y.push(`**input**: ${S(V)}`);if(Q)Y.push(""),Y.push(Q);if(J!=null)Y.push(""),Y.push("---"),Y.push("**结果**"),Y.push(B0(J,3000));return Y.join(`
|
|
81
|
+
`)}function SK($){let Z=typeof $?.revisedPrompt==="string"?$.revisedPrompt:"",J=typeof $?.status==="string"?$.status:"";return Z||J}function sJ($,Z,J){let Q=[];if($?.status)Q.push(`**状态**: ${S($.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(S(Z.trim()));return Q.length>0?Q.join(`
|
|
82
|
+
`):v$($??{},2000)}function kK($){let Z=typeof $?.tool==="string"?$.tool:"",J=typeof $?.prompt==="string"?$.prompt:"",Q=typeof $?.description==="string"?$.description:"",Y=typeof $?.subject==="string"?$.subject:"",V=Q||Y||J;return Z&&V?`${Z}: ${V}`:V||Z}function W4($,Z,J){let Q=[];if($?.tool)Q.push(`**tool**: ${S($.tool)}`);if($?.model)Q.push(`**model**: ${S($.model)}`);if($?.description)Q.push(`**描述**: ${$.description}`);if($?.subagent_type)Q.push(`**类型**: ${S($.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=x9(Z);Q.push(Y?v$(Y,3000):d$(Z.slice(0,3000)))}return Q.length>0?Q.join(`
|
|
83
|
+
`):v$($??{},2000)}function F0($,Z,J,Q,Y="⏳",V){let X=c2(Z)&&Q!=null?CK(J,Q):L0(Z,J),H=X.length>80?X.slice(0,80)+"…":X,W=t0(Z),z=H?`${Y} \uD83D\uDD27 ${W}: ${H}`:`${Y} \uD83D\uDD27 ${W}`,G=V?`
|
|
84
|
+
|
|
85
|
+
${V}`:"",q=z4(Z)?bJ(J,Q,V):K4(Z)?vJ(J,Q,V):A4(Z)?yK(Z,J,Q,V):G4(Z)?mJ(J,Q,V):c2(Z)?rJ(J,Q,V):q4(Z)?aJ(J,Q,V):R9(Z)?tJ(J,Q,V):_4(Z)?sJ(J,Q,V):B4(Z)?uJ(J,Q,V):L4(Z)?pJ(J,Q,V):F4(Z)?lJ(J,Q,V):U4(Z)?dJ(J,Q,V):T9(Z)?iJ(Z,J,Q,V):D4(Z)?nJ(J,Q,V):P4(Z)?W4({prompt:u2(J)||"提交计划"},Q,V):E9(Z)?W4(J,Q,V):"```\n"+JSON.stringify(J??{},null,2).slice(0,2000)+"\n```"+G+(Q!=null?`
|
|
85
86
|
---
|
|
86
87
|
**output:**
|
|
87
88
|
\`\`\`
|
|
88
|
-
`+Q.slice(0,3000)+"\n```":"");return{tag:"collapsible_panel",element_id:
|
|
89
|
-
`))}]}}function
|
|
90
|
-
`))}]}}function
|
|
91
|
-
`)}]}}function
|
|
92
|
-
`)}function
|
|
93
|
-
`)}]}}function
|
|
94
|
-
`)});continue}if(X===J){if(V.push({tag:"markdown",content:`**\uD83E\uDD14 ${
|
|
95
|
-
*— 由 ${
|
|
96
|
-
`).map((
|
|
97
|
-
`)){let B=
|
|
98
|
-
`)}function
|
|
99
|
-
`)}function
|
|
100
|
-
`);let Z=[];if($.cpu){let{cores:J,load1:Q,load5:Y,load15:V}=$.cpu;Z.push(`**负载** ${Q.toFixed(2)} / ${Y.toFixed(2)} / ${V.toFixed(2)} (${J}核)`)}else Z.push("**负载** _n/a_");if($.mem)Z.push(`**内存** ${$.mem.percent}% (${
|
|
101
|
-
`)}function
|
|
102
|
-
`)}function
|
|
103
|
-
`)}function
|
|
104
|
-
`)}function
|
|
105
|
-
选账号进入模型选择。`},...$.providers.map((Z)=>
|
|
106
|
-
${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
|
|
107
|
-
`)},...$.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
|
|
108
|
-
`)},{tag:"button",text:{tag:"plain_text",content:"取消"},type:"default",width:"default",behaviors:[{type:"callback",value:{kind:"model_panel_cancel",panel_id:J}}]}]},"blue")}function
|
|
109
|
-
`)},...$.model.efforts.length?$.model.efforts.map((Z)=>
|
|
110
|
-
`)}]}}function
|
|
111
|
-
${
|
|
112
|
-
`+
|
|
113
|
-
`)+Y}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:$.selected?"primary":"default",behaviors:[{type:"callback",value
|
|
114
|
-
`)}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:V?"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
|
|
89
|
+
`+Q.slice(0,3000)+"\n```":"");return{tag:"collapsible_panel",element_id:O.tool($),header:{title:{tag:"plain_text",content:z}},expanded:!1,elements:[{tag:"markdown",content:D$(q)}]}}function c1($,Z){let J=Z.length,Q=Z.some((W)=>W.isError),Y=Z.every((W)=>W.output!==null),V=Q?"❌":Y?"✅":"⏳",X=J===1?(()=>{let W=NJ(Z[0]);return W?`${V} \uD83D\uDD27 编辑文件: ${W}`:`${V} \uD83D\uDD27 编辑文件`})():`${V} \uD83D\uDD27 编辑文件 · ${J} 次`,H=Z.map((W)=>{let z=NJ(W);return z?`\`${z}\``:"`(无 path)`"});return{tag:"collapsible_panel",element_id:O.tool($),header:{title:{tag:"plain_text",content:X}},expanded:!1,elements:[{tag:"markdown",content:D$(H.join(`
|
|
90
|
+
`))}]}}function NJ($){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 u1($,Z){let J=Z.length,Q=Z.some((W)=>W.isError),Y=Z.every((W)=>W.output!==null),V=Q?"❌":Y?"✅":"⏳",X=J===1?(()=>{let W=L0("Read",Z[0]?.input);return W?`${V} \uD83D\uDD27 Read: ${W}`:`${V} \uD83D\uDD27 Read`})():`${V} \uD83D\uDD27 Read · ${J} 次`,H=Z.map((W)=>`\`${String(W.input.file_path??"(无 path)")}\``);return{tag:"collapsible_panel",element_id:O.tool($),header:{title:{tag:"plain_text",content:X}},expanded:!1,elements:[{tag:"markdown",content:D$(H.join(`
|
|
91
|
+
`))}]}}function M4($,Z,J,Q){let Y=L0(Z,J),V=t0(Z),X=Y?`\uD83D\uDD10 等审批 · ${V}: ${Y}`:`\uD83D\uDD10 等审批 · ${V}`,H=z4(Z)?bJ(J,null):K4(Z)?vJ(J,null):G4(Z)?mJ(J,null):c2(Z)?rJ(J,null):q4(Z)?aJ(J,null):R9(Z)?tJ(J,null):_4(Z)?sJ(J,null):B4(Z)?uJ(J,null):L4(Z)?pJ(J,null):F4(Z)?lJ(J,null):U4(Z)?dJ(J,null):T9(Z)?iJ(Z,J,null):D4(Z)?nJ(J,null):P4(Z)?W4({prompt:u2(J)||"提交计划"},null):E9(Z)?W4(J,null):"```\n"+JSON.stringify(J??{},null,2).slice(0,2000)+"\n```";return{tag:"collapsible_panel",element_id:O.tool($),header:{title:{tag:"plain_text",content:X}},expanded:!0,elements:[{tag:"markdown",content:H},{tag:"column_set",columns:[P9("✅ 允许","primary",Q,"allow"),P9("♾️ 始终允许","default",Q,"allow_always"),P9("❌ 拒绝","danger",Q,"deny")]}]}}function P9($,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 _K=300,yJ="server_tool:";var S9=T(()=>{y$();S8()});function j4($){return JSON.stringify({objective:$.objective,status:$.status,tokenBudget:$.tokenBudget})}function wK($){switch($){case"pending":return"☐";case"inProgress":return"\uD83D\uDD04";case"completed":return"✅";default:return"·"}}function bK($,Z){return $.length>Z?$.slice(0,Z)+"…":$}function O4($){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 eJ($){switch($){case"active":return"进行中";case"paused":return"已暂停";case"blocked":return"受阻";case"usageLimited":return"额度受限";case"budgetLimited":return"预算受限";case"complete":return"已完成";default:return $}}function ZQ($){let Z=$.filter((V)=>V.status==="completed").length,J=$.filter((V)=>V.status==="inProgress").length,Q=$.filter((V)=>V.status==="pending").length,Y=[`${$.length} 项`];if(J)Y.push(`${J} 进行中`);if(Z)Y.push(`${Z} 完成`);if(Q)Y.push(`${Q} 待办`);return Y.join(" · ")}function vK($,Z=""){let J=Z.trim();if($.length===0)return J?"\uD83D\uDCCB 计划草稿":"\uD83D\uDCCB 计划更新";return`\uD83D\uDCCB 计划更新 · ${ZQ($)}`}function JQ($){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 k9($){return typeof $==="number"&&Number.isFinite($)?$:null}function fK($){let Z=k9($.startedAtMs),J=k9($.completedAtMs);if(Z==null||J==null||J<Z)return"";return` · 耗时 ${JQ((J-Z)/1000)}`}function hK($){let Z=k9($);return Z==null?null:O4(Z)}function IK($,Z){if(!Z)return["压缩中..."];let J=[],Q=typeof $.trigger==="string"&&$.trigger.trim()?$.trigger.trim():"",Y=hK($.preTokens),V=typeof $.sourceType==="string"&&$.sourceType.trim()?$.sourceType.trim():"";if(Q)J.push(`**触发**: ${Q}`);if(Y)J.push(`**压缩前**: ${Y} tokens`);if(V)J.push(`**来源**: ${V}`);return J.length>0?J:["压缩完成,无摘要内容"]}function w9($,Z,J){if($==null||!Number.isFinite($))return null;let Q=xJ($,Z,J);return Q?`${Q.used}% · ${H4($,Z)}`:"--"}function b9($){let Z=O4($?.input_tokens??Number.NaN),J=O4($?.cache_read_input_tokens??Number.NaN),Q=O4($?.output_tokens??Number.NaN);return`└ 入 ${Z} | 缓 ${J} | 出 ${Q}`}function p2($,Z,J){let Q=Z&&typeof Z==="object"?Z:{},Y=Q.phase==="end"||Q.phase==="event",V=Y?"✅":"⏳",X=Y?fK(Q):"",H=`${V} \uD83D\uDEA8 上下文压缩 #${$+1}${X}`,W=IK(Q,Y);return{tag:"collapsible_panel",element_id:J,header:{title:{tag:"plain_text",content:H}},expanded:!1,elements:[{tag:"markdown",content:W.join(`
|
|
92
|
+
`)}]}}function QQ($,Z,J=""){let Q=["**\uD83D\uDCCB 当前计划**"],Y=Z?.trim();if(Y)Q.push(""),Q.push(Y);if($.length>0){Q.push("");for(let V of $)Q.push(`- ${wK(V.status)} ${V.step}`)}else{let V=J.trim();if(Q.push(""),V)Q.push("正在生成计划草稿..."),Q.push(""),Q.push(V);else Q.push("--")}return Q.join(`
|
|
93
|
+
`)}function v9($,Z,J="",Q){return{tag:"collapsible_panel",element_id:Q,header:{title:{tag:"plain_text",content:vK($,J)}},expanded:!1,elements:[{tag:"markdown",content:QQ($,Z,J)}]}}function l2($,Z,J){let Q=$.length>0?`\uD83D\uDCCB 当前计划 · ${ZQ($)}`:"\uD83D\uDCCB 当前计划";return{tag:"collapsible_panel",element_id:J,header:{title:{tag:"plain_text",content:Q}},expanded:!0,elements:[{tag:"markdown",content:QQ($,Z)}]}}function f9($,Z){let J=Number.isFinite($.tokensUsed)?String($.tokensUsed):"MISS",Q=$.tokenBudget==null?"":Number.isFinite($.tokenBudget)?` / ${$.tokenBudget}`:" / MISS",Y=[`**\uD83C\uDFAF 当前目标** · ${eJ($.status)}`,"",$.objective,"",`- 用量: ${J}${Q} tokens`,`- 用时: ${JQ($.timeUsedSeconds)}`];return{tag:"collapsible_panel",element_id:Z,header:{title:{tag:"plain_text",content:`\uD83C\uDFAF 目标更新 · ${eJ($.status)}: ${bK($.objective,48)}`}},expanded:!1,elements:[{tag:"markdown",content:Y.join(`
|
|
94
|
+
`)}]}}function R4($){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}`}]:[],Q=$.userInputs??[],Y=`\uD83D\uDCE5 收到 (${Q.length}) ${$.directStart?"\uD83D\uDE80":`#${$.turn}`}`,V=Q.length>0?[{tag:"collapsible_panel",element_id:O.userInput,header:{title:{tag:"plain_text",content:Y}},expanded:!1,elements:Q.map((X)=>({tag:"markdown",content:D$(X)}))}]:[];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,...V,{tag:"markdown",element_id:O.footer,content:$.initialFooter??"Waiting...(0s)"}]}}}function YQ($,Z,J){let Q=$.question.trim()||`问题 ${Z+1}`;return`${Z+1}/${J} · ${Q}`}function gK($,Z){if(!Z)return"?";return Z.customText??(Z.optionIdx!==void 0?$.options[Z.optionIdx]?.label:void 0)??"?"}function mK($,Z,J){let Q=[];for(let Y=0;Y<$.options.length;Y++){let V=$.options[Y],X=V.description?` · ${D$(V.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:`**${D$(V.label)}**${X}`}]})}return Q}function $Q($,Z,J,Q){if($.length===0)return null;let Y=$.length,V=[];for(let X=0;X<$.length;X++){let H=$[X];if(!H)continue;let W=YQ(H,X,Y),z=Q.get(X);if(z){let G=gK(H,z),q=[`**✅ ${W}**`,`**回答**:${G}`];V.push({tag:"markdown",content:q.join(`
|
|
95
|
+
`)});continue}if(X===J){if(V.push({tag:"markdown",content:`**\uD83E\uDD14 ${W}**`}),H.options.length>0)V.push(...mK(H,Z,X));V.push({tag:"markdown",content:"_\uD83D\uDCAC 也可以直接在群里回复你的答案(裸词命令 `hi`/`stop`/`kill`/`restart`/`clear`/`model` 仍然优先)_"});continue}V.push({tag:"markdown",content:`**⏳ ${W}**`})}return V}function d2($,Z,J,Q="\uD83E\uDD14",Y){let V=J.length,X=Y?.answered??new Map,H=Y?.currentIdx,W=H===void 0&&X.size>0,z=[],G;if(W){G=`${Q} 已回答 · ${V}/${V}`,z.push(...$Q(J,Z,H,X)??[]);let q=[...X.values()].reverse().find((B)=>B.user)?.user;if(q)z.push({tag:"markdown",content:`
|
|
96
|
+
*— 由 ${q} 回答*`})}else if(H!==void 0&&J[H])G=`${Q} 等你确认 · ${H+1}/${V}`,z.push(...$Q(J,Z,H,X)??[]);else if(G=`${Q} 等你确认`,J[0])z.push({tag:"markdown",content:`**${YQ(J[0],0,V||1)}**`});return{tag:"collapsible_panel",element_id:O.tool($),header:{title:{tag:"plain_text",content:G}},expanded:!W,elements:z}}var VQ=T(()=>{y$();S9()});import{execFile as cK}from"node:child_process";import{readFileSync as h9,statfsSync as uK,statSync as XQ}from"node:fs";import{cpus as pK,homedir as lK}from"node:os";import{promisify as dK}from"node:util";function nK(){try{let $=h9("/proc/loadavg","utf8").trim().split(/\s+/);return{cores:pK().length,load1:parseFloat($[0]??"0"),load5:parseFloat($[1]??"0"),load15:parseFloat($[2]??"0")}}catch($){return K(`sysinfo: read /proc/loadavg failed: ${$}`),null}}function oK(){try{let $=h9("/proc/meminfo","utf8"),Z=(V)=>{let X=$.match(new RegExp(`^${V}:\\s+(\\d+)\\s*kB`,"m"));return X?parseInt(X[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 K(`sysinfo: read /proc/meminfo failed: ${$}`),null}}function HQ($,Z){try{let J=uK(Z,{bigint:!1}),Q=J.blocks*J.bsize,Y=J.bavail*J.bsize,V=Math.max(0,Q-Y);if(!Q)return null;return{label:$,path:Z,totalBytes:Q,availBytes:Y,usedBytes:V,percent:Math.round(V/Q*100)}}catch(J){return K(`sysinfo: statfs ${Z} failed: ${J}`),null}}function rK(){let $=[],Z=HQ("/","/");if(Z)$.push(Z);let J=lK();if(J&&J!=="/"){let Q=!1;try{let Y=XQ("/"),V=XQ(J);Q=Y.dev===V.dev}catch{}if(!Q){let Y=HQ("$HOME",J);if(Y)$.push(Y)}}return $}function aK(){try{let $=h9("/proc/uptime","utf8").trim().split(/\s+/);return parseFloat($[0]??"0")}catch{return null}}async function WQ($,Z=2000){try{let{stdout:J}=await iK("systemctl",["--user",...$],{timeout:Z,maxBuffer:4194304});return J}catch(J){return K(`sysinfo: systemctl ${$.join(" ")} failed: ${J}`),null}}function zQ($){return KQ.some((Z)=>$.startsWith(Z))&&$.endsWith(".service")}async function tK(){let $=await WQ(["list-units","--type=service","--all","--no-legend","--plain",...KQ.map((W)=>`${W}*`)]);if($===null)return{services:[],error:"systemctl 不可用"};let Z=$.split(`
|
|
97
|
+
`).map((W)=>W.trim()).filter((W)=>W.length>0);if(Z.length===0)return{services:[],error:null};let J=[];for(let W of Z){let G=W.replace(/^●\s*/,"").split(/\s+/)[0];if(!G)continue;if(!zQ(G))continue;J.push(G)}if(J.length===0)return{services:[],error:null};let Q=await WQ(["show",...J,"-p","Id","-p","ActiveState","-p","SubState","-p","ActiveEnterTimestampMonotonic","-p","StateChangeTimestampMonotonic"]);if(Q===null)return{services:[],error:"systemctl show 失败"};let Y=aK(),V=Q.split(/\n\s*\n/),X=[],H=(W)=>{let z=parseInt(W??"0",10);if(z<=0||Y===null)return null;return Math.max(0,Y-z/1e6)};for(let W of V){let z={};for(let q of W.split(`
|
|
98
|
+
`)){let B=q.indexOf("=");if(B<=0)continue;z[q.slice(0,B)]=q.slice(B+1)}let G=z.Id??"";if(!zQ(G))continue;X.push({name:G.replace(/\.service$/,""),active:z.ActiveState??"unknown",sub:z.SubState??"",lastActiveAgoSec:H(z.ActiveEnterTimestampMonotonic),stateAgoSec:H(z.StateChangeTimestampMonotonic)})}return X.sort((W,z)=>W.name.localeCompare(z.name)),{services:X,error:null}}async function GQ(){if(process.platform==="win32")return{cpu:null,mem:null,disks:[],services:[],servicesError:"Windows: sysinfo 暂未支持"};let $=nK(),Z=oK(),J=rK(),{services:Q,error:Y}=await tK();return{cpu:$,mem:Z,disks:J,services:Q,servicesError:Y}}var iK,KQ,i2="cc-* / codex-*";var I9=T(()=>{v();iK=dK(cK),KQ=["cc-","codex-"]});function o2($,Z){return Z}function g9($){return{schema:"2.0",config:{update_multi:!0,streaming_mode:!0,summary:{content:$.status}},body:{elements:[{tag:"markdown",element_id:O.footer,content:o2($.title,$.status)}]}}}function qQ($){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 sK($){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 n2($){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 U0($){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 BQ($){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=[p1($.fiveHour.percent)];if($.fiveHour.resetsAt)Q.push(`重置 ${U0($.fiveHour.resetsAt)}`);J.push(` · ${_Q($.fiveHour.durationMins,"主窗口")} ${Q.join(" · ")}`)}if($.weekly){let Q=[p1($.weekly.percent)];if($.weekly.resetsAt)Q.push(`重置 ${U0($.weekly.resetsAt)}`);J.push(` · ${_Q($.weekly.durationMins,"次窗口")} ${Q.join(" · ")}`)}return J.length===1?"**\uD83D\uDCCA Codex 额度** _无数据_":J.join(`
|
|
99
|
+
`)}function ZG($){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=[p1($.fiveHour.percent)];if($.fiveHour.resetsAt)Y.push(`重置 ${U0($.fiveHour.resetsAt)}`);Q.push(` · 5h 窗口 ${Y.join(" · ")}`)}if($.weekly){let Y=[p1($.weekly.percent)];if($.weekly.resetsAt)Y.push(`重置 ${U0($.weekly.resetsAt)}`);Q.push(` · 周额度 ${Y.join(" · ")}`)}if($.monthly){let Y=[p1($.monthly.percent)];if(typeof $.monthly.used==="number"&&typeof $.monthly.total==="number")Y.push(`${$.monthly.used}/${$.monthly.total}`);if($.monthly.resetsAt)Y.push(`重置 ${U0($.monthly.resetsAt)}`);Q.push(` · 月度工具 ${Y.join(" · ")}`)}return Q.length===1?"**\uD83D\uDCCA GLM 额度** _无数据_":Q.join(`
|
|
100
|
+
`)}function p1($){return typeof $==="number"&&Number.isFinite($)?`${Math.round($)}%`:"MISS"}function _Q($,Z){if(!$||$<=0)return Z;if($%1440===0)return`${$/1440}d`;if($%60===0)return`${$/60}h`;return`${$}m`}function QG($){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 YG($){if(!$)return["**负载** _n/a_","**内存** _n/a_",`**服务** ${i2} _n/a_`].join(`
|
|
101
|
+
`);let Z=[];if($.cpu){let{cores:J,load1:Q,load5:Y,load15:V}=$.cpu;Z.push(`**负载** ${Q.toFixed(2)} / ${Y.toFixed(2)} / ${V.toFixed(2)} (${J}核)`)}else Z.push("**负载** _n/a_");if($.mem)Z.push(`**内存** ${$.mem.percent}% (${qQ($.mem.usedBytes)}/${qQ($.mem.totalBytes)})`);else Z.push("**内存** _n/a_");if($.servicesError)Z.push(`**服务** ${i2} _${$.servicesError}_`);else if($.services.length===0)Z.push(`**服务** ${i2} _无_`);else{Z.push(`**服务** ${i2} (${$.services.length})`);for(let J of $.services){let Q=JG[J.active]??"·",Y=J.lastActiveAgoSec,V=J.stateAgoSec,X=[J.active];if(J.active==="active"){if(V!=null)X.push(`已运行 ${n2(V*1000)}`)}else if(J.active==="inactive"||J.active==="failed"){if(Y!=null)X.push(`上次活跃 ${n2(Y*1000)}前`);else X.push("从未启动");if(V!=null){let H=J.active==="failed"?"已挂":"已停";X.push(`${H} ${n2(V*1000)}`)}}else if(V!=null)X.push(`已 ${n2(V*1000)}`);Z.push(` · ${Q} \`${J.name}\` · ${X.join(" · ")}`)}}return Z.join(`
|
|
102
|
+
`)}function VG($){let Z=$.peers??[];if(Z.length===0)return"_无_";return Z.map((J)=>{let Q=eK[J.status]??"·",Y=$G[J.status]??J.status,V=J.uptimeMs!=null&&J.uptimeMs>0?` · ${n2(J.uptimeMs)}`:"",X=J.isCurrent?" · 当前":"";return` · ${Q} \`${J.name}\` · ${Y}${V}${X}`}).join(`
|
|
103
|
+
`)}function E4($,Z=O.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:VG($)}]}}function XG($){let Z=$.model?`${$.model}${$.effort?`/${$.effort}`:""}`:$.effort?`强度 ${$.effort}`:"未就绪";return[`**\uD83E\uDD16 当前模型${$.provider==="claude"?` (${d9($.provider)})`:""}** \`${Z}\``,...$.worktreeInstructionNotice?[$.worktreeInstructionNotice]:[]].join(`
|
|
104
|
+
`)}function T4($,Z=O.consoleCurrentModel){return{tag:"markdown",element_id:Z,content:XG($)}}function x4($,Z=O.consoleHost){let J=QG($);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:YG($)}]}}function HG($){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=[p1(Q.percent)];if(typeof Q.used==="number"&&typeof Q.total==="number")Y.push(`${Q.used}/${Q.total}`);if(Q.resetsAt)Y.push(`重置 ${U0(Q.resetsAt)}`);J.push(` · ${Q.label} ${Y.join(" · ")}`)}return J.length===1&&!$.planLabel?"**\uD83D\uDCCA 额度** _无数据_":J.join(`
|
|
105
|
+
`)}function r2($){let Z=$.unifiedUsage!==void 0?HG($.unifiedUsage):$.provider==="claude"?ZG($.glmUsage):BQ($.usage);return{tag:"markdown",element_id:O.consoleUsage,content:Z}}function LQ($,Z){return[T4($,Z),E4($),x4($.sysinfo),r2($)]}function m9($){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:LQ($)}}}function c9($){return l1($.sessionName,{tag:"collapsible_panel",element_id:O.modelPanel,header:{title:{tag:"plain_text",content:"选择账号"}},expanded:!0,elements:[{tag:"markdown",content:`当前: ${s0($.currentDisplay??"未选择")}
|
|
106
|
+
选账号进入模型选择。`},...$.providers.map((Z)=>WG(Z,$.panelId))]})}function WG($,Z){if(!$.enabled)return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`⚙️ **${Z0($.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:`**${Z0($.display)}**
|
|
107
|
+
${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 u9($){return l1($.sessionName,FQ($))}function p9($){return l1($.sessionName,S4($))}function C4($){return l1($.sessionName,UQ($),"green")}function l1($,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 FQ($){let Z=KG($.models,$.panelId);return{tag:"collapsible_panel",element_id:O.modelPanel,header:{title:{tag:"plain_text",content:"选择模型"}},expanded:!0,elements:[{tag:"markdown",content:[`当前: ${DQ($.currentModel,$.currentEffort)}`,"选模型进入 effort 选择。"].join(`
|
|
108
|
+
`)},...$.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 N4($,Z="cancelled"){return l1($,{tag:"collapsible_panel",element_id:O.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:Z==="stale"?"_此补录面板已失效 — 当前等待中的补录未受影响_":"_已取消补录 — 列表未改动_"}]},"grey")}function l9($,Z,J){return l1($,{tag:"collapsible_panel",element_id:O.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:[`**直接回复模型名补录到 ${Z}**(列表外的模型,端点会先校验真伪)`,"_裸词命令(hi/stop/model 等)不受影响_"].join(`
|
|
109
|
+
`)},{tag:"button",text:{tag:"plain_text",content:"取消"},type:"default",width:"default",behaviors:[{type:"callback",value:{kind:"model_panel_cancel",panel_id:J}}]}]},"blue")}function y4($,Z,J){return{tag:"collapsible_panel",element_id:O.modelPanel,header:{title:{tag:"plain_text",content:"补录模型"}},expanded:!0,elements:[{tag:"markdown",content:$?`✅ \`${Z}\` 已加入列表`:`❌ \`${Z}\` 未加入 — ${J}`}]}}function S4($){return{tag:"collapsible_panel",element_id:O.modelPanel,header:{title:{tag:"plain_text",content:"选择 effort"}},expanded:!0,elements:[{tag:"markdown",content:[`模型: ${_G($.model)}`,`当前: ${DQ($.currentModel,$.currentEffort)}`].join(`
|
|
110
|
+
`)},...$.model.efforts.length?$.model.efforts.map((Z)=>GG($.model,Z,$.panelId,$.currentModel,$.currentEffort)):[{tag:"markdown",content:"_该模型未返回可用 effort_"}]]}}function UQ($){return{tag:"collapsible_panel",element_id:O.modelPanel,header:{title:{tag:"plain_text",content:"选择已保存"}},expanded:!0,elements:[{tag:"markdown",content:["**已保存**",s0(PQ($.model,$.effort,$.provider)),Z0($.scope)].join(`
|
|
111
|
+
`)}]}}function zG($,Z){if($.enabled===!1)return[{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`⚙️ **${Z0($.displayName)}** · 未配置
|
|
112
|
+
${Z0($.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?`**${Z0($.displayName)}**`:`**${s0($.model)}**`,Q=[$.isDefault?`${d9($.provider)} 默认`:"",$.selected?"当前模型":""].filter(Boolean),Y=$.description?`
|
|
113
|
+
`+Z0(BG($.description,110)):"";return[{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:[J,s0($.model),Q.length?Q.join(" · "):""].filter(Boolean).join(`
|
|
114
|
+
`)+Y}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:$.selected?"primary":"default",behaviors:[{type:"callback",value:qG($,Z)}]}]}]}]}function KG($,Z){let J=[{title:"Codex",models:$.filter((V)=>(V.provider??"codex")==="codex")},{title:"Claude Code 后端",models:$.filter((V)=>V.provider==="claude")}].filter((V)=>V.models.length>0),Q=(V)=>V.flatMap((X)=>zG(X,Z));if(J.length<=1)return Q($);let Y=[];for(let V of J)Y.push({tag:"markdown",content:`**${V.title}**`}),Y.push(...Q(V.models));return Y}function GG($,Z,J,Q,Y){let V=Q===$.model&&Y===Z.effort,X=[Z.isDefault?"默认":"",V?"当前":""].filter(Boolean).join(" · ");return{tag:"column_set",columns:[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:[`**${Z0(Z.effort)}**`,X,Z.description?Z0(Z.description):""].filter(Boolean).join(`
|
|
115
|
+
`)}]},{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"选"},type:V?"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 qG($,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 _G($){return $.displayName&&$.displayName!==$.model?`${Z0($.displayName)} (${s0($.model)})`:s0($.model)}function DQ($,Z){return s0(PQ($,Z))}function PQ($,Z,J){let Q=J&&J!=="codex"?`${d9(J)} · `:"";if($&&Z)return`${Q}${$}/${Z}`;if($)return`${Q}${$}`;if(Z)return`${Q}${Z}`;return"未选择"}function d9($){return $==="claude"?"Claude":"Codex"}function BG($,Z){return $.length<=Z?$:$.slice(0,Z-1)+"…"}function Z0($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function s0($){return"`"+$.replace(/`/g,"\\`")+"`"}function i$($){let Z=[];if(Z.push($.suffix??"✅"),$.durationSec)Z.push(`⏱ ${$.durationSec}s`);if($.outputTokens!=null&&$.outputTokens>0)Z.push(`\uD83D\uDCF6 ${sK($.outputTokens)}`);return{config:{streaming_mode:!1,summary:{content:Z.join(" · ")}}}}var eK,$G,JG;var AQ=T(()=>{I9();y$();eK={idle:"\uD83D\uDFE2",working:"⚙️",awaiting_permission:"\uD83D\uDD10",starting:"\uD83D\uDE80",stopped:"⚪"},$G={idle:"闲",working:"工作中",awaiting_permission:"等审批",starting:"启动中",stopped:"未运行"};JG={active:"\uD83D\uDFE2",activating:"\uD83D\uDE80",reloading:"\uD83D\uDD04",inactive:"⚪",deactivating:"\uD83D\uDFE1",failed:"❌"}});function i9($){let Z=UG($);return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:"\uD83C\uDF3F wt"},template:LG($.notice)},body:{elements:[...$.notice?[FG($.notice)]:[],...Z?[{tag:"markdown",content:Z}]:[],...$.entries.flatMap(DG)]}}}function LG($){if($?.type==="error")return"red";if($?.type==="success")return"green";return"turquoise"}function FG($){let Z=$.type==="error"?"red":$.type==="success"?"green":"grey";return{tag:"markdown",content:$.content.split(`
|
|
115
116
|
`).map((J)=>`<font color='${Z}'>${J||" "}</font>`).join(`
|
|
116
|
-
`)}}function
|
|
117
|
+
`)}}function UG($){let Z=$.hiddenMergedUnmountedCount??0;if(!$.entries.length&&Z===0)return`_无 work/* 分支。发 ${k4("wt name")} 创建。_`;if(Z>0)return`${Z}个已归档分支`;return""}function DG($){let Z=$.error?"出错":$.mounted&&$.dirtyCount&&$.dirtyCount>0?`有未提交改动 ${$.dirtyCount}`:$.state==="merged"?"已合并":$.state==="stale"?"两边都有新改动":$.mounted?"进行中":"未挂载",J=$.duplicateChatCount>1?`群重复 ${$.duplicateChatCount} 个`:$.chatId?"群正常":"无群",Q=$.protected?" · 系统保留":"",Y=[{tag:"column",width:"weighted",weight:4,elements:[{tag:"markdown",content:`**${k4($.slug)}**
|
|
117
118
|
${Z} · ${J}${Q}
|
|
118
|
-
${
|
|
119
|
-
`)}]}}}function
|
|
119
|
+
${k4($.branch)}`}]}];if(!$.protected&&($.mounted||$.chatId))Y.push({tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:"删"},type:"danger",behaviors:[{type:"callback",value:{kind:"worktree_disband",slug:$.slug}}]}]});return[{tag:"column_set",columns:Y}]}function a2($){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,k4($.branch),...$.body?[$.body]:[]].join(`
|
|
120
|
+
`)}]}}}function k4($){return"`"+$.replace(/`/g,"\\`")+"`"}function o9($){let Z=$.mode==="fork",J=Z?"分叉":"回退",Q=Z?"temp_fork_select":"temp_back_select",Y=Z?`\uD83D\uDCA1 选择一条「用户输入」,将在临时群从它**之前**创建独立对话分支;选中的输入本身不包含。
|
|
120
121
|
分支与本群共享 cwd 和磁盘文件;只分叉对话历史,不复制或回滚文件,原会话不动。`:`⚠️ 选择一条「用户输入」,将停止本群当前 turn 和后台任务,并从它**之前**创建后续对话分支;选中的输入本身不包含。
|
|
121
|
-
只回退对话历史,不会回滚 cwd 中的文件。`,V=[];if($.notice)V.push({tag:"markdown",content:
|
|
122
|
-
${
|
|
123
|
-
新分支共享当前 cwd 和磁盘文件;只分叉对话历史,不复制或回滚文件。`});for(let J of $.entries)Z.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:5,elements:[{tag:"markdown",content:`**${
|
|
124
|
-
${
|
|
122
|
+
只回退对话历史,不会回滚 cwd 中的文件。`,V=[];if($.notice)V.push({tag:"markdown",content:PG($.notice)});if(!$.entries.length)V.push({tag:"markdown",content:"_当前会话还没有已完成的 turn,无法分叉/回退。_"});else{V.push({tag:"markdown",content:Y});for(let X of $.entries)V.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:5,elements:[{tag:"markdown",content:`**${s9(X.ts)}**
|
|
123
|
+
${N0(X.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:X.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:V}}}function r9($){let Z=[];if(!$.entries.length)Z.push({tag:"markdown",content:`_项目「${$.projectName}」没有可创建分支的历史会话。_`});else{Z.push({tag:"markdown",content:`\uD83D\uDCA1 选择一个历史会话,在**当前群**创建独立对话分支;源会话不动。
|
|
124
|
+
新分支共享当前 cwd 和磁盘文件;只分叉对话历史,不复制或回滚文件。`});for(let J of $.entries)Z.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:5,elements:[{tag:"markdown",content:`**${s9(J.ts)}**
|
|
125
|
+
${N0(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 a9($){let Z=$.entries.length===0?"(回退范围内未观察到 Write/Edit/FileChange 类文件变更)":$.entries.map((J)=>{let Q=J.body.length>800?J.body.slice(0,800)+`
|
|
125
126
|
…(截断)`:J.body;return`${J.path} (${J.tool})
|
|
126
127
|
${Q}`}).join(`
|
|
127
128
|
|
|
128
|
-
`);return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83D\uDCCB 观察到的文件变更 · ${$.projectName}`},template:"grey"},body:{elements:[{tag:"markdown",content:"以下是回退范围内观察到的文件变更,可复制、编辑后交给新分支参考。bk 只回退对话历史,不会回滚磁盘文件;Shell/MCP 等工具造成的副作用可能未被记录。"},{tag:"markdown",content:"```\n"+Z+"\n```"}]}}}function
|
|
129
|
+
`);return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:`\uD83D\uDCCB 观察到的文件变更 · ${$.projectName}`},template:"grey"},body:{elements:[{tag:"markdown",content:"以下是回退范围内观察到的文件变更,可复制、编辑后交给新分支参考。bk 只回退对话历史,不会回滚磁盘文件;Shell/MCP 等工具造成的副作用可能未被记录。"},{tag:"markdown",content:"```\n"+Z+"\n```"}]}}}function d1($){return{schema:"2.0",config:{update_multi:!0},header:{title:{tag:"plain_text",content:$.title},template:$.ok?"green":"red"},body:{elements:[{tag:"markdown",content:`${$.ok?"✅":"❌"} ${n9($.message)}`}]}}}function t9($){let Z=$.provider==="codex"?"Codex":"Claude",J=$.bindingState==="changed"?"已接入":$.bindingState==="prepared"?"已准备":$.bindingState==="unchanged"?"未切换":"状态待确认",Q=$.bindingState==="changed"?"✅":$.bindingState==="prepared"?"⏳":$.bindingState==="unchanged"?"❌":"⚠️",Y=$.selectedPreview.slice(0,80)||"(无摘要)",V=$.sourceStatus?` · 状态 ${N0($.sourceStatus)}`:"",X=$.bindingState==="changed"?["**当前群**",`新会话 ${N0(w4($.newSessionId))}`,"","源会话未修改;新分支与当前群共享 cwd 和磁盘文件。"].join(`
|
|
129
130
|
`):$.bindingState==="prepared"?["**当前群**","Claude 独立分支已准备;发送下一条消息时生成并接入新会话。","","源会话未修改;新分支与当前群共享 cwd 和磁盘文件。"].join(`
|
|
130
|
-
`):$.bindingState==="unchanged"?[`${
|
|
131
|
-
`):[`${
|
|
132
|
-
`);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}**`,`**${
|
|
133
|
-
`)},{tag:"markdown",content:X}]}}}function
|
|
131
|
+
`):$.bindingState==="unchanged"?[`${n9($.message)}`,"",`本群原绑定 ${N0(w4($.previousSessionId))};源会话未修改。`].join(`
|
|
132
|
+
`):[`${n9($.message)}`,"",`后端返回会话 ${N0(w4($.newSessionId))};当前绑定无法确认。`,"请发送 hi 或 rs 检查当前状态,不要把本卡视为成功回执。"].join(`
|
|
133
|
+
`);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}**`,`**${s9($.selectedTs)}**${V}`,N0(Y),`源会话 ${N0(w4($.sourceSessionId))}`].join(`
|
|
134
|
+
`)},{tag:"markdown",content:X}]}}}function s9($){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 N0($){return"`"+MQ($.replace(/`/g,"\\`").replace(/\n/g," "))+"`"}function w4($){let Z=$?.trim()??"";if(!Z)return"MISS";return Z.length>13?`${Z.slice(0,8)}…${Z.slice(-4)}`:Z}function n9($){return MQ($).replace(/\\/g,"\\\\").replace(/([`*_{}\[\]()#+\-.!|>~])/g,"\\$1")}function MQ($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function PG($){let Z=$.type==="error"?"red":"grey";return $.content.split(`
|
|
134
135
|
`).map((J)=>`<font color='${Z}'>${J||" "}</font>`).join(`
|
|
135
|
-
`)}function
|
|
136
|
+
`)}function OQ($,Z){if(!Z||typeof Z!=="object")return"";if(typeof Z.content==="string")return Z.content;if(typeof Z.new_string==="string")return Z.new_string;if(typeof Z.new_source==="string")return Z.new_source;if(Array.isArray(Z.edits))return Z.edits.map((J)=>typeof J?.new_string==="string"?J.new_string:"").filter(Boolean).join(`
|
|
136
137
|
---
|
|
137
|
-
`);return""}function
|
|
138
|
-
`)}}function
|
|
139
|
-
`),
|
|
140
|
-
${
|
|
141
|
-
`)}function
|
|
138
|
+
`);return""}function e9($,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:OQ($,Z)}]}function Z5($){return{schema:"2.0",config:{update_multi:!0,streaming_mode:!0,summary:{content:`${$.stats.status} · agy`}},body:{elements:[RQ($.prompt),t2($.stats),f4({status:"⏳ 等待 agy 返回...",stdout:"",stderr:""}),EQ(),h4({before:$.beforeGit})]}}}function RQ($){return{tag:"collapsible_panel",element_id:O.agyPrompt,header:{title:{tag:"plain_text",content:"\uD83D\uDCE5 agy收到"}},expanded:!1,elements:[{tag:"markdown",content:y0($).trim()||"_空_"}]}}function t2($){return{tag:"markdown",element_id:O.agyStats,content:[RG($.status),`${$.elapsedSec}s`,`CPU ${EG($.cpuPercent)}`,`MEM ${TG($.memBytes)}`].join(" · ")}}function f4($){let Z=J0($.stdout).trim(),J=J0($.stderr).trim(),Q=[`**${y0($.status)}**`],Y=J0($.notice??"").trim();if(Y)Q.push(""),Q.push(y0(Y));if(Z){let V=$5(Z,AG);if(Q.push(""),Q.push(y0(V.text)),V.didTruncate||$.cardTruncated)Q.push(""),Q.push("_输出已截断,完整内容未全部写入卡片。_")}if(J){let V=$5(J,MG);if(Q.push(""),Q.push("---"),Q.push("**stderr**"),Q.push(b4(y0(V.text))),V.didTruncate)Q.push("_stderr 已截断。_")}if(!Z&&!J)Q.push(""),Q.push("_暂无输出_");return{tag:"markdown",element_id:O.agyResult,content:Q.join(`
|
|
139
|
+
`)}}function EQ(){return{tag:"markdown",element_id:O.agyForward,content:" "}}function J5($,Z="Codex"){return{tag:"column_set",element_id:O.agyForward,columns:[{tag:"column",width:"weighted",weight:1,elements:[{tag:"button",text:{tag:"plain_text",content:`转 ${Z}`},type:"primary",behaviors:[{type:"callback",value:{kind:"agy_forward_codex",result_id:$}}]}]}]}}function h4($){let Z=v4($.before),J=$.after?v4($.after):null,Q=$.after?$.after.ok?$.after.diffShortStat||(J?"有未提交变更":"无未提交变更"):"统计失败":$.before.ok?Z?"执行前已有变更":"执行前干净":"执行前统计失败";return{tag:"collapsible_panel",element_id:O.agyRepo,header:{title:{tag:"plain_text",content:`\uD83D\uDCE6 仓库变更 · ${xG(Q,48)}`}},expanded:!1,elements:[{tag:"markdown",content:jG($.before,$.after)}]}}function jG($,Z){let J=[];if(J.push("**执行前**"),J.push(jQ($)),Z){if(J.push(""),J.push("**执行后**"),J.push(jQ(Z)),v4($))J.push(""),J.push("⚠️ 执行前已有未提交变更,以上结束状态不能全部归因于本次 agy 执行。")}return $5(J.join(`
|
|
140
|
+
`),OG).text}function jQ($){if(!$.ok)return`❌ Git 统计失败
|
|
141
|
+
${b4(y0($.error??"unknown error"))}`;let Z=[];if(Z.push(v4($)?"dirty":"clean"),$.diffShortStat)Z.push(`diff: ${CG($.diffShortStat)}`);if($.statusShort)Z.push(""),Z.push(b4(y0($.statusShort)));if($.diffNameOnly)Z.push(""),Z.push("files"),Z.push(b4(y0($.diffNameOnly)));return Z.join(`
|
|
142
|
+
`)}function v4($){return!!($.statusShort.trim()||$.diffShortStat.trim()||$.diffNameOnly.trim())}function RG($){if(/完成/.test($))return"✅ 完成";if(/运行中|等待|正在停止/.test($))return"⏳ 执行中";return"❌ 出错"}function EG($){return typeof $==="number"&&Number.isFinite($)?`${$.toFixed(1)}%`:"--"}function TG($){if(typeof $!=="number"||!Number.isFinite($))return"--";if($<1024)return`${$}B`;let Z=["KB","MB","GB","TB"],J=$/1024;for(let Q of Z){if(J<1024||Q===Z[Z.length-1])return`${J.toFixed(J>=10?0:1)}${Q}`;J/=1024}return`${$}B`}function xG($,Z){let J=$.replace(/\s+/g," ").trim();if(!J)return"空";return J.length<=Z?J:J.slice(0,Z-1)+"…"}function $5($,Z){if($.length<=Z)return{text:$,didTruncate:!1};return{text:$.slice(0,Math.max(0,Z-1))+"…",didTruncate:!0}}function y0($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function CG($){return"`"+$.replace(/`/g,"\\`")+"`"}function b4($){return"```\n"+$.replace(/```/g,"`\\`\\`")+"\n```"}function J0($){return $.replace(/\r\n/g,`
|
|
142
143
|
`).replace(/\x1B\][\s\S]*?(?:\x07|\x1B\\)/g,"").replace(/\x1B\[[0-?]*[ -/]*[@-~]/g,"").replace(/\x1B[=>]/g,"").split(`
|
|
143
144
|
`).map((Z)=>{let J=Z.split("\r");return J[J.length-1]??""}).join(`
|
|
144
|
-
`).replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g,"")}var
|
|
145
|
-
`);if(Z.push("","已启用"),Z.push(`GUID:${
|
|
146
|
-
`)}function
|
|
147
|
-
`).map((J)=>`<font color='${Z}'>${
|
|
148
|
-
`)}}function
|
|
149
|
-
`)}function
|
|
150
|
-
`))>=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=
|
|
151
|
-
`,(
|
|
145
|
+
`).replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g,"")}var AG=8000,MG=2000,OG=5000;var TQ=T(()=>{y$()});import{existsSync as NG,readFileSync as yG}from"node:fs";function Y5($){return`${$}[lodestar]`}function E$($){let Z=f$.get($);return Z?e0(Z):null}function e2(){return[...f$.values()].map(e0)}function i1($,Z){let J=f$.get($);if(!J)throw Error(`tasklist is not enabled for ${$}`);let Q=e0(J);return Z(Q),vQ($,Q),wQ($,Q),e0(Q)}async function g4($,Z){let J=I4.get($)??Promise.resolve(),Q,Y=new Promise((X)=>{Q=X}),V=J.catch(()=>{}).then(()=>Y);I4.set($,V),await J.catch(()=>{});try{return await Z()}finally{if(Q(),I4.get($)===V)I4.delete($)}}function xQ($,Z=new Date().toISOString()){$.deleting??={requestedAt:Z,attempts:0}}function kG($){if($&&typeof $==="object"&&$.code===1470404)return!0;let Z=$ instanceof Error?$.message:String($);return/\bcode=1470404\b/.test(Z)}async function wG($,Z=v6){try{return await Z($),"deleted"}catch(J){if(kG(J))return"already_deleted";throw J}}function bG($,Z,J){if($.guid!==Z)throw Error(`tasklist binding changed while ensuring sections: current=${$.guid} expected=${Z}`);if($.deleting)throw Error(`tasklist deletion is pending for ${$.projectName}`);$.sections={...J}}async function CQ($,Z){return await g4($,()=>vG($,Z))}async function vG($,Z){let J=E$($);if(J?.deleting)throw Error(`tasklist deletion is pending for ${$}`);if(J)return Q5($);let Q=Y5($);if(Q.length>100)throw Error(`tasklist name is too long (${Q.length}/100): ${Q}`);let Y=await w6(Z),V=await b6(Q,Y),X={guid:V.guid,name:V.name,url:V.url,projectName:$,ownerOpenId:Y,createdAt:V.createdAt,sections:{},tasks:{},processes:{},worker:{}};return wQ($,X),await Q5($),E$($)}async function NQ($){return await g4($,()=>Q5($))}async function Q5($){let Z=E$($);if(!Z)throw Error(`tasklist is not enabled for ${$}`);if(Z.deleting)throw Error(`tasklist deletion is pending for ${$}`);let J=await x2(Z.guid);J=await hG(J);let Q=new Map(J.map((X)=>[X.name,X.guid])),Y={...Z.sections??{}};Y.design=await fG(Z.guid,Y.design);let V;for(let X of SG){let H=Q.get(X.name)??await gG(Z.guid,X.name,V);Y[X.key]=H,V=H}return i1($,(X)=>{bG(X,Z.guid,Y)})}async function fG($,Z){let J=$8("design"),Q=null;if(Z){let Y=await d8(Z);if(Y.tasklistGuid&&Y.tasklistGuid!==$)throw Error(`stored design section ${Z} belongs to tasklist ${Y.tasklistGuid}, expected ${$}`);if(Y.isDefault)Q=Y;else K(`tasklist: ignore non-default stored design section ${Z}`)}if(!Q){let Y=await m6($);if(Q=await d8(Y),Q.tasklistGuid&&Q.tasklistGuid!==$)throw Error(`discovered design section ${Y} belongs to tasklist ${Q.tasklistGuid}, expected ${$}`);if(!Q.isDefault)throw Error(`discovered design section is not default: ${Y}`)}if(Q.name!==J){if(Q=await h6(Q.guid,J),!Q.isDefault)throw Error(`renamed design section is not default: ${Q.guid}`)}return Q.guid}async function hG($){let Z=[],J=$8("design");for(let Q of $){if(Q.isDefault||Q.name!==J){Z.push(Q);continue}let Y=await K0(Q.guid);if(Y.length>0){K(`tasklist: keep non-empty legacy design section ${Q.guid} tasks=${Y.length}`),Z.push(Q);continue}await I6(Q.guid),K(`tasklist: deleted empty legacy design section ${Q.guid}`)}return Z}async function yQ($,Z){return await g4($,()=>IG($,Z))}async function IG($,Z){let J=E$($);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)i1($,(Q)=>xQ(Q));return await SQ($,Z)}async function SQ($,Z){let J=i1($,(Q)=>{if(Q.guid!==Z)throw Error(`tasklist binding changed during deletion: current=${Q.guid} expected=${Z}`);xQ(Q),Q.deleting.attempts++,Q.deleting.lastAttemptAt=new Date().toISOString(),Q.deleting.lastError=void 0});try{if(await wG(Z)==="already_deleted")K(`tasklist: ${$} remote list ${Z} is already deleted (code=1470404); finishing tombstone`);let Y=f$.get($);if(!Y||Y.guid!==Z||!Y.deleting)throw Error(`tasklist deletion state changed before local commit: ${$}`);let V=new Map(f$);return V.delete($),bQ(V),f$.delete($),e0(J)}catch(Q){let Y=Q instanceof Error?Q.message:String(Q);try{i1($,(V)=>{if(V.guid===Z&&V.deleting)V.deleting.lastError=Y})}catch(V){K(`tasklist: failed to persist delete error for ${$}: ${V}`)}throw Q}}async function kQ(){let $=[...f$.entries()].filter(([,J])=>!!J.deleting).map(([J,Q])=>({projectName:J,guid:Q.guid})),Z=[];for(let J of $)try{await g4(J.projectName,()=>SQ(J.projectName,J.guid)),K(`tasklist: reconciled pending deletion for ${J.projectName}`)}catch(Q){Z.push(`${J.projectName}: ${Q instanceof Error?Q.message:String(Q)}`)}if(Z.length>0)throw Error(`tasklist deletion reconcile failed: ${Z.join("; ")}`)}function h$($,Z){$.tasks??={};let J=$.tasks[Z]??{guid:Z};return $.tasks[Z]=J,J}function $8($){return s2.find((Z)=>Z.key===$)?.name??$}function gG($,Z,J){return f6({tasklistGuid:$,name:Z,insertAfter:J})}function mG(){if(!NG(A8))return;try{let $=JSON.parse(yG(A8,"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)continue;if(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,sections:cG(Q.sections),tasks:uG(Q.tasks),processes:pG(Q.processes),worker:lG(Q.worker),deleting:dG(Q.deleting)};vQ(Z,Y),f$.set(Z,Y)}K(`tasklist: loaded ${f$.size} project bindings`)}catch($){K(`tasklist: load map failed: ${$}`)}}function wQ($,Z){let J=new Map(f$);J.set($,e0(Z)),bQ(J),f$.set($,Z)}function bQ($=f$){let Z={};for(let[J,Q]of $)Z[J]=e0(Q);O$(A8,Z)}function vQ($,Z){Z.projectName=$,Z.sections??={},Z.tasks??={},Z.processes??={},Z.worker??={}}function e0($){return JSON.parse(JSON.stringify($))}function cG($){let Z={};if(!$||typeof $!=="object")return Z;let J=$;for(let Q of s2){let Y=J[Q.key];if(typeof Y==="string"&&Y)Z[Q.key]=Y}return Z}function uG($){if(!$||typeof $!=="object")return{};let Z={};for(let[J,Q]of Object.entries($)){if(!Q||typeof Q!=="object")continue;let Y=Q;Z[J]={...Y,guid:J}}return Z}function pG($){if(!$||typeof $!=="object")return{};let Z={};for(let[J,Q]of Object.entries($)){if(!Q||typeof Q!=="object")continue;let Y=Q;if(typeof Y.projectName!=="string")continue;if(typeof Y.tasklistGuid!=="string")continue;if(!Array.isArray(Y.command))continue;if(typeof Y.cwd!=="string")continue;Z[J]={runId:J,projectName:Y.projectName,tasklistGuid:Y.tasklistGuid,taskGuid:typeof Y.taskGuid==="string"?Y.taskGuid:void 0,kind:Y.kind??"agy-plan",pid:typeof Y.pid==="number"?Y.pid:void 0,pgid:typeof Y.pgid==="number"?Y.pgid:void 0,command:Y.command.map(String),cwd:Y.cwd,status:Y.status??"failed",startedAt:typeof Y.startedAt==="string"?Y.startedAt:new Date().toISOString(),finishedAt:typeof Y.finishedAt==="string"?Y.finishedAt:void 0,exitCode:typeof Y.exitCode==="number"||Y.exitCode===null?Y.exitCode:void 0,signal:typeof Y.signal==="string"||Y.signal===null?Y.signal:void 0,stdoutTail:typeof Y.stdoutTail==="string"?Y.stdoutTail:void 0,stderrTail:typeof Y.stderrTail==="string"?Y.stderrTail:void 0,error:typeof Y.error==="string"?Y.error:void 0,treeCleanupWarning:typeof Y.treeCleanupWarning==="string"?Y.treeCleanupWarning:void 0}}return Z}function lG($){if(!$||typeof $!=="object")return{};let Z=$;return{lastScanAt:typeof Z.lastScanAt==="string"?Z.lastScanAt:void 0,lastScanError:typeof Z.lastScanError==="string"?Z.lastScanError:void 0,runningTaskGuid:typeof Z.runningTaskGuid==="string"?Z.runningTaskGuid:void 0,lastSectionEnsureAt:typeof Z.lastSectionEnsureAt==="string"?Z.lastSectionEnsureAt:void 0}}function dG($){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}}var s2,SG,f$,I4;var m4=T(()=>{m$();n();v();f0();s2=[{key:"design",name:"设计中"},{key:"aiTodo",name:"[AI]待执行"},{key:"aiDoing",name:"[AI]执行中"},{key:"aiReview",name:"[AI]待审核"},{key:"done",name:"已完成"}],SG=s2.filter(($)=>$.key!=="design"),f$=new Map,I4=new Map;mG()});function X5($){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 · ${hQ}`},template:J},body:{elements:[...$.notice?[rG($.notice)]:[],{tag:"markdown",element_id:O.tasklistPanel,content:iG($)},oG($)]}}}function iG($){let Z=[`项目:${V5($.projectName)}`,`清单:${V5($.tasklistName)}`,`阶段:${hQ}`];if(!$.binding)return Z.push("","未启用"),Z.join(`
|
|
146
|
+
`);if(Z.push("","已启用"),Z.push(`GUID:${V5($.binding.guid)}`),Z.push(`分组:${nG($.binding)}`),$.binding.url)Z.push(`链接:${$.binding.url}`);if($.confirmDelete)Z.push(""),Z.push("<font color='red'>确认后会删除该清单以及清单内所有任务。</font>");return Z.join(`
|
|
147
|
+
`)}function nG($){let Z=$.sections??{};return s2.map((J)=>J.key==="design"?`${J.name}默认`:`${J.name}${Z[J.key]?"✓":"MISS"}`).join(" · ")}function oG($){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 rG($){let Z=$.type==="error"?"red":$.type==="success"?"green":"grey";return{tag:"markdown",content:$.content.split(`
|
|
148
|
+
`).map((J)=>`<font color='${Z}'>${aG(J)||" "}</font>`).join(`
|
|
149
|
+
`)}}function V5($){return"`"+$.replace(/`/g,"\\`")+"`"}function aG($){return $.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}var hQ="预览版";var IQ=T(()=>{y$();m4()});function Z1($){return tG.has($)?$:null}function c4($){if(!$)return null;try{let Z=JSON.parse($);return Z&&typeof Z==="object"?Z:null}catch{return null}}function n1($){return String($?.taskId??$?.id??$?.task_id??"").trim()}function $1($){return String($?.subject??$?.content??"").trim()}function H5($){let Z=$?.status;return Z==="pending"||Z==="in_progress"||Z==="completed"||Z==="deleted"?Z:void 0}function cQ($){return`subj:${$}`}function gQ($){let Z=$.match(/#\s*(\d+)/);return Z?Z[1]:""}function Zq($){let Z=$1($);if(!Z)return null;return{id:n1($)||cQ(Z),subject:Z,description:typeof $?.description==="string"?$.description:void 0,activeForm:typeof $?.activeForm==="string"?$.activeForm:void 0,status:H5($)??"pending"}}function W5($,Z,J,Q){if(Z==="TaskList"){let Y=c4(Q),V=Array.isArray(Y?.tasks)?Y.tasks:Array.isArray(Y)?Y:null;if(V===null)return $;let X=[];for(let H of V){let W=Zq(H);if(W)X.push(W)}return X}if(Z==="TaskCreate"){let Y=Array.isArray(J?.tasks)?J.tasks:null;if(Y){let z=c4(Q),G=Array.isArray(z?.tasks)?z.tasks:Array.isArray(z)?z:null,q=$;return Y.forEach((B,L)=>{let F=$1(B);if(!F)return;let U=G?.[L],R=U&&n1(U)||gQ(Q??"");q=mQ(q,R,F,B)}),q}let V=c4(Q),X=V?.task??V,H=n1(X)||gQ(Q??""),W=$1(X)||$1(J);if(!W)return $;return mQ($,H,W,J)}if(Z==="TaskUpdate"){let Y=n1(J);if(!Y)return $;let V=H5(J);if(V==="deleted")return $.filter((H)=>H.id!==Y);let X=$1(J);if($.some((H)=>H.id===Y))return $.map((H)=>H.id===Y?{...H,...V?{status:V}:{},...X?{subject:X}:{},...typeof J?.activeForm==="string"?{activeForm:J.activeForm}:{}}:H);return $}if(Z==="TaskGet"){let Y=c4(Q),V=Y?.task??Y,X=n1(V)||n1(J);if(!X)return $;let H=$.find((G)=>G.id===X),W=$1(V)||H?.subject||$1(J);if(!W)return $;let z={id:X,subject:W,description:typeof V?.description==="string"?V.description:H?.description,activeForm:typeof V?.activeForm==="string"?V.activeForm:H?.activeForm,status:H5(V)??H?.status??"pending"};return H?$.map((G)=>G.id===X?z:G):[...$,z]}return $}function mQ($,Z,J,Q){let Y=Z||cQ(J),V={...typeof Q?.activeForm==="string"&&Q.activeForm?{activeForm:Q.activeForm}:{},...typeof Q?.description==="string"&&Q.description?{description:Q.description}:{}};if($.some((X)=>X.id===Y))return $.map((X)=>X.id===Y?{...X,id:Y,subject:J,...V}:X);return[...$,{id:Y,subject:J,status:"pending",...V}]}function z5($){let Z=$.filter((V)=>V.status!=="deleted");if(Z.length===0)return"空";let J=new Map;for(let V of Z){let X=eG[V.status];J.set(X,(J.get(X)??0)+1)}let Y=["进行中","待办","完成"].map((V)=>J.has(V)?`${V} ${J.get(V)}`:"").filter(Boolean).join(" · ");return`${Z.length} 项${Y?` · ${Y}`:""}`}function uQ($,Z){let J=$.filter((X)=>X.status!=="deleted"),Q=[`**待办**: ${J.length} 项`],Y=(X)=>{let H=parseInt(X,10);return Number.isNaN(H)?Number.MAX_SAFE_INTEGER:H},V=[...J].sort((X,H)=>{let W=Y(X.id)-Y(H.id);return W!==0?W:X.id.localeCompare(H.id)});for(let X of V.slice(0,12)){let H=$q[X.status],W=X.status==="in_progress"&&X.activeForm?X.activeForm:X.subject;Q.push(`- ${H} ${W||"(空)"}`)}if(V.length>12)Q.push(`- 还有 ${V.length-12} 项未显示`);if(Z)Q.push(""),Q.push(Z);return Q.join(`
|
|
150
|
+
`)}function S0($,Z,J,Q){let Y=sG[J.name],V=z5(Z),X=`${J.status} \uD83D\uDD27 ${Y}: ${V}`;return{tag:"collapsible_panel",element_id:O.tool($),header:{title:{tag:"plain_text",content:X}},expanded:!1,elements:[{tag:"markdown",content:uQ(Z,Q)}]}}function J1($){return{tag:"collapsible_panel",element_id:O.taskBoardLive,header:{title:{tag:"plain_text",content:`\uD83D\uDCCB 任务总览 · ${z5($)}`}},expanded:!0,elements:[{tag:"markdown",content:uQ($)}]}}var tG,sG,eG,$q;var pQ=T(()=>{y$();tG=new Set(["TaskCreate","TaskUpdate","TaskList","TaskGet"]);sG={TaskCreate:"创建任务",TaskUpdate:"更新任务",TaskList:"任务列表",TaskGet:"查看任务"},eG={pending:"待办",in_progress:"进行中",completed:"完成",deleted:"已删"},$q={pending:"⬜",in_progress:"\uD83D\uDD04",completed:"✅",deleted:"\uD83D\uDDD1️"}});var n$=T(()=>{y$();VQ();S9();AQ();TQ();IQ();pQ();D6()});import{spawn as Jq}from"node:child_process";class l4{proc;buf="";nextId=1;alive=!0;exitPromise;resolveExit;pending=new Map;constructor(){this.proc=Jq(H0(),["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)K(`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(`
|
|
151
|
+
`))>=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=Z8){let Q=this.nextId++;return new Promise((Y,V)=>{if(!this.alive){V(Error(`codex app-server is not alive; cannot request ${$}`));return}let X=setTimeout(()=>{if(!this.pending.delete(Q))return;V(Error(`codex app-server ${$} timed out after ${J}ms`))},J);this.pending.set(Q,{resolve:Y,reject:V,method:$,timer:X});try{this.proc.stdin.write(JSON.stringify({id:Q,method:$,params:Z})+`
|
|
152
|
+
`,(H)=>{if(!H)return;let W=this.pending.get(Q);if(!W)return;this.pending.delete(Q),clearTimeout(W.timer),W.reject(Error(`codex app-server write failed for ${$}: ${H.message}`))})}catch(H){this.pending.delete(Q),clearTimeout(X),V(H instanceof Error?H:Error(String(H)))}})}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 u4($,Z){return new Promise((J,Q)=>{let Y=setTimeout(()=>Q(Error(`timeout after ${Z}ms`)),Z);$.then((V)=>{clearTimeout(Y),J(V)},(V)=>{clearTimeout(Y),Q(V)})})}function Qq($){return typeof $==="number"&&isFinite($)?Math.max(0,Math.min(100,$)):null}function p4($){if(!$)return null;return{percent:Qq($.usedPercent),resetsAt:typeof $.resetsAt==="number"?new Date($.resetsAt*1000):null,durationMins:typeof $.windowDurationMins==="number"?$.windowDurationMins:null}}function Yq($){let Z=p4($?.primary),J=p4($?.secondary),Q=(V)=>V?.durationMins!=null&&V.durationMins>0&&V.durationMins<=720,Y=(V)=>V?.durationMins!=null&&V.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 Vq($){let Z=$?.rateLimitsByLimitId,J=Z&&typeof Z==="object"?Object.entries(Z):$?.rateLimits?[[$.rateLimits.limitId??"codex",$.rateLimits]]:[],Q=[];for(let[Y,V]of J){let{fiveHour:X,weekly:H}=Yq(V);if(!X&&!H)continue;Q.push({limitId:Y,limitName:V?.limitName??null,fiveHour:X,weekly:H})}return{buckets:Q,defaultLimitId:$?.rateLimits?.limitId??void 0}}function Xq($){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 dQ($){let Z=Xq($),J=Q1?.state==="ok"?Q1.buckets??[]:[],Q=J.filter((Y)=>lQ(Y.fiveHour,p4($?.primary))&&lQ(Y.weekly,p4($?.secondary)));if(J.length>0&&Q.length===0)K(`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)K(`usage: rate-limit notification labeled limitId=${$.limitId} but content matches bucket ${Q[0].limitId} (known codex parser fallback relabels; ignoring notification payload)`)}function lQ($,Z){if(!$||!Z)return!$&&!Z;return $.percent===Z.percent&&$.durationMins===Z.durationMins&&$.resetsAt?.getTime()===Z.resetsAt?.getTime()}async function Hq(){let $=new l4;try{await u4($.request("initialize",{clientInfo:{name:"lodestar-usage",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}),Z8);let J=(await u4($.request("account/read",{}),Z8))?.account;if(!J)return{state:"no_credentials"};if(J.type!=="chatgpt")return{state:"auth_failed"};let Q=await u4($.request("account/rateLimits/read",{}),Z8);return iQ(Q,J.planType)}catch(Z){return K(`usage: codex app-server usage failed: ${Z?.message??Z}`),{state:"network",reason:Z?.message??String(Z)}}finally{await $.close()}}function iQ($,Z){let{buckets:J,defaultLimitId:Q}=Vq($),Y=J.find((V)=>V.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 nQ(){return Q1}async function d4(){if(o1)return o1;return o1=Hq().then(($)=>{if(o1=null,$.state==="network")return Q1??$;return Q1=$,$}).catch(($)=>{return K(`usage: fetchUsage threw: ${$}`),o1=null,Q1??{state:"network",reason:String($)}}),o1}function oQ($){return K5??=u4($("account/rateLimits/read",{}),Z8).then((Z)=>{let J=iQ(Z);if(J.state==="ok")Q1=J;else K(`usage: refresh from connection: ${J.state==="network"?J.reason:J.state}`);return J}).catch((Z)=>{return K(`usage: refresh from connection failed: ${Z?.message??Z}`),null}).finally(()=>{K5=null}),K5}var Z8=1e4,Q1=null,o1=null,K5=null;var i4=T(()=>{E1();v()});import{readFileSync as Wq}from"node:fs";import{homedir as zq}from"node:os";import{join as sQ}from"node:path";function Kq(){return process.env.CLAUDE_CONFIG_DIR||sQ(zq(),".claude")}function q5(){try{let $=Wq(sQ(Kq(),"settings.json"),"utf8"),Z=JSON.parse($)?.env;return Z&&typeof Z==="object"?Z:{}}catch($){return K(`glm-usage: read settings.json env failed: ${$}`),{}}}function n4($){try{let Z=new URL($).hostname.toLowerCase();return Z==="open.bigmodel.cn"||Z==="dev.bigmodel.cn"||Z==="api.z.ai"}catch{return!1}}function Gq($){try{let Z=new URL($);return`${Z.protocol}//${Z.host}`}catch{return null}}function qq($){let Z=Gq($);return Z&&n4($)?Z:null}function aQ($){return typeof $==="number"&&isFinite($)?Math.max(0,Math.min(100,$)):null}function tQ($){return typeof $==="number"&&isFinite($)&&$>0?new Date($):null}function _q($){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),V=Z.find((G)=>G?.type==="TIME_LIMIT"),X=(G)=>G?{percent:aQ(G.percentage),resetsAt:tQ(G.nextResetTime)}:null,H=X(Q),W=X(Y),z=V?{percent:aQ(V.percentage),resetsAt:tQ(V.nextResetTime),...typeof V.currentValue==="number"?{used:V.currentValue}:{},...typeof V.usage==="number"?{total:V.usage}:{}}:null;return{state:"ok",level:typeof $?.level==="string"&&$.level?$.level:void 0,fiveHour:H,weekly:W,monthly:z,fetchedAt:Date.now()}}async function _5($,Z){let J=$&&Z?{ANTHROPIC_BASE_URL:$,ANTHROPIC_AUTH_TOKEN:Z}:q5(),Q=J.ANTHROPIC_AUTH_TOKEN,Y=J.ANTHROPIC_BASE_URL||"";if(!Q)return{state:"no_credentials"};let V=qq(Y);if(!V)return{state:"not_glm",baseUrl:Y||void 0};let X=`${V}/api/monitor/usage/quota/limit`,H=new AbortController,W=setTimeout(()=>H.abort(),rQ);try{let z=await fetch(X,{headers:{Authorization:Q,"Content-Type":"application/json","Accept-Language":"en-US,en"},signal:H.signal});if(z.status===429)return{state:"rate_limited"};if(!z.ok)return{state:"network",reason:`HTTP ${z.status}`};let G=await z.json();if(G?.success===!1||typeof G?.code==="number"&&G.code!==200)return{state:"network",reason:G?.msg?String(G.msg):`code ${G?.code}`};let q=G?.data??G;return _q(q)}catch(z){let G=z?.name==="AbortError"?`timeout ${rQ}ms`:z?.message??String(z);return K(`glm-usage: quota/limit fetch failed: ${G}`),{state:"network",reason:G}}finally{clearTimeout(W)}}async function B5(){if(r1)return r1;return r1=_5().then(($)=>{if(r1=null,$.state==="network")return G5??$;return G5=$,$}).catch(($)=>{return K(`glm-usage: fetchGlmUsage threw: ${$}`),r1=null,G5??{state:"network",reason:String($)}}),r1}var rQ=1e4,G5=null,r1=null;var o4=T(()=>{v()});function eQ($){let Z=[];for(let J of $.matchAll(Bq)){let Q=J[1]?.trim();if(Q)Z.push(Q)}return Z}function r4($,Z=process.platform){if(Z!=="win32")return $;let J=Lq.exec($);if(!J)return $;return`${J[1].toUpperCase()}:\\`+$.slice(J[0].length).replace(/\//g,"\\")}var Bq,Lq;var L5=T(()=>{Bq=/\[\[send:[ \t]*([^\n]*?)[ \t]*\]\]/g;Lq=/^\/([a-zA-Z])\//});function JY($){if($Y.test($))return{marker:"start",body:$.replace($Y,"")};if(ZY.test($))return{marker:"end",body:$.replace(ZY,"")};return{marker:"none",body:$}}var $Y,ZY;var QY=T(()=>{$Y=/^>{3,}[ \t]?/,ZY=/^<{3,}[ \t]?/});async function YY($,Z,J,Q,Y){let{marker:V,body:X}=JY(Z);if(V==="start"){if($.multiMsgBuffer!==null&&$.multiMsgBuffer.length>0)U5($,"reopen");return $.multiMsgBuffer=[],F5($,X,J,Q,Y),!0}if(V==="end"){if($.multiMsgBuffer===null){if(X.trim()||J.length)return!1;return K(`session "${$.sessionName}": end marker without active multi-msg buffer, ignoring`),!0}F5($,X,J,Q,Y);let{multiMsgBuffer:H,multiMsgReactions:W}=$;return $.multiMsgBuffer=null,$.multiMsgReactions=new Map,await Uq($,H,W),!0}if($.multiMsgBuffer!==null)return F5($,Z,J,Q,Y),!0;return!1}function F5($,Z,J,Q,Y){if(Z.trim()||J.length)$.multiMsgBuffer.push({text:Z,files:J,userOpenId:Q,msgId:Y});if(Y)Fq($,Y)}function Fq($,Z){$.multiMsgReactions.set(Z,""),(async()=>{let J=await R$(Z,"Pin");if(!J)return;if($.multiMsgReactions.has(Z))$.multiMsgReactions.set(Z,J);else P$(Z,J)})()}async function Uq($,Z,J){for(let[X,H]of J)if(H)P$(X,H);let Q=Z.filter((X)=>X.text.trim()||X.files.length);if(Q.length===0){K(`session "${$.sessionName}": multi-msg flush with empty buffer, not sent`),await E($.chatId,"⚠️ 多条消息缓冲为空,未发送(只收到标记没有正文)。");return}let Y=Q.map((X)=>{return(X.files.length?X.files.map((W)=>`[file: ${W}]`).join(" ")+`
|
|
152
153
|
`:"")+X.text}).join(`
|
|
153
154
|
|
|
154
|
-
`),V=Q[Q.length-1];K(`session "${$.sessionName}": multi-msg flush ${Q.length} segment(s) → 1 turn`),await $.onUserMessage(Y,[],V.userOpenId,V.msgId)}function
|
|
155
|
-
`)}:{}}}function
|
|
156
|
-
`)}function
|
|
157
|
-
`)}function
|
|
158
|
-
`):JSON.stringify(J);Y.output=V,Y.isError=Q;let X=r_(Y.name,V,Q);if(X)$.sendOutboundPath(X,Y.name);if(Y.name==="AskUserQuestion"){l4($);return}if(Y.batchSlot!=null){let W=$.currentTurn.toolBatches.get(Y.i);if(W){let G=W.items[Y.batchSlot];if(G)G.output=V,G.isError=Q;let _=AY(W.kind,Y.i,W.items);c($.currentTurn.cardId,U.tool(Y.i),_)}l4($);return}let z=n0(Y.name);if(z){a_($,Y,z,Y.input,V,Q,Y.resolvedNote);return}let H=G0(Y.i,Y.name,Y.input,V,Q?"❌":"✅",Y.resolvedNote);c($.currentTurn.cardId,U.tool(Y.i),H),l4($)}function a_($,Z,J,Q,Y,V,X){if(!$.currentTurn)return;if(!V)$.taskBoard=o9($.taskBoard,J,Q,Y);let z=j0(Z.i,$.taskBoard,{name:J,status:V?"❌":"✅"},X);if(c($.currentTurn.cardId,U.tool(Z.i),z),$.currentTurn.taskLiveInserted)c($.currentTurn.cardId,U.taskBoardLive,r0($.taskBoard));l4($)}function l4($){let Z=$.currentTurn;if(!Z)return;for(let J of Z.toolByUseId.values())if(J.output==null)return;$.startThinkingFooter(Z)}function RY($,Z,J,Q,Y){let V=$.currentTurn;if(!V)return;for(let[X,z]of Q){let H=z.batchSlot??null,W=z.input,G,_;if(H!=null){let M=Y.get(z.i)?.items[H];if(!M)continue;W=M.input,G=M.output,_=M.isError}else G=z.output??null,_=z.isError??!1;let B=G!=null,L=N1(Z,U.tool(z.i));if(B&&!L)continue;if(H!=null){let M=Y.get(z.i)?.kind;if(!M)continue;let O=V.toolCount++,P={toolUseId:X,input:W,output:G,isError:_};V.toolBatches.set(O,{kind:M,items:[P]}),V.toolByUseId.set(X,{...z,i:O,batchSlot:0}),a(J,AY(M,O,[P]),{type:"insert_before",targetElementId:D$(V)});continue}let F=n0(z.name);if(F){let M=F==="TaskCreate";if(M)V.taskUpdateI=null;else V.taskCreateI=null;let O=(M?V.taskCreateI:V.taskUpdateI)===null;if(O)if(M)V.taskCreateI=V.toolCount++;else V.taskUpdateI=V.toolCount++;let P=M?V.taskCreateI:V.taskUpdateI;V.toolByUseId.set(X,{...z,i:P});let y=!B?"⏳":_?"❌":"✅",m=j0(P,$.taskBoard,{name:F,status:y},z.resolvedNote);O?a(J,m,{type:"insert_before",targetElementId:D$(V)}):c(J,U.tool(P),m);continue}let D=V.toolCount++;V.toolByUseId.set(X,{...z,i:D});let j=!B?"⏳":_?"❌":"✅";a(J,G0(D,z.name,z.input,G,j,z.resolvedNote),{type:"insert_before",targetElementId:D$(V)})}}var jY=E(()=>{J5();u0();c$();d()});function EY($){return $.pendingAsks.size>0}async function TY($,Z,J,Q){let Y=$.pendingAsks.entries().next();if(Y.done){K(`session "${$.sessionName}": onAskMessageAnswer with no pending — falling back to onUserMessage`),await $.onUserMessage(Z,[],J,Q);return}let[V,X]=Y.value;if(X.currentIdx===void 0){if(X.requestId){K(`session "${$.sessionName}": pending ask ${V} awaiting finalize — ignoring message`);return}K(`session "${$.sessionName}": pending ask ${V} orphaned (no can_use_tool) — dropping zombie, reprocessing as user message`),$.pendingAsks.delete(V),await $.onUserMessage(Z,[],J,Q);return}if(await L5($,V,X.currentIdx,Z,J)&&Q)P$(Q,"CheckMark")}async function xY($,Z,J,Q,Y){let V=$.pendingAsks.get(Z);if(!V)return K(`session "${$.sessionName}": stray ask answer for ${Z}`),!1;if(J!==V.currentIdx)return K(`session "${$.sessionName}": stale ask click q=${J} current=${V.currentIdx}`),!1;return yY($,Z,{optionIdx:Q,user:Y})}async function L5($,Z,J,Q,Y){let V=$.pendingAsks.get(Z);if(!V)return K(`session "${$.sessionName}": stray ask custom for ${Z}`),!1;let X=(Q??"").trim();if(!X)return K(`session "${$.sessionName}": empty custom answer, ignoring`),!1;if(J!==V.currentIdx)return K(`session "${$.sessionName}": stale ask custom q=${J} current=${V.currentIdx}`),!1;return yY($,Z,{customText:X,user:Y})}function yY($,Z,J){let Q=$.pendingAsks.get(Z);if(!Q||Q.currentIdx===void 0)return!1;let Y=Q.currentIdx,V=Q.questions[Y];if(!V)return K(`session "${$.sessionName}": advanceAsk currentIdx=${Y} out of range`),!1;let X;if(J.customText!==void 0)X=J.customText;else if(J.optionIdx!==void 0){let _=V.options?.[J.optionIdx];if(!_)return K(`session "${$.sessionName}": advanceAsk option ${J.optionIdx} out of range`),!1;X=_.label}else return K(`session "${$.sessionName}": advanceAsk with neither customText nor optionIdx`),!1;Q.answers[V.question]=X,Q.answered.set(Y,{optionIdx:J.optionIdx,customText:J.customText,user:J.user});let z=Q.questions.length,H=void 0;for(let _=Y+1;_<z;_++)if(!Q.answered.has(_)){H=_;break}Q.currentIdx=H;let W=$.currentTurn,G=W?.toolByUseId.get(Z);if(W&&G){let _=g2(G.i,Z,Q.questions,H===void 0?"✅":"\uD83E\uDD14",{currentIdx:H,answered:Q.answered});c(W.cardId,U.tool(G.i),_)}if(H===void 0)if(Q.requestId)F5($,Z);else K(`session "${$.sessionName}": ask ${Z} all answered, waiting for can_use_tool`);return!0}function F5($,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 D5=E(()=>{u0();c$();d();v()});async function CY($,Z,J,Q){let Y=$.pendingPermissions.get(Z);if(!Y)return K(`session "${$.sessionName}": stray permission ${Z}`),{ok:!1,message:"此权限请求已失效或已处理"};let V=$.proc;if(!V)return K(`session "${$.sessionName}": permission ${Z} has no active process`),{ok:!1,message:"后端进程已退出,权限决定未送达"};let X=J==="deny"?"deny":"allow";try{V.sendPermissionResponse(Z,X,J==="allow_always"?{updatedPermissions:Y.permissionSuggestions}:void 0)}catch(W){return K(`session "${$.sessionName}": permission response ${Z} failed: ${W}`),{ok:!1,message:`权限决定发送失败: ${W instanceof Error?W.message:W}`}}$.pendingPermissions.delete(Z);let z=$.currentTurn,H=z?.toolByUseId.get(Y.toolUseId);if(z&&H){let W=n0(H.name);if(J==="deny"){let G=`\uD83D\uDEAB 已拒绝 by ${Q||"匿名"}`,_=W?j0(H.i,$.taskBoard,{name:W,status:"❌"},G):G0(H.i,H.name,H.input,G,"❌");c(z.cardId,U.tool(H.i),_)}else{let G=J==="allow_always"?"始终允许":"已允许";H.resolvedNote=`✅ **${G}** by ${Q||"匿名"}`;let _=W?j0(H.i,$.taskBoard,{name:W,status:"⏳"},H.resolvedNote):G0(H.i,H.name,H.input,null,"⏳",H.resolvedNote);c(z.cardId,U.tool(H.i),_)}}if(K(`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 NY($,Z){let J=$.currentTurn;if(!J){K(`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){K(`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){K(`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 X=$.pendingAsks.get(Q);if(!X){K(`session "${$.sessionName}": AskUserQuestion ${Q} missing pendingAsk — deny`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"no pending ask"});return}if(X.requestId=Z.request_id,$.pendingPermissions.set(Z.request_id,{toolUseId:Q}),X.currentIdx===void 0)F5($,Q);return}$.status="awaiting_permission",$.pendingPermissions.set(Z.request_id,{toolUseId:Q,permissionSuggestions:Z.permission_suggestions}),K(`session "${$.sessionName}": can_use_tool request=${Z.request_id} tool_use_id=${Q} tool=${Y.name}`);let V=K4(Y.i,Y.name,Y.input,Z.request_id);if(c(J.cardId,U.tool(Y.i),V),J.userOpenId&&J.messageId){let X=K0(Y.name,Y.input),z=p0(Y.name),H=X&&X.length>30?X.slice(0,30)+"…":X,W=H?`\uD83D\uDD10 等审批: ${z} · ${H}`:`\uD83D\uDD10 等审批: ${z}`;(async()=>{V$(J.cardId),await n8(J.cardId,{config:{summary:{content:W}}}),await g0(J.messageId,[J.userOpenId])})()}}var SY=E(()=>{u0();c$();d();v();D5()});function kY($,Z=bY){return new Promise((J,Q)=>{let Y=setTimeout(()=>Q(Error(`timeout ${Z}ms`)),Z);$.then((V)=>{clearTimeout(Y),J(V)},(V)=>{clearTimeout(Y),Q(V)})})}function wY($){return typeof $==="string"&&$q.includes($)?$:null}async function vY(){let $=new w4;try{await kY($.request("initialize",{clientInfo:{name:"lodestar-models",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}));let Z=await kY($.request("model/list",{})),J=Array.isArray(Z?.data)?Z.data:[],Q=[];for(let Y of J){if(!Y||Y.hidden||!Y.id)continue;let V=(Array.isArray(Y.supportedReasoningEfforts)?Y.supportedReasoningEfforts:[]).map((z)=>wY(z?.reasoningEffort)).filter((z)=>z!==null);if(!V.length)continue;let X=wY(Y.defaultReasoningEffort)??V[0];Q.push({model:String(Y.id),display:typeof Y.displayName==="string"&&Y.displayName?String(Y.displayName):String(Y.id),efforts:V,defaultEffort:X})}return Q}finally{await $.close()}}async function fY($,Z){let J=new URL($),Q=J.pathname.replace(/\/+$/,""),Y=`${J.protocol}//${J.host}${Q}/v1/models`,V=await fetch(Y,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(bY)});if(!V.ok)throw Error(`HTTP ${V.status}`);let X=await V.json();return(Array.isArray(X?.data)?X.data:[]).filter((H)=>H&&(H.display_name||H.id)).map((H)=>{let W=String(H.display_name||H.id);return{model:W,display:W,efforts:u$,defaultEffort:"max"}})}var bY=1e4,$q,u$;var $8=E(()=>{v4();$q=["none","minimal","low","medium","high","xhigh","max","ultra"];u$=["max","xhigh","high","medium","low"]});import{existsSync as Zq}from"node:fs";import{homedir as Jq}from"node:os";import{join as IY}from"node:path";function i4($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function Qq($){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(i4($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(i4($.weekly,"weekly","周配额"));return{state:"ok",planLabel:$.subscriptionType,windows:Z,fetchedAt:$.fetchedAt}}function Yq($){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(i4(J.fiveHour,"fiveHour",`${Q} 5h`));if(J.weekly)Z.push(i4(J.weekly,"weekly",`${Q} 周`))}return Z.length?Z:null}function Vq(){let $=process.env.CODEX_HOME||IY(Jq(),".codex");return Zq(IY($,"auth.json"))}var hY=E(()=>{E$();x$();v4();$8();v();Y0({kind:"codex-subscription",configSectionId:"codex-sub",build:($)=>{let Z=Vq(),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:[],defaultModel:J??"",async refreshModels(){if(!Y.enabled){Y.models=[];return}try{if(Y.models=await vY(),Q)for(let V of Y.models)V.defaultEffort=Q;if(!J)Y.defaultModel=Y.models[0]?.model??""}catch(V){K(`codex-sub refreshModels MISS: ${V?.message??V}`),Y.models=[]}},spawnEnv(V){let X=k0(V);return Object.assign(X,f.codex.env),X},resolveSpawnModel(V){return V},async readUsage(){let V=await b4(),X=Qq(V),z=Yq(V);if(z)X.windows=z;return X}};return Y}})});function zq($){let Z=new URL($),J=Z.pathname.replace(/\/+$/,"");return`${Z.protocol}//${Z.host}${J}/v1/messages`}async function d4($,Z,J){try{let Q=await fetch(zq($),{method:"POST",headers:{"Content-Type":"application/json",...Z},body:JSON.stringify({model:J,max_tokens:1,messages:[{role:"user",content:"hi"}]}),signal:AbortSignal.timeout(Xq)});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 K(`model-existence: ${J} HTTP ${Q.status}, no verdict`),"no_verdict"}catch(Q){return K(`model-existence: ${J} MISS (${Q?.message??Q})`),"no_verdict"}}var Xq=15000;var U5=E(()=>{v()});function gY($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function Hq($){return{kind:"monthly",label:"月度工具",percent:$.percent,resetsAt:$.resetsAt,...$.used!=null?{used:$.used}:{},...$.total!=null?{total:$.total}:{}}}function Wq($){return($??"").split(",").map((Z)=>Z.trim()).filter(Boolean)}function Kq($){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 Gq($){let Z={};for(let J of($??"").split(",")){let Q=J.indexOf("=");if(Q<=0)continue;let Y=J.slice(0,Q).trim().toLowerCase(),V=J.slice(Q+1).trim();if((Y==="opus"||Y==="sonnet"||Y==="haiku")&&V)Z[Y]=V}return Z}function _q($){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(gY($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(gY($.weekly,"weekly","周额度"));if($.monthly)Z.push(Hq($.monthly));return{state:"ok",planLabel:$.level?`${$.level} 套餐`:void 0,windows:Z,fetchedAt:$.fetchedAt}}var mY=E(()=>{x$();I4();$8();w8();U5();v();Y0({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)&&f4(J),V=$.model?.trim()||void 0,X=Gq($.slots),z={id:"glm",kind:"glm-coding-plan",agent:"claude",display:$.display?.trim()||"GLM Coding Plan",enabled:Y,models:[],defaultModel:V??"",async refreshModels(){if(!z.enabled){z.models=[];return}try{let H=await fY(J,Q),G=Wq($.models).filter((_)=>!H.some((B)=>B.model.toLowerCase()===_.toLowerCase())).map((_)=>({model:_,display:_,efforts:u$,defaultEffort:"max"}));if(z.models=[...H,...G],!V)z.defaultModel=Kq(z.models.map((_)=>_.model));for(let _ of z.models){let B=k8("glm",_.model);_.context1m=B!=null&&B>=1e6||void 0}}catch(H){K(`glm refreshModels MISS: ${H?.message??H}`),z.models=[]}},spawnEnv(H){let G={...k0(H)};if(G.ANTHROPIC_BASE_URL=J,G.ANTHROPIC_AUTH_TOKEN=Q,X.opus)G.ANTHROPIC_DEFAULT_OPUS_MODEL=X.opus;if(X.sonnet)G.ANTHROPIC_DEFAULT_SONNET_MODEL=X.sonnet;if(X.haiku)G.ANTHROPIC_DEFAULT_HAIKU_MODEL=X.haiku;return G},resolveSpawnModel(H){return S8("glm",H)},async verifyModel(H){return d4(J,{Authorization:`Bearer ${Q}`},H)},async readUsage(){return _q(await $5(J,Q))}};return z},setup:{commandSuffix:"glm",hint:($)=>`启用 ${$}:发送
|
|
155
|
+
`),V=Q[Q.length-1];K(`session "${$.sessionName}": multi-msg flush ${Q.length} segment(s) → 1 turn`),await $.onUserMessage(Y,[],V.userOpenId,V.msgId)}function U5($,Z){if($.multiMsgBuffer===null)return;let J=$.multiMsgBuffer.length;K(`session "${$.sessionName}": clear multi-msg buffer (${Z}): ${J} segment(s)`);for(let[Q,Y]of $.multiMsgReactions){if(Y)P$(Q,Y);R$(Q,"CrossMark")}$.multiMsgBuffer=null,$.multiMsgReactions=new Map}var VY=T(()=>{n();v();QY()});import{mkdtemp as Pq,rm as Aq,writeFile as Mq}from"node:fs/promises";import{createRequire as Oq}from"node:module";import{tmpdir as jq}from"node:os";import{join as XY}from"node:path";function Sq($){let Z=KY.get($);if(Z)return Z;let{liteAdaptor:J}=V1("mathjax-full/js/adaptors/liteAdaptor.js"),{RegisterHTMLHandler:Q}=V1("mathjax-full/js/handlers/html.js"),{mathjax:Y}=V1("mathjax-full/js/mathjax.js"),{TeX:V}=V1("mathjax-full/js/input/tex.js"),{AllPackages:X}=V1("mathjax-full/js/input/tex/AllPackages.js"),{SVG:H}=V1("mathjax-full/js/output/svg.js"),W=J({fontSize:$});Q(W);let z=Y.document("",{InputJax:new V({packages:X}),OutputJax:new H({fontCache:"none"})}),G={adaptor:W,doc:z};return KY.set($,G),G}function GY($,Z){let J=Number.parseFloat($??"");if(!Number.isFinite(J)||J<=0)throw Error(`MathJax SVG missing valid ${Z}`);return J}function kq($){return $.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function wq($,Z=A5,J=!0){try{let Q=Z*Rq,{adaptor:Y,doc:V}=Sq(Z),X=V.convert($,{display:J,em:Z,ex:Q,containerWidth:80*Z}),H=Y.outerHTML(X);if(/data-mjx-error=|mjx-merror/.test(H)){let t$=H.match(/data-mjx-error="([^"]+)"/)?.[1]??"MathJax parse error";throw Error(t$)}let W=H.indexOf("<svg"),z=H.lastIndexOf("</svg>");if(W<0||z<0)throw Error("MathJax returned no SVG");let G=H.slice(W,z+6),q=G.match(/^<svg\b[^>]*>/)?.[0];if(!q)throw Error("MathJax returned malformed SVG root");let B=GY(q.match(/\bwidth="([\d.]+)ex"/)?.[1],"width"),L=GY(q.match(/\bheight="([\d.]+)ex"/)?.[1],"height"),F=q.match(/\bviewBox="([^"]+)"/)?.[1];if(!F)throw Error("MathJax SVG missing viewBox");let U=F.trim().split(/[\s,]+/).map(Number);if(U.length!==4||U.some((t$)=>!Number.isFinite(t$))||U[2]<=0||U[3]<=0)throw Error("MathJax SVG has invalid viewBox");let[R,D,P,M]=U,x=/<text\b/.test(G)?Nq:0,y=`${R} ${D} ${P+x} ${M}`,N=B*Q,m=x*(N/P),h=Math.max(1,Math.ceil(N+m)),w=Math.max(1,Math.ceil(L*Q)),A=Eq-D5*2,k=Math.min(1,A/h),s=Math.max(1,Math.round(h*k)),c=Math.max(1,Math.round(w*k));if(k<1&&c<Tq)throw Error(`formula would be unreadable after width cap (${s}x${c})`);let a$=s+D5*2,J$=c+WY*2,U1=G.slice(q.length,-6).replace(/currentColor/g,HY).replace(/font-family="serif"/g,`font-family="${yq}"`);return{svg:[`<svg xmlns="http://www.w3.org/2000/svg" width="${a$}" height="${J$}" viewBox="0 0 ${a$} ${J$}" style="color:${HY}">`,`<rect x="0" y="0" width="${a$}" height="${J$}" rx="6" fill="${LY}"/>`,`<svg x="${D5}" y="${WY}" width="${s}" height="${c}" viewBox="${kq(y)}" preserveAspectRatio="xMidYMid meet">`,U1,"</svg>","</svg>"].join(""),width:a$,height:J$}}catch(Q){return K(`math-render: TeX→SVG failed for ${$.slice(0,80)}…: ${Q}`),null}}function bq($,Z=A5,J=!0){let Q=wq($,Z,J);if(!Q)return null;try{let{Resvg:Y}=V1("@resvg/resvg-js"),X=new Y(Q.svg,{background:LY,fitTo:{mode:"original"},shapeRendering:2,textRendering:1,font:{loadSystemFonts:!0,serifFamily:zY,sansSerifFamily:zY}}).render().asPng(),H=new DataView(X.buffer,X.byteOffset,X.byteLength),W=H.getUint32(16),z=H.getUint32(20);if(W!==Q.width||z!==Q.height)throw Error(`PNG dimensions ${W}x${z} != SVG ${Q.width}x${Q.height}`);return{png:X,width:W,height:z}}catch(Y){return K(`math-render: SVG→PNG failed for ${$.slice(0,80)}…: ${Y}`),null}}function vq($){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 qY($,Z){let J=[],Q=(G,q,B)=>{let L=G[0],F=q.trim();if(!F)return;J.push({start:Z+G.index,end:Z+G.index+L.length,tex:F,raw:L,display:B})},Y,V=/(?<!\\)\$\$([\s\S]+?)(?<!\\)\$\$|\\\[([\s\S]+?)\\\]/g;while((Y=V.exec($))!==null)Q(Y,Y[1]??Y[2]??"",!0);let X=/\\\(([\s\S]+?)\\\)/g;while((Y=X.exec($))!==null)Q(Y,Y[1]??"",!1);let H=/(?<![\\$])\$(?!\$)([^$\n]+?)(?<![\\$])\$(?!\$)/g;while((Y=H.exec($))!==null){let G=(Y[1]??"").trim();if(vq(G))Q(Y,G,!1)}J.sort((G,q)=>G.start-q.start||q.end-G.end);let W=[],z=-1;for(let G of J){if(G.start<z)continue;W.push(G),z=G.end}return W}function FY($){let Z=J6($),J=[],Q=0;for(let Y of Z){if(Q<Y.start)J.push(...qY($.slice(Q,Y.start),Q));Q=Math.max(Q,Y.end)}if(Q<$.length)J.push(...qY($.slice(Q),Q));return J}function fq($){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(_Y[Q])return _Y[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 mq($){let Z=BY.get($);if(Z!==void 0)return Z;return Z=Iq++,BY.set($,Z),Z}function cq($,Z){return`${Cq}\x00${mq(Z)}\x00${$}`}function uq($){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 pq($,Z){let J=cq($,Z),Q=Y1.get(J);if(Q)return Q;let Y=P5.get(J);if(Y)return Y;let V=(async()=>{let X=bq($,A5,!0);if(!X)return null;let H=null;try{H=await Pq(XY(jq(),"lodestar-math-"));let W=XY(H,`formula-${uq($)}.png`);await Mq(W,X.png);let z=await Z(W,{tex:$,width:X.width,height:X.height});if(!z)return K(`math-render: upload returned no image key for ${$.slice(0,80)}…`),null;let G={key:z,width:X.width,height:X.height};if(Y1.has(J))Y1.delete(J);Y1.set(J,G);while(Y1.size>gq){let q=Y1.keys().next().value;if(typeof q!=="string")break;Y1.delete(q)}return G}catch(W){return K(`math-render: upload failed for ${$.slice(0,80)}…: ${W}`),null}finally{if(H)try{await Aq(H,{recursive:!0,force:!0})}catch(W){K(`math-render: temp cleanup failed for ${H}: ${W}`)}}})();P5.set(J,V);try{return await V}finally{P5.delete(J)}}function lq($,Z,J){let Q=$.width<=xq;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 UY($,Z={}){let J=FY($);if(!J.length)return{blocks:[{type:"markdown",text:$}],formulaCount:0,renderedImageCount:0};let Q=Z.uploader??hq,Y=await Promise.all(J.map(async(G)=>{if(!G.display){let q=fq(G.tex);if(q!==null)return{unicode:q,uploaded:null}}return{unicode:null,uploaded:await pq(G.tex,Q)}})),V=[],X="",H=0,W=0,z=()=>{if(!X)return;if(X.trim())V.push({type:"markdown",text:X});X=""};for(let G=0;G<J.length;G++){let q=J[G],B=Y[G];if(X+=$.slice(H,q.start),B.unicode!==null){X+=B.unicode,H=q.end;continue}let L=B.uploaded;if(!L){X+=q.raw,H=q.end;continue}z(),V.push(lq(L,q,W++)),H=q.end}if(X+=$.slice(H),z(),!V.length)V.push({type:"markdown",text:$});return{blocks:V,formulaCount:J.length,renderedImageCount:W}}function M5($){return FY($).length>0}var V1,Rq=0.5,A5=22,HY="#1F2329",LY="#F7F8FA",D5=12,WY=8,Eq=720,Tq=14,xq=278,Cq="v4-native-cjk-tail-pad",Nq=1100,zY,yq="Noto Sans CJK SC, Noto Sans CJK JP, Microsoft YaHei, PingFang SC, Arial Unicode MS, sans-serif",KY,_Y,hq=async($)=>{let{uploadImageKey:Z}=await Promise.resolve().then(() => (n(),a));return Z($)},BY,Iq=1,Y1,P5,gq=512;var DY=T(()=>{v();V1=Oq(import.meta.url),zY=process.platform==="win32"?"Microsoft YaHei":process.platform==="darwin"?"PingFang SC":"Noto Sans CJK SC",KY=new Map;_Y={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:"Ω"};BY=new WeakMap,Y1=new Map,P5=new Map});import{spawn as PY}from"cross-spawn";import{existsSync as AY}from"node:fs";import{homedir as t4}from"node:os";import{delimiter as O5,join as J8}from"node:path";function Y8(){if(process.platform!=="win32"){let $=J8(t4(),".local","bin","agy");if(AY($))return $}return iq()??"agy"}function s4(){if(process.platform==="win32")return process.env.PATH??"";return[...new Set([J8(t4(),".local","bin"),J8(t4(),".local","npm-global","bin"),J8(t4(),".bun","bin"),...(process.env.PATH??"").split(O5),"/usr/local/bin","/usr/bin","/bin"].filter(Boolean))].join(O5)}function V8($){return["--model",Q8,"--dangerously-skip-permissions","--print-timeout",MY,"-p",$]}function j5(){return`agy --model "${Q8}" --dangerously-skip-permissions --print-timeout ${MY} -p <prompt>`}function jY($,Z){let J=Y8(),Q=V8($);return{proc:PY(J,Q,{cwd:Z,stdio:["ignore","pipe","pipe"],shell:!1,env:{...process.env,PATH:s4()}}),bin:J,args:Q}}async function R5($){let Z=await a4($,["status","--short","--untracked-files=all"]);if(!Z.ok)return{ok:!1,statusShort:Z.stdout,diffShortStat:"",diffNameOnly:"",error:(Z.error??Z.stderr.trim())||"git status failed"};let Q=(await a4($,["rev-parse","--verify","HEAD"])).ok?["HEAD","--"]:["--"],Y=await a4($,["diff","--shortstat",...Q]),V=await a4($,["diff","--name-only",...Q]),X=[Y,V].filter((H)=>!H.ok).map((H)=>H.error??H.stderr.trim()).filter(Boolean);return{ok:X.length===0,statusShort:Z.stdout.trimEnd(),diffShortStat:Y.stdout.trim(),diffNameOnly:V.stdout.trimEnd(),...X.length?{error:X.join(`
|
|
156
|
+
`)}:{}}}function iq(){let $=process.env.PATH??"";if(!$)return null;let Z=process.platform==="win32"?["agy.cmd","agy.bat","agy.exe","agy"]:["agy"];for(let J of $.split(O5)){if(!J)continue;for(let Q of Z){let Y=J8(J,Q);if(AY(Y))return Y}}return null}async function a4($,Z){return new Promise((J)=>{let Q=PY("git",Z,{cwd:$,stdio:["ignore","pipe","pipe"],shell:!1,env:{...process.env,PATH:s4()}}),Y="",V="",X=!1,H=setTimeout(()=>{if(X)return;X=!0,Q.kill("SIGTERM"),J({ok:!1,stdout:Y,stderr:V,error:`git ${Z.join(" ")} timed out after 10s`})},1e4);Q.stdout.on("data",(W)=>{Y+=W.toString()}),Q.stderr.on("data",(W)=>{V+=W.toString()}),Q.on("error",(W)=>{if(X)return;X=!0,clearTimeout(H),J({ok:!1,stdout:Y,stderr:V,error:W.message})}),Q.on("close",(W)=>{if(X)return;X=!0,clearTimeout(H);let z=W===0;J({ok:z,stdout:Y,stderr:V,...z?{}:{error:`git ${Z.join(" ")} exited ${W}`}})})})}var Q8="Gemini 3.1 Pro (High)",MY="180m0s",OY=10860000;var E5=()=>{};import{execFileSync as nq}from"node:child_process";import{randomUUID as oq}from"node:crypto";import{StringDecoder as RY}from"node:string_decoder";function CY($,Z=Date.now()){return((Z-$.startedAt)/1000).toFixed(1)}function sq($){let Z=$.proc.pid;if(!Z||process.platform==="win32")return{cpuPercent:$.lastCpuPercent,memBytes:$.lastMemBytes};try{let J=nq("ps",["-p",String(Z),"-o","%cpu=,rss="],{encoding:"utf8",timeout:2000,stdio:["ignore","pipe","ignore"]}).trim(),[Q,Y]=J.split(/\s+/),V=Number.parseFloat(Q??""),X=Number.parseInt(Y??"",10);if(Number.isFinite(V))$.lastCpuPercent=V;if(Number.isFinite(X))$.lastMemBytes=X*1024}catch{}return{cpuPercent:$.lastCpuPercent,memBytes:$.lastMemBytes}}function NY($){let Z=[$.stderr.trim()];if($.spawnError)Z.push(`spawn error: ${$.spawnError}`);return Z.filter(Boolean).join(`
|
|
157
|
+
`)}function yY($,Z,J,Q,Y){let V=NY(Z),X=sq(Z);return{status:J,model:Q8,cwd:$.workDir,command:j5(),startedAtMs:Z.startedAt,elapsedSec:CY(Z,Q??Date.now()),cpuPercent:X.cpuPercent,memBytes:X.memBytes,...Q?{endedAtMs:Q}:{},...Y?{exitCode:Y.code,signal:Y.signal}:{},stdoutBytes:Z.stdoutBytes,stderrBytes:Z.stderrBytes,captureTruncated:Z.captureTruncated,cardTruncated:Z.stdout.length>TY||V.length>xY,hostTimedOut:Z.hostTimedOut}}function e4($,Z,J){u(Z.cardId,O.agyStats,t2(yY($,Z,J)))}function T5($,Z,J){if(!J)return;let Q=Z==="stdout"?$.stdout:$.stderr,Y=rq-Q.length;if(Y<=0){$.captureTruncated=!0;return}let V=Q+J.slice(0,Y);if(Z==="stdout")$.stdout=V;else $.stderr=V;if(J.length>Y)$.captureTruncated=!0}function eq($){if($.decodersEnded)return;$.decodersEnded=!0;let Z=$.stdoutDecoder.end(),J=$.stderrDecoder.end();if(Z)T5($,"stdout",Z);if(J)T5($,"stderr",J)}function EY($,Z,J){if(Z==="stdout")$.stdoutBytes+=J.length;else $.stderrBytes+=J.length;let Q=Z==="stdout"?$.stdoutDecoder.write(J):$.stderrDecoder.write(J);T5($,Z,Q)}function $_($,Z,J){let Q=J0($.stdout).trim(),Y=J0(Z).trim(),V=J0(J).trim(),X=["agy 返回结果如下,请基于这份结果继续处理。","","原始 agy 任务:",$.prompt.trim(),"","agy 结果:",Q||"(无 stdout 输出)"];if(V)X.push("","agy 状态说明:",V);if(Y)X.push("","agy stderr:",Y);if($.captureTruncated)X.push("","注意: daemon 捕获的 agy 输出已截断。");return X.join(`
|
|
158
|
+
`)}function Z_($,Z,J,Q){let Y=oq();if($.agyForwardPrompts.set(Y,{prompt:$_(Z,J,Q),used:!1}),$.agyForwardPrompts.size>20){let V=$.agyForwardPrompts.keys().next().value;if(V)$.agyForwardPrompts.delete(V)}return Y}function SY($,Z,J=""){let Q=$.backendLabel(),Y=Z.trim(),V=$.agyForwardPrompts.get(Y);if(!V)return{ok:!1,message:"agy 结果已过期,请重新运行 agy"};if(V.used)return{ok:!1,message:"agy 结果已转发,请勿重复点击"};if($.startingAgy||$.runningAgy)return{ok:!1,message:"agy 任务仍在执行,请稍后再转发"};return V.used=!0,(async()=>{try{await $.onUserMessage(V.prompt,[],J)}catch(X){V.used=!1;let H=`❌ agy 结果转发 ${Q} 失败: ${j(X)}`;K(`session "${$.sessionName}": ${H}`),await C($.chatId,H)}})(),{ok:!0,message:`已转发 ${Q}`}}async function kY($,Z){if(!Z.trim()){await E($.chatId,"用法: agy <任务说明>");return}if($.startingAgy||$.runningAgy){await E($.chatId,"⏳ 当前已有 agy 任务在执行;请等待完成,或发送 stop 打断。");return}if($.currentTurn||$.openingTurn||$.pendingUserMessageCount>0||$.pendingMidTurnMsgs.length>0){await E($.chatId,`⚠️ ${$.backendLabel()} 当前有正在执行或排队的 turn;请先发送 stop,或等待当前 turn 完成后再运行 agy。`);return}$.startingAgy=!0;let J=Date.now();try{let Q=await R5($.workDir),Y={status:"⏳ agy 运行中",model:Q8,cwd:$.workDir,command:j5(),startedAtMs:J,elapsedSec:"0.0",stdoutBytes:0,stderrBytes:0},V=await l($.chatId,Z5({sessionName:$.sessionName,prompt:Z,stats:Y,beforeGit:Q}));if(!V){await C($.chatId,"❌ 创建 agy 卡片失败,任务未启动。");return}let X;try{X=await $0(V)}catch(F){K(`session "${$.sessionName}": agy card id_convert failed: ${F}`),await C($.chatId,`❌ agy 卡片初始化失败,任务未启动: ${j(F)}`);return}let H=null;p$(X,5,(F)=>{if(H?.cardWriteFailed)return;if(H)H.cardWriteFailed=!0;let U=`❌ agy 卡片更新失败${F?` code=${F}`:""},请查看 daemon 日志。`;K(`session "${$.sessionName}": ${U}`),C($.chatId,U)});let{proc:W,bin:z,args:G}=jY(Z,$.workDir);K(`session "${$.sessionName}": spawn agy ${z} ${G.slice(0,-1).join(" ")} <prompt> cwd=${$.workDir}`);let q,B=new Promise((F)=>{q=F}),L;L={proc:W,cardId:X,messageId:V,prompt:Z,startedAt:J,beforeGit:Q,stdout:"",stderr:"",stdoutDecoder:new RY("utf8"),stderrDecoder:new RY("utf8"),decodersEnded:!1,stdoutBytes:0,stderrBytes:0,lastCpuPercent:null,lastMemBytes:null,captureTruncated:!1,cardWriteFailed:!1,finished:!1,stopRequested:!1,hostTimedOut:!1,timer:setInterval(()=>e4($,L,L.stopRequested?"\uD83D\uDED1 正在停止 agy":"⏳ agy 运行中"),tq),hostTimeout:setTimeout(()=>{if(L.finished)return;L.hostTimedOut=!0,L.stopStatus="❌ agy 超时",e4($,L,"❌ agy 超时,正在停止"),wY(L)},OY),done:B,resolveDone:q},H=L,$.runningAgy=L,$.status="working",$.opts.onLifecycleChange?.(),e4($,L,"⏳ agy 运行中"),W.stdout.on("data",(F)=>EY(L,"stdout",F)),W.stderr.on("data",(F)=>EY(L,"stderr",F)),W.on("error",(F)=>{L.spawnError=F.message,K(`session "${$.sessionName}": agy spawn error: ${F.message}`)}),W.on("close",(F,U)=>{J_($,L,F,U)})}finally{$.startingAgy=!1}}function wY($){if(!$.proc.killed)$.proc.kill("SIGTERM");if(!$.forceKillTimer)$.forceKillTimer=setTimeout(()=>{if(!$.finished)$.proc.kill("SIGKILL")},aq)}async function bY($,Z="\uD83D\uDED1 agy 已打断"){let J=$.runningAgy;if(!J)return!1;return J.stopRequested=!0,J.stopStatus=Z,e4($,J,"\uD83D\uDED1 正在停止 agy"),wY(J),await J.done,!0}async function J_($,Z,J,Q){if(Z.finished)return;if(Z.finished=!0,eq(Z),clearInterval(Z.timer),clearTimeout(Z.hostTimeout),Z.forceKillTimer)clearTimeout(Z.forceKillTimer);let Y="❌ agy 失败";try{let V=Date.now(),X=await R5($.workDir),H=NY(Z),W="",z=J0(Z.stdout).trim(),G=J0(H).trim(),q=!z&&!G;if(J===0&&!Q&&!Z.spawnError&&!Z.hostTimedOut&&!Z.stopRequested&&q)W="agy 进程退出码为 0,但没有返回 stdout/stderr。";let B=J===0&&!Q&&!Z.spawnError&&!Z.hostTimedOut&&!Z.stopRequested&&!q;Y=Z.stopRequested?Z.stopStatus??"\uD83D\uDED1 agy 已打断":Z.hostTimedOut?"❌ agy 超时":B?"✅ agy 完成":"❌ agy 出错";let L=Z.stdout.length>TY||H.length>xY,F=Z_($,Z,H,W);await l$(Z.cardId);let U=await W$(Z.cardId,O.agyStats,t2(yY($,Z,Y,V,{code:J,signal:Q}))),R=await W$(Z.cardId,O.agyResult,f4({status:Y,stdout:Z.stdout,stderr:H,notice:W,cardTruncated:L})),D=await W$(Z.cardId,O.agyForward,J5(F,$.backendLabel())),P=await W$(Z.cardId,O.agyRepo,h4({before:Z.beforeGit,after:X}));X$(Z.cardId);let M=await B$(Z.cardId,i$({durationSec:CY(Z,V),suffix:Y}));if(!U||!R||!D||!P||!M)throw Error([`stats=${U?"ok":"MISS"}`,`result=${R?"ok":"MISS"}`,`forward=${D?"ok":"MISS"}`,`repo=${P?"ok":"MISS"}`,`settings=${M?"ok":"MISS"}`].join(", "));await b$(Z.cardId)}catch(V){Y=`❌ agy 收尾失败: ${j(V)}`,K(`session "${$.sessionName}": ${Y}`),await C($.chatId,Y)}finally{if($.runningAgy===Z)$.runningAgy=null,$.status=$.isRunning()?"idle":"stopped",$.opts.onLifecycleChange?.();K(`session "${$.sessionName}": agy finished status=${Y} code=${J} signal=${Q} stdout=${Z.stdoutBytes} stderr=${Z.stderrBytes}`),Z.resolveDone()}}var rq=1e6,aq=5000,TY=8000,xY=2000,tq=30000;var vY=T(()=>{a0();n$();n();v();E5()});import{isAbsolute as Y_}from"node:path";function L$($){if($?.planLiveInserted)return O.planLive;return $?.taskLiveInserted?O.taskBoardLive:O.footer}function V_($){return $==="ImageGeneration"||$==="imageGeneration"}function X_($,Z,J){if(J||!V_($))return null;let Q=r4(Z.trim());return Y_(Q)?Q:null}function H_($){if($==="Read")return"read";if($==="Edit"||$==="MultiEdit"||$==="NotebookEdit")return"edit";return null}function fY($,Z,J){return $==="read"?u1(Z,J):c1(Z,J)}function hY($,Z,J,Q){if(!$.currentTurn)return;if($.maybeMidTurnRotate(),$.startWorkingFooter($.currentTurn),$.currentTurn.currentAssistantSegmentId)$.finalizeCurrentAssistantSegment();let Y=H_(J);if(Y&&$.currentTurn.openBatchI!==null){let W=$.currentTurn.openBatchI,z=$.currentTurn.toolBatches.get(W);if(z&&z.kind===Y){let G=z.items.length;z.items.push({toolUseId:Z,input:Q,output:null,isError:!1}),$.currentTurn.toolByUseId.set(Z,{i:W,name:J,input:Q,batchSlot:G});let q=Y==="read"?u1(W,z.items):c1(W,z.items);u($.currentTurn.cardId,O.tool(W),q),$Z($.currentTurn,J,Q);return}}if(!Y)$.currentTurn.openBatchI=null;let V=Z1(J);if(V){let W=$.currentTurn;if(V==="TaskCreate"&&!W.taskBoardResetThisTurn)$.taskBoard=[],W.taskBoardResetThisTurn=!0;if(!W.taskLiveInserted)W.taskLiveInserted=!0,H$(W.cardId,J1($.taskBoard),{type:"insert_before",targetElementId:O.footer});else u(W.cardId,O.taskBoardLive,J1($.taskBoard));let z=V==="TaskCreate";if(z)W.taskUpdateI=null;else W.taskCreateI=null;let G=(z?W.taskCreateI:W.taskUpdateI)===null;if(G)if(z)W.taskCreateI=W.toolCount++;else W.taskUpdateI=W.toolCount++;let q=z?W.taskCreateI:W.taskUpdateI;W.toolByUseId.set(Z,{i:q,name:J,input:Q});let B=S0(q,$.taskBoard,{name:V,status:"⏳"});G?H$(W.cardId,B,{type:"insert_before",targetElementId:L$(W)}):u(W.cardId,O.tool(q),B),$Z(W,J,Q);return}$.currentTurn.taskCreateI=null,$.currentTurn.taskUpdateI=null;let X=$.currentTurn.toolCount++;if(Y){$.currentTurn.openBatchI=X;let W=[{toolUseId:Z,input:Q,output:null,isError:!1}];$.currentTurn.toolBatches.set(X,{kind:Y,items:W}),$.currentTurn.toolByUseId.set(Z,{i:X,name:J,input:Q,batchSlot:0});let z=Y==="read"?u1(X,W):c1(X,W);H$($.currentTurn.cardId,z,{type:"insert_before",targetElementId:L$($.currentTurn)}),$Z($.currentTurn,J,Q);return}if($.currentTurn.toolByUseId.set(Z,{i:X,name:J,input:Q}),J==="AskUserQuestion"){let W=Array.isArray(Q?.questions)?Q.questions:[],z=W.length>0?0:void 0,G=new Map;$.pendingAsks.set(Z,{questions:W,i:X,answers:{},answered:G,currentIdx:z});let q=d2(X,Z,W,"\uD83E\uDD14",{currentIdx:z,answered:G});if(H$($.currentTurn.cardId,q,{type:"insert_before",targetElementId:L$($.currentTurn)}),$.currentTurn.userOpenId&&$.currentTurn.messageId){let B=$.currentTurn,L=W[0]?.question?.trim()??"",F=L.length>40?L.slice(0,40)+"…":L,U=W.length>1?`❓ 待回答 ${W.length} 题${F?`: ${F}`:""}`:F?`❓ ${F}`:"❓ 等你回答问题";(async()=>{X$(B.cardId),await Y4(B.cardId,{config:{summary:{content:U}}}),await n0(B.messageId,[B.userOpenId])})()}return}let H=F0(X,J,Q,null,"⏳");H$($.currentTurn.cardId,H,{type:"insert_before",targetElementId:L$($.currentTurn)}),$Z($.currentTurn,J,Q)}function $Z($,Z,J){if(!$)return;let Q=L0(Z,J),Y=Q.length>80?Q.slice(0,80)+"…":Q,V=t0(Z),X=Y?`\uD83D\uDD27 ${V}: ${Y}`:`\uD83D\uDD27 ${V}`;r0($.cardId,X)}function IY($,Z,J,Q){if(!$.currentTurn)return;let Y=$.currentTurn.toolByUseId.get(Z);if(!Y)return;let V=typeof J==="string"?J:Array.isArray(J)?J.map((z)=>z?.text??JSON.stringify(z)).join(`
|
|
159
|
+
`):JSON.stringify(J);Y.output=V,Y.isError=Q;let X=X_(Y.name,V,Q);if(X)$.sendOutboundPath(X,Y.name);if(Y.name==="AskUserQuestion"){ZZ($);return}if(Y.batchSlot!=null){let z=$.currentTurn.toolBatches.get(Y.i);if(z){let G=z.items[Y.batchSlot];if(G)G.output=V,G.isError=Q;let q=fY(z.kind,Y.i,z.items);u($.currentTurn.cardId,O.tool(Y.i),q)}ZZ($);return}let H=Z1(Y.name);if(H){W_($,Y,H,Y.input,V,Q,Y.resolvedNote);return}let W=F0(Y.i,Y.name,Y.input,V,Q?"❌":"✅",Y.resolvedNote);u($.currentTurn.cardId,O.tool(Y.i),W),ZZ($)}function W_($,Z,J,Q,Y,V,X){if(!$.currentTurn)return;if(!V)$.taskBoard=W5($.taskBoard,J,Q,Y);let H=S0(Z.i,$.taskBoard,{name:J,status:V?"❌":"✅"},X);if(u($.currentTurn.cardId,O.tool(Z.i),H),$.currentTurn.taskLiveInserted)u($.currentTurn.cardId,O.taskBoardLive,J1($.taskBoard));ZZ($)}function ZZ($){let Z=$.currentTurn;if(!Z)return;for(let J of Z.toolByUseId.values())if(J.output==null)return;$.startThinkingFooter(Z)}function x5($,Z,J,Q,Y){let V=$.currentTurn;if(!V)return;for(let[X,H]of Q){if(V.toolByUseId.has(X))continue;let W=H.batchSlot??null,z=H.input,G,q;if(W!=null){let D=Y.get(H.i)?.items[W];if(!D)continue;z=D.input,G=D.output,q=D.isError}else G=H.output??null,q=H.isError??!1;let B=G!=null,L=I1(Z,O.tool(H.i));if(B&&!L)continue;if(W!=null){let D=Y.get(H.i)?.kind;if(!D)continue;let P=V.toolCount++,M={toolUseId:X,input:z,output:G,isError:q};V.toolBatches.set(P,{kind:D,items:[M]}),V.toolByUseId.set(X,{...H,i:P,batchSlot:0}),H$(J,fY(D,P,[M]),{type:"insert_before",targetElementId:L$(V)});continue}let F=Z1(H.name);if(F){let D=F==="TaskCreate";if(D)V.taskUpdateI=null;else V.taskCreateI=null;let P=(D?V.taskCreateI:V.taskUpdateI)===null;if(P)if(D)V.taskCreateI=V.toolCount++;else V.taskUpdateI=V.toolCount++;let M=D?V.taskCreateI:V.taskUpdateI;V.toolByUseId.set(X,{...H,i:M});let x=!B?"⏳":q?"❌":"✅",y=S0(M,$.taskBoard,{name:F,status:x},H.resolvedNote);P?H$(J,y,{type:"insert_before",targetElementId:L$(V)}):u(J,O.tool(M),y);continue}let U=V.toolCount++;V.toolByUseId.set(X,{...H,i:U});let R=!B?"⏳":q?"❌":"✅";H$(J,F0(U,H.name,H.input,G,R,H.resolvedNote),{type:"insert_before",targetElementId:L$(V)})}}var gY=T(()=>{L5();a0();n$();n()});function mY($){return $.pendingAsks.size>0}async function cY($,Z,J,Q){let Y=$.pendingAsks.entries().next();if(Y.done){K(`session "${$.sessionName}": onAskMessageAnswer with no pending — falling back to onUserMessage`),await $.onUserMessage(Z,[],J,Q);return}let[V,X]=Y.value;if(X.currentIdx===void 0){if(X.requestId){K(`session "${$.sessionName}": pending ask ${V} awaiting finalize — ignoring message`);return}K(`session "${$.sessionName}": pending ask ${V} orphaned (no can_use_tool) — dropping zombie, reprocessing as user message`),$.pendingAsks.delete(V),await $.onUserMessage(Z,[],J,Q);return}if(await C5($,V,X.currentIdx,Z,J)&&Q)R$(Q,"CheckMark")}async function uY($,Z,J,Q,Y){let V=$.pendingAsks.get(Z);if(!V)return K(`session "${$.sessionName}": stray ask answer for ${Z}`),!1;if(J!==V.currentIdx)return K(`session "${$.sessionName}": stale ask click q=${J} current=${V.currentIdx}`),!1;return pY($,Z,{optionIdx:Q,user:Y})}async function C5($,Z,J,Q,Y){let V=$.pendingAsks.get(Z);if(!V)return K(`session "${$.sessionName}": stray ask custom for ${Z}`),!1;let X=(Q??"").trim();if(!X)return K(`session "${$.sessionName}": empty custom answer, ignoring`),!1;if(J!==V.currentIdx)return K(`session "${$.sessionName}": stale ask custom q=${J} current=${V.currentIdx}`),!1;return pY($,Z,{customText:X,user:Y})}function pY($,Z,J){let Q=$.pendingAsks.get(Z);if(!Q||Q.currentIdx===void 0)return!1;let Y=Q.currentIdx,V=Q.questions[Y];if(!V)return K(`session "${$.sessionName}": advanceAsk currentIdx=${Y} out of range`),!1;let X;if(J.customText!==void 0)X=J.customText;else if(J.optionIdx!==void 0){let q=V.options?.[J.optionIdx];if(!q)return K(`session "${$.sessionName}": advanceAsk option ${J.optionIdx} out of range`),!1;X=q.label}else return K(`session "${$.sessionName}": advanceAsk with neither customText nor optionIdx`),!1;Q.answers[V.question]=X,Q.answered.set(Y,{optionIdx:J.optionIdx,customText:J.customText,user:J.user});let H=Q.questions.length,W=void 0;for(let q=Y+1;q<H;q++)if(!Q.answered.has(q)){W=q;break}Q.currentIdx=W;let z=$.currentTurn,G=z?.toolByUseId.get(Z);if(z&&G){let q=d2(G.i,Z,Q.questions,W===void 0?"✅":"\uD83E\uDD14",{currentIdx:W,answered:Q.answered});u(z.cardId,O.tool(G.i),q)}if(W===void 0)if(Q.requestId)N5($,Z);else K(`session "${$.sessionName}": ask ${Z} all answered, waiting for can_use_tool`);return!0}function N5($,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 y5=T(()=>{a0();n$();n();v()});async function lY($,Z,J,Q){let Y=$.pendingPermissions.get(Z);if(!Y)return K(`session "${$.sessionName}": stray permission ${Z}`),{ok:!1,message:"此权限请求已失效或已处理"};let V=$.proc;if(!V)return K(`session "${$.sessionName}": permission ${Z} has no active process`),{ok:!1,message:"后端进程已退出,权限决定未送达"};let X=J==="deny"?"deny":"allow";try{V.sendPermissionResponse(Z,X,J==="allow_always"?{updatedPermissions:Y.permissionSuggestions}:void 0)}catch(z){return K(`session "${$.sessionName}": permission response ${Z} failed: ${z}`),{ok:!1,message:`权限决定发送失败: ${z instanceof Error?z.message:z}`}}$.pendingPermissions.delete(Z);let H=$.currentTurn,W=H?.toolByUseId.get(Y.toolUseId);if(H&&W){let z=Z1(W.name);if(J==="deny"){let G=`\uD83D\uDEAB 已拒绝 by ${Q||"匿名"}`,q=z?S0(W.i,$.taskBoard,{name:z,status:"❌"},G):F0(W.i,W.name,W.input,G,"❌");u(H.cardId,O.tool(W.i),q)}else{let G=J==="allow_always"?"始终允许":"已允许";W.resolvedNote=`✅ **${G}** by ${Q||"匿名"}`;let q=z?S0(W.i,$.taskBoard,{name:z,status:"⏳"},W.resolvedNote):F0(W.i,W.name,W.input,null,"⏳",W.resolvedNote);u(H.cardId,O.tool(W.i),q)}}if(K(`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 dY($,Z){let J=$.currentTurn;if(!J){K(`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){K(`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){K(`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 X=$.pendingAsks.get(Q);if(!X){K(`session "${$.sessionName}": AskUserQuestion ${Q} missing pendingAsk — deny`),$.proc?.sendPermissionResponse(Z.request_id,"deny",{denyMessage:"no pending ask"});return}if(X.requestId=Z.request_id,$.pendingPermissions.set(Z.request_id,{toolUseId:Q}),X.currentIdx===void 0)N5($,Q);return}$.status="awaiting_permission",$.pendingPermissions.set(Z.request_id,{toolUseId:Q,permissionSuggestions:Z.permission_suggestions}),K(`session "${$.sessionName}": can_use_tool request=${Z.request_id} tool_use_id=${Q} tool=${Y.name}`);let V=M4(Y.i,Y.name,Y.input,Z.request_id);if(u(J.cardId,O.tool(Y.i),V),J.userOpenId&&J.messageId){let X=L0(Y.name,Y.input),H=t0(Y.name),W=X&&X.length>30?X.slice(0,30)+"…":X,z=W?`\uD83D\uDD10 等审批: ${H} · ${W}`:`\uD83D\uDD10 等审批: ${H}`;(async()=>{X$(J.cardId),await Y4(J.cardId,{config:{summary:{content:z}}}),await n0(J.messageId,[J.userOpenId])})()}}var iY=T(()=>{a0();n$();n();v();y5()});function nY($,Z=rY){return new Promise((J,Q)=>{let Y=setTimeout(()=>Q(Error(`timeout ${Z}ms`)),Z);$.then((V)=>{clearTimeout(Y),J(V)},(V)=>{clearTimeout(Y),Q(V)})})}function oY($){return typeof $==="string"&&q_.includes($)?$:null}async function aY(){let $=new l4;try{await nY($.request("initialize",{clientInfo:{name:"lodestar-models",version:"0.0.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}));let Z=await nY($.request("model/list",{})),J=Array.isArray(Z?.data)?Z.data:[],Q=[];for(let Y of J){if(!Y||Y.hidden||!Y.id)continue;let V=(Array.isArray(Y.supportedReasoningEfforts)?Y.supportedReasoningEfforts:[]).map((H)=>oY(H?.reasoningEffort)).filter((H)=>H!==null);if(!V.length)continue;let X=oY(Y.defaultReasoningEffort)??V[0];Q.push({model:String(Y.id),display:typeof Y.displayName==="string"&&Y.displayName?String(Y.displayName):String(Y.id),efforts:V,defaultEffort:X})}return Q}finally{await $.close()}}async function tY($,Z){let J=new URL($),Q=J.pathname.replace(/\/+$/,""),Y=`${J.protocol}//${J.host}${Q}/v1/models`,V=await fetch(Y,{headers:{Authorization:`Bearer ${Z}`},signal:AbortSignal.timeout(rY)});if(!V.ok)throw Error(`HTTP ${V.status}`);let X=await V.json();return(Array.isArray(X?.data)?X.data:[]).filter((W)=>W&&(W.display_name||W.id)).map((W)=>{let z=String(W.display_name||W.id);return{model:z,display:z,efforts:o$,defaultEffort:"max"}})}var rY=1e4,q_,o$;var X8=T(()=>{i4();q_=["none","minimal","low","medium","high","xhigh","max","ultra"];o$=["max","xhigh","high","medium","low"]});import{existsSync as __}from"node:fs";import{homedir as B_}from"node:os";import{join as sY}from"node:path";function JZ($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function L_($){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(JZ($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push(JZ($.weekly,"weekly","周配额"));return{state:"ok",planLabel:$.subscriptionType,windows:Z,fetchedAt:$.fetchedAt}}function F_($){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(JZ(J.fiveHour,"fiveHour",`${Q} 5h`));if(J.weekly)Z.push(JZ(J.weekly,"weekly",`${Q} 周`))}return Z.length?Z:null}function U_(){let $=process.env.CODEX_HOME||sY(B_(),".codex");return __(sY($,"auth.json"))}var eY=T(()=>{N$();k$();i4();X8();v();z0({kind:"codex-subscription",configSectionId:"codex-sub",build:($)=>{let Z=U_(),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:[],defaultModel:J??"",async refreshModels(){if(!Y.enabled){Y.models=[];return}try{if(Y.models=await aY(),Q)for(let V of Y.models)V.defaultEffort=Q;if(!J)Y.defaultModel=Y.models[0]?.model??""}catch(V){K(`codex-sub refreshModels MISS: ${V?.message??V}`),Y.models=[]}},spawnEnv(V){let X=g0(V);return Object.assign(X,f.codex.env),X},resolveSpawnModel(V){return V},async readUsage(){let V=await d4(),X=L_(V),H=F_(V);if(H)X.windows=H;return X}};return Y}})});function P_($){let Z=new URL($),J=Z.pathname.replace(/\/+$/,"");return`${Z.protocol}//${Z.host}${J}/v1/messages`}async function QZ($,Z,J){try{let Q=await fetch(P_($),{method:"POST",headers:{"Content-Type":"application/json",...Z},body:JSON.stringify({model:J,max_tokens:1,messages:[{role:"user",content:"hi"}]}),signal:AbortSignal.timeout(D_)});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 K(`model-existence: ${J} HTTP ${Q.status}, no verdict`),"no_verdict"}catch(Q){return K(`model-existence: ${J} MISS (${Q?.message??Q})`),"no_verdict"}}var D_=15000;var S5=T(()=>{v()});function $V($,Z,J){return{kind:Z,label:J,percent:$.percent,resetsAt:$.resetsAt}}function A_($){return{kind:"monthly",label:"月度工具",percent:$.percent,resetsAt:$.resetsAt,...$.used!=null?{used:$.used}:{},...$.total!=null?{total:$.total}:{}}}function M_($){return($??"").split(",").map((Z)=>Z.trim()).filter(Boolean)}function O_($){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 j_($){let Z={};for(let J of($??"").split(",")){let Q=J.indexOf("=");if(Q<=0)continue;let Y=J.slice(0,Q).trim().toLowerCase(),V=J.slice(Q+1).trim();if((Y==="opus"||Y==="sonnet"||Y==="haiku")&&V)Z[Y]=V}return Z}function R_($){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($V($.fiveHour,"fiveHour","5h 窗口"));if($.weekly)Z.push($V($.weekly,"weekly","周额度"));if($.monthly)Z.push(A_($.monthly));return{state:"ok",planLabel:$.level?`${$.level} 套餐`:void 0,windows:Z,fetchedAt:$.fetchedAt}}var ZV=T(()=>{k$();o4();X8();u8();S5();v();z0({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)&&n4(J),V=$.model?.trim()||void 0,X=j_($.slots),H={id:"glm",kind:"glm-coding-plan",agent:"claude",display:$.display?.trim()||"GLM Coding Plan",enabled:Y,models:[],defaultModel:V??"",async refreshModels(){if(!H.enabled){H.models=[];return}try{let W=await tY(J,Q),G=M_($.models).filter((q)=>!W.some((B)=>B.model.toLowerCase()===q.toLowerCase())).map((q)=>({model:q,display:q,efforts:o$,defaultEffort:"max"}));if(H.models=[...W,...G],!V)H.defaultModel=O_(H.models.map((q)=>q.model));for(let q of H.models){let B=c8("glm",q.model);q.context1m=B!=null&&B>=1e6||void 0}}catch(W){K(`glm refreshModels MISS: ${W?.message??W}`),H.models=[]}},spawnEnv(W){let G={...g0(W)};if(G.ANTHROPIC_BASE_URL=J,G.ANTHROPIC_AUTH_TOKEN=Q,X.opus)G.ANTHROPIC_DEFAULT_OPUS_MODEL=X.opus;if(X.sonnet)G.ANTHROPIC_DEFAULT_SONNET_MODEL=X.sonnet;if(X.haiku)G.ANTHROPIC_DEFAULT_HAIKU_MODEL=X.haiku;return G},resolveSpawnModel(W){return m8("glm",W)},async verifyModel(W){return QZ(J,{Authorization:`Bearer ${Q}`},W)},async readUsage(){return R_(await _5(J,Q))}};return H},setup:{commandSuffix:"glm",hint:($)=>`启用 ${$}:发送
|
|
159
160
|
\`\`\`
|
|
160
161
|
glm-setup <base_url> <token>
|
|
161
|
-
\`\`\``,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(!
|
|
162
|
+
\`\`\``,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(!n4(Z))return null;let J=$.ANTHROPIC_AUTH_TOKEN?.trim()??"";return J?{base_url:Z,auth_token:J}:null}}})});var JV;var QV=T(()=>{k$();X8();JV=[{model:"fable",display:"Fable",efforts:o$,defaultEffort:"max"},{model:"opus",display:"Opus",efforts:o$,defaultEffort:"high"},{model:"sonnet",display:"Sonnet",efforts:o$,defaultEffort:"medium"},{model:"haiku",display:"Haiku",efforts:o$,defaultEffort:"medium"}];z0({kind:"claude-native",build:($)=>{let Z={id:"claude-native",kind:"claude-native",agent:"claude",display:"Claude",enabled:!1,models:JV,defaultModel:"opus",settingSources:["user","project","local"],async refreshModels(){Z.models=JV},spawnEnv(J){return J},resolveSpawnModel(J){return J},async readUsage(){return{state:"not_applicable",windows:[]}}};return Z}})});function T_($){return($??"").split(",").map((Z)=>Z.trim()).filter(Boolean)}function x_($){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 C_($){let Z={};for(let J of($??"").split(",")){let Q=J.indexOf("=");if(Q<=0)continue;let Y=J.slice(0,Q).trim().toLowerCase(),V=J.slice(Q+1).trim();if((Y==="opus"||Y==="sonnet"||Y==="haiku")&&V)Z[Y]=V}return Z}function N_($){try{return new URL($).hostname.toLowerCase()==="api.deepseek.com"}catch{return!1}}async function y_($,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((X)=>X&&typeof X.id==="string"&&X.id).map((X)=>({model:X.id,display:X.id,efforts:o$,defaultEffort:"high"}))}async function k_($,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(S_)});if(!Q.ok)return{state:"network",windows:[],reason:`HTTP ${Q.status}`};let Y=await Q.json(),X=(Array.isArray(Y?.balance_infos)?Y.balance_infos:[])[0],H=typeof X?.currency==="string"?X.currency:"",W=H==="CNY"?"¥":H==="USD"?"$":H?`${H} `:"",z=X?.total_balance;if(typeof z!=="string"&&typeof z!=="number")return{state:"ok",windows:[],planLabel:"余额 —(无明细)"};let G=Y?.is_available!==!1;return{state:"ok",windows:[],planLabel:G?`剩余 ${W}${z}`:`⚠️ 余额不足 ${W}${z}`}}catch(Q){return K(`deepseek readUsage MISS: ${Q?.message??Q}`),{state:"network",windows:[],reason:Q?.message??String(Q)}}}var E_="https://api.deepseek.com/anthropic",S_=1e4;var YV=T(()=>{k$();X8();u8();S5();v();z0({kind:"deepseek",configSectionId:"deepseek",build:($,Z)=>{let J=$.base_url?.trim()||Z?.base_url?.trim()||E_,Q=$.api_key?.trim()||Z?.api_key?.trim()||"",Y=!!Q,V=$.model?.trim()||void 0,X=C_($.slots),H={id:"deepseek",kind:"deepseek",agent:"claude",display:$.display?.trim()||"DeepSeek",enabled:Y,models:[],defaultModel:V??"",async refreshModels(){if(!H.enabled){H.models=[];return}try{let W=await y_(J,Q),G=T_($.models).filter((q)=>!W.some((B)=>B.model.toLowerCase()===q.toLowerCase())).map((q)=>({model:q,display:q,efforts:o$,defaultEffort:"high"}));if(H.models=[...W,...G],!V)H.defaultModel=x_(H.models.map((q)=>q.model));for(let q of H.models){let B=c8("deepseek",q.model);q.context1m=B!=null&&B>=1e6||void 0}}catch(W){K(`deepseek refreshModels MISS: ${W?.message??W}`),H.models=[]}},spawnEnv(W){let G={...g0(W)};if(G.ANTHROPIC_BASE_URL=J,G.ANTHROPIC_API_KEY=Q,X.opus)G.ANTHROPIC_DEFAULT_OPUS_MODEL=X.opus;if(X.sonnet)G.ANTHROPIC_DEFAULT_SONNET_MODEL=X.sonnet;if(X.haiku)G.ANTHROPIC_DEFAULT_HAIKU_MODEL=X.haiku;return G},resolveSpawnModel(W){return m8("deepseek",W)},async verifyModel(W){return QZ(J,{"x-api-key":Q},W)},async readUsage(){if(!Q)return{state:"no_credentials",windows:[]};return k_(J,Q)}};return H},setup:{commandSuffix:"deepseek",hint:($)=>`启用 ${$}:发送
|
|
162
163
|
\`\`\`
|
|
163
164
|
deepseek-setup <api_key>
|
|
164
165
|
\`\`\`
|
|
165
|
-
默认官方 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(!
|
|
166
|
-
`)}function
|
|
167
|
-
`),V=!1,X={},
|
|
166
|
+
默认官方 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(!N_(Z))return null;let J=$.ANTHROPIC_API_KEY?.trim()??"";return J?{base_url:Z,api_key:J}:null}}})});var XV={};q2(XV,{tokenSourceSpawnRevision:()=>VV,buildTokenSourcesFromConfig:()=>k5});import{createHash as w_}from"node:crypto";function k5(){M6();let $=q5(),Z=N1().map((V)=>{let X=V.configSectionId?(f.token_sources??{})[V.configSectionId]??{}:{},H=V.detect?.fromSettingsEnv($)??null,W=V.build(X,H);return W.spawnRevision=VV(V.kind,X,H),W}),J=Z.find((V)=>V.kind==="claude-native");if(J){let V=Z.some((X)=>X.agent==="claude"&&X.enabled&&X.kind!=="claude-native");J.enabled=!V}for(let V of Z)P6(V);let Y=Z.find((V)=>V.enabled&&f.token_sources?.[V.id]?.default===!0)??Z.find((V)=>V.enabled);if(Y)A6(Y.id);return Z.length}function VV($,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 w_("sha256").update(JSON.stringify({kind:$,configured:Q(Z),detected:Q(J)})).digest("hex")}var w5=T(()=>{N$();k$();o4();eY();ZV();QV();YV()});import{readFileSync as b_}from"node:fs";function v_($){return $.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}function f_($,Z){let J=[`[token_source.${$}]`],Q=(Y,V)=>{if(V&&V.length)J.push(`${Y} = "${v_(V)}"`)};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(`
|
|
167
|
+
`)}function h_(){d3(),k5(),m0()}function YZ($,Z){let J=b_(U$,"utf8"),Q=`[token_source.${$}]`,Y=J.split(`
|
|
168
|
+
`),V=!1,X={},H=[];for(let q of Y){let B=q.match(/^\s*(\[[^\]]+\])\s*(?:#.*)?$/)?.[1];if(B)V=B===Q;if(V){let L=q.match(/^\s*([A-Za-z_]+)\s*=\s*"([^"]*)"/);if(L)X[L[1]]=L[2]}else H.push(q)}let W={...X},z={...Z};for(let q of Object.keys(z))if(z[q])W[q]=z[q];let G=W;while(H.length&&H[H.length-1]==="")H.pop();P1(U$,H.join(`
|
|
168
169
|
`)+`
|
|
169
170
|
|
|
170
|
-
`+
|
|
171
|
-
`),
|
|
172
|
-
⚠️ kill 状态卡片终态写入失败: ${
|
|
173
|
-
请重新发送 model 打开面板。`;if(!await C($.chatId,
|
|
174
|
-
`),
|
|
175
|
-
`)});import{execFileSync as
|
|
176
|
-
`).map((V)=>V.trim()).filter(Boolean).filter((V)=>V.startsWith(
|
|
177
|
-
`).filter(Boolean);L.statusLine=
|
|
178
|
-
`).filter(Boolean);if(
|
|
171
|
+
`+f_($,G)+`
|
|
172
|
+
`),h_()}var b5=T(()=>{m$();N$();w5();k$();f0()});var v5={};q2(v5,{runTokenSourceSetup:()=>g_,onTokenSourceEnable:()=>I_});async function I_($,Z){let J=Y$(Z);if(!J){await E($.chatId,`❌ 未知 token source: ${Z}`);return}if(J.enabled){await E($.chatId,`${J.display} 已启用,发 \`model\` 选择。`);return}let Q=N1().find((Y)=>Y.setup?.commandSuffix===Z||Y.configSectionId===Z);if(Q?.setup)await E($.chatId,Q.setup.hint(J.display));else if(J.kind==="codex-subscription")await E($.chatId,`${J.display} 需要 ChatGPT 登录:在服务器执行 \`codex login\`,完成后按当前服务管理方式重启 daemon,或重发 \`model\` 刷新。`);else if(J.kind==="claude-native")await E($.chatId,`${J.display} 直接使用本机 Claude Code 配置,无需单独启用。`)}async function g_($,Z,J){let Q=N1().find((V)=>V.setup?.commandSuffix===Z);if(!Q?.setup||!Q.configSectionId){await E($.chatId,`❌ 未知或不可配置的 source: ${Z}`);return}let Y=Q.setup.parseArgs(J);if("error"in Y){await E($.chatId,Y.error);return}try{YZ(Q.configSectionId,Y.config),await m0();let V=Y$(Q.configSectionId);await E($.chatId,`✅ ${V?.display??Z} 已启用。发 \`model\` 重新选择。`)}catch(V){await E($.chatId,`❌ 启用失败: ${V?.message??V}`)}}var f5=T(()=>{n();k$();b5()});async function HV($,Z,J=""){let Q=Z.trim().match(/^(?:wt|worktree)(?:\s+(.+))?$/i);if(Q){if($.startingAgy||$.runningAgy)return await E($.chatId,"⏳ agy 任务正在执行;请等待完成,或发送 stop 打断后再使用 wt。"),!0;return await $.runWorktreeCommand((Q[1]??"").trim(),J),!0}if(Z.trim().match(/^btw$/i)){if($.startingAgy||$.runningAgy)return await E($.chatId,"⏳ agy 任务正在执行;请等待完成,或发送 stop 打断后再使用 btw。"),!0;return await $.runBtwCommand(J),!0}if(Z.trim().match(/^bye$/i))return await $.runByeCommand(),!0;if(Z.trim().match(/^(?:fk|fork)$/i)){if($.startingAgy||$.runningAgy)return await E($.chatId,"⏳ agy 任务正在执行;请等待完成,或发送 stop 打断后再使用 fk。"),!0;return await $.showForkList(J),!0}if(Z.trim().match(/^(?:bk|back)$/i)){if($.startingAgy||$.runningAgy)return await E($.chatId,"⏳ agy 任务正在执行;请等待完成,或发送 stop 打断后再使用 bk。"),!0;return await $.showBackList(J),!0}let Y=Z.trim().match(/^agy(?:\s+([\s\S]+))?$/i);if(Y)return await $.runAgyCommand((Y[1]??"").trim()),!0;if(Z.trim().toLowerCase()==="task")return await $.showTasklistPanel(),!0;let V=Z.trim().match(/^(\w+)-setup\s+([\s\S]+)$/i);if(V){let{runTokenSourceSetup:H}=await Promise.resolve().then(() => (f5(),v5));return await H($,V[1].trim(),V[2].trim()),!0}let X=m_.get(Z.trim().toLowerCase());if(!X)return!1;if(($.startingAgy||$.runningAgy)&&!["stop","kill","restart","hi","model"].includes(X))return await E($.chatId,`⏳ agy 任务正在执行;请等待完成,或发送 stop 打断后再执行 ${X}。`),!0;switch(X){case"model":return await $.showModelPanel(),!0;case"compact":return await $.runCompactCommand(),!0;case"hi":{let W=!$.isRunning(),z=$.backendLabel(),G=W?await $.openStatusCard("hi",$.withModel(`\uD83D\uDE80 启动 ${z}`)):null,q=$.withModel(`\uD83D\uDE80 启动 ${z}`);if(!(W?await $.start({announce:!G,onStatus:(L)=>{q=L,$.setStatusCard(G,L)}}):!0))return await $.closeStatusCard(G,q.startsWith("❌")?q:"❌ 启动失败"),!0;if(G)return await $.replaceStatusCardWithConsole(G,$.withModel($.withWorktreeInstructionNotice(`✅ ${$.backendLabel()} 已就绪`))),!0;if(W)await $.closeStatusCard(G,$.withModel($.withWorktreeInstructionNotice(`✅ ${$.backendLabel()} 已就绪`)))}return await $.showConsole(),!0;case"stop":if($.runningAgy)return await $.stopAgyTask("\uD83D\uDED1 agy 已打断"),!0;if($.clearStaleIdleQueueState("stop"),$.clearMultiMsgBuffer("stop command"),!$.currentTurn&&$.pendingUserMessageCount===0&&$.pendingMidTurnMsgs.length===0){let W=await $.openStatusCard("stop","⚪ 当前没有正在执行的 turn","grey");if(W)await $.closeStatusCard(W,"⚪ 无正在执行的 turn");else await E($.chatId,"⚪ 当前没有正在执行的 turn");return!0}K(`session "${$.sessionName}": stop command — interrupt + drop count=${$.pendingUserMessageCount} midBuffer=${$.pendingMidTurnMsgs.length}`);let H=new Set;for(let[W,z]of[...$.pendingReactionIds.entries(),...$.currentBatchReactionIds.entries()]){if(z)P$(W,z);R$(W,"CrossMark"),H.add(W)}for(let W of $.pendingMidTurnMsgs)if(W.msgId&&!H.has(W.msgId))R$(W.msgId,"CrossMark");return $.pendingUserMessageCount=0,$.pendingMidTurnMsgs=[],$.pendingTurnInputs=[],$.lastUserOpenId="",$.pendingReactionIds=new Map,$.currentBatchReactionIds=new Map,$.userInterrupted=!0,$.interrupt(),await $.closeTurnCard("\uD83D\uDED1 打断"),!0;case"kill":{if($.runningAgy)await $.stopAgyTask("\uD83D\uDED1 agy 已终止");let W=$.isRunning(),z=$.backendLabel($.proc?.provider??$.currentProvider()),G=W?`\uD83D\uDED1 停止 ${z}`:"⚪ session 当前未运行",q=await $.openStatusCard("kill",G,W?"red":"grey"),B=null,L=W?`✅ ${z} 已终止`:`⚪ ${z} 未运行`;try{await $.stop("已终止",{announce:!q,onStatus:(F)=>{$.setStatusCard(q,F)}})}catch(F){B=F,L=$.isRunning()?`❌ ${z} 未确认终止: ${j(F)};会话已阻断,请重试 kill/restart 或等待旧进程退出`:`❌ ${z} 停止收尾失败: ${j(F)}`}finally{try{await $.closeStatusCard(q,L)}catch(F){K(`session "${$.sessionName}": kill status card close failed: ${j(F)}`),await C($.chatId,`${L}
|
|
173
|
+
⚠️ kill 状态卡片终态写入失败: ${j(F)}`)}}if(B&&!q)await C($.chatId,L)}return!0;case"restart":if(!$.isRunning())return await $.showResumeList(J),!0;{let W=$.lastSessionId?z$($.lastSessionId):"",z=$.backendLabel($.proc?.provider??$.currentProvider()),G=$.isRunning()?$.withModel(`\uD83D\uDD01 重启 ${z}`):W?$.withModel(`\uD83D\uDD01 恢复上一会话 thread=${W}`):$.withModel(`\uD83D\uDD01 启动 ${z}`),q=await $.openStatusCard("restart",G);if($.runningAgy)$.setStatusCard(q,"\uD83D\uDED1 restart 前终止 agy"),await $.stopAgyTask("\uD83D\uDED1 restart 前已终止 agy");let B=G,L=await $.restart(!0,{announce:!q,onStatus:(U)=>{B=U,$.setStatusCard(q,U)}}),F=L?B.startsWith("✅")?B:$.withWorktreeInstructionNotice(W?"✅ 已恢复上一会话":`✅ ${$.backendLabel()} 已就绪`):B.startsWith("❌")?B:"❌ 重启失败";await $.closeStatusCard(q,L?$.withModel(F):F)}return!0;case"clear":if(!$.isRunning()){$.status="stopped",$.opts.onLifecycleChange?.();let W=await $.openStatusCard("clear","⚪ session 当前未运行","grey");if(W)await $.closeStatusCard(W,`⚪ ${$.backendLabel()} 未运行,clear 无效`);else await E($.chatId,`⚪ session "${$.sessionName}" 当前未运行,clear 无效;用 \`hi\` 启动或 \`restart\` 恢复上一会话`);return!0}{let W=await $.openStatusCard("clear","\uD83E\uDDF9 清空并启动新会话","orange"),z="\uD83E\uDDF9 清空并启动新会话",G=await $.restart(!1,{announce:!W,onStatus:(q)=>{z=q,$.setStatusCard(W,q)}});await $.closeStatusCard(W,G?$.withModel($.withWorktreeInstructionNotice("✅ 已清空并启动新会话")):z.startsWith("❌")?z:"❌ 清空失败")}return!0}}var m_;var WV=T(()=>{n();v();m_=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 l_($,Z){let J=!1,Q=null,Y=()=>{},V=()=>{},X=$.sessionId,H=()=>{if(Q)clearTimeout(Q),Q=null;$.off("context_compacted",G),$.off("exit",q),$.off("error",B)},W=(F)=>{if(J)return;J=!0,H(),Y(F)},z=(F)=>{if(J)return;J=!0,H(),V(F)},G=(F)=>{if(F.phase==="start")return;if(F.threadId&&X&&F.threadId!==X)return;W(F)},q=()=>z(Error("codex app-server exited before context compaction completed")),B=(F)=>z(F instanceof Error?F:Error(String(F))),L=new Promise((F,U)=>{Y=F,V=U});return $.on("context_compacted",G),$.once("exit",q),$.once("error",B),{promise:L,cancel(){if(J)return;J=!0,H()}}}function d_($,Z){let J=[],Q=new Set,Y=(H,W)=>{let z=W.threadId??Z;if(z&&H.threadId&&H.threadId!==z)return!1;if(W.turnId)return H.turnId===W.turnId;return!0},V=(H)=>{for(let W=J.length-1;W>=0;W--){let z=J[W];if(z&&Y(z,H))return z}return null},X=(H)=>{if(Z&&H.threadId&&H.threadId!==Z)return;let W={usage:H.usage,contextWindow:H.contextWindow,threadId:H.threadId,turnId:H.turnId};J.push(W);for(let z of[...Q])if(Y(W,z.notice))z.finish(W)};return $.on("token_usage",X),{waitFor(H,W){let z=V(H);if(z)return Promise.resolve(z);return new Promise((G)=>{let q=null,B={notice:H,finish:(L)=>{if(q)clearTimeout(q);Q.delete(B),G(L)}};q=setTimeout(()=>B.finish(null),W),Q.add(B)})},cancel(){$.off("token_usage",X);for(let H of[...Q])H.finish(null)}}}function i_($){if(!$)return" · \uD83E\uDDE0 MISS";let Z=V4($.usage);if(Z==null)return" · \uD83E\uDDE0 MISS";let J=X4($.contextWindow);return` · \uD83E\uDDE0 ${CJ(Z,J)} (${H4(Z,J)})`}async function zV($){$.clearStaleIdleQueueState("compact");let Z=!$.currentTurn&&$.pendingUserMessageCount===0&&$.pendingMidTurnMsgs.length===0&&!$.openingTurn;if(!$.isRunning()||!$.proc){$.status="stopped",$.opts.onLifecycleChange?.();let z=await $.openStatusCard("compact","⚪ session 当前未运行","grey");if(z)await $.closeStatusCard(z,"⚪ 后端未运行,compact 无效");else await E($.chatId,`⚪ session "${$.sessionName}" 当前未运行,compact 无效;用 \`hi\` 启动或 \`restart\` 恢复上一会话`);return}if(!Z){let z=await $.openStatusCard("compact","⚠️ 当前 turn 正在执行","grey");if(z)await $.closeStatusCard(z,"⚠️ 先 stop 当前 turn,再 compact");else await E($.chatId,"⚠️ 当前 turn 正在执行,先 `stop` 后再 `compact`。");return}if($.manualContextCompactionPending){let z=await $.openStatusCard("compact","⏳ 上下文压缩已在进行中","grey");if(z)await $.closeStatusCard(z,"⏳ 上下文压缩已在进行中");else await E($.chatId,"⏳ 上下文压缩已在进行中。");return}let J=$.proc,Q=J.sessionId?z$(J.sessionId):"",Y=$.withModel(Q?`\uD83E\uDDE0 压缩上下文 thread=${Q}`:"\uD83E\uDDE0 压缩上下文…"),V=await $.openStatusCard("compact",Y,"orange"),X=async(z)=>{if(V)await $.closeStatusCard(V,z);else await E($.chatId,z)},H=l_(J,u_),W=d_(J,J.sessionId);$.manualContextCompactionPending=!0;try{$.setStatusCard(V,$.withModel("\uD83E\uDDE0 发起上下文压缩")),await J.compactThread(),$.setStatusCard(V,$.withModel("⏳ 等待压缩完成事件"));let z=await H.promise,G=await W.waitFor(z,p_),q=z.threadId?` thread=${z$(z.threadId)}`:"";await X($.withModel(`✅ 上下文已压缩${q}${i_(G)}`))}catch(z){if(H.cancel(),z instanceof D2)await X($.withModel(`ⓘ ${z.message}`));else await X(`❌ 上下文压缩失败: ${j(z)}`)}finally{W.cancel(),$.manualContextCompactionPending=!1}}var u_=600000,p_=1500;var KV=T(()=>{C1();n()});import{randomUUID as o_}from"node:crypto";function r_($){let Z=$.currentTokenSource(),J=$.currentModelLabel();return O2().filter((Q)=>Q.enabled||Q.kind!=="claude-native").map((Q)=>({provider:Q.agent,sourceId:Q.id,display:Q.display,enabled:Q.enabled,modelCount:Q.models.length,selected:Z?.id===Q.id}))}function GV($,Z){let J=$.currentModelLabel(),Q=$.currentEffortLabel(),Y=$.currentTokenSource()?.id===Z.id;return Z.models.map((V)=>{let X=Y&&J===V.model;return{provider:Z.agent,sourceId:Z.id,model:V.model,displayName:V.display,description:Z.display,enabled:!0,isDefault:!1,selected:X,efforts:V.efforts.map((H)=>({effort:H,description:"",isDefault:H===V.defaultEffort,selected:X&&Q===H}))}})}async function qV($){m0();let Z=o_(),J=r_($);if($.modelPanels.set(Z,{models:[]}),!await l($.chatId,c9({sessionName:$.sessionName,panelId:Z,currentDisplay:$.currentTokenSource()?.display??$.currentModelLabel(),providers:J})))$.modelPanels.delete(Z),await C($.chatId,"❌ 模型面板发送失败")}async function _V($,Z,J=""){let Q=Z.trim(),Y=Y$(Q);if(!Y)return{ok:!1,message:`未知账号: ${Q}`};if(!Y.enabled)return{ok:!1,message:`${Y.display} 未配置,请先点「启用」`};let V=J.trim(),X=GV($,Y);return $.modelPanels.set(V,{models:X}),{ok:!0,message:"",card:u9({sessionName:$.sessionName,panelId:V,currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),models:X})}}async function BV($,Z,J,Q=""){let Y=Y$(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 V=J.trim();if(!V)return{ok:!1,message:"补录面板缺少 panel_id,请重新发送 model"};return $.modelCustomPrompt={sourceId:Y.id,panelId:V,cardMessageId:Q},{ok:!0,message:"等待模型名",card:l9($.sessionName,Y.display,V)}}async function LV($,Z,J){let Q=$.modelCustomPrompt;if(!Q)return!1;$.modelCustomPrompt=null;let Y=Z.trim(),V=Y$(Q.sourceId),X=async(U)=>{if(!Q.cardMessageId)return!1;let R="",D=!1,P=!1;try{if(R=await $0(Q.cardMessageId),p$(R,1),D=await W$(R,O.modelPanel,U,{notifyCardFailure:!1}),!D)throw Error("model panel replace rejected");if(P=await B$(R,{config:{streaming_mode:!1}}),!P)throw Error("model panel streaming-off rejected")}catch(M){K(`model-custom: card update MISS (${M?.message??M})`)}finally{if(R){if(!P)try{P=await B$(R,{config:{streaming_mode:!1}})}catch(M){K(`model-custom: streaming-off retry MISS (${M?.message??M})`)}if(D&&P)try{await b$(R)}catch(M){K(`model-custom: card dispose MISS (${M?.message??M})`)}else K(`model-custom: retain card state after checked MISS mutation=${D} streamingOff=${P} card=${R.slice(0,12)}`)}}return D&&P},H=async(U,R)=>{if(await X(U))return!0;let P=`⚠️ 模型补录结果未能写回原卡。${R}
|
|
174
|
+
请重新发送 model 打开面板。`;if(!await C($.chatId,P))K(`model-custom: visible fallback send MISS (${R})`);return!1},W=(U)=>H(y4(!1,Y,U),`❌ ${Y?`模型 ${Y}`:"模型名"} 未加入:${U}。`);if(!V||!V.enabled||!V.verifyModel)return await W("账号不可用"),!0;if(!Y)return await W("模型名为空"),!0;if(V.models.some((U)=>U.model.toLowerCase()===Y.toLowerCase()))return await H(y4(!1,Y,"已在列表中"),`ℹ️ 模型 ${Y} 已在列表中,未重复加入。`),!0;let z=await V.verifyModel(Y);if(z==="not_found")return await W("端点确认不存在"),!0;if(z==="no_verdict")return await W("无法校验(端点无响应或凭据问题)"),!0;let G=[...a_(V.id),Y].join(",");YZ(V.id,{models:G}),K(`model-custom: ${V.id} 补录 ${Y} by ${J}(端点校验通过,已持久化)`);let q=Y$(V.id)??V;try{await eZ(q.refreshModels(),15000,"refreshModels")}catch(U){K(`model-custom: refresh after 补录 MISS (${U?.message??U})`)}let B=q.models.some((U)=>U.model===Y)?q:V,L=GV($,B),F=L.find((U)=>U.model===Y);if(!F)return await W("模型已验证,但刷新后的模型列表未返回该项"),!0;return $.modelPanels.set(Q.panelId,{models:L}),await H(S4({sessionName:$.sessionName,panelId:Q.panelId,currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:F}),`✅ 模型 ${Y} 已补录成功。`),!0}function a_($){return(f.token_sources[$]?.models??"").split(",").map((J)=>J.trim()).filter(Boolean)}async function FV($,Z=""){let J=Z.trim(),Q=$.modelCustomPrompt;if(!J||!Q||Q.panelId!==J)return{ok:!1,message:"此补录面板已失效",card:N4($.sessionName,"stale")};return $.modelCustomPrompt=null,{ok:!0,message:"已取消",card:N4($.sessionName)}}function t_($,Z){return Z?.provider==="claude"||Z?.provider==="codex"?Z.provider:x1($)}function s_($,Z){if($.currentTurn)return"当前 turn 不变,后续新 turn 使用。";if($.proc?.isAlive()&&$.proc.provider===Z)return Z==="codex"?"Codex 需重启进程生效(发 restart)。":"下一轮开始使用。";return`下次启动 ${W0(Z)} 时使用。`}async function UV($,Z,J="",Q="",Y=null){let V=Z.trim();if(!V)return await E($.chatId,`❌ ${"模型为空"}`),{ok:!1,message:"模型为空"};let X=t_(V,Y),H=$.modelPanels.get(J.trim())?.models.find((W)=>W.model===V&&(W.provider??"codex")===X);if(!H)return{ok:!1,message:"模型不在当前选项中,请重新发送 model"};if(H.enabled===!1)return{ok:!1,message:`${H.displayName} 未配置,请先点「启用」`};if(H.efforts.length===0)return{ok:!1,message:"模型未返回 effort"};return{ok:!0,message:"",card:p9({sessionName:$.sessionName,panelId:J.trim(),currentModel:$.currentModelLabel(),currentEffort:$.currentEffortLabel(),model:H})}}async function DV($,Z,J,Q="",Y="",V=""){let X=Z.trim(),H=J.trim();if(!X)return{ok:!1,message:"模型为空"};let W=Q.trim(),z=$.modelPanels.get(W),G=V==="claude"||V==="codex"?V:z?.models.find((P)=>P.model===X)?.provider??x1(X);if(G==="claude"){if(!j0(H))return{ok:!1,message:"Claude reasoning effort 无效"}}else if(!s$(H))return{ok:!1,message:"Codex reasoning effort 无效"};let q=H,B=z?.models.find((P)=>P.model===X&&(P.provider??"codex")===G);if(!B||!B.efforts.some((P)=>P.effort===q))return{ok:!1,message:`${W0(G)} · ${X}/${q} 不在选项中`};let L=!!B.sourceId&&$.currentTokenSource()?.id!==B.sourceId;if($.currentProvider()===G&&!L&&$.currentModelLabel()===X&&$.currentEffortLabel()===q)return $.modelPanels.delete(W),{ok:!0,message:`当前已是 ${W0(G)} · ${X} / ${q}`,card:C4({sessionName:$.sessionName,provider:G,model:X,effort:q,scope:"当前已是此设置,无需变更。"})};if($.proc?.isAlive()&&$.proc.provider!==G&&($.currentTurn||$.openingTurn||$.pendingUserMessageCount>0||$.pendingMidTurnMsgs.length>0))return{ok:!1,message:`当前 ${$.backendLabel($.proc.provider)} turn 正在执行或排队;请等结束或 stop 后再切换到 ${W0(G)}`};let R=$.currentModelLabel()!==X||L,D=!!($.currentTurn||$.openingTurn||$.pendingUserMessageCount>0||$.pendingMidTurnMsgs.length>0);if(G==="claude"&&$.proc?.isAlive()&&$.proc.provider==="claude"&&R&&D)return{ok:!1,message:"当前 Claude turn 正在执行或排队;Claude 模型 profile 通过 env 生效,请等结束或 stop 后再切换"};try{if($.proc?.isAlive()&&$.proc.provider===G&&!L){let M=B.sourceId?Y$(B.sourceId)?.resolveSpawnModel(X)??X:X;await eZ($.proc.setModelSettings(M,q),20000,"thread/settings/update")}await $.applyModelSelectionUnlocked(G,X,q,B.sourceId);let P=s_($,G);return $.modelPanels.delete(W),{ok:!0,message:`已选择 ${W0(G)} · ${X} / ${q}`,card:C4({sessionName:$.sessionName,provider:G,model:X,effort:q,scope:P})}}catch(P){let M=`模型切换失败: ${j(P)}`;return K(`session "${$.sessionName}": set model settings failed: ${j(P)}`),await E($.chatId,`❌ ${M}`),{ok:!1,message:M}}}var PV=T(()=>{N$();k$();b5();E1();C1();n$();a0();n();v()});function k0($,Z,J=!1){let Q=$.worktreeProjectName();return X5({projectName:Q,tasklistName:Y5(Q),binding:E$(Q),notice:Z,confirmDelete:J})}async function AV($){if(!await l($.chatId,k0($)))await C($.chatId,"❌ task 面板发送失败")}async function MV($){let Z=$.worktreeProjectName();try{let J=E$(Z),Q=await CQ(Z,$.chatId),Y=J?"已启用":`已启用 ${Q.name}`;return{ok:!0,message:Y,card:k0($,{type:"success",content:`✅ ${Y}`})}}catch(J){let Q=`启用失败: ${j(J)}`;return K(`session "${$.sessionName}": tasklist enable failed: ${j(J)}`),{ok:!1,message:Q,card:k0($,{type:"error",content:`❌ ${Q}`})}}}function OV($,Z){let J=$.worktreeProjectName(),Q=E$(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 jV($,Z){let J=$.worktreeProjectName(),Q=Z.trim();try{let V=`已删除 ${(await yQ(J,Q)).name}`;return{ok:!0,message:V,card:k0($,{type:"success",content:`✅ ${V}`})}}catch(Y){let V=`删除失败: ${j(Y)}`;return K(`session "${$.sessionName}": tasklist delete failed: ${j(Y)}`),{ok:!1,message:V,card:k0($,{type:"error",content:`❌ ${V}`})}}}var RV=T(()=>{n$();n();v();m4()});var EV,TV,xV,CV;var NV=T(()=>{EV=["- 以 `[file: /abs/path]` 开头的文本表示该路径上挂着一个文件,相关时去读它。","- 在回复任意位置,独占一行写 `[[send: /abs/path]]` 即可把该文件作为单独一条消息送出。只在用户主动要文件、或你要交付最终产物时才发。"],TV=["- 判断是否该发文件:导出附件/数据集、用户明确要文件或下载物时,应先写到本机绝对路径,再用独占一行的 `[[send: /abs/path]]` 发给用户;短总结、普通说明、无需留存的正文答复不要为了发文件而发文件。","- 使用图片生成工具生成图片后,不要再补充说明文字或 `[[send: ...]]`;Lodestar 会根据工具返回的本机图片路径自动发给用户。若你用脚本或文件编辑生成图片,按上一条用 `[[send: /abs/path]]` 发出。","- 每次调用 Bash / shell 命令时,第一行都必须写 shell 注释 `# desc: <一句中文说明>`,再写真正命令。这个注释只给 Lodestar 卡片做摘要,不要依赖它改变命令行为。"],xV=[...EV,"- 当你有问题需要澄清时,使用 request_user_input 工具向用户提问;不要把多选题写成文本。",...TV].join(`
|
|
175
|
+
`),CV=[...EV,"- 当你有问题需要澄清时,使用 Claude Code 自带的 AskUserQuestion 工具向用户提问;不要输出 Codex 专属的 host-marker 文本协议。",...TV].join(`
|
|
176
|
+
`)});import{execFileSync as ZB}from"node:child_process";import{existsSync as X1,readdirSync as JB,readFileSync as QB,realpathSync as h5,statSync as YB}from"node:fs";import{dirname as VB,join as SV,resolve as XZ}from"node:path";async function H1($,Z){let J=h5($),Q=process.platform==="win32"?J.toLowerCase():J,Y=VZ.get(Q)??Promise.resolve(),V,X=new Promise((W)=>{V=W}),H=Y.catch(()=>{}).then(()=>X);VZ.set(Q,H),await Y.catch(()=>{});try{return await Z()}finally{if(V(),VZ.get(Q)===H)VZ.delete(Q)}}function W1($){let Z=$.trim();if(!XB.test(Z))return null;return Z}function H8($){return $.startsWith(HB)}function kV($){return $.match(/^(.+)\[[^\[\]]+\]$/)?.[1]??$}function t1($,Z){return`${$}[${Z}]`}function wV($){return`${a1}${$}`}function s1($,Z,J){return SV(VB($),t1(Z,J))}function bV($,Z,J){let Q=WB($,Z,J);if(!Q)return null;let Y=QB(Q.path,"utf8").trim();if(!Y)return null;return{path:Q.path,content:Y,slug:Q.slug}}function vV($,Z){g5($);let J=F$($,["for-each-ref","--format=%(refname:short)",`refs/heads/${a1}`]).split(`
|
|
177
|
+
`).map((V)=>V.trim()).filter(Boolean).filter((V)=>V.startsWith(a1)),Q=m5($),Y=[];for(let V of J){let X=V.slice(a1.length);if(!W1(X))continue;if(H8(X))continue;let H=t1(Z,X),W=s1($,Z,X),z=Q.get(V)??null,G=z??W,q=!!z&&X1(z),B=gV($,V,q),L={slug:X,chatName:H,branch:V,state:B,expectedPath:W,worktreePath:q?z:null,mounted:q,dirtyCount:null,statusLine:null,error:null};if(z&&X1(z))try{let U=F$(z,["status","--porcelain=v1","--branch"]).split(`
|
|
178
|
+
`).filter(Boolean);L.statusLine=U[0]?.startsWith("## ")?U[0].slice(3):null,L.dirtyCount=U.filter((R)=>!R.startsWith("## ")).length}catch(F){L.error=c5(F)}Y.push(L)}return Y.sort((V,X)=>V.slug.localeCompare(X.slug))}function fV($,Z,J){let Q=W1(J);if(!Q)throw Error(`invalid worktree name "${J}"`);g5($);let Y=wV(Q),V=t1(Z,Q),X=s1($,Z,Q),H=qB($,Y),W=m5($).get(Y)??null,z=H&&!W&&gV($,Y,!1)==="merged"?F$($,["rev-parse","HEAD"]).trim():null;if(W){if(XZ(W)!==XZ(X))throw Error(`branch ${Y} is already mounted at ${W}`);return IV(X,Y),{slug:Q,chatName:V,branch:Y,worktreePath:X,createdBranch:!1,createdWorktree:!1}}if(X1(X)){if(!YB(X).isDirectory())throw Error(`${X} exists but is not a directory`);if(!H)throw Error(`${X} already exists while branch ${Y} does not`)}if(H){if(F$($,["worktree","add",X,Y]),z)F$(X,["rebase",z]);return{slug:Q,chatName:V,branch:Y,worktreePath:X,createdBranch:!1,createdWorktree:!0}}return F$($,["worktree","add","-b",Y,X,"HEAD"]),{slug:Q,chatName:V,branch:Y,worktreePath:X,createdBranch:!0,createdWorktree:!0}}function hV($,Z,J){let Q=I5($,Z,J);if(!X1(Q.worktreePath))return Q;return F$($,["worktree","remove",Q.worktreePath]),{...Q,removedWorktree:!0}}function I5($,Z,J){let Q=W1(J);if(!Q)throw Error(`invalid worktree name "${J}"`);g5($);let Y=wV(Q),V=t1(Z,Q),X=s1($,Z,Q),W=m5($).get(Y)??null??X;if(!X1(W))return{slug:Q,chatName:V,branch:Y,worktreePath:W,removedWorktree:!1};IV(W,Y);let z=F$(W,["status","--porcelain=v1"]).split(`
|
|
179
|
+
`).filter(Boolean);if(z.length>0){let G=z.slice(0,8).join(`
|
|
179
180
|
`);throw Error(`worktree has uncommitted changes:
|
|
180
|
-
${G}`)}return{slug:Q,chatName:V,branch:Y,worktreePath:
|
|
181
|
-
`)){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
|
|
182
|
-
${J}`:Z}function
|
|
183
|
-
${J}`:Z}function
|
|
184
|
-
`)}async function
|
|
185
|
-
${V}`,card:
|
|
186
|
-
`),type:"success"}})}catch(X){V={ok:!1,message:`❌ 解散 ${J} 失败: ${
|
|
187
|
-
`)){let V=Y.trim();if(!V)continue;let X;try{X=JSON.parse(V)}catch{continue}if(X.type==="queue-operation"&&X.operation==="enqueue"&&typeof X.content==="string"){let z=X.content.trim();if(z)return z.slice(0,80)}if(!Q&&X.type==="user"&&X.message){let z=OB(X.message);if(z)Q=z}}return Q.slice(0,80)}function OB($){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 fV($,Z,J){if(!J){await A($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let Q=DB($),Y=UB($),V=new Map,X=[];for(let G=0;G<Q.length;G++){let _=Q[G];if(G===0&&Y===null)continue;let B=b5(),L=G===0?Y:FB(Q[G-1].checkpoint);V.set(B,{kind:Z,launch:L,branchBase:Y,seedAnchors:Q.slice(0,G),writes:Q.slice(G).flatMap((F)=>F.writes)}),X.push({choiceId:B,preview:_.preview,ts:_.ts})}X.reverse();let z=vV($,Z,J,V),H=v9({projectName:s4($),panelId:z.id,mode:Z,entries:X}),W;try{W=await p($.chatId,H)}catch(G){throw n1($).delete(z.id),G}if(!W)n1($).delete(z.id),await C($.chatId,`❌ ${Z==="fork"?"fk":"bk"} 列表发送失败`)}function IV($,Z){return fV($,"fork",Z)}function hV($,Z){return fV($,"back",Z)}async function gV($,Z){if(!Z){await A($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let J;try{J=$.selectedProvider==="codex"?await $.listCodexConversations():PB($.workDir)}catch(H){await C($.chatId,`❌ 历史会话读取失败: ${H instanceof Error?H.message:H}`);return}let Q=new Map,Y=AB(J).map((H)=>{let W=b5();return Q.set(W,{kind:"resume",launch:{kind:"fork",source:{provider:H.provider,sessionId:H.sessionId,cwd:H.cwd}},sourcePreview:H.preview,sourceTs:H.ts,sourceStatus:H.status}),{choiceId:W,preview:H.preview,ts:H.ts}}),V=vV($,"resume",Z,Q),X=f9({projectName:s4($),panelId:V.id,entries:Y}),z;try{z=await p($.chatId,X)}catch(H){throw n1($).delete(V.id),H}if(!z)n1($).delete(V.id),await C($.chatId,"❌ rs 历史列表发送失败")}async function mV($,Z){if(!Z){await A($.chatId,"❌ 找不到发起人,无法建临时群。");return}if(!$.opts.onCreateTempSession){await A($.chatId,"❌ 临时群能力未就绪(daemon 未注入回调)。");return}let J=wV(s4($));await A($.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{bV(J)}if(!Q.ok){await A($.chatId,`❌ 建临时会话失败: ${Q.error??"未知"}`);return}await A($.chatId,`✅ 已创建 ${J}。临时群不会自动删除;在该群发送 bye 可停止并解散。`)}async function cV($){if(!d$($.sessionName)){await A($.chatId,"❌ bye 只能在带 *MMDD-HHMM 后缀的临时会话群里使用。");return}if(!$.opts.onDisbandTempSession){await A($.chatId,"❌ 解散能力未就绪(daemon 未注入回调)。");return}await A($.chatId,`\uD83D\uDC4B 正在停止会话并解散 ${$.sessionName}…`);let Z=await $.opts.onDisbandTempSession($.sessionName,$.chatId);if(!Z.ok)await A($.chatId,`❌ 解散失败: ${Z.error??"未知"}`)}async function uV($,Z,J,Q){let Y=v5($,"fork",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:V,choice:X}=Y;try{if(X.kind!=="fork")return{ok:!1,message:"选择项类型不匹配"};if(!$.opts.onCreateTempSession)return{ok:!1,message:"临时群能力未就绪"};let z=wV(V.baseName);K(`session-temp: fork ${$.sessionName} → ${z} (${X.launch.kind})`),await A($.chatId,`\uD83D\uDD31 正在分叉到 ${z}…`);let H;try{H=await $.opts.onCreateTempSession({chatName:z,userOpenId:Q,workDir:V.workDir,routing:V.routing,launch:X.launch,branchBase:X.branchBase,seedAnchors:X.seedAnchors})}finally{bV(z)}if(!H.ok)return{ok:!1,message:`分叉失败: ${H.error??"未知"}`};return{ok:!0,message:`已分叉到 ${z};原会话和磁盘文件未回滚`}}catch(z){return{ok:!1,message:`分叉失败: ${z instanceof Error?z.message:z}`}}finally{t4(V)}}async function pV($,Z,J,Q){let Y=v5($,"back",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:V,choice:X}=Y;try{if(X.kind!=="back")return{ok:!1,message:"选择项类型不匹配"};let z="";try{if(!await p($.chatId,I9({projectName:V.baseName,entries:X.writes})))z=";文件变更记录卡发送失败"}catch(G){z=`;文件变更记录卡发送失败: ${G instanceof Error?G.message:G}`}if(K(`session-temp: back ${$.sessionName} (${X.launch.kind}, writes=${X.writes.length})`),!await $.rollbackTo(X.launch,{anchors:X.seedAnchors,base:X.branchBase}))return{ok:!1,message:`回退失败;原会话绑定未改,请检查日志后重试${z}`};if(V.routing.provider==="claude")return{ok:!0,message:`本群已准备 Claude 新分支;发送下一条消息时生成并接入,旧会话未删除,磁盘文件未回滚${z}`};return{ok:!0,message:`本群已改接新会话${$.lastSessionId?` ${$.lastSessionId.slice(0,8)}…`:""};旧会话未删除,磁盘文件未回滚${z}`}}catch(z){return{ok:!1,message:`回退失败: ${z instanceof Error?z.message:z}`}}finally{t4(V)}}async function lV($,Z,J,Q){let Y=v5($,"resume",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:V,choice:X}=Y;if(X.kind!=="resume")throw t4(V),Error("resume panel contained a non-resume choice");let z=X.launch.source.sessionId,H=$.lastSessionId,W=(_,B)=>({projectName:V.baseName,provider:X.launch.source.provider,selectedPreview:X.sourcePreview,selectedTs:X.sourceTs,sourceSessionId:z,...X.sourceStatus?{sourceStatus:X.sourceStatus}:{},previousSessionId:H,newSessionId:_,bindingState:B}),G=(_,B,L,F=null)=>({ok:_,message:B,resumePresentation:W(F,L)});try{if($.isRunning())return G(!1,"当前群已经启动了新进程;为避免误杀,请先停止后重新发送 rs","unchanged");if(X.sourceStatus==="active")return G(!1,"所选 Codex 会话仍在运行;请先在原位置停止后再创建完整分支","unchanged");if(K(`session-temp: history fork ${$.sessionName} ← ${X.launch.source.provider} ${z.slice(0,8)}`),!await $.rollbackTo(X.launch,{anchors:[],base:X.launch,pendingLaunch:X.launch.source.provider==="claude"?{launch:X.launch,previousSessionId:H}:null}))return G(!1,"历史分支创建失败;原会话绑定未改,请检查日志后重试","unchanged");if(X.launch.source.provider==="claude")return G(!0,"Claude 独立分支已准备;首条消息时生成并接入新会话","prepared");let B=$.lastSessionId;if(!B)return G(!1,"历史分支已启动,但后端没有返回新会话 id","unknown");if(B===z||H&&B===H)return G(!1,"后端没有返回独立的新会话 id;为避免误判,本次不标记为恢复成功","unknown",B);return G(!0,"已创建并接入独立分支;源会话未修改","changed",B)}catch(_){return G(!1,`历史分支创建失败: ${_ instanceof Error?_.message:_}`,"unknown")}finally{t4(V)}}var GB=86400000,_B=1800000,qB=3600000,BB=40,kV,w5;var iV=E(()=>{d();c$();v();U6();D1();kV=new WeakMap,w5=new Set});import{existsSync as dV}from"node:fs";import{isAbsolute as jB}from"node:path";function EB($){return $.itemId||$.turnId||"__latest__"}function TB($){let Z=null;for(let J of $.contextCompactionPending.keys())Z=J;return Z}function xB($,Z){if(!$)return Z;return{...$,...Z,phase:"end"}}function Z1(){return f.runtime?.live_elapsed??"bucket"}function aV($,Z){return`${$} (${L0(Date.now()-Z,Z1()).label})`}var yB="Thinking...",CB="Writing...",NB="Working...",nV=1e4,rV=120000,SB=50,f5=5,oV=250,J1;var tV=E(()=>{U1();Y6();M1();E$();x$();B7();U6();u0();c$();d();v();E9();v4();I4();J5();pQ();JY();PY();jY();D5();SY();nY();oY();YV();WV();SV();iV();D1();J1=class J1{sessionName;chatId;opts;static all=new Set;proc=null;lifecycleTail=Promise.resolve();lifecycleSequence=0;procEpoch=0;stoppingProc=null;blockedProc=null;blockedProcReason=null;procSourceRevisions=new WeakMap;currentTurn=null;backgroundTasks=[];pendingBgTasks=[];backgroundCard=null;settlingBackgroundCard=!1;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;runningAgy=null;startingAgy=!1;agyForwardPrompts=new Map;taskBoard=[];constructor($,Z,J={}){this.sessionName=$;this.chatId=Z;this.opts=J;J1.all.add(this);let Q=d6($);this.selectedProvider=Q?.provider??"claude",this.selectedModel=Q?.model??null,this.selectedEffort=Q?.effort??null,this.selectedTokenSourceId=this.deriveTokenSourceId(Q);let Y=Q$(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((X)=>X.model===this.selectedModel))this.selectedModel=Y.defaultModel}if(this.selectedModel)K(`session "${$}": restored selected provider=${this.selectedProvider} model=${this.selectedModel} effort=${this.selectedEffort??"unset"}`);if(this.lastSessionRef=T2($,this.selectedProvider),this.lastSessionId=this.lastSessionRef?.sessionId??null,this.lastSessionId)K(`session "${$}": restored ${this.selectedProvider} lastSessionId=${this.lastSessionId.slice(0,8)}…`);let V=y2($);if(V)if(this.selectedProvider!=="claude")y$($,[],null,null),K(`session "${$}": cleared pending Claude fork after provider changed`);else{X$(V.launch,"claude",this.workDir);let X=this.lastSessionId===V.previousSessionId,z=this.lastSessionRef,H=!X&&z?.provider==="claude"&&z.cwd===this.workDir&&z.sessionId!==V.launch.source.sessionId&&z.sessionId!==V.previousSessionId;if(!X&&!H)throw Error(`pending Claude fork has inconsistent resume binding for session "${$}"`);this.pendingConversationMaterialization=V,K(`session "${$}": restored ${H?"materialized":"pending"} Claude fork source=${V.launch.source.sessionId.slice(0,8)}…`)}}peerSnapshot(){return{name:this.sessionName,status:this.status,uptimeMs:this.startedAt?Date.now()-this.startedAt:void 0}}get workDir(){return EV(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 N8(J==="codex"?"codex":"claude")[0]?.id??null}currentTokenSource(){return Q$(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=Q$($.tokenSourceId);if(Z&&Z.agent!==$.provider)throw Error(`token source "${Z.id}" belongs to ${Z.agent}, not ${$.provider}`);if(this.selectedProvider!==$.provider)y$(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$.provider,this.selectedTokenSourceId=$.tokenSourceId,this.selectedModel=$.model,this.selectedEffort=$.effort,this.lastSessionRef=T2(this.sessionName,$.provider),this.lastSessionId=this.lastSessionRef?.sessionId??null,i6(this.sessionName,$.provider,$.model,$.effort,$.tokenSourceId)}async listCodexConversations(){if(this.selectedProvider!=="codex")throw Error("Codex history requested for a non-Codex session");if(!S2())throw Error("Codex 未登录 ChatGPT 账号");let $=this.currentTokenSource();if(this.selectedTokenSourceId&&(!$||!$.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或选择其他账号`);let Z=$?.enabled?$:void 0,J=Z?(z)=>Z.spawnEnv(z):void 0,Q=new W2({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Z?.id??null,transformEnv:J}),Y=null,V=null;try{Y=await Q.listConversations()}catch(z){V=z}let X=null;try{await Q.kill(2000)}catch(z){X=z}if(V&&X)throw AggregateError([V,X],`Codex history query and cleanup failed: ${R(V)}; ${R(X)}`);if(V)throw V;if(X)throw X;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=F6(this.workDir,$.sessionId);if(!dV(J))throw Error(`旧 Claude 会话不属于当前 cwd,或 transcript 不存在: ${$.sessionId.slice(0,8)}…`);Z={...$,cwd:this.workDir}}else{if(!S2())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 W2({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Q?.id??null,transformEnv:Q?(z)=>Q.spawnEnv(z):void 0}),V=null;try{Z=await Y.readConversationRef($.sessionId)}catch(z){V=z,Z=$}let X=null;try{await Y.kill(2000)}catch(z){X=z}if(V&&X)throw AggregateError([V,X],"Codex legacy resume lookup and cleanup failed");if(V)throw V;if(X)throw X}return X$({kind:"resume",source:Z},this.selectedProvider,this.workDir),E2(this.sessionName,Z),Z}hasRunningPeerSession($){return[...J1.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 l$(this.selectedEffort)?this.selectedEffort:H2}return H2}claudeEffortForSpawn(){return this.selectedProvider==="claude"&&D0(this.selectedEffort)?this.selectedEffort:F0}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"?F0:H2)}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"?F0:H2);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"?`${Q0($.provider)} · ${J}`:J}withModel($,Z){let J=this.modelEffortLabel(Z);return $.includes(J)?$:`${$} · ${J}`}replaceFooterContent($,Z){return c($,U.footer,this.footerElement(Z))}footerElement($){return{tag:"markdown",element_id:U.footer,content:$.trim()||" "}}modelLine($){return this.modelEffortLabel($)}backendLabel($=this.selectedProvider){return Q0($)}pendingConversationLaunch=null;pendingConversationMaterialization=null;lastTurnUserPreview="";pendingMaterializationLaunch(){let $=this.pendingConversationMaterialization;if(!$)return null;if(X$($.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($){let Z=this.pendingConversationLaunch??this.pendingMaterializationLaunch()??($?{kind:"resume",source:$}:{kind:"fresh"});X$(Z,this.selectedProvider,this.workDir);let J=this.currentTokenSource();if(this.selectedTokenSourceId&&(!J||!J.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或在 model 面板选择其他账号`);let Q=J?.enabled?J:void 0,Y=Q?(z)=>Q.spawnEnv(z):void 0,V=Q?Q.resolveSpawnModel(this.selectedModel??Q.defaultModel):this.modelForSpawn();if(this.selectedProvider==="claude"){y7();let z=Z.kind==="fresh"?void 0:Z.source.sessionId,H=Z.kind==="fork"?Z.through:void 0;if(H&&(H.provider!=="claude"||H.kind!=="assistant-message"))throw Error(`Claude cannot fork from ${H.provider}/${H.kind} checkpoint`);let W=new D6({workDir:this.workDir,model:V,effort:this.claudeEffortForSpawn(),resumeSessionId:z,resumeSessionAt:H?.id,forkSession:Z.kind==="fork",appendSystemPrompt:this.spawnDeveloperInstructions(),profile:u8(this.worktreeProjectName()),...Q?.settingSources?{settingSources:Q.settingSources}:{},tokenSourceId:Q?.id??null,transformEnv:Y});return this.procSourceRevisions.set(W,Q?.spawnRevision??null),W}let X=new W2({workDir:this.workDir,model:V,effort:this.effortForSpawn(),launch:Z,appendSystemPrompt:this.spawnDeveloperInstructions(),tokenSourceId:Q?.id??null,transformEnv:Y});return this.procSourceRevisions.set(X,Q?.spawnRevision??null),X}async applyModelSelection($,Z,J,Q){await this.runLifecycle("apply-model-selection",()=>this.applyModelSelectionUnlocked($,Z,J,Q))}async applyModelSelectionUnlocked($,Z,J,Q){if(this.selectedProvider!==$)y$(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$,this.selectedTokenSourceId=Q??this.selectedTokenSourceId;let V=Q$(this.selectedTokenSourceId);if(V)this.selectedModel=Z||null,this.selectedEffort=J??V.models.find((X)=>X.model===Z)?.defaultEffort??V.models[0]?.defaultEffort??null;else this.selectedModel=$==="codex"?null:Z,this.selectedEffort=$==="codex"?null:J;this.lastSessionRef=T2(this.sessionName,$),this.lastSessionId=this.lastSessionRef?.sessionId??null,l6(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;K(`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=null;try{await J.kill(1000)}catch(V){Q=V}let Y=this.finishProcStop(J,Q);if(this.opts.onLifecycleChange?.(),!Y)throw Q??Error(this.blockedProcReason??"process stop unconfirmed")}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;K(`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=null;try{await Z.kill(1000)}catch(Y){J=Y}let Q=this.finishProcStop(Z,J);if(this.opts.onLifecycleChange?.(),!Q)throw J??Error(this.blockedProcReason??"process stop unconfirmed");return!0}startFooterTimer($,Z,J=(Q)=>Q){let Q=Date.now(),Y=Z,V=!1,X=()=>{if(V)return;this.replaceFooterContent($,J(aV(Y,Q)))},z=null,H=()=>{if(V)return;let{nextDelayMs:W}=L0(Date.now()-Q,Z1());z=setTimeout(()=>{X(),H()},Math.max(1,Math.ceil(W)))};return X(),H(),{setStatus(W){Y=W,X()},stop(){if(V=!0,z)clearTimeout(z)},elapsedSec(){return((Date.now()-Q)/1000).toFixed(1)}}}async openStatusCard($,Z,J="blue"){let Q=Date.now(),Y=T9({sessionName:this.sessionName,title:$,status:aV(Z,Q),template:J}),V=await p(this.chatId,Y);if(!V)return K(`session "${this.sessionName}": status card send failed title=${$}`),await C(this.chatId,`❌ 创建状态卡片失败: ${$}`),null;let X;try{X=await r$(V)}catch(z){return K(`session "${this.sessionName}": status card id_convert failed title=${$}: ${z}`),await C(this.chatId,`❌ 状态卡片初始化失败: ${$}`),null}return h$(X,1),{cardId:X,title:$,timer:this.startFooterTimer(X,Z,(z)=>u2($,z))}}setStatusCard($,Z){$?.timer.setStatus(Z)}async closeStatusCard($,Z){if(!$)return;$.timer.stop();let J=$.timer.elapsedSec(),Q=u2($.title,`${Z} (${J}s)`);await o$($.cardId);let Y=await L$($.cardId,U.footer,this.footerElement(Q));V$($.cardId);let V=await K$($.cardId,m$({durationSec:J,suffix:Z}));if(Y&&V)await C$($.cardId);else{let X=`footer=${Y?"ok":"MISS"}, settings=${V?"ok":"MISS"}`;K(`session "${this.sessionName}": status card terminal transaction incomplete card=${$.cardId.slice(0,12)} ${X}`),await C(this.chatId,`⚠️ 状态卡片终态写入失败 (${X}):${Z}`)}}beginAgyForwardToCodex($,Z=""){return LY(this,$,Z)}runAgyCommand($){return FY(this,$)}stopAgyTask($="\uD83D\uDED1 agy 已打断"){return UY(this,$)}async runLifecycle($,Z){let J=this.lifecycleTail,Q;this.lifecycleTail=new Promise((V)=>{Q=V}),await J;let Y=++this.lifecycleSequence;K(`session "${this.sessionName}": lifecycle#${Y} ${$} begin`);try{return await Z()}finally{Q(),K(`session "${this.sessionName}": lifecycle#${Y} ${$} end`)}}async waitForLifecycleIdle(){await this.lifecycleTail}beginTurnOpen($=this.proc,Z=this.procEpoch){let J={token:++this.turnOpenSequence,proc:$,procEpoch:Z,sawResult:!1,terminalForcePush:!1};return this.openingTurnOwner=J,this.openingTurn=!0,J}ownsTurnOpen($){return this.openingTurnOwner===$&&this.proc===$.proc&&this.procEpoch===$.procEpoch}releaseTurnOpen($){if(this.openingTurnOwner!==$)return;this.openingTurnOwner=null,this.openingTurn=!1}invalidateTurnOpen(){this.openingTurnOwner=null,this.openingTurn=!1}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.stoppingProc===$)this.stoppingProc=null;if(this.blockedProc===$)this.blockedProc=null,this.blockedProcReason=null;return this.procEpoch++,!0}beginProcStop($){this.stoppingProc=$}finishProcStop($,Z){if(this.stoppingProc===$)this.stoppingProc=null;if(!$.isAlive())return this.detachProc($),!0;return this.blockedProc=$,this.blockedProcReason=Z?R(Z):"kill returned while process still reports alive",K(`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)}resetFreshConversationState(){this.turnCounter=0,this.pendingConversationMaterialization=null,y$(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 A(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"&&!S2()){if(this.status="stopped",this.opts.onLifecycleChange?.(),J?.("❌ Codex 未登录 ChatGPT 账号"),Z)await A(this.chatId,"❌ Codex 未登录 ChatGPT 账号。\n请在服务器上运行 `codex login` 后再试。");return!1}if(!dV(this.workDir)){if(J?.(`\uD83C\uDD95 创建项目目录 ~/${this.sessionName}`),Z)await A(this.chatId,`\uD83C\uDD95 目录 ~/${this.sessionName} 不存在,正在创建…`);try{J9(this.workDir)}catch(H){if(this.status="stopped",this.opts.onLifecycleChange?.(),J?.(`❌ 创建项目失败: ${H}`),Z)await A(this.chatId,`❌ 创建项目失败: ${H}`);return!1}}if(!$.freshConversationStateAlreadyReset&&!this.pendingConversationMaterialization)this.resetFreshConversationState();this.status="starting",J?.(this.withModel(`\uD83D\uDE80 启动 ${this.backendLabel()}`));let Y;try{Y=this.spawnAgent()}catch(H){let W=`${this.backendLabel()} 启动失败: ${R(H)}`;if(K(`session "${this.sessionName}": ${W}`),J?.(`❌ ${W}`),Z)await A(this.chatId,`❌ ${W}`);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}this.attachProc(Y);let V=this.backendLabel(),X=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(Y,oV):this.waitForProcInit(Y,5000);J?.(this.selectedProvider==="claude"?`⏳ 检查 ${V} 启动`:`⏳ 等待 ${V} init`),Y.sendInitialize();let z=await X;if(z.state==="error"||z.state==="exit"){let H=z.error?R(z.error):z.state;if(K(`session "${this.sessionName}": ${this.selectedProvider} init failed: ${H}`),J?.(`❌ ${V} 启动失败: ${H}`),Z)await A(this.chatId,`❌ ${V} 启动失败: ${H}`);return await this.stopOwnedProc(Y,1000),this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(z.state==="timeout"){K(`session "${this.sessionName}": ${this.selectedProvider} init wait timeout (5s)`);let H=`${V} 启动超时: 5 秒内未收到 init 确认`;if(J?.(`❌ ${H}`),Z)await A(this.chatId,`❌ ${H}`);return await this.stopOwnedProc(Y,1000),this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(this.proc!==Y||!Y.isAlive()){let H=`${V} 启动期间已退出`;if(K(`session "${this.sessionName}": ${H}`),J?.(`❌ ${H}`),Z)await A(this.chatId,`❌ ${H}`);return this.detachProc(Y),this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(Z){let H=this.modelLine();await A(this.chatId,[this.withWorktreeInstructionNotice(`✅ Lodestar session "${this.sessionName}" 已就绪,发消息开始对话。`),H].filter(Boolean).join(`
|
|
188
|
-
`))}return this.status="idle",this.startedAt=Date.now(),this.opts.onLifecycleChange?.(),J?.(this.withModel(this.withWorktreeInstructionNotice(`✅ ${this.backendLabel()} 已就绪`))),!0}async waitForProcInit($,Z){return await new Promise((J)=>{let Q=!1,Y=(W,G)=>{if(Q)return;Q=!0,clearTimeout(V),$.off("init",X),$.off("error",z),$.off("exit",H),J({state:W,error:G})},V=setTimeout(()=>Y("timeout"),Z),X=()=>Y("init"),z=(W)=>Y("error",W),H=(W)=>Y("exit",W);$.once("init",X),$.once("error",z),$.once("exit",H)})}async waitForProcEarlyFailure($,Z){return await new Promise((J)=>{let Q=!1,Y=(W,G)=>{if(Q)return;Q=!0,clearTimeout(V),$.off("init",X),$.off("error",z),$.off("exit",H),J({state:W,error:G})},V=setTimeout(()=>Y("ready"),Z),X=()=>Y("init"),z=(W)=>Y("error",W),H=(W)=>Y("exit",W);$.once("init",X),$.once("error",z),$.once("exit",H)})}async waitForProcResumeInit($,Z){return await new Promise((J)=>{let Q=!1,Y=(G,_)=>{if(Q)return;Q=!0,clearTimeout(V),clearTimeout(X),$.off("init",z),$.off("error",H),$.off("exit",W),J({state:G,error:_})},V=setTimeout(()=>{if(!Q)Z()},nV),X=setTimeout(()=>{Y("timeout",Error(`resume init timed out after ${rV/1000}s`))},rV),z=()=>Y("init"),H=(G)=>Y("error",G),W=(G)=>Y("exit",G);$.once("init",z),$.once("error",H),$.once("exit",W)})}releaseAllReactions(){for(let[$,Z]of[...this.pendingReactionIds.entries(),...this.currentBatchReactionIds.entries()])if(Z)B$($,Z);this.pendingReactionIds=new Map,this.currentBatchReactionIds=new Map}clearStaleIdleQueueState($){if(this.initCount<1||this.currentTurn||this.openingTurn||this.pendingUserMessageCount===0)return;K(`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)B$(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,Y=await this.stopAgyTask(`\uD83D\uDED1 ${$}`);if(!this.proc){if(this.status="stopped",this.opts.onLifecycleChange?.(),Q?.(Y?`✅ ${$}`:"⚪ session 当前未运行"),J&&!Y)await A(this.chatId,`⚪ session "${this.sessionName}" 当前未运行`);return}Q?.(`\uD83D\uDED1 停止 ${this.backendLabel(this.proc.provider)}`),K(`session "${this.sessionName}": stop (${$})`);let V=this.proc;if(this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.currentTurn)this.closeTurnCard(`\uD83D\uDED1 ${$}`).catch((L)=>{K(`session "${this.sessionName}": stop current main-card close failed: ${R(L)}`)});let X=this.waitForTurnCloses().catch((L)=>K(`session "${this.sessionName}": stop main-card close failed: ${R(L)}`));this.beginProcStop(V),this.status="stopped";let z=[];try{this.opts.onLifecycleChange?.()}catch(L){z.push(L),K(`session "${this.sessionName}": stop intent lifecycle write failed: ${R(L)}`)}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 H=null;try{await V.kill()}catch(L){H=L}let G=(await Promise.allSettled([this.resetBackgroundTasks(),X])).filter((L)=>L.status==="rejected").map((L)=>L.reason);for(let L of G)K(`session "${this.sessionName}": stop terminal cleanup failed: ${R(L)}`);let _=this.finishProcStop(V,H);try{this.opts.onLifecycleChange?.()}catch(L){z.push(L),K(`session "${this.sessionName}": stop final lifecycle write failed: ${R(L)}`)}let B=[...H?[H]:[],...!_&&!H?[Error(this.blockedProcReason??"process stop unconfirmed")]:[],...G,...z];if(B.length===1)throw B[0];if(B.length>1)throw AggregateError(B,`stop failed: ${B.map(R).join("; ")}`);if(Q?.(`✅ ${$}`),J)await A(this.chatId,`\uD83D\uDD34 ${$} (session: ${this.sessionName})`)}async restart($=!1,Z={}){return await this.runLifecycle("restart",()=>this.restartUnlocked($,Z))}async restartUnlocked($=!1,Z={}){let J=Z.announce??!0,Q=Z.onStatus,Y=this.status,V=null;if(!$&&!this.pendingConversationLaunch&&this.pendingConversationMaterialization)V=this.pendingConversationMaterialization,A0(this.sessionName,null),this.pendingConversationMaterialization=null;let X=this.pendingConversationLaunch??this.pendingMaterializationLaunch(),z=this.lastSessionRef;if($&&!X&&z?.cwd===null)try{z=await this.resolveLegacyResumeRef(z),this.lastSessionRef=z,this.lastSessionId=z.sessionId}catch(T){let w=`❌ 旧会话 cwd 校验失败: ${R(T)};请在进程已停时发送 rs 重新选择历史会话`;if(this.status=this.proc?.isAlive()?Y:"stopped",Q?.(w),J)await A(this.chatId,w);return!1}let H=z?.sessionId??null,W=X&&X.kind!=="fresh"?X.source.sessionId:H,G=W?W.slice(0,8):"",_=null;if(!Q&&J&&$&&H){let T=this.proc?this.withModel(`\uD83D\uDD01 重启 ${this.backendLabel(this.proc.provider)}`):this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${G}…`);if(_=await this.openStatusCard("restart",T),_)Q=(w)=>this.setStatusCard(_,w)}let B=J&&!_,L=async(T)=>{if(_)await this.closeStatusCard(_,T)};if(this.bgResumePending=!1,this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.discardOrphanAssistant(),this.currentTurn)this.closeTurnCard("\uD83D\uDD01 已中止,正在重启").catch((T)=>{K(`session "${this.sessionName}": restart current main-card close failed: ${R(T)}`)});let F=this.waitForTurnCloses().catch((T)=>K(`session "${this.sessionName}": restart main-card close failed: ${R(T)}`)),D=null,j=null;if(this.proc){Q?.(`\uD83D\uDED1 停止当前 ${this.backendLabel(this.proc.provider)}`);let T=this.proc;j=T,this.beginProcStop(T);try{await T.kill()}catch(w){D=w}}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 O=(await Promise.allSettled([this.resetBackgroundTasks(),F])).filter((T)=>T.status==="rejected").map((T)=>T.reason);for(let T of O)K(`session "${this.sessionName}": restart terminal cleanup failed: ${R(T)}`);let P=j?this.finishProcStop(j,D):!0,y=[...D?[`kill=${R(D)}`]:[],...!P&&!D?[`kill=${this.blockedProcReason??"process stop unconfirmed"}`]:[],...O.map((T)=>`cleanup=${R(T)}`)];if(y.length>0&&V)try{A0(this.sessionName,V),this.pendingConversationMaterialization=V}catch(T){y.push(`pendingRestore=${R(T)}`)}if(y.length>0){let T=`❌ 旧 ${this.backendLabel()} 进程停止/清理失败: ${y.join("; ")}`;if(this.status="stopped",this.opts.onLifecycleChange?.(),Q?.(T),B)await A(this.chatId,T);return await L(T),!1}let m=X?.kind==="resume"||X?.kind==="fork";if($&&z||m){this.status="starting",this.usageTotalsSeedUnknown=!0,Q?.(this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${G}…`));let T;try{T=this.spawnAgent(z??void 0)}catch(k){let s=`❌ ${this.backendLabel()} 恢复失败: ${R(k)}`;if(K(`session "${this.sessionName}": ${this.selectedProvider} resume failed before spawn: ${R(k)}`),Q?.(s),B)await A(this.chatId,s);return this.status="stopped",this.opts.onLifecycleChange?.(),await L(s),!1}this.attachProc(T);let w=this.backendLabel(),g=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(T,oV):this.waitForProcResumeInit(T,()=>{K(`session "${this.sessionName}": ${this.selectedProvider} resume init still pending after ${nV/1000}s`),Q?.(this.withModel(`⏳ 仍在等待 ${w} init 确认 thread=${G}…`))});Q?.(this.selectedProvider==="claude"?`⏳ 检查 ${w} 恢复启动`:`⏳ 等待 ${w} init 确认`),T.sendInitialize();let N=await g;if(N.state==="error"||N.state==="exit"||N.state==="timeout"){let k=N.error?R(N.error):N.state;K(`session "${this.sessionName}": ${this.selectedProvider} resume failed: ${k}`);let s=N.state==="timeout"?`❌ ${w} 恢复超时`:`❌ ${w} 恢复失败: ${k}`;if(Q?.(s),B)await A(this.chatId,s);return await this.stopOwnedProc(T,1000),this.status="stopped",this.opts.onLifecycleChange?.(),await L(s),!1}if(this.proc!==T||!T.isAlive()){let k=`❌ ${w} 恢复期间已退出`;if(K(`session "${this.sessionName}": ${this.selectedProvider} resume process exited before ready`),Q?.(k),B)await A(this.chatId,k);return this.detachProc(T),this.status="stopped",this.opts.onLifecycleChange?.(),await L(k),!1}let x=this.withModel(this.withWorktreeInstructionNotice(this.selectedProvider==="claude"&&N.state==="ready"?`✅ 已准备恢复上一会话 thread=${G}…`:`✅ 已恢复上一会话 thread=${G}…`));if(Q?.(x),B)await A(this.chatId,x);this.status="idle",this.startedAt=Date.now(),this.opts.onLifecycleChange?.();try{await L(x)}catch(k){K(`session "${this.sessionName}": restart succeeded but status-card close failed: ${R(k)}`),await C(this.chatId,`⚠️ ${x}
|
|
189
|
-
状态卡收尾失败: ${R(k)}`)}return!0}else{if($&&!X){if(Q?.("⚠️ 没有可恢复的上一会话,将以新会话启动"),B)await A(this.chatId,"⚠️ 没有可恢复的上一会话,将以新会话启动")}return this.resetFreshConversationState(),await this.startUnlocked({...Z,freshConversationStateAlreadyReset:!0})}}async startForked($,Z={}){return await this.runLifecycle("start-forked",async()=>{X$($,this.selectedProvider,this.workDir);let J=y2(this.sessionName),Q=this.selectedProvider==="claude"?{launch:$,previousSessionId:this.lastSessionId}:null;if(Q)A0(this.sessionName,Q),this.pendingConversationMaterialization=Q;this.pendingConversationLaunch=$;try{let Y=await this.startUnlocked(Z);if(!Y&&Q)A0(this.sessionName,J),this.pendingConversationMaterialization=J;return Y}catch(Y){if(!Q)throw Y;try{A0(this.sessionName,J),this.pendingConversationMaterialization=J}catch(V){throw AggregateError([Y,V],`fork start and pending-intent restore failed: ${R(Y)}; ${R(V)}`)}throw Y}finally{this.pendingConversationLaunch=null}})}async rollbackTo($,Z,J={}){return await this.runLifecycle("rollback",async()=>{X$($,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,V=this.lastSessionId,X=this.lastSessionRef,z=x1(this.sessionName).slice(),H=x2(this.sessionName),W=y2(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},_=()=>{if(this.lastSessionId=V,this.lastSessionRef=X,X)E2(this.sessionName,X);else h6(this.sessionName,this.selectedProvider);y$(this.sessionName,z,H,W),this.pendingConversationMaterialization=W,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)y$(this.sessionName,Q.anchors,Q.base,Q.pendingLaunch),this.pendingConversationMaterialization=Q.pendingLaunch,B=!0;this.pendingConversationLaunch=$;try{let L;try{L=$.kind==="fresh"?await this.restartUnlocked(!1,J):await this.restartUnlocked(!0,J)}catch(F){let D=null,j=this.proc&&this.proc!==Y?this.proc:null;if(j)try{await this.stopUnlocked("回滚启动事务失败",{announce:!1})}catch(y){D=y}let M=!j||this.proc!==j&&!j.isAlive();if(!M&&!D)D=Error("replacement process stop was not confirmed");let O=null;if(M)try{_()}catch(y){O=y}let P=[F,...D?[D]:[],...O?[O]:[]];if(P.length===1)throw F;throw AggregateError(P,`rollback launch and cleanup failed: ${P.map(R).join("; ")}`)}if(!L)return _(),!1;if(Q)try{if(!B)y$(this.sessionName,Q.anchors,Q.base,Q.pendingLaunch);this.pendingConversationMaterialization=Q.pendingLaunch}catch(F){let D=null,j=this.proc;try{await this.stopUnlocked("回滚分支状态持久化失败",{announce:!1})}catch(y){D=y}let M=!j||this.proc!==j&&!j.isAlive();if(!M&&!D)D=Error("replacement process stop was not confirmed");let O=null;if(M)try{_()}catch(y){O=y}let P=[F,...D?[D]:[],...O?[O]:[]];if(P.length===1)throw F;throw AggregateError(P,`rollback branch commit failed: ${P.map(R).join("; ")}`)}return L}finally{this.pendingConversationLaunch=null}})}dispose(){J1.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 K(`session "${this.sessionName}": ${Q}`),this.lastTurnUserPreview="",Q}let J=this.collectTurnWrites();try{return p8(this.sessionName,{checkpoint:$,preview:this.lastTurnUserPreview.slice(0,80),ts:Date.now(),writes:J}),null}catch(Q){let Y=`分叉 checkpoint 持久化失败: ${R(Q)}`;return K(`session "${this.sessionName}": ${Y}`),Y}finally{this.lastTurnUserPreview=""}}collectTurnWrites(){let $=this.currentTurn;if(!$)return[];let Z=[];for(let J of $.toolByUseId.values())Z.push(...m9(J.name,J.input));return Z}worktreeProjectName(){return T0(this)}worktreeProjectDir(){return d1(this)}spawnDeveloperInstructions(){return TV(this)}worktreeInstructionLoadedNotice(){return S5(this)}withWorktreeInstructionNotice($){return xV(this,$)}worktreeExtraInstruction(){return a4(this)}runWorktreeCommand($,Z){return yV(this,$,Z)}showWorktrees(){return k5(this)}showTasklistPanel(){return VV(this)}onTasklistEnable(){return XV(this)}onTasklistDeletePrompt($){return zV(this,$)}onTasklistDeleteConfirm($){return HV(this,$)}runCompactCommand(){return rY(this)}showModelPanel(){return tY(this)}onModelSelect($,Z="",J="",Q=null){return JV(this,$,Z,J,Q)}onModelEffortSelect($,Z,J="",Q="",Y=""){return this.runLifecycle("model-effort-select",()=>QV(this,$,Z,J,Q,Y))}onProviderSelect($,Z=""){return sY(this,$,Z)}onModelPanelCancel($=""){return ZV(this,$)}onModelCustomPrompt($,Z,J=""){return eY(this,$,Z,J)}consumeModelCustomMessage($,Z){return $V(this,$,Z)}onWorktreeDisband($){return NV(this,$)}showForkList($=""){return IV(this,$)}showBackList($=""){return hV(this,$)}showResumeList($=""){return gV(this,$)}runBtwCommand($){return mV(this,$)}runByeCommand(){return cV(this)}onForkSelect($,Z,J=""){return uV(this,$,Z,J)}onBackSelect($,Z,J=""){return pV(this,$,Z,J)}onResumeSelect($,Z,J=""){return lV(this,$,Z,J)}runCommand($,Z=""){return dY(this,$,Z)}async buildConsoleOpts($,Z){let J=await oJ(),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:[...J1.all].filter((Y)=>Y.isRunning()).map((Y)=>({...Y.peerSnapshot(),isCurrent:Y===this})),usage:$,glmUsage:Z,sysinfo:J}}async buildConsoleCard($){return x9(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:N8(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 Z5();else Z.usage=await b4();if(!await L$($,U.consoleUsage,p2(Z),{notifyCardFailure:!1}))throw Error("console usage element replace rejected")}async mutateStaticCard($,Z,J){let Q=!0;try{await J()}catch(V){Q=!1,K(`session "${this.sessionName}": ${Z} mutation failed: ${R(V)}`)}let Y=!1;try{Y=await K$($,{config:{streaming_mode:!1}})}catch(V){K(`session "${this.sessionName}": ${Z} streaming-off failed: ${R(V)}`)}if(!Q||!Y)return K(`session "${this.sessionName}": ${Z} state retained after checked MISS mutation=${Q} streamingOff=${Y} card=${$.slice(0,12)}`),!1;try{await C$($)}catch(V){return K(`session "${this.sessionName}": ${Z} dispose failed: ${R(V)}`),!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 o$($.cardId);let Y=await L$($.cardId,U.footer,L4(Q,U.footer)),V=await S1($.cardId,B4(Q),{type:"insert_after",targetElementId:U.footer}),X=await S1($.cardId,F4(Q.sysinfo),{type:"insert_after",targetElementId:U.consoleProjects}),z=await S1($.cardId,p2(Q),{type:"insert_after",targetElementId:U.consoleHost});if(!Y||!V||!X||!z){await C(this.chatId,"⚠️ 控制台卡片结构写入失败,请重新发送 hi。"),await this.mutateStaticCard($.cardId,"console structure",async()=>{});return}V$($.cardId),await K$($.cardId,m$({durationSec:J,suffix:Z})),this.patchConsoleUsageLater($.cardId)}async showConsole(){let $=await this.buildConsoleCard(void 0),Z=await p(this.chatId,$);if(!Z)return;(async()=>{let J="";try{J=await r$(Z),h$(J,4)}catch(Q){K(`session "${this.sessionName}": console card conversion failed: ${R(Q)}`);return}await this.mutateStaticCard(J,"console usage",()=>this.patchConsoleUsage(J))})().catch((J)=>K(`session "${this.sessionName}": console async update rejected: ${R(J)}`))}interrupt(){if(!this.proc)return;K(`session "${this.sessionName}": interrupt`),this.proc.sendInterrupt()}async startColdUserTurn($,Z,J){if(!this.pendingConversationMaterialization)this.resetFreshConversationState();this.pendingTurnInputs.push($);let Q=this.beginTurnOpen();try{let V=await this.openTurnCard(Q,J,"user_message",{initialFooter:"Waiting...(0s)",startThinking:!1,directStart:!0});if(!V||this.currentTurn!==V)return;let X=this.startFooterTimer(V.cardId,`\uD83D\uDE80 启动 ${this.backendLabel()}`,(G)=>this.withModel(G)),z=`\uD83D\uDE80 启动 ${this.backendLabel()}`,H=await this.startUnlocked({announce:!1,freshConversationStateAlreadyReset:!0,onStatus:(G)=>{z=G,X.setStatus(G)}});if(X.stop(),await o$(V.cardId),!H){this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),await this.closeTurnCard(z.startsWith("❌")?z:"❌ 启动失败",{forcePush:!0});return}let W=this.proc;if(!W?.isAlive()){await this.closeTurnCard(`❌ ${this.backendLabel()} 启动后已退出`,{forcePush:!0});return}this.startThinkingFooter(V),W.sendUserText(Z,[]),this.pendingUserMessageCount++,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 A(this.chatId,`❌ ${Y}。请重试 stop/restart,或等待旧进程退出。`);return}if(this.clearStaleIdleQueueState("user_message"),this.startingAgy||this.runningAgy){await A(this.chatId,"⏳ agy 任务正在执行;请等待完成,或发送 stop 打断后再继续。");return}if(this.proc?.isAlive()&&!this.currentTurn&&!this.openingTurn&&this.pendingUserMessageCount===0&&this.pendingMidTurnMsgs.length===0)await this.stopIdleMismatchedProcessUnlocked();let V=this.currentTurn!==null||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0;this.lastUserOpenId=J;let z=(Z.length?Z.map((W)=>`[file: ${W}]`).join(" ")+`
|
|
190
|
-
`:"")+$,H=(W)=>{this.pendingReactionIds.set(W,""),(async()=>{let G=await P$(W,"OneSecond");if(!G)return;if(this.pendingReactionIds.has(W))this.pendingReactionIds.set(W,G);else if(this.currentBatchReactionIds.has(W))this.currentBatchReactionIds.set(W,G);else B$(W,G)})().catch((G)=>{K(`session "${this.sessionName}": reaction tracking failed: ${R(G)}`)})};if(!this.isRunning()){if(this.openingTurn||this.currentTurn){if(this.pendingMidTurnMsgs.push({text:$,wireText:z,userOpenId:J,msgId:Q}),Q)H(Q);return}await this.startColdUserTurn($,z,J);return}if(this.currentTurn!==null){if(this.pendingMidTurnMsgs.push({text:$,wireText:z,userOpenId:J,msgId:Q}),Q)H(Q);return}if(!this.openingTurn&&this.initCount>=1){let W=this.proc,G=this.procEpoch,_=this.beginTurnOpen(W,G);try{this.pendingTurnInputs.push($);let B=await this.openTurnCard(_,J,"user_message");if(!B||this.currentTurn!==B)return;if(this.proc!==W||this.procEpoch!==G||!W.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel(W.provider)} 已退出`);return}W.sendUserText(z,[]),this.pendingUserMessageCount++,this.status="working"}finally{this.releaseTurnOpen(_)}return}if(this.openingTurn||this.pendingUserMessageCount>0){if(this.pendingMidTurnMsgs.push({text:$,wireText:z,userOpenId:J,msgId:Q}),Q)H(Q);return}if(this.pendingTurnInputs.push($),this.proc.sendUserText(z,[]),this.pendingUserMessageCount++,V&&Q)H(Q)}hasPendingAsk(){return EY(this)}onMultiMessageInbound($,Z,J,Q){return uQ(this,$,Z,J,Q)}clearMultiMsgBuffer($){Y5(this,$)}onAskMessageAnswer($,Z,J){return TY(this,$,Z,J)}onAskAnswer($,Z,J,Q){return xY(this,$,Z,J,Q)}onAskCustomAnswer($,Z,J,Q){return L5(this,$,Z,J,Q)}onPermissionDecision($,Z,J){return CY(this,$,Z,J)}persistResumableSessionId($=!1){let Z=this.proc,J=Z?.provider==="claude"?this.pendingConversationMaterialization:null,Q=Z?.sessionId;if(!Z)return null;if(!Q){if(!J)return null;let V=Error("Claude pending fork did not provide a materialized session id");if(K(`session "${this.sessionName}": ${V.message}`),$)throw V;return V.message}let Y={provider:Z.provider,sessionId:Q,cwd:this.workDir};if(J&&(Q===J.launch.source.sessionId||J.previousSessionId!==null&&Q===J.previousSessionId)){let V=Error(`Claude fork did not materialize an independent session id (${Q})`);if(K(`session "${this.sessionName}": ${V.message}`),$)throw V;return V.message}try{E2(this.sessionName,Y)}catch(V){let X=`会话恢复点持久化失败: ${R(V)}`,z=this.resumePersistenceError!==X;if(this.resumePersistenceError=X,Z.provider===this.selectedProvider)this.lastSessionRef=Y,this.lastSessionId=Q;if(K(`session "${this.sessionName}": ${X}`),$)throw V;if(z)C(this.chatId,`⚠️ ${X};当前进程可继续,但 daemon 重启前请先解决本机状态目录写入问题。`);return X}if(Z.provider===this.selectedProvider)this.lastSessionRef=Y,this.lastSessionId=Q;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 K(`session "${this.sessionName}": ${"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker"}`),"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker";try{return A0(this.sessionName,null),this.pendingConversationMaterialization=null,null}catch(J){let Q=`Claude 待生成分支标记清除失败: ${R(J)}`;return K(`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(tZ(this.bgStore())),this.onBackgroundTaskChanged()}bgTaskOwns($){return this.backgroundTasks.some((Z)=>Z.toolUseId===$)||this.pendingBgTasks.some((Z)=>Z.toolUseId===$)}onBackgroundTaskChanged(){if(!B0(this.backgroundTasks)){if(this.backgroundCard)this.settleBackgroundCard().catch((Z)=>{K(`session "${this.sessionName}": background settle failed: ${R(Z)}`)});return}if(!this.backgroundCard&&!this.openingBackground){this.openBackgroundCard().catch((Z)=>{K(`session "${this.sessionName}": background open failed: ${R(Z)}`)});return}this.scheduleBackgroundRefresh()}async openBackgroundCard(){let $=this.beginBackgroundOpen();if(!$)return;let Z=this.backgroundTasks.slice();try{let J=J6(Z,Date.now(),Z1()),Q=await p(this.chatId,J);if(!Q){if(this.ownsBackgroundOpen($))K(`session "${this.sessionName}": background card send failed`);return}let Y;try{Y=await r$(Q)}catch(V){K(`session "${this.sessionName}": background card id_convert failed: ${V}`);return}if(h$(Y,Z.length),!this.ownsBackgroundOpen($)){await this.terminalizeSupersededCard(Y,"⚠️ 后台任务世代已切换,本卡已作废",!1);return}if(this.backgroundCard={messageId:Q,cardId:Y},this.backgroundDetailAdded=new Set(Z.map((V)=>V.id)),this.backgroundDetailAdding.clear(),K(`session "${this.sessionName}": background card opened cardId=${Y.slice(0,12)} tasks=${Z.length}`),!B0(this.backgroundTasks)){this.settleBackgroundCard().catch((V)=>{K(`session "${this.sessionName}": background settle-after-open failed: ${R(V)}`)});return}this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}finally{this.releaseBackgroundOpen($)}}startBackgroundRefreshTick(){if(this.backgroundRefreshTick)return;let $=()=>{if(!this.backgroundCard||!B0(this.backgroundTasks))return;let Z=Z1(),J=Date.now(),Q=1/0;for(let Y of this.backgroundTasks){if(T$(Y))continue;let V=L0(J-Y.startedAt,Z).nextDelayMs;if(V<Q)Q=V}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)return;if(this.backgroundRefreshTimer)return;this.backgroundRefreshTimer=setTimeout(()=>{this.backgroundRefreshTimer=null,this.refreshBackgroundCardFull()},1500)}refreshBackgroundCardFull(){let $=this.backgroundCard;if(!$)return;let Z=Date.now(),J=Z1();for(let Q of this.backgroundTasks)if(!this.backgroundDetailAdded.has(Q.id)){if(this.backgroundDetailAdding.has(Q.id))continue;this.backgroundDetailAdding.add(Q.id),S1($.cardId,P1(Q,Z,J)).then((Y)=>{if(Y)this.backgroundDetailAdded.add(Q.id);else K(`session "${this.sessionName}": background panel add MISS task=${Q.id}`)}).finally(()=>{this.backgroundDetailAdding.delete(Q.id)})}else c($.cardId,K2.panel(Q.id),P1(Q,Z,J));c0($.cardId,y8(this.backgroundTasks))}async resetBackgroundTasks(){if(this.invalidateBackgroundOpen(),this.backgroundTasks.some(($)=>!T$($))){let $=Date.now();this.backgroundTasks=this.backgroundTasks.map((Z)=>T$(Z)?Z:{...Z,status:"killed",endTime:Z.endTime??$})}if(this.pendingBgTasks=[],this.backgroundCard){await this.settleBackgroundCard();return}if(this.stopBackgroundRefreshTick(),this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;this.backgroundTasks=[],this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear()}async settleBackgroundCard(){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 o$($.cardId),await z0($.messageId,C8(Z)),V$($.cardId),!await K$($.cardId,m$({suffix:"\uD83E\uDDED 后台任务已结束"})))throw Error("background history streaming-off rejected");if(await C$($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((Q)=>!T$(Q)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),K(`session "${this.sessionName}": background card settled cardId=${$.cardId.slice(0,12)} remaining=${this.backgroundTasks.length}`)}finally{if(this.settlingBackgroundCard=!1,this.backgroundCard===$&&B0(this.backgroundTasks))this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(this.backgroundTasks.length>0)this.onBackgroundTaskChanged()}async migrateBackgroundCard(){let $=this.backgroundCard;if(!$)return;if(this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;this.stopBackgroundRefreshTick();let Z=this.backgroundTasks.filter(T$).length;if(await o$($.cardId),Z>0)await z0($.messageId,C8(this.backgroundTasks));else await z0($.messageId,Q6());if(V$($.cardId),!await K$($.cardId,m$({suffix:"\uD83E\uDDED 已迁移至新卡"})))throw Error("background migration streaming-off rejected");await C$($.cardId),this.backgroundCard=null,this.backgroundTasks=this.backgroundTasks.filter((Q)=>!T$(Q)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),K(`session "${this.sessionName}": background card migrated cardId=${$.cardId.slice(0,12)} terminal=${Z} active=${this.backgroundTasks.length}`)}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,V=!1,X=(z,H)=>{$.on(z,(W)=>{if(!Q()){if(!Y)Y=!0,K(`session "${this.sessionName}": ignore stale ${$.provider} event=${String(z)} epoch=${J} currentEpoch=${this.procEpoch}`);return}if(z!=="exit"&&(this.stoppingProc===$||this.blockedProc===$)){if(!V)V=!0,K(`session "${this.sessionName}": ignore ${$.provider} event=${String(z)} while process stop is pending`);return}H(W)})};X("error",(z)=>{K(`session "${this.sessionName}": ${$.provider} process error: ${z}`)}),X("init",()=>{if(q7(),this.persistResumableSessionId(!0),this.initCount++,K(`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)return;let z=this.pendingUserMessageCount>0,H=!z&&this.bgResumePending;if(!z&&!H)return;this.bgResumePending=!1;let W=this.lastUserOpenId;if(z)this.pendingUserMessageCount=0,this.currentBatchReactionIds=this.pendingReactionIds,this.pendingReactionIds=new Map;let G=z?[...this.currentBatchReactionIds.keys()]:[],_=()=>{for(let L of G){let F=this.currentBatchReactionIds.get(L);if(this.currentBatchReactionIds.delete(L),F)B$(L,F)}},B=this.beginTurnOpen($,J);(async()=>{try{let L=await this.openTurnCard(B,W,z?"user_message":"bg_task_resume");if(!Q()){if(K(`session "${this.sessionName}": ${$.provider} became stale while opening turn card epoch=${J}`),L&&this.currentTurn===L)await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);_();return}if(!L||this.currentTurn!==L){if(!this.ownsTurnOpen(B)){_();return}if(B.sawResult&&B.terminalSuffix)C(this.chatId,B.terminalSuffix);if(z)K(`session "${this.sessionName}": init-path openTurnCard failed — sendInterrupt + release reactions`),this.proc?.sendInterrupt(),_();else if(this.bgResumeCardless=!0,B.sawResult)B.sawResult=!1,K(`session "${this.sessionName}": bg-resume openTurnCard failed, result already arrived — flushing orphan now`),this.flushOrphanAssistantToChat("bg-resume open failed, result already arrived");else K(`session "${this.sessionName}": bg-resume openTurnCard failed — orphan text flush will cover the output`)}else if(B.sawResult)B.sawResult=!1,K(`session "${this.sessionName}": result raced card-open — closing freshly-opened turn card now`),await this.closeTurnCard(B.terminalSuffix,{forcePush:B.terminalForcePush,hasFreshResult:!0}),this.status="idle";else this.status="working"}finally{this.releaseTurnOpen(B)}})().catch((L)=>{K(`session "${this.sessionName}": init turn-open handler failed: ${R(L)}`)})}),X("turn_started",()=>{this.persistResumableSessionId();let z=this.proc?.lastTotalUsage;if(this.usageTotalsSeedUnknown&&!z){this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;return}this.currentTurnUsageBaseline=z?{...z}:null,this.currentTurnUsageBaselineKnown=!0}),X("token_usage",({totalUsage:z})=>{if(this.persistResumableSessionId(),z)this.usageTotalsSeedUnknown=!1}),X("turn_plan_updated",(z)=>{this.handleTurnPlanUpdated(z)}),X("plan_delta",(z)=>{this.handlePlanDelta(z)}),X("context_compacted",(z)=>{this.handleContextCompacted(z)}),X("rate_limits_updated",(z)=>{if($.provider==="codex")CQ(z)}),X("thread_goal_updated",(z)=>{this.handleThreadGoalUpdated(z)}),X("thread_goal_cleared",()=>{this.handleThreadGoalCleared()}),X("assistant_text",({text:z})=>{this.appendAssistant(z)}),X("assistant_block_stop",()=>{this.finalizeCurrentAssistantSegment(),this.onMainThreadAdvance()}),X("tool_use",({id:z,name:H,input:W,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(eZ({active:this.backgroundTasks,pending:this.pendingBgTasks},G,z,H,W)),this.onBackgroundTaskChanged();return}if(MY(this,z,H,W),!G)this.onMainThreadAdvance();if(!G&&(H==="Task"||H==="Agent"))this.lastMainTaskToolUseId=z}),X("tool_result",({tool_use_id:z,content:H,is_error:W,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(Z6({active:this.backgroundTasks,pending:this.pendingBgTasks},G,z,H,W)),this.onBackgroundTaskChanged();return}OY(this,z,H,W)}),X("can_use_tool",(z)=>{NY(this,z)}),X("hook_callback",(z)=>{this.proc?.sendHookResponse(z.request_id,{})}),X("result",(z)=>{let H=this.persistResumableSessionId(),W=H?null:this.consumePendingConversationMaterialization(),G=[H,W].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 P=this.proc?.lastResult.subtype??"unknown",y=this.proc?.lastResult.is_error===!0;K(`session "${this.sessionName}": SDK result after user stop subtype=${P} isError=${y} — ignored`),this.status="idle";return}let _=z?.is_error!==!0?this.recordTurnAnchor(z?.checkpoint):null;if(z?.is_error===!0)this.lastTurnUserPreview="";if(!this.currentTurn&&!this.openingTurn)this.flushOrphanAssistantToChat("result with no turn card");let B=this.pendingMidTurnMsgs.length>0,L=this.proc?.lastResult.is_error===!0,F=this.proc?.lastResult.subtype??"success",D,j=!1,M=this.proc?this.backendLabel(this.proc.provider):this.backendLabel(),O=[G,_].filter(Boolean).join(";")||null;if(O)D=`⚠️ ${O}`,j=!0;else if(B)D=L?`⚠️ ${M} ${F},用户已介入`:"\uD83D\uDCE8 转交新卡";else if(L)D=`⚠️ ${M} ${F}`,j=!0;if(this.openingTurnOwner)this.openingTurnOwner.terminalSuffix=D,this.openingTurnOwner.terminalForcePush=j;if(O&&!this.currentTurn&&!this.openingTurn)C(this.chatId,`⚠️ ${O}`);if(K(`session "${this.sessionName}": SDK result subtype=${F} isError=${L} midBuffer=${this.pendingMidTurnMsgs.length} forcePush=${j}`),this.closeTurnCard(D,{forcePush:j,hasFreshResult:!0}).catch((P)=>{K(`session "${this.sessionName}": result card close failed: ${R(P)}`)}),this.status="idle",B)this.drainMidTurnAndOpen().catch((P)=>{K(`session "${this.sessionName}": mid-turn drain failed: ${R(P)}`)})}),X("bg_task_started",(z)=>{let H=z.tool_use_id??this.lastMainTaskToolUseId??void 0;K(`session "${this.sessionName}": bg_task_started task=${z.task_id} type=${z.task_type??"-"} subagent=${z.subagent_type??"-"} toolUseId=${H?.slice(0,8)??"-"} desc=${(z.description??"").slice(0,40)}`),this.applyBgStore(rZ(this.bgStore(),{...z,tool_use_id:H})),this.onBackgroundTaskChanged()}),X("bg_task_progress",(z)=>{this.applyBgStore(oZ(this.bgStore(),z)),this.onBackgroundTaskChanged()}),X("bg_task_updated",(z)=>{this.applyBgStore(aZ(this.bgStore(),z)),this.onBackgroundTaskChanged()}),X("bg_task_settled",(z)=>{if(K(`session "${this.sessionName}": bg_task_settled task=${z.task_id} status=${z.status}`),this.applyBgStore(sZ(this.bgStore(),z)),this.onBackgroundTaskChanged(),$.provider==="claude"&&!this.currentTurn&&!this.openingTurn&&this.initCount>=1)this.bgResumePending=!0}),X("subagent_step",(z)=>{this.applyBgStore($6(this.bgStore(),z.thread_id,z.item_id,z.tool,z.phase,z.brief)),this.onBackgroundTaskChanged()}),X("exit",({code:z,signal:H,expected:W})=>{if(K(`session "${this.sessionName}": ${$.provider} exited code=${z} signal=${H} expected=${W}`),this.stoppingProc===$||this.blockedProc===$){K(`session "${this.sessionName}": blocked/stopping ${$.provider} exit confirmed`),this.detachProc($),this.status="stopped",this.opts.onLifecycleChange?.();return}let G=this.backendLabel($.provider),_=`code=${z??"null"}, signal=${H??"null"}`,B=W?`\uD83D\uDED1 ${G} 已退出`:`⚠️ ${G} 异常退出 (${_})`;if(this.currentTurn)this.closeTurnCard(B).catch((F)=>{K(`session "${this.sessionName}": process-exit current main-card close failed: ${R(F)}`)});let L=this.waitForTurnCloses().catch((F)=>{K(`session "${this.sessionName}": process-exit main-card close failed: ${R(F)}`)});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 F=await Promise.allSettled([L,this.resetBackgroundTasks()]);for(let D of F)if(D.status==="rejected")K(`session "${this.sessionName}": process-exit terminal cleanup failed: ${R(D.reason)}`);if(!W)await A(this.chatId,`⚠️ ${G} 异常退出 (${_})。回复任意消息将重新启动。`)}).catch((F)=>{K(`session "${this.sessionName}": process-exit cleanup rejected: ${R(F)}`)})})}accumulateResultStats(){let $=this.proc?.lastResult;if(!$)return;let Z=this.currentTurnUsageBaselineKnown?fZ(this.proc?.lastTotalUsage,this.currentTurnUsageBaseline):this.proc?.provider==="claude"&&$.usage?{...$.usage}:null;this.lastTurnUsage=Z,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;let J=IZ(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 r8(Z)}contextLimitForDisplay($=this.proc){return o8($?.lastContextWindow)}async drainMidTurnAndOpen(){if(this.pendingMidTurnMsgs.length===0)return;let $=this.proc,Z=this.procEpoch;if(!$?.isAlive())return;let J=this.pendingMidTurnMsgs;this.pendingMidTurnMsgs=[];let Q=this.beginTurnOpen($,Z);try{for(let H of J)if(this.pendingTurnInputs.push(H.text),H.msgId){let W=this.pendingReactionIds.get(H.msgId)??"";this.currentBatchReactionIds.set(H.msgId,W),this.pendingReactionIds.delete(H.msgId)}let Y=J.map((H)=>H.wireText).join(`
|
|
181
|
+
${G}`)}return{slug:Q,chatName:V,branch:Y,worktreePath:W,removedWorktree:!1}}function g5($){if(!X1($))throw Error(`project directory does not exist: ${$}`);let Z=F$($,["rev-parse","--show-toplevel"]).trim();if(h5(Z)!==h5($))throw Error(`${$} is not the git repository root (${Z})`)}function IV($,Z){let J=F$($,["rev-parse","--abbrev-ref","HEAD"]).trim();if(J!==Z)throw Error(`${$} is on ${J}, expected ${Z}`)}function WB($,Z,J){let Q=zB($);if(!Q?.startsWith(a1))return null;let Y=Q.slice(a1.length);if(!W1(Y))throw Error(`invalid worktree branch "${Q}"`);let V=s1(Z,J,Y);if(XZ($)!==XZ(V))return null;let X=GB($,KB(Y));return X?{path:X,slug:Y}:null}function zB($){if(!X1($))return null;try{return F$($,["branch","--show-current"]).trim()||null}catch(Z){if(_B(Z))return null;throw Z}}function KB($){return $.split("-",1)[0]??$}function GB($,Z){let J=`agents.${Z}.md`,Q=JB($).filter((Y)=>Y.toLowerCase()===J).sort();if(Q.length>1)throw Error(`multiple worktree instruction files match ${J}: ${Q.join(", ")}`);return Q[0]?SV($,Q[0]):null}function qB($,Z){try{return F$($,["show-ref","--verify","--quiet",`refs/heads/${Z}`]),!0}catch{return!1}}function gV($,Z,J){let Q=F$($,["rev-parse",Z]).trim(),Y=F$($,["rev-parse","HEAD"]).trim();if(Q===Y)return J?"active":"merged";if(yV($,Z,"HEAD"))return"merged";if(yV($,"HEAD",Z))return"active";return"stale"}function yV($,Z,J){try{return F$($,["merge-base","--is-ancestor",Z,J]),!0}catch{return!1}}function m5($){let Z=new Map,J=F$($,["worktree","list","--porcelain"]),Q="";for(let Y of J.split(`
|
|
182
|
+
`)){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 F$($,Z){try{return ZB("git",Z,{cwd:$,encoding:"utf8",stdio:["ignore","pipe","pipe"]})}catch(J){throw Error(c5(J))}}function c5($){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 _B($){return/not a git repository/i.test(c5($))}var a1="work/",XB,HB="AI-",VZ;var u5=T(()=>{XB=/^[A-Za-z0-9][A-Za-z0-9._-]{0,62}$/,VZ=new Map});function w0($){return kV(e$($.sessionName)??$.sessionName)}function e1($){return l0(w0($))}function mV($){let Z=e$($.sessionName)??$.sessionName,J=w0($),Q=l0(J);if(J===Z)return Q;let Y=Z.slice(J.length+1,-1);return s1(Q,J,Y)}function cV($){let Z=$.currentProvider()==="claude"?CV:xV,J=HZ($);return J?`${Z}
|
|
183
|
+
${J}`:Z}function l5($){return HZ($)?"已载入wt特殊约定":null}function uV($,Z){let J=l5($);return J?`${Z}
|
|
184
|
+
${J}`:Z}function HZ($){let Z=w0($),J=bV($.workDir,e1($),Z);if(!J)return null;return[`你要把下面这份额外的工作树约定视为和AGENTS.md一样重要。来源文件:${J.path}`,"",`# Additional AGENTS.md instructions for ${$.workDir}`,"","<INSTRUCTIONS>",J.content,"</INSTRUCTIONS>"].join(`
|
|
185
|
+
`)}async function pV($,Z,J){if(!Z){await d5($);return}let Q=W1(Z);if(!Q){await E($.chatId,"❌ 名称无效。用英文/数字/._-,最长 63。");return}if(H8(Q)){await E($.chatId,`❌ ${Q} 是 AI 自动化系统保留 worktree,不能用 wt 命令操作。`);return}if(!J){await E($.chatId,"❌ 找不到发起人,不能拉群。");return}let Y=w0($),V=e1($);try{await H1(V,async()=>{let X;try{X=fV(V,Y,Q)}catch(H){await E($.chatId,`❌ wt 失败: ${j(H)}`);return}try{let H=await W9(X.chatName,J),W=H.created?"已创建":H.joined?"已加入":"已在群内";if(!await l($.chatId,a2({slug:Q,branch:X.branch,status:W})))await C($.chatId,`❌ wt 卡片失败: ${Q}`);if(!await l(H.chatId,a2({slug:Q,branch:X.branch,status:"就绪",body:"开始吧。"})))await C(H.chatId,`❌ wt 卡片失败: ${Q}`)}catch(H){await E($.chatId,`❌ wt 已建,拉群失败: ${j(H)}`)}})}catch(X){await E($.chatId,`❌ wt 失败: ${j(X)}`)}}async function lV($,Z){let J=w0($),Q=e1($);return await H1(Q,async()=>{return await LB($,J,Q,Z)})}async function LB($,Z,J,Q){let Y=vV(J,Z),V=Y.filter((W)=>W.state==="merged"&&!W.mounted).length,X=Y.filter((W)=>W.state!=="merged"||W.mounted),H=await e8();return i9({projectName:Z,projectDir:J,hiddenMergedUnmountedCount:V,notice:Q,entries:X.map((W)=>{let z=H.get(W.chatName)??[],G=$$.get(W.chatName),q=G&&z.includes(G)?G:z.length===1?z[0]:null;return{slug:W.slug,chatName:W.chatName,branch:W.branch,state:W.state,path:W.worktreePath??W.expectedPath,mounted:W.mounted,dirtyCount:W.dirtyCount,statusLine:W.statusLine,error:W.error,chatId:q,duplicateChatCount:z.length,protected:H8(W.slug)}})})}async function d5($){try{let Z=await lV($);if(!await l($.chatId,Z))await C($.chatId,"❌ wt 列表失败")}catch(Z){await E($.chatId,`❌ wt 列表失败: ${j(Z)}`)}}async function p5($,Z,J,Q){try{return{ok:Z,message:J,card:await lV($,{type:Q,content:J})}}catch(Y){let V=`列表刷新失败: ${j(Y)}`;return K(`session "${$.sessionName}": wt action panel refresh failed: ${j(Y)}`),{ok:!1,message:`${J}
|
|
186
|
+
${V}`,card:a2({slug:"wt",branch:"work/*",status:J,body:V,template:"red"})}}}async function dV($,Z){let J=W1(Z);if(!J)return p5($,!1,"❌ 名称无效","error");if(H8(J))return p5($,!1,`❌ ${J} 是 AI 自动化系统保留 worktree,不能解散。`,"error");let Q=w0($),Y=e1($),V;try{V=await H1(Y,async()=>{let X=t1(Q,J);if($.hasRunningPeerSession(X))return{ok:!1,message:`❌ 解散 ${J} 失败: Codex 正在运行,请先在 ${X} 群里 stop 或 kill。`,type:"error"};I5(Y,Q,J);let H=await K9(X),W=hV(Y,Q,J);return{ok:!0,message:[`✅ ${J} 已解散`,W.removedWorktree?"dir removed":"dir missing",H.disbanded?"group removed":"group missing",W.branch].join(`
|
|
187
|
+
`),type:"success"}})}catch(X){V={ok:!1,message:`❌ 解散 ${J} 失败: ${j(X)}`,type:"error"}}return p5($,V.ok,V.message,V.type)}var iV=T(()=>{NV();n$();n();v();u5()});import{closeSync as UB,openSync as DB,readSync as PB,readdirSync as AB,statSync as MB}from"node:fs";import{randomUUID as n5}from"node:crypto";import{join as OB}from"node:path";function zZ($){return e$($.sessionName)??$.sessionName}function oV($){let Z=Z9($,i5);return i5.add(Z),Z}function rV($){i5.delete($)}function $2($){let Z=nV.get($);if(!Z)Z=new Map,nV.set($,Z);let J=Date.now();for(let[Q,Y]of Z){let V=Y.status==="consumed"?EB:RB,X=Y.consumedAt??Y.createdAt;if(J-X>V)Z.delete(Q)}return Z}function xB($,Z){return $.provider===Z.provider&&$.tokenSourceId===Z.tokenSourceId&&$.model===Z.model&&$.effort===Z.effort}function aV($,Z,J,Q){let Y={id:n5(),mode:Z,requesterOpenId:J,provider:$.selectedProvider,sourceSessionId:$.lastSessionId,workDir:$.workDir,baseName:zZ($),routing:$.conversationRouting(),createdAt:Date.now(),status:"open",choices:Q};return $2($).set(Y.id,Y),Y}function o5($,Z,J,Q,Y){let V=$2($).get(J);if(!V||V.mode!==Z)return{error:"这张选择卡已过期,请重新发送命令"};if(!Y||V.requesterOpenId!==Y)return{error:"只有打开这张选择卡的用户可以执行;请自行发送命令重新打开"};if(V.status!=="open")return{error:"这张选择卡已执行或正在处理,请勿重复点击"};if(V.provider!==$.selectedProvider||V.workDir!==$.workDir||V.sourceSessionId!==$.lastSessionId||!xB(V.routing,$.conversationRouting()))return{error:"这张卡对应的 provider、目录或源会话已经变化,请重新发送命令"};let X=V.choices.get(Q);if(!X)return{error:"无效的选择项,这张卡可能已过期"};return V.status="processing",{panel:V,choice:X}}function WZ($){$.status="consumed",$.consumedAt=Date.now()}function CB($){return{kind:"fork",source:$.source,through:$}}function NB($){return v1($.sessionName).filter((Z)=>Z.checkpoint.provider===$.selectedProvider&&Z.checkpoint.source.cwd===$.workDir)}function yB($){let Z=w2($.sessionName);if(Z===null||Z.kind==="fresh")return Z;try{return K$(Z,$.selectedProvider,$.workDir),Z}catch{return null}}function SB($){let Z=N6($),J;try{J=AB(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 V=OB(Z,Y),X;try{X=MB(V).mtimeMs}catch(H){throw Error(`读取 Claude 会话元数据失败 (${Y}): ${H?.message??H}`)}Q.push({provider:"claude",sessionId:Y.slice(0,-6),cwd:$,preview:wB(V),ts:X})}return Q.sort((Y,V)=>V.ts-Y.ts)}function kB($){let Z=$.slice().sort((Y,V)=>V.ts-Y.ts),J=Date.now()-jB,Q=Z.filter((Y)=>Y.ts>=J).length;return Z.slice(0,Math.min(TB,Math.max(10,Q)))}function wB($){let Z="",J=null;try{J=DB($,"r");let Y=Buffer.alloc(65536),V=PB(J,Y,0,65536,0);Z=Y.subarray(0,V).toString("utf8")}catch(Y){throw Error(`读取 Claude 会话摘要失败 (${$}): ${Y?.message??Y}`)}finally{if(J!==null)UB(J)}let Q="";for(let Y of Z.split(`
|
|
188
|
+
`)){let V=Y.trim();if(!V)continue;let X;try{X=JSON.parse(V)}catch{continue}if(X.type==="queue-operation"&&X.operation==="enqueue"&&typeof X.content==="string"){let H=X.content.trim();if(H)return H.slice(0,80)}if(!Q&&X.type==="user"&&X.message){let H=bB(X.message);if(H)Q=H}}return Q.slice(0,80)}function bB($){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 tV($,Z,J){if(!J){await E($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let Q=NB($),Y=yB($),V=new Map,X=[];for(let G=0;G<Q.length;G++){let q=Q[G];if(G===0&&Y===null)continue;let B=n5(),L=G===0?Y:CB(Q[G-1].checkpoint);V.set(B,{kind:Z,launch:L,branchBase:Y,seedAnchors:Q.slice(0,G),writes:Q.slice(G).flatMap((F)=>F.writes)}),X.push({choiceId:B,preview:q.preview,ts:q.ts})}X.reverse();let H=aV($,Z,J,V),W=o9({projectName:zZ($),panelId:H.id,mode:Z,entries:X}),z;try{z=await l($.chatId,W)}catch(G){throw $2($).delete(H.id),G}if(!z)$2($).delete(H.id),await C($.chatId,`❌ ${Z==="fork"?"fk":"bk"} 列表发送失败`)}function sV($,Z){return tV($,"fork",Z)}function eV($,Z){return tV($,"back",Z)}async function $X($,Z){if(!Z){await E($.chatId,"❌ 找不到发起人,无法创建安全选择卡。");return}let J;try{J=$.selectedProvider==="codex"?await $.listCodexConversations():SB($.workDir)}catch(W){await C($.chatId,`❌ 历史会话读取失败: ${W instanceof Error?W.message:W}`);return}let Q=new Map,Y=kB(J).map((W)=>{let z=n5();return Q.set(z,{kind:"resume",launch:{kind:"fork",source:{provider:W.provider,sessionId:W.sessionId,cwd:W.cwd}},sourcePreview:W.preview,sourceTs:W.ts,sourceStatus:W.status}),{choiceId:z,preview:W.preview,ts:W.ts}}),V=aV($,"resume",Z,Q),X=r9({projectName:zZ($),panelId:V.id,entries:Y}),H;try{H=await l($.chatId,X)}catch(W){throw $2($).delete(V.id),W}if(!H)$2($).delete(V.id),await C($.chatId,"❌ rs 历史列表发送失败")}async function ZX($,Z){if(!Z){await E($.chatId,"❌ 找不到发起人,无法建临时群。");return}if(!$.opts.onCreateTempSession){await E($.chatId,"❌ 临时群能力未就绪(daemon 未注入回调)。");return}let J=oV(zZ($));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{rV(J)}if(!Q.ok){await E($.chatId,`❌ 建临时会话失败: ${Q.error??"未知"}`);return}await E($.chatId,`✅ 已创建 ${J}。临时群不会自动删除;在该群发送 bye 可停止并解散。`)}async function JX($){if(!e$($.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 QX($,Z,J,Q){let Y=o5($,"fork",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:V,choice:X}=Y;try{if(X.kind!=="fork")return{ok:!1,message:"选择项类型不匹配"};if(!$.opts.onCreateTempSession)return{ok:!1,message:"临时群能力未就绪"};let H=oV(V.baseName);K(`session-temp: fork ${$.sessionName} → ${H} (${X.launch.kind})`),await E($.chatId,`\uD83D\uDD31 正在分叉到 ${H}…`);let W;try{W=await $.opts.onCreateTempSession({chatName:H,userOpenId:Q,workDir:V.workDir,routing:V.routing,launch:X.launch,branchBase:X.branchBase,seedAnchors:X.seedAnchors})}finally{rV(H)}if(!W.ok)return{ok:!1,message:`分叉失败: ${W.error??"未知"}`};return{ok:!0,message:`已分叉到 ${H};原会话和磁盘文件未回滚`}}catch(H){return{ok:!1,message:`分叉失败: ${H instanceof Error?H.message:H}`}}finally{WZ(V)}}async function YX($,Z,J,Q){let Y=o5($,"back",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:V,choice:X}=Y;try{if(X.kind!=="back")return{ok:!1,message:"选择项类型不匹配"};let H="";try{if(!await l($.chatId,a9({projectName:V.baseName,entries:X.writes})))H=";文件变更记录卡发送失败"}catch(G){H=`;文件变更记录卡发送失败: ${G instanceof Error?G.message:G}`}if(K(`session-temp: back ${$.sessionName} (${X.launch.kind}, writes=${X.writes.length})`),!await $.rollbackTo(X.launch,{anchors:X.seedAnchors,base:X.branchBase}))return{ok:!1,message:`回退失败;原会话绑定未改,请检查日志后重试${H}`};if(V.routing.provider==="claude")return{ok:!0,message:`本群已准备 Claude 新分支;发送下一条消息时生成并接入,旧会话未删除,磁盘文件未回滚${H}`};return{ok:!0,message:`本群已改接新会话${$.lastSessionId?` ${z$($.lastSessionId)}`:""};旧会话未删除,磁盘文件未回滚${H}`}}catch(H){return{ok:!1,message:`回退失败: ${H instanceof Error?H.message:H}`}}finally{WZ(V)}}async function VX($,Z,J,Q){let Y=o5($,"resume",Z,J,Q);if("error"in Y)return{ok:!1,message:Y.error,replaceCard:!1};let{panel:V,choice:X}=Y;if(X.kind!=="resume")throw WZ(V),Error("resume panel contained a non-resume choice");let H=X.launch.source.sessionId,W=$.lastSessionId,z=(q,B)=>({projectName:V.baseName,provider:X.launch.source.provider,selectedPreview:X.sourcePreview,selectedTs:X.sourceTs,sourceSessionId:H,...X.sourceStatus?{sourceStatus:X.sourceStatus}:{},previousSessionId:W,newSessionId:q,bindingState:B}),G=(q,B,L,F=null)=>({ok:q,message:B,resumePresentation:z(F,L)});try{if($.isRunning())return G(!1,"当前群已经启动了新进程;为避免误杀,请先停止后重新发送 rs","unchanged");if(X.sourceStatus==="active")return G(!1,"所选 Codex 会话仍在运行;请先在原位置停止后再创建完整分支","unchanged");if(K(`session-temp: history fork ${$.sessionName} ← ${X.launch.source.provider} ${H}`),!await $.rollbackTo(X.launch,{anchors:[],base:X.launch,pendingLaunch:X.launch.source.provider==="claude"?{launch:X.launch,previousSessionId:W}:null}))return G(!1,"历史分支创建失败;原会话绑定未改,请检查日志后重试","unchanged");if(X.launch.source.provider==="claude")return G(!0,"Claude 独立分支已准备;首条消息时生成并接入新会话","prepared");let B=$.lastSessionId;if(!B)return G(!1,"历史分支已启动,但后端没有返回新会话 id","unknown");if(B===H||W&&B===W)return G(!1,"后端没有返回独立的新会话 id;为避免误判,本次不标记为恢复成功","unknown",B);return G(!0,"已创建并接入独立分支;源会话未修改","changed",B)}catch(q){return G(!1,`历史分支创建失败: ${q instanceof Error?q.message:q}`,"unknown")}finally{WZ(V)}}var jB=86400000,RB=1800000,EB=3600000,TB=40,nV,i5;var XX=T(()=>{n();n$();v();k6();R1();nV=new WeakMap,i5=new Set});import{existsSync as HX}from"node:fs";import{isAbsolute as fB}from"node:path";function a5($,Z=new Set){if($ instanceof v8)return $;if(!$||typeof $!=="object"&&typeof $!=="function"||Z.has($))return null;if(Z.add($),$ instanceof AggregateError)for(let J of $.errors){let Q=a5(J,Z);if(Q)return Q}if($ instanceof Error&&$.cause!==void 0)return a5($.cause,Z);return null}function hB($){return $.itemId||$.turnId||"__latest__"}function WX($){let Z=[];if($.itemId)Z.push(`item:${$.itemId}`);if($.turnId)Z.push(`turn:${$.threadId??$.sessionId??"-"}:${$.turnId}`);return Z}function IB($){let Z=null;for(let J of $.contextCompactionPending.keys())Z=J;return Z}function gB($,Z){if(!$)return Z;return{...$,...Z,phase:"end"}}function z1(){return f.runtime?.live_elapsed??"bucket"}function KX($,Z){return`${$} (${M0(Date.now()-Z,z1()).label})`}var mB="Thinking...",cB="Writing...",uB="Working...",r5=1e4,KZ=120000,pB=50,W8=5,lB=256,GZ=1e4,zX=250,K1;var GX=T(()=>{E1();D6();C1();N$();k$();N7();k6();a0();n$();n();v();I9();i4();o4();L5();VY();DY();vY();gY();y5();iY();WV();KV();PV();RV();iV();XX();R1();K1=class K1{sessionName;chatId;opts;static all=new Set;proc=null;lifecycleTail=Promise.resolve();lifecycleSequence=0;procEpoch=0;stoppingProc=null;blockedProc=null;blockedProcReason=null;procSourceRevisions=new WeakMap;currentTurn=null;contextCompactionReceipts=new Map;contextCompactionOwnerIds=new WeakMap;contextCompactionOwnerSequence=0;lastManualContextCompactionCompletedAt=0;lastManualContextCompactionWasAnonymous=!1;backgroundTasks=[];pendingBgTasks=[];backgroundCard=null;settlingBackgroundCard=!1;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;runningAgy=null;startingAgy=!1;agyForwardPrompts=new Map;taskBoard=[];constructor($,Z,J={}){this.sessionName=$;this.chatId=Z;this.opts=J;K1.all.add(this);let Q=V9($);this.selectedProvider=Q?.provider??"claude",this.selectedModel=Q?.model??null,this.selectedEffort=Q?.effort??null,this.selectedTokenSourceId=this.deriveTokenSourceId(Q);let Y=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((X)=>X.model===this.selectedModel))this.selectedModel=Y.defaultModel}if(this.selectedModel)K(`session "${$}": restored selected provider=${this.selectedProvider} model=${this.selectedModel} effort=${this.selectedEffort??"unset"}`);if(this.lastSessionRef=i0($,this.selectedProvider),this.lastSessionId=this.lastSessionRef?.sessionId??null,this.lastSessionId)K(`session "${$}": restored ${this.selectedProvider} lastSessionId=${this.lastSessionId}`);let V=b2($);if(V)if(this.selectedProvider!=="claude")w$($,[],null,null),K(`session "${$}": cleared pending Claude fork after provider changed`);else{K$(V.launch,"claude",this.workDir);let X=this.lastSessionId===V.previousSessionId,H=this.lastSessionRef,W=!X&&H?.provider==="claude"&&H.cwd===this.workDir&&H.sessionId!==V.launch.source.sessionId&&H.sessionId!==V.previousSessionId;if(!X&&!W)throw Error(`pending Claude fork has inconsistent resume binding for session "${$}"`);this.pendingConversationMaterialization=V,K(`session "${$}": restored ${W?"materialized":"pending"} Claude fork source=${V.launch.source.sessionId}`)}}peerSnapshot(){return{name:this.sessionName,status:this.status,uptimeMs:this.startedAt?Date.now()-this.startedAt:void 0}}get workDir(){return mV(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 g8(J==="codex"?"codex":"claude")[0]?.id??null}currentTokenSource(){return Y$(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=Y$($.tokenSourceId);if(Z&&Z.agent!==$.provider)throw Error(`token source "${Z.id}" belongs to ${Z.agent}, not ${$.provider}`);if(this.selectedProvider!==$.provider)w$(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$.provider,this.selectedTokenSourceId=$.tokenSourceId,this.selectedModel=$.model,this.selectedEffort=$.effort,this.lastSessionRef=i0(this.sessionName,$.provider),this.lastSessionId=this.lastSessionRef?.sessionId??null,Y9(this.sessionName,$.provider,$.model,$.effort,$.tokenSourceId)}async listCodexConversations(){if(this.selectedProvider!=="codex")throw Error("Codex history requested for a non-Codex session");if(!h2())throw Error("Codex 未登录 ChatGPT 账号");let $=this.currentTokenSource();if(this.selectedTokenSourceId&&(!$||!$.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或选择其他账号`);let Z=$?.enabled?$:void 0,J=Z?(H)=>Z.spawnEnv(H):void 0,Q=new F2({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Z?.id??null,transformEnv:J}),Y=null,V=null;try{Y=await Q.listConversations()}catch(H){V=H}let X=null;try{await Q.kill(2000)}catch(H){X=H}if(V&&X)throw AggregateError([V,X],`Codex history query and cleanup failed: ${j(V)}; ${j(X)}`);if(V)throw V;if(X)throw X;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=y6(this.workDir,$.sessionId);if(!HX(J))throw Error(`旧 Claude 会话不属于当前 cwd,或 transcript 不存在: ${z$($.sessionId)}`);Z={...$,cwd:this.workDir}}else{if(!h2())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 F2({workDir:this.workDir,launch:{kind:"fresh"},tokenSourceId:Q?.id??null,transformEnv:Q?(H)=>Q.spawnEnv(H):void 0}),V=null;try{Z=await Y.readConversationRef($.sessionId)}catch(H){V=H,Z=$}let X=null;try{await Y.kill(2000)}catch(H){X=H}if(V&&X)throw AggregateError([V,X],`Codex legacy resume lookup and cleanup failed: read=${j(V)}; cleanup=${j(X)}`);if(V)throw V;if(X)throw X}return K$({kind:"resume",source:Z},this.selectedProvider,this.workDir),k2(this.sessionName,Z),Z}hasRunningPeerSession($){return[...K1.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:L2}return L2}claudeEffortForSpawn(){return this.selectedProvider==="claude"&&j0(this.selectedEffort)?this.selectedEffort:O0}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"?O0:L2)}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"?O0:L2);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"?`${W0($.provider)} · ${J}`:J}withModel($,Z){let J=this.modelEffortLabel(Z);return $.includes(J)?$:`${$} · ${J}`}replaceFooterContent($,Z){return u($,O.footer,this.footerElement(Z))}footerElement($){return{tag:"markdown",element_id:O.footer,content:$.trim()||" "}}modelLine($){return this.modelEffortLabel($)}backendLabel($=this.selectedProvider){return W0($)}pendingConversationLaunch=null;pendingConversationMaterialization=null;lastTurnUserPreview="";pendingCodexTurnAnchors=[];pendingMaterializationLaunch(){let $=this.pendingConversationMaterialization;if(!$)return null;if(K$($.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($){let Z=this.pendingConversationLaunch??this.pendingMaterializationLaunch()??($?{kind:"resume",source:$}:{kind:"fresh"});K$(Z,this.selectedProvider,this.workDir);let J=this.currentTokenSource();if(this.selectedTokenSourceId&&(!J||!J.enabled))throw Error(`token source "${this.selectedTokenSourceId}" 不可用,请重新配置或在 model 面板选择其他账号`);let Q=J?.enabled?J:void 0,Y=Q?(H)=>Q.spawnEnv(H):void 0,V=Q?Q.resolveSpawnModel(this.selectedModel??Q.defaultModel):this.modelForSpawn();if(this.selectedProvider==="claude"){p7();let H=Z.kind==="fresh"?void 0:Z.source.sessionId,W=Z.kind==="fork"?Z.through:void 0;if(W&&(W.provider!=="claude"||W.kind!=="assistant-message"))throw Error(`Claude cannot fork from ${W.provider}/${W.kind} checkpoint`);let z=new S6({workDir:this.workDir,model:V,effort:this.claudeEffortForSpawn(),resumeSessionId:H,resumeSessionAt:W?.id,forkSession:Z.kind==="fork",appendSystemPrompt:this.spawnDeveloperInstructions(),profile:t8(this.worktreeProjectName()),...Q?.settingSources?{settingSources:Q.settingSources}:{},tokenSourceId:Q?.id??null,transformEnv:Y});return this.procSourceRevisions.set(z,Q?.spawnRevision??null),z}let X=new F2({workDir:this.workDir,model:V,effort:this.effortForSpawn(),launch:Z,appendSystemPrompt:this.spawnDeveloperInstructions(),tokenSourceId:Q?.id??null,transformEnv:Y});return this.procSourceRevisions.set(X,Q?.spawnRevision??null),X}async applyModelSelection($,Z,J,Q){await this.runLifecycle("apply-model-selection",()=>this.applyModelSelectionUnlocked($,Z,J,Q))}async applyModelSelectionUnlocked($,Z,J,Q){if(this.selectedProvider!==$)w$(this.sessionName,[],null,null),this.pendingConversationMaterialization=null;this.selectedProvider=$,this.selectedTokenSourceId=Q??this.selectedTokenSourceId;let V=Y$(this.selectedTokenSourceId);if(V)this.selectedModel=Z||null,this.selectedEffort=J??V.models.find((X)=>X.model===Z)?.defaultEffort??V.models[0]?.defaultEffort??null;else this.selectedModel=$==="codex"?null:Z,this.selectedEffort=$==="codex"?null:J;this.lastSessionRef=i0(this.sessionName,$),this.lastSessionId=this.lastSessionRef?.sessionId??null,Q9(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;K(`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(H){Y=H}Q=await this.settleProcResumableState(J);let V=this.finishProcStop(J,Y);this.opts.onLifecycleChange?.();let X=[...!V?[Y??Error(this.blockedProcReason??"process stop unconfirmed")]:[],...Q?[Error(Q)]:[]];if(X.length===1)throw X[0];if(X.length>1)throw AggregateError(X,`idle process stop failed: ${X.map(j).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;K(`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(X){Q=X}J=await this.settleProcResumableState(Z);let Y=this.finishProcStop(Z,Q);this.opts.onLifecycleChange?.();let V=[...!Y?[Q??Error(this.blockedProcReason??"process stop unconfirmed")]:[],...J?[Error(J)]:[]];if(V.length===1)throw V[0];if(V.length>1)throw AggregateError(V,`idle process stop failed: ${V.map(j).join("; ")}`);return!0}startFooterTimer($,Z,J=(Q)=>Q){let Q=Date.now(),Y=Z,V=!1,X=()=>{if(V)return;this.replaceFooterContent($,J(KX(Y,Q)))},H=null,W=()=>{if(V)return;let{nextDelayMs:z}=M0(Date.now()-Q,z1());H=setTimeout(()=>{X(),W()},Math.max(1,Math.ceil(z)))};return X(),W(),{setStatus(z){Y=z,X()},stop(){if(V=!0,H)clearTimeout(H)},elapsedSec(){return((Date.now()-Q)/1000).toFixed(1)}}}async openStatusCard($,Z,J="blue"){let Q=Date.now(),Y=g9({sessionName:this.sessionName,title:$,status:KX(Z,Q),template:J}),V=await l(this.chatId,Y);if(!V)return K(`session "${this.sessionName}": status card send failed title=${$}`),await C(this.chatId,`❌ 创建状态卡片失败: ${$}`),null;let X;try{X=await $0(V)}catch(H){return K(`session "${this.sessionName}": status card id_convert failed title=${$}: ${H}`),await C(this.chatId,`❌ 状态卡片初始化失败: ${$}`),null}return p$(X,1),{cardId:X,title:$,timer:this.startFooterTimer(X,Z,(H)=>o2($,H))}}setStatusCard($,Z){$?.timer.setStatus(Z)}async closeStatusCard($,Z){if(!$)return;$.timer.stop();let J=$.timer.elapsedSec(),Q=o2($.title,`${Z} (${J}s)`);await l$($.cardId);let Y=await W$($.cardId,O.footer,this.footerElement(Q));X$($.cardId);let V=await B$($.cardId,i$({durationSec:J,suffix:Z}));if(Y&&V)await b$($.cardId);else{let X=`footer=${Y?"ok":"MISS"}, settings=${V?"ok":"MISS"}`;K(`session "${this.sessionName}": status card terminal transaction incomplete card=${$.cardId.slice(0,12)} ${X}`),await C(this.chatId,`⚠️ 状态卡片终态写入失败 (${X}):${Z}`)}}beginAgyForwardToCodex($,Z=""){return SY(this,$,Z)}runAgyCommand($){return kY(this,$)}stopAgyTask($="\uD83D\uDED1 agy 已打断"){return bY(this,$)}async runLifecycle($,Z){let J=this.lifecycleTail,Q;this.lifecycleTail=new Promise((V)=>{Q=V}),await J;let Y=++this.lifecycleSequence;K(`session "${this.sessionName}": lifecycle#${Y} ${$} begin`);try{return await Z()}finally{Q(),K(`session "${this.sessionName}": lifecycle#${Y} ${$} end`)}}async waitForLifecycleIdle(){await this.lifecycleTail}beginTurnOpen($=this.proc,Z=this.procEpoch,J=!1){let Q={token:++this.turnOpenSequence,proc:$,procEpoch:Z,sawResult:!1,terminalForcePush:!1,pendingCompactions:[],backendTurnStarted:J};return this.openingTurnOwner=Q,this.openingTurn=!0,Q}ownsTurnOpen($){return this.openingTurnOwner===$&&this.proc===$.proc&&this.procEpoch===$.procEpoch}releaseTurnOpen($){if(this.openingTurnOwner!==$)return;this.openingTurnOwner=null,this.openingTurn=!1}invalidateTurnOpen(){this.openingTurnOwner=null,this.openingTurn=!1}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.stoppingProc===$)this.stoppingProc=null;if(this.blockedProc===$)this.blockedProc=null,this.blockedProcReason=null;return this.procEpoch++,!0}beginProcStop($){this.stoppingProc=$}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?j(Z):"kill returned while process still reports alive",K(`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(V){Z=`Codex 会话落盘确认失败: ${j(V)}`}let Q=$.conversationMaterializationFailure?.();if(Q&&$.isConversationResumable?.()!==!0)Z=`Codex 会话落盘确认失败: ${j(Q)}`;let Y=this.persistResumableSessionId(!1,$,!1);return[Z,Y].filter(Boolean).join(";")||null}resetFreshConversationState(){this.turnCounter=0,this.pendingConversationMaterialization=null,w$(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"&&!h2()){if(this.status="stopped",this.opts.onLifecycleChange?.(),J?.("❌ Codex 未登录 ChatGPT 账号"),Z)await E(this.chatId,"❌ Codex 未登录 ChatGPT 账号。\n请在服务器上运行 `codex login` 后再试。");return!1}if(!HX(this.workDir)){if(J?.(`\uD83C\uDD95 创建项目目录 ~/${this.sessionName}`),Z)await E(this.chatId,`\uD83C\uDD95 目录 ~/${this.sessionName} 不存在,正在创建…`);try{L9(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{Y=this.spawnAgent()}catch(G){let q=`${this.backendLabel()} 启动失败: ${j(G)}`;if(K(`session "${this.sessionName}": ${q}`),J?.(`❌ ${q}`),Z)await E(this.chatId,`❌ ${q}`);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}this.attachProc(Y);let V=this.backendLabel(),X=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(Y,zX):null;J?.(this.selectedProvider==="claude"?`⏳ 检查 ${V} 启动`:`⏳ 等待 ${V} init`);let H,W=null;try{if(Y.sendInitialize(),this.selectedProvider==="codex")H=Y.initializationPromise?.()}catch(G){H=void 0,W=G}let z=W?{state:"error",error:W}:this.selectedProvider==="claude"?await X:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(H),()=>{K(`session "${this.sessionName}": codex init still pending after ${r5/1000}s`),J?.(this.withModel(`⏳ 仍在等待 ${V} init 确认`))});if(z.state==="error"||z.state==="exit"){let G=z.error?j(z.error):z.state;K(`session "${this.sessionName}": ${this.selectedProvider} init failed: ${G}`);let B=await this.stopOwnedProc(Y,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,L=`❌ ${V} 启动失败: ${G}${B}`;if(J?.(L),Z)await E(this.chatId,L);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(z.state==="timeout"){K(`session "${this.sessionName}": ${this.selectedProvider} init wait timeout (${KZ/1000}s)`);let q=await this.stopOwnedProc(Y,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,B=`❌ ${V} 启动超时: ${KZ/1000} 秒内初始化事务未完成${q}`;if(J?.(B),Z)await E(this.chatId,B);return this.status="stopped",this.opts.onLifecycleChange?.(),!1}if(this.proc!==Y||!Y.isAlive()){let G=`${V} 启动期间已退出`;if(K(`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(`
|
|
189
|
+
`))}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=(H,W)=>{if(Q)return;Q=!0,clearTimeout(V),clearTimeout(X),J({state:H,error:W})},V=setTimeout(()=>{if(Q)return;try{Z?.()}catch(H){Y("error",H)}},r5),X=setTimeout(()=>{Y("timeout",Error(`codex init timed out after ${KZ/1000}s`))},KZ);$.then(()=>Y("init"),(H)=>Y("error",H))})}async waitForProcEarlyFailure($,Z){return await new Promise((J)=>{let Q=!1,Y=(z,G)=>{if(Q)return;Q=!0,clearTimeout(V),$.off("init",X),$.off("error",H),$.off("exit",W),J({state:z,error:G})},V=setTimeout(()=>Y("ready"),Z),X=()=>Y("init"),H=(z)=>Y("error",z),W=(z)=>Y("exit",z);$.once("init",X),$.once("error",H),$.once("exit",W)})}releaseAllReactions(){for(let[$,Z]of[...this.pendingReactionIds.entries(),...this.currentBatchReactionIds.entries()])if(Z)P$($,Z);this.pendingReactionIds=new Map,this.currentBatchReactionIds=new Map}clearStaleIdleQueueState($){if(this.initCount<1||this.currentTurn||this.openingTurn||this.pendingUserMessageCount===0)return;K(`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)P$(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,Y=await this.stopAgyTask(`\uD83D\uDED1 ${$}`);if(!this.proc){if(this.status="stopped",this.opts.onLifecycleChange?.(),Q?.(Y?`✅ ${$}`:"⚪ session 当前未运行"),J&&!Y)await E(this.chatId,`⚪ session "${this.sessionName}" 当前未运行`);return}let V=this.proc,X=this.persistResumableSessionId(!1,V,!1),H=null;if(Q?.(`\uD83D\uDED1 停止 ${this.backendLabel(this.proc.provider)}`),K(`session "${this.sessionName}": stop (${$})`),this.invalidateTurnOpen(),this.invalidateBackgroundOpen(),this.currentTurn)this.closeTurnCard(`\uD83D\uDED1 ${$}`).catch((D)=>{K(`session "${this.sessionName}": stop current main-card close failed: ${j(D)}`)});let W=this.waitForTurnCloses().catch((D)=>K(`session "${this.sessionName}": stop main-card close failed: ${j(D)}`));this.beginProcStop(V),this.status="stopped";let z=[];try{this.opts.onLifecycleChange?.()}catch(D){z.push(D),K(`session "${this.sessionName}": stop intent lifecycle write failed: ${j(D)}`)}let G=V.conversationMaterializationBarrier?.();if(G){try{await G}catch(D){H=`Codex 会话落盘确认失败: ${j(D)}`}X=this.persistResumableSessionId(!1,V,!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 q=null;try{await V.kill()}catch(D){q=D}let B=V.conversationMaterializationFailure?.();if(B&&V.isConversationResumable?.()!==!0)H=`Codex 会话落盘确认失败: ${j(B)}`;X=this.persistResumableSessionId(!1,V,!1);let F=(await Promise.allSettled([this.resetBackgroundTasks(),W])).filter((D)=>D.status==="rejected").map((D)=>D.reason);for(let D of F)K(`session "${this.sessionName}": stop terminal cleanup failed: ${j(D)}`);let U=this.finishProcStop(V,q);try{this.opts.onLifecycleChange?.()}catch(D){z.push(D),K(`session "${this.sessionName}": stop final lifecycle write failed: ${j(D)}`)}let R=[...q?[q]:[],...!U&&!q?[Error(this.blockedProcReason??"process stop unconfirmed")]:[],...F,...z,...X?[Error(X)]:[],...H&&V.isConversationResumable?.()!==!0?[Error(H)]:[]];if(R.length===1)throw R[0];if(R.length>1)throw AggregateError(R,`stop failed: ${R.map(j).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,V=this.status,X=null;if(!$&&!this.pendingConversationLaunch&&this.pendingConversationMaterialization)X=this.pendingConversationMaterialization,T0(this.sessionName,null),this.pendingConversationMaterialization=null;let H=this.pendingConversationLaunch??this.pendingMaterializationLaunch(),W=this.lastSessionRef;if($&&!H&&W?.cwd===null)try{W=await this.resolveLegacyResumeRef(W),this.lastSessionRef=W,this.lastSessionId=W.sessionId}catch(A){let k=this.invalidateMissingCodexResume(W.sessionId,A,J),s=k?`❌ 旧会话不可恢复: ${j(A)};${k}`:`❌ 旧会话 cwd 校验失败: ${j(A)};请在进程已停时发送 rs 重新选择历史会话`;if(this.status=this.proc?.isAlive()?V:"stopped",Y?.(s),Q)await E(this.chatId,s);return!1}let z=W?.sessionId??null,G=H&&H.kind!=="fresh"?H.source.sessionId:z,q=G?z$(G):"",B=null,L=(A=this.proc)=>{if(!$||H||A?.provider!=="codex"||A.isConversationResumable?.()!==!0)return;B=this.persistResumableSessionId(!1,A,!1),W=this.lastSessionRef,z=W?.sessionId??null,G=z,q=G?z$(G):""},F=null;if(!Y&&Q&&$&&z){let A=this.proc?this.withModel(`\uD83D\uDD01 重启 ${this.backendLabel(this.proc.provider)}`):this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${q}`);if(F=await this.openStatusCard("restart",A),F)Y=(k)=>this.setStatusCard(F,k)}let U=Q&&!F,R=async(A)=>{if(F)await this.closeStatusCard(F,A)},D=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((A)=>{K(`session "${this.sessionName}": restart current main-card close failed: ${j(A)}`)});let P=this.waitForTurnCloses().catch((A)=>K(`session "${this.sessionName}": restart main-card close failed: ${j(A)}`)),M=null,x=null;if(this.proc){let A=this.proc;Y?.(`\uD83D\uDED1 停止当前 ${this.backendLabel(A.provider)}`),x=A,this.beginProcStop(A);let k=A.conversationMaterializationBarrier?.();if(k)try{await k}catch(c){B=`Codex 会话落盘确认失败: ${j(c)}`}if(L(A),$&&!H&&B&&!D&&A.isAlive()){if(this.stoppingProc===A)this.stoppingProc=null;this.status=V;let c=`❌ ${this.backendLabel(A.provider)} 恢复点尚未安全落盘,已保留当前进程: ${B}`;if(K(`session "${this.sessionName}": abort restart before kill: ${B}`),Y?.(c),U)await E(this.chatId,c);return await R(c),!1}try{await A.kill()}catch(c){M=c}let s=A.conversationMaterializationFailure?.();if(s&&A.isConversationResumable?.()!==!0)B=`Codex 会话落盘确认失败: ${j(s)}`;L(A)}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 N=(await Promise.allSettled([this.resetBackgroundTasks(),P])).filter((A)=>A.status==="rejected").map((A)=>A.reason);for(let A of N)K(`session "${this.sessionName}": restart terminal cleanup failed: ${j(A)}`);let m=x?this.finishProcStop(x,M):!0,h=[...M?[`kill=${j(M)}`]:[],...!m&&!M?[`kill=${this.blockedProcReason??"process stop unconfirmed"}`]:[],...N.map((A)=>`cleanup=${j(A)}`),...B?[`resume=${B}`]:[]];if(h.length>0&&X)try{T0(this.sessionName,X),this.pendingConversationMaterialization=X}catch(A){h.push(`pendingRestore=${j(A)}`)}if(h.length>0){let A=`❌ 旧 ${this.backendLabel()} 进程停止/清理失败: ${h.join("; ")}`;if(this.status="stopped",this.opts.onLifecycleChange?.(),Y?.(A),U)await E(this.chatId,A);return await R(A),!1}let w=H?.kind==="resume"||H?.kind==="fork";if($&&W||w){this.status="starting",this.usageTotalsSeedUnknown=!0,Y?.(this.withModel(`\uD83D\uDD01 恢复上一会话 thread=${q}`));let A;try{A=this.spawnAgent(W??void 0)}catch(M$){let t$=`❌ ${this.backendLabel()} 恢复失败: ${j(M$)}`;if(K(`session "${this.sessionName}": ${this.selectedProvider} resume failed before spawn: ${j(M$)}`),Y?.(t$),U)await E(this.chatId,t$);return this.status="stopped",this.opts.onLifecycleChange?.(),await R(t$),!1}this.attachProc(A);let k=this.backendLabel(),s=this.selectedProvider==="claude"?this.waitForProcEarlyFailure(A,zX):null;Y?.(this.selectedProvider==="claude"?`⏳ 检查 ${k} 恢复启动`:`⏳ 等待 ${k} init 确认`);let c,a$=null;try{if(A.sendInitialize(),this.selectedProvider==="codex")c=A.initializationPromise?.()}catch(M$){c=void 0,a$=M$}let J$=a$?{state:"error",error:a$}:this.selectedProvider==="claude"?await s:await this.waitForCodexInitialization(this.requireCodexInitializationPromise(c),()=>{K(`session "${this.sessionName}": codex resume init still pending after ${r5/1000}s`),Y?.(this.withModel(`⏳ 仍在等待 ${k} init 确认 thread=${q}`))});if(J$.state==="error"||J$.state==="exit"||J$.state==="timeout"){let M$=J$.state==="error"?this.invalidateMissingCodexResume(G,J$.error,J):null,t$=[J$.error?j(J$.error):J$.state,M$].filter(Boolean).join(";");K(`session "${this.sessionName}": ${this.selectedProvider} resume failed: ${t$}`);let E3=await this.stopOwnedProc(A,1000)?"":`;进程终止未确认: ${this.blockedProcReason??"未知原因"}`,xZ=J$.state==="timeout"?`❌ ${k} 恢复超时${E3}`:`❌ ${k} 恢复失败: ${t$}${E3}`;if(Y?.(xZ),U)await E(this.chatId,xZ);return this.status="stopped",this.opts.onLifecycleChange?.(),await R(xZ),!1}if(this.proc!==A||!A.isAlive()){let M$=`❌ ${k} 恢复期间已退出`;if(K(`session "${this.sessionName}": ${this.selectedProvider} resume process exited before ready`),Y?.(M$),U)await E(this.chatId,M$);return this.detachProc(A),this.status="stopped",this.opts.onLifecycleChange?.(),await R(M$),!1}let U1=this.withModel(this.withWorktreeInstructionNotice(this.selectedProvider==="claude"&&J$.state==="ready"?`✅ 已准备恢复上一会话 thread=${q}`:`✅ 已恢复上一会话 thread=${q}`));if(Y?.(U1),U)await E(this.chatId,U1);this.status="idle",this.startedAt=Date.now(),this.opts.onLifecycleChange?.();try{await R(U1)}catch(M$){K(`session "${this.sessionName}": restart succeeded but status-card close failed: ${j(M$)}`),await C(this.chatId,`⚠️ ${U1}
|
|
190
|
+
状态卡收尾失败: ${j(M$)}`)}return!0}else{if($&&!H){if(Y?.("⚠️ 没有可恢复的上一会话,将以新会话启动"),U)await E(this.chatId,"⚠️ 没有可恢复的上一会话,将以新会话启动")}return this.resetFreshConversationState(),await this.startUnlocked({...Z,freshConversationStateAlreadyReset:!0})}}async startForked($,Z={}){return await this.runLifecycle("start-forked",async()=>{K$($,this.selectedProvider,this.workDir);let J=b2(this.sessionName),Q=this.selectedProvider==="claude"?{launch:$,previousSessionId:this.lastSessionId}:null;if(Q)T0(this.sessionName,Q),this.pendingConversationMaterialization=Q;this.pendingConversationLaunch=$;try{let Y=await this.startUnlocked(Z);if(!Y&&Q)T0(this.sessionName,J),this.pendingConversationMaterialization=J;return Y}catch(Y){if(!Q)throw Y;try{T0(this.sessionName,J),this.pendingConversationMaterialization=J}catch(V){throw AggregateError([Y,V],`fork start and pending-intent restore failed: ${j(Y)}; ${j(V)}`)}throw Y}finally{this.pendingConversationLaunch=null}})}async rollbackTo($,Z,J={}){return await this.runLifecycle("rollback",async()=>{K$($,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,V=this.lastSessionId,X=this.lastSessionRef,H=v1(this.sessionName).slice(),W=w2(this.sessionName),z=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},q=!1,B=()=>{if(q)this.lastSessionId=null,this.lastSessionRef=null,b1(this.sessionName,"codex");else if(this.lastSessionId=V,this.lastSessionRef=X,X)k2(this.sessionName,X);else b1(this.sessionName,this.selectedProvider);w$(this.sessionName,H,W,z),this.pendingConversationMaterialization=z,this.turnCounter=G.turnCounter,this.currentGoal=G.currentGoal,this.cumStats=G.cumStats,this.lastTurnDelta=G.lastTurnDelta,this.currentTurnUsageBaseline=G.currentTurnUsageBaseline,this.currentTurnUsageBaselineKnown=G.currentTurnUsageBaselineKnown,this.lastTurnUsage=G.lastTurnUsage,this.usageTotalsSeedUnknown=G.usageTotalsSeedUnknown},L=!1;if(Q?.pendingLaunch)w$(this.sessionName,Q.anchors,Q.base,Q.pendingLaunch),this.pendingConversationMaterialization=Q.pendingLaunch,L=!0;this.pendingConversationLaunch=$;let F=(U)=>{q=X?.provider==="codex"&&X.sessionId===U};try{let U;try{U=$.kind==="fresh"?await this.restartUnlocked(!1,J,F):await this.restartUnlocked(!0,J,F)}catch(R){let D=null,P=this.proc&&this.proc!==Y?this.proc:null;if(P)try{await this.stopUnlocked("回滚启动事务失败",{announce:!1})}catch(N){D=N}let M=!P||this.proc!==P&&!P.isAlive();if(!M&&!D)D=Error("replacement process stop was not confirmed");let x=null;if(M)try{B()}catch(N){x=N}let y=[R,...D?[D]:[],...x?[x]:[]];if(y.length===1)throw R;throw AggregateError(y,`rollback launch and cleanup failed: ${y.map(j).join("; ")}`)}if(!U)return B(),!1;if(Q)try{if(!L)w$(this.sessionName,Q.anchors,Q.base,Q.pendingLaunch);this.pendingConversationMaterialization=Q.pendingLaunch}catch(R){let D=null,P=this.proc;try{await this.stopUnlocked("回滚分支状态持久化失败",{announce:!1})}catch(N){D=N}let M=!P||this.proc!==P&&!P.isAlive();if(!M&&!D)D=Error("replacement process stop was not confirmed");let x=null;if(M)try{B()}catch(N){x=N}let y=[R,...D?[D]:[],...x?[x]:[]];if(y.length===1)throw R;throw AggregateError(y,`rollback branch commit failed: ${y.map(j).join("; ")}`)}return U}finally{this.pendingConversationLaunch=null}})}dispose(){K1.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 K(`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 K(`session "${this.sessionName}": ${"Codex rollout 长期未确认,延迟 checkpoint 队列已满"} thread=${Z.sessionId}`),"Codex rollout 长期未确认,延迟 checkpoint 队列已满";return this.pendingCodexTurnAnchors.push({proc:Z,anchor:J}),K(`session "${this.sessionName}": defer Codex turn checkpoint until rollout confirmation thread=${Z.sessionId} checkpoint=${$.id}`),null}return this.appendTurnAnchor(J)}appendTurnAnchor($){try{return s8(this.sessionName,$),null}catch(Z){let J=`分叉 checkpoint 持久化失败: ${j(Z)}`;return K(`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)K(`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(...e9(J.name,J.input));return Z}worktreeProjectName(){return w0(this)}worktreeProjectDir(){return e1(this)}spawnDeveloperInstructions(){return cV(this)}worktreeInstructionLoadedNotice(){return l5(this)}withWorktreeInstructionNotice($){return uV(this,$)}worktreeExtraInstruction(){return HZ(this)}runWorktreeCommand($,Z){return pV(this,$,Z)}showWorktrees(){return d5(this)}showTasklistPanel(){return AV(this)}onTasklistEnable(){return MV(this)}onTasklistDeletePrompt($){return OV(this,$)}onTasklistDeleteConfirm($){return jV(this,$)}runCompactCommand(){return zV(this)}showModelPanel(){return qV(this)}onModelSelect($,Z="",J="",Q=null){return UV(this,$,Z,J,Q)}onModelEffortSelect($,Z,J="",Q="",Y=""){return this.runLifecycle("model-effort-select",()=>DV(this,$,Z,J,Q,Y))}onProviderSelect($,Z=""){return _V(this,$,Z)}onModelPanelCancel($=""){return FV(this,$)}onModelCustomPrompt($,Z,J=""){return BV(this,$,Z,J)}consumeModelCustomMessage($,Z){return LV(this,$,Z)}onWorktreeDisband($){return dV(this,$)}showForkList($=""){return sV(this,$)}showBackList($=""){return eV(this,$)}showResumeList($=""){return $X(this,$)}runBtwCommand($){return ZX(this,$)}runByeCommand(){return JX(this)}onForkSelect($,Z,J=""){return QX(this,$,Z,J)}onBackSelect($,Z,J=""){return YX(this,$,Z,J)}onResumeSelect($,Z,J=""){return VX(this,$,Z,J)}runCommand($,Z=""){return HV(this,$,Z)}async buildConsoleOpts($,Z){let J=await GQ(),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:[...K1.all].filter((Y)=>Y.isRunning()).map((Y)=>({...Y.peerSnapshot(),isCurrent:Y===this})),usage:$,glmUsage:Z,sysinfo:J}}async buildConsoleCard($){return m9(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:g8(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 B5();else Z.usage=await d4();if(!await W$($,O.consoleUsage,r2(Z),{notifyCardFailure:!1}))throw Error("console usage element replace rejected")}async mutateStaticCard($,Z,J){let Q=!0;try{await J()}catch(V){Q=!1,K(`session "${this.sessionName}": ${Z} mutation failed: ${j(V)}`)}let Y=!1;try{Y=await B$($,{config:{streaming_mode:!1}})}catch(V){K(`session "${this.sessionName}": ${Z} streaming-off failed: ${j(V)}`)}if(!Q||!Y)return K(`session "${this.sessionName}": ${Z} state retained after checked MISS mutation=${Q} streamingOff=${Y} card=${$.slice(0,12)}`),!1;try{await b$($)}catch(V){return K(`session "${this.sessionName}": ${Z} dispose failed: ${j(V)}`),!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 l$($.cardId);let Y=await W$($.cardId,O.footer,T4(Q,O.footer)),V=await x0($.cardId,E4(Q),{type:"insert_after",targetElementId:O.footer}),X=await x0($.cardId,x4(Q.sysinfo),{type:"insert_after",targetElementId:O.consoleProjects}),H=await x0($.cardId,r2(Q),{type:"insert_after",targetElementId:O.consoleHost});if(!Y||!V||!X||!H){await C(this.chatId,"⚠️ 控制台卡片结构写入失败,请重新发送 hi。"),await this.mutateStaticCard($.cardId,"console structure",async()=>{});return}X$($.cardId),await B$($.cardId,i$({durationSec:J,suffix:Z})),this.patchConsoleUsageLater($.cardId)}async showConsole(){let $=await this.buildConsoleCard(void 0),Z=await l(this.chatId,$);if(!Z)return;(async()=>{let J="";try{J=await $0(Z),p$(J,4)}catch(Q){K(`session "${this.sessionName}": console card conversion failed: ${j(Q)}`);return}await this.mutateStaticCard(J,"console usage",()=>this.patchConsoleUsage(J))})().catch((J)=>K(`session "${this.sessionName}": console async update rejected: ${j(J)}`))}interrupt(){if(!this.proc)return;K(`session "${this.sessionName}": interrupt`),this.proc.sendInterrupt()}async startColdUserTurn($,Z,J){if(!this.pendingConversationMaterialization)this.resetFreshConversationState();this.pendingTurnInputs.push($);let Q=this.beginTurnOpen();try{let V=await this.openTurnCard(Q,J,"user_message",{initialFooter:"Waiting...(0s)",startThinking:!1,directStart:!0});if(!V||this.currentTurn!==V)return;let X=this.startFooterTimer(V.cardId,`\uD83D\uDE80 启动 ${this.backendLabel()}`,(G)=>this.withModel(G)),H=`\uD83D\uDE80 启动 ${this.backendLabel()}`,W=await this.startUnlocked({announce:!1,freshConversationStateAlreadyReset:!0,onStatus:(G)=>{H=G,X.setStatus(G)}});if(X.stop(),await l$(V.cardId),!W){this.pendingUserMessageCount=0,this.pendingMidTurnMsgs=[],this.pendingTurnInputs=[],this.lastUserOpenId="",this.releaseAllReactions(),await this.closeTurnCard(H.startsWith("❌")?H:"❌ 启动失败",{forcePush:!0});return}let z=this.proc;if(!z?.isAlive()){await this.closeTurnCard(`❌ ${this.backendLabel()} 启动后已退出`,{forcePush:!0});return}this.startThinkingFooter(V),z.sendUserText(Z,[]),this.pendingUserMessageCount++,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.startingAgy||this.runningAgy){await E(this.chatId,"⏳ agy 任务正在执行;请等待完成,或发送 stop 打断后再继续。");return}if(this.proc?.isAlive()&&!this.currentTurn&&!this.openingTurn&&this.pendingUserMessageCount===0&&this.pendingMidTurnMsgs.length===0)await this.stopIdleMismatchedProcessUnlocked();let V=this.currentTurn!==null||this.openingTurn||this.pendingUserMessageCount>0||this.pendingMidTurnMsgs.length>0;this.lastUserOpenId=J;let H=(Z.length?Z.map((z)=>`[file: ${z}]`).join(" ")+`
|
|
191
|
+
`:"")+$,W=(z)=>{this.pendingReactionIds.set(z,""),(async()=>{let G=await R$(z,"OneSecond");if(!G)return;if(this.pendingReactionIds.has(z))this.pendingReactionIds.set(z,G);else if(this.currentBatchReactionIds.has(z))this.currentBatchReactionIds.set(z,G);else P$(z,G)})().catch((G)=>{K(`session "${this.sessionName}": reaction tracking failed: ${j(G)}`)})};if(!this.isRunning()){if(this.openingTurn||this.currentTurn){if(this.pendingMidTurnMsgs.push({text:$,wireText:H,userOpenId:J,msgId:Q}),Q)W(Q);return}await this.startColdUserTurn($,H,J);return}if(this.currentTurn!==null){if(this.pendingMidTurnMsgs.push({text:$,wireText:H,userOpenId:J,msgId:Q}),Q)W(Q);return}if(!this.openingTurn&&this.initCount>=1){let z=this.proc,G=this.procEpoch,q=this.beginTurnOpen(z,G);try{this.pendingTurnInputs.push($);let B=await this.openTurnCard(q,J,"user_message");if(!B||this.currentTurn!==B)return;if(this.proc!==z||this.procEpoch!==G||!z.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel(z.provider)} 已退出`);return}z.sendUserText(H,[]),this.pendingUserMessageCount++,this.status="working"}finally{this.releaseTurnOpen(q)}return}if(this.openingTurn||this.pendingUserMessageCount>0){if(this.pendingMidTurnMsgs.push({text:$,wireText:H,userOpenId:J,msgId:Q}),Q)W(Q);return}if(this.pendingTurnInputs.push($),this.proc.sendUserText(H,[]),this.pendingUserMessageCount++,V&&Q)W(Q)}hasPendingAsk(){return mY(this)}onMultiMessageInbound($,Z,J,Q){return YY(this,$,Z,J,Q)}clearMultiMsgBuffer($){U5(this,$)}onAskMessageAnswer($,Z,J){return cY(this,$,Z,J)}onAskAnswer($,Z,J,Q){return uY(this,$,Z,J,Q)}onAskCustomAnswer($,Z,J,Q){return C5(this,$,Z,J,Q)}onPermissionDecision($,Z,J){return lY(this,$,Z,J)}clearResumeBindingForFreshCodex($){if($.isConversationResumable?.())throw Error("fresh Codex thread was unexpectedly marked resumable during init");let Z=i0(this.sessionName,"codex");if(b1(this.sessionName,"codex"),this.selectedProvider==="codex")this.lastSessionRef=null,this.lastSessionId=null;if(Z)K(`session "${this.sessionName}": cleared pre-fresh Codex resume binding thread=${Z.sessionId}`)}invalidateMissingCodexResume($,Z,J){if(!$||this.selectedProvider!=="codex")return null;let Q=a5(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=i0(this.sessionName,"codex");if(!Y||Y.sessionId!==$)return null;try{b1(this.sessionName,"codex")}catch(X){let H=`已确认恢复点无 rollout,但作废失败: ${j(X)}`;return K(`session "${this.sessionName}": ${H} thread=${$}`),H}if(this.lastSessionRef?.provider==="codex"&&this.lastSessionRef.sessionId===$)this.lastSessionRef=null,this.lastSessionId=null;J?.($);let V=`已作废无 rollout 的恢复点 thread=${z$($)}`;return K(`session "${this.sessionName}": ${V} fullThread=${$}`),V}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 H=Error("Claude pending fork did not provide a materialized session id");if(K(`session "${this.sessionName}": ${H.message}`),$)throw H;return H.message}let V={provider:Z.provider,sessionId:Y,cwd:this.workDir};if(Q&&(Y===Q.launch.source.sessionId||Q.previousSessionId!==null&&Y===Q.previousSessionId)){let H=Error(`Claude fork did not materialize an independent session id (${Y})`);if(K(`session "${this.sessionName}": ${H.message}`),$)throw H;return H.message}try{k2(this.sessionName,V)}catch(H){let W=`会话恢复点持久化失败: ${j(H)}`,z=this.resumePersistenceError!==W;if(this.resumePersistenceError=W,Z.provider===this.selectedProvider)this.lastSessionRef=V,this.lastSessionId=Y;if(K(`session "${this.sessionName}": ${W}`),$)throw H;if(z&&J)C(this.chatId,`⚠️ ${W};当前进程可继续,但 daemon 重启前请先解决本机状态目录写入问题。`);return W}if(Z.provider===this.selectedProvider)this.lastSessionRef=V,this.lastSessionId=Y;let X=Z.provider==="codex"?this.flushPendingCodexTurnAnchors(Z):null;if(X){let H=this.resumePersistenceError!==X;if(this.resumePersistenceError=X,$)throw Error(X);if(H&&J)C(this.chatId,`⚠️ ${X}`);return X}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 K(`session "${this.sessionName}": ${"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker"}`),"Claude 待生成分支没有可验证的新会话恢复点,保留 pending marker";try{return T0(this.sessionName,null),this.pendingConversationMaterialization=null,null}catch(J){let Q=`Claude 待生成分支标记清除失败: ${j(J)}`;return K(`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(G6(this.bgStore())),this.onBackgroundTaskChanged()}bgTaskOwns($){return this.backgroundTasks.some((Z)=>Z.toolUseId===$)||this.pendingBgTasks.some((Z)=>Z.toolUseId===$)}onBackgroundTaskChanged(){if(!A0(this.backgroundTasks)){if(this.backgroundCard)this.settleBackgroundCard().catch((Z)=>{K(`session "${this.sessionName}": background settle failed: ${j(Z)}`)});return}if(!this.backgroundCard&&!this.openingBackground){this.openBackgroundCard().catch((Z)=>{K(`session "${this.sessionName}": background open failed: ${j(Z)}`)});return}this.scheduleBackgroundRefresh()}async openBackgroundCard(){let $=this.beginBackgroundOpen();if(!$)return;let Z=this.backgroundTasks.slice();try{let J=F6(Z,Date.now(),z1()),Q=await l(this.chatId,J);if(!Q){if(this.ownsBackgroundOpen($))K(`session "${this.sessionName}": background card send failed`);return}let Y;try{Y=await $0(Q)}catch(V){K(`session "${this.sessionName}": background card id_convert failed: ${V}`);return}if(p$(Y,Z.length),!this.ownsBackgroundOpen($)){await this.terminalizeSupersededCard(Y,"⚠️ 后台任务世代已切换,本卡已作废",!1);return}if(this.backgroundCard={messageId:Q,cardId:Y},this.backgroundDetailAdded=new Set(Z.map((V)=>V.id)),this.backgroundDetailAdding.clear(),K(`session "${this.sessionName}": background card opened cardId=${Y.slice(0,12)} tasks=${Z.length}`),!A0(this.backgroundTasks)){this.settleBackgroundCard().catch((V)=>{K(`session "${this.sessionName}": background settle-after-open failed: ${j(V)}`)});return}this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}finally{this.releaseBackgroundOpen($)}}startBackgroundRefreshTick(){if(this.backgroundRefreshTick)return;let $=()=>{if(!this.backgroundCard||!A0(this.backgroundTasks))return;let Z=z1(),J=Date.now(),Q=1/0;for(let Y of this.backgroundTasks){if(S$(Y))continue;let V=M0(J-Y.startedAt,Z).nextDelayMs;if(V<Q)Q=V}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)return;if(this.backgroundRefreshTimer)return;this.backgroundRefreshTimer=setTimeout(()=>{this.backgroundRefreshTimer=null,this.refreshBackgroundCardFull()},1500)}refreshBackgroundCardFull(){let $=this.backgroundCard;if(!$)return;let Z=Date.now(),J=z1();for(let Q of this.backgroundTasks)if(!this.backgroundDetailAdded.has(Q.id)){if(this.backgroundDetailAdding.has(Q.id))continue;this.backgroundDetailAdding.add(Q.id),x0($.cardId,T1(Q,Z,J)).then((Y)=>{if(Y)this.backgroundDetailAdded.add(Q.id);else K(`session "${this.sessionName}": background panel add MISS task=${Q.id}`)}).finally(()=>{this.backgroundDetailAdding.delete(Q.id)})}else u($.cardId,U2.panel(Q.id),T1(Q,Z,J));r0($.cardId,h8(this.backgroundTasks))}async resetBackgroundTasks(){if(this.invalidateBackgroundOpen(),this.backgroundTasks.some(($)=>!S$($))){let $=Date.now();this.backgroundTasks=this.backgroundTasks.map((Z)=>S$(Z)?Z:{...Z,status:"killed",endTime:Z.endTime??$})}if(this.pendingBgTasks=[],this.backgroundCard){await this.settleBackgroundCard();return}if(this.stopBackgroundRefreshTick(),this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;this.backgroundTasks=[],this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear()}async settleBackgroundCard(){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 l$($.cardId),await q0($.messageId,I8(Z)),X$($.cardId),!await B$($.cardId,i$({suffix:"\uD83E\uDDED 后台任务已结束"})))throw Error("background history streaming-off rejected");if(await b$($.cardId),this.backgroundCard===$)this.backgroundCard=null;this.backgroundTasks=this.backgroundTasks.filter((Q)=>!S$(Q)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),K(`session "${this.sessionName}": background card settled cardId=${$.cardId.slice(0,12)} remaining=${this.backgroundTasks.length}`)}finally{if(this.settlingBackgroundCard=!1,this.backgroundCard===$&&A0(this.backgroundTasks))this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(this.backgroundTasks.length>0)this.onBackgroundTaskChanged()}async migrateBackgroundCard(){let $=this.backgroundCard;if(!$)return;if(this.backgroundRefreshTimer)clearTimeout(this.backgroundRefreshTimer),this.backgroundRefreshTimer=null;this.stopBackgroundRefreshTick();let Z=this.backgroundTasks.filter(S$).length;if(await l$($.cardId),Z>0)await q0($.messageId,I8(this.backgroundTasks));else await q0($.messageId,U6());if(X$($.cardId),!await B$($.cardId,i$({suffix:"\uD83E\uDDED 已迁移至新卡"})))throw Error("background migration streaming-off rejected");await b$($.cardId),this.backgroundCard=null,this.backgroundTasks=this.backgroundTasks.filter((Q)=>!S$(Q)),this.backgroundDetailAdded.clear(),this.backgroundDetailAdding.clear(),K(`session "${this.sessionName}": background card migrated cardId=${$.cardId.slice(0,12)} terminal=${Z} active=${this.backgroundTasks.length}`)}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,V=!1,X=(H,W)=>{$.on(H,(z)=>{if(!Q()){if(!Y)Y=!0,K(`session "${this.sessionName}": ignore stale ${$.provider} event=${String(H)} epoch=${J} currentEpoch=${this.procEpoch}`);return}if(H!=="exit"&&(this.stoppingProc===$||this.blockedProc===$)){if(!V)V=!0,K(`session "${this.sessionName}": ignore ${$.provider} event=${String(H)} while process stop is pending`);return}W(z)})};X("error",(H)=>{K(`session "${this.sessionName}": ${$.provider} process error: ${H}`)}),X("init",()=>{if($.provider==="codex"&&$.launchKind==="fresh")this.clearResumeBindingForFreshCodex($);else this.persistResumableSessionId(!0);if(C7(),this.initCount++,K(`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)return;let H=this.pendingUserMessageCount>0,W=!H&&this.bgResumePending;if(!H&&!W)return;this.bgResumePending=!1;let z=this.lastUserOpenId;if(H)this.pendingUserMessageCount=0,this.currentBatchReactionIds=this.pendingReactionIds,this.pendingReactionIds=new Map;let G=H?[...this.currentBatchReactionIds.keys()]:[],q=()=>{for(let L of G){let F=this.currentBatchReactionIds.get(L);if(this.currentBatchReactionIds.delete(L),F)P$(L,F)}},B=this.beginTurnOpen($,J,!0);(async()=>{try{let L=await this.openTurnCard(B,z,H?"user_message":"bg_task_resume");if(!Q()){if(K(`session "${this.sessionName}": ${$.provider} became stale while opening turn card epoch=${J}`),L&&this.currentTurn===L)await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);q();return}if(!L||this.currentTurn!==L){if(!this.ownsTurnOpen(B)){q();return}if(B.sawResult&&B.terminalSuffix)C(this.chatId,B.terminalSuffix);if(H)K(`session "${this.sessionName}": init-path openTurnCard failed — sendInterrupt + release reactions`),this.proc?.sendInterrupt(),q();else if(this.bgResumeCardless=!0,B.sawResult)B.sawResult=!1,K(`session "${this.sessionName}": bg-resume openTurnCard failed, result already arrived — flushing orphan now`),this.flushOrphanAssistantToChat("bg-resume open failed, result already arrived");else K(`session "${this.sessionName}": bg-resume openTurnCard failed — orphan text flush will cover the output`)}else if(B.sawResult)B.sawResult=!1,K(`session "${this.sessionName}": result raced card-open — closing freshly-opened turn card now`),await this.closeTurnCard(B.terminalSuffix,{forcePush:B.terminalForcePush,hasFreshResult:!0}),this.status="idle";else this.status="working"}finally{this.releaseTurnOpen(B)}})().catch((L)=>{K(`session "${this.sessionName}": init turn-open handler failed: ${j(L)}`)})}),X("conversation_materialized",({session_id:H,source:W})=>{if($.provider!=="codex")return;if($.sessionId!==H){K(`session "${this.sessionName}": ignore mismatched Codex materialization session=${H} current=${$.sessionId??"MISS"} source=${W}`);return}K(`session "${this.sessionName}": Codex resume point materialized thread=${H} source=${W}`),this.persistResumableSessionId()}),X("conversation_materialization_failed",({session_id:H,source:W,error:z})=>{if($.provider!=="codex"||$.sessionId!==H)return;let G=`Codex 会话落盘确认失败,未写恢复点: ${j(z)}`,q=this.resumePersistenceError!==G;if(this.resumePersistenceError=G,K(`session "${this.sessionName}": ${G} thread=${H} source=${W}`),q)C(this.chatId,`⚠️ ${G}`)}),X("turn_started",()=>{this.persistResumableSessionId();let H=this.proc?.lastTotalUsage;if(this.usageTotalsSeedUnknown&&!H){this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;return}this.currentTurnUsageBaseline=H?{...H}:null,this.currentTurnUsageBaselineKnown=!0}),X("token_usage",({totalUsage:H})=>{if(this.persistResumableSessionId(),H)this.usageTotalsSeedUnknown=!1}),X("turn_plan_updated",(H)=>{this.handleTurnPlanUpdated(H)}),X("plan_delta",(H)=>{this.handlePlanDelta(H)}),X("context_compacted",(H)=>{this.handleContextCompacted(H)}),X("rate_limits_updated",(H)=>{if($.provider==="codex")dQ(H)}),X("thread_goal_updated",(H)=>{this.handleThreadGoalUpdated(H)}),X("thread_goal_cleared",()=>{this.handleThreadGoalCleared()}),X("assistant_text",({text:H})=>{this.appendAssistant(H)}),X("assistant_block_stop",()=>{this.finalizeCurrentAssistantSegment(),this.onMainThreadAdvance()}),X("tool_use",({id:H,name:W,input:z,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(_6({active:this.backgroundTasks,pending:this.pendingBgTasks},G,H,W,z)),this.onBackgroundTaskChanged();return}if(hY(this,H,W,z),!G)this.onMainThreadAdvance();if(!G&&(W==="Task"||W==="Agent"))this.lastMainTaskToolUseId=H}),X("tool_result",({tool_use_id:H,content:W,is_error:z,parentToolUseId:G})=>{if(G&&this.bgTaskOwns(G)){this.applyBgStore(L6({active:this.backgroundTasks,pending:this.pendingBgTasks},G,H,W,z)),this.onBackgroundTaskChanged();return}IY(this,H,W,z)}),X("can_use_tool",(H)=>{dY(this,H)}),X("hook_callback",(H)=>{this.proc?.sendHookResponse(H.request_id,{})}),X("result",(H)=>{let W=this.persistResumableSessionId(),z=W?null:this.consumePendingConversationMaterialization(),G=[W,z].filter(Boolean).join(";")||null;if(this.accumulateResultStats(),this.openingTurnOwner)this.openingTurnOwner.sawResult=!0;if(this.userInterrupted){this.userInterrupted=!1,this.discardOrphanAssistant(),this.bgResumePending=!1;let M=this.proc?.lastResult.subtype??"unknown",x=this.proc?.lastResult.is_error===!0;K(`session "${this.sessionName}": SDK result after user stop subtype=${M} isError=${x} — ignored`),this.status="idle";return}let q=H?.is_error!==!0?this.recordTurnAnchor(H?.checkpoint):null;if(H?.is_error===!0)this.lastTurnUserPreview="";if(!this.currentTurn&&!this.openingTurn)this.flushOrphanAssistantToChat("result with no turn card");let B=this.pendingMidTurnMsgs.length>0,L=this.proc?.lastResult.is_error===!0,F=this.proc?.lastResult.subtype??"success",U,R=!1,D=this.proc?this.backendLabel(this.proc.provider):this.backendLabel(),P=[G,q].filter(Boolean).join(";")||null;if(P)U=`⚠️ ${P}`,R=!0;else if(B)U=L?`⚠️ ${D} ${F},用户已介入`:"\uD83D\uDCE8 转交新卡";else if(L)U=`⚠️ ${D} ${F}`,R=!0;if(this.openingTurnOwner)this.openingTurnOwner.terminalSuffix=U,this.openingTurnOwner.terminalForcePush=R;if(P&&!this.currentTurn&&!this.openingTurn)C(this.chatId,`⚠️ ${P}`);if(K(`session "${this.sessionName}": SDK result subtype=${F} isError=${L} midBuffer=${this.pendingMidTurnMsgs.length} forcePush=${R}`),this.closeTurnCard(U,{forcePush:R,hasFreshResult:!0}).catch((M)=>{K(`session "${this.sessionName}": result card close failed: ${j(M)}`)}),this.status="idle",B)this.drainMidTurnAndOpen().catch((M)=>{K(`session "${this.sessionName}": mid-turn drain failed: ${j(M)}`)})}),X("bg_task_started",(H)=>{let W=H.tool_use_id??this.lastMainTaskToolUseId??void 0;K(`session "${this.sessionName}": bg_task_started task=${H.task_id} type=${H.task_type??"-"} subagent=${H.subagent_type??"-"} toolUseId=${W?.slice(0,8)??"-"} desc=${(H.description??"").slice(0,40)}`),this.applyBgStore(W6(this.bgStore(),{...H,tool_use_id:W})),this.onBackgroundTaskChanged()}),X("bg_task_progress",(H)=>{this.applyBgStore(z6(this.bgStore(),H)),this.onBackgroundTaskChanged()}),X("bg_task_updated",(H)=>{this.applyBgStore(K6(this.bgStore(),H)),this.onBackgroundTaskChanged()}),X("bg_task_settled",(H)=>{if(K(`session "${this.sessionName}": bg_task_settled task=${H.task_id} status=${H.status}`),this.applyBgStore(q6(this.bgStore(),H)),this.onBackgroundTaskChanged(),$.provider==="claude"&&!this.currentTurn&&!this.openingTurn&&this.initCount>=1)this.bgResumePending=!0}),X("subagent_step",(H)=>{this.applyBgStore(B6(this.bgStore(),H.thread_id,H.item_id,H.tool,H.phase,H.brief)),this.onBackgroundTaskChanged()}),X("exit",({code:H,signal:W,expected:z})=>{if(K(`session "${this.sessionName}": ${$.provider} exited code=${H} signal=${W} expected=${z}`),this.stoppingProc===$||this.blockedProc===$){if(this.blockedProc===$){let F=$.conversationMaterializationFailure?.(),U=this.persistResumableSessionId(!1,$,!1),R=[F&&$.isConversationResumable?.()!==!0?`Codex 会话落盘确认失败: ${j(F)}`:null,U].filter(Boolean).join(";");if(R)C(this.chatId,`⚠️ 旧进程退出后的恢复状态收尾失败: ${R}`);this.discardPendingCodexTurnAnchors($,"blocked process finally exited")}K(`session "${this.sessionName}": blocked/stopping ${$.provider} exit confirmed`),this.detachProc($),this.status="stopped",this.opts.onLifecycleChange?.();return}this.discardPendingCodexTurnAnchors($,"unexpected process exit");let G=this.backendLabel($.provider),q=`code=${H??"null"}, signal=${W??"null"}`,B=z?`\uD83D\uDED1 ${G} 已退出`:`⚠️ ${G} 异常退出 (${q})`;if(this.currentTurn)this.closeTurnCard(B).catch((F)=>{K(`session "${this.sessionName}": process-exit current main-card close failed: ${j(F)}`)});let L=this.waitForTurnCloses().catch((F)=>{K(`session "${this.sessionName}": process-exit main-card close failed: ${j(F)}`)});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 F=await Promise.allSettled([L,this.resetBackgroundTasks()]);for(let U of F)if(U.status==="rejected")K(`session "${this.sessionName}": process-exit terminal cleanup failed: ${j(U.reason)}`);if(!z)await E(this.chatId,`⚠️ ${G} 异常退出 (${q})。回复任意消息将重新启动。`)}).catch((F)=>{K(`session "${this.sessionName}": process-exit cleanup rejected: ${j(F)}`)})})}accumulateResultStats(){let $=this.proc?.lastResult;if(!$)return;let Z=this.currentTurnUsageBaselineKnown?rZ(this.proc?.lastTotalUsage,this.currentTurnUsageBaseline):this.proc?.provider==="claude"&&$.usage?{...$.usage}:null;this.lastTurnUsage=Z,this.currentTurnUsageBaseline=null,this.currentTurnUsageBaselineKnown=!1;let J=aZ(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 V4(Z)}contextLimitForDisplay($=this.proc){return X4($?.lastContextWindow)}async drainMidTurnAndOpen(){if(this.pendingMidTurnMsgs.length===0)return;let $=this.proc,Z=this.procEpoch;if(!$?.isAlive())return;let J=this.pendingMidTurnMsgs;this.pendingMidTurnMsgs=[];let Q=this.beginTurnOpen($,Z);try{for(let W of J)if(this.pendingTurnInputs.push(W.text),W.msgId){let z=this.pendingReactionIds.get(W.msgId)??"";this.currentBatchReactionIds.set(W.msgId,z),this.pendingReactionIds.delete(W.msgId)}let Y=J.map((W)=>W.wireText).join(`
|
|
191
192
|
|
|
192
|
-
`),X=J[J.length-1]?.userOpenId??this.lastUserOpenId,z=await this.openTurnCard(Q,X,"user_message");if(!z||this.currentTurn!==z){for(let H of J){if(!H.msgId)continue;let W=this.currentBatchReactionIds.get(H.msgId);if(this.currentBatchReactionIds.delete(H.msgId),W)B$(H.msgId,W)}this.status="idle";return}if(this.proc!==$||this.procEpoch!==Z||!$.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);for(let H of J){if(!H.msgId)continue;let W=this.currentBatchReactionIds.get(H.msgId);if(this.currentBatchReactionIds.delete(H.msgId),W)B$(H.msgId,W)}this.status="stopped";return}try{$.sendUserText(Y,[])}catch(H){K(`session "${this.sessionName}": mid-turn sendUserText failed after card open: ${H}`),await this.closeTurnCard(`❌ ${this.backendLabel($.provider)} 接收消息失败`),await C(this.chatId,`❌ ${this.backendLabel($.provider)} 接收消息失败: ${R(H)}。这批消息未开始处理,请重发。`),this.status="idle";return}this.pendingUserMessageCount++,this.status="working"}finally{if(this.releaseTurnOpen(Q),!this.currentTurn&&this.pendingMidTurnMsgs.length>0&&this.proc===$&&this.procEpoch===Z&&$.isAlive())this.drainMidTurnAndOpen()}}async terminalizeSupersededCard($,Z,J){let Q=J?await L$($,U.footer,this.footerElement(Z)):!0;V$($);let Y=await K$($,m$({suffix:Z}));if(Q&&Y){await C$($);return}let V=`footer=${Q?"ok":"MISS"}, settings=${Y?"ok":"MISS"}`;K(`session "${this.sessionName}": superseded card terminal transaction incomplete card=${$.slice(0,12)} ${V}`),await C(this.chatId,`⚠️ 已作废卡片未能正常关闭 (${V})。`)}async openTurnCard($,Z,J,Q={}){if(!this.ownsTurnOpen($))return null;if(this.bgResumePending=!1,this.backgroundCard&&B0(this.backgroundTasks))try{await this.migrateBackgroundCard(),this.pendingRebuildBackgroundCard=!0}catch(F){K(`session "${this.sessionName}": background migrate failed (non-blocking): ${F}`),this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(!this.ownsTurnOpen($))return null;let Y=++this.turnCounter,V=this.pendingTurnInputs;this.pendingTurnInputs=[],this.lastTurnUserPreview=V[0]?.slice(0,80)??this.lastTurnUserPreview,K(`session "${this.sessionName}": openTurnCard turn=${Y} trigger=${J} inputs=${V.length}`);let X=this.runtimeModelSelection(),z=this.withModel(Q.initialFooter??"Waiting...(0s)",X),H=q4({sessionName:this.sessionName,turn:Y,provider:X.provider,model:X.model??void 0,effort:X.effort,kind:J,userInputs:V,initialFooter:z,directStart:Q.directStart}),W=await p(this.chatId,H);if(!W){if(!this.ownsTurnOpen($))return null;if(K(`session "${this.sessionName}": openTurnCard sendCard EXHAUSTED retries — surfacing via raw text`),J==="user_message")await C(this.chatId,`❌ 创建对话卡片失败 (Feishu SDK 重试 3 次后仍连不上)。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);return null}let G;try{G=await r$(W)}catch(F){if(K(`session "${this.sessionName}": id_convert failed: ${F}`),J==="user_message"&&this.ownsTurnOpen($))await C(this.chatId,`❌ 对话卡片初始化失败。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);return null}let _=(J==="bg_task_resume"?1:0)+(V.length>0?1:0)+1;if(!this.ownsTurnOpen($))return h$(G,_),await this.terminalizeSupersededCard(G,"⚠️ 会话已切换,本卡已作废",!0),null;h$(G,_,(F)=>this.onCardWriteFailure(F));let B={cardId:G,...X,messageId:W,userOpenId:Z,trigger:J,toolCount:0,toolByUseId:new Map,planSteps:[],planExplanation:null,planUpdateCount:0,goalUpdateCount:0,contextCompactCount:0,contextCompactionPending:new Map,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,rotateGivenUp:!1,outboundSeenPaths:new Set,outboundSentPaths:new Set};if(this.currentTurn=B,Q.startThinking!==!1)this.startThinkingFooter(B);let L=this.takeOrphanAssistantText();if(L)this.appendAssistant(L),this.finalizeCurrentAssistantSegment();if(this.pendingRebuildBackgroundCard){if(this.pendingRebuildBackgroundCard=!1,B0(this.backgroundTasks))this.openBackgroundCard().catch((F)=>{K(`session "${this.sessionName}": background rebuild failed: ${R(F)}`)})}return B}maybeMidTurnRotate(){let $=this.currentTurn;if(!$)return;if($.rotating)return;if(Q9($.cardId)<SB)return;this.startMidTurnRotate($)}onCardWriteFailure($){let Z=this.currentTurn;if(!Z)return;if(Z.rotating)return;if(Z.rotateGivenUp)return;if(Z.failureRotateCount>=f5){Z.rotateGivenUp=!0,this.stopFooterStatus(Z),WJ(Z.cardId),K(`session "${this.sessionName}": failure-rotate cap (${f5}) hit — giving up, rest of turn is log-only`),C(this.chatId,`⚠️ 卡片写入失败已触发 ${f5} 次换卡仍未恢复(疑似飞书故障或元素超限),本轮后续输出仅日志可见。`);return}let J=HJ($)?`element limit (${$})`:`write failure (code=${$??"n/a"})`;K(`session "${this.sessionName}": ${J} on card=${Z.cardId.slice(0,8)}… — rotating to fresh card`),Z.failureRotateCount++,this.startMidTurnRotate(Z)}startMidTurnRotate($){if($.rotating)return;$.rotateCount++;let{cardId:Z,toolByUseId:J,toolBatches:Q}=$,Y=!1,V;$.rotating=(async()=>{try{K(`session "${this.sessionName}": mid-turn rotate triggered card=${Z.slice(0,8)}… elementCount=${Q9(Z)}`);let X=q4({sessionName:this.sessionName,turn:this.turnCounter,provider:$.provider,model:$.model??void 0,effort:$.effort,kind:"card_full",userInputs:[]}),z=await p(this.chatId,X);if(!z){K(`session "${this.sessionName}": mid-turn rotate sendCard EXHAUSTED — staying on old card,subsequent adds will drop`),await C(this.chatId,"⚠️ 卡片元素超出飞书上限,本轮后续输出仅日志可见(开新卡失败)。");return}let H;try{H=await r$(z)}catch(L){K(`session "${this.sessionName}": mid-turn rotate id_convert failed: ${L}`);return}h$(H,2,(L)=>{if($.rotating){Y=!0,V=L;return}this.onCardWriteFailure(L)});let W=$.assistantWriteInflight?.get(Z);if(W?.size)await Promise.allSettled([...W]);this.stopFooterStatus($),$.cardId=H,$.messageId=z,$.toolCount=0,$.toolByUseId=new Map,$.toolBatches=new Map,$.openBatchI=null,$.planUpdateCount=0,$.goalUpdateCount=0;let G=$.currentAssistantSegmentId,_=($.currentAssistantText??"").trim(),B=$.segmentTexts;if($.assistantSegmentCount=0,$.currentAssistantSegmentId=null,$.currentAssistantText="",$.segmentTexts=new Map,_)this.startWritingFooter($);else this.startThinkingFooter($);if($.taskLiveInserted)a($.cardId,r0(this.taskBoard),{type:"insert_before",targetElementId:U.footer});if($.planLiveInserted)a($.cardId,h2($.planSteps,$.planExplanation,U.planLive),{type:"insert_before",targetElementId:$.taskLiveInserted?U.taskBoardLive:U.footer});for(let[L,F]of B){if(G&&_&&L===G)continue;if(!N1(Z,L))continue;let D=$.assistantSegmentCount++,j=U.assistant(D);if($.segmentTexts.set(j,F),!await this.addCompletedAssistantSegment($,j,F))Y=!0}if(RY(this,Z,H,J,Q),G&&_){let L=$.assistantSegmentCount++,F=U.assistant(L);$.currentAssistantSegmentId=F,$.currentAssistantText=_,$.segmentTexts.set(F,_)}try{let L=$.mathRenderInflight?.get(Z);if(L?.size)await Promise.allSettled([...L]);await o$(Z);let F=$.mathRendered?.get(Z);for(let[O,P]of B){if(G&&_&&O===G)continue;if(N1(Z,O))continue;if(F?.has(O))continue;await c(Z,O,this.completedAssistantElement(O,P))}let D=$.contextCompactCount>0?` · \uD83D\uDEA8 压缩×${$.contextCompactCount}`:"",j=await L$(Z,U.footer,this.footerElement(this.withModel(`\uD83D\uDCE8 已续至下一张卡 ↓${D}`)));V$(Z);let M=await K$(Z,m$({suffix:"\uD83D\uDCE8 转下一张"}));if(j&&M)await C$(Z);else K(`session "${this.sessionName}": rotate old-card terminal MISS footer=${j} settings=${M}`),await C(this.chatId,`⚠️ 上一张对话卡未能正常关闭 (footer=${j?"ok":"MISS"}, settings=${M?"ok":"MISS"}),本轮输出已续到新卡。`)}catch(L){K(`session "${this.sessionName}": mid-turn rotate close-old failed: ${L}`)}K(`session "${this.sessionName}": mid-turn rotate done old=${Z.slice(0,8)}… new=${H.slice(0,8)}…`)}finally{if($.rotating=null,Y&&this.currentTurn===$)this.onCardWriteFailure(V)}})()}addPlanSnapshotOnCurrentTurn(){let $=this.currentTurn;if(!$||$.planSteps.length===0)return;this.maybeMidTurnRotate();let Z=$.cardId,J=U.planUpdate($.planUpdateCount++);a(Z,O9($.planSteps,$.planExplanation,"",J),{type:"insert_before",targetElementId:D$($)})}addGoalUpdateOnCurrentTurn($){let Z=this.currentTurn;if(!Z)return;this.maybeMidTurnRotate();let J=U.goalUpdate(Z.goalUpdateCount++);a(Z.cardId,R9($,J),{type:"insert_before",targetElementId:D$(Z)})}addGoalClearedOnCurrentTurn(){let $=this.currentTurn;if(!$)return;this.maybeMidTurnRotate();let Z=U.goalUpdate($.goalUpdateCount++);a($.cardId,{tag:"markdown",element_id:Z,content:`**\uD83C\uDFAF 当前目标**
|
|
193
|
+
`),X=J[J.length-1]?.userOpenId??this.lastUserOpenId,H=await this.openTurnCard(Q,X,"user_message");if(!H||this.currentTurn!==H){for(let W of J){if(!W.msgId)continue;let z=this.currentBatchReactionIds.get(W.msgId);if(this.currentBatchReactionIds.delete(W.msgId),z)P$(W.msgId,z)}this.status="idle";return}if(this.proc!==$||this.procEpoch!==Z||!$.isAlive()){await this.closeTurnCard(`⚠️ ${this.backendLabel($.provider)} 已退出`);for(let W of J){if(!W.msgId)continue;let z=this.currentBatchReactionIds.get(W.msgId);if(this.currentBatchReactionIds.delete(W.msgId),z)P$(W.msgId,z)}this.status="stopped";return}try{$.sendUserText(Y,[])}catch(W){K(`session "${this.sessionName}": mid-turn sendUserText failed after card open: ${W}`),await this.closeTurnCard(`❌ ${this.backendLabel($.provider)} 接收消息失败`),await C(this.chatId,`❌ ${this.backendLabel($.provider)} 接收消息失败: ${j(W)}。这批消息未开始处理,请重发。`),this.status="idle";return}this.pendingUserMessageCount++,this.status="working"}finally{if(this.releaseTurnOpen(Q),!this.currentTurn&&this.pendingMidTurnMsgs.length>0&&this.proc===$&&this.procEpoch===Z&&$.isAlive())this.drainMidTurnAndOpen()}}async terminalizeSupersededCard($,Z,J){let Q=J?await W$($,O.footer,this.footerElement(Z)):!0;X$($);let Y=await B$($,i$({suffix:Z}));if(Q&&Y){await b$($);return}let V=`footer=${Q?"ok":"MISS"}, settings=${Y?"ok":"MISS"}`;K(`session "${this.sessionName}": superseded card terminal transaction incomplete card=${$.slice(0,12)} ${V}`),await C(this.chatId,`⚠️ 已作废卡片未能正常关闭 (${V})。`)}async openTurnCard($,Z,J,Q={}){if(!this.ownsTurnOpen($))return null;if(this.bgResumePending=!1,this.backgroundCard&&A0(this.backgroundTasks))try{await this.migrateBackgroundCard(),this.pendingRebuildBackgroundCard=!0}catch(F){K(`session "${this.sessionName}": background migrate failed (non-blocking): ${F}`),this.startBackgroundRefreshTick(),this.scheduleBackgroundRefresh()}if(!this.ownsTurnOpen($))return null;let Y=++this.turnCounter,V=this.pendingTurnInputs;this.pendingTurnInputs=[],this.lastTurnUserPreview=V[0]?.slice(0,80)??this.lastTurnUserPreview,K(`session "${this.sessionName}": openTurnCard turn=${Y} trigger=${J} inputs=${V.length}`);let X=this.runtimeModelSelection(),H=this.withModel(Q.initialFooter??"Waiting...(0s)",X),W=R4({sessionName:this.sessionName,turn:Y,provider:X.provider,model:X.model??void 0,effort:X.effort,kind:J,userInputs:V,initialFooter:H,directStart:Q.directStart}),z=await l(this.chatId,W);if(!z){if(!this.ownsTurnOpen($))return null;if(K(`session "${this.sessionName}": openTurnCard sendCard EXHAUSTED retries — surfacing via raw text`),J==="user_message")await C(this.chatId,`❌ 创建对话卡片失败 (Feishu SDK 重试 3 次后仍连不上)。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);return null}let G;try{G=await $0(z)}catch(F){if(K(`session "${this.sessionName}": id_convert failed: ${F}`),J==="user_message"&&this.ownsTurnOpen($))await C(this.chatId,`❌ 对话卡片初始化失败。你这条消息尚未送给 ${this.backendLabel()},请稍后重发。`);return null}let q=(J==="bg_task_resume"?1:0)+(V.length>0?1:0)+1;if(!this.ownsTurnOpen($))return p$(G,q),await this.terminalizeSupersededCard(G,"⚠️ 会话已切换,本卡已作废",!0),null;let B={cardId:G,...X,messageId:z,userOpenId:Z,trigger:J,toolCount:0,toolByUseId:new Map,planSteps:[],planExplanation:null,planUpdateCount:0,goalUpdateCount:0,contextCompactCount:0,contextCompactionPending:new Map,contextCompactionCompleted:new Set,contextCompactionCompleting:new Set,contextCompactionEndOnly:new Map,lastContextCompactionCompletedAt:0,lastContextCompactionWasAnonymous:!1,toolBatches:new Map,openBatchI:null,taskCreateI:null,taskUpdateI:null,taskBoardResetThisTurn:!1,taskLiveInserted:!1,planLiveInserted:!1,assistantSegmentCount:0,currentAssistantSegmentId:null,currentAssistantText:"",segmentTexts:new Map,startedAt:Date.now(),footerStatusHandle:null,footerStatusStartedAt:0,footerStatusLabel:null,rotating:null,rotateCount:0,failureRotateCount:0,cardWriteFailureNotified:!1,rotateGivenUp:!1,outboundSeenPaths:new Set,outboundSentPaths:new Set};if(p$(G,q,(F,U)=>{this.onCardWriteFailure(B,G,F,U)}),this.currentTurn=B,Q.startThinking!==!1)this.startThinkingFooter(B);if($.pendingCompactions.length>0){let F=$.pendingCompactions.splice(0);K(`session "${this.sessionName}": replay ${F.length} context compaction event(s) buffered during card open`);for(let U of F)this.handleContextCompacted(U)}let L=this.takeOrphanAssistantText();if(L)this.appendAssistant(L),this.finalizeCurrentAssistantSegment();if(this.pendingRebuildBackgroundCard){if(this.pendingRebuildBackgroundCard=!1,A0(this.backgroundTasks))this.openBackgroundCard().catch((F)=>{K(`session "${this.sessionName}": background rebuild failed: ${j(F)}`)})}return B}maybeMidTurnRotate(){let $=this.currentTurn;if(!$)return;if($.rotateGivenUp)return;if($.rotating)return;if(F9($.cardId)<pB)return;this.startMidTurnRotate($)}onCardWriteFailure($,Z,J,Q){let Y=this.currentTurn;if(Y!==$){K(`session "${this.sessionName}": ignore stale card failure card=${Z.slice(0,12)} code=${J??"n/a"} (turn owner changed)`);return}if(Y.cardId!==Z){K(`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(!jJ(J,Q)){let V=Q?.operation??"unknown operation",X=Q?.elementId?` element=${Q.elementId}`:"";if(K(`session "${this.sessionName}": non-capacity card write failure card=${Z.slice(0,12)} operation=${V}${X} code=${J??"n/a"} — not rotating`),!Y.cardWriteFailureNotified)Y.cardWriteFailureNotified=!0,C(this.chatId,`⚠️ 对话卡片有一项写入失败(code=${J??"MISS"}, ${V})。该错误不是卡片元素上限,已停止无效换卡;其余输出继续处理。`);return}if(Y.failureRotateCount>=W8){Y.rotateGivenUp=!0,this.stopFooterStatus(Y),Z4(Y.cardId),K(`session "${this.sessionName}": failure-rotate cap (${W8}) hit — giving up, rest of turn is log-only`),C(this.chatId,`⚠️ 本轮已因元素容量超限换卡 ${W8} 次,现停止继续换卡;本轮后续输出仅日志可见。`);return}K(`session "${this.sessionName}": confirmed element 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},V=(X,H)=>{if(!Y.value)Y.value={code:X,failure:H}};$.rotating=(async()=>{try{K(`session "${this.sessionName}": mid-turn rotate triggered card=${Z.slice(0,8)}… elementCount=${F9(Z)}`);let X=R4({sessionName:this.sessionName,turn:this.turnCounter,provider:$.provider,model:$.model??void 0,effort:$.effort,kind:"card_full",userInputs:[]}),H=await l(this.chatId,X);if(!H){if(K(`session "${this.sessionName}": mid-turn rotate sendCard EXHAUSTED — staying on old card,subsequent adds will drop`),this.currentTurn===$)$.rotateGivenUp=!0,this.stopFooterStatus($),Z4($.cardId);await C(this.chatId,"⚠️ 卡片元素超出飞书上限,本轮后续输出仅日志可见(开新卡失败)。");return}let W;try{W=await $0(H)}catch(L){if(K(`session "${this.sessionName}": mid-turn rotate id_convert failed: ${L}`),this.currentTurn===$)$.rotateGivenUp=!0,this.stopFooterStatus($),Z4($.cardId),await C(this.chatId,"⚠️ 新对话卡已发送,但 Card Kit 初始化失败;已停止继续换卡,本轮后续输出仅日志可见。");return}p$(W,2,(L,F)=>{if($.rotating){V(L,F);return}this.onCardWriteFailure($,W,L,F)});let z=$.assistantWriteInflight?.get(Z);if(z?.size)await Promise.allSettled([...z]);this.stopFooterStatus($),$.cardId=W,$.messageId=H,$.toolCount=0,$.toolByUseId=new Map,$.toolBatches=new Map,$.openBatchI=null,$.planUpdateCount=0,$.goalUpdateCount=0;let G=$.currentAssistantSegmentId,q=($.currentAssistantText??"").trim(),B=$.segmentTexts;if($.assistantSegmentCount=0,$.currentAssistantSegmentId=null,$.currentAssistantText="",$.segmentTexts=new Map,q)this.startWritingFooter($);else this.startThinkingFooter($);if($.taskLiveInserted)H$($.cardId,J1(this.taskBoard),{type:"insert_before",targetElementId:O.footer});if($.planLiveInserted)H$($.cardId,l2($.planSteps,$.planExplanation,O.planLive),{type:"insert_before",targetElementId:$.taskLiveInserted?O.taskBoardLive:O.footer});for(let L of $.contextCompactionPending.values()){if(L.cardId!==Z)continue;L.cardId=W,L.created=!1,L.createFailure=void 0;let F=O.contextCompact(L.i);L.createPromise=Q4(W,p2(L.i,L.notice,F),{type:"insert_before",targetElementId:L$($)}).then((U)=>{if(L.cardId===W)L.created=U.landed,L.createFailure=U.failure;return U.landed})}for(let[L,F]of B){if(G&&q&&L===G)continue;if(!I1(Z,L))continue;let U=$.assistantSegmentCount++,R=O.assistant(U);$.segmentTexts.set(R,F),await this.addCompletedAssistantSegment($,R,F)}if(x5(this,Z,W,J,Q),await l$(Z),x5(this,Z,W,J,Q),G&&q){let L=$.assistantSegmentCount++,F=O.assistant(L);$.currentAssistantSegmentId=F,$.currentAssistantText=q,$.segmentTexts.set(F,q)}try{let L=$.mathRenderInflight?.get(Z);if(L?.size)await Promise.allSettled([...L]);await l$(Z);let F=$.mathRendered?.get(Z);for(let[P,M]of B){if(G&&q&&P===G)continue;if(I1(Z,P))continue;if(F?.has(P))continue;await u(Z,P,this.completedAssistantElement(P,M))}let U=$.contextCompactCount>0?` · \uD83D\uDEA8 压缩×${$.contextCompactCount}`:"",R=await W$(Z,O.footer,this.footerElement(this.withModel(`\uD83D\uDCE8 已续至下一张卡 ↓${U}`)),{notifyCardFailure:!1});X$(Z);let D=await B$(Z,i$({suffix:"\uD83D\uDCE8 转下一张"}));if(R&&D)await b$(Z);else K(`session "${this.sessionName}": rotate old-card terminal MISS footer=${R} settings=${D}`),await C(this.chatId,`⚠️ 上一张对话卡未能正常关闭 (footer=${R?"ok":"MISS"}, settings=${D?"ok":"MISS"}),本轮输出已续到新卡。`)}catch(L){K(`session "${this.sessionName}": mid-turn rotate close-old failed: ${L}`)}K(`session "${this.sessionName}": mid-turn rotate done old=${Z.slice(0,8)}… new=${W.slice(0,8)}…`)}finally{$.rotating=null;let X=Y.value;if(X&&this.currentTurn===$)this.onCardWriteFailure($,$.cardId,X.code,X.failure)}})()}addPlanSnapshotOnCurrentTurn(){let $=this.currentTurn;if(!$||$.planSteps.length===0)return;this.maybeMidTurnRotate();let Z=$.cardId,J=O.planUpdate($.planUpdateCount++);H$(Z,v9($.planSteps,$.planExplanation,"",J),{type:"insert_before",targetElementId:L$($)})}addGoalUpdateOnCurrentTurn($){let Z=this.currentTurn;if(!Z)return;this.maybeMidTurnRotate();let J=O.goalUpdate(Z.goalUpdateCount++);H$(Z.cardId,f9($,J),{type:"insert_before",targetElementId:L$(Z)})}addGoalClearedOnCurrentTurn(){let $=this.currentTurn;if(!$)return;this.maybeMidTurnRotate();let Z=O.goalUpdate($.goalUpdateCount++);H$($.cardId,{tag:"markdown",element_id:Z,content:`**\uD83C\uDFAF 当前目标**
|
|
193
194
|
|
|
194
|
-
已清除`},{type:"insert_before",targetElementId:D$($)})}handleContextCompacted($){let Z=this.currentTurn;if(!Z){if(this.manualContextCompactionPending){K(`session "${this.sessionName}": manual context compaction ${$.phase??"event"} with no current turn`);return}if($.phase==="start"){K(`session "${this.sessionName}": context compaction start with no current turn`);return}K(`session "${this.sessionName}": context compacted with no current turn`);let H=this.proc?this.backendLabel(this.proc.provider):this.backendLabel();C(this.chatId,`\uD83D\uDEA8\uD83D\uDEA8\uD83D\uDEA8 CONTEXT COMPACTED / 上下文已压缩 \uD83D\uDEA8\uD83D\uDEA8\uD83D\uDEA8
|
|
195
|
+
已清除`},{type:"insert_before",targetElementId:L$($)})}handleContextCompacted($){let Z=WX($);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;K(`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<GZ){K(`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:")),V=Q??Y,X=V?this.contextCompactionReceipts.get(V):void 0;if(Q&&!X&&$.phase!=="start"&&Y){let P=this.contextCompactionReceipts.get(Y);if(!P?.hasItemAlias&&P?.completed&&Date.now()-P.completedAt<GZ||!P?.hasItemAlias&&P?.completionKey&&J?.contextCompactionCompleting.has(P.completionKey))V=Y,X=P,P.hasItemAlias=!0,this.contextCompactionReceipts.delete(Q),this.contextCompactionReceipts.set(Q,P)}if(!J){if(this.openingTurnOwner?.backendTurnStarted){this.openingTurnOwner.pendingCompactions.push($),K(`session "${this.sessionName}": buffer context compaction ${$.phase??"event"} while turn card opens`);return}if(Z.length>0)this.rememberContextCompactionReceipt(Z,null,$.phase!=="start");K(`session "${this.sessionName}": context compaction ${$.phase??"event"} with no current turn thread=${$.threadId??"-"} turn=${$.turnId??"-"} item=${$.itemId??"-"}`);return}if(V&&X?.completed){K(`session "${this.sessionName}": duplicate context compaction ${$.phase??"event"} ignored receipt=${V}`);return}let H=this.contextCompactionOwnerId(J);if(V&&X&&X.ownerId!==H){this.rememberContextCompactionReceipt(Z,null,!0),K(`session "${this.sessionName}": late context compaction ${$.phase??"event"} ignored receipt=${V} (turn owner changed)`);return}if(V&&X?.completionKey&&J.contextCompactionCompleting.has(X.completionKey)){K(`session "${this.sessionName}": context compaction alias already writing receipt=${V}`);return}if($.phase!=="start"&&Z.length>0&&J.contextCompactionPending.size===0&&J.contextCompactionCompleting.has("__anonymous__")){K(`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<GZ){K(`session "${this.sessionName}": identified context compaction duplicate ignored after anonymous completion`);return}if($.phase==="start"){let P=hB($);if(J.contextCompactionPending.has(P)||J.contextCompactionCompleted.has(P)){K(`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,H,!1);let M=J.contextCompactCount++,x=J.cardId,y=O.contextCompact(M),N={i:M,cardId:x,notice:$,created:!1,createFailure:void 0,createPromise:Promise.resolve(!1)};N.createPromise=Q4(x,p2(M,$,y),{type:"insert_before",targetElementId:L$(J)}).then((m)=>{if(N.cardId===x)N.created=m.landed,N.createFailure=m.failure;return m.landed}),J.contextCompactionPending.set(P,N),K(`session "${this.sessionName}": context compaction start #${M+1} key=${P}`),r0(J.cardId,`\uD83D\uDEA8 压缩×${J.contextCompactCount}`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionCompleting.size>0){K(`session "${this.sessionName}": anonymous context compaction duplicate ignored while completion writes`);return}if(!$.itemId&&!$.turnId&&J.contextCompactionPending.size===0&&Date.now()-J.lastContextCompactionCompletedAt<GZ){K(`session "${this.sessionName}": immediate anonymous context compaction duplicate ignored`);return}let W=$.itemId||$.turnId;if(W&&J.contextCompactionCompleted.has(W)){K(`session "${this.sessionName}": duplicate context compaction completion ignored key=${W}`);return}let z=$.itemId?J.contextCompactionPending.has($.itemId)?$.itemId:null:IB(J),G=z?J.contextCompactionPending.get(z):void 0,q=z??W??"__anonymous__";if(J.contextCompactionCompleting.has(q)){K(`session "${this.sessionName}": context compaction completion already writing key=${q}`);return}if(this.startWorkingFooter(J),J.currentAssistantSegmentId)this.finalizeCurrentAssistantSegment();J.openBatchI=null,this.maybeMidTurnRotate();let B=gB(G?.notice,$),L=J.contextCompactionEndOnly.get(q),F=G?.i??L??J.contextCompactCount++;if(!G&&L===void 0)J.contextCompactionEndOnly.set(q,F);J.contextCompactionCompleting.add(q);let U=[...new Set([...WX(G?.notice??{}),...Z])];if(U.length>0)this.rememberContextCompactionReceipt(U,H,!1,q);let R=O.contextCompact(F),D=p2(F,B,R);K(`session "${this.sessionName}": context compaction completion write #${F+1} key=${q}`),(async()=>{let P=!1;if(!G)for(let M=0;M<W8+2;M++){let x=J.cardId;if(P=await x0(x,D,{type:"insert_before",targetElementId:L$(J)}),P)break;let y=J.rotating;if(y){await y;continue}if(J.cardId!==x)continue;break}else for(let M=0;M<W8+2;M++){let x=G.cardId;if(await G.createPromise,G.cardId!==x)continue;if(G.created)P=await W$(x,R,D);else{if(RJ(G.createFailure?.code,G.createFailure))EJ(x,R),P=await W$(x,R,D,{notifyCardFailure:!1});if(!P)P=await x0(x,D,{type:"insert_before",targetElementId:L$(J)})}if(G.cardId!==x)continue;if(P){G.created=!0;break}let y=J.rotating;if(y){await y;continue}if(G.cardId!==x)continue;break}if(J.contextCompactionCompleting.delete(q),!P){K(`session "${this.sessionName}": context compaction completion write MISS #${F+1} key=${q}`);return}if(z&&J.contextCompactionPending.get(z)===G)J.contextCompactionPending.delete(z);if(J.contextCompactionEndOnly.delete(q),q!=="__anonymous__")J.contextCompactionCompleted.add(q);if(J.lastContextCompactionCompletedAt=Date.now(),J.lastContextCompactionWasAnonymous=q==="__anonymous__",U.length>0){let M=[...this.contextCompactionReceipts.entries()].filter(([,x])=>x.completionKey===q).map(([x])=>x);this.rememberContextCompactionReceipt([...new Set([...U,...M])],null,!0)}K(`session "${this.sessionName}": context compaction completed #${F+1} key=${q}`)})().catch((P)=>{J.contextCompactionCompleting.delete(q),K(`session "${this.sessionName}": context compaction completion transaction failed: ${j(P)}`)}),r0(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((V)=>V.startsWith("item:"))};for(let V of $)this.contextCompactionReceipts.delete(V),this.contextCompactionReceipts.set(V,Y);while(this.contextCompactionReceipts.size>lB){let V;for(let X of this.contextCompactionReceipts.values()){if(X.completed){V=X;break}V??=X}if(!V)break;for(let[X,H]of this.contextCompactionReceipts)if(H===V)this.contextCompactionReceipts.delete(X)}}handleTurnPlanUpdated($){let Z=this.currentTurn;if(!Z){K(`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))K(`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?O.taskBoardLive:O.footer;Z.planLiveInserted=!0,H$(Z.cardId,l2(Z.planSteps,Z.planExplanation,O.planLive),{type:"insert_before",targetElementId:J})}else u(Z.cardId,O.planLive,l2(Z.planSteps,Z.planExplanation,O.planLive));this.addPlanSnapshotOnCurrentTurn()}handlePlanDelta($){if(typeof $.delta!=="string"||!$.delta){K(`session "${this.sessionName}": item/plan/delta missing delta text`);return}if(typeof $.itemId!=="string"||!$.itemId)K(`session "${this.sessionName}": item/plan/delta missing itemId`)}handleThreadGoalUpdated($){if(!$||typeof $.objective!=="string"){K(`session "${this.sessionName}": thread/goal/updated missing objective`);return}if($.tokenBudget!=null&&typeof $.tokenBudget!=="number")K(`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&&j4(Z)===j4(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 V=Z.assistantSegmentCount++,X=O.assistant(V);Z.currentAssistantSegmentId=X,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);r0(Z.cardId,Y)}takeOrphanAssistantText(){let $=[...this.orphanAssistantSegments];if(this.orphanAssistantCurrent.trim())$.push(this.orphanAssistantCurrent);return this.orphanAssistantSegments=[],this.orphanAssistantCurrent="",$.join(`
|
|
195
196
|
|
|
196
|
-
|
|
197
|
+
`).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;K(`session "${this.sessionName}": flushing ${J.length} chars of orphan assistant text (${$})`),E(this.chatId,`\uD83D\uDCC4 后台轮输出(未能建卡,纯文本兜底):
|
|
197
198
|
|
|
198
|
-
`)
|
|
199
|
+
${J}`)}completedAssistantElement($,Z){if(M5(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 UY(Q);if(!await W$(Z,J,this.mathAssistantContainer(J,Y.blocks),{notifyCardFailure:!1})){K(`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),K(`session "${this.sessionName}": math rendered ${J} (${Y.renderedImageCount} img, ${Y.blocks.length} blocks)`)}addCompletedAssistantSegment($,Z,J){let Q=$.cardId,Y=L$($),V=(async()=>{if(!await x0(Q,this.completedAssistantElement(Z,J),{type:"insert_before",targetElementId:Y}))return K(`session "${this.sessionName}": assistant segment ${Z} raw write failed on card=${Q}`),!1;if(M5(J)){let H=this.replaceSegmentWithMathImgs($,Q,Z,J).catch((W)=>K(`session "${this.sessionName}": math render ${Z} failed: ${W}`));$.mathRenderInflight??=new Map,$.mathRenderInflight.get(Q)??$.mathRenderInflight.set(Q,new Set),$.mathRenderInflight.get(Q).add(H),H.finally(()=>$.mathRenderInflight?.get(Q)?.delete(H))}return!0})();return $.assistantWriteInflight??=new Map,$.assistantWriteInflight.get(Q)??$.assistantWriteInflight.set(Q,new Set),$.assistantWriteInflight.get(Q).add(V),V.finally(()=>$.assistantWriteInflight?.get(Q)?.delete(V)),V}async sendAssistantTextFallback($,Z){let J=$.trim();if(!J)return;let Q=`⚠️ 对话卡片正文写入失败(${Z}),以下为 agent 原始回复:
|
|
199
200
|
|
|
200
|
-
${J}
|
|
201
|
-
|
|
202
|
-
${J}`;if(!await A(this.chatId,Q))K(`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 IQ($))this.sendOutboundPath(Z,"send marker")}cleanAssistantTextForDisplay($){return q$($)}sendOutboundPath($,Z){let J=h4($.trim());if(!J)return;let Q=this.currentTurn;if(Q?.outboundSeenPaths.has(J))return;if(Q?.outboundSeenPaths.add(J),!jB(J)){K(`session "${this.sessionName}": ignore non-absolute outbound path from ${Z}: ${J}`);return}Q?.outboundSentPaths.add(J),K(`session "${this.sessionName}": outbound send from ${Z}: ${J}`),Z9(this.chatId,J)}startFooterStatus($,Z){if($.rotateGivenUp)return;if($.footerStatusHandle&&$.footerStatusLabel===Z)return;this.stopFooterStatus($),$.footerStatusLabel=Z,$.footerStatusStartedAt=Date.now();let J=()=>{if($.footerStatusLabel!==Z)return;let{label:Y}=L0(Date.now()-$.footerStatusStartedAt,Z1());this.replaceFooterContent($.cardId,this.withModel(`${Z} (${Y})`))},Q=()=>{if($.footerStatusLabel!==Z)return;let{nextDelayMs:Y}=L0(Date.now()-$.footerStatusStartedAt,Z1());$.footerStatusHandle=setTimeout(()=>{J(),Q()},Math.max(1,Math.ceil(Y)))};J(),Q()}startThinkingFooter($){this.startFooterStatus($,yB)}startWritingFooter($){this.startFooterStatus($,CB)}startWorkingFooter($){this.startFooterStatus($,NB)}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 X=await Q.readUsage(),z=X.windows.find((W)=>W.kind==="fiveHour"),H=X.windows.find((W)=>W.kind==="weekly");if(z||H)return this.fmtDualWindowSuffix(z??null,H??null);return X.state==="ok"&&X.planLabel?` | ${X.planLabel}`:""}if($==="codex"){let X=Z?.isAlive()&&Z.provider==="codex"&&Z.readRateLimits?Z:null,H=(X?await kQ(()=>X.readRateLimits()):null)??Y;return H?.state==="ok"?this.fmtDualWindowSuffix(H.fiveHour??null,H.weekly??null):""}let V=await Z5();return V.state==="ok"?this.fmtDualWindowSuffix(V.fiveHour??null,V.weekly??null):""}fmtDualWindowSuffix($,Z){let J=(X)=>X.resetsAt&&X.resetsAt.getTime()>Date.now()?_0(X.resetsAt):"",Q=(X)=>{if(X?.percent==null)return null;let z=J(X);return z?`${z}·${Math.round(X.percent)}%`:`${Math.round(X.percent)}%`},Y=Q($),V=Q(Z);if(Y&&V)return` | ${Y}·[${V}]`;if(Y)return` | ${Y}`;if(V)return` | [${V}]`;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(R).join("; ")}`)})}releaseTurnCloseReactions($){for(let[Z,J]of[...$.currentBatchReactionIds.entries(),...$.pendingReactionIds.entries()])if(J)B$(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:SQ(),currentBatchReactionIds:this.currentBatchReactionIds,pendingReactionIds:this.pendingReactionIds};this.currentBatchReactionIds=new Map,this.pendingReactionIds=new Map;let V=this.finishTurnCardClose(Y,$,Z).finally(()=>this.releaseTurnCloseReactions(Y));return this.turnCloseInflight.add(V),V.then(()=>{this.turnCloseInflight.delete(V)},()=>{this.turnCloseInflight.delete(V)}),V}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),V=Q.cardId,X=Q.segmentTexts;await o$(V);let z=new Map;if(Q.currentAssistantSegmentId&&Q.currentAssistantText.trim()){let{currentAssistantSegmentId:P,currentAssistantText:y}=Q;if(!await this.addCompletedAssistantSegment(Q,P,y))z.set(P,y);Q.currentAssistantSegmentId=null,Q.currentAssistantText=""}let H=Q.assistantWriteInflight?.get(V);if(H?.size)await Promise.allSettled([...H]);let W=Q.mathRenderInflight?.get(V);if(W?.size)await Promise.allSettled([...W]);let G=Q.mathRendered?.get(V);for(let[P,y]of X){if(N1(V,P)){z.set(P,y);continue}if(G?.has(P))continue;await c(V,P,this.completedAssistantElement(P,y))}if(Q.rotateGivenUp)for(let[P,y]of X)z.set(P,y);let _=Z?Z:"✅",B=[`${_} ⏱ ${Y}s`];if(J.hasFreshResult){let{contextTokens:P,contextLimit:y}=$,m=Q.provider==="claude",T=A9(P,y,m?0:void 0);if(T)B.push(`\uD83E\uDDE0 ${T}`);let w=$.lastTurnDelta?.costUsd??0;if(w>0)B.push(`\uD83D\uDCB0 $${w.toFixed(3)}`)}if(Q.contextCompactCount>0)B.push(`\uD83D\uDEA8 压缩×${Q.contextCompactCount}`);if(Q.outboundSentPaths.size>0)B.push(`\uD83D\uDCCE ${Q.outboundSentPaths.size}`);let L=this.modelLine(Q);if(L)B.push(L);let F=B.join(" | "),D=J.hasFreshResult?M9($.lastTurnUsage)+(Q.rotateGivenUp?"":await this.footerUsageSuffix(Q.provider,$.proc,$.tokenSourceId,$.tokenSource,$.codexUsage)):"",j=D?`${F}
|
|
203
|
-
${D}`:F,M=await L$(V,U.footer,this.footerElement(j));V$(V);let O=await K$(V,m$({durationSec:Y,outputTokens:J.hasFreshResult?$.lastTurnUsage?.output_tokens:void 0,suffix:Z}));if(M&&O)await C$(V);else{let P=`footer=${M?"ok":"MISS"}, settings=${O?"ok":"MISS"}`;K(`session "${this.sessionName}": terminal card transaction incomplete card=${V.slice(0,12)} ${P}`),await C(this.chatId,`⚠️ 对话卡片终态写入失败 (${P})。本轮已结束: ${_}`)}for(let P of z.values())await this.sendAssistantTextFallback(P,"CardKit 元素未落地");if((J.forcePush||!Z)&&Q.userOpenId&&Q.messageId&&!Q.rotateGivenUp)g0(Q.messageId,[Q.userOpenId])}}});function w$($){return{card:{type:"raw",data:$}}}import{readFileSync as kB}from"node:fs";function ZX($){return I5.has($)}function JX($){I5.add($)}function QX($){I5.delete($)}function J8(){try{let $={};for(let[Z,J]of e$)$[Z]=J;U$(e4,$)}catch($){throw K(`notify-callbacks: save failed (${e4}): ${$}`),$}}function YX(){let $;try{$=kB(e4,"utf8")}catch{return}try{let Z=JSON.parse($),J=Date.now()-$X,Q=0;for(let[Y,V]of Object.entries(Z)){if(!V||typeof V!=="object")continue;if(typeof V.notifyId!=="string"||typeof V.callbackUrl!=="string")continue;if(typeof V.createdAt!=="number"||V.createdAt<J){Q++;continue}e$.set(V.notifyId,V)}if(K(`notify-callbacks: loaded ${e$.size} registration(s)${Q?`, dropped ${Q} stale`:""}`),Q>0)J8()}catch(Z){K(`notify-callbacks: load failed (${e4}): ${Z}`)}}function VX($){let Z=Date.now();if(Z-eV>=wB)vB(Z),eV=Z;e$.set($.notifyId,$),J8()}function $Z($){return e$.get($)}function h5($,Z,J){let Q=e$.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{J8()}catch(V){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 V}}function bB($,Z,J,Q){let Y=e$.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,J8()}function XX($,Z,J){try{return h5($,Z,J),{state:"complete"}}catch(Q){let V=`resolved tombstone persistence failed: ${Q instanceof Error?Q.message:String(Q)}`;try{bB($,Z,J,V)}catch(X){let z=X instanceof Error?X.message:String(X);V+=`; unknown tombstone persistence also failed: ${z}`;let H=e$.get($);if(H)H.unknownReason=V}return{state:"unknown",detail:V}}}function vB($=Date.now()){let Z=$-$X,J=0;for(let[Q,Y]of e$)if(typeof Y.createdAt!=="number"||Y.createdAt<Z)e$.delete(Q),J++;if(J>0)J8();return J}async function zX($,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,V=setTimeout(()=>Y.abort(),sV);try{let X=await fetch($.callbackUrl,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(Q),signal:Y.signal});if(X.status>=200&&X.status<300){let H;try{let W=(await X.text()).trim();if(W.startsWith("{")){let G=JSON.parse(W),_=typeof G?.text==="string"?G.text:typeof G?.reply==="string"?G.reply:typeof G?.message==="string"?G.message:"";if(_.trim())H=_.trim().slice(0,500)}else if(W)H=W.slice(0,500)}catch{}return{ok:!0,detail:`${X.status}`,reply:H}}let z="";try{z=(await X.text()).slice(0,120)}catch{}return{ok:!1,detail:`HTTP ${X.status}${z?` ${z}`:""}`}}catch(X){if(X?.name==="AbortError")return{ok:!1,detail:`回调超时 ${sV}ms(本地服务未在窗口内 2xx)`};return{ok:!1,detail:`回调失败: ${String(X?.message??X).slice(0,160)}`}}finally{clearTimeout(V)}}function HX($){let Z=!!$.resolvedAt,J=!!$.unknownAt,Q=$.resolvedBy?.buttonId??$.unknownBy?.buttonId,Y=Q?$.buttons.find((V)=>V.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 $X=604800000,sV=2500,e$,eV,wB=86400000,I5,e4;var g5=E(()=>{v();v$();C0();e$=new Map,eV=Date.now(),I5=new Set;e4=B3});import{createServer as fB}from"node:http";import{randomUUID as IB}from"node:crypto";function KX($){let Z=$.level==="error"?"red":$.level==="warn"?"yellow":"blue",J=$.level==="error"?"❌":$.level==="warn"?"⚠️":"\uD83D\uDD14",Q=!!($.buttons?.length&&$.notifyId),Y=new Date,V=`${String(Y.getHours()).padStart(2,"0")}:${String(Y.getMinutes()).padStart(2,"0")}`,X=[];for(let z of $.images??[])if(z.key)X.push({tag:"img",img_key:z.key,alt:{tag:"plain_text",content:"screenshot"}});else X.push({tag:"markdown",content:`<font color='red'>\uD83D\uDCF7 图片上传失败: ${z.src}</font>`});if(X.push({tag:"markdown",content:Z7($.text??"")||"_(空消息)_"}),$.resolution){let z=$.resolution,H;if(z.status==="processing")H=`<font color='blue'>⏳ 已选择:${z.text} · 推送中…</font>`;else if(z.status==="failed")H=`<font color='red'>⚠️ 已选:${z.text} · 回调失败:${z.detail??"未知"} · ${V}</font>`;else if(z.status==="delivered")H=`<font color='green'>✅ 已选择:${z.text} · 反馈已送达 · ${V}</font>`;else if(z.status==="unknown")H=`<font color='red'>⚠️ 已选择:${z.text} · 外部回调已成功,但本地确认状态未知,禁止自动重试 · ${V}</font>`;else H=`<font color='green'>✅ 已选择:${z.text} · ${V}</font>`;if(X.push({tag:"markdown",content:H}),z.status==="delivered"&&z.reply)X.push({tag:"markdown",content:q$(z.reply)})}if(Q&&(!$.resolution||$.resolution.status==="failed"))X.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:1,elements:$.buttons.map((z)=>({tag:"button",text:{tag:"plain_text",content:z.text},type:z.type,behaviors:[{type:"callback",value:{kind:"notify_callback",notify_id:$.notifyId,button_id:z.id}}]}))}]});return X.push({tag:"hr"}),X.push({tag:"markdown",content:`<font color='grey'>via notify · ${V}</font>`}),{schema:"2.0",config:Q?{update_multi:!0}:{},header:{title:{tag:"plain_text",content:`${J} ${$.title}`},template:Z},body:{elements:X}}}function cB($){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(),V=String(Q.text??"").trim();if(!mB.test(Y))return{error:`button id "${Y.slice(0,32)}" invalid (need ^[A-Za-z0-9_-]{1,64}$)`};if(!V)return{error:`button "${Y}" missing text`};if(V.length>WX)return{error:`button "${Y}" text > ${WX} chars`};if(Z.has(Y))return{error:`button id "${Y}" duplicated`};Z.add(Y);let X=String(Q.type??"default").toLowerCase(),z=gB.has(X)?X:"default";J.push({id:Y,text:V,type:z})}return{buttons:J}}function uB($){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 GX($){try{let Z=fB((J,Q)=>{pB(J,Q).catch((Y)=>{if(K(`notify: handler crash: ${Y?.message??Y}`),!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)=>{K(`notify: server bind failed (${$.bind}:${$.port}): ${J.message}`)}),Z.listen($.port,$.bind,()=>{K(`notify: HTTP listening at http://${$.bind}:${$.port}/notify`)})}catch(Z){K(`notify: server bind failed (${$.bind}:${$.port}): ${Z}`)}}async function pB($,Z){let J=new URL($.url??"/",`http://${$.headers.host??"localhost"}`),Q=(x,k)=>{Z.statusCode=x,Z.setHeader("content-type","text/plain; charset=utf-8"),Z.end(k)},Y=(x,k)=>{Z.statusCode=x,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify(k))};if($.method==="GET"&&J.pathname==="/")return Q(200,`lodestar notify
|
|
201
|
+
${J}`;if(!await E(this.chatId,Q))K(`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 eQ($))this.sendOutboundPath(Z,"send marker")}cleanAssistantTextForDisplay($){return D$($)}sendOutboundPath($,Z){let J=r4($.trim());if(!J)return;let Q=this.currentTurn;if(Q?.outboundSeenPaths.has(J))return;if(Q?.outboundSeenPaths.add(J),!fB(J)){K(`session "${this.sessionName}": ignore non-absolute outbound path from ${Z}: ${J}`);return}Q?.outboundSentPaths.add(J),K(`session "${this.sessionName}": outbound send from ${Z}: ${J}`),B9(this.chatId,J)}startFooterStatus($,Z){if($.rotateGivenUp)return;if($.footerStatusHandle&&$.footerStatusLabel===Z)return;this.stopFooterStatus($),$.footerStatusLabel=Z,$.footerStatusStartedAt=Date.now();let J=()=>{if($.footerStatusLabel!==Z)return;let{label:Y}=M0(Date.now()-$.footerStatusStartedAt,z1());this.replaceFooterContent($.cardId,this.withModel(`${Z} (${Y})`))},Q=()=>{if($.footerStatusLabel!==Z)return;let{nextDelayMs:Y}=M0(Date.now()-$.footerStatusStartedAt,z1());$.footerStatusHandle=setTimeout(()=>{J(),Q()},Math.max(1,Math.ceil(Y)))};J(),Q()}startThinkingFooter($){this.startFooterStatus($,mB)}startWritingFooter($){this.startFooterStatus($,cB)}startWorkingFooter($){this.startFooterStatus($,uB)}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 X=await Q.readUsage(),H=X.windows.find((z)=>z.kind==="fiveHour"),W=X.windows.find((z)=>z.kind==="weekly");if(H||W)return this.fmtDualWindowSuffix(H??null,W??null);return X.state==="ok"&&X.planLabel?` | ${X.planLabel}`:""}if($==="codex"){let X=Z?.isAlive()&&Z.provider==="codex"&&Z.readRateLimits?Z:null,W=(X?await oQ(()=>X.readRateLimits()):null)??Y;return W?.state==="ok"?this.fmtDualWindowSuffix(W.fiveHour??null,W.weekly??null):""}let V=await B5();return V.state==="ok"?this.fmtDualWindowSuffix(V.fiveHour??null,V.weekly??null):""}fmtDualWindowSuffix($,Z){let J=(X)=>X.resetsAt&&X.resetsAt.getTime()>Date.now()?U0(X.resetsAt):"",Q=(X)=>{if(X?.percent==null)return null;let H=J(X);return H?`${H}·${Math.round(X.percent)}%`:`${Math.round(X.percent)}%`},Y=Q($),V=Q(Z);if(Y&&V)return` | ${Y}·[${V}]`;if(Y)return` | ${Y}`;if(V)return` | [${V}]`;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(j).join("; ")}`)})}releaseTurnCloseReactions($){for(let[Z,J]of[...$.currentBatchReactionIds.entries(),...$.pendingReactionIds.entries()])if(J)P$(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:nQ(),currentBatchReactionIds:this.currentBatchReactionIds,pendingReactionIds:this.pendingReactionIds};this.currentBatchReactionIds=new Map,this.pendingReactionIds=new Map;let V=this.finishTurnCardClose(Y,$,Z).finally(()=>this.releaseTurnCloseReactions(Y));return this.turnCloseInflight.add(V),V.then(()=>{this.turnCloseInflight.delete(V)},()=>{this.turnCloseInflight.delete(V)}),V}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),V=Q.cardId,X=Q.segmentTexts;await l$(V);let H=new Map;if(Q.currentAssistantSegmentId&&Q.currentAssistantText.trim()){let{currentAssistantSegmentId:M,currentAssistantText:x}=Q;if(!await this.addCompletedAssistantSegment(Q,M,x))H.set(M,x);Q.currentAssistantSegmentId=null,Q.currentAssistantText=""}let W=Q.assistantWriteInflight?.get(V);if(W?.size)await Promise.allSettled([...W]);let z=Q.mathRenderInflight?.get(V);if(z?.size)await Promise.allSettled([...z]);let G=Q.mathRendered?.get(V);for(let[M,x]of X){if(I1(V,M)){H.set(M,x);continue}if(G?.has(M))continue;await u(V,M,this.completedAssistantElement(M,x))}if(Q.rotateGivenUp)for(let[M,x]of X)H.set(M,x);let q=Z?Z:"✅",B=[`${q} ⏱ ${Y}s`];if(J.hasFreshResult){let{contextTokens:M,contextLimit:x}=$,y=Q.provider==="claude",N=w9(M,x,y?0:void 0);if(N)B.push(`\uD83E\uDDE0 ${N}`);let m=$.lastTurnDelta?.costUsd??0;if(m>0)B.push(`\uD83D\uDCB0 $${m.toFixed(3)}`)}if(Q.contextCompactCount>0)B.push(`\uD83D\uDEA8 压缩×${Q.contextCompactCount}`);if(Q.outboundSentPaths.size>0)B.push(`\uD83D\uDCCE ${Q.outboundSentPaths.size}`);let L=this.modelLine(Q);if(L)B.push(L);let F=B.join(" | "),U=J.hasFreshResult?b9($.lastTurnUsage)+(Q.rotateGivenUp?"":await this.footerUsageSuffix(Q.provider,$.proc,$.tokenSourceId,$.tokenSource,$.codexUsage)):"",R=U?`${F}
|
|
202
|
+
${U}`:F,D=await W$(V,O.footer,this.footerElement(R));X$(V);let P=await B$(V,i$({durationSec:Y,outputTokens:J.hasFreshResult?$.lastTurnUsage?.output_tokens:void 0,suffix:Z}));if(D&&P)await b$(V);else{let M=`footer=${D?"ok":"MISS"}, settings=${P?"ok":"MISS"}`;K(`session "${this.sessionName}": terminal card transaction incomplete card=${V.slice(0,12)} ${M}`),await C(this.chatId,`⚠️ 对话卡片终态写入失败 (${M})。本轮已结束: ${q}`)}for(let M of H.values())await this.sendAssistantTextFallback(M,"CardKit 元素未落地");if((J.forcePush||!Z)&&Q.userOpenId&&Q.messageId&&!Q.rotateGivenUp)n0(Q.messageId,[Q.userOpenId])}}});function I$($){return{card:{type:"raw",data:$}}}import{readFileSync as dB}from"node:fs";function LX($){return t5.has($)}function FX($){t5.add($)}function UX($){t5.delete($)}function z8(){try{let $={};for(let[Z,J]of Y0)$[Z]=J;O$(qZ,$)}catch($){throw K(`notify-callbacks: save failed (${qZ}): ${$}`),$}}function DX(){let $;try{$=dB(qZ,"utf8")}catch{return}try{let Z=JSON.parse($),J=Date.now()-BX,Q=0;for(let[Y,V]of Object.entries(Z)){if(!V||typeof V!=="object")continue;if(typeof V.notifyId!=="string"||typeof V.callbackUrl!=="string")continue;if(typeof V.createdAt!=="number"||V.createdAt<J){Q++;continue}Y0.set(V.notifyId,V)}if(K(`notify-callbacks: loaded ${Y0.size} registration(s)${Q?`, dropped ${Q} stale`:""}`),Q>0)z8()}catch(Z){K(`notify-callbacks: load failed (${qZ}): ${Z}`)}}function PX($){let Z=Date.now();if(Z-_X>=iB)oB(Z),_X=Z;Y0.set($.notifyId,$),z8()}function _Z($){return Y0.get($)}function s5($,Z,J){let Q=Y0.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{z8()}catch(V){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 V}}function nB($,Z,J,Q){let Y=Y0.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,z8()}function AX($,Z,J){try{return s5($,Z,J),{state:"complete"}}catch(Q){let V=`resolved tombstone persistence failed: ${Q instanceof Error?Q.message:String(Q)}`;try{nB($,Z,J,V)}catch(X){let H=X instanceof Error?X.message:String(X);V+=`; unknown tombstone persistence also failed: ${H}`;let W=Y0.get($);if(W)W.unknownReason=V}return{state:"unknown",detail:V}}}function oB($=Date.now()){let Z=$-BX,J=0;for(let[Q,Y]of Y0)if(typeof Y.createdAt!=="number"||Y.createdAt<Z)Y0.delete(Q),J++;if(J>0)z8();return J}async function MX($,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,V=setTimeout(()=>Y.abort(),qX);try{let X=await fetch($.callbackUrl,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(Q),signal:Y.signal});if(X.status>=200&&X.status<300){let W;try{let z=(await X.text()).trim();if(z.startsWith("{")){let G=JSON.parse(z),q=typeof G?.text==="string"?G.text:typeof G?.reply==="string"?G.reply:typeof G?.message==="string"?G.message:"";if(q.trim())W=q.trim().slice(0,500)}else if(z)W=z.slice(0,500)}catch{}return{ok:!0,detail:`${X.status}`,reply:W}}let H="";try{H=(await X.text()).slice(0,120)}catch{}return{ok:!1,detail:`HTTP ${X.status}${H?` ${H}`:""}`}}catch(X){if(X?.name==="AbortError")return{ok:!1,detail:`回调超时 ${qX}ms(本地服务未在窗口内 2xx)`};return{ok:!1,detail:`回调失败: ${String(X?.message??X).slice(0,160)}`}}finally{clearTimeout(V)}}function OX($){let Z=!!$.resolvedAt,J=!!$.unknownAt,Q=$.resolvedBy?.buttonId??$.unknownBy?.buttonId,Y=Q?$.buttons.find((V)=>V.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 BX=604800000,qX=2500,Y0,_X,iB=86400000,t5,qZ;var e5=T(()=>{v();m$();f0();Y0=new Map,_X=Date.now(),t5=new Set;qZ=N3});import{createServer as rB}from"node:http";import{randomUUID as aB}from"node:crypto";function RX($){let Z=$.level==="error"?"red":$.level==="warn"?"yellow":"blue",J=$.level==="error"?"❌":$.level==="warn"?"⚠️":"\uD83D\uDD14",Q=!!($.buttons?.length&&$.notifyId),Y=new Date,V=`${String(Y.getHours()).padStart(2,"0")}:${String(Y.getMinutes()).padStart(2,"0")}`,X=[];for(let H of $.images??[])if(H.key)X.push({tag:"img",img_key:H.key,alt:{tag:"plain_text",content:"screenshot"}});else X.push({tag:"markdown",content:`<font color='red'>\uD83D\uDCF7 图片上传失败: ${H.src}</font>`});if(X.push({tag:"markdown",content:Y6($.text??"")||"_(空消息)_"}),$.resolution){let H=$.resolution,W;if(H.status==="processing")W=`<font color='blue'>⏳ 已选择:${H.text} · 推送中…</font>`;else if(H.status==="failed")W=`<font color='red'>⚠️ 已选:${H.text} · 回调失败:${H.detail??"未知"} · ${V}</font>`;else if(H.status==="delivered")W=`<font color='green'>✅ 已选择:${H.text} · 反馈已送达 · ${V}</font>`;else if(H.status==="unknown")W=`<font color='red'>⚠️ 已选择:${H.text} · 外部回调已成功,但本地确认状态未知,禁止自动重试 · ${V}</font>`;else W=`<font color='green'>✅ 已选择:${H.text} · ${V}</font>`;if(X.push({tag:"markdown",content:W}),H.status==="delivered"&&H.reply)X.push({tag:"markdown",content:D$(H.reply)})}if(Q&&(!$.resolution||$.resolution.status==="failed"))X.push({tag:"column_set",columns:[{tag:"column",width:"weighted",weight:1,elements:$.buttons.map((H)=>({tag:"button",text:{tag:"plain_text",content:H.text},type:H.type,behaviors:[{type:"callback",value:{kind:"notify_callback",notify_id:$.notifyId,button_id:H.id}}]}))}]});return X.push({tag:"hr"}),X.push({tag:"markdown",content:`<font color='grey'>via notify · ${V}</font>`}),{schema:"2.0",config:Q?{update_multi:!0}:{},header:{title:{tag:"plain_text",content:`${J} ${$.title}`},template:Z},body:{elements:X}}}function $L($){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(),V=String(Q.text??"").trim();if(!eB.test(Y))return{error:`button id "${Y.slice(0,32)}" invalid (need ^[A-Za-z0-9_-]{1,64}$)`};if(!V)return{error:`button "${Y}" missing text`};if(V.length>jX)return{error:`button "${Y}" text > ${jX} chars`};if(Z.has(Y))return{error:`button id "${Y}" duplicated`};Z.add(Y);let X=String(Q.type??"default").toLowerCase(),H=sB.has(X)?X:"default";J.push({id:Y,text:V,type:H})}return{buttons:J}}function ZL($){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 EX($){try{let Z=rB((J,Q)=>{JL(J,Q).catch((Y)=>{if(K(`notify: handler crash: ${Y?.message??Y}`),!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)=>{K(`notify: server bind failed (${$.bind}:${$.port}): ${J.message}`)}),Z.listen($.port,$.bind,()=>{K(`notify: HTTP listening at http://${$.bind}:${$.port}/notify`)})}catch(Z){K(`notify: server bind failed (${$.bind}:${$.port}): ${Z}`)}}async function JL($,Z){let J=new URL($.url??"/",`http://${$.headers.host??"localhost"}`),Q=(A,k)=>{Z.statusCode=A,Z.setHeader("content-type","text/plain; charset=utf-8"),Z.end(k)},Y=(A,k)=>{Z.statusCode=A,Z.setHeader("content-type","application/json"),Z.end(JSON.stringify(k))};if($.method==="GET"&&J.pathname==="/")return Q(200,`lodestar notify
|
|
204
203
|
`+`POST /notify body={project,text,title?,level?,images?,buttons?,callback?} → push card to group
|
|
205
204
|
`+`GET /notify/result/<notify_id> → poll a button card's resolution (pull mode, no callback server)
|
|
206
205
|
`+`levels: info|warn|error (default info); images=[/abs/*.png] uploaded + embedded
|
|
207
206
|
`+`buttons:[{id,text,type?}] (any count, one per row); callback=http://127.0.0.1:PORT/path optional (push) — omit to poll
|
|
208
|
-
`);if($.method==="GET"&&J.pathname.startsWith("/notify/result/")){let
|
|
209
|
-
name: ${
|
|
207
|
+
`);if($.method==="GET"&&J.pathname.startsWith("/notify/result/")){let A=decodeURIComponent(J.pathname.slice(15)).trim();if(!A)return Q(400,"missing notify_id in path");let k=_Z(A);if(!k)return Y(404,{error:"unknown notify_id",notify_id:A});return Y(200,OX(k))}if($.method!=="POST"||J.pathname!=="/notify")return Q(405,"use POST /notify");let V="";for await(let A of $)V+=A.toString();let X={};try{X=JSON.parse(V)}catch{return Q(400,"bad json")}let H=String(X.project??"").trim(),W=String(X.text??""),z=String(X.title??"").trim(),G=String(X.level??"info").toLowerCase();if(!H)return Q(400,'missing "project"');if(!W)return Q(400,'missing "text"');let{buttons:q,error:B}=$L(X.buttons);if(B)return Q(400,B);let{url:L,error:F}=ZL(X.callback);if(F)return Q(400,F);let U=!!(q&&q.length),R=L??"",D=tB.has(G)?G:"info",P=z||H,M=I2(H),x=f1(M);if(!x)return K(`notify: project "${H}" (sanitized "${M}") has no chat binding → 404`),Q(404,`project "${H}" not bound — send any message in that Feishu group at least once after the daemon started, then retry`);let y=Array.isArray(X.images)?X.images:[],N=[];for(let A of y){let k=String(A??"").trim();if(!k)continue;let s=await _9(k);N.push({key:s??"",src:k})}let m=U?`nf_${aB()}`:"",h=RX({title:P,text:W,level:D,images:N,buttons:q,notifyId:m}),w=await l(x,h);if(!w)return K(`notify: sendCard failed → 502 (project="${H}" chat=${x.slice(0,8)}…)`),Q(502,"feishu sendCard failed (see daemon log)");if(U&&m){let A={notifyId:m,callbackUrl:R,chatId:x,messageId:w,project:H,title:P,text:W,level:D,imageKeys:N,buttons:q,createdAt:Date.now()};PX(A)}K(`notify: → ${H} (${x.slice(0,8)}…) level=${D} bytes=${W.length} images=${N.length} buttons=${q?.length??0} push=${U&&!!R?1:0} msg=${w}`),Y(200,{ok:!0,chat_id:x,message_id:w,...m?{notify_id:m}:{}})}function BZ($,Z){return RX({title:$.title,text:$.text,level:$.level,images:$.imageKeys,buttons:$.buttons,notifyId:$.notifyId,resolution:Z})}var tB,sB,eB,jX=64;var $3=T(()=>{v();n();y$();e5();tB=new Set(["info","warn","error"]),sB=new Set(["default","primary","danger"]),eB=/^[A-Za-z0-9_-]{1,64}$/});import{existsSync as QL,mkdirSync as YL,readFileSync as VL,writeFileSync as XL}from"node:fs";import{homedir as TX}from"node:os";import{dirname as HL,join as Z3}from"node:path";function WL($){return`---
|
|
208
|
+
name: ${xX}
|
|
210
209
|
description: 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.
|
|
211
210
|
---
|
|
212
211
|
|
|
@@ -374,25 +373,25 @@ Notes:
|
|
|
374
373
|
Hand-edits will be overwritten — set
|
|
375
374
|
\`LODESTAR_DISABLE_SKILL_SYNC=1\` and restart the daemon if you want
|
|
376
375
|
to maintain the file yourself.
|
|
377
|
-
`}function
|
|
376
|
+
`}function CX(){if(process.env.LODESTAR_DISABLE_SKILL_SYNC==="1"){K("skill: sync disabled via LODESTAR_DISABLE_SKILL_SYNC, skip");return}let $=[Z3(TX(),".codex","skills"),Z3(TX(),".claude","skills")],Z=WL(f.notify.port);for(let J of $){let Q=Z3(J,xX,"SKILL.md");try{let Y=QL(Q)?VL(Q,"utf8"):null;if(Y===Z)continue;YL(HL(Q),{recursive:!0}),XL(Q,Z),K(`skill: ${Y===null?"installed":"updated"} ${Q}`)}catch(Y){K(`skill: sync failed (${Q}): ${Y}`)}}}var xX="feishu-notify";var NX=T(()=>{v();N$()});import{execFileSync as zL}from"node:child_process";import{dirname as KL,join as GL,resolve as LZ}from"node:path";function J3($,Z,J,Q){qL($);let Y=GL(KL($),`${Z}[${J}]`),V=d($,["rev-parse","HEAD"]).trim();if(Q&&V!==Q)throw Error(`project HEAD changed before worktree prepare: expected ${Q}, got ${V}`);let X=Q??V,H=FL($).get(J)??null;if(!LL($,J))d($,["branch",J,"HEAD"]);if(H){if(LZ(H)!==LZ(Y))throw Error(`${J} is already mounted at ${H}`)}else d($,["worktree","add",Y,J]);_L(Y,J),BL(Y);let W=Number(d(Y,["rev-list","--count",`${X}..HEAD`]).trim()||"0");if(W>0)throw Error(`${J} has ${W} commit(s) not reachable from project HEAD; merge or reset it before next automation run`);return d(Y,["reset","--hard",X]),Y}function qL($){let Z=d($,["rev-parse","--show-toplevel"]).trim();if(LZ(Z)!==LZ($))throw Error(`${$} is not the git repository root (${Z})`)}function _L($,Z){let J=d($,["branch","--show-current"]).trim();if(J!==Z)throw Error(`${$} is on ${J}, expected ${Z}`)}function BL($){let Z=d($,["status","--porcelain=v1"]).split(`
|
|
378
377
|
`).filter(Boolean);if(Z.length>0)throw Error(`worktree has uncommitted changes:
|
|
379
378
|
${Z.slice(0,8).join(`
|
|
380
|
-
`)}`)}function
|
|
381
|
-
`)){if(Q.startsWith("worktree "))J=Q.slice(9);if(Q.startsWith("branch refs/heads/")&&J)Z.set(Q.slice(18),J)}return Z}function
|
|
382
|
-
`)}var r1="AI-AUTO",Q8="AI-REVIEW";var l5=()=>{};import{execFileSync as t5}from"node:child_process";import{spawn as zL}from"cross-spawn";import{createHash as HL,randomUUID as WL}from"node:crypto";import{existsSync as KL,readFileSync as TX}from"node:fs";import{StringDecoder as UX}from"node:string_decoder";function CX(){return process.env.LODESTAR_TASK_CODEX_MODEL??Q$("codex-sub")?.defaultModel??""}function s5(){let $=CX(),Z=process.env.LODESTAR_TASK_CODEX_EFFORT??"xhigh";return $?["-m",$,"-c",`model_reasoning_effort="${Z}"`]:[]}function NX($={}){if(X8||o1||a1)return;t1=!1,($.adoptPersistedRuns??RL)(),o1=setTimeout(()=>{o1=null,a1=BL($.reconcileDeletions??FQ).catch((J)=>K(`tasklist-worker: startup failed: ${O$(J)}`)).finally(()=>{a1=null})},$.bootDelayMs??GL),K(`tasklist-worker: scheduled every ${xX/1000}s`)}async function BL($){try{await $()}catch(Z){K(`tasklist-worker: deletion reconcile failed: ${O$(Z)}`)}if(t1)return;if(await AX(),!t1)X8=setInterval(()=>{AX()},xX)}async function AX(){if(t1)return;if(d5){K("tasklist-worker: previous scan still running, skip");return}d5=!0;try{let $=n2().filter((J)=>!J.deleting);if($.length===0)return;let Z=PX%$.length;for(let{value:J,index:Q}of LL($,Z)){let Y=J.projectName;if(Q1.has(Y))continue;if(Q1.size>=qL)break;let V=DL(Y).catch((X)=>K(`tasklist-worker: ${Y} scan crashed: ${O$(X)}`)).finally(()=>{Q1.delete(Y)});Q1.set(Y,V),PX=(Q+1)%$.length}}catch($){K(`tasklist-worker: scan failed: ${O$($)}`)}finally{d5=!1}}function LL($,Z){if($.length===0)return[];let J=(Z%$.length+$.length)%$.length;return $.map((Q,Y)=>{let V=(J+Y)%$.length;return{value:$[V],index:V}})}function MX($,Z,J){return $===0&&Z===0&&!J}async function SX($=HZ){if(t1=!0,o1)clearTimeout(o1),o1=null;if(X8)clearInterval(X8),X8=null;let Z=async(J)=>{let Q=new Set,Y=Date.now()+$;while(Date.now()<Y){EX();for(let V of M$.values()){if(Q.has(V))continue;Q.add(V),n5(V,J)}if(MX(M$.size,Q1.size,!!a1))return!0;await new Promise((V)=>setTimeout(V,50))}return EX(),MX(M$.size,Q1.size,!!a1)};if(await Z("SIGTERM"))return;if(await Z("SIGKILL"))return;throw Error(`${M$.size} tasklist process group(s), ${Q1.size} project scan(s), startup=${a1?"running":"idle"} did not settle during shutdown`)}function FL($){let Z=$.sections;return Boolean(Z&&Z.design&&Z.aiTodo&&Z.aiDoing&&Z.aiReview&&Z.done)}async function DL($){let Z=I0($);try{if(!KL(Z))throw Error(`project directory does not exist: ${Z}`);let J=A$($);if(!J)throw Error(`tasklist is not enabled for ${$}`);if(J.deleting){K(`tasklist-worker: skip ${$}; tasklist deletion is pending`);return}let Q=J,Y=J.worker?.lastSectionEnsureAt?Date.parse(J.worker.lastSectionEnsureAt):0;if(Date.now()-Y>_L||!FL(J))Q=await qQ($),F$($,(X)=>{X.worker??={},X.worker.lastSectionEnsureAt=new Date().toISOString()}),Q=A$($)??Q;if(await OL($,Q),Q=A$($)??Q,jL($)){K(`tasklist-worker: skip ${$}; recovered automation run is still alive`);return}let V=await UL(Q);if(ML($,V),await NL($,Z,Q,V.aiReview))return;if(await xL($,Z,Q,V.design))return;if(await yL($,Z,Q,V.aiTodo,V.aiDoing,V.aiReview))return;if(await CL($,Z,Q,V.aiDoing))return}catch(J){let Q=O$(J);K(`tasklist-worker: ${$} failed: ${Q}`),F$($,(Y)=>{Y.worker??={},Y.worker.lastScanAt=new Date().toISOString(),Y.worker.lastScanError=Q})}}async function UL($){let Z=$.sections??{},J=Z.aiTodo?await V0(Z.aiTodo,!1):[],Q=Z.aiDoing?await V0(Z.aiDoing,!1):[],Y=Z.aiReview?await V0(Z.aiReview):[],V=Z.done?await V0(Z.done):[],X=new Set([Z.aiTodo,Z.aiDoing,Z.aiReview,Z.done].filter((G)=>!!G)),z=PL(await A2($.guid)).filter((G)=>!X.has(G.guid)),H=await Promise.all(z.map((G)=>V0(G.guid,!1))),W=await E6($.guid,!1);return{design:AL(W,[J,Q,Y,V,...H]),aiTodo:J,aiDoing:Q,aiReview:Y,done:V}}function PL($){let Z=r2("design");return $.filter((J)=>!J.isDefault).filter((J)=>J.name!==Z)}function AL($,Z){let J=new Set(Z.flat().map((Q)=>Q.guid));return $.filter((Q)=>!J.has(Q.guid))}function ML($,Z){F$($,(J)=>{let Q=new Date().toISOString();J.worker??={},J.worker.lastScanAt=Q,J.worker.lastScanError=void 0;for(let[Y,V]of Object.entries(Z))for(let X of V){let z=k$(J,X.guid);z.summary=X.summary,z.sectionKey=Y,z.completedAt=X.completedAt,z.lastSeenAt=Q}})}async function OL($,Z){let J=Object.values(Z.processes??{}).filter((Q)=>Q.status==="running");for(let Q of J){if(e5(Q)){kX(Q);continue}let Y="",V=M$.get(Q.runId);if(V?.source==="recovered"&&V.pgid&&x0(V.pgid))try{await wX(V.pgid)}catch(z){Y=`; recovered process-group cleanup failed: ${O$(z)}`}if(!V?.pgid||!x0(V.pgid))M$.delete(Q.runId);let X=`recorded ${Q.kind} process is no longer running (pid ${Q.pid??"unknown"})${Y}`;if(K(`tasklist-worker: mark stale process failed project=${$} run=${Q.runId}: ${X}`),a5($,Q,X),Q.taskGuid)try{await b$($,Q.taskGuid,`自动化进程已丢失:${X}`)}catch(z){K(`tasklist-worker: stale process comment failed run=${Q.runId}: ${O$(z)}`)}}}function RL(){if(process.platform==="win32"){let $=n2().flatMap((Z)=>Object.values(Z.processes??{})).filter((Z)=>Z.status==="running").length;if($>0)K(`tasklist-worker: ${$} recovered Windows run(s) cannot be adopted after restart without a Job Object; taskkill /T remains available only for leaders spawned by this daemon`);return}for(let $ of n2())for(let Z of Object.values($.processes??{}))if(Z.status==="running"&&e5(Z))kX(Z)}function kX($){if(process.platform==="win32"||$.status!=="running")return!1;if(M$.has($.runId))return!1;if(!e5($))return!1;if(!$.pid||!$.pgid||$.pgid<=0)return K(`tasklist-worker: cannot adopt recovered run=${$.runId}; missing pid/pgid`),!1;let Z=TL($.pid);if(Z!==$.pgid)return K(`tasklist-worker: cannot adopt recovered run=${$.runId}; persisted pgid=${$.pgid} actual=${Z??"MISS"}`),!1;return M$.set($.runId,{runId:$.runId,projectName:$.projectName,source:"recovered",proc:null,pid:$.pid,pgid:$.pgid,leaderFinished:!0}),K(`tasklist-worker: adopted recovered run=${$.runId} pid=${$.pid} pgid=${$.pgid}`),!0}function jL($){return[...M$.values()].some((Z)=>Z.source==="recovered"&&Z.projectName===$)}function e5($){if(!$.pid||$.pid<=0)return!1;let Z=EL($.pid);if(!Z)return!1;let J=$.command[0];if(!J)return!0;let Q=J.split(/[\\/]/).pop()??J;if(!(Z.includes(J)||Z.includes(Q)))return!1;return $.command.slice(1).filter((V)=>V&&V!=="<prompt>").every((V)=>Z.includes(V))}function EL($){try{if(process.platform==="linux")return TX(`/proc/${$}/cmdline`,"utf8").replace(/\0/g," ").trim();return t5("ps",["-p",String($),"-o","args="],{encoding:"utf8",timeout:2000}).trim()}catch{return null}}function TL($){try{if(process.platform==="linux"){let Z=TX(`/proc/${$}/stat`,"utf8"),J=Z.slice(Z.lastIndexOf(") ")+2).trim().split(/\s+/),Q=Number.parseInt(J[2]??"",10);return Number.isInteger(Q)&&Q>0?Q:null}if(process.platform!=="win32"){let Z=Number.parseInt(t5("ps",["-p",String($),"-o","pgid="],{encoding:"utf8",timeout:2000}).trim(),10);return Number.isInteger(Z)&&Z>0?Z:null}}catch{}return null}async function xL($,Z,J,Q){for(let Y of Q){let V=await $3(J,"design",Y.guid),X=uL(V),z=e1($,Y.guid);if(z.codexPlan?.status==="running"||z.agyPlan?.status==="running")return!0;let H=z.codexPlan?.fingerprint===X&&!!z.codexPlan.status,W=z.agyPlan?.fingerprint===X&&!!z.agyPlan.status;if(H&&W)continue;if(!H){if((await kL($,Z,J,Y.guid,V,X)).status!=="exited")return!0}if(!W)await wL($,Z,J,Y.guid,V,X);return!0}return!1}async function yL($,Z,J,Q,Y,V){if(Y.length>0||V.length>0||Q.length===0)return!1;let X=n2().find((W)=>W.projectName===$)?.processes;if(X&&Object.values(X).some((W)=>W.status==="running"&&W.kind==="codex-execute"))return!0;let z=await bL($,Z,J,Q);if(!z)return!0;let H=J.sections?.aiDoing;if(!H)throw Error("missing [AI]执行中 section guid");return await O2(z,J.guid,H),F$($,(W)=>{let G=k$(W,z);G.sectionKey="aiDoing",G.codexExecution=void 0,G.agyReview=void 0,G.codexMerge=void 0,G.executionBranch=void 0,G.executionTag=void 0,G.reviewBranch=void 0,G.reviewRef=void 0,G.lastError=void 0,W.worker??={},W.worker.runningTaskGuid=z}),!0}async function CL($,Z,J,Q){if(Q.length===0)return!1;let Y=Q[0],V=e1($,Y.guid);if(V.codexExecution?.status==="running")return!0;if(V.codexExecution?.status==="failed")return!0;if(V.codexExecution?.status==="exited"){if(!XZ(V)){let z=YZ(Y.guid);try{let H=l(Z,["rev-parse",`${z}^`]).trim();if(!H)throw Error(`cannot resolve parent of ${z}`);F$($,(W)=>{let G=k$(W,Y.guid);G.executionBranch=r1,G.executionTag=z,G.reviewBranch=Q8,G.reviewRef=QZ(H,z)})}catch(H){let W=`Codex 执行进程已退出,但无法恢复本地审查请求:${O$(H)}`;return V1($,Y.guid,"codexExecution",V.codexExecution.runId,void 0,"failed",W),await b$($,Y.guid,W),!0}}return await OX($,Z,J,Y.guid)}if((await vL($,Z,J,Y.guid)).status!=="exited")return!0;return await OX($,Z,J,Y.guid)}async function OX($,Z,J,Q){let Y=e1($,Q);if(!XZ(Y))return!0;if(Y.agyReview?.status==="running")return!0;if(Y.agyReview?.status==="failed")return!0;if(Y.agyReview?.status!=="exited"){if((await fL($,Z,J,Q,r5(Y))).status!=="exited")return!0}let V=J.sections?.aiReview;if(!V)throw Error("missing [AI]待审核 section guid");return await O2(Q,J.guid,V),F$($,(X)=>{let z=k$(X,Q);z.sectionKey="aiReview",X.worker??={},X.worker.runningTaskGuid=void 0}),!0}async function NL($,Z,J,Q){for(let Y of Q){if(!SL(Y))continue;let V=e1($,Y.guid);if(V.codexMerge?.status==="running")return!0;if(V.codexMerge?.status==="exited"){if(!XZ(V))return V1($,Y.guid,"codexMerge",V.codexMerge.runId,void 0,"failed","Codex 合并进程已退出,但本地状态缺少审查请求。"),await b$($,Y.guid,"Codex 合并进程已退出,但本地状态缺少审查请求。"),!0;return await RX($,Z,J,Y.guid,r5(V))}if(V.codexMerge?.status==="failed")return!0;if(!XZ(V))return await b$($,Y.guid,"审核完成后无法合并:本地状态里没有本地审查请求。"),!0;let X=r5(V),z=await IL($,Z,J,Y.guid,X);if(z.status!=="exited")return!0;if(!String(z.stdoutTail??"").includes("LODESTAR_MERGE_STATUS: MERGED"))return await b$($,Y.guid,"Codex 合并进程未明确输出 `LODESTAR_MERGE_STATUS: MERGED`,任务保留在审核分组。"),!0;return await RX($,Z,J,Y.guid,X)}return!1}async function RX($,Z,J,Q,Y){let V=DX(Z,Y);if(V.ok===!1){let z=e1($,Q),H=`Codex 合并进程已退出,但本地 Git 未确认合并:${V.error}`;if(z.codexMerge)V1($,Q,"codexMerge",z.codexMerge.runId,void 0,"failed",H);return await b$($,Q,H),!0}let X=J.sections?.done;if(!X)throw Error("missing 已完成 section guid");return await O2(Q,J.guid,X),F$($,(z)=>{let H=k$(z,Q);H.sectionKey="done"}),!0}function SL($){return typeof $.completedAt==="string"&&$.completedAt.trim().length>0}async function kL($,Z,J,Q,Y,V){let X=[`你是 ${$} 项目的任务讨论者。`,"请结合项目实情,对这个需求做简单评审;不执行、不修改文件,可以帮着扩展想法。","如果任务中有明确的询问性质内容,必须认真回答。",`最终回答以 ${CX()||"codex"} 的身份输出,内容会直接发到飞书任务评论区。`,"","任务完整结构化数据:",z8(Y)].join(`
|
|
383
|
-
`),
|
|
384
|
-
`),
|
|
385
|
-
`),V=await
|
|
386
|
-
`),G=await
|
|
387
|
-
`)))}catch(
|
|
388
|
-
`),G=await
|
|
389
|
-
`),
|
|
390
|
-
${
|
|
391
|
-
${
|
|
392
|
-
`)}function
|
|
393
|
-
`)}function
|
|
394
|
-
|
|
395
|
-
[truncated ${Z.length-
|
|
396
|
-
`+$.replace(/```/g,"`\\`\\`")+"\n```"}function Y1($,Z){return $.length<=Z?$:$.slice($.length-Z)}function O$($){return $ instanceof Error?$.message:String($)}var xX=300000,GL=15000,_L=1800000,VZ=20000,i5=15000,qL=2,zZ=3600000,yX=10800000,HZ=5000,X8=null,o1=null,a1=null,d5=!1,t1=!1,Q1,M$,PX=0;var bX=E(()=>{_5();U1();x$();d();v();C4();C5();l5();l5();Q1=new Map,M$=new Map});function vX($,Z,J){return $>0&&Z-$>J}function fX($,Z){return $.add(Z),Z.then(()=>{$.delete(Z)},()=>{$.delete(Z)}),Z}async function IX($){while(!0){let Z=[...$()];if(Z.length===0)return;await Promise.allSettled(Z)}}function sL($){let Z=$?.action?.value??{},J=String(Z.kind??"");if(!J)return"无效操作";if(!tL.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 Q3{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),V;return V=Y.then(()=>{},()=>{}).finally(()=>{if(this.tails.get(J)===V)this.tails.delete(J)}),this.tails.set(J,V),{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 hX($){let Z=$.now??Date.now;return{accept(J){let Q=Z();return $.actor.tryEnqueue($.key(J),()=>$.execute(J,Q))}}}class Y3{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 J3($){if(Array.isArray($))return`[${$.map(J3).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)}:${J3(J)}`).join(",")}}`}function eL($){let Z=$?.action?.value??{},J=String(Z?.kind??"unknown"),Q=String($?.context?.open_chat_id??""),Y=String($?.context?.open_message_id??""),V=null;switch(J){case"menu":V={request_id:Z.request_id};break;case"permission":V={request_id:Z.request_id};break;case"ask":V={tool_use_id:Z.tool_use_id,question_idx:Z.question_idx};break;case"worktree_disband":V={slug:Z.slug};break;case"temp_fork_select":case"temp_back_select":case"temp_resume_select":V={panel_id:Z.panel_id};break;case"tasklist_delete_prompt":case"tasklist_delete_confirm":V={guid:Z.guid};break;case"tasklist_enable":V={guid:Z.guid,project:Z.project,panel_id:Z.panel_id};break;case"token_source_enable":V={source_id:Z.source_id};break;case"agy_forward_codex":V={result_id:Z.result_id};break;case"notify_callback":V={notify_id:Z.notify_id};break;case"provider_select":case"model_select":case"model_custom_prompt":case"model_panel_cancel":case"model_effort_select":V={panel_id:Z.panel_id};break;default:V=Z}return`${Q}\x00${Y}\x00${J}\x00${J3(V)}`}function $F($){let Z=String($?.event_id??$?.header?.event_id??$?.event?.event_id??"");return{...Z?{deliveryKey:`event\x00${Z}`}:{},businessKey:`semantic\x00${eL($)}`}}function ZF(){return new Promise(($)=>setTimeout($,0))}function WZ($,Z,J){if(Z.deliveryKey)$.complete(Z.deliveryKey);if(J)$.complete(Z.businessKey);else $.fail(Z.businessKey)}function gX($){let Z=$.afterAck??ZF,J=(Y)=>{try{$.onBackgroundError?.(Y)}catch{}},Q=async(Y)=>{try{await Y()}catch(V){J(V)}};return{accept(Y){if(!$.actor.isAccepting())return $.responses.closed(Y);let V=sL(Y);if(V)return $.responses.invalid(Y,V);let X=$F(Y),z=X.deliveryKey?[X.deliveryKey,X.businessKey]:[X.businessKey],H=$.deduper.claimAll(z);if(H==="inflight")return $.responses.inflight(Y);if(H==="completed")return $.responses.completed(Y);let W=$.actor.tryEnqueue($.scope(Y),async()=>{try{await Z()}catch(B){$.deduper.failAll(z),J(B);return}let G;try{G=await $.execute(Y)}catch(B){$.deduper.completeAll(z),await Q(()=>$.presentExecutionFailure(Y,B));return}await Q(async()=>{try{await $.present(Y,G)}catch(B){await $.presentPresentationFailure(Y,B)}});let _;try{_=$.completion(Y,G)}catch(B){WZ($.deduper,X,!1),J(B);return}if(_){let B=_.then((L)=>{WZ($.deduper,X,L==="complete")},(L)=>{WZ($.deduper,X,!1),J(L)});$.track(B);return}WZ($.deduper,X,$.businessSucceeded(Y,G))});if(!W.accepted)return $.deduper.failAll(z),$.responses.closed(Y);return $.track(W.completion),W.completion.catch(J),$.responses.accepted(Y)}}}var tL;var mX=E(()=>{tL=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","agy_forward_codex","notify_callback"])});function q0($){return $ instanceof Error?$.message:String($)}function cX($,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 uX($){let Z=(Y,V)=>{let X=$.registry.get(Y);if(X&&X.sessionName!==V)throw Error(`chat ${Y} is already owned by session "${X.sessionName}", not "${V}"`);if(!X)X=$.createSession(V,Y),$.registry.set(Y,X);return X};return{sessionFor:Z,createTempSession:async(Y)=>{let V;try{if(X$(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(V=await $.ensureChatForSession(Y.chatName,Y.userOpenId),!V.created)return{ok:!1,chatId:V.chatId,error:"临时会话必须使用新群;既有群保留,未执行加入、启动或删除"}}catch(z){let H=q0(z);return $.log(`temp-session: create "${Y.chatName}" failed: ${H}`),{ok:!1,error:H}}let X=async()=>{let z=null;try{if($.registerTempSessionLease(Y.chatName,V.chatId),z=Z(V.chatId,Y.chatName),z.isRunning())return{ok:!1,error:`${Y.chatName} 已有会话在跑,先 bye 解散再重试`};if(z.workDir!==Y.workDir)throw Error(`临时群 cwd 不匹配: source=${Y.workDir} target=${z.workDir}`);if(z.applyConversationRouting(Y.routing),!(Y.launch.kind==="fork"?await z.startForked(Y.launch,{announce:!1}):await z.start({announce:!1})))throw Error(`${z.backendLabel()} 启动失败`);return $.replaceTurnAnchors(Y.chatName,Y.seedAnchors??[],Y.branchBase),{ok:!0,chatId:V.chatId}}catch(H){let W=q0(H);if($.log(`temp-session: initialize "${Y.chatName}" failed: ${W}`),z)try{await z.stop("临时群启动失败清理",{announce:!1})}catch(_){let B=q0(_);return $.log(`temp-session: failed-create stop "${Y.chatName}" failed: ${B}`),{ok:!1,chatId:V.chatId,error:`${W};无法确认 Session 已停止,临时群/session 仍保留: ${B}`}}if(!V.created)return{ok:!1,error:`${W};既有群保留,未执行删除`};let G;try{let _=await $.disbandChatForSessionExact(Y.chatName,V.chatId);G=cX(Y.chatName,V.chatId,_)}catch(_){let B=q0(_);return $.log(`temp-session: create cleanup "${Y.chatName}" failed: ${B}`),{ok:!1,chatId:V.chatId,error:`${W};自动解散失败,临时群/session 仍保留: ${B}`}}try{$.registry.delete(G),z?.dispose(),$.clearSessionConversationState(Y.chatName)}catch(_){let B=q0(_);return $.log(`temp-session: local cleanup "${Y.chatName}" failed: ${B}`),{ok:!1,error:`${W};临时群已确认解散,但本地状态清理失败: ${B}`}}return{ok:!1,error:`${W};本次新建的临时群已确认解散`}}};try{return $.runExclusive?await $.runExclusive(V.chatId,X):await X()}catch(z){let H=q0(z);return $.log(`temp-session: target actor "${Y.chatName}" failed: ${H}`),{ok:!1,chatId:V.chatId,error:`${H};临时群/session 仍保留`}}},disbandTempSession:async(Y,V)=>{let X=$.chatIdForSession(Y);if(!V||X!==V){let W=`临时群 chat_id 已变化: expected=${V||"-"} bound=${X??"-"}`;return $.log(`temp-session: disband identity rejected "${Y}": ${W}`),{ok:!1,error:`${W};未执行停止或删群`}}if(!$.hasTempSessionLease(Y,V)){let W=`群 ${V} 没有 Lodestar 临时会话 lease,拒绝解散`;return $.log(`temp-session: disband lease rejected "${Y}": ${W}`),{ok:!1,error:`${W};未执行停止或删群`}}let z=$.registry.get(X);try{if(z)await z.stop("bye 解散",{announce:!1})}catch(W){let G=q0(W);return $.log(`temp-session: stop before disband "${Y}" failed: ${G}`),{ok:!1,error:`${G};无法确认 Session 已停止,未执行删群`}}let H;try{let W=await $.disbandChatForSessionExact(Y,X);H=cX(Y,X,W)}catch(W){let G=q0(W);return $.log(`temp-session: disband "${Y}" failed: ${G}`),{ok:!1,error:`${G};临时群/session 仍保留`}}try{return $.registry.delete(H),z?.dispose(),$.clearSessionConversationState(Y),{ok:!0}}catch(W){let G=q0(W);return $.log(`temp-session: local cleanup after disband "${Y}" failed: ${G}`),{ok:!1,error:`临时群已确认解散,但本地状态清理失败: ${G}`}}}}}var pX=E(()=>{D1()});var EF={};import*as Q2 from"@larksuiteoapi/node-sdk";import{chmodSync as JF,existsSync as X3,mkdirSync as QF,readFileSync as YF,unlinkSync as _Z,writeFileSync as VF}from"node:fs";import{dirname as XF}from"node:path";function Y2($,Z){if(X1=Math.max(X1,Z),KZ)return KZ;H3=!0,G8.close(),z3=W3();try{C2(z3)}catch(J){K(`shutdown alive marker write failed: ${J}`),X1=1}return KZ=(async()=>{K(`${$}: staged shutdown begin sessions=${K8.size}`);try{let J=(async()=>{return await IX(()=>[...G8.pending(),...nX]),await Promise.allSettled([...[...K8.values()].map((X)=>X.stop(`daemon ${$}`,{announce:!1})),SX()])})(),Q=null,Y=new Promise((X)=>{Q=setTimeout(()=>X("deadline"),iX)}),V=await Promise.race([J.then((X)=>{for(let z of X)if(z.status==="rejected")X1=1,K(`shutdown session stop failed: ${z.reason}`);return"stopped"}),Y]);if(Q)clearTimeout(Q);if(V==="deadline")X1=1,K(`${$}: shutdown deadline ${iX}ms reached; forcing exit`);else K(`${$}: all sessions stopped`)}catch(J){K(`${$}: staged shutdown failed: ${J}`),X1=1}finally{dX(),process.exit(X1)}})(),KZ}function rX($){return fX(nX,$)}function oX($,Z="ws"){if(H3)return K(`${Z}: reject inbound message: daemon shutdown in progress`),!1;let J=String($?.message?.chat_id??""),Q=HF.accept($);if(!Q.accepted)return K(`${Z}: reject inbound message${J?"":" without chat_id"}: actor ${Q.reason}`),!1;return Q.completion.catch((Y)=>{K(`${Z}: handleMessage rejected chat=${J.slice(0,8)}…: ${Y}`)}),!0}function W3(){let $=new Set;for(let Z of K8.values())if(Z.shouldRevive())$.add(Z.sessionName);for(let Z of W8)$.add(Z);return[...$]}function GZ(){C2(W3())}function aX($,Z){return K3.sessionFor($,Z)}async function WF($){return await K3.createTempSession($)}async function KF($,Z){return await K3.disbandTempSession($,Z)}async function GF(){let $=[...new Set(r6())];if($.length===0)return;W8=new Set($),K(`revive: ${$.length} session(s) marked alive on shutdown: ${$.join(", ")}`);try{await Promise.all($.map(async(Z)=>{let J=y1(Z);if(!J){K(`revive: no chatId binding for "${Z}", skip`),W8.delete(Z),GZ();return}let Q=aX(J,Z);try{if(await Q.restart(!0))K(`revive: spawned "${Z}" (chat ${J.slice(0,8)}…)`);else K(`revive: "${Z}" did not start`)}catch(Y){K(`revive: restart "${Z}" failed: ${Y}`)}finally{W8.delete(Z),GZ()}}))}finally{W8.clear(),GZ()}}function _F($){let Z=[],J=[],Q=[],Y=typeof $?.title==="string"?$.title.trim():"";if(Y)Q.push(`# ${Y}`);let V=Array.isArray($?.content)?$.content:[];for(let X of V){if(!Array.isArray(X))continue;let z=[];for(let W of X){if(!W||typeof W!=="object")continue;switch(W.tag){case"text":{let G=String(W.text??""),_=Array.isArray(W.style)?W.style:[];if(_.includes("bold"))G=`**${G}**`;if(_.includes("italic"))G=`*${G}*`;if(_.includes("lineThrough")||_.includes("strikethrough"))G=`~~${G}~~`;z.push(G);break}case"a":{let G=String(W.href??""),_=String(W.text??G);z.push(`[${_}](${G})`);break}case"at":{let G=String(W.user_name??W.user_id??"");z.push(`@${G}`);break}case"code_inline":z.push(`\`${String(W.text??"")}\``);break;case"hr":z.push("---");break;case"img":if(W.image_key)Z.push(String(W.image_key));break;case"media":if(W.file_key)J.push({key:String(W.file_key),name:W.file_name});break;case"emotion":break;default:if(typeof W.text==="string")z.push(W.text)}}let H=z.join("");if(H.trim())Q.push(H)}return{markdown:Q.join(`
|
|
397
|
-
|
|
398
|
-
`),imageKeys:Z,fileKeys:J}}async function BF($,Z=Date.now()){let J=$?.message;if(!J)return;let Y=($?.sender?.sender_id??$?.event?.sender?.sender_id??J?.sender?.sender_id)?.open_id??"",V=J.message_id;if(V&&J2.has(V))return;if(V){if(J2.add(V),J2.size>200){let M=[...J2];J2.clear();for(let O of M.slice(-100))J2.add(O)}}let X=Number(J.create_time??0);if(vX(X,Z,qF)){if(K(`drop stale message ${V} ageAtReceipt=${Math.round((Z-X)/1000)}s`),V)P$(V,"CrossMark");return}let z=J.chat_id,H={};try{H=JSON.parse(J.content??"{}")}catch{}let W=J.message_type==="text"?H.text??"":"";if(typeof W==="string"&&W.startsWith("[DEBUG]")){try{VF(L8,JSON.stringify({chat_id:z,sender_open_id:Y,seeded_at:new Date().toISOString(),seeded_msg_id:V??""},null,2)),K(`debug: seeded inject context chat=${z.slice(0,8)}… sender=${Y.slice(0,8)}…`)}catch(O){K(`debug: seed context failed: ${O}`)}let M=W.slice(7);H.text=M,J.content=JSON.stringify(H)}let G=Z$.get(z);if(!G)await N2(),G=Z$.get(z);if(!G)G=await e6(z)??void 0;if(!G){K(`unknown chat ${z}, dropping message`),await A(z,"❌ 无法识别群名。请确认:① 机器人已被拉进本群;② 群已设置名称(未命名群拿不到群名,无法映射项目目录)。设置后再发一条消息即可。");return}let _=k2(G);E1(_,z);let B=aX(z,_),L={};try{L=JSON.parse(J.content??"{}")}catch{}let F=J.message_type,D="",j=[];if(F==="text")D=(L.text??"").trim();else if(F==="post"){let M=_F(L);D=M.markdown.trim();for(let O of M.imageKeys){let P=await C1(J.message_id,O,"image");if(P)j.push(P)}for(let O of M.fileKeys){let P=await C1(J.message_id,O.key,"file",O.name);if(P)j.push(P)}}if(F==="text"&&D){if(await B.runCommand(D,Y))return}if(F==="text"&&D&&await B.consumeModelCustomMessage(D,Y))return;if(F==="text"&&D&&B.hasPendingAsk()){await B.onAskMessageAnswer(D,Y,V??"");return}if(F==="image"&&L.image_key){let M=await C1(J.message_id,L.image_key,"image");if(M)j.push(M)}else if(F==="file"&&L.file_key){let M=await C1(J.message_id,L.file_key,"file",L.file_name);if(M)j.push(M);if(!D)D=`(file: ${L.file_name})`}if(!D&&j.length===0){K(`drop empty message ${V} type=${F}`);return}if(await B.onMultiMessageInbound(D,j,Y,V??""))return;await B.onUserMessage(D||"(empty)",j,Y,V??"")}function qZ($){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:"启用账号",agy_forward_codex:"agy 结果转交",notify_callback:"通知反馈"}[$]??$}function LF($){return $?.card?.type==="raw"&&$.card.data&&typeof $.card.data==="object"?$.card.data:null}function t($,Z,J){return{...$,__businessOk:Z,...J?{__businessMessage:J}:{}}}function z1($,Z){return{...Z,__cardActionMessageId:$.messageId,__cardActionChatId:$.chatId}}function H8($){return t($.card?w$($.card):{toast:{type:$.ok?"success":"error",content:$.message}},$.ok)}async function H1($,Z){if(!$){K(`card-action: cannot send receipt without chat_id: ${Z}`);return}if(!await C($,Z))K(`card-action: visible receipt MISS chat=${$.slice(0,8)}… text=${Z.slice(0,120)}`)}async function FF($,Z){let J=String($?.action?.value?.kind??"unknown"),Q=qZ(J),Y=String(Z?.__cardActionChatId??$?.__cardActionChatId??$?.context?.open_chat_id??""),V=String(Z?.__cardActionMessageId??$?.context?.open_message_id??""),X=LF(Z),z=Z?.__businessOk===!1&&typeof Z?.__businessMessage==="string"?` 业务失败: ${Z.__businessMessage.replace(/\s+/g," ").trim().slice(0,300)}。`:"";if(X&&V)try{await z0(V,X);return}catch(L){K(`card-action: ${J} original-card update failed: ${L instanceof Error?L.message:L}`),await H1(Y,`⚠️ ${Q}已处理,但原卡更新失败。${z}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":"请重新打开操作面板。"}`);return}if(X){await H1(Y,`⚠️ ${Q}已处理,但回调缺少原卡 message_id,无法更新。${z}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":""}`);return}if(J==="notify_callback"&&Z?.__cardActionCompletion)return;let H=Z?.toast,W=typeof H?.content==="string"&&H.content.trim()?H.content.trim():`${Q}已完成`,G=J==="permission"&&String($?.action?.value?.decision??"")==="deny",_=Z?.__businessOk===!1||H?.type==="error"&&!G;if(!_&&new Set(["permission","ask","token_source_enable","agy_forward_codex"]).has(J))return;await H1(Y,`${_?"❌":"✅"} ${Q}: ${W}`)}async function DF($,Z){let J=String($?.action?.value?.kind??"unknown"),Q=Z instanceof Error?Z.message:String(Z);await H1(String($?.__cardActionChatId??$?.context?.open_chat_id??""),`❌ ${qZ(J)}失败: ${Q}`)}function PF($){return UF.accept($)}async function AF($){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 MF(J,Q,Y);let V=K8.get(Q);if(!V)return t({toast:{type:"error",content:"会话不存在,请先发消息启动"}},!1);switch(J.kind){case"permission":{let X=String(J.decision??"");if(!["allow","allow_always","deny"].includes(X))return{toast:{type:"error",content:"无效的权限决定"}};let z=await V.onPermissionDecision(J.request_id,X,Y);return t({toast:{type:z.ok?X==="deny"?"error":"success":"error",content:z.message}},z.ok)}case"menu":{let X=Number(J.choice??-1);try{if(!Number.isInteger(X)||X<0)throw Error("无效的菜单选项");return await V.onUserMessage(`(menu choice ${X+1})`),t(w$(h1({title:"\uD83D\uDCCB 菜单选择",message:`已选择第 ${X+1} 项`,ok:!0})),!0)}catch(z){let H=z instanceof Error?z.message:String(z);return t(w$(h1({title:"\uD83D\uDCCB 菜单选择",message:H,ok:!1})),!1)}}case"provider_select":{let X=await V.onProviderSelect(String(J.source_id??""),String(J.panel_id??""));return H8(X)}case"model_select":{let X=await V.onModelSelect(String(J.model??""),String(J.panel_id??""),Y,J);return H8(X)}case"model_custom_prompt":{let X=await V.onModelCustomPrompt(String(J.source_id??""),String(J.panel_id??""),String($?.context?.open_message_id??""));return H8(X)}case"model_panel_cancel":{let X=await V.onModelPanelCancel(String(J.panel_id??""));return H8(X)}case"model_effort_select":{let X=await V.onModelEffortSelect(String(J.model??""),String(J.effort??""),String(J.panel_id??""),Y,String(J.provider??""));return H8(X)}case"ask":{if(J.custom){let H=(Z?.form_value??Z?.input??{})?.custom_answer??Z?.input_value??"",W=await V.onAskCustomAnswer(J.tool_use_id,J.question_idx??0,H,Y);return t({toast:{type:W?"success":"error",content:W?"已回答":H.trim()?"问题已失效或答案未被接受":"请输入答案"}},W)}let X=await V.onAskAnswer(J.tool_use_id,J.question_idx??0,J.option_idx,Y);return t({toast:{type:X?"success":"error",content:X?"已回答":"问题已失效或选项无效"}},X)}case"worktree_disband":{let X=await V.onWorktreeDisband(String(J.slug??""));return t(w$(X.card),X.ok)}case"temp_fork_select":{let X=await V.onForkSelect(String(J.panel_id??""),String(J.choice_id??""),Y);return t(X.replaceCard===!1?{toast:{type:"error",content:X.message}}:w$(h1({title:"\uD83D\uDD31 会话分叉",message:X.message,ok:X.ok})),X.ok)}case"temp_back_select":{let X=await V.onBackSelect(String(J.panel_id??""),String(J.choice_id??""),Y);return t(X.replaceCard===!1?{toast:{type:"error",content:X.message}}:w$(h1({title:"⏪ 会话回滚",message:X.message,ok:X.ok})),X.ok)}case"temp_resume_select":{let X=await V.onResumeSelect(String(J.panel_id??""),String(J.choice_id??""),Y);if(X.replaceCard===!1)return t({toast:{type:"error",content:X.message}},X.ok);if(!X.resumePresentation)throw Error("rs selection result missing trusted presentation snapshot");return t(w$(h9({...X.resumePresentation,message:X.message,ok:X.ok})),X.ok,X.message)}case"tasklist_enable":{let X=await V.onTasklistEnable();return t(w$(X.card),X.ok)}case"tasklist_delete_prompt":{let X=V.onTasklistDeletePrompt(String(J.guid??""));return t(w$(X.card),X.ok)}case"tasklist_delete_confirm":{let X=await V.onTasklistDeleteConfirm(String(J.guid??""));return t(w$(X.card),X.ok)}case"token_source_enable":{let{onTokenSourceEnable:X}=await Promise.resolve().then(() => (R5(),O5));return await X(V,String(J.source_id??"")),{toast:{type:"info",content:"已处理"}}}case"agy_forward_codex":{let X=V.beginAgyForwardToCodex(String(J.result_id??""),Y);return t({toast:{type:X.ok?"success":"error",content:X.message}},X.ok)}}return{toast:{type:"info",content:"unknown action"}}}async function MF($,Z,J){let Q=String($?.notify_id??""),Y=String($?.button_id??"");if(!Q)return{toast:{type:"error",content:"回调缺少 notify_id"}};let V=$Z(Q);if(!V)return K(`notify-callback: notify_id=${Q.slice(0,12)}… not found (expired or pre-restart)`),{toast:{type:"error",content:"通知已过期或已移除"}};if(V.unknownAt)return z1(V,t({toast:{type:"error",content:`外部回调可能已成功,但本地确认状态未知,已禁止自动重试${V.unknownReason?`: ${V.unknownReason}`:""}`}},!0));if(V.resolvedAt)return z1(V,{toast:{type:"info",content:"已处理过"}});if(ZX(Q))return z1(V,{toast:{type:"info",content:"处理中…"}});let X=V.buttons.find((W)=>W.id===Y);if(!X)return K(`notify-callback: notify_id=${Q.slice(0,12)}… unknown button_id="${Y}"`),z1(V,t({toast:{type:"error",content:"未知按钮"}},!1));if(!V.callbackUrl){try{h5(V.notifyId,X.id,J)}catch(W){return z1(V,t({toast:{type:"error",content:`保存反馈结果失败: ${W instanceof Error?W.message:W}`}},!1))}return K(`notify-callback: notify_id=${Q.slice(0,12)}… resolved button="${Y}" by=${J.slice(0,8)}… (no callback, pull/display)`),z1(V,{...w$(ZZ(V,{status:"done",buttonId:X.id,text:X.text,operatorOpenId:J}))})}JX(V.notifyId);let z=rX(OF(V,X,J));z.catch((W)=>{K(`notify-callback: notify_id=${V.notifyId.slice(0,12)}… phase-2 rejected: ${W instanceof Error?W.message:W}`)});let H=z.then((W)=>W==="retry"?"retry":"complete").catch(()=>"retry");return z1(V,{toast:{type:"info",content:`⏳ 已选择:${X.text} · 推送中…`},__cardActionCompletion:H})}async function OF($,Z,J){try{let Q=ZZ($,{status:"processing",buttonId:Z.id,text:Z.text,operatorOpenId:J});try{await z0($.messageId,Q)}catch(z){K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-1 (processing) updateCard failed: ${z instanceof Error?z.message:z}`)}let Y=await zX($,Z,J),V=Y.ok?"complete":"retry",X;if(Y.ok){let z=XX($.notifyId,Z.id,J);if(z.state==="complete")X={status:"delivered",buttonId:Z.id,text:Z.text,operatorOpenId:J,reply:Y.reply};else{V="unknown",X={status:"unknown",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:z.detail},K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… callback succeeded but tombstone is UNKNOWN: ${z.detail}`);try{await H1($.chatId,`⚠️ 通知反馈的外部回调已成功,但本地确认状态未知;为避免重复副作用,已禁止自动重试。${z.detail}`)}catch(H){K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… UNKNOWN warning receipt failed: ${H instanceof Error?H.message:H}`)}}}else X={status:"failed",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:Y.detail};try{let z=ZZ($,X);await z0($.messageId,z)}catch(z){K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-2 (final) presentation failed: ${z instanceof Error?z.message:z}`);try{await H1($.chatId,`⚠️ 通知反馈${V==="retry"?"失败且结果卡更新失败,可重新点击":"已执行,但结果卡更新失败"}: ${z instanceof Error?z.message:z}`)}catch(H){K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… final fallback receipt failed: ${H instanceof Error?H.message:H}`)}}return K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… button="${Z.id}" ${V==="complete"?"delivered":V==="unknown"?"unknown/non-retryable":`failed: ${Y.detail}`} by=${J.slice(0,8)}…`),V}finally{QX($.notifyId)}}function V3($){return $.map((Z)=>typeof Z==="string"?Z:JSON.stringify(Z)).join(" ")}function RF(){if(process.platform==="win32"){K("debug: inject socket skipped on Windows (dev-only feature)");return}if(typeof Bun>"u"){K("debug: inject socket skipped (Bun runtime only — npm/Node build does not include it)");return}try{if(X3(y0))_Z(y0)}catch{}try{Bun.serve({unix:y0,fetch:async($)=>{if($.method!=="POST")return new Response("use POST",{status:405});if(H3)return new Response("daemon shutdown in progress",{status:503});let Z={};try{Z=await $.json()}catch{return new Response("bad json",{status:400})}if(!X3(L8))return new Response("no debug context yet — send `[DEBUG]hi` from Feishu first",{status:412});let J={};try{J=JSON.parse(YF(L8,"utf8"))}catch(z){return new Response(`ctx read failed: ${z}`,{status:500})}let Q=String(Z.text??"");if(!Q)return new Response("text required",{status:400});let Y=`【自动化测试】:${Q}`,V=await A(J.chat_id,Y);if(!V)return new Response("sendText failed — see daemon log",{status:502});let X={sender:{sender_id:{open_id:J.sender_open_id}},message:{message_id:V,chat_id:J.chat_id,message_type:"text",content:JSON.stringify({text:Q}),create_time:String(Date.now())}};if(K(`debug: inject text=${JSON.stringify(Q).slice(0,80)} msg_id=${V}`),!oX(X,"debug"))return new Response("daemon shutdown in progress",{status:503});return new Response(JSON.stringify({ok:!0,msg_id:V}),{headers:{"content-type":"application/json"}})}});try{JF(y0,384)}catch{}K(`debug: inject socket listening at ${y0}`)}catch($){K(`debug: socket bind failed: ${$}`)}}async function jF(){K(`lodestar-daemon: pid ${process.pid} starting`);let{buildTokenSourcesFromConfig:$}=await Promise.resolve().then(() => (A5(),iY));$();let{refreshAllTokenSourceModels:Z}=await Promise.resolve().then(() => (x$(),G7));Z(),w6(),f6(),I6(),m6(),p6(),await N2(),setInterval(()=>{N2()},1800000),NX();let J,Q=Date.now(),Y=0,V=!1,X=null,z=1500,H=90000,W=600000,G=3,_=null,B=0,L="",F=!1,D=(x)=>{K(`[ws] rebuild requested before WS init — ${x}`)},j=(x,k=0,s=!1)=>{let R$=Date.now()+k;if(_){if(F||=s,R$>=B){K(`[ws] rebuild already scheduled — ${x}`);return}clearTimeout(_)}B=R$,L=x,F=s,_=setTimeout(()=>{let W1=L,K1=F;_=null,B=0,L="",F=!1,D(W1,K1)},k)},M={error:(x)=>K(`[ws-sdk error] ${V3(x)}`),warn:(x)=>{let k=V3(x);if(K(`[ws-sdk warn] ${k}`),k.includes("no pong/inbound"))j("ping-timeout: SDK liveness watchdog fired",2000,Date.now()-Q<W)},info:(x)=>K(`[ws-sdk] ${V3(x)}`),debug:(x)=>{},trace:(x)=>{}},O=new Q2.EventDispatcher({}),P=()=>{if(Q=Date.now(),Y=0,X)clearTimeout(X),X=null};O.register({"im.message.receive_v1":async(x)=>{if(P(),!oX(x))throw Error("daemon shutdown in progress")}}),O.register({"card.action.trigger":async(x)=>{return P(),PF(x)}});let y=()=>new Q2.WSClient({appId:f.feishu.app_id,appSecret:f.feishu.app_secret,loggerLevel:Q2.LoggerLevel.info,logger:M,wsConfig:{pingTimeout:60},handshakeTimeoutMs:1e4,onReconnecting:()=>K("[ws] reconnecting — WS lost, SDK is retrying"),onReconnected:()=>T(),onError:(x)=>D(`SDK onError: ${x?.message??x}`)});D=(x,k=!1)=>{if(V){K(`[ws] rebuild skipped (already rebuilding) — ${x}`);return}if(_)clearTimeout(_),_=null,B=0;V=!0,Y++,K(`[ws] rebuild #${Y} (fresh WSClient) — ${x}`);let s=J;try{s?.close({force:!0})}catch(R$){K(`[ws] rebuild: old close failed: ${R$}`)}if(J=y(),J.start({eventDispatcher:O}).catch((R$)=>{K(`[ws] rebuild start failed: ${R$}`),j(`fresh client start failed: ${R$}`,z,k)}),V=!1,k)m()};let m=()=>{if(X)clearTimeout(X);let x=Date.now();X=setTimeout(()=>{if(X=null,Q>=x){Y=0;return}if(Y>=G){K(`[ws] STILL deaf after ${G} fresh rebuilds — auto-heal exhausted, `+"leaving last client up (no process exit). Restart the configured service or run lodestar-stop && lodestar-daemon"),Y=0;return}D(`verify: no event ${Math.round((Date.now()-x)/1000)}s after rebuild`,!0)},H)},T=()=>{let x=Date.now()-Q<W;K("[ws] reconnected — swapping in a fresh WSClient (cluster-routing precaution; "+`recentlyActive=${x})`),Y=0,j("post-reconnect precaution",z,x)};J=y(),J.start({eventDispatcher:O}).catch((x)=>{K(`[ws] initial start failed: ${x}`),j(`initial start failed: ${x}`,z,!1)}),K(`lodestar-daemon: WS start requested, watching ${Z$.size} groups`);let w=15000,g=2,N=0;setInterval(()=>{let{state:x}=J.getConnectionStatus();if(x==="connected"){N=0;return}if(x==="failed"||x==="idle"){N=0,D(`watchdog: state=${x}`);return}if(N++,K(`[ws] watchdog: state=${x} (${N}/${g})`),N>=g)N=0,D(`watchdog: stuck in '${x}' ~${Math.round(w*g/1000)}s`)},w),RF(),YX(),GX({bind:f.notify.bind,port:f.notify.port}),BX(),await GF()}var lX=!1,H3=!1,KZ=null,X1=0,z3=null,iX=15000,dX=()=>{if(lX)return;lX=!0;try{let $=z3??W3();if(C2($),$.length>0)K(`alive marker: [${$.join(", ")}]`)}catch($){K(`alive marker write failed: ${$}`)}try{_Z(j$)}catch{}try{_Z(y0)}catch{}},K8,W8,G8,zF,nX,HF,K3,qF=30000,J2,UF;var tX=E(()=>{tV();d();c$();g5();m5();m5();LX();bX();E$();v();v$();OZ();mX();pX();{let $=F8(j$);if($.state==="exit")console.error(`lodestar-daemon: already running (pid ${$.pid})`),process.exit(1);if(X3(j$))try{_Z(j$)}catch{}}QF(XF(j$),{recursive:!0});D3(j$);process.on("exit",dX);process.on("SIGTERM",()=>{Y2("SIGTERM",0)});process.on("SIGINT",()=>{Y2("SIGINT",0)});if(process.platform==="win32")process.on("SIGBREAK",()=>{Y2("SIGBREAK",0)});process.on("unhandledRejection",($)=>{K(`unhandledRejection: ${$ instanceof Error?$.stack??$.message:$}`),Y2("unhandledRejection",1)});process.on("uncaughtException",($)=>{K(`uncaughtException: ${$.stack??$.message}`),Y2("uncaughtException",1)});K8=new Map,W8=new Set,G8=new Q3,zF=new Y3(30000),nX=new Set,HF=hX({actor:G8,key:($)=>String($?.message?.chat_id??""),execute:($,Z)=>BF($,Z)});K3=uX({registry:K8,createSession:($,Z)=>new J1($,Z,{onLifecycleChange:GZ,onCreateTempSession:WF,onDisbandTempSession:KF}),ensureChatForSession:a6,disbandChatForSessionExact:s6,chatIdForSession:y1,clearSessionConversationState:n6,registerTempSessionLease:b6,hasTempSessionLease:v6,replaceTurnAnchors:y$,runExclusive:($,Z)=>G8.enqueue($,Z),log:K});J2=new Set;UF=gX({actor:G8,deduper:zF,scope:($)=>String($?.context?.open_chat_id??"")||"__notify_global__",execute:AF,present:FF,presentExecutionFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");K(`handleCardAction ${J}: ${Z instanceof Error?Z.stack??Z.message:Z}`),await DF($,Z)},presentPresentationFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");K(`card-action presentation ${J}: ${Z instanceof Error?Z.message:Z}`),await H1(String($?.context?.open_chat_id??""),`⚠️ ${qZ(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:($)=>{rX($)},onBackgroundError:($)=>{K(`card-action background: ${$ instanceof Error?$.stack??$.message:$}`)},responses:{accepted:($)=>({toast:{type:"info",content:`⏳ ${qZ(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}})}});jF().catch(($)=>{K(`boot fatal: ${$}`),Y2("boot fatal",1)})});v$();OZ();import{existsSync as sX,unlinkSync as TF}from"node:fs";var p$={reset:"\x1B[0m",bold:"\x1B[1m",yellow:"\x1B[33m",green:"\x1B[32m",red:"\x1B[31m"};async function xF(){if(!sX(_$)){if(process.stdin.isTTY){console.log(),console.log(`${p$.bold}${p$.yellow}Lodestar: 未找到配置, 启动安装向导...${p$.reset}`);let{runSetup:Z}=await Promise.resolve().then(() => (T3(),E3));await Z();return}console.error(`${p$.red}Lodestar: 未找到配置 ${_$}${p$.reset}`),console.error(`请在交互式 cmd / PowerShell 里运行 ${p$.green}lodestar-setup${p$.reset} 完成首次配置 (或直接运行 ${p$.green}lodestar-daemon${p$.reset} 也会触发同一个向导)。`),process.exit(1)}let $=F8(j$);if($.state==="exit")console.error(`${p$.yellow}Lodestar: 已经有一个 daemon 在运行 (pid ${$.pid})${p$.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(` • 误判 / 已经死了: 手删 ${j$} 后再跑`),process.exit(1);if(sX(j$))try{TF(j$)}catch{}await Promise.resolve().then(() => (tX(),EF))}xF().catch(($)=>{console.error("lodestar fatal:",$?.message??$),process.exit(1)});
|
|
379
|
+
`)}`)}function LL($,Z){try{return d($,["show-ref","--verify","--quiet",`refs/heads/${Z}`]),!0}catch{return!1}}function FL($){let Z=new Map,J="";for(let Q of d($,["worktree","list","--porcelain"]).split(`
|
|
380
|
+
`)){if(Q.startsWith("worktree "))J=Q.slice(9);if(Q.startsWith("branch refs/heads/")&&J)Z.set(Q.slice(18),J)}return Z}function d($,Z){try{return zL("git",Z,{cwd:$,encoding:"utf8",stdio:["ignore","pipe","pipe"]})}catch(J){throw Error(PL(J))}}function FZ($,Z){let J=$.trim(),Q=Z.trim();if(!J)throw Error("base branch is required for local review ref");if(!Q)throw Error("head branch is required for local review ref");return`local:${J}..${Q}`}function UZ($){let Z=$.trim();if(!Z)throw Error("task guid is required for task artifact tag");return`${Z2}/${Z}`}function G8($){let Z=$.trim();if(!Z.startsWith("local:"))throw Error(`unsupported local review request: ${$}`);let J=Z.slice(6).trim();if(!J.includes(".."))throw Error(`unsupported local review diff: ${$}`);return J}function q8($){let Z=G8($),J=Z.lastIndexOf(".."),Q=Z.slice(J+2).trim();if(!Q)throw Error(`missing review head ref: ${$}`);return Q}function Q3($,Z){try{d($,["check-ref-format",`refs/tags/${Z}`])}catch{throw Error(`invalid task artifact tag: ${Z}`)}if(UL($,`refs/tags/${Z}`))throw Error(`task artifact tag already exists: ${Z}`)}function yX($,Z,J){Q3($,Z),d($,["tag",Z,J])}function UL($,Z){try{return d($,["rev-parse","--verify","--quiet",Z]),!0}catch{return!1}}function SX($,Z){let J;try{J=q8(Z)}catch(Q){return{ok:!1,error:DL(Q)}}try{return d($,["merge-base","--is-ancestor",J,"HEAD"]),{ok:!0}}catch{return{ok:!1,error:`${J} is not an ancestor of HEAD`}}}function DL($){return $ instanceof Error?$.message:String($)}function PL($){let Z=$,J=Buffer.isBuffer(Z?.stderr)?Z.stderr.toString("utf8"):String(Z?.stderr??""),Q=Buffer.isBuffer(Z?.stdout)?Z.stdout.toString("utf8"):String(Z?.stdout??"");return[$ instanceof Error?$.message:String($),Q.trim(),J.trim()].filter(Boolean).join(`
|
|
381
|
+
`)}var Z2="AI-AUTO",K8="AI-REVIEW";var Y3=()=>{};import{execFileSync as G3}from"node:child_process";import{spawn as AL}from"cross-spawn";import{createHash as ML,randomUUID as OL}from"node:crypto";import{existsSync as jL,readFileSync as mX}from"node:fs";import{StringDecoder as kX}from"node:string_decoder";function pX(){return process.env.LODESTAR_TASK_CODEX_MODEL??Y$("codex-sub")?.defaultModel??""}function q3(){let $=pX(),Z=process.env.LODESTAR_TASK_CODEX_EFFORT??"xhigh";return $?["-m",$,"-c",`model_reasoning_effort="${Z}"`]:[]}function lX($={}){if(_8||J2||Q2)return;Y2=!1,($.adoptPersistedRuns??fL)(),J2=setTimeout(()=>{J2=null,Q2=xL($.reconcileDeletions??kQ).catch((J)=>K(`tasklist-worker: startup failed: ${x$(J)}`)).finally(()=>{Q2=null})},$.bootDelayMs??RL),K(`tasklist-worker: scheduled every ${cX/1000}s`)}async function xL($){try{await $()}catch(Z){K(`tasklist-worker: deletion reconcile failed: ${x$(Z)}`)}if(Y2)return;if(await bX(),!Y2)_8=setInterval(()=>{bX()},cX)}async function bX(){if(Y2)return;if(X3){K("tasklist-worker: previous scan still running, skip");return}X3=!0;try{let $=e2().filter((J)=>!J.deleting);if($.length===0)return;let Z=wX%$.length;for(let{value:J,index:Q}of CL($,Z)){let Y=J.projectName;if(G1.has(Y))continue;if(G1.size>=TL)break;let V=yL(Y).catch((X)=>K(`tasklist-worker: ${Y} scan crashed: ${x$(X)}`)).finally(()=>{G1.delete(Y)});G1.set(Y,V),wX=(Q+1)%$.length}}catch($){K(`tasklist-worker: scan failed: ${x$($)}`)}finally{X3=!1}}function CL($,Z){if($.length===0)return[];let J=(Z%$.length+$.length)%$.length;return $.map((Q,Y)=>{let V=(J+Y)%$.length;return{value:$[V],index:V}})}function vX($,Z,J){return $===0&&Z===0&&!J}async function dX($=MZ){if(Y2=!0,J2)clearTimeout(J2),J2=null;if(_8)clearInterval(_8),_8=null;let Z=async(J)=>{let Q=new Set,Y=Date.now()+$;while(Date.now()<Y){gX();for(let V of T$.values()){if(Q.has(V))continue;Q.add(V),H3(V,J)}if(vX(T$.size,G1.size,!!Q2))return!0;await new Promise((V)=>setTimeout(V,50))}return gX(),vX(T$.size,G1.size,!!Q2)};if(await Z("SIGTERM"))return;if(await Z("SIGKILL"))return;throw Error(`${T$.size} tasklist process group(s), ${G1.size} project scan(s), startup=${Q2?"running":"idle"} did not settle during shutdown`)}function NL($){let Z=$.sections;return Boolean(Z&&Z.design&&Z.aiTodo&&Z.aiDoing&&Z.aiReview&&Z.done)}async function yL($){let Z=l0($);try{if(!jL(Z))throw Error(`project directory does not exist: ${Z}`);let J=E$($);if(!J)throw Error(`tasklist is not enabled for ${$}`);if(J.deleting){K(`tasklist-worker: skip ${$}; tasklist deletion is pending`);return}let Q=J,Y=J.worker?.lastSectionEnsureAt?Date.parse(J.worker.lastSectionEnsureAt):0;if(Date.now()-Y>EL||!NL(J))Q=await NQ($),A$($,(X)=>{X.worker??={},X.worker.lastSectionEnsureAt=new Date().toISOString()}),Q=E$($)??Q;if(await vL($,Q),Q=E$($)??Q,hL($)){K(`tasklist-worker: skip ${$}; recovered automation run is still alive`);return}let V=await SL(Q);if(bL($,V),await pL($,Z,Q,V.aiReview))return;if(await mL($,Z,Q,V.design))return;if(await cL($,Z,Q,V.aiTodo,V.aiDoing,V.aiReview))return;if(await uL($,Z,Q,V.aiDoing))return}catch(J){let Q=x$(J);K(`tasklist-worker: ${$} failed: ${Q}`),A$($,(Y)=>{Y.worker??={},Y.worker.lastScanAt=new Date().toISOString(),Y.worker.lastScanError=Q})}}async function SL($){let Z=$.sections??{},J=Z.aiTodo?await K0(Z.aiTodo,!1):[],Q=Z.aiDoing?await K0(Z.aiDoing,!1):[],Y=Z.aiReview?await K0(Z.aiReview):[],V=Z.done?await K0(Z.done):[],X=new Set([Z.aiTodo,Z.aiDoing,Z.aiReview,Z.done].filter((G)=>!!G)),H=kL(await x2($.guid)).filter((G)=>!X.has(G.guid)),W=await Promise.all(H.map((G)=>K0(G.guid,!1))),z=await g6($.guid,!1);return{design:wL(z,[J,Q,Y,V,...W]),aiTodo:J,aiDoing:Q,aiReview:Y,done:V}}function kL($){let Z=$8("design");return $.filter((J)=>!J.isDefault).filter((J)=>J.name!==Z)}function wL($,Z){let J=new Set(Z.flat().map((Q)=>Q.guid));return $.filter((Q)=>!J.has(Q.guid))}function bL($,Z){A$($,(J)=>{let Q=new Date().toISOString();J.worker??={},J.worker.lastScanAt=Q,J.worker.lastScanError=void 0;for(let[Y,V]of Object.entries(Z))for(let X of V){let H=h$(J,X.guid);H.summary=X.summary,H.sectionKey=Y,H.completedAt=X.completedAt,H.lastSeenAt=Q}})}async function vL($,Z){let J=Object.values(Z.processes??{}).filter((Q)=>Q.status==="running");for(let Q of J){if(_3(Q)){iX(Q);continue}let Y="",V=T$.get(Q.runId);if(V?.source==="recovered"&&V.pgid&&b0(V.pgid))try{await nX(V.pgid)}catch(H){Y=`; recovered process-group cleanup failed: ${x$(H)}`}if(!V?.pgid||!b0(V.pgid))T$.delete(Q.runId);let X=`recorded ${Q.kind} process is no longer running (pid ${Q.pid??"unknown"})${Y}`;if(K(`tasklist-worker: mark stale process failed project=${$} run=${Q.runId}: ${X}`),K3($,Q,X),Q.taskGuid)try{await g$($,Q.taskGuid,`自动化进程已丢失:${X}`)}catch(H){K(`tasklist-worker: stale process comment failed run=${Q.runId}: ${x$(H)}`)}}}function fL(){if(process.platform==="win32"){let $=e2().flatMap((Z)=>Object.values(Z.processes??{})).filter((Z)=>Z.status==="running").length;if($>0)K(`tasklist-worker: ${$} recovered Windows run(s) cannot be adopted after restart without a Job Object; taskkill /T remains available only for leaders spawned by this daemon`);return}for(let $ of e2())for(let Z of Object.values($.processes??{}))if(Z.status==="running"&&_3(Z))iX(Z)}function iX($){if(process.platform==="win32"||$.status!=="running")return!1;if(T$.has($.runId))return!1;if(!_3($))return!1;if(!$.pid||!$.pgid||$.pgid<=0)return K(`tasklist-worker: cannot adopt recovered run=${$.runId}; missing pid/pgid`),!1;let Z=gL($.pid);if(Z!==$.pgid)return K(`tasklist-worker: cannot adopt recovered run=${$.runId}; persisted pgid=${$.pgid} actual=${Z??"MISS"}`),!1;return T$.set($.runId,{runId:$.runId,projectName:$.projectName,source:"recovered",proc:null,pid:$.pid,pgid:$.pgid,leaderFinished:!0}),K(`tasklist-worker: adopted recovered run=${$.runId} pid=${$.pid} pgid=${$.pgid}`),!0}function hL($){return[...T$.values()].some((Z)=>Z.source==="recovered"&&Z.projectName===$)}function _3($){if(!$.pid||$.pid<=0)return!1;let Z=IL($.pid);if(!Z)return!1;let J=$.command[0];if(!J)return!0;let Q=J.split(/[\\/]/).pop()??J;if(!(Z.includes(J)||Z.includes(Q)))return!1;return $.command.slice(1).filter((V)=>V&&V!=="<prompt>").every((V)=>Z.includes(V))}function IL($){try{if(process.platform==="linux")return mX(`/proc/${$}/cmdline`,"utf8").replace(/\0/g," ").trim();return G3("ps",["-p",String($),"-o","args="],{encoding:"utf8",timeout:2000}).trim()}catch{return null}}function gL($){try{if(process.platform==="linux"){let Z=mX(`/proc/${$}/stat`,"utf8"),J=Z.slice(Z.lastIndexOf(") ")+2).trim().split(/\s+/),Q=Number.parseInt(J[2]??"",10);return Number.isInteger(Q)&&Q>0?Q:null}if(process.platform!=="win32"){let Z=Number.parseInt(G3("ps",["-p",String($),"-o","pgid="],{encoding:"utf8",timeout:2000}).trim(),10);return Number.isInteger(Z)&&Z>0?Z:null}}catch{}return null}async function mL($,Z,J,Q){for(let Y of Q){let V=await B3(J,"design",Y.guid),X=ZF(V),H=X2($,Y.guid);if(H.codexPlan?.status==="running"||H.agyPlan?.status==="running")return!0;let W=H.codexPlan?.fingerprint===X&&!!H.codexPlan.status,z=H.agyPlan?.fingerprint===X&&!!H.agyPlan.status;if(W&&z)continue;if(!W){if((await dL($,Z,J,Y.guid,V,X)).status!=="exited")return!0}if(!z)await iL($,Z,J,Y.guid,V,X);return!0}return!1}async function cL($,Z,J,Q,Y,V){if(Y.length>0||V.length>0||Q.length===0)return!1;let X=e2().find((z)=>z.projectName===$)?.processes;if(X&&Object.values(X).some((z)=>z.status==="running"&&z.kind==="codex-execute"))return!0;let H=await nL($,Z,J,Q);if(!H)return!0;let W=J.sections?.aiDoing;if(!W)throw Error("missing [AI]执行中 section guid");return await N2(H,J.guid,W),A$($,(z)=>{let G=h$(z,H);G.sectionKey="aiDoing",G.codexExecution=void 0,G.agyReview=void 0,G.codexMerge=void 0,G.executionBranch=void 0,G.executionTag=void 0,G.reviewBranch=void 0,G.reviewRef=void 0,G.lastError=void 0,z.worker??={},z.worker.runningTaskGuid=H}),!0}async function uL($,Z,J,Q){if(Q.length===0)return!1;let Y=Q[0],V=X2($,Y.guid);if(V.codexExecution?.status==="running")return!0;if(V.codexExecution?.status==="failed")return!0;if(V.codexExecution?.status==="exited"){if(!PZ(V)){let H=UZ(Y.guid);try{let W=d(Z,["rev-parse",`${H}^`]).trim();if(!W)throw Error(`cannot resolve parent of ${H}`);A$($,(z)=>{let G=h$(z,Y.guid);G.executionBranch=Z2,G.executionTag=H,G.reviewBranch=K8,G.reviewRef=FZ(W,H)})}catch(W){let z=`Codex 执行进程已退出,但无法恢复本地审查请求:${x$(W)}`;return _1($,Y.guid,"codexExecution",V.codexExecution.runId,void 0,"failed",z),await g$($,Y.guid,z),!0}}return await fX($,Z,J,Y.guid)}if((await oL($,Z,J,Y.guid)).status!=="exited")return!0;return await fX($,Z,J,Y.guid)}async function fX($,Z,J,Q){let Y=X2($,Q);if(!PZ(Y))return!0;if(Y.agyReview?.status==="running")return!0;if(Y.agyReview?.status==="failed")return!0;if(Y.agyReview?.status!=="exited"){if((await rL($,Z,J,Q,W3(Y))).status!=="exited")return!0}let V=J.sections?.aiReview;if(!V)throw Error("missing [AI]待审核 section guid");return await N2(Q,J.guid,V),A$($,(X)=>{let H=h$(X,Q);H.sectionKey="aiReview",X.worker??={},X.worker.runningTaskGuid=void 0}),!0}async function pL($,Z,J,Q){for(let Y of Q){if(!lL(Y))continue;let V=X2($,Y.guid);if(V.codexMerge?.status==="running")return!0;if(V.codexMerge?.status==="exited"){if(!PZ(V))return _1($,Y.guid,"codexMerge",V.codexMerge.runId,void 0,"failed","Codex 合并进程已退出,但本地状态缺少审查请求。"),await g$($,Y.guid,"Codex 合并进程已退出,但本地状态缺少审查请求。"),!0;return await hX($,Z,J,Y.guid,W3(V))}if(V.codexMerge?.status==="failed")return!0;if(!PZ(V))return await g$($,Y.guid,"审核完成后无法合并:本地状态里没有本地审查请求。"),!0;let X=W3(V),H=await aL($,Z,J,Y.guid,X);if(H.status!=="exited")return!0;if(!String(H.stdoutTail??"").includes("LODESTAR_MERGE_STATUS: MERGED"))return await g$($,Y.guid,"Codex 合并进程未明确输出 `LODESTAR_MERGE_STATUS: MERGED`,任务保留在审核分组。"),!0;return await hX($,Z,J,Y.guid,X)}return!1}async function hX($,Z,J,Q,Y){let V=SX(Z,Y);if(V.ok===!1){let H=X2($,Q),W=`Codex 合并进程已退出,但本地 Git 未确认合并:${V.error}`;if(H.codexMerge)_1($,Q,"codexMerge",H.codexMerge.runId,void 0,"failed",W);return await g$($,Q,W),!0}let X=J.sections?.done;if(!X)throw Error("missing 已完成 section guid");return await N2(Q,J.guid,X),A$($,(H)=>{let W=h$(H,Q);W.sectionKey="done"}),!0}function lL($){return typeof $.completedAt==="string"&&$.completedAt.trim().length>0}async function dL($,Z,J,Q,Y,V){let X=[`你是 ${$} 项目的任务讨论者。`,"请结合项目实情,对这个需求做简单评审;不执行、不修改文件,可以帮着扩展想法。","如果任务中有明确的询问性质内容,必须认真回答。",`最终回答以 ${pX()||"codex"} 的身份输出,内容会直接发到飞书任务评论区。`,"","任务完整结构化数据:",B8(Y)].join(`
|
|
382
|
+
`),H=await V2({projectName:$,tasklistGuid:J.guid,taskGuid:Q,kind:"codex-plan",cwd:Z,command:[H0(),"exec",...q3(),"-s","read-only","-C",Z,X],timeoutMs:AZ,refKey:"codexPlan",fingerprint:V});if(H.status==="exited"&&H.exitCode===0){let W=await E0(Q,W2("Codex 规划",H.stdoutTail??""));L3($,Q,"codexPlan",W)}else await g$($,Q,`Codex 规划失败:${H2(H)}`);return{runId:H.runId,status:H.status,fingerprint:V,stdoutTail:H.stdoutTail}}async function iL($,Z,J,Q,Y,V){let X=[`你是 ${$} 项目的任务讨论者。`,"请结合项目实情,对这个需求做简单评审;不执行、不修改文件,可以帮着扩展想法。","如果任务中有明确的询问性质内容,必须认真回答。","最终回答以 gemini-3.1-pro 的身份输出,内容会直接发到飞书任务评论区。","","任务完整结构化数据:",B8(Y)].join(`
|
|
383
|
+
`),H=await V2({projectName:$,tasklistGuid:J.guid,taskGuid:Q,kind:"agy-plan",cwd:Z,command:[Y8(),...V8(X)],timeoutMs:AZ,refKey:"agyPlan",fingerprint:V});if(H.status==="exited"&&H.exitCode===0){let W=await E0(Q,W2("agy 看法",H.stdoutTail??""));L3($,Q,"agyPlan",W)}else await g$($,Q,`agy 规划失败:${H2(H)}`);return{runId:H.runId,status:H.status,fingerprint:V}}async function nL($,Z,J,Q){let Y=["你是 Lodestar 的任务调度 Agent。","从候选任务里选择最适合下一个自动执行的一个任务。",'只输出 JSON:{"task_guid":"...","reason":"..."},不要输出其他文字。',"",B8({projectName:$,tasks:Q})].join(`
|
|
384
|
+
`),V=await V2({projectName:$,tasklistGuid:J.guid,kind:"agy-pick",cwd:Z,command:[Y8(),...V8(Y)],timeoutMs:AZ});if(V.status!=="exited"||V.exitCode!==0)return K(`tasklist-worker: agy pick failed for ${$}: ${H2(V)}`),null;let X=YF(V.stdoutTail??"",Q.map((H)=>H.guid));if(!X)return A$($,(H)=>{H.worker??={},H.worker.lastScanError="agy pick did not return a valid task_guid"}),null;return _1($,X,"agyPick",V.runId,void 0,"exited"),X}async function oL($,Z,J,Q){let Y=UZ(Q);Q3(Z,Y);let V=d(Z,["branch","--show-current"]).trim();if(!V)throw Error("cannot determine base branch from project directory");let X=d(Z,["rev-parse","HEAD"]).trim(),H=await H1(Z,async()=>{return J3(Z,$,Z2,X)}),W=await B3(J,"aiDoing",Q),z=["你是 Lodestar 自动执行 Agent。","根据飞书任务完成代码实现,直接在当前仓库工作区修改文件。","完成后运行与改动风险匹配的验证。不要提交 git commit,不要操作 GitHub 或远端 PR。","worker 会在你完成后生成本地审查请求。","最终回复必须包含变更摘要和验证结果。","","任务完整结构化数据:",B8(W)].join(`
|
|
385
|
+
`),G=await V2({projectName:$,tasklistGuid:J.guid,taskGuid:Q,kind:"codex-execute",cwd:H,command:[H0(),"exec",...q3(),"--dangerously-bypass-approvals-and-sandbox","-C",H,z],timeoutMs:uX,refKey:"codexExecution"});if(G.status!=="exited"||G.exitCode!==0)return await g$($,Q,`Codex 执行失败:${H2(G)}`),G;try{if(!d(H,["status","--porcelain=v1"]).trim())return await g$($,Q,"Codex 执行完成但没有产生仓库变更,未生成本地审查请求。"),K3($,G,"Codex execution produced no repository changes");let B=await C2(Q),L=WF(B?.summary||Q);d(H,["add","-A"]),d(H,["commit","-m",L]);let F=d(H,["rev-parse","HEAD"]).trim();yX(H,Y,F),d(H,["reset","--hard",X]);let U=FZ(X,Y);A$($,(R)=>{let D=h$(R,Q);D.executionBranch=Z2,D.executionTag=Y,D.reviewBranch=K8,D.reviewRef=U});try{await E0(Q,W2("Codex 执行",[`任务产物:${Y}`,`Base:${V}@${X.slice(0,12)}`,`Diff:${X}..${Y}`,`提交:${F.slice(0,12)}`,"","输出摘要:",q1(G.stdoutTail??"",6000)].join(`
|
|
386
|
+
`)))}catch(R){let D=`Codex 执行评论写入失败:${x$(R)}`;K(`tasklist-worker: ${D}`),A$($,(P)=>{let M=h$(P,Q);M.lastError=D})}}catch(q){let B=x$(q);return await g$($,Q,`Codex 执行后生成本地审查请求失败:${B}`),K3($,G,B)}return G}async function rL($,Z,J,Q,Y){let V=await H1(Z,async()=>{return J3(Z,$,K8)}),X=await B3(J,"aiReview",Q),H=G8(Y),W=q8(Y),z=["你是 Lodestar 自动审核 Agent。",`请审核本地审查请求:${Y}`,`当前工作区在 ${K8},临时执行 worktree 分支是 ${Z2}。`,`任务产物 ref 是 ${W}。`,`重点查看 git diff ${H},输出可以直接发到飞书任务评论区的审核意见。`,"不要修改文件,不要合并,不要操作 GitHub 或远端 PR。","","任务完整结构化数据:",B8(X)].join(`
|
|
387
|
+
`),G=await V2({projectName:$,tasklistGuid:J.guid,taskGuid:Q,kind:"agy-review",cwd:V,command:[Y8(),...V8(z)],timeoutMs:AZ,refKey:"agyReview"});if(G.status==="exited"&&G.exitCode===0){let q=await E0(Q,W2("agy 审核",G.stdoutTail??""));L3($,Q,"agyReview",q)}else await g$($,Q,`agy 审核失败:${H2(G)}`);return G}async function aL($,Z,J,Q,Y){let V=G8(Y),X=q8(Y),H=["你是 Lodestar 自动合并 Agent。",`任务已由人工在飞书清单中勾选完成。请合并本地审查请求:${Y}`,`任务产物 ref 是 ${X}。`,`只使用本地 Git,把 ${X} 合并到当前主工作区所在分支。`,`合并前确认工作区干净,并查看 git diff ${V}。`,"不要使用 GitHub、gh CLI、远端 PR 或 push。","如发生冲突,按仓库约定解决并运行与风险匹配的验证。","如果确认已经合并,最终输出一行:LODESTAR_MERGE_STATUS: MERGED","如果不能合并,最终输出一行:LODESTAR_MERGE_STATUS: FAILED,并说明原因。"].join(`
|
|
388
|
+
`),W=await V2({projectName:$,tasklistGuid:J.guid,taskGuid:Q,kind:"codex-merge",cwd:Z,command:[H0(),"exec",...q3(),"--dangerously-bypass-approvals-and-sandbox","-C",Z,H],timeoutMs:uX,refKey:"codexMerge"}),z=W.status==="exited"&&W.exitCode===0?"Codex 合并":"Codex 合并失败";return await E0(Q,W2(z,W.stdoutTail||H2(W))),W}function tL($=process.platform){return $==="win32"?"Windows process-tree cleanup is best-effort: taskkill /T covers a live leader, but post-exit descendant verification requires a Job Object supervisor":null}async function V2($){if(Y2)throw Error(`tasklist worker is stopping; refusing to spawn ${$.kind}`);let Z=`${$.kind}-${Date.now()}-${OL().slice(0,8)}`,J=new Date().toISOString(),Q={runId:Z,projectName:$.projectName,tasklistGuid:$.tasklistGuid,taskGuid:$.taskGuid,kind:$.kind,command:VF($.command),cwd:$.cwd,status:"running",startedAt:J},Y=tL();if(Y)Q.treeCleanupWarning=Y,K(`tasklist-worker: run=${Z}: ${Y}`);let V=AL($.command[0],$.command.slice(1),{cwd:$.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,PATH:s4()},shell:!1,detached:process.platform!=="win32"});Q={...Q,pid:V.pid||void 0,pgid:process.platform!=="win32"?V.pid||void 0:void 0};let X={runId:Z,projectName:$.projectName,source:"spawned",proc:V,pid:Q.pid,pgid:Q.pgid,leaderFinished:!1};if(T$.set(Z,X),z3($.projectName,Q),$.taskGuid&&$.refKey)_1($.projectName,$.taskGuid,$.refKey,Z,$.fingerprint,"running");K(`tasklist-worker: spawned ${$.kind} run=${Z} pid=${Q.pid??"unknown"} cwd=${$.cwd}`);let H=new kX("utf8"),W=new kX("utf8"),z="",G="";V.stdout.on("data",(U)=>{z=q1(z+H.write(U),DZ)}),V.stderr.on("data",(U)=>{G=q1(G+W.write(U),DZ)});let q=await sL(X,$.timeoutMs);X.leaderFinished=!0;let B=await eL(X);if(!X.pgid||!b0(X.pgid))T$.delete(X.runId);z=q1(z+H.end(),DZ),G=q1(G+W.end(),DZ);let L=q.error||q.timedOut||q.exitCode!==0||B?"failed":"exited",F={...Q,status:L,finishedAt:new Date().toISOString(),exitCode:q.exitCode,signal:q.signal,stdoutTail:z.trimEnd(),stderrTail:G.trimEnd(),error:q.error??(q.timedOut?`${$.kind} timed out after ${$.timeoutMs/1000}s`:void 0)??B};if(z3($.projectName,F),$.taskGuid&&$.refKey)_1($.projectName,$.taskGuid,$.refKey,Z,$.fingerprint,L,F.error);return F}function sL($,Z){let J=$.proc;return new Promise((Q)=>{let Y=!1,V=!1,X=null,H=setTimeout(()=>{if(Y)return;V=!0,H3($,"SIGTERM"),X=setTimeout(()=>{if(!Y)H3($,"SIGKILL")},MZ)},Z);J.on("error",(W)=>{if(Y)return;if(Y=!0,clearTimeout(H),X)clearTimeout(X);Q({exitCode:null,signal:null,error:W.message})}),J.on("close",(W,z)=>{if(Y)return;if(Y=!0,clearTimeout(H),X)clearTimeout(X);Q({exitCode:W,signal:z,timedOut:V})})})}function H3($,Z){let J=$.proc;try{if(process.platform==="win32"&&$.pid)G3("taskkill",["/PID",String($.pid),"/T",...Z==="SIGKILL"?["/F"]:[]],{stdio:"ignore",timeout:MZ});else if($.pgid)process.kill(-$.pgid,Z);else if(J)J.kill(Z);else K(`tasklist-worker: cannot send ${Z} to recovered run=${$.runId}; no verified pgid`)}catch(Q){if(Q?.code!=="ESRCH")K(`tasklist-worker: ${Z} failed for run=${$.runId} pid=${$.pid??"unknown"} pgid=${$.pgid??"unknown"}: ${x$(Q)}`)}}function b0($){if(!Number.isInteger($)||$<=0)return!1;try{return process.kill(-$,0),!0}catch(Z){if(Z?.code==="ESRCH")return!1;if(Z?.code==="EPERM")return!0;throw Z}}async function IX($,Z){let J=Date.now()+Z;while(Date.now()<J){if(!b0($))return!0;await new Promise((Q)=>setTimeout(Q,25))}return!b0($)}async function nX($,Z=MZ){if(process.platform==="win32")throw Error("cannot verify a Windows process tree without a Job Object supervisor");if(!b0($))return;try{process.kill(-$,"SIGTERM")}catch(J){if(J?.code!=="ESRCH")throw J}if(await IX($,Z))return;try{process.kill(-$,"SIGKILL")}catch(J){if(J?.code!=="ESRCH")throw J}if(await IX($,Z))return;throw Error(`process group ${$} still exists after SIGTERM and SIGKILL`)}async function eL($){if(!$.pgid||!b0($.pgid))return;let Z=`automation leader exited while process group ${$.pgid} still had descendants`;try{return await nX($.pgid),`${Z}; descendants were terminated`}catch(J){return`${Z}; cleanup failed: ${x$(J)}`}}function gX(){for(let[$,Z]of T$){if(Z.source==="spawned"&&!Z.leaderFinished)continue;if(!Z.pgid||!b0(Z.pgid))T$.delete($)}}async function B3($,Z,J){let Q=await C2(J),Y=await c6(J),V=QF(X2($.projectName,J));return{project:{name:$.projectName,root:l0($.projectName)},tasklist:{guid:$.guid,name:$.name,url:$.url,section:$8(Z)},task:Q,comments:Y.filter((X)=>$F(X,V))}}function $F($,Z){if(Z.has($.id))return!1;let J=$.creator;if(!J||typeof J!=="object")return!1;return J.type==="user"}function ZF($){let Z=$?.task??{};return ML("sha256").update(JSON.stringify({summary:Z.summary,description:Z.description,due:Z.due,members:Z.members,comments:$?.comments??[]})).digest("hex")}function PZ($){return Boolean($.reviewRef||$.executionTag||$.executionBranch)}function W3($){if($.reviewRef)return $.reviewRef;if($.executionTag)return`local:HEAD..${$.executionTag}`;if($.executionBranch)return`local:HEAD..${$.executionBranch}`;throw Error("missing local review request")}function X2($,Z){let J=E$($);if(!J)throw Error(`tasklist is not enabled for ${$}`);return J.tasks?.[Z]??{guid:Z}}function A$($,Z){try{i1($,Z)}catch(J){K(`tasklist-worker: state update failed for ${$}: ${x$(J)}`)}}function z3($,Z){A$($,(J)=>{J.processes??={},J.processes[Z.runId]=Z})}function K3($,Z,J){let Q={...Z,status:"failed",error:J,finishedAt:Z.finishedAt??new Date().toISOString()};if(z3($,Q),Z.taskGuid){let Y=JF(Z.kind);if(Y)_1($,Z.taskGuid,Y,Z.runId,void 0,"failed",J)}return Q}function JF($){switch($){case"codex-plan":return"codexPlan";case"agy-plan":return"agyPlan";case"agy-pick":return"agyPick";case"codex-execute":return"codexExecution";case"agy-review":return"agyReview";case"codex-merge":return"codexMerge"}}function _1($,Z,J,Q,Y,V,X){A$($,(H)=>{let W=h$(H,Z);W[J]={...W[J],runId:Q,fingerprint:Y,status:V,...V==="running"?{startedAt:new Date().toISOString()}:{finishedAt:new Date().toISOString()},...X?{error:X}:{}}})}function L3($,Z,J,Q){A$($,(Y)=>{let X=h$(Y,Z)[J];if(X)X.commentId=Q})}async function g$($,Z,J){A$($,(Y)=>{let V=h$(Y,Z);V.lastError=J});let Q=await E0(Z,W2("Lodestar 自动化错误",J));A$($,(Y)=>{let V=h$(Y,Z);V.errorCommentIds=[...V.errorCommentIds??[],Q]})}function QF($){let Z=[$.codexPlan?.commentId,$.agyPlan?.commentId,$.codexExecution?.commentId,$.agyReview?.commentId,$.codexMerge?.commentId,...$.errorCommentIds??[]].filter((J)=>!!J);return new Set(Z)}function YF($,Z){try{let J=JSON.parse($.trim());if(typeof J.task_guid==="string"&&Z.includes(J.task_guid))return J.task_guid}catch{}return null}function H2($){return[$.error,`exit=${$.exitCode??"null"} signal=${$.signal??"null"} run=${$.runId} pid=${$.pid??"unknown"}`,$.stderrTail?`stderr:
|
|
389
|
+
${q1($.stderrTail,4000)}`:"",$.stdoutTail?`stdout:
|
|
390
|
+
${q1($.stdoutTail,4000)}`:""].filter(Boolean).join(`
|
|
391
|
+
`)}function VF($){if($.length<=1)return $;return[...$.slice(0,-1),$[$.length-1].length>240?"<prompt>":$[$.length-1]]}function W2($,Z){return[`### ${$}`,"",XF(Z||"(empty)")].join(`
|
|
392
|
+
`)}function XF($){let Z=HF($).trim();if(Z.length<=V3)return Z;return`${Z.slice(0,V3)}
|
|
393
|
+
|
|
394
|
+
[truncated ${Z.length-V3} chars]`}function HF($){return $.replace(/\[([^\]\n]+)\]\(((?!https?:\/\/|applink:\/\/)[^)]+)\)/g,"$1")}function WF($){return`AI-AUTO: ${($.replace(/\s+/g," ").trim()||"task").slice(0,80)}`}function B8($){return zF(JSON.stringify($,null,2),"json")}function zF($,Z=""){return"```"+Z+`
|
|
395
|
+
`+$.replace(/```/g,"`\\`\\`")+"\n```"}function q1($,Z){return $.length<=Z?$:$.slice($.length-Z)}function x$($){return $ instanceof Error?$.message:String($)}var cX=300000,RL=15000,EL=1800000,DZ=20000,V3=15000,TL=2,AZ=3600000,uX=10800000,MZ=5000,_8=null,J2=null,Q2=null,X3=!1,Y2=!1,G1,T$,wX=0;var oX=T(()=>{E5();E1();k$();n();v();m4();u5();Y3();Y3();G1=new Map,T$=new Map});function rX($,Z,J){return $>0&&Z-$>J}function aX($,Z){return $.add(Z),Z.then(()=>{$.delete(Z)},()=>{$.delete(Z)}),Z}async function tX($){while(!0){let Z=[...$()];if(Z.length===0)return;await Promise.allSettled(Z)}}function GF($){let Z=$?.action?.value??{},J=String(Z.kind??"");if(!J)return"无效操作";if(!KF.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 U3{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),V;return V=Y.then(()=>{},()=>{}).finally(()=>{if(this.tails.get(J)===V)this.tails.delete(J)}),this.tails.set(J,V),{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 sX($){let Z=$.now??Date.now;return{accept(J){let Q=Z();return $.actor.tryEnqueue($.key(J),()=>$.execute(J,Q))}}}class D3{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 F3($){if(Array.isArray($))return`[${$.map(F3).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)}:${F3(J)}`).join(",")}}`}function qF($){let Z=$?.action?.value??{},J=String(Z?.kind??"unknown"),Q=String($?.context?.open_chat_id??""),Y=String($?.context?.open_message_id??""),V=null;switch(J){case"menu":V={request_id:Z.request_id};break;case"permission":V={request_id:Z.request_id};break;case"ask":V={tool_use_id:Z.tool_use_id,question_idx:Z.question_idx};break;case"worktree_disband":V={slug:Z.slug};break;case"temp_fork_select":case"temp_back_select":case"temp_resume_select":V={panel_id:Z.panel_id};break;case"tasklist_delete_prompt":case"tasklist_delete_confirm":V={guid:Z.guid};break;case"tasklist_enable":V={guid:Z.guid,project:Z.project,panel_id:Z.panel_id};break;case"token_source_enable":V={source_id:Z.source_id};break;case"agy_forward_codex":V={result_id:Z.result_id};break;case"notify_callback":V={notify_id:Z.notify_id};break;case"provider_select":case"model_select":case"model_custom_prompt":case"model_panel_cancel":case"model_effort_select":V={panel_id:Z.panel_id};break;default:V=Z}return`${Q}\x00${Y}\x00${J}\x00${F3(V)}`}function _F($){let Z=String($?.event_id??$?.header?.event_id??$?.event?.event_id??"");return{...Z?{deliveryKey:`event\x00${Z}`}:{},businessKey:`semantic\x00${qF($)}`}}function BF(){return new Promise(($)=>setTimeout($,0))}function OZ($,Z,J){if(Z.deliveryKey)$.complete(Z.deliveryKey);if(J)$.complete(Z.businessKey);else $.fail(Z.businessKey)}function eX($){let Z=$.afterAck??BF,J=(Y)=>{try{$.onBackgroundError?.(Y)}catch{}},Q=async(Y)=>{try{await Y()}catch(V){J(V)}};return{accept(Y){if(!$.actor.isAccepting())return $.responses.closed(Y);let V=GF(Y);if(V)return $.responses.invalid(Y,V);let X=_F(Y),H=X.deliveryKey?[X.deliveryKey,X.businessKey]:[X.businessKey],W=$.deduper.claimAll(H);if(W==="inflight")return $.responses.inflight(Y);if(W==="completed")return $.responses.completed(Y);let z=$.actor.tryEnqueue($.scope(Y),async()=>{try{await Z()}catch(B){$.deduper.failAll(H),J(B);return}let G;try{G=await $.execute(Y)}catch(B){$.deduper.completeAll(H),await Q(()=>$.presentExecutionFailure(Y,B));return}await Q(async()=>{try{await $.present(Y,G)}catch(B){await $.presentPresentationFailure(Y,B)}});let q;try{q=$.completion(Y,G)}catch(B){OZ($.deduper,X,!1),J(B);return}if(q){let B=q.then((L)=>{OZ($.deduper,X,L==="complete")},(L)=>{OZ($.deduper,X,!1),J(L)});$.track(B);return}OZ($.deduper,X,$.businessSucceeded(Y,G))});if(!z.accepted)return $.deduper.failAll(H),$.responses.closed(Y);return $.track(z.completion),z.completion.catch(J),$.responses.accepted(Y)}}}var KF;var $H=T(()=>{KF=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","agy_forward_codex","notify_callback"])});function D0($){return $ instanceof Error?$.message:String($)}function ZH($,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 JH($){let Z=(Y,V)=>{let X=$.registry.get(Y);if(X&&X.sessionName!==V)throw Error(`chat ${Y} is already owned by session "${X.sessionName}", not "${V}"`);if(!X)X=$.createSession(V,Y),$.registry.set(Y,X);return X};return{sessionFor:Z,createTempSession:async(Y)=>{let V;try{if(K$(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(V=await $.ensureChatForSession(Y.chatName,Y.userOpenId),!V.created)return{ok:!1,chatId:V.chatId,error:"临时会话必须使用新群;既有群保留,未执行加入、启动或删除"}}catch(H){let W=D0(H);return $.log(`temp-session: create "${Y.chatName}" failed: ${W}`),{ok:!1,error:W}}let X=async()=>{let H=null;try{if($.registerTempSessionLease(Y.chatName,V.chatId),H=Z(V.chatId,Y.chatName),H.isRunning())return{ok:!1,error:`${Y.chatName} 已有会话在跑,先 bye 解散再重试`};if(H.workDir!==Y.workDir)throw Error(`临时群 cwd 不匹配: source=${Y.workDir} target=${H.workDir}`);if(H.applyConversationRouting(Y.routing),!(Y.launch.kind==="fork"?await H.startForked(Y.launch,{announce:!1}):await H.start({announce:!1})))throw Error(`${H.backendLabel()} 启动失败`);return $.replaceTurnAnchors(Y.chatName,Y.seedAnchors??[],Y.branchBase),{ok:!0,chatId:V.chatId}}catch(W){let z=D0(W);if($.log(`temp-session: initialize "${Y.chatName}" failed: ${z}`),H)try{await H.stop("临时群启动失败清理",{announce:!1})}catch(q){let B=D0(q);return $.log(`temp-session: failed-create stop "${Y.chatName}" failed: ${B}`),{ok:!1,chatId:V.chatId,error:`${z};无法确认 Session 已停止,临时群/session 仍保留: ${B}`}}if(!V.created)return{ok:!1,error:`${z};既有群保留,未执行删除`};let G;try{let q=await $.disbandChatForSessionExact(Y.chatName,V.chatId);G=ZH(Y.chatName,V.chatId,q)}catch(q){let B=D0(q);return $.log(`temp-session: create cleanup "${Y.chatName}" failed: ${B}`),{ok:!1,chatId:V.chatId,error:`${z};自动解散失败,临时群/session 仍保留: ${B}`}}try{$.registry.delete(G),H?.dispose(),$.clearSessionConversationState(Y.chatName)}catch(q){let B=D0(q);return $.log(`temp-session: local cleanup "${Y.chatName}" failed: ${B}`),{ok:!1,error:`${z};临时群已确认解散,但本地状态清理失败: ${B}`}}return{ok:!1,error:`${z};本次新建的临时群已确认解散`}}};try{return $.runExclusive?await $.runExclusive(V.chatId,X):await X()}catch(H){let W=D0(H);return $.log(`temp-session: target actor "${Y.chatName}" failed: ${W}`),{ok:!1,chatId:V.chatId,error:`${W};临时群/session 仍保留`}}},disbandTempSession:async(Y,V)=>{let X=$.chatIdForSession(Y);if(!V||X!==V){let z=`临时群 chat_id 已变化: expected=${V||"-"} bound=${X??"-"}`;return $.log(`temp-session: disband identity rejected "${Y}": ${z}`),{ok:!1,error:`${z};未执行停止或删群`}}if(!$.hasTempSessionLease(Y,V)){let z=`群 ${V} 没有 Lodestar 临时会话 lease,拒绝解散`;return $.log(`temp-session: disband lease rejected "${Y}": ${z}`),{ok:!1,error:`${z};未执行停止或删群`}}let H=$.registry.get(X);try{if(H)await H.stop("bye 解散",{announce:!1})}catch(z){let G=D0(z);return $.log(`temp-session: stop before disband "${Y}" failed: ${G}`),{ok:!1,error:`${G};无法确认 Session 已停止,未执行删群`}}let W;try{let z=await $.disbandChatForSessionExact(Y,X);W=ZH(Y,X,z)}catch(z){let G=D0(z);return $.log(`temp-session: disband "${Y}" failed: ${G}`),{ok:!1,error:`${G};临时群/session 仍保留`}}try{return $.registry.delete(W),H?.dispose(),$.clearSessionConversationState(Y),{ok:!0}}catch(z){let G=D0(z);return $.log(`temp-session: local cleanup after disband "${Y}" failed: ${G}`),{ok:!1,error:`临时群已确认解散,但本地状态清理失败: ${G}`}}}}}var QH=T(()=>{R1()});var IF={};import*as K2 from"@larksuiteoapi/node-sdk";import{chmodSync as LF,existsSync as A3,mkdirSync as FF,readFileSync as UF,unlinkSync as EZ,writeFileSync as DF}from"node:fs";import{dirname as PF}from"node:path";function G2($,Z){if(B1=Math.max(B1,Z),jZ)return jZ;O3=!0,D8.close(),M3=j3();try{v2(M3)}catch(J){K(`shutdown alive marker write failed: ${J}`),B1=1}return jZ=(async()=>{K(`${$}: staged shutdown begin sessions=${U8.size}`);try{let J=(async()=>{return await tX(()=>[...D8.pending(),...HH]),await Promise.allSettled([...[...U8.values()].map((X)=>X.stop(`daemon ${$}`,{announce:!1})),dX()])})(),Q=null,Y=new Promise((X)=>{Q=setTimeout(()=>X("deadline"),VH)}),V=await Promise.race([J.then((X)=>{for(let H of X)if(H.status==="rejected")B1=1,K(`shutdown session stop failed: ${H.reason}`);return"stopped"}),Y]);if(Q)clearTimeout(Q);if(V==="deadline")B1=1,K(`${$}: shutdown deadline ${VH}ms reached; forcing exit`);else K(`${$}: all sessions stopped`)}catch(J){K(`${$}: staged shutdown failed: ${J}`),B1=1}finally{XH(),process.exit(B1)}})(),jZ}function WH($){return aX(HH,$)}function zH($,Z="ws"){if(O3)return K(`${Z}: reject inbound message: daemon shutdown in progress`),!1;let J=String($?.message?.chat_id??""),Q=MF.accept($);if(!Q.accepted)return K(`${Z}: reject inbound message${J?"":" without chat_id"}: actor ${Q.reason}`),!1;return Q.completion.catch((Y)=>{K(`${Z}: handleMessage rejected chat=${J.slice(0,8)}…: ${Y}`)}),!0}function j3(){let $=new Set;for(let Z of U8.values())if(Z.shouldRevive())$.add(Z.sessionName);for(let Z of F8)$.add(Z);return[...$]}function RZ(){v2(j3())}function KH($,Z){return R3.sessionFor($,Z)}async function OF($){return await R3.createTempSession($)}async function jF($,Z){return await R3.disbandTempSession($,Z)}async function RF(){let $=[...new Set(H9())];if($.length===0)return;F8=new Set($),K(`revive: ${$.length} session(s) marked alive on shutdown: ${$.join(", ")}`);try{await Promise.all($.map(async(Z)=>{let J=f1(Z);if(!J){K(`revive: no chatId binding for "${Z}", skip`),F8.delete(Z),RZ();return}let Q=KH(J,Z);try{if(await Q.restart(!0))K(`revive: spawned "${Z}" (chat ${J.slice(0,8)}…)`);else K(`revive: "${Z}" did not start`)}catch(Y){K(`revive: restart "${Z}" failed: ${Y}`)}finally{F8.delete(Z),RZ()}}))}finally{F8.clear(),RZ()}}function EF($){let Z=[],J=[],Q=[],Y=typeof $?.title==="string"?$.title.trim():"";if(Y)Q.push(`# ${Y}`);let V=Array.isArray($?.content)?$.content:[];for(let X of V){if(!Array.isArray(X))continue;let H=[];for(let z of X){if(!z||typeof z!=="object")continue;switch(z.tag){case"text":{let G=String(z.text??""),q=Array.isArray(z.style)?z.style:[];if(q.includes("bold"))G=`**${G}**`;if(q.includes("italic"))G=`*${G}*`;if(q.includes("lineThrough")||q.includes("strikethrough"))G=`~~${G}~~`;H.push(G);break}case"a":{let G=String(z.href??""),q=String(z.text??G);H.push(`[${q}](${G})`);break}case"at":{let G=String(z.user_name??z.user_id??"");H.push(`@${G}`);break}case"code_inline":H.push(`\`${String(z.text??"")}\``);break;case"hr":H.push("---");break;case"img":if(z.image_key)Z.push(String(z.image_key));break;case"media":if(z.file_key)J.push({key:String(z.file_key),name:z.file_name});break;case"emotion":break;default:if(typeof z.text==="string")H.push(z.text)}}let W=H.join("");if(W.trim())Q.push(W)}return{markdown:Q.join(`
|
|
396
|
+
|
|
397
|
+
`),imageKeys:Z,fileKeys:J}}async function xF($,Z=Date.now()){let J=$?.message;if(!J)return;let Y=($?.sender?.sender_id??$?.event?.sender?.sender_id??J?.sender?.sender_id)?.open_id??"",V=J.message_id;if(V&&z2.has(V))return;if(V){if(z2.add(V),z2.size>200){let D=[...z2];z2.clear();for(let P of D.slice(-100))z2.add(P)}}let X=Number(J.create_time??0);if(rX(X,Z,TF)){if(K(`drop stale message ${V} ageAtReceipt=${Math.round((Z-X)/1000)}s`),V)R$(V,"CrossMark");return}let H=J.chat_id,W={};try{W=JSON.parse(J.content??"{}")}catch{}let z=J.message_type==="text"?W.text??"":"";if(typeof z==="string"&&z.startsWith("[DEBUG]")){try{DF(O8,JSON.stringify({chat_id:H,sender_open_id:Y,seeded_at:new Date().toISOString(),seeded_msg_id:V??""},null,2)),K(`debug: seeded inject context chat=${H.slice(0,8)}… sender=${Y.slice(0,8)}…`)}catch(P){K(`debug: seed context failed: ${P}`)}let D=z.slice(7);W.text=D,J.content=JSON.stringify(W)}let G=Z$.get(H);if(!G)await f2(),G=Z$.get(H);if(!G)G=await q9(H)??void 0;if(!G){K(`unknown chat ${H}, dropping message`),await E(H,"❌ 无法识别群名。请确认:① 机器人已被拉进本群;② 群已设置名称(未命名群拿不到群名,无法映射项目目录)。设置后再发一条消息即可。");return}let q=I2(G);k1(q,H);let B=KH(H,q),L={};try{L=JSON.parse(J.content??"{}")}catch{}let F=J.message_type,U="",R=[];if(F==="text")U=(L.text??"").trim();else if(F==="post"){let D=EF(L);U=D.markdown.trim();for(let P of D.imageKeys){let M=await h1(J.message_id,P,"image");if(M)R.push(M)}for(let P of D.fileKeys){let M=await h1(J.message_id,P.key,"file",P.name);if(M)R.push(M)}}if(F==="text"&&U){if(await B.runCommand(U,Y))return}if(F==="text"&&U&&await B.consumeModelCustomMessage(U,Y))return;if(F==="text"&&U&&B.hasPendingAsk()){await B.onAskMessageAnswer(U,Y,V??"");return}if(F==="image"&&L.image_key){let D=await h1(J.message_id,L.image_key,"image");if(D)R.push(D)}else if(F==="file"&&L.file_key){let D=await h1(J.message_id,L.file_key,"file",L.file_name);if(D)R.push(D);if(!U)U=`(file: ${L.file_name})`}if(!U&&R.length===0){K(`drop empty message ${V} type=${F}`);return}if(await B.onMultiMessageInbound(U,R,Y,V??""))return;await B.onUserMessage(U||"(empty)",R,Y,V??"")}function TZ($){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:"启用账号",agy_forward_codex:"agy 结果转交",notify_callback:"通知反馈"}[$]??$}function CF($){return $?.card?.type==="raw"&&$.card.data&&typeof $.card.data==="object"?$.card.data:null}function t($,Z,J){return{...$,__businessOk:Z,...J?{__businessMessage:J}:{}}}function L1($,Z){return{...Z,__cardActionMessageId:$.messageId,__cardActionChatId:$.chatId}}function L8($){return t($.card?I$($.card):{toast:{type:$.ok?"success":"error",content:$.message}},$.ok)}async function F1($,Z){if(!$){K(`card-action: cannot send receipt without chat_id: ${Z}`);return}if(!await C($,Z))K(`card-action: visible receipt MISS chat=${$.slice(0,8)}… text=${Z.slice(0,120)}`)}async function NF($,Z){let J=String($?.action?.value?.kind??"unknown"),Q=TZ(J),Y=String(Z?.__cardActionChatId??$?.__cardActionChatId??$?.context?.open_chat_id??""),V=String(Z?.__cardActionMessageId??$?.context?.open_message_id??""),X=CF(Z),H=Z?.__businessOk===!1&&typeof Z?.__businessMessage==="string"?` 业务失败: ${Z.__businessMessage.replace(/\s+/g," ").trim().slice(0,300)}。`:"";if(X&&V)try{await q0(V,X);return}catch(L){K(`card-action: ${J} original-card update failed: ${L instanceof Error?L.message:L}`),await F1(Y,`⚠️ ${Q}已处理,但原卡更新失败。${H}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":"请重新打开操作面板。"}`);return}if(X){await F1(Y,`⚠️ ${Q}已处理,但回调缺少原卡 message_id,无法更新。${H}${J==="temp_resume_select"?"请发送 rs 查看当前状态。":""}`);return}if(J==="notify_callback"&&Z?.__cardActionCompletion)return;let W=Z?.toast,z=typeof W?.content==="string"&&W.content.trim()?W.content.trim():`${Q}已完成`,G=J==="permission"&&String($?.action?.value?.decision??"")==="deny",q=Z?.__businessOk===!1||W?.type==="error"&&!G;if(!q&&new Set(["permission","ask","token_source_enable","agy_forward_codex"]).has(J))return;await F1(Y,`${q?"❌":"✅"} ${Q}: ${z}`)}async function yF($,Z){let J=String($?.action?.value?.kind??"unknown"),Q=Z instanceof Error?Z.message:String(Z);await F1(String($?.__cardActionChatId??$?.context?.open_chat_id??""),`❌ ${TZ(J)}失败: ${Q}`)}function kF($){return SF.accept($)}async function wF($){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 bF(J,Q,Y);let V=U8.get(Q);if(!V)return t({toast:{type:"error",content:"会话不存在,请先发消息启动"}},!1);switch(J.kind){case"permission":{let X=String(J.decision??"");if(!["allow","allow_always","deny"].includes(X))return{toast:{type:"error",content:"无效的权限决定"}};let H=await V.onPermissionDecision(J.request_id,X,Y);return t({toast:{type:H.ok?X==="deny"?"error":"success":"error",content:H.message}},H.ok)}case"menu":{let X=Number(J.choice??-1);try{if(!Number.isInteger(X)||X<0)throw Error("无效的菜单选项");return await V.onUserMessage(`(menu choice ${X+1})`),t(I$(d1({title:"\uD83D\uDCCB 菜单选择",message:`已选择第 ${X+1} 项`,ok:!0})),!0)}catch(H){let W=H instanceof Error?H.message:String(H);return t(I$(d1({title:"\uD83D\uDCCB 菜单选择",message:W,ok:!1})),!1)}}case"provider_select":{let X=await V.onProviderSelect(String(J.source_id??""),String(J.panel_id??""));return L8(X)}case"model_select":{let X=await V.onModelSelect(String(J.model??""),String(J.panel_id??""),Y,J);return L8(X)}case"model_custom_prompt":{let X=await V.onModelCustomPrompt(String(J.source_id??""),String(J.panel_id??""),String($?.context?.open_message_id??""));return L8(X)}case"model_panel_cancel":{let X=await V.onModelPanelCancel(String(J.panel_id??""));return L8(X)}case"model_effort_select":{let X=await V.onModelEffortSelect(String(J.model??""),String(J.effort??""),String(J.panel_id??""),Y,String(J.provider??""));return L8(X)}case"ask":{if(J.custom){let W=(Z?.form_value??Z?.input??{})?.custom_answer??Z?.input_value??"",z=await V.onAskCustomAnswer(J.tool_use_id,J.question_idx??0,W,Y);return t({toast:{type:z?"success":"error",content:z?"已回答":W.trim()?"问题已失效或答案未被接受":"请输入答案"}},z)}let X=await V.onAskAnswer(J.tool_use_id,J.question_idx??0,J.option_idx,Y);return t({toast:{type:X?"success":"error",content:X?"已回答":"问题已失效或选项无效"}},X)}case"worktree_disband":{let X=await V.onWorktreeDisband(String(J.slug??""));return t(I$(X.card),X.ok)}case"temp_fork_select":{let X=await V.onForkSelect(String(J.panel_id??""),String(J.choice_id??""),Y);return t(X.replaceCard===!1?{toast:{type:"error",content:X.message}}:I$(d1({title:"\uD83D\uDD31 会话分叉",message:X.message,ok:X.ok})),X.ok)}case"temp_back_select":{let X=await V.onBackSelect(String(J.panel_id??""),String(J.choice_id??""),Y);return t(X.replaceCard===!1?{toast:{type:"error",content:X.message}}:I$(d1({title:"⏪ 会话回滚",message:X.message,ok:X.ok})),X.ok)}case"temp_resume_select":{let X=await V.onResumeSelect(String(J.panel_id??""),String(J.choice_id??""),Y);if(X.replaceCard===!1)return t({toast:{type:"error",content:X.message}},X.ok);if(!X.resumePresentation)throw Error("rs selection result missing trusted presentation snapshot");return t(I$(t9({...X.resumePresentation,message:X.message,ok:X.ok})),X.ok,X.message)}case"tasklist_enable":{let X=await V.onTasklistEnable();return t(I$(X.card),X.ok)}case"tasklist_delete_prompt":{let X=V.onTasklistDeletePrompt(String(J.guid??""));return t(I$(X.card),X.ok)}case"tasklist_delete_confirm":{let X=await V.onTasklistDeleteConfirm(String(J.guid??""));return t(I$(X.card),X.ok)}case"token_source_enable":{let{onTokenSourceEnable:X}=await Promise.resolve().then(() => (f5(),v5));return await X(V,String(J.source_id??"")),{toast:{type:"info",content:"已处理"}}}case"agy_forward_codex":{let X=V.beginAgyForwardToCodex(String(J.result_id??""),Y);return t({toast:{type:X.ok?"success":"error",content:X.message}},X.ok)}}return{toast:{type:"info",content:"unknown action"}}}async function bF($,Z,J){let Q=String($?.notify_id??""),Y=String($?.button_id??"");if(!Q)return{toast:{type:"error",content:"回调缺少 notify_id"}};let V=_Z(Q);if(!V)return K(`notify-callback: notify_id=${Q.slice(0,12)}… not found (expired or pre-restart)`),{toast:{type:"error",content:"通知已过期或已移除"}};if(V.unknownAt)return L1(V,t({toast:{type:"error",content:`外部回调可能已成功,但本地确认状态未知,已禁止自动重试${V.unknownReason?`: ${V.unknownReason}`:""}`}},!0));if(V.resolvedAt)return L1(V,{toast:{type:"info",content:"已处理过"}});if(LX(Q))return L1(V,{toast:{type:"info",content:"处理中…"}});let X=V.buttons.find((z)=>z.id===Y);if(!X)return K(`notify-callback: notify_id=${Q.slice(0,12)}… unknown button_id="${Y}"`),L1(V,t({toast:{type:"error",content:"未知按钮"}},!1));if(!V.callbackUrl){try{s5(V.notifyId,X.id,J)}catch(z){return L1(V,t({toast:{type:"error",content:`保存反馈结果失败: ${z instanceof Error?z.message:z}`}},!1))}return K(`notify-callback: notify_id=${Q.slice(0,12)}… resolved button="${Y}" by=${J.slice(0,8)}… (no callback, pull/display)`),L1(V,{...I$(BZ(V,{status:"done",buttonId:X.id,text:X.text,operatorOpenId:J}))})}FX(V.notifyId);let H=WH(vF(V,X,J));H.catch((z)=>{K(`notify-callback: notify_id=${V.notifyId.slice(0,12)}… phase-2 rejected: ${z instanceof Error?z.message:z}`)});let W=H.then((z)=>z==="retry"?"retry":"complete").catch(()=>"retry");return L1(V,{toast:{type:"info",content:`⏳ 已选择:${X.text} · 推送中…`},__cardActionCompletion:W})}async function vF($,Z,J){try{let Q=BZ($,{status:"processing",buttonId:Z.id,text:Z.text,operatorOpenId:J});try{await q0($.messageId,Q)}catch(H){K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-1 (processing) updateCard failed: ${H instanceof Error?H.message:H}`)}let Y=await MX($,Z,J),V=Y.ok?"complete":"retry",X;if(Y.ok){let H=AX($.notifyId,Z.id,J);if(H.state==="complete")X={status:"delivered",buttonId:Z.id,text:Z.text,operatorOpenId:J,reply:Y.reply};else{V="unknown",X={status:"unknown",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:H.detail},K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… callback succeeded but tombstone is UNKNOWN: ${H.detail}`);try{await F1($.chatId,`⚠️ 通知反馈的外部回调已成功,但本地确认状态未知;为避免重复副作用,已禁止自动重试。${H.detail}`)}catch(W){K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… UNKNOWN warning receipt failed: ${W instanceof Error?W.message:W}`)}}}else X={status:"failed",buttonId:Z.id,text:Z.text,operatorOpenId:J,detail:Y.detail};try{let H=BZ($,X);await q0($.messageId,H)}catch(H){K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… phase-2 (final) presentation failed: ${H instanceof Error?H.message:H}`);try{await F1($.chatId,`⚠️ 通知反馈${V==="retry"?"失败且结果卡更新失败,可重新点击":"已执行,但结果卡更新失败"}: ${H instanceof Error?H.message:H}`)}catch(W){K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… final fallback receipt failed: ${W instanceof Error?W.message:W}`)}}return K(`notify-callback: notify_id=${$.notifyId.slice(0,12)}… button="${Z.id}" ${V==="complete"?"delivered":V==="unknown"?"unknown/non-retryable":`failed: ${Y.detail}`} by=${J.slice(0,8)}…`),V}finally{UX($.notifyId)}}function P3($){return $.map((Z)=>typeof Z==="string"?Z:JSON.stringify(Z)).join(" ")}function fF(){if(process.platform==="win32"){K("debug: inject socket skipped on Windows (dev-only feature)");return}if(typeof Bun>"u"){K("debug: inject socket skipped (Bun runtime only — npm/Node build does not include it)");return}try{if(A3(v0))EZ(v0)}catch{}try{Bun.serve({unix:v0,fetch:async($)=>{if($.method!=="POST")return new Response("use POST",{status:405});if(O3)return new Response("daemon shutdown in progress",{status:503});let Z={};try{Z=await $.json()}catch{return new Response("bad json",{status:400})}if(!A3(O8))return new Response("no debug context yet — send `[DEBUG]hi` from Feishu first",{status:412});let J={};try{J=JSON.parse(UF(O8,"utf8"))}catch(H){return new Response(`ctx read failed: ${H}`,{status:500})}let Q=String(Z.text??"");if(!Q)return new Response("text required",{status:400});let Y=`【自动化测试】:${Q}`,V=await E(J.chat_id,Y);if(!V)return new Response("sendText failed — see daemon log",{status:502});let X={sender:{sender_id:{open_id:J.sender_open_id}},message:{message_id:V,chat_id:J.chat_id,message_type:"text",content:JSON.stringify({text:Q}),create_time:String(Date.now())}};if(K(`debug: inject text=${JSON.stringify(Q).slice(0,80)} msg_id=${V}`),!zH(X,"debug"))return new Response("daemon shutdown in progress",{status:503});return new Response(JSON.stringify({ok:!0,msg_id:V}),{headers:{"content-type":"application/json"}})}});try{LF(v0,384)}catch{}K(`debug: inject socket listening at ${v0}`)}catch($){K(`debug: socket bind failed: ${$}`)}}async function hF(){K(`lodestar-daemon: pid ${process.pid} starting`);let{buildTokenSourcesFromConfig:$}=await Promise.resolve().then(() => (w5(),XV));$();let{refreshAllTokenSourceModels:Z}=await Promise.resolve().then(() => (k$(),T7));Z(),n6(),a6(),t6(),e6(),J9(),await f2(),setInterval(()=>{f2()},1800000),lX();let J,Q=Date.now(),Y=0,V=!1,X=null,H=1500,W=90000,z=600000,G=3,q=null,B=0,L="",F=!1,U=(A)=>{K(`[ws] rebuild requested before WS init — ${A}`)},R=(A,k=0,s=!1)=>{let c=Date.now()+k;if(q){if(F||=s,c>=B){K(`[ws] rebuild already scheduled — ${A}`);return}clearTimeout(q)}B=c,L=A,F=s,q=setTimeout(()=>{let a$=L,J$=F;q=null,B=0,L="",F=!1,U(a$,J$)},k)},D={error:(A)=>K(`[ws-sdk error] ${P3(A)}`),warn:(A)=>{let k=P3(A);if(K(`[ws-sdk warn] ${k}`),k.includes("no pong/inbound"))R("ping-timeout: SDK liveness watchdog fired",2000,Date.now()-Q<z)},info:(A)=>K(`[ws-sdk] ${P3(A)}`),debug:(A)=>{},trace:(A)=>{}},P=new K2.EventDispatcher({}),M=()=>{if(Q=Date.now(),Y=0,X)clearTimeout(X),X=null};P.register({"im.message.receive_v1":async(A)=>{if(M(),!zH(A))throw Error("daemon shutdown in progress")}}),P.register({"card.action.trigger":async(A)=>{return M(),kF(A)}});let x=()=>new K2.WSClient({appId:f.feishu.app_id,appSecret:f.feishu.app_secret,loggerLevel:K2.LoggerLevel.info,logger:D,wsConfig:{pingTimeout:60},handshakeTimeoutMs:1e4,onReconnecting:()=>K("[ws] reconnecting — WS lost, SDK is retrying"),onReconnected:()=>N(),onError:(A)=>U(`SDK onError: ${A?.message??A}`)});U=(A,k=!1)=>{if(V){K(`[ws] rebuild skipped (already rebuilding) — ${A}`);return}if(q)clearTimeout(q),q=null,B=0;V=!0,Y++,K(`[ws] rebuild #${Y} (fresh WSClient) — ${A}`);let s=J;try{s?.close({force:!0})}catch(c){K(`[ws] rebuild: old close failed: ${c}`)}if(J=x(),J.start({eventDispatcher:P}).catch((c)=>{K(`[ws] rebuild start failed: ${c}`),R(`fresh client start failed: ${c}`,H,k)}),V=!1,k)y()};let y=()=>{if(X)clearTimeout(X);let A=Date.now();X=setTimeout(()=>{if(X=null,Q>=A){Y=0;return}if(Y>=G){K(`[ws] STILL deaf after ${G} fresh rebuilds — auto-heal exhausted, `+"leaving last client up (no process exit). Restart the configured service or run lodestar-stop && lodestar-daemon"),Y=0;return}U(`verify: no event ${Math.round((Date.now()-A)/1000)}s after rebuild`,!0)},W)},N=()=>{let A=Date.now()-Q<z;K("[ws] reconnected — swapping in a fresh WSClient (cluster-routing precaution; "+`recentlyActive=${A})`),Y=0,R("post-reconnect precaution",H,A)};J=x(),J.start({eventDispatcher:P}).catch((A)=>{K(`[ws] initial start failed: ${A}`),R(`initial start failed: ${A}`,H,!1)}),K(`lodestar-daemon: WS start requested, watching ${Z$.size} groups`);let m=15000,h=2,w=0;setInterval(()=>{let{state:A}=J.getConnectionStatus();if(A==="connected"){w=0;return}if(A==="failed"||A==="idle"){w=0,U(`watchdog: state=${A}`);return}if(w++,K(`[ws] watchdog: state=${A} (${w}/${h})`),w>=h)w=0,U(`watchdog: stuck in '${A}' ~${Math.round(m*h/1000)}s`)},m),fF(),DX(),EX({bind:f.notify.bind,port:f.notify.port}),CX(),await RF()}var YH=!1,O3=!1,jZ=null,B1=0,M3=null,VH=15000,XH=()=>{if(YH)return;YH=!0;try{let $=M3??j3();if(v2($),$.length>0)K(`alive marker: [${$.join(", ")}]`)}catch($){K(`alive marker write failed: ${$}`)}try{EZ(C$)}catch{}try{EZ(v0)}catch{}},U8,F8,D8,AF,HH,MF,R3,TF=30000,z2,SF;var GH=T(()=>{GX();n();n$();e5();$3();$3();NX();oX();N$();v();m$();vZ();$H();QH();{let $=j8(C$);if($.state==="exit")console.error(`lodestar-daemon: already running (pid ${$.pid})`),process.exit(1);if(A3(C$))try{EZ(C$)}catch{}}FF(PF(C$),{recursive:!0});k3(C$);process.on("exit",XH);process.on("SIGTERM",()=>{G2("SIGTERM",0)});process.on("SIGINT",()=>{G2("SIGINT",0)});if(process.platform==="win32")process.on("SIGBREAK",()=>{G2("SIGBREAK",0)});process.on("unhandledRejection",($)=>{K(`unhandledRejection: ${$ instanceof Error?$.stack??$.message:$}`),G2("unhandledRejection",1)});process.on("uncaughtException",($)=>{K(`uncaughtException: ${$.stack??$.message}`),G2("uncaughtException",1)});U8=new Map,F8=new Set,D8=new U3,AF=new D3(30000),HH=new Set,MF=sX({actor:D8,key:($)=>String($?.message?.chat_id??""),execute:($,Z)=>xF($,Z)});R3=JH({registry:U8,createSession:($,Z)=>new K1($,Z,{onLifecycleChange:RZ,onCreateTempSession:OF,onDisbandTempSession:jF}),ensureChatForSession:z9,disbandChatForSessionExact:G9,chatIdForSession:f1,clearSessionConversationState:X9,registerTempSessionLease:o6,hasTempSessionLease:r6,replaceTurnAnchors:w$,runExclusive:($,Z)=>D8.enqueue($,Z),log:K});z2=new Set;SF=eX({actor:D8,deduper:AF,scope:($)=>String($?.context?.open_chat_id??"")||"__notify_global__",execute:wF,present:NF,presentExecutionFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");K(`handleCardAction ${J}: ${Z instanceof Error?Z.stack??Z.message:Z}`),await yF($,Z)},presentPresentationFailure:async($,Z)=>{let J=String($?.action?.value?.kind??"unknown");K(`card-action presentation ${J}: ${Z instanceof Error?Z.message:Z}`),await F1(String($?.context?.open_chat_id??""),`⚠️ ${TZ(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:($)=>{WH($)},onBackgroundError:($)=>{K(`card-action background: ${$ instanceof Error?$.stack??$.message:$}`)},responses:{accepted:($)=>({toast:{type:"info",content:`⏳ ${TZ(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}})}});hF().catch(($)=>{K(`boot fatal: ${$}`),G2("boot fatal",1)})});m$();vZ();import{existsSync as qH,unlinkSync as gF}from"node:fs";var r$={reset:"\x1B[0m",bold:"\x1B[1m",yellow:"\x1B[33m",green:"\x1B[32m",red:"\x1B[31m"};async function mF(){if(!qH(U$)){if(process.stdin.isTTY){console.log(),console.log(`${r$.bold}${r$.yellow}Lodestar: 未找到配置, 启动安装向导...${r$.reset}`);let{runSetup:Z}=await Promise.resolve().then(() => (c3(),m3));await Z();return}console.error(`${r$.red}Lodestar: 未找到配置 ${U$}${r$.reset}`),console.error(`请在交互式 cmd / PowerShell 里运行 ${r$.green}lodestar-setup${r$.reset} 完成首次配置 (或直接运行 ${r$.green}lodestar-daemon${r$.reset} 也会触发同一个向导)。`),process.exit(1)}let $=j8(C$);if($.state==="exit")console.error(`${r$.yellow}Lodestar: 已经有一个 daemon 在运行 (pid ${$.pid})${r$.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(` • 误判 / 已经死了: 手删 ${C$} 后再跑`),process.exit(1);if(qH(C$))try{gF(C$)}catch{}await Promise.resolve().then(() => (GH(),IF))}mF().catch(($)=>{console.error("lodestar fatal:",$?.message??$),process.exit(1)});
|