@leviyuan/lodestar 0.13.3 → 0.13.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  `)+`
230
230
 
231
- `:"";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));k(`claude-agent-process: sendUserText failed: ${z.message}`),this.failTurnStart(z)}}sendInterrupt(){this.query?.interrupt().catch((x)=>k(`claude-agent-process: interrupt failed: ${x}`))}sendPermissionResponse(x,Z,Q){let J=this.pendingPermissions.get(String(x));if(!J){k(`claude-agent-process: permission response for unknown request ${x}`);return}if(this.pendingPermissions.delete(String(x)),J.cleanup?.(),Z==="allow")J.resolve({behavior:"allow",updatedInput:Q?.updatedInput??{}});else J.resolve({behavior:"deny",message:Q?.denyMessage??""})}sendToolResult(x,Z,Q=!1){k("claude-agent-process: sendToolResult ignored; Claude Agent SDK executes built-in tools internally")}sendHookResponse(x,Z={}){k("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();if(!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");return(await this.query.supportedModels()).map(r$0)}async setModelSettings(x,Z){let Q=aU(x);if(!L3(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(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?c3(x):"claude:default",this.lastEffort=Z}async setModel(x){await this.setModelSettings(x,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((x,Z)=>{let J=!1,X=()=>{clearTimeout(z),this.off("context_compacted",Y),this.off("result",G)},z=setTimeout(()=>{if(J)return;J=!0,X(),Z(Error("claude /compact timed out (no compact_boundary, no result)"))},600000),Y=()=>{if(J)return;J=!0,X(),x()},G=()=>{if(J)return;J=!0,X(),Z(new J2)};this.on("context_compacted",Y),this.on("result",G)})}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(`
231
+ `:"";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));k(`claude-agent-process: sendUserText failed: ${z.message}`),this.failTurnStart(z)}}sendInterrupt(){this.query?.interrupt().catch((x)=>k(`claude-agent-process: interrupt failed: ${x}`))}sendPermissionResponse(x,Z,Q){let J=this.pendingPermissions.get(String(x));if(!J){k(`claude-agent-process: permission response for unknown request ${x}`);return}if(this.pendingPermissions.delete(String(x)),J.cleanup?.(),Z==="allow")J.resolve({behavior:"allow",updatedInput:Q?.updatedInput??{}});else J.resolve({behavior:"deny",message:Q?.denyMessage??""})}sendToolResult(x,Z,Q=!1){k("claude-agent-process: sendToolResult ignored; Claude Agent SDK executes built-in tools internally")}sendHookResponse(x,Z={}){k("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();if(!this.query)throw Error("claude-agent-process: SDK query not initialized (sendInitialize failed or not called)");return(await this.query.supportedModels()).map(r$0)}async setModelSettings(x,Z){let Q=aU(x);if(!L3(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(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?c3(x):"claude:default",this.lastEffort=Z}async setModel(x){await this.setModelSettings(x,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((x,Z)=>{let J=!1,X=()=>{clearTimeout(z),this.off("context_compacted",Y),this.off("assistant_text",G)},z=setTimeout(()=>{if(J)return;J=!0,X(),Z(Error("claude /compact 超时(10min 内无 compact_boundary 也无 Not enough 文案)"))},600000),Y=()=>{if(J)return;J=!0,X(),x()},G=(K)=>{if(J)return;if((K?.text??"").includes("Not enough messages to compact"))J=!0,X(),Z(new J2)};this.on("context_compacted",Y),this.on("assistant_text",G)})}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(`
232
232
  `))}canUseTool(x,Z,Q){if(x!=="AskUserQuestion")return Promise.resolve({behavior:"allow",updatedInput:Z});let J=YF0(Z);if(J.length===0)return k("claude-agent-process: AskUserQuestion 无有效 questions — allow 原样"),Promise.resolve({behavior:"allow",updatedInput:Z});let X={...Z,questions:J},z=`claude_perm_${++this.requestCounter}`,Y=Q.toolUseID||z,G={request_id:z,tool_name:"AskUserQuestion",input:X,tool_use_id:Y},K=new Promise((H)=>{let W=(N)=>{Q.signal.removeEventListener("abort",L),H(N)},L=()=>{if(!this.pendingPermissions.delete(z))return;W({behavior:"deny",message:"aborted"})};Q.signal.addEventListener("abort",L,{once:!0}),this.pendingPermissions.set(z,{kind:"dialog",resolve:W,request:G})});return this.emitToolUseOnce(Y,"AskUserQuestion",X,null),this.emit("can_use_tool",G),K}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));k(`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);k(`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:k(`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=c3(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":k(`claude-agent-process: api retry attempt=${x.attempt}/${x.max_retries} status=${x.error_status} error=${x.error}`);return;case"permission_denied":k(`claude-agent-process: permission denied ${x.tool_name} ${x.tool_use_id}: ${x.message}`);return;case"task_started":this.emit("bg_task_started",{task_id:String(x.task_id??""),tool_use_id:typeof x.tool_use_id==="string"?x.tool_use_id:void 0,task_type:typeof x.task_type==="string"?x.task_type:void 0,description:String(x.description??""),subagent_type:typeof x.subagent_type==="string"?x.subagent_type:void 0,workflow_name:typeof x.workflow_name==="string"?x.workflow_name:void 0,prompt:typeof x.prompt==="string"?x.prompt:void 0});return;case"task_progress":this.emit("bg_task_progress",{task_id:String(x.task_id??""),description:typeof x.description==="string"?x.description:void 0,subagent_type:typeof x.subagent_type==="string"?x.subagent_type:void 0,usage:x.usage,last_tool_name:typeof x.last_tool_name==="string"?x.last_tool_name:void 0,summary:typeof x.summary==="string"?x.summary:void 0});return;case"task_updated":this.emit("bg_task_updated",{task_id:String(x.task_id??""),patch:x.patch&&typeof x.patch==="object"?x.patch:{}});return;case"task_notification":this.emit("bg_task_settled",{task_id:String(x.task_id??""),tool_use_id:typeof x.tool_use_id==="string"?x.tool_use_id:void 0,status:x.status==="completed"||x.status==="failed"||x.status==="stopped"?x.status:"completed",summary:typeof x.summary==="string"?x.summary:void 0,usage:x.usage});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=c3(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=s$0(J.text);if(X){if(this.pendingServerToolInputs.push(X),this.pendingServerToolInputs.length>20)this.pendingServerToolInputs.shift()}if(o$0(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??{},x.parent_tool_use_id??null);else if(J.type==="server_tool_use"&&typeof J.id==="string"&&typeof J.name==="string")this.emitToolUseOnce(J.id,p$0(J.name),{tool:J.name,input:this.serverToolInput(J.name,J.input??{})},x.parent_tool_use_id??null);else if(J.type==="tool_result"&&typeof J.tool_use_id==="string")this.emitToolResultOnce(J.tool_use_id,i$0(J.content),J.is_error===!0,x.parent_tool_use_id??null)}}emitToolUseOnce(x,Z,Q,J){if(this.emittedToolUseIds.has(x))return;this.emittedToolUseIds.add(x),this.emit("tool_use",{id:x,name:Z,input:Q,parentToolUseId:J})}serverToolInput(x,Z){let Q=SY(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,J){if(this.emittedToolResultIds.has(x))return;this.emittedToolResultIds.add(x),this.emit("tool_result",{tool_use_id:x,content:Z,is_error:Q,parentToolUseId:J})}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=Ju(Q.content),z=J&&typeof J==="object"?[typeof J.stdout==="string"?J.stdout:"",typeof J.stderr==="string"?J.stderr:""].filter(Boolean).join(`
233
233
  `):"",Y=X||z;this.emitToolResultOnce(Q.tool_use_id,Y,Q.is_error===!0||J?.interrupted===!0,x.parent_tool_use_id??null)}}handleResultMessage(x){if(typeof x.session_id==="string"&&x.session_id)this.sessionId=x.session_id;this.turnActive=!1;let Z=m$0(x.usage),Q=x.modelUsage??x.model_usage,J=n$0(Q);if(!Z&&!J.usage)k(`claude-agent-process: result usage missing rootKeys=${xL(x).join(",")||"-"} usageKeys=${xL(x.usage).join(",")||"-"} modelUsageKeys=${xL(Q).join(",")||"-"}`);if(this.lastUsage=Z,J.usage)this.cumulativeUsageFromResults=Yz(J.usage),this.lastTotalUsage=Yz(J.usage);else if(Z)this.cumulativeUsageFromResults=d$0(this.cumulativeUsageFromResults,Z),this.lastTotalUsage=Yz(this.cumulativeUsageFromResults);else this.lastTotalUsage=this.cumulativeUsageFromResults?Yz(this.cumulativeUsageFromResults):null;if(J.contextWindow!=null){let G=ew(this.opts.model),K=RY.get(G)??0;if(J.contextWindow>K)RY.set(G,J.contextWindow),k(`claude-agent-process: SDK contextWindow ${J.contextWindow} (global max for ${G}, prev ${K||"-"})`);else if(J.contextWindow<(RY.get(G)??0))k(`claude-agent-process: SDK contextWindow ${J.contextWindow} ignored (global max ${RY.get(G)} locked for ${G})`)}this.lastContextWindow=RY.get(ew(this.opts.model))??J.contextWindow??null;let X=_$0(this.opts.workDir,this.sessionId??""),z=l$0(X);if(this.lastContextTokens=tw(z)??(Zz(X)?tw(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:x.uuid});let Y=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:Y,is_error:x.is_error===!0||Y!=="success"},this.emit("result",{subtype:Y,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 JF0}from"node:crypto";async function Xu(x){let Z=await H8("feishu chat.get",()=>K1.im.chat.get({path:{chat_id:x},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)W8("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 zu(x,Z){let Q=await H8("feishu tasklist.create",()=>K1.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)W8("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 Wu(x){let Z=await H8("feishu tasklist.delete",()=>K1.task.v2.tasklist.delete({path:{tasklist_guid:x}}));if(Z.code&&Z.code!==0)W8("feishu tasklist.delete",Z)}async function Qz(x){let Z=[],Q;do{let J=await H8("feishu section.list",()=>K1.task.v2.section.list({params:{resource_type:"tasklist",resource_id:x,page_size:50,...Q?{page_token:Q}:{}}}));if(J.code&&J.code!==0)W8("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 Ku(x){let Z=await H8("feishu section.create",()=>K1.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)W8("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 zL(x){let Z=await H8("feishu section.get",()=>K1.task.v2.section.get({path:{section_guid:x},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)W8("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 Vu(x,Z){let Q=await H8("feishu section.patch",()=>K1.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)W8("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 Hu(x){let Z=await H8("feishu section.delete",()=>K1.task.v2.section.delete({path:{section_guid:x}}));if(Z.code&&Z.code!==0)W8("feishu section.delete",Z)}async function q3(x,Z){let Q=[],J;do{let X=await H8("feishu section.tasks",()=>K1.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)W8("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 Gu(x,Z){let Q=[],J;do{let X=await H8("feishu tasklist.tasks",()=>K1.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)W8("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 $u(x){let Z=`lodestar-default-section-discovery-${Date.now()}-${JF0().slice(0,8)}`,Q="";try{let J=await H8("feishu task.create",()=>K1.task.v2.task.create({params:{user_id_type:"open_id"},data:{summary:Z,tasklists:[{tasklist_guid:x}]}}));if(J.code&&J.code!==0)W8("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((K)=>K.tasklist_guid===x)?.section_guid;if(z)return z;let G=(await Jz(Q)).tasklists?.find((K)=>K.tasklist_guid===x)?.section_guid;if(!G)throw Error(`failed to discover default section guid for tasklist ${x}`);return G}finally{if(Q)await XF0(Q)}}async function XF0(x){let Z=await H8("feishu task.delete",()=>K1.task.v2.task.delete({path:{task_guid:x}}));if(Z.code&&Z.code!==0)W8("feishu task.delete",Z)}async function Jz(x){let Z=await H8("feishu task.get",()=>K1.task.v2.task.get({path:{task_guid:x},params:{user_id_type:"open_id"}}));if(Z.code&&Z.code!==0)W8("feishu task.get",Z);let Q=Z.data?.task;if(!Q)throw Error(`feishu task.get returned no task: ${x}`);return Q}async function Fu(x){let Z=[],Q;do{let J=await H8("feishu comment.list",()=>K1.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)W8("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 Ex(x,Z){let Q=await H8("feishu comment.create",()=>K1.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)W8("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 Xz(x,Z,Q){let J=await H8("feishu task.addTasklist",()=>K1.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)W8("feishu task.addTasklist",J)}function zF0(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,G=Array.isArray(Y)?Y.map((K)=>K?.scope??K?.subject??K?.name??K).filter(Boolean).join(", "):"";return`${x} failed code=${X??"unknown"} msg=${z}${G?` missing_scopes=${G}`:""}`}async function H8(x,Z){try{return await Z()}catch(Q){W8(x,Q)}}function W8(x,Z){throw Error(zF0(x,Z))}var Uu=R0(()=>{h1()});import{execSync as vu}from"node:child_process";import{randomUUID as Mu}from"node:crypto";import{existsSync as WF0,mkdirSync as kx,readFileSync as b5,statSync as Ru,writeFileSync as gx}from"node:fs";import{readFile as Cu}from"node:fs/promises";import{homedir as Lu}from"node:os";import{basename as bx,extname as KF0,join as WL}from"node:path";function VL(x){return Z1.projects[x]}async function E3(){if(zz&&Date.now()<Nu)return zz;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:Su,app_secret:ju})})).json();if(!Z.tenant_access_token)throw Error("feishu: failed to obtain tenant token");return zz=Z.tenant_access_token,Nu=Date.now()+((Z.expire??7200)-60)*1000,zz}function Iu(){try{let x=JSON.parse(b5(jW,"utf8"));for(let[Z,Q]of Object.entries(x))if(typeof Q==="string")s8.set(Z,Q);k(`feishu: loaded ${s8.size} session→chat bindings`)}catch{}}function Tu(){try{let x={};for(let[Z,Q]of s8)x[Z]=Q;kx(C1,{recursive:!0}),gx(jW,JSON.stringify(x,null,2))}catch(x){k(`feishu: save session-chat-map failed: ${x}`)}}function Kz(x,Z){if(s8.get(x)===Z)return;let Q=s8.get(x);s8.set(x,Z),Tu(),k(`feishu: bound session "${x}" → ${Z}${Q?` (was ${Q})`:""}`)}function KL(x){let Z=s8.get(x);if(!Z)return;s8.delete(x),Tu(),k(`feishu: unbound session "${x}" from ${Z}`)}function Wz(x,Z,Q){let J=E5.get(x)??{};J[Z]=Q,E5.set(x,J)}function cu(){try{let x=JSON.parse(b5(IW,"utf8"));for(let[Z,Q]of Object.entries(x)){if(typeof Q==="string"&&Q.trim()){Wz(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()){Wz(Z,X,z);continue}for(let Y of["codex","claude"]){let G=J[Y];if(typeof G==="string"&&G.trim())Wz(Z,Y,G)}}k(`feishu: loaded ${E5.size} session→resume bindings`)}catch{}}function VF0(){try{let x={};for(let[Z,Q]of E5)x[Z]={...Q};kx(C1,{recursive:!0}),gx(IW,JSON.stringify(x,null,2))}catch(x){k(`feishu: save session-resume-map failed: ${x}`)}}function qu(x,Z,Q="codex"){if(E5.get(x)?.[Q]===Z)return;Wz(x,Q,Z),VF0()}function HL(x,Z="codex"){return E5.get(x)?.[Z]??null}function Au(){try{let x=JSON.parse(b5(TW,"utf8")),Z=0;for(let[Q,J]of Object.entries(x)){if(!Array.isArray(J))continue;let X=J.filter((z)=>z&&typeof z.uuid==="string"&&typeof z.ts==="number").map((z)=>({uuid:String(z.uuid),sid:String(z.sid??""),preview:String(z.preview??""),ts:Number(z.ts),writes:Array.isArray(z.writes)?z.writes.filter((Y)=>Y&&typeof Y.path==="string").map((Y)=>({tool:String(Y.tool??"Write"),path:String(Y.path),body:String(Y.body??"")})).filter((Y)=>Y.path!==""||Y.body!==""):[]}));if(X.length)w4.set(Q,X),Z+=X.length}k(`feishu: loaded ${Z} turn anchors across ${w4.size} sessions`)}catch(x){if(x?.code!=="ENOENT")k(`feishu: load session-turns-map failed: ${x?.message??x}`)}}function GL(){try{let x={};for(let[Z,Q]of w4)x[Z]=Q;kx(C1,{recursive:!0}),gx(TW,JSON.stringify(x,null,2))}catch(x){k(`feishu: save session-turns-map failed: ${x}`)}}function Eu(x,Z){let Q=w4.get(x)??[];if(Q.push(Z),Q.length>Du)Q.splice(0,Q.length-Du);w4.set(x,Q),GL()}function IY(x){return w4.get(x)??[]}function bu(x,Z){let Q=w4.get(x);if(!Q||Q.length<=Z)return;w4.set(x,Q.slice(0,Z)),GL()}function wx(x){if(!w4.has(x))return;w4.delete(x),GL()}function ux(x){return Ou.test(x)?x.replace(Ou,""):null}function $L(x){let Z=new Date,Q=(Y)=>String(Y).padStart(2,"0"),J=`${Q(Z.getMonth()+1)}${Q(Z.getDate())}-${Q(Z.getHours())}${Q(Z.getMinutes())}`,X=new Set([...M8.values(),...w4.keys()]),z=`${x}*${J}`;for(let Y=2;X.has(z);Y++)z=`${x}*${J}-${Y}`;return z}function ku(){try{let x=JSON.parse(b5(cW,"utf8"));for(let[Z,Q]of Object.entries(x)){if(typeof Q==="string"&&Q.trim()){A3.set(Z,{provider:d7(Q),model:Q,effort:null});continue}if(!Q||typeof Q!=="object")continue;let{model:J,provider:X}=Q,z=X==="claude"||X==="codex"?X:typeof J==="string"&&J.trim()?d7(J):"claude",Y=typeof J==="string"&&J.trim()?J:null;if(z==="claude"&&!Y)continue;let{effort:G,tokenSourceId:K}=Q,H=typeof K==="string"&&K.trim()?K.trim():null,W=z==="claude"?L3(G)?G:null:Y6(G)?G:null;A3.set(Z,{provider:z,model:Y,effort:W,...H?{tokenSourceId:H}:{}})}k(`feishu: loaded ${A3.size} session→model bindings`)}catch{}}function HF0(){try{let x={};for(let[Z,Q]of A3)x[Z]=Q;kx(C1,{recursive:!0}),gx(cW,JSON.stringify(x,null,2))}catch(x){k(`feishu: save session-model-map failed: ${x}`)}}function gu(x,Z,Q,J,X){let z=A3.get(x);if(z?.provider===Z&&z.model===Q&&z.effort===J&&(z.tokenSourceId??null)===(X??null))return;A3.set(x,{provider:Z,model:Q,effort:J,...X?{tokenSourceId:X}:{}}),HF0()}function Pu(x){let Z=A3.get(x);if(Z)return Z;let Q=ux(x);return Q?A3.get(Q)??null:null}function FL(x){try{gx(UZ,JSON.stringify(x,null,2))}catch(Z){k(`feishu: write alive marker failed: ${Z}`)}}function wu(){if(!WF0(UZ))return[];try{let x=b5(UZ,"utf8"),Z=JSON.parse(x);return Array.isArray(Z)?Z.filter((Q)=>typeof Q==="string"):[]}catch(x){return k(`feishu: read alive marker failed: ${x}`),[]}}function TY(x){let Z=s8.get(x);if(Z){let J=M8.get(Z);if(J&&J!==x)k(`feishu: chatIdForSession("${x}"): persisted binding ${Z} has cached name "${J}", using persisted binding`);return Z}let Q=[];for(let[J,X]of M8)if(X===x)Q.push(J);if(Q.length===1)return Q[0];if(Q.length>1)k(`feishu: chatIdForSession("${x}"): ${Q.length} candidates with no binding — [${Q.join(", ")}]`);return null}async function Vz(){try{let x;do{let Z=await K1.im.chat.list({params:{page_size:100,...x?{page_token:x}:{}}});for(let Q of Z.data?.items??[])if(Q.chat_id&&Q.name)M8.set(Q.chat_id,Q.name);x=Z.data?.page_token}while(x);k(`feishu: refreshed chat list — ${M8.size} groups`)}catch(x){k(`feishu: refresh chat list failed: ${x}`)}}async function UL(){let x=new Map,Z;do{let Q=await K1.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;M8.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 uu(x){let Z=s8.get(x);if(Z&&M8.get(Z)===x){let z=await $F0(Z);if(z.name===x&&FF0(z.status))return Z;M8.delete(Z),KL(x)}let J=(await UL()).get(x)??[];if(J.length===0)return null;let X=s8.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 Hz(x,Z){if(!Z)throw Error("missing sender open_id; cannot add user to worktree group");let Q=await uu(x);if(Q){let z=await GF0(Q,Z);return Kz(x,Q),{chatId:Q,created:!1,joined:z}}let J=await K1.im.chat.create({params:{user_id_type:"open_id",uuid:Mu()},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 M8.set(X,x),Kz(x,X),{chatId:X,created:!0,joined:!0}}async function cY(x){let Z=await uu(x);if(!Z)return KL(x),{chatId:null,disbanded:!1};let Q=await K1.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 M8.delete(Z),KL(x),{chatId:Z,disbanded:!0}}async function GF0(x,Z){let Q;do{let X=await K1.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 K1.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 fu(x){try{let Z=await E3(),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 k(`feishu: fetchChatName ${x} code=${J?.code} msg=${J?.msg}`),null;let X=J.data?.name;if(typeof X==="string"&&X)return M8.set(x,X),k(`feishu: fetchChatName ${x} → "${X}" (point lookup)`),X;return k(`feishu: fetchChatName ${x} — chat has no name (unnamed group?)`),null}catch(Z){return k(`feishu: fetchChatName ${x} failed: ${Z}`),null}}async function yu(x,Z,Q,J){let X=Mu(),z=null;for(let Y=0;Y<jY.length;Y++){if(jY[Y]>0)await new Promise((G)=>setTimeout(G,jY[Y]));try{let G=await K1.im.message.create({params:{receive_id_type:"chat_id"},data:{receive_id:Z,msg_type:Q,content:J,uuid:X}});if(G?.code&&G.code!==0)return k(`feishu: send${x==="text"?"Text":"Card"} rejected chat=${Z} code=${G.code} msg=${G.msg}`),null;return G?.data?.message_id??null}catch(G){z=G,k(`feishu: send${x==="text"?"Text":"Card"} attempt ${Y+1}/${jY.length} chat=${Z} failed: ${G}`)}}return k(`feishu: send${x==="text"?"Text":"Card"} chat=${Z} EXHAUSTED ${jY.length} retries: ${z}`),null}async function $F0(x){let Z=await K1.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 FF0(x){return x===null||x==="normal"}async function W0(x,Z){return yu("text",x,"text",JSON.stringify({text:Z}))}async function M1(x,Z){return yu("card",x,"interactive",JSON.stringify(Z))}async function fx(x,Z){let Q=await K1.im.v1.message.patch({path:{message_id:x},data:{content:JSON.stringify(Z)}});if(Q?.code&&Q.code!==0)throw Error(`feishu message.patch failed code=${Q.code} msg=${Q.msg}`)}async function R1(x,Z){try{let Q=await E3(),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 k(`feishu: sendTextRaw rejected chat=${x} code=${X?.code} msg=${X?.msg}`),null;return X.data?.message_id??null}catch(Q){return k(`feishu: sendTextRaw chat=${x} failed: ${Q}`),null}}async function k8(x,Z){if(!x)return null;try{return(await K1.im.messageReaction.create({path:{message_id:x},data:{reaction_type:{emoji_type:Z}}}))?.data?.reaction_id??null}catch(Q){return k(`feishu: addReaction ${Z} on ${x} failed: ${Q}`),null}}async function u4(x,Z){if(!x||!Z)return;try{await K1.im.messageReaction.delete({path:{message_id:x,reaction_id:Z}})}catch(Q){k(`feishu: deleteReaction ${Z} on ${x} failed: ${Q}`)}}async function k5(x,Z){if(!x){k("feishu: urgentApp skip — missing messageId");return}if(Z.length===0){k(`feishu: urgentApp skip — empty openIds (msg=${x})`);return}let Q=await E3(),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){k(`feishu: urgentApp ${x} code=${z?.code} msg=${z?.msg}`);return}let Y=z.data?.invalid_user_id_list??[],G=Z.length-Y.length;k(`feishu: urgentApp ${x} ok — delivered=${G}${Y.length?` invalid=${Y.length}`:""}`)}catch(X){k(`feishu: urgentApp ${x} failed: ${X}`)}}async function qY(x,Z,Q,J){try{let X=await E3(),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){k(`feishu: download ${Q} HTTP ${Y.status}: ${(await Y.text()).slice(0,200)}`);return}let G=Buffer.from(await Y.arrayBuffer());kx(qW,{recursive:!0});let K=J?J.replace(/[^a-zA-Z0-9._-]/g,"_"):`${Z.replace(/[^a-zA-Z0-9_-]/g,"_")}.png`,H=WL(qW,`${Date.now()}-${K}`);return gx(H,G),k(`feishu: downloaded ${Q} ${H} (${G.length}B)`),H}catch(X){k(`feishu: download ${Q} failed: ${X instanceof Error?X.message:X}`);return}}function LF0(x){return UF0.has(KF0(x).toLowerCase())}async function mu(x){let Z=await E3(),Q=new Blob([await Cu(x)]),J=new FormData;J.append("image_type","message"),J.append("image",Q,bx(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 k(`feishu: uploadImage ${x} code=${z.code} msg=${z.msg}`),null;return z.data?.image_key??null}async function _u(x){try{let Z=Ru(x);if(!Z.isFile())return k(`feishu: uploadImageKey not a file — ${x}`),null;if(Z.size>hu)return k(`feishu: uploadImageKey oversize — ${x} (${(Z.size/1024/1024).toFixed(1)} MB)`),null}catch(Z){return k(`feishu: uploadImageKey stat failed — ${x}: ${Z}`),null}return mu(x)}async function NF0(x){let Z=await E3(),Q=new Blob([await Cu(x)]),J=new FormData;J.append("file_type","stream"),J.append("file_name",bx(x)),J.append("file",Q,bx(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 k(`feishu: uploadFile ${x} code=${z.code} msg=${z.msg}`),null;return z.data?.file_key??null}async function DF0(x,Z){try{let Q=await K1.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 k(`feishu: sendImage rejected chat=${x} code=${Q.code} msg=${Q.msg}`),null;return Q?.data?.message_id??null}catch(Q){return k(`feishu: sendImage failed chat=${x}: ${Q}`),null}}async function OF0(x,Z){try{let Q=await K1.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 k(`feishu: sendFile rejected chat=${x} code=${Q.code} msg=${Q.msg}`),null;return Q?.data?.message_id??null}catch(Q){return k(`feishu: sendFile failed chat=${x}: ${Q}`),null}}async function lu(x,Z){try{let J=Ru(Z);if(!J.isFile())return await W0(x,`❌ 出站文件: 路径不是文件 — ${Z}`),!1;if(J.size>hu)return await W0(x,`❌ 出站文件: ${bx(Z)} 超过 30 MB (${(J.size/1024/1024).toFixed(1)} MB)`),!1}catch(J){return await W0(x,`❌ 出站文件: 无法读取 ${Z} (${J})`),!1}let Q=LF0(Z);try{if(Q){let J=await mu(Z);if(!J)return await W0(x,`❌ 出站图片上传失败: ${bx(Z)}`),!1;return await DF0(x,J)!=null}else{let J=await NF0(Z);if(!J)return await W0(x,`❌ 出站文件上传失败: ${bx(Z)}`),!1;return await OF0(x,J)!=null}}catch(J){return k(`feishu: uploadAndSend ${Z} failed: ${J}`),await W0(x,`❌ 出站文件异常: ${bx(Z)} — ${J}`),!1}}function nu(x){kx(x,{recursive:!0}),k(`feishu: provisioned ${x}`);let Z=WL(Lu(),".codex","config.toml");try{kx(WL(Lu(),".codex"),{recursive:!0});let Q="";try{Q=b5(Z,"utf8")}catch{}let J=`[projects.${JSON.stringify(x)}]`;if(!Q.includes(J)){let X=Q.trimEnd();Q=`${X}${X?`
234
234
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leviyuan/lodestar",
3
- "version": "0.13.3",
3
+ "version": "0.13.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },