@leviyuan/lodestar 0.11.0 → 0.11.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.
Files changed (2) hide show
  1. package/dist/lodestar.js +1 -1
  2. package/package.json +1 -1
package/dist/lodestar.js CHANGED
@@ -228,7 +228,7 @@ Please migrate to a newer model. Visit https://docs.anthropic.com/en/docs/resour
228
228
 
229
229
  `:"";try{this.input.push({type:"user",session_id:this.sessionId??"",message:{role:"user",content:[{type:"text",text:J+Q+x}]},parent_tool_use_id:null,priority:"now"})}catch(X){let z=X instanceof Error?X:Error(String(X));u(`claude-agent-process: sendUserText failed: ${z.message}`),this.failTurnStart(z)}}sendInterrupt(){this.query?.interrupt().catch((x)=>u(`claude-agent-process: interrupt failed: ${x}`))}sendPermissionResponse(x,Z,Q){let J=this.pendingPermissions.get(String(x));if(!J){u(`claude-agent-process: permission response for unknown request ${x}`);return}if(this.pendingPermissions.delete(String(x)),J.cleanup?.(),Z==="allow"){let X=Q?.updatedInput??{};J.resolve({behavior:"completed",result:"answers"in X?X.answers:X})}else J.resolve({behavior:"cancelled"})}sendToolResult(x,Z,Q=!1){u("claude-agent-process: sendToolResult ignored; Claude Agent SDK executes built-in tools internally")}sendHookResponse(x,Z={}){u("claude-agent-process: sendHookResponse ignored; hooks are handled by SDK callbacks")}isAlive(){return this.alive}async kill(x=5000){if(!this.alive)return;this.expectedExit=!0,this.input.close();try{this.query?.close()}catch{}let Z=Date.now();while(this.alive&&Date.now()-Z<x)await new Promise((Q)=>setTimeout(Q,100));if(this.alive)this.alive=!1,this.emit("exit",{code:null,signal:"SIGKILL",expected:this.expectedExit})}async listModels(){if(!this.started)this.sendInitialize();return(await this.query.supportedModels()).map(mV0)}async setModelSettings(x,Z){let Q=w$(x);if(!e4(Z))throw Error(`invalid Claude effort: ${String(Z)}`);if(!this.started)this.sendInitialize();if(Q)await this.query.setModel(Q);if(Z==="max")await this.query.applyFlagSettings({ultracode:!0,effortLevel:null});else await this.query.applyFlagSettings({effortLevel:Z,ultracode:null});this.opts.model=x,this.opts.effort=Z,this.lastModel=Q?F6(x):"claude:default",this.lastEffort=Z}async setModel(x){await this.setModelSettings(x,this.opts.effort)}async compactThread(){throw Error("Claude Agent SDK backend does not support Lodestar compact yet")}async injectThreadItems(x){if(!Array.isArray(x)||x.length===0)return;this.pendingInjectedContext.push(["Host-injected prior tool context for this continuation:",JSON.stringify(x,null,2)].join(`
230
230
  `))}onUserDialog(x,Z){let Q=lV0(x);if(!Q)return u(`claude-agent-process: cancel unsupported user dialog kind=${x.dialogKind}`),Promise.resolve({behavior:"cancelled"});let J=`claude_dialog_${++this.requestCounter}`,X=x.toolUseID||J,z={request_id:J,tool_name:"AskUserQuestion",input:Q,tool_use_id:X},Y=new Promise((U)=>{let W=(K)=>{Z.signal.removeEventListener("abort",H),U(K)},H=()=>{if(!this.pendingPermissions.delete(J))return;W({behavior:"cancelled"})};Z.signal.addEventListener("abort",H,{once:!0}),this.pendingPermissions.set(J,{kind:"dialog",resolve:W,request:z})});return this.emitToolUseOnce(X,"AskUserQuestion",Q),this.emit("can_use_tool",z),Y}async readLoop(x){try{for await(let Z of x)this.handleMessage(Z);this.finishExit(null,null)}catch(Z){let Q=Z instanceof Error?Z:Error(String(Z));u(`claude-agent-process: read loop failed: ${Q.message}`),this.emit("error",Q),this.finishExit(1,null)}}finishExit(x,Z){if(!this.alive)return;this.alive=!1,this.turnActive=!1;for(let[Q,J]of this.pendingPermissions)J.cleanup?.(),J.resolve({behavior:"cancelled"}),this.pendingPermissions.delete(Q);u(`claude-agent-process: exited code=${x} signal=${Z} expected=${this.expectedExit}`),this.emit("exit",{code:x,signal:Z,expected:this.expectedExit})}handleMessage(x){let Z=x;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:u(`claude-agent-process: unhandled message type=${Z.type??"unknown"} subtype=${Z.subtype??""}`)}}handleSystemMessage(x){switch(x.subtype){case"init":if(typeof x.model==="string"&&x.model)this.lastModel=F6(x.model);this.lastEffort=this.opts.effort,this.emit("init",{session_id:this.sessionId,raw:x});return;case"session_state_changed":if(x.state==="running"&&!this.turnActive)this.turnActive=!0,this.emit("turn_started",{turn_id:x.uuid,thread_id:this.sessionId});else if(x.state==="idle")this.turnActive=!1;return;case"compact_boundary":this.emit("context_compacted",{threadId:x.session_id??this.sessionId??void 0,sessionId:x.session_id??this.sessionId??void 0,itemId:x.uuid,phase:"event",sourceMethod:"claude_agent_sdk",sourceType:"compact_boundary",preTokens:x.compact_metadata?.pre_tokens,trigger:x.compact_metadata?.trigger});return;case"api_retry":u(`claude-agent-process: api retry attempt=${x.attempt}/${x.max_retries} status=${x.error_status} error=${x.error}`);return;case"permission_denied":u(`claude-agent-process: permission denied ${x.tool_name} ${x.tool_use_id}: ${x.message}`);return;default:return}}handleAssistantMessage(x){let Z=x.message;if(typeof x.uuid==="string")this.lastAssistantUuid=x.uuid;if(typeof Z?.model==="string"&&Z.model)this.lastModel=F6(Z.model);let Q=Array.isArray(Z?.content)?Z.content:[];for(let J of Q){if(!J||typeof J!=="object")continue;if(J.type==="text"&&typeof J.text==="string"&&J.text.length>0){let X=yV0(J.text);if(X){if(this.pendingServerToolInputs.push(X),this.pendingServerToolInputs.length>20)this.pendingServerToolInputs.shift()}if(hV0(J.text))continue;let z=x.uuid??Z?.id;this.emit("assistant_text",{uuid:z,text:J.text}),this.emit("assistant_block_stop",{index:z})}else if(J.type==="tool_use"&&typeof J.id==="string"&&typeof J.name==="string")this.emitToolUseOnce(J.id,J.name,J.input??{});else if(J.type==="server_tool_use"&&typeof J.id==="string"&&typeof J.name==="string")this.emitToolUseOnce(J.id,fV0(J.name),{tool:J.name,input:this.serverToolInput(J.name,J.input??{})});else if(J.type==="tool_result"&&typeof J.tool_use_id==="string")this.emitToolResultOnce(J.tool_use_id,wV0(J.content),J.is_error===!0)}}emitToolUseOnce(x,Z,Q){if(this.emittedToolUseIds.has(x))return;this.emittedToolUseIds.add(x),this.emit("tool_use",{id:x,name:Z,input:Q})}serverToolInput(x,Z){let Q=d2(Z);if(Q&&typeof Q==="object"&&!Array.isArray(Q)&&Object.keys(Q).length>0)return Q;let J=this.pendingServerToolInputs.findIndex((X)=>X.name===x);if(J>=0){let[X]=this.pendingServerToolInputs.splice(J,1);return X.input}return Q}emitToolResultOnce(x,Z,Q){if(this.emittedToolResultIds.has(x))return;this.emittedToolResultIds.add(x),this.emit("tool_result",{tool_use_id:x,content:Z,is_error:Q})}handleUserMessage(x){let Z=Array.isArray(x.message?.content)?x.message.content:[];for(let Q of Z){if(!Q||typeof Q!=="object")continue;if(Q.type!=="tool_result"||typeof Q.tool_use_id!=="string")continue;let J=x.tool_use_result,X=pg(Q.content),z=J&&typeof J==="object"?[typeof J.stdout==="string"?J.stdout:"",typeof J.stderr==="string"?J.stderr:""].filter(Boolean).join(`
231
- `):"",Y=X||z;this.emitToolResultOnce(Q.tool_use_id,Y,Q.is_error===!0||J?.interrupted===!0)}}handleResultMessage(x){if(typeof x.session_id==="string"&&x.session_id)this.sessionId=x.session_id;this.turnActive=!1;let Z=kV0(x.usage),Q=x.modelUsage??x.model_usage,J=uV0(Q);if(!Z&&!J.usage)u(`claude-agent-process: result usage missing rootKeys=${y$(x).join(",")||"-"} usageKeys=${y$(x.usage).join(",")||"-"} modelUsageKeys=${y$(Q).join(",")||"-"}`);if(this.lastUsage=Z,J.usage)this.cumulativeUsageFromResults=VX(J.usage),this.lastTotalUsage=VX(J.usage);else if(Z)this.cumulativeUsageFromResults=PV0(this.cumulativeUsageFromResults,Z),this.lastTotalUsage=VX(this.cumulativeUsageFromResults);else this.lastTotalUsage=this.cumulativeUsageFromResults?VX(this.cumulativeUsageFromResults):null;if(J.contextWindow!=null){let z=_g(this.opts.model),Y=l2.get(z)??0;if(J.contextWindow>Y)l2.set(z,J.contextWindow),u(`claude-agent-process: SDK contextWindow ${J.contextWindow} (global max for ${z}, prev ${Y||"-"})`);else if(J.contextWindow<(l2.get(z)??0))u(`claude-agent-process: SDK contextWindow ${J.contextWindow} ignored (global max ${l2.get(z)} locked for ${z})`)}if(this.lastContextWindow=l2.get(_g(this.opts.model))??J.contextWindow??null,this.lastContextTokens=gV0(this.lastTotalUsage),this.lastTotalUsage||this.lastUsage)this.emit("token_usage",{usage:this.lastUsage,totalUsage:this.lastTotalUsage,contextWindow:this.lastContextWindow,threadId:this.sessionId??void 0,turnId:x.uuid});let X=typeof x.subtype==="string"?x.subtype:x.is_error?"error":"success";this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:typeof x.duration_ms==="number"?x.duration_ms:null,num_turns:typeof x.num_turns==="number"?x.num_turns:1,usage:this.lastUsage,subtype:X,is_error:x.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})}failTurnStart(x){this.turnActive=!1,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:x.message})}}});import{randomUUID as sV0}from"node:crypto";async function rg(x){let Z=await V1("feishu chat.get",()=>Xx.im.chat.get({path:{chat_id:x},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)z1("feishu chat.get",Z);let Q=Z.data?.owner_id;if(!Q)throw Error("feishu chat.get returned no owner_id; cannot add project group owner to tasklist");return Q}async function tg(x,Z){let Q=await V1("feishu tasklist.create",()=>Xx.task.v2.tasklist.create({params:{user_id_type:"open_id"},data:{name:x,members:[{id:Z,type:"user",role:"editor"}]}}));if(Q.code&&Q.code!==0)z1("feishu tasklist.create",Q);let J=Q.data?.tasklist,X=J?.guid;if(!X)throw Error("feishu tasklist.create returned no guid");return{guid:X,name:J?.name||x,url:J?.url??"",createdAt:J?.created_at}}async function eg(x){let Z=await V1("feishu tasklist.delete",()=>Xx.task.v2.tasklist.delete({path:{tasklist_guid:x}}));if(Z.code&&Z.code!==0)z1("feishu tasklist.delete",Z)}async function GX(x){let Z=[],Q;do{let J=await V1("feishu section.list",()=>Xx.task.v2.section.list({params:{resource_type:"tasklist",resource_id:x,page_size:50,...Q?{page_token:Q}:{}}}));if(J.code&&J.code!==0)z1("feishu section.list",J);for(let X of J.data?.items??[]){if(!X.guid||!X.name)continue;Z.push({guid:X.guid,name:X.name,isDefault:X.is_default})}Q=J.data?.has_more?J.data?.page_token:void 0}while(Q);return Z}async function ag(x){let Z=await V1("feishu section.create",()=>Xx.task.v2.section.create({data:{resource_type:"tasklist",resource_id:x.tasklistGuid,name:x.name,...x.insertAfter?{insert_after:x.insertAfter}:{}}}));if(Z.code&&Z.code!==0)z1("feishu section.create",Z);let Q=Z.data?.section?.guid;if(!Q)throw Error(`feishu section.create returned no guid for "${x.name}"`);return Q}async function n$(x){let Z=await V1("feishu section.get",()=>Xx.task.v2.section.get({path:{section_guid:x},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)z1("feishu section.get",Z);let Q=Z.data?.section;if(!Q?.guid)throw Error(`feishu section.get returned no section: ${x}`);return{guid:Q.guid,name:Q.name??"",isDefault:Q.is_default,tasklistGuid:Q.tasklist?.guid}}async function xu(x,Z){let Q=await V1("feishu section.patch",()=>Xx.task.v2.section.patch({path:{section_guid:x},params:{user_id_type:"open_id"},data:{section:{name:Z},update_fields:["name"]}}));if(Q.code&&Q.code!==0)z1("feishu section.patch",Q);let J=Q.data?.section;if(!J?.guid)throw Error(`feishu section.patch returned no section: ${x}`);return{guid:J.guid,name:J.name??"",isDefault:J.is_default,tasklistGuid:J.tasklist?.guid}}async function Yu(x){let Z=await V1("feishu section.delete",()=>Xx.task.v2.section.delete({path:{section_guid:x}}));if(Z.code&&Z.code!==0)z1("feishu section.delete",Z)}async function $6(x,Z){let Q=[],J;do{let X=await V1("feishu section.tasks",()=>Xx.task.v2.section.tasks({path:{section_guid:x},params:{page_size:50,...typeof Z==="boolean"?{completed:Z}:{},...J?{page_token:J}:{}}}));if(X.code&&X.code!==0)z1("feishu section.tasks",X);for(let z of X.data?.items??[]){if(!z.guid)continue;Q.push({guid:z.guid,summary:z.summary??"",completedAt:z.completed_at,subtaskCount:z.subtask_count})}J=X.data?.has_more?X.data?.page_token:void 0}while(J);return Q}async function Zu(x,Z){let Q=[],J;do{let X=await V1("feishu tasklist.tasks",()=>Xx.task.v2.tasklist.tasks({path:{tasklist_guid:x},params:{page_size:50,user_id_type:"open_id",...typeof Z==="boolean"?{completed:Z}:{},...J?{page_token:J}:{}}}));if(X.code&&X.code!==0)z1("feishu tasklist.tasks",X);for(let z of X.data?.items??[]){if(!z.guid)continue;Q.push({guid:z.guid,summary:z.summary??"",completedAt:z.completed_at,subtaskCount:z.subtask_count})}J=X.data?.has_more?X.data?.page_token:void 0}while(J);return Q}async function Qu(x){let Z=`lodestar-default-section-discovery-${Date.now()}-${sV0().slice(0,8)}`,Q="";try{let J=await V1("feishu task.create",()=>Xx.task.v2.task.create({params:{user_id_type:"open_id"},data:{summary:Z,tasklists:[{tasklist_guid:x}]}}));if(J.code&&J.code!==0)z1("feishu task.create",J);let X=J.data?.task;if(Q=X?.guid??"",!Q)throw Error("feishu task.create returned no guid during default section discovery");let z=X.tasklists?.find((W)=>W.tasklist_guid===x)?.section_guid;if(z)return z;let U=(await FX(Q)).tasklists?.find((W)=>W.tasklist_guid===x)?.section_guid;if(!U)throw Error(`failed to discover default section guid for tasklist ${x}`);return U}finally{if(Q)await oV0(Q)}}async function oV0(x){let Z=await V1("feishu task.delete",()=>Xx.task.v2.task.delete({path:{task_guid:x}}));if(Z.code&&Z.code!==0)z1("feishu task.delete",Z)}async function FX(x){let Z=await V1("feishu task.get",()=>Xx.task.v2.task.get({path:{task_guid:x},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)z1("feishu task.get",Z);let Q=Z.data?.task;if(!Q)throw Error(`feishu task.get returned no task: ${x}`);return Q}async function Ju(x){let Z=[],Q;do{let J=await V1("feishu comment.list",()=>Xx.task.v2.comment.list({params:{resource_type:"task",resource_id:x,direction:"asc",page_size:50,user_id_type:"open_id",...Q?{page_token:Q}:{}}}));if(J.code&&J.code!==0)z1("feishu comment.list",J);for(let X of J.data?.items??[]){if(!X.id)continue;Z.push({id:X.id,content:X.content??"",createdAt:X.created_at,updatedAt:X.updated_at,creator:X.creator})}Q=J.data?.has_more?J.data?.page_token:void 0}while(Q);return Z}async function N3(x,Z){let Q=await V1("feishu comment.create",()=>Xx.task.v2.comment.create({data:{resource_type:"task",resource_id:x,content:Z},params:{user_id_type:"open_id"}}));if(Q.code&&Q.code!==0)z1("feishu comment.create",Q);let J=Q.data?.comment?.id;if(!J)throw Error(`feishu comment.create returned no id for task ${x}`);return J}async function $X(x,Z,Q){let J=await V1("feishu task.addTasklist",()=>Xx.task.v2.task.addTasklist({path:{task_guid:x},data:{tasklist_guid:Z,section_guid:Q},params:{user_id_type:"open_id"}}));if(J.code&&J.code!==0)z1("feishu task.addTasklist",J)}function rV0(x,Z){let Q=Z&&typeof Z==="object"?Z:{},J=Q.response?.data&&typeof Q.response.data==="object"?Q.response.data:Q.data&&typeof Q.data==="object"?Q.data:Q,X=J.code??Q.code,z=J.msg??J.message??Q.msg??Q.message??"unknown error",Y=J.error?.permission_violations??J.permission_violations??Q.error?.permission_violations,U=Array.isArray(Y)?Y.map((W)=>W?.scope??W?.subject??W?.name??W).filter(Boolean).join(", "):"";return`${x} failed code=${X??"unknown"} msg=${z}${U?` missing_scopes=${U}`:""}`}async function V1(x,Z){try{return await Z()}catch(Q){z1(x,Q)}}function z1(x,Z){throw Error(rV0(x,Z))}var Xu=k0(()=>{x1()});import{execSync as Vu}from"node:child_process";import{randomUUID as Hu}from"node:crypto";import{existsSync as tV0,mkdirSync as Z5,readFileSync as p2,statSync as eV0,writeFileSync as J5}from"node:fs";import{readFile as Gu}from"node:fs/promises";import{homedir as zu}from"node:os";import{basename as L3,extname as aV0,join as l$}from"node:path";async function U6(){if(UX&&Date.now()<Ku)return UX;let Z=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:Fu,app_secret:$u})})).json();if(!Z.tenant_access_token)throw Error("feishu: failed to obtain tenant token");return UX=Z.tenant_access_token,Ku=Date.now()+((Z.expire??7200)-60)*1000,UX}function Uu(){try{let x=JSON.parse(p2(jz,"utf8"));for(let[Z,Q]of Object.entries(x))if(typeof Q==="string")h1.set(Z,Q);u(`feishu: loaded ${h1.size} session→chat bindings`)}catch{}}function Nu(){try{let x={};for(let[Z,Q]of h1)x[Z]=Q;Z5(kx,{recursive:!0}),J5(jz,JSON.stringify(x,null,2))}catch(x){u(`feishu: save session-chat-map failed: ${x}`)}}function LX(x,Z){if(h1.get(x)===Z)return;let Q=h1.get(x);h1.set(x,Z),Nu(),u(`feishu: bound session "${x}" → ${Z}${Q?` (was ${Q})`:""}`)}function d$(x){let Z=h1.get(x);if(!Z)return;h1.delete(x),Nu(),u(`feishu: unbound session "${x}" from ${Z}`)}function NX(x,Z,Q){let J=Q5.get(x)??{};J[Z]=Q,Q5.set(x,J)}function Lu(){try{let x=JSON.parse(p2(Iz,"utf8"));for(let[Z,Q]of Object.entries(x)){if(typeof Q==="string"&&Q.trim()){NX(Z,"codex",Q);continue}if(!Q||typeof Q!=="object")continue;let J=Q,X=J.provider==="claude"||J.provider==="codex"?J.provider:null,z=typeof J.sessionId==="string"?J.sessionId:typeof J.session_id==="string"?J.session_id:null;if(X&&z?.trim()){NX(Z,X,z);continue}for(let Y of["codex","claude"]){let U=J[Y];if(typeof U==="string"&&U.trim())NX(Z,Y,U)}}u(`feishu: loaded ${Q5.size} session→resume bindings`)}catch{}}function xH0(){try{let x={};for(let[Z,Q]of Q5)x[Z]={...Q};Z5(kx,{recursive:!0}),J5(Iz,JSON.stringify(x,null,2))}catch(x){u(`feishu: save session-resume-map failed: ${x}`)}}function Du(x,Z,Q="codex"){if(Q5.get(x)?.[Q]===Z)return;NX(x,Q,Z),xH0()}function i$(x,Z="codex"){return Q5.get(x)?.[Z]??null}function Ou(){try{let x=JSON.parse(p2(Tz,"utf8"));for(let[Z,Q]of Object.entries(x)){if(typeof Q==="string"&&Q.trim()){D3.set(Z,{provider:O7(Q),model:Q,effort:null});continue}if(!Q||typeof Q!=="object")continue;let J=Q.model;if(typeof J!=="string"||!J.trim())continue;let X=Q.provider,z=X==="claude"||X==="codex"?X:O7(J),Y=Q.effort,U=z==="claude"?e4(Y)?Y:null:B8(Y)?Y:null;D3.set(Z,{provider:z,model:J,effort:U})}u(`feishu: loaded ${D3.size} session→model bindings`)}catch{}}function YH0(){try{let x={};for(let[Z,Q]of D3)x[Z]=Q;Z5(kx,{recursive:!0}),J5(Tz,JSON.stringify(x,null,2))}catch(x){u(`feishu: save session-model-map failed: ${x}`)}}function Bu(x,Z,Q,J){let X=D3.get(x);if(X?.provider===Z&&X.model===Q&&X.effort===J)return;D3.set(x,{provider:Z,model:Q,effort:J}),YH0()}function vu(x){return D3.get(x)??null}function p$(x){try{J5(cY,JSON.stringify(x,null,2))}catch(Z){u(`feishu: write alive marker failed: ${Z}`)}}function Mu(){if(!tV0(cY))return[];try{let x=p2(cY,"utf8"),Z=JSON.parse(x);return Array.isArray(Z)?Z.filter((Q)=>typeof Q==="string"):[]}catch(x){return u(`feishu: read alive marker failed: ${x}`),[]}}function DX(x){let Z=h1.get(x);if(Z){let J=c1.get(Z);if(J&&J!==x)u(`feishu: chatIdForSession("${x}"): persisted binding ${Z} has cached name "${J}", using persisted binding`);return Z}let Q=[];for(let[J,X]of c1)if(X===x)Q.push(J);if(Q.length===1)return Q[0];if(Q.length>1)u(`feishu: chatIdForSession("${x}"): ${Q.length} candidates with no binding — [${Q.join(", ")}]`);return null}async function OX(){try{let x;do{let Z=await Xx.im.chat.list({params:{page_size:100,...x?{page_token:x}:{}}});for(let Q of Z.data?.items??[])if(Q.chat_id&&Q.name)c1.set(Q.chat_id,Q.name);x=Z.data?.page_token}while(x);u(`feishu: refreshed chat list — ${c1.size} groups`)}catch(x){u(`feishu: refresh chat list failed: ${x}`)}}async function s$(){let x=new Map,Z;do{let Q=await Xx.im.chat.list({params:{page_size:100,...Z?{page_token:Z}:{}}});if(Q.code&&Q.code!==0)throw Error(`feishu chat.list failed code=${Q.code} msg=${Q.msg}`);for(let J of Q.data?.items??[]){if(!J.chat_id||!J.name)continue;if(J.chat_status&&J.chat_status!=="normal")continue;c1.set(J.chat_id,J.name);let X=x.get(J.name)??[];X.push(J.chat_id),x.set(J.name,X)}Z=Q.data?.page_token}while(Z);return x}async function Su(x){let Z=h1.get(x);if(Z&&c1.get(Z)===x){let z=await QH0(Z);if(z.name===x&&JH0(z.status))return Z;c1.delete(Z),d$(x)}let J=(await s$()).get(x)??[];if(J.length===0)return null;let X=h1.get(x);if(X&&J.includes(X))return X;if(J.length===1)return J[0];throw Error(`multiple Feishu groups named "${x}": ${J.join(", ")}`)}async function Ru(x,Z){if(!Z)throw Error("missing sender open_id; cannot add user to worktree group");let Q=await Su(x);if(Q){let z=await ZH0(Q,Z);return LX(x,Q),{chatId:Q,created:!1,joined:z}}let J=await Xx.im.chat.create({params:{user_id_type:"open_id",uuid:Hu()},data:{name:x,user_id_list:[Z],group_message_type:"chat"}});if(J.code&&J.code!==0)throw Error(`feishu chat.create failed code=${J.code} msg=${J.msg}`);let X=J.data?.chat_id;if(!X)throw Error("feishu chat.create returned no chat_id");return c1.set(X,x),LX(x,X),{chatId:X,created:!0,joined:!0}}async function Cu(x){let Z=await Su(x);if(!Z)return d$(x),{chatId:null,disbanded:!1};let Q=await Xx.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 c1.delete(Z),d$(x),{chatId:Z,disbanded:!0}}async function ZH0(x,Z){let Q;do{let X=await Xx.im.chatMembers.get({path:{chat_id:x},params:{member_id_type:"open_id",page_size:100,...Q?{page_token:Q}:{}}});if(X.code&&X.code!==0)throw Error(`feishu chatMembers.get failed code=${X.code} msg=${X.msg}`);for(let z of X.data?.items??[])if(z.member_id===Z)return!1;Q=X.data?.page_token}while(Q);let J=await Xx.im.chatMembers.create({path:{chat_id:x},params:{member_id_type:"open_id"},data:{id_list:[Z]}});if(J.code&&J.code!==0)throw Error(`feishu chatMembers.create failed code=${J.code} msg=${J.msg}`);return!0}async function ju(x){try{let Z=await U6(),J=await(await fetch(`https://open.feishu.cn/open-apis/im/v1/chats/${encodeURIComponent(x)}`,{headers:{Authorization:`Bearer ${Z}`}})).json();if(J?.code!==0)return u(`feishu: fetchChatName ${x} code=${J?.code} msg=${J?.msg}`),null;let X=J.data?.name;if(typeof X==="string"&&X)return c1.set(x,X),u(`feishu: fetchChatName ${x} → "${X}" (point lookup)`),X;return u(`feishu: fetchChatName ${x} — chat has no name (unnamed group?)`),null}catch(Z){return u(`feishu: fetchChatName ${x} failed: ${Z}`),null}}async function Iu(x,Z,Q,J){let X=Hu(),z=null;for(let Y=0;Y<i2.length;Y++){if(i2[Y]>0)await new Promise((U)=>setTimeout(U,i2[Y]));try{let U=await Xx.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:Z,msg_type:Q,content:J,uuid:X}});if(U?.code&&U.code!==0)return u(`feishu: send${x==="text"?"Text":"Card"} rejected chat=${Z} code=${U.code} msg=${U.msg}`),null;return U?.data?.message_id??null}catch(U){z=U,u(`feishu: send${x==="text"?"Text":"Card"} attempt ${Y+1}/${i2.length} chat=${Z} failed: ${U}`)}}return u(`feishu: send${x==="text"?"Text":"Card"} chat=${Z} EXHAUSTED ${i2.length} retries: ${z}`),null}async function QH0(x){let Z=await Xx.im.chat.get({path:{chat_id:x}});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 JH0(x){return x===null||x==="normal"}async function c0(x,Z){return Iu("text",x,"text",JSON.stringify({text:Z}))}async function ix(x,Z){return Iu("card",x,"interactive",JSON.stringify(Z))}async function Px(x,Z){try{let Q=await U6(),X=await(await fetch("https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({receive_id:x,msg_type:"text",content:JSON.stringify({text:Z})})})).json();if(X?.code!==0)return u(`feishu: sendTextRaw rejected chat=${x} code=${X?.code} msg=${X?.msg}`),null;return X.data?.message_id??null}catch(Q){return u(`feishu: sendTextRaw chat=${x} failed: ${Q}`),null}}async function c8(x,Z){if(!x)return null;try{return(await Xx.im.messageReaction.create({path:{message_id:x},data:{reaction_type:{emoji_type:Z}}}))?.data?.reaction_id??null}catch(Q){return u(`feishu: addReaction ${Z} on ${x} failed: ${Q}`),null}}async function B3(x,Z){if(!x||!Z)return;try{await Xx.im.messageReaction.delete({path:{message_id:x,reaction_id:Z}})}catch(Q){u(`feishu: deleteReaction ${Z} on ${x} failed: ${Q}`)}}async function X5(x,Z){if(!x){u("feishu: urgentApp skip — missing messageId");return}if(Z.length===0){u(`feishu: urgentApp skip — empty openIds (msg=${x})`);return}let Q=await U6(),J=`https://open.feishu.cn/open-apis/im/v1/messages/${x}/urgent_app?user_id_type=open_id`;try{let z=await(await fetch(J,{method:"PATCH",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({user_id_list:Z})})).json();if(z?.code!==0){u(`feishu: urgentApp ${x} code=${z?.code} msg=${z?.msg}`);return}let Y=z.data?.invalid_user_id_list??[],U=Z.length-Y.length;u(`feishu: urgentApp ${x} ok — delivered=${U}${Y.length?` invalid=${Y.length}`:""}`)}catch(X){u(`feishu: urgentApp ${x} failed: ${X}`)}}async function s2(x,Z,Q,J){try{let X=await U6(),z=`https://open.feishu.cn/open-apis/im/v1/messages/${x}/resources/${Z}?type=${Q}`,Y=await fetch(z,{headers:{Authorization:`Bearer ${X}`}});if(!Y.ok){u(`feishu: download ${Q} HTTP ${Y.status}: ${(await Y.text()).slice(0,200)}`);return}let U=Buffer.from(await Y.arrayBuffer());Z5(cz,{recursive:!0});let W=J?J.replace(/[^a-zA-Z0-9._-]/g,"_"):`${Z.replace(/[^a-zA-Z0-9_-]/g,"_")}.png`,H=l$(cz,`${Date.now()}-${W}`);return J5(H,U),u(`feishu: downloaded ${Q} ${H} (${U.length}B)`),H}catch(X){u(`feishu: download ${Q} failed: ${X instanceof Error?X.message:X}`);return}}function KH0(x){return zH0.has(aV0(x).toLowerCase())}async function WH0(x){let Z=await U6(),Q=new Blob([await Gu(x)]),J=new FormData;J.append("image_type","message"),J.append("image",Q,L3(x));let z=await(await fetch("https://open.feishu.cn/open-apis/im/v1/images",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:J})).json();if(z?.code!==0)return u(`feishu: uploadImage ${x} code=${z.code} msg=${z.msg}`),null;return z.data?.image_key??null}async function VH0(x){let Z=await U6(),Q=new Blob([await Gu(x)]),J=new FormData;J.append("file_type","stream"),J.append("file_name",L3(x)),J.append("file",Q,L3(x));let z=await(await fetch("https://open.feishu.cn/open-apis/im/v1/files",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:J})).json();if(z?.code!==0)return u(`feishu: uploadFile ${x} code=${z.code} msg=${z.msg}`),null;return z.data?.file_key??null}async function HH0(x,Z){try{let Q=await Xx.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:x,msg_type:"image",content:JSON.stringify({image_key:Z})}});if(Q?.code&&Q.code!==0)return u(`feishu: sendImage rejected chat=${x} code=${Q.code} msg=${Q.msg}`),null;return Q?.data?.message_id??null}catch(Q){return u(`feishu: sendImage failed chat=${x}: ${Q}`),null}}async function GH0(x,Z){try{let Q=await Xx.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:x,msg_type:"file",content:JSON.stringify({file_key:Z})}});if(Q?.code&&Q.code!==0)return u(`feishu: sendFile rejected chat=${x} code=${Q.code} msg=${Q.msg}`),null;return Q?.data?.message_id??null}catch(Q){return u(`feishu: sendFile failed chat=${x}: ${Q}`),null}}async function Tu(x,Z){try{let J=eV0(Z);if(!J.isFile())return await c0(x,`❌ 出站文件: 路径不是文件 — ${Z}`),!1;if(J.size>XH0)return await c0(x,`❌ 出站文件: ${L3(Z)} 超过 30 MB (${(J.size/1024/1024).toFixed(1)} MB)`),!1}catch(J){return await c0(x,`❌ 出站文件: 无法读取 ${Z} (${J})`),!1}let Q=KH0(Z);try{if(Q){let J=await WH0(Z);if(!J)return await c0(x,`❌ 出站图片上传失败: ${L3(Z)}`),!1;return await HH0(x,J)!=null}else{let J=await VH0(Z);if(!J)return await c0(x,`❌ 出站文件上传失败: ${L3(Z)}`),!1;return await GH0(x,J)!=null}}catch(J){return u(`feishu: uploadAndSend ${Z} failed: ${J}`),await c0(x,`❌ 出站文件异常: ${L3(Z)} — ${J}`),!1}}function cu(x){Z5(x,{recursive:!0}),u(`feishu: provisioned ${x}`);let Z=l$(zu(),".codex","config.toml");try{Z5(l$(zu(),".codex"),{recursive:!0});let Q="";try{Q=p2(Z,"utf8")}catch{}let J=`[projects.${JSON.stringify(x)}]`;if(!Q.includes(J)){let X=Q.trimEnd();Q=`${X}${X?`
231
+ `):"",Y=X||z;this.emitToolResultOnce(Q.tool_use_id,Y,Q.is_error===!0||J?.interrupted===!0)}}handleResultMessage(x){if(typeof x.session_id==="string"&&x.session_id)this.sessionId=x.session_id;this.turnActive=!1;let Z=kV0(x.usage),Q=x.modelUsage??x.model_usage,J=uV0(Q);if(!Z&&!J.usage)u(`claude-agent-process: result usage missing rootKeys=${y$(x).join(",")||"-"} usageKeys=${y$(x.usage).join(",")||"-"} modelUsageKeys=${y$(Q).join(",")||"-"}`);if(this.lastUsage=Z,J.usage)this.cumulativeUsageFromResults=VX(J.usage),this.lastTotalUsage=VX(J.usage);else if(Z)this.cumulativeUsageFromResults=PV0(this.cumulativeUsageFromResults,Z),this.lastTotalUsage=VX(this.cumulativeUsageFromResults);else this.lastTotalUsage=this.cumulativeUsageFromResults?VX(this.cumulativeUsageFromResults):null;if(J.contextWindow!=null){let z=_g(this.opts.model),Y=l2.get(z)??0;if(J.contextWindow>Y)l2.set(z,J.contextWindow),u(`claude-agent-process: SDK contextWindow ${J.contextWindow} (global max for ${z}, prev ${Y||"-"})`);else if(J.contextWindow<(l2.get(z)??0))u(`claude-agent-process: SDK contextWindow ${J.contextWindow} ignored (global max ${l2.get(z)} locked for ${z})`)}if(this.lastContextWindow=l2.get(_g(this.opts.model))??J.contextWindow??null,this.lastContextTokens=gV0(this.lastUsage),this.lastTotalUsage||this.lastUsage)this.emit("token_usage",{usage:this.lastUsage,totalUsage:this.lastTotalUsage,contextWindow:this.lastContextWindow,threadId:this.sessionId??void 0,turnId:x.uuid});let X=typeof x.subtype==="string"?x.subtype:x.is_error?"error":"success";this.lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:typeof x.duration_ms==="number"?x.duration_ms:null,num_turns:typeof x.num_turns==="number"?x.num_turns:1,usage:this.lastUsage,subtype:X,is_error:x.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})}failTurnStart(x){this.turnActive=!1,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:x.message})}}});import{randomUUID as sV0}from"node:crypto";async function rg(x){let Z=await V1("feishu chat.get",()=>Xx.im.chat.get({path:{chat_id:x},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)z1("feishu chat.get",Z);let Q=Z.data?.owner_id;if(!Q)throw Error("feishu chat.get returned no owner_id; cannot add project group owner to tasklist");return Q}async function tg(x,Z){let Q=await V1("feishu tasklist.create",()=>Xx.task.v2.tasklist.create({params:{user_id_type:"open_id"},data:{name:x,members:[{id:Z,type:"user",role:"editor"}]}}));if(Q.code&&Q.code!==0)z1("feishu tasklist.create",Q);let J=Q.data?.tasklist,X=J?.guid;if(!X)throw Error("feishu tasklist.create returned no guid");return{guid:X,name:J?.name||x,url:J?.url??"",createdAt:J?.created_at}}async function eg(x){let Z=await V1("feishu tasklist.delete",()=>Xx.task.v2.tasklist.delete({path:{tasklist_guid:x}}));if(Z.code&&Z.code!==0)z1("feishu tasklist.delete",Z)}async function GX(x){let Z=[],Q;do{let J=await V1("feishu section.list",()=>Xx.task.v2.section.list({params:{resource_type:"tasklist",resource_id:x,page_size:50,...Q?{page_token:Q}:{}}}));if(J.code&&J.code!==0)z1("feishu section.list",J);for(let X of J.data?.items??[]){if(!X.guid||!X.name)continue;Z.push({guid:X.guid,name:X.name,isDefault:X.is_default})}Q=J.data?.has_more?J.data?.page_token:void 0}while(Q);return Z}async function ag(x){let Z=await V1("feishu section.create",()=>Xx.task.v2.section.create({data:{resource_type:"tasklist",resource_id:x.tasklistGuid,name:x.name,...x.insertAfter?{insert_after:x.insertAfter}:{}}}));if(Z.code&&Z.code!==0)z1("feishu section.create",Z);let Q=Z.data?.section?.guid;if(!Q)throw Error(`feishu section.create returned no guid for "${x.name}"`);return Q}async function n$(x){let Z=await V1("feishu section.get",()=>Xx.task.v2.section.get({path:{section_guid:x},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)z1("feishu section.get",Z);let Q=Z.data?.section;if(!Q?.guid)throw Error(`feishu section.get returned no section: ${x}`);return{guid:Q.guid,name:Q.name??"",isDefault:Q.is_default,tasklistGuid:Q.tasklist?.guid}}async function xu(x,Z){let Q=await V1("feishu section.patch",()=>Xx.task.v2.section.patch({path:{section_guid:x},params:{user_id_type:"open_id"},data:{section:{name:Z},update_fields:["name"]}}));if(Q.code&&Q.code!==0)z1("feishu section.patch",Q);let J=Q.data?.section;if(!J?.guid)throw Error(`feishu section.patch returned no section: ${x}`);return{guid:J.guid,name:J.name??"",isDefault:J.is_default,tasklistGuid:J.tasklist?.guid}}async function Yu(x){let Z=await V1("feishu section.delete",()=>Xx.task.v2.section.delete({path:{section_guid:x}}));if(Z.code&&Z.code!==0)z1("feishu section.delete",Z)}async function $6(x,Z){let Q=[],J;do{let X=await V1("feishu section.tasks",()=>Xx.task.v2.section.tasks({path:{section_guid:x},params:{page_size:50,...typeof Z==="boolean"?{completed:Z}:{},...J?{page_token:J}:{}}}));if(X.code&&X.code!==0)z1("feishu section.tasks",X);for(let z of X.data?.items??[]){if(!z.guid)continue;Q.push({guid:z.guid,summary:z.summary??"",completedAt:z.completed_at,subtaskCount:z.subtask_count})}J=X.data?.has_more?X.data?.page_token:void 0}while(J);return Q}async function Zu(x,Z){let Q=[],J;do{let X=await V1("feishu tasklist.tasks",()=>Xx.task.v2.tasklist.tasks({path:{tasklist_guid:x},params:{page_size:50,user_id_type:"open_id",...typeof Z==="boolean"?{completed:Z}:{},...J?{page_token:J}:{}}}));if(X.code&&X.code!==0)z1("feishu tasklist.tasks",X);for(let z of X.data?.items??[]){if(!z.guid)continue;Q.push({guid:z.guid,summary:z.summary??"",completedAt:z.completed_at,subtaskCount:z.subtask_count})}J=X.data?.has_more?X.data?.page_token:void 0}while(J);return Q}async function Qu(x){let Z=`lodestar-default-section-discovery-${Date.now()}-${sV0().slice(0,8)}`,Q="";try{let J=await V1("feishu task.create",()=>Xx.task.v2.task.create({params:{user_id_type:"open_id"},data:{summary:Z,tasklists:[{tasklist_guid:x}]}}));if(J.code&&J.code!==0)z1("feishu task.create",J);let X=J.data?.task;if(Q=X?.guid??"",!Q)throw Error("feishu task.create returned no guid during default section discovery");let z=X.tasklists?.find((W)=>W.tasklist_guid===x)?.section_guid;if(z)return z;let U=(await FX(Q)).tasklists?.find((W)=>W.tasklist_guid===x)?.section_guid;if(!U)throw Error(`failed to discover default section guid for tasklist ${x}`);return U}finally{if(Q)await oV0(Q)}}async function oV0(x){let Z=await V1("feishu task.delete",()=>Xx.task.v2.task.delete({path:{task_guid:x}}));if(Z.code&&Z.code!==0)z1("feishu task.delete",Z)}async function FX(x){let Z=await V1("feishu task.get",()=>Xx.task.v2.task.get({path:{task_guid:x},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)z1("feishu task.get",Z);let Q=Z.data?.task;if(!Q)throw Error(`feishu task.get returned no task: ${x}`);return Q}async function Ju(x){let Z=[],Q;do{let J=await V1("feishu comment.list",()=>Xx.task.v2.comment.list({params:{resource_type:"task",resource_id:x,direction:"asc",page_size:50,user_id_type:"open_id",...Q?{page_token:Q}:{}}}));if(J.code&&J.code!==0)z1("feishu comment.list",J);for(let X of J.data?.items??[]){if(!X.id)continue;Z.push({id:X.id,content:X.content??"",createdAt:X.created_at,updatedAt:X.updated_at,creator:X.creator})}Q=J.data?.has_more?J.data?.page_token:void 0}while(Q);return Z}async function N3(x,Z){let Q=await V1("feishu comment.create",()=>Xx.task.v2.comment.create({data:{resource_type:"task",resource_id:x,content:Z},params:{user_id_type:"open_id"}}));if(Q.code&&Q.code!==0)z1("feishu comment.create",Q);let J=Q.data?.comment?.id;if(!J)throw Error(`feishu comment.create returned no id for task ${x}`);return J}async function $X(x,Z,Q){let J=await V1("feishu task.addTasklist",()=>Xx.task.v2.task.addTasklist({path:{task_guid:x},data:{tasklist_guid:Z,section_guid:Q},params:{user_id_type:"open_id"}}));if(J.code&&J.code!==0)z1("feishu task.addTasklist",J)}function rV0(x,Z){let Q=Z&&typeof Z==="object"?Z:{},J=Q.response?.data&&typeof Q.response.data==="object"?Q.response.data:Q.data&&typeof Q.data==="object"?Q.data:Q,X=J.code??Q.code,z=J.msg??J.message??Q.msg??Q.message??"unknown error",Y=J.error?.permission_violations??J.permission_violations??Q.error?.permission_violations,U=Array.isArray(Y)?Y.map((W)=>W?.scope??W?.subject??W?.name??W).filter(Boolean).join(", "):"";return`${x} failed code=${X??"unknown"} msg=${z}${U?` missing_scopes=${U}`:""}`}async function V1(x,Z){try{return await Z()}catch(Q){z1(x,Q)}}function z1(x,Z){throw Error(rV0(x,Z))}var Xu=k0(()=>{x1()});import{execSync as Vu}from"node:child_process";import{randomUUID as Hu}from"node:crypto";import{existsSync as tV0,mkdirSync as Z5,readFileSync as p2,statSync as eV0,writeFileSync as J5}from"node:fs";import{readFile as Gu}from"node:fs/promises";import{homedir as zu}from"node:os";import{basename as L3,extname as aV0,join as l$}from"node:path";async function U6(){if(UX&&Date.now()<Ku)return UX;let Z=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:Fu,app_secret:$u})})).json();if(!Z.tenant_access_token)throw Error("feishu: failed to obtain tenant token");return UX=Z.tenant_access_token,Ku=Date.now()+((Z.expire??7200)-60)*1000,UX}function Uu(){try{let x=JSON.parse(p2(jz,"utf8"));for(let[Z,Q]of Object.entries(x))if(typeof Q==="string")h1.set(Z,Q);u(`feishu: loaded ${h1.size} session→chat bindings`)}catch{}}function Nu(){try{let x={};for(let[Z,Q]of h1)x[Z]=Q;Z5(kx,{recursive:!0}),J5(jz,JSON.stringify(x,null,2))}catch(x){u(`feishu: save session-chat-map failed: ${x}`)}}function LX(x,Z){if(h1.get(x)===Z)return;let Q=h1.get(x);h1.set(x,Z),Nu(),u(`feishu: bound session "${x}" → ${Z}${Q?` (was ${Q})`:""}`)}function d$(x){let Z=h1.get(x);if(!Z)return;h1.delete(x),Nu(),u(`feishu: unbound session "${x}" from ${Z}`)}function NX(x,Z,Q){let J=Q5.get(x)??{};J[Z]=Q,Q5.set(x,J)}function Lu(){try{let x=JSON.parse(p2(Iz,"utf8"));for(let[Z,Q]of Object.entries(x)){if(typeof Q==="string"&&Q.trim()){NX(Z,"codex",Q);continue}if(!Q||typeof Q!=="object")continue;let J=Q,X=J.provider==="claude"||J.provider==="codex"?J.provider:null,z=typeof J.sessionId==="string"?J.sessionId:typeof J.session_id==="string"?J.session_id:null;if(X&&z?.trim()){NX(Z,X,z);continue}for(let Y of["codex","claude"]){let U=J[Y];if(typeof U==="string"&&U.trim())NX(Z,Y,U)}}u(`feishu: loaded ${Q5.size} session→resume bindings`)}catch{}}function xH0(){try{let x={};for(let[Z,Q]of Q5)x[Z]={...Q};Z5(kx,{recursive:!0}),J5(Iz,JSON.stringify(x,null,2))}catch(x){u(`feishu: save session-resume-map failed: ${x}`)}}function Du(x,Z,Q="codex"){if(Q5.get(x)?.[Q]===Z)return;NX(x,Q,Z),xH0()}function i$(x,Z="codex"){return Q5.get(x)?.[Z]??null}function Ou(){try{let x=JSON.parse(p2(Tz,"utf8"));for(let[Z,Q]of Object.entries(x)){if(typeof Q==="string"&&Q.trim()){D3.set(Z,{provider:O7(Q),model:Q,effort:null});continue}if(!Q||typeof Q!=="object")continue;let J=Q.model;if(typeof J!=="string"||!J.trim())continue;let X=Q.provider,z=X==="claude"||X==="codex"?X:O7(J),Y=Q.effort,U=z==="claude"?e4(Y)?Y:null:B8(Y)?Y:null;D3.set(Z,{provider:z,model:J,effort:U})}u(`feishu: loaded ${D3.size} session→model bindings`)}catch{}}function YH0(){try{let x={};for(let[Z,Q]of D3)x[Z]=Q;Z5(kx,{recursive:!0}),J5(Tz,JSON.stringify(x,null,2))}catch(x){u(`feishu: save session-model-map failed: ${x}`)}}function Bu(x,Z,Q,J){let X=D3.get(x);if(X?.provider===Z&&X.model===Q&&X.effort===J)return;D3.set(x,{provider:Z,model:Q,effort:J}),YH0()}function vu(x){return D3.get(x)??null}function p$(x){try{J5(cY,JSON.stringify(x,null,2))}catch(Z){u(`feishu: write alive marker failed: ${Z}`)}}function Mu(){if(!tV0(cY))return[];try{let x=p2(cY,"utf8"),Z=JSON.parse(x);return Array.isArray(Z)?Z.filter((Q)=>typeof Q==="string"):[]}catch(x){return u(`feishu: read alive marker failed: ${x}`),[]}}function DX(x){let Z=h1.get(x);if(Z){let J=c1.get(Z);if(J&&J!==x)u(`feishu: chatIdForSession("${x}"): persisted binding ${Z} has cached name "${J}", using persisted binding`);return Z}let Q=[];for(let[J,X]of c1)if(X===x)Q.push(J);if(Q.length===1)return Q[0];if(Q.length>1)u(`feishu: chatIdForSession("${x}"): ${Q.length} candidates with no binding — [${Q.join(", ")}]`);return null}async function OX(){try{let x;do{let Z=await Xx.im.chat.list({params:{page_size:100,...x?{page_token:x}:{}}});for(let Q of Z.data?.items??[])if(Q.chat_id&&Q.name)c1.set(Q.chat_id,Q.name);x=Z.data?.page_token}while(x);u(`feishu: refreshed chat list — ${c1.size} groups`)}catch(x){u(`feishu: refresh chat list failed: ${x}`)}}async function s$(){let x=new Map,Z;do{let Q=await Xx.im.chat.list({params:{page_size:100,...Z?{page_token:Z}:{}}});if(Q.code&&Q.code!==0)throw Error(`feishu chat.list failed code=${Q.code} msg=${Q.msg}`);for(let J of Q.data?.items??[]){if(!J.chat_id||!J.name)continue;if(J.chat_status&&J.chat_status!=="normal")continue;c1.set(J.chat_id,J.name);let X=x.get(J.name)??[];X.push(J.chat_id),x.set(J.name,X)}Z=Q.data?.page_token}while(Z);return x}async function Su(x){let Z=h1.get(x);if(Z&&c1.get(Z)===x){let z=await QH0(Z);if(z.name===x&&JH0(z.status))return Z;c1.delete(Z),d$(x)}let J=(await s$()).get(x)??[];if(J.length===0)return null;let X=h1.get(x);if(X&&J.includes(X))return X;if(J.length===1)return J[0];throw Error(`multiple Feishu groups named "${x}": ${J.join(", ")}`)}async function Ru(x,Z){if(!Z)throw Error("missing sender open_id; cannot add user to worktree group");let Q=await Su(x);if(Q){let z=await ZH0(Q,Z);return LX(x,Q),{chatId:Q,created:!1,joined:z}}let J=await Xx.im.chat.create({params:{user_id_type:"open_id",uuid:Hu()},data:{name:x,user_id_list:[Z],group_message_type:"chat"}});if(J.code&&J.code!==0)throw Error(`feishu chat.create failed code=${J.code} msg=${J.msg}`);let X=J.data?.chat_id;if(!X)throw Error("feishu chat.create returned no chat_id");return c1.set(X,x),LX(x,X),{chatId:X,created:!0,joined:!0}}async function Cu(x){let Z=await Su(x);if(!Z)return d$(x),{chatId:null,disbanded:!1};let Q=await Xx.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 c1.delete(Z),d$(x),{chatId:Z,disbanded:!0}}async function ZH0(x,Z){let Q;do{let X=await Xx.im.chatMembers.get({path:{chat_id:x},params:{member_id_type:"open_id",page_size:100,...Q?{page_token:Q}:{}}});if(X.code&&X.code!==0)throw Error(`feishu chatMembers.get failed code=${X.code} msg=${X.msg}`);for(let z of X.data?.items??[])if(z.member_id===Z)return!1;Q=X.data?.page_token}while(Q);let J=await Xx.im.chatMembers.create({path:{chat_id:x},params:{member_id_type:"open_id"},data:{id_list:[Z]}});if(J.code&&J.code!==0)throw Error(`feishu chatMembers.create failed code=${J.code} msg=${J.msg}`);return!0}async function ju(x){try{let Z=await U6(),J=await(await fetch(`https://open.feishu.cn/open-apis/im/v1/chats/${encodeURIComponent(x)}`,{headers:{Authorization:`Bearer ${Z}`}})).json();if(J?.code!==0)return u(`feishu: fetchChatName ${x} code=${J?.code} msg=${J?.msg}`),null;let X=J.data?.name;if(typeof X==="string"&&X)return c1.set(x,X),u(`feishu: fetchChatName ${x} → "${X}" (point lookup)`),X;return u(`feishu: fetchChatName ${x} — chat has no name (unnamed group?)`),null}catch(Z){return u(`feishu: fetchChatName ${x} failed: ${Z}`),null}}async function Iu(x,Z,Q,J){let X=Hu(),z=null;for(let Y=0;Y<i2.length;Y++){if(i2[Y]>0)await new Promise((U)=>setTimeout(U,i2[Y]));try{let U=await Xx.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:Z,msg_type:Q,content:J,uuid:X}});if(U?.code&&U.code!==0)return u(`feishu: send${x==="text"?"Text":"Card"} rejected chat=${Z} code=${U.code} msg=${U.msg}`),null;return U?.data?.message_id??null}catch(U){z=U,u(`feishu: send${x==="text"?"Text":"Card"} attempt ${Y+1}/${i2.length} chat=${Z} failed: ${U}`)}}return u(`feishu: send${x==="text"?"Text":"Card"} chat=${Z} EXHAUSTED ${i2.length} retries: ${z}`),null}async function QH0(x){let Z=await Xx.im.chat.get({path:{chat_id:x}});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 JH0(x){return x===null||x==="normal"}async function c0(x,Z){return Iu("text",x,"text",JSON.stringify({text:Z}))}async function ix(x,Z){return Iu("card",x,"interactive",JSON.stringify(Z))}async function Px(x,Z){try{let Q=await U6(),X=await(await fetch("https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({receive_id:x,msg_type:"text",content:JSON.stringify({text:Z})})})).json();if(X?.code!==0)return u(`feishu: sendTextRaw rejected chat=${x} code=${X?.code} msg=${X?.msg}`),null;return X.data?.message_id??null}catch(Q){return u(`feishu: sendTextRaw chat=${x} failed: ${Q}`),null}}async function c8(x,Z){if(!x)return null;try{return(await Xx.im.messageReaction.create({path:{message_id:x},data:{reaction_type:{emoji_type:Z}}}))?.data?.reaction_id??null}catch(Q){return u(`feishu: addReaction ${Z} on ${x} failed: ${Q}`),null}}async function B3(x,Z){if(!x||!Z)return;try{await Xx.im.messageReaction.delete({path:{message_id:x,reaction_id:Z}})}catch(Q){u(`feishu: deleteReaction ${Z} on ${x} failed: ${Q}`)}}async function X5(x,Z){if(!x){u("feishu: urgentApp skip — missing messageId");return}if(Z.length===0){u(`feishu: urgentApp skip — empty openIds (msg=${x})`);return}let Q=await U6(),J=`https://open.feishu.cn/open-apis/im/v1/messages/${x}/urgent_app?user_id_type=open_id`;try{let z=await(await fetch(J,{method:"PATCH",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({user_id_list:Z})})).json();if(z?.code!==0){u(`feishu: urgentApp ${x} code=${z?.code} msg=${z?.msg}`);return}let Y=z.data?.invalid_user_id_list??[],U=Z.length-Y.length;u(`feishu: urgentApp ${x} ok — delivered=${U}${Y.length?` invalid=${Y.length}`:""}`)}catch(X){u(`feishu: urgentApp ${x} failed: ${X}`)}}async function s2(x,Z,Q,J){try{let X=await U6(),z=`https://open.feishu.cn/open-apis/im/v1/messages/${x}/resources/${Z}?type=${Q}`,Y=await fetch(z,{headers:{Authorization:`Bearer ${X}`}});if(!Y.ok){u(`feishu: download ${Q} HTTP ${Y.status}: ${(await Y.text()).slice(0,200)}`);return}let U=Buffer.from(await Y.arrayBuffer());Z5(cz,{recursive:!0});let W=J?J.replace(/[^a-zA-Z0-9._-]/g,"_"):`${Z.replace(/[^a-zA-Z0-9_-]/g,"_")}.png`,H=l$(cz,`${Date.now()}-${W}`);return J5(H,U),u(`feishu: downloaded ${Q} ${H} (${U.length}B)`),H}catch(X){u(`feishu: download ${Q} failed: ${X instanceof Error?X.message:X}`);return}}function KH0(x){return zH0.has(aV0(x).toLowerCase())}async function WH0(x){let Z=await U6(),Q=new Blob([await Gu(x)]),J=new FormData;J.append("image_type","message"),J.append("image",Q,L3(x));let z=await(await fetch("https://open.feishu.cn/open-apis/im/v1/images",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:J})).json();if(z?.code!==0)return u(`feishu: uploadImage ${x} code=${z.code} msg=${z.msg}`),null;return z.data?.image_key??null}async function VH0(x){let Z=await U6(),Q=new Blob([await Gu(x)]),J=new FormData;J.append("file_type","stream"),J.append("file_name",L3(x)),J.append("file",Q,L3(x));let z=await(await fetch("https://open.feishu.cn/open-apis/im/v1/files",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:J})).json();if(z?.code!==0)return u(`feishu: uploadFile ${x} code=${z.code} msg=${z.msg}`),null;return z.data?.file_key??null}async function HH0(x,Z){try{let Q=await Xx.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:x,msg_type:"image",content:JSON.stringify({image_key:Z})}});if(Q?.code&&Q.code!==0)return u(`feishu: sendImage rejected chat=${x} code=${Q.code} msg=${Q.msg}`),null;return Q?.data?.message_id??null}catch(Q){return u(`feishu: sendImage failed chat=${x}: ${Q}`),null}}async function GH0(x,Z){try{let Q=await Xx.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:x,msg_type:"file",content:JSON.stringify({file_key:Z})}});if(Q?.code&&Q.code!==0)return u(`feishu: sendFile rejected chat=${x} code=${Q.code} msg=${Q.msg}`),null;return Q?.data?.message_id??null}catch(Q){return u(`feishu: sendFile failed chat=${x}: ${Q}`),null}}async function Tu(x,Z){try{let J=eV0(Z);if(!J.isFile())return await c0(x,`❌ 出站文件: 路径不是文件 — ${Z}`),!1;if(J.size>XH0)return await c0(x,`❌ 出站文件: ${L3(Z)} 超过 30 MB (${(J.size/1024/1024).toFixed(1)} MB)`),!1}catch(J){return await c0(x,`❌ 出站文件: 无法读取 ${Z} (${J})`),!1}let Q=KH0(Z);try{if(Q){let J=await WH0(Z);if(!J)return await c0(x,`❌ 出站图片上传失败: ${L3(Z)}`),!1;return await HH0(x,J)!=null}else{let J=await VH0(Z);if(!J)return await c0(x,`❌ 出站文件上传失败: ${L3(Z)}`),!1;return await GH0(x,J)!=null}}catch(J){return u(`feishu: uploadAndSend ${Z} failed: ${J}`),await c0(x,`❌ 出站文件异常: ${L3(Z)} — ${J}`),!1}}function cu(x){Z5(x,{recursive:!0}),u(`feishu: provisioned ${x}`);let Z=l$(zu(),".codex","config.toml");try{Z5(l$(zu(),".codex"),{recursive:!0});let Q="";try{Q=p2(Z,"utf8")}catch{}let J=`[projects.${JSON.stringify(x)}]`;if(!Q.includes(J)){let X=Q.trimEnd();Q=`${X}${X?`
232
232
 
233
233
  `:""}${J}
234
234
  trust_level = "trusted"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leviyuan/lodestar",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },