blade-code 0.8.2 → 0.9.0
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/blade.js +2 -2
- package/dist/chunk-0abtfzm6.js +1 -0
- package/dist/chunk-0zkhjsbv.js +1 -0
- package/dist/chunk-119fhp5q.js +9 -0
- package/dist/{chunk-j77gyhpf.js → chunk-1rpgvk3r.js} +1 -1
- package/dist/{chunk-81p4kz0b.js → chunk-1v2n922p.js} +1 -1
- package/dist/{chunk-9xvnrq7m.js → chunk-2fbwmdvg.js} +2 -2
- package/dist/chunk-3qgj2y5r.js +1 -0
- package/dist/{chunk-887qxhn5.js → chunk-45bme7n9.js} +2 -2
- package/dist/{chunk-w11ht6f9.js → chunk-5jq01mg6.js} +2 -2
- package/dist/{chunk-p4yrmzyr.js → chunk-5nye3k5w.js} +1 -1
- package/dist/chunk-7pevqbfd.js +2 -0
- package/dist/chunk-8dqvnx7n.js +2 -0
- package/dist/chunk-8edsvxf3.js +1 -0
- package/dist/{chunk-11s7t9dp.js → chunk-8vemqfe4.js} +2 -2
- package/dist/{chunk-5fw9k1ff.js → chunk-8vtznxpq.js} +2 -2
- package/dist/chunk-936ft6kq.js +2 -0
- package/dist/chunk-9ax02vtg.js +22 -0
- package/dist/chunk-9qknesxs.js +6 -0
- package/dist/chunk-acegy4td.js +3 -0
- package/dist/chunk-aewrn5xp.js +1 -0
- package/dist/{chunk-fpdqvnmq.js → chunk-aq7wf2zt.js} +2 -2
- package/dist/{chunk-5ad4qmfj.js → chunk-ax7bx0j8.js} +1 -1
- package/dist/chunk-b10vr4xj.js +2 -0
- package/dist/{chunk-1x3846v7.js → chunk-bc6wbcrs.js} +1 -1
- package/dist/chunk-bfgm5k3e.js +1566 -0
- package/dist/chunk-cf3fhs7j.js +1 -0
- package/dist/chunk-d7y2mf7c.js +4 -0
- package/dist/chunk-e1586s4t.js +1 -0
- package/dist/chunk-enk621t7.js +98 -0
- package/dist/chunk-fpr6d8zc.js +2 -0
- package/dist/{chunk-fkaebj8c.js → chunk-gagt42k2.js} +1 -1
- package/dist/chunk-gdm1xzvp.js +2 -0
- package/dist/chunk-gm62cfjw.js +1 -0
- package/dist/chunk-h3bjmkvz.js +1 -0
- package/dist/{chunk-9b297mzh.js → chunk-j8en7x02.js} +1 -1
- package/dist/{chunk-6jq8h5s9.js → chunk-jyr9417h.js} +2 -2
- package/dist/chunk-mcnfbhpr.js +6 -0
- package/dist/{chunk-6x6zqjcs.js → chunk-mns8e65q.js} +1 -1
- package/dist/chunk-mpkr3s6b.js +3 -0
- package/dist/chunk-n9tgxfvw.js +615 -0
- package/dist/{chunk-w4xcmzjm.js → chunk-ppyg431d.js} +1 -1
- package/dist/chunk-qxhrzws6.js +1 -0
- package/dist/{chunk-y08szyf9.js → chunk-r6h7eja3.js} +20 -20
- package/dist/chunk-r8pjwjt6.js +1 -0
- package/dist/chunk-rmfk5f9m.js +2 -0
- package/dist/chunk-rrg9bw8r.js +25 -0
- package/dist/chunk-w3me85va.js +2 -0
- package/dist/{chunk-f3pvwxp8.js → chunk-wtxwny0p.js} +3 -3
- package/dist/{chunk-s1y8w68s.js → chunk-x40fkg4z.js} +2 -2
- package/dist/{chunk-0z5qe4m2.js → chunk-x548f12z.js} +1 -1
- package/dist/chunk-xtfzjb72.js +6 -0
- package/dist/{chunk-kne7h7p5.js → chunk-z0qxaky4.js} +1 -1
- package/dist/web/assets/{FilePreview-60E51igH.js → FilePreview-DpovIbME.js} +1 -1
- package/dist/web/assets/{MarkdownRenderer-DU7jPn9K.js → MarkdownRenderer-73wC_SGk.js} +1 -1
- package/dist/web/assets/{McpModal-CAMU6yrS.js → McpModal-CIpxuyTG.js} +1 -1
- package/dist/web/assets/{SettingsModal-Cjj8NUQy.js → SettingsModal-BBa1libe.js} +1 -1
- package/dist/web/assets/{SettingsStore-CjvkbtuZ.js → SettingsStore-C8YBWQPS.js} +1 -1
- package/dist/web/assets/{SkillsModal-Cyc2JAFj.js → SkillsModal-DArZ-nCX.js} +1 -1
- package/dist/web/assets/{TerminalPanel-DI-Ls-U8.js → TerminalPanel-BX7C7qiD.js} +1 -1
- package/dist/web/assets/index-Ch0eqSLM.css +1 -0
- package/dist/web/assets/index-DIWzaS2_.js +16 -0
- package/dist/web/index.html +2 -2
- package/package.json +2 -1
- package/dist/chunk-0g9cb41d.js +0 -3
- package/dist/chunk-1evg2hdd.js +0 -2
- package/dist/chunk-3wghk9bp.js +0 -1
- package/dist/chunk-4fye39a8.js +0 -2
- package/dist/chunk-510rwhx6.js +0 -1
- package/dist/chunk-6avkjdjc.js +0 -615
- package/dist/chunk-83dkggbx.js +0 -1
- package/dist/chunk-8epvwyg8.js +0 -6
- package/dist/chunk-8fp3q919.js +0 -24
- package/dist/chunk-9jkbykwq.js +0 -1
- package/dist/chunk-a83s9mww.js +0 -1
- package/dist/chunk-a90mfxv9.js +0 -3
- package/dist/chunk-btst30by.js +0 -6
- package/dist/chunk-e9t5ga1b.js +0 -1
- package/dist/chunk-eycs00af.js +0 -1577
- package/dist/chunk-gvf4gff0.js +0 -9
- package/dist/chunk-j14rn2dx.js +0 -22
- package/dist/chunk-kcjgbbec.js +0 -1
- package/dist/chunk-q223bq79.js +0 -1
- package/dist/chunk-qwfqp465.js +0 -2
- package/dist/chunk-rxjt7ma7.js +0 -2
- package/dist/chunk-x83a97eh.js +0 -1
- package/dist/chunk-yfcfx0zk.js +0 -6
- package/dist/chunk-zns65xsy.js +0 -2
- package/dist/web/assets/index-BC0ssrep.js +0 -16
- package/dist/web/assets/index-Ci6gCUjf.css +0 -1
package/dist/chunk-gvf4gff0.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{p as c}from"./chunk-qwfqp465.js";import{$ as q,C as B,K,M as j,P as h,R as T,S as A,U as b,Z as x,aa as M}from"./chunk-eycs00af.js";import"./chunk-kne7h7p5.js";import{ea as v}from"./chunk-6jq8h5s9.js";import"./chunk-fpdqvnmq.js";import{xa as k}from"./chunk-8fp3q919.js";import"./chunk-j14rn2dx.js";import{Ka as u}from"./chunk-11s7t9dp.js";import"./chunk-887qxhn5.js";import{cb as y}from"./chunk-6avkjdjc.js";import{ub as N}from"./chunk-p4yrmzyr.js";import"./chunk-f3pvwxp8.js";import"./chunk-0z5qe4m2.js";import{Eb as C}from"./chunk-81p4kz0b.js";import{Kb as I}from"./chunk-rxjt7ma7.js";import"./chunk-5fw9k1ff.js";import{Vb as w}from"./chunk-9xvnrq7m.js";import"./chunk-0g9cb41d.js";import"./chunk-w4xcmzjm.js";import{Readable as l,Writable as i}from"node:stream";import*as E from"@agentclientprotocol/sdk";import S from"node:path";import{PROTOCOL_VERSION as m}from"@agentclientprotocol/sdk";import{nanoid as R}from"nanoid";var W=w("Agent");function f(z){return Object.fromEntries(z.map((J)=>[J.name,J.value]))}function d(z){if("command"in z)return{type:"stdio",command:z.command,args:z.args,env:f(z.env)};return{type:z.type,url:z.url,headers:f(z.headers)}}function p(z){return Object.fromEntries(z.map((J)=>[J.name,d(J)]))}function O(z){if(typeof z==="string")return z?[{type:"text",text:z}]:[];return z.flatMap((J)=>{if(J.type==="text")return J.text?[{type:"text",text:J.text}]:[];let H=J.image_url.url,Q=/^data:([^;,]+);base64,(.+)$/s.exec(H);if(!Q)return[{type:"text",text:"[Image]"}];return[{type:"image",mimeType:Q[1]??"image/png",data:Q[2]??""}]})}class L{id;cwd;connection;clientCapabilities;options;agent=null;runtime=null;pendingPrompt=null;pendingResumeRequested=!1;availableCommandsTimer=null;taskStatusUnsubscribe;destroyed=!1;messages;mode="default";constructor(z,J,H,Q,X={}){this.id=z;this.cwd=J;this.connection=H;this.clientCapabilities=Q;this.options=X;this.messages=[...X.initialMessages??[]]}createAgent(){if(!this.runtime)throw Error("Session runtime is unavailable");return b.createWithRuntime(this.runtime,{sessionId:this.id,...this.options.taskWorktree?{toolBlacklist:["EnterWorktree","ExitWorktree"]}:{}})}async initialize(){W.debug(`[AcpSession ${this.id}] Initializing...`),B.initializeSession(this.connection,this.id,this.clientCapabilities,this.cwd),W.debug(`[AcpSession ${this.id}] ACP service context initialized`);let z=this.options.mcpServers?p(this.options.mcpServers):void 0;this.runtime=await h.create({sessionId:this.id,workspaceRoot:this.cwd,...z?{mcpServers:z}:{},...this.options.taskWorktree?{taskWorktree:this.options.taskWorktree}:{}}),this.agent=await this.createAgent(),W.debug(`[AcpSession ${this.id}] Agent created successfully`),this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=K.subscribe((H)=>{if(H.type!=="task.status"||H.sessionId!==this.id||H.projectPath!==this.cwd)return;this.sendUpdate({sessionUpdate:"session_info_update",updatedAt:typeof H.properties.updatedAt==="string"?H.properties.updatedAt:new Date().toISOString(),_meta:{"blade/taskStatus":H.properties.taskStatus,...typeof H.properties.taskStatusReason==="string"?{"blade/taskStatusReason":H.properties.taskStatusReason}:{},...typeof H.properties.taskStartedAt==="string"?{"blade/taskStartedAt":H.properties.taskStartedAt}:{},...typeof H.properties.taskCompletedAt==="string"?{"blade/taskCompletedAt":H.properties.taskCompletedAt}:{},...H.properties.taskDiffStat&&typeof H.properties.taskDiffStat==="object"?{"blade/taskDiffStat":H.properties.taskDiffStat}:{}}})});let J=await this.runtime.getGoal();if(this.runtime.getPendingSteeringCount()>0||J?.status==="active")if(this.options.initialMessages===void 0)this.schedulePendingResume();else this.pendingResumeRequested=!0}async replayHistory(){for(let z of this.messages){if(!this.canSendUpdates())return;let J=z.role==="user"?"user_message_chunk":z.role==="assistant"?"agent_message_chunk":void 0;if(!J)continue;for(let H of O(z.content)){if(!this.canSendUpdates())return;if(!await this.sendUpdateAndWait({sessionUpdate:J,content:H}))return}}if(this.pendingResumeRequested)this.schedulePendingResume()}sendAvailableCommandsDelayed(){if(this.destroyed||this.connection.signal.aborted)return;if(this.availableCommandsTimer!==null)clearTimeout(this.availableCommandsTimer);W.debug(`[AcpSession ${this.id}] Scheduling available commands update (500ms delay)`),this.availableCommandsTimer=setTimeout(()=>{if(this.availableCommandsTimer=null,this.destroyed||this.connection.signal.aborted)return;this.sendAvailableCommands()},500)}async handleSlashCommand(z,J){try{W.debug(`[AcpSession ${this.id}] Executing slash command: ${z}`);let H={cwd:this.cwd,workspaceRoot:this.cwd,sessionId:this.id,messages:[...this.messages],rewind:{listCheckpoints:async()=>{if(!this.runtime)throw Error("Session runtime is unavailable");return this.runtime.listRewindCheckpoints()},execute:async(Z)=>{if(!this.runtime)throw Error("Session runtime is unavailable");let $=await this.runtime.rewindSession(Z);return this.messages=[...$.messages],await this.agent?.destroy(),this.agent=await this.createAgent(),$}},subagents:{list:async()=>{if(!this.runtime)throw Error("Session runtime is unavailable");return this.runtime.listSubagents()},resume:async(Z,$)=>{if(!this.runtime)throw Error("Session runtime is unavailable");let G=!1,V,U=(_)=>{this.sendUpdate({sessionUpdate:"tool_call_update",toolCallId:_.id,status:_.status==="completed"?"completed":"failed",content:[{type:"content",content:{type:"text",text:_.result?.message||_.result?.error||`Subagent ${_.status}`}}]})},D=this.runtime.resumeSubagent({agentId:Z,prompt:$,onCompleted:(_)=>{if(G)U(_);else V=_}});if(this.sendUpdate({sessionUpdate:"tool_call",toolCallId:D.session.id,status:"in_progress",title:`Resuming ${D.session.subagentType} subagent`,content:[{type:"content",content:{type:"text",text:`Resumed from ${D.source.id} at depth ${D.session.resumeDepth}`}}],kind:this.mapToolKind("readonly")}),G=!0,V)U(V);return D}},signal:J,acp:{sendMessage:(Z)=>{this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:Z}})},sendToolStart:(Z,$,G)=>{let V=`tool_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,U=this.mapToolKind(G);this.sendUpdate({sessionUpdate:"tool_call",toolCallId:V,status:"in_progress",title:`${Z}`,content:[{type:"content",content:{type:"text",text:JSON.stringify($,null,2)}}],kind:U})},sendToolResult:(Z,$)=>{if($.summary)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:$.summary}})}}},Q=await q(z,H),X=Q.data?.action;if(X==="start_goal"||X==="resume_goal")this.schedulePendingResume();if(X==="rewind_session"&&Array.isArray(Q.data?.messages))this.messages=[...Q.data.messages];if((Q.message==="compact_completed"||Q.message==="compact_fallback")&&Q.data?.compactedMessages)this.messages=[...Q.data.compactedMessages];let Y=Q.content||Q.message;if(Y)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:Y}});if(Q.error)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`[FAIL] ${Q.error}`}});return{stopReason:Q.success?"end_turn":"cancelled"}}catch(H){return W.error(`[AcpSession ${this.id}] Slash command error:`,H),this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`[FAIL] 命令执行失败: ${H instanceof Error?H.message:"未知错误"}`}}),{stopReason:"cancelled"}}}async sendAvailableCommands(){try{let z=M(),J=["model","permissions","theme","config","exit","ide"],Q=z.filter((X)=>!J.includes(X.name)).map((X)=>{let Y;if(X.usage){let Z=X.usage.replace(/^\/\w+\s*/,"").trim();if(Z)Y=Z}if(X.aliases?.length){let Z=`Aliases: ${X.aliases.join(", ")}`;Y=Y?`${Y} | ${Z}`:Z}return{name:X.name,description:X.description,input:Y?{hint:Y}:void 0}});W.info(`[AcpSession ${this.id}] Sending available commands: ${JSON.stringify(Q.map((X)=>X.name))}`),this.sendUpdate({sessionUpdate:"available_commands_update",availableCommands:Q}),W.info(`[AcpSession ${this.id}] Sent ${Q.length} available commands`)}catch(z){W.error(`[AcpSession ${this.id}] Failed to send available commands:`,z)}}async prompt(z,J={}){if(B.setCurrentSession(this.id),!this.agent||!this.runtime)throw Error("Session not initialized");let H=this.resolvePrompt(z.prompt);if(this.pendingPrompt){if(/^\/goal(?:\s|$)/i.test(H.trim()))return this.handleSlashCommand(H,this.pendingPrompt.signal);let X=await this.runtime.enqueueSteering(H,{allowBeforeTurn:!0});if(!X.accepted)throw Error(X.reason==="queue_full"?"Active turn steering queue is full":"Active turn is no longer steerable");if(W.debug(`[AcpSession ${this.id}] Queued steering for active turn (${X.queued})`),X.delivery==="next_turn")this.schedulePendingResume();return{stopReason:"end_turn"}}let Q=new AbortController;this.pendingPrompt=Q;try{if(W.debug(`[AcpSession ${this.id}] Received prompt: ${H.slice(0,100)}...`),x(H))return await this.handleSlashCommand(H,Q.signal);let X={sessionId:this.id,userId:"acp-user",workspaceRoot:this.cwd,messages:[...this.messages],signal:Q.signal,permissionMode:this.mapModeToPermissionMode(),...this.options.taskWorktree?{worktreeActive:!0}:{},confirmationHandler:{requestConfirmation:async(Y)=>{return this.requestPermission(Y)}}};if(await y(this.agent.chatStream(H,X,{pendingInputOnly:J.pendingInputOnly,goalContinuationOnly:J.goalContinuationOnly}),async(Y)=>{switch(Y.kind){case"content_delta":this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:Y.delta}});break;case"thinking_delta":this.sendUpdate({sessionUpdate:"agent_thought_chunk",content:{type:"text",text:Y.delta}});break;case"tool_start":{let Z=Y.toolCall,$="function"in Z?Z.function.name:Z.type,G=this.mapToolKind(Y.toolKind),V=`Executing ${$}`;if($==="Task"&&"function"in Z)try{let U=JSON.parse(Z.function.arguments),D=U.resume_from??U.resume;if(typeof D==="string")V=`Resuming ${String(U.subagent_type||"subagent")} from ${D}`}catch{}this.sendUpdate({sessionUpdate:"tool_call",toolCallId:Z.id,status:"in_progress",title:V,content:[],kind:G});break}case"tool_result":{let{toolCall:Z,result:$}=Y,G=[],V=$.metadata;if(V?.kind==="edit"&&typeof V.file_path==="string"&&typeof V.oldContent==="string"&&(typeof V.newContent==="string"||V.newContent===void 0))G.push({type:"diff",path:V.file_path,oldText:V.oldContent,newText:V.newContent??null});else{let D="function"in Z?Z.function.name:Z.type,_=A(T(D,$));G.push({type:"content",content:{type:"text",text:_}})}let U=$.success?"completed":"failed";this.sendUpdate({sessionUpdate:"tool_call_update",toolCallId:Z.id,status:U,content:G});break}case"task_update":this.sendPlanUpdate(Y.tasks);break;case"steering_applied":break;case"follow_up_started":for(let Z of Y.messages){if(!Z.recovered||Z.persisted)continue;for(let $ of O(Z.content))this.sendUpdate({sessionUpdate:"user_message_chunk",content:$})}if(Y.recovered>0)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`[Resuming ${Y.recovered} queued instruction${Y.recovered===1?"":"s"} recovered after restart]
|
|
2
|
-
`}});break;case"goal_updated":if(Y.goal&&Y.goal.status!=="active")this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`[Goal ${Y.goal.status}: ${Y.goal.objective}]
|
|
3
|
-
`}});break;case"goal_continuation_started":break;default:break}}),this.messages=[...X.messages],Q.signal.aborted)return{stopReason:"cancelled"};return{stopReason:"end_turn"}}catch(X){if(Q.signal.aborted||X instanceof Error&&X.name==="AbortError")return{stopReason:"cancelled"};throw W.error(`[AcpSession ${this.id}] Prompt error:`,X),X}finally{if(this.pendingPrompt===Q){if(this.pendingPrompt=null,!this.destroyed&&this.pendingResumeRequested)this.schedulePendingResume()}}}schedulePendingResume(){if(this.destroyed||this.connection.signal.aborted)return;this.pendingResumeRequested=!0,queueMicrotask(()=>{this.resumePendingIfIdle()})}async resumePendingIfIdle(){if(this.destroyed||this.connection.signal.aborted)return;if(this.pendingPrompt||!this.runtime||!this.agent)return;let z=this.runtime.getPendingSteeringCount()>0,H=(z?null:await this.runtime.getGoal())?.status==="active";if(!z&&!H){this.pendingResumeRequested=!1;return}this.pendingResumeRequested=!1,await this.prompt({sessionId:this.id,prompt:[]},{pendingInputOnly:z,goalContinuationOnly:H}).catch((Q)=>{W.error(`[AcpSession ${this.id}] Failed to resume pending input:`,Q)})}cancel(){if(W.info(`[AcpSession ${this.id}] Cancel requested`),this.pendingResumeRequested=!1,this.pendingPrompt)this.pendingPrompt.abort(),this.pendingPrompt=null,W.info(`[AcpSession ${this.id}] Cancelled successfully`);else W.warn(`[AcpSession ${this.id}] No pending prompt to cancel`)}async setMode(z){let J=["default","auto-edit","yolo","plan"];this.mode=J.includes(z)?z:"default",W.info(`[AcpSession ${this.id}] Mode set to: ${this.mode}`),this.sendUpdate({sessionUpdate:"current_mode_update",currentModeId:this.mode})}mapModeToPermissionMode(){switch(this.mode){case"yolo":return"yolo";case"auto-edit":return"autoEdit";case"plan":return"plan";case"default":default:return"default"}}shouldAutoApprove(z){switch(this.mode){case"yolo":return!0;case"auto-edit":return z==="readonly"||z==="write";case"plan":return z==="readonly";case"default":default:return!1}}async setModel(z){if(W.info(`[AcpSession ${this.id}] Model set to: ${z}`),this.pendingPrompt)throw Error("Cannot switch models while a prompt is active");if(!this.agent)throw Error("Session not initialized");await this.agent.switchModel(z)}async destroy(){if(this.destroyed)return;if(this.destroyed=!0,this.availableCommandsTimer!==null)clearTimeout(this.availableCommandsTimer),this.availableCommandsTimer=null;this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=void 0;let z=this.agent,J=this.runtime;this.agent=null,this.runtime=null;let H,Q=async(X)=>{try{await X()}catch(Y){H??=Y}};if(await Q(()=>this.cancel()),z)await Q(()=>z.destroy());if(J)await Q(()=>J.dispose());if(await Q(()=>B.destroySession(this.id)),W.debug(`[AcpSession ${this.id}] Destroyed`),H!==void 0)throw H}resolvePrompt(z){let J=[];for(let H of z)if(H.type==="text")J.push(H.text);else if(H.type==="image")J.push(`[Image: ${H.mimeType}]`);else if(H.type==="resource"){let Q=H.resource;if("text"in Q)J.push(`<file path="${Q.uri}">
|
|
4
|
-
${Q.text}
|
|
5
|
-
</file>`)}else if(H.type==="resource_link")J.push(`[Resource: ${H.uri}]`);return J.join(`
|
|
6
|
-
`)}canSendUpdates(){return!this.destroyed&&!this.connection.signal.aborted}async sendUpdateAndWait(z){if(!this.canSendUpdates())return!1;return await this.connection.sessionUpdate({sessionId:this.id,update:z}),this.canSendUpdates()}sendUpdate(z){if(!this.canSendUpdates())return;let J={sessionId:this.id,update:z};this.connection.sessionUpdate(J).catch((H)=>{W.warn(`[AcpSession ${this.id}] Failed to send update:`,H)})}sendPlanUpdate(z){let J=z.map((H)=>({content:H.subject,priority:H.priority,status:H.status}));W.debug(`[AcpSession ${this.id}] Sending plan update with ${J.length} entries`),this.sendUpdate({sessionUpdate:"plan",entries:J})}async requestPermission(z){let J=this.pendingPrompt?.signal;if(z.type==="askUserQuestion")return this.requestUserQuestions(z,J);let H=z.kind?.toLowerCase()||"execute";if(this.shouldAutoApprove(H))return W.debug(`[AcpSession ${this.id}] Auto-approving ${H} in mode: ${this.mode}`),{approved:!0};if(this.mode==="plan"&&(H==="write"||H==="execute"))return W.debug(`[AcpSession ${this.id}] Rejecting ${H} in plan mode`),{approved:!1,reason:"Write and execute operations are not allowed in Plan mode"};try{let Q=R(),X=[];if(z.message)X.push({type:"content",content:{type:"text",text:z.message}});if(z.risks&&z.risks.length>0)X.push({type:"content",content:{type:"text",text:`Risks:
|
|
7
|
-
- ${z.risks.join(`
|
|
8
|
-
- `)}`}});let Y=this.mapToolKind(H),Z={sessionId:this.id,options:[{optionId:"allow_once",name:"Allow once",kind:"allow_once"},{optionId:"allow_always",name:"Always allow",kind:"allow_always"},{optionId:"reject_once",name:"Deny once",kind:"reject_once"},{optionId:"reject_always",name:"Always deny",kind:"reject_always"}],toolCall:{toolCallId:Q,status:"pending",title:z.title||"Permission Required",content:X,kind:Y}},$=await this.waitForClientInteraction(this.connection.requestPermission(Z),J);if(!$)return{approved:!1,reason:N};let G=$.outcome;if(G.outcome==="cancelled")return{approved:!1,reason:"User cancelled the permission request"};let V=G.optionId;if(V==="allow_always")return{approved:!0,scope:"project"};if(V==="reject_always")return{approved:!1,scope:"project",reason:"User permanently denied the permission request"};let U=V==="allow_once";return{approved:U,scope:"once",reason:U?void 0:"User denied the operation"}}catch(Q){return W.warn(`[AcpSession ${this.id}] Permission request failed:`,Q),{approved:!1,reason:"Permission request failed"}}}async requestUserQuestions(z,J){let H=z.questions??[];if(H.length===0)return{approved:!1,reason:"No structured questions were provided"};if(H.some((X)=>X.multiSelect))return{approved:!1,reason:"ACP does not support multi-select question responses"};let Q={};try{for(let[X,Y]of H.entries()){let Z=Y.options.map((U,D)=>`answer:${X}:${D}`),$=`answer:${X}:cancel`,G=await this.waitForClientInteraction(this.connection.requestPermission({sessionId:this.id,options:[...Y.options.map((U,D)=>({optionId:Z[D],name:U.label,kind:"allow_once"})),{optionId:$,name:"Cancel",kind:"reject_once"}],toolCall:{toolCallId:R(),status:"pending",title:Y.header,kind:"think",content:[{type:"content",content:{type:"text",text:[Y.question,...Y.options.map((U)=>`${U.label}: ${U.description}`)].join(`
|
|
9
|
-
`)}}]}}),J);if(!G)return{approved:!1,reason:N};if(G.outcome.outcome!=="selected")return{approved:!1,reason:"User cancelled the question prompt"};let V=Z.indexOf(G.outcome.optionId);if(V<0)return{approved:!1,reason:"User cancelled the question prompt"};Q[Y.header]=Y.options[V].label}return{approved:!0,answers:Q}}catch(X){return W.warn(`[AcpSession ${this.id}] Question request failed:`,X),{approved:!1,reason:"Question request failed"}}}async waitForClientInteraction(z,J){if(!J)return z;if(J.aborted)return;return new Promise((H,Q)=>{let X=!1,Y=($)=>{if(X)return;X=!0,J.removeEventListener("abort",Z),$()},Z=()=>Y(()=>H(void 0));if(J.addEventListener("abort",Z,{once:!0}),J.aborted)Z();z.then(($)=>Y(()=>H($)),($)=>Y(()=>Q($)))})}mapToolKind(z){return{readonly:"read",write:"edit",execute:"execute",read:"read",edit:"edit",delete:"delete",move:"move",search:"search",think:"think",fetch:"fetch"}[z||""]||"other"}}var F=w("Agent");class P{connection;sessions=new Map;sessionLoadQueues=new Map;clientCapabilities;destroyed=!1;constructor(z){this.connection=z}async initialize(z){return F.info("[BladeAgent] Initializing ACP connection"),F.debug(`[BladeAgent] Client capabilities: ${JSON.stringify(z.clientCapabilities)}`),this.clientCapabilities=z.clientCapabilities,{protocolVersion:m,agentCapabilities:{loadSession:!0,sessionCapabilities:{list:{},fork:{}},promptCapabilities:{image:!0,audio:!1,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0}}}}async authenticate(z){return}async newSession(z){this.assertNotDestroyed();let J=C("acp"),H=z.cwd||I(),Q=z._meta?.["blade/taskIsolation"],X=Q==="local"||Q==="worktree"?Q:void 0,Y=z._meta?.["blade/taskPrompt"],Z=X?await c.createSessionTask({sessionId:J,prompt:typeof Y==="string"&&Y.trim()?Y:"ACP task session",sourceProjectPath:H,isolation:X}):void 0,$=Z?.metadata.projectPath??H;F.info(`[BladeAgent] Creating new session: ${J}`),F.debug(`[BladeAgent] Session cwd: ${$}`);let G=new L(J,$,this.connection,this.clientCapabilities,{mcpServers:z.mcpServers,...Z?.taskWorktree?{taskWorktree:Z.taskWorktree}:{}});try{await G.initialize(),this.assertNotDestroyed()}catch(V){throw await G.destroy().catch(()=>{return}),V}return this.sessions.set(J,G),F.info(`[BladeAgent] Session ${J} created, scheduling available commands update`),G.sendAvailableCommandsDelayed(),this.buildChildSessionResponse(J,Z?.metadata)}async unstable_listSessions(z){if(z.cwd!=null&&!S.isAbsolute(z.cwd))throw Error("ACP session list cwd must be absolute");let J=await j.listSessionPage({cwd:z.cwd??void 0,cursor:z.cursor??void 0,limit:50,includeSubagents:!1});return{sessions:J.sessions.map((H)=>({sessionId:H.sessionId,cwd:H.projectPath,title:H.title??null,updatedAt:H.lastMessageTime,_meta:{"blade/taskStatus":H.taskStatus,...H.taskStatusReason?{"blade/taskStatusReason":H.taskStatusReason}:{},...H.taskStartedAt?{"blade/taskStartedAt":H.taskStartedAt}:{},...H.taskCompletedAt?{"blade/taskCompletedAt":H.taskCompletedAt}:{},...H.taskIsolation?{"blade/taskIsolation":H.taskIsolation}:{},...H.taskSourceProjectPath?{"blade/taskSourceProjectPath":H.taskSourceProjectPath}:{},...H.taskWorktreeBranch?{"blade/taskWorktreeBranch":H.taskWorktreeBranch}:{},...H.taskBaseCommit?{"blade/taskBaseCommit":H.taskBaseCommit}:{},...H.taskDiffStat?{"blade/taskDiffStat":H.taskDiffStat}:{}}})),nextCursor:J.nextCursor}}async unstable_forkSession(z){if(this.assertNotDestroyed(),!S.isAbsolute(z.cwd))throw Error("ACP session fork cwd must be absolute");let J=await j.forkSession(z.sessionId,{sourceProjectPath:z.cwd,targetProjectPath:z.cwd});this.assertNotDestroyed();let H=new L(J.sessionId,z.cwd,this.connection,this.clientCapabilities,{initialMessages:J.messages,mcpServers:z.mcpServers});try{await H.initialize(),this.assertNotDestroyed()}catch(Q){throw await H.destroy().catch(()=>{return}),Q}return this.sessions.set(J.sessionId,H),H.sendAvailableCommandsDelayed(),this.buildChildSessionResponse(J.sessionId)}async loadSession(z){this.assertNotDestroyed(),F.info(`[BladeAgent] Loading session: ${z.sessionId}`);let H=(this.sessionLoadQueues.get(z.sessionId)??Promise.resolve()).then(()=>this.replaceSession(z)),Q=H.then(()=>{return},()=>{return});this.sessionLoadQueues.set(z.sessionId,Q);try{return await H}finally{if(this.sessionLoadQueues.get(z.sessionId)===Q)this.sessionLoadQueues.delete(z.sessionId)}}async replaceSession(z){this.assertNotDestroyed();let J=this.sessions.get(z.sessionId);if(J)try{await J.destroy()}finally{if(this.sessions.get(z.sessionId)===J)this.sessions.delete(z.sessionId)}let H=await j.loadSession(z.sessionId,z.cwd),Q=new L(z.sessionId,z.cwd,this.connection,this.clientCapabilities,{initialMessages:H,mcpServers:z.mcpServers});try{await Q.initialize(),await Q.replayHistory(),this.assertNotDestroyed()}catch(X){throw await Q.destroy().catch(()=>{return}),X}return this.sessions.set(z.sessionId,Q),Q.sendAvailableCommandsDelayed(),this.buildSessionSetup()}buildChildSessionResponse(z,J){return{sessionId:z,...this.buildSessionSetup(),...J?{_meta:{"blade/taskIsolation":J.taskIsolation,"blade/taskSourceProjectPath":J.taskSourceProjectPath,"blade/taskProjectPath":J.projectPath,...J.taskWorktreeBranch?{"blade/taskWorktreeBranch":J.taskWorktreeBranch}:{},...J.taskBaseCommit?{"blade/taskBaseCommit":J.taskBaseCommit}:{}}}:{}}}assertNotDestroyed(){if(this.destroyed)throw Error("BladeAgent is destroyed")}buildSessionSetup(){let z=k(),J=z?.models||[],H=z?.currentModelId||J[0]?.id,Q=J.map((Y)=>({modelId:Y.id,name:u(Y),description:`${Y.provider}/${Y.model}`}));return{modes:{availableModes:[{id:"default",name:"Default",description:"Ask for confirmation before all file edits and commands"},{id:"auto-edit",name:"Auto Edit",description:"Auto-approve file edits, ask for shell commands"},{id:"yolo",name:"Full Auto",description:"Auto-approve everything without confirmation"},{id:"plan",name:"Plan Only",description:"Read-only mode, no file changes or commands"}],currentModeId:"default"},models:Q.length>0?{availableModels:Q,currentModelId:H}:void 0}}async prompt(z){let J=this.sessions.get(z.sessionId);if(!J)throw Error(`Session not found: ${z.sessionId}`);return J.prompt(z)}async cancel(z){F.info(`[BladeAgent] Cancel notification received for session: ${z.sessionId}`);let J=this.sessions.get(z.sessionId);if(J)F.info("[BladeAgent] Found session, calling session.cancel()"),J.cancel();else F.warn(`[BladeAgent] Session not found for cancel: ${z.sessionId}`)}async setSessionMode(z){F.info(`[BladeAgent] Setting session mode: ${z.modeId}`);let J=this.sessions.get(z.sessionId);if(J)await J.setMode(z.modeId);return{}}async unstable_setSessionModel(z){F.info(`[BladeAgent] Setting session model: ${z.modelId}`);let J=this.sessions.get(z.sessionId);if(!J)throw Error(`Session not found: ${z.sessionId}`);return await J.setModel(z.modelId),{}}async destroy(){this.destroyed=!0,await Promise.all([...this.sessionLoadQueues.values()]),this.sessionLoadQueues.clear();let z;for(let J of this.sessions.values())try{await J.destroy()}catch(H){z??=H}this.sessions.clear();try{await v.getInstance().disconnectAll()}catch(J){z??=J}if(z!==void 0)throw z}}async function Nz(){let z=i.toWeb(process.stdout),J=l.toWeb(process.stdin),H=E.ndJsonStream(z,J);await new E.AgentSideConnection((X)=>new P(X),H).closed}export{Nz as runAcpIntegration};
|
package/dist/chunk-j14rn2dx.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import{Kb as V,Mb as L,Nb as M}from"./chunk-rxjt7ma7.js";import{Vb as b}from"./chunk-9xvnrq7m.js";import{fc as E}from"./chunk-0g9cb41d.js";var G={currentModelId:"",models:[],temperature:0,maxOutputTokens:void 0,stream:!0,topP:0.9,topK:50,timeout:180000,theme:"dracula",uiTheme:"system",language:"zh-CN",fontSize:14,autoSaveSessions:!0,notifyBuild:!0,notifyErrors:!1,notifySounds:!1,privacyTelemetry:!1,privacyCrash:!0,debug:!1,mcpEnabled:!1,mcpServers:{},permissions:{allow:["Bash(pwd)","Bash(which *)","Bash(whoami)","Bash(hostname)","Bash(uname *)","Bash(date)","Bash(echo *)","Bash(ls *)","Bash(tree *)","Bash(git status)","Bash(git status -*)","Bash(git log *)","Bash(git diff *)","Bash(git show *)","Bash(git branch -* *)","Bash(git branch)","Bash(git tag -l *)","Bash(git tag --list *)","Bash(git stash list *)","Bash(git stash show *)","Bash(git rev-parse *)","Bash(git describe *)","Bash(git blame *)","Bash(git ls-files *)","Bash(git config --get *)","Bash(git config --list *)","Bash(git shortlog *)","Bash(git merge-base *)","Bash(git cat-file *)","Bash(git for-each-ref *)","Bash(git grep *)","Bash(git worktree list *)","Bash(git reflog show *)","Bash(git reflog)","Bash(git rev-list *)","Bash(git ls-remote *)","Bash(git remote -v)","Bash(git remote --verbose)","Bash(git remote)","Bash(gh pr view *)","Bash(gh pr list *)","Bash(gh pr diff *)","Bash(gh pr checks *)","Bash(gh pr status *)","Bash(gh issue view *)","Bash(gh issue list *)","Bash(gh issue status *)","Bash(gh run list *)","Bash(gh run view *)","Bash(gh repo view *)","Bash(gh auth status)","Bash(npm list *)","Bash(bun pm ls *)","Bash(npm view *)","Bash(npm outdated *)","Bash(pnpm list *)","Bash(yarn list *)","Bash(pip list *)","Bash(pip show *)"],ask:["Bash(curl *)","Bash(wget *)","Bash(aria2c *)","Bash(axel *)","Bash(rm -rf *)","Bash(rm -r *)","Bash(rm --recursive *)","Bash(nc *)","Bash(netcat *)","Bash(telnet *)","Bash(ncat *)"],deny:["Read(./.env)","Read(./.env.*)","Bash(rm -rf /)","Bash(rm -rf /*)","Bash(sudo *)","Bash(chmod 777 *)","Bash(bash *)","Bash(sh *)","Bash(zsh *)","Bash(fish *)","Bash(dash *)","Bash(eval *)","Bash(source *)","Bash(mkfs *)","Bash(fdisk *)","Bash(dd *)","Bash(format *)","Bash(parted *)","Bash(open http*)","Bash(open https*)","Bash(xdg-open http*)","Bash(xdg-open https*)"]},permissionMode:"default",hooks:{enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],PostToolUseFailure:[],PermissionRequest:[],UserPromptSubmit:[],SessionStart:[],SessionEnd:[],Stop:[],SubagentStop:[],Notification:[],Compaction:[]},env:{},disableAllHooks:!1,maxTurns:-1};import{promises as T}from"fs";import{merge as A}from"lodash-es";import R from"os";import $ from"path";var x={sonnet:"claude-sonnet-4-20250514",opus:"claude-opus-4-20250514",haiku:"claude-3-5-haiku-20241022",claude:"claude-sonnet-4-20250514",gpt4o:"gpt-4o",gpt4:"gpt-4o",o1:"o1",o3:"o3","o4-mini":"o4-mini",deepseek:"deepseek-chat","deepseek-v3":"deepseek-chat","deepseek-r1":"deepseek-reasoner","deepseek-v4":"deepseek-v4-0324",gemini:"gemini-2.5-pro",flash:"gemini-2.5-flash",qwen:"qwen3-235b-a22b","qwen-max":"qwen-max","qwen-plus":"qwen-plus"};function _(J){let q=J.toLowerCase().trim();return x[q]??J}class N{static instance=null;runtimePermissionOverrides;constructor(){}static getInstance(){if(!N.instance)N.instance=new N;return N.instance}static resetInstance(){N.instance=null}async initialize(J){try{this.runtimePermissionOverrides=J?.permissions;let q=await this.loadConfigFiles(),H=await this.loadSettingsFiles(),K={...q,...H};if(J)K=this.mergeSettings(K,J);let Q=this.normalizeConfig(K),W={...G,...Q};if(this.resolveEnvInterpolation(W),process.env.BLADE_MODEL&&W.models?.length>0){let X=_(process.env.BLADE_MODEL),Y=W.models.find((Z)=>Z.id===X||Z.model===X||Z.id===process.env.BLADE_MODEL||Z.model===process.env.BLADE_MODEL);if(Y)W.currentModelId=Y.id}if(process.env.BLADE_DEBUG)W.debug=process.env.BLADE_DEBUG==="1"||process.env.BLADE_DEBUG==="true"||process.env.BLADE_DEBUG;if(W.models.length>0)this.validateConfig(W);if(W.debug)console.log("[ConfigManager] Configuration loaded successfully");return W}catch(q){return console.error("[ConfigManager] Failed to initialize:",q),G}}async loadConfigFiles(){let J=$.join(R.homedir(),".blade","config.json"),q=$.join(V(),".blade","config.json"),H={},K=await this.loadJsonFile(J);if(K)H={...H,...K};let Q=await this.loadJsonFile(q);if(Q){let W={...H.mcpServers||{},...Q.mcpServers||{}};if(H={...H,...Q},Object.keys(W).length>0)H.mcpServers=W}return H}async loadSettingsFiles(){let J=$.join(R.homedir(),".blade","settings.json"),q=$.join(V(),".blade","settings.json"),H=$.join(V(),".blade","settings.local.json"),K={},Q=await this.loadJsonFile(J);if(Q)K=this.mergeSettings(K,Q);let W=await this.loadJsonFile(q);if(W)K=this.mergeSettings(K,W);let X=await this.loadJsonFile(H);if(X)K=this.mergeSettings(K,X);return K}async loadWorkspacePermissions(J,q){let H={allow:[...q.allow],ask:[...q.ask],deny:[...q.deny]};if($.resolve(J)!==$.resolve(V())){let Q=await this.loadWorkspacePermissionOverrides(V()),W=await this.loadJsonFile($.join(R.homedir(),".blade","settings.json")),X={allow:Array.from(new Set([...G.permissions.allow,...W?.permissions?.allow||[],...this.runtimePermissionOverrides?.allow||[]])),ask:Array.from(new Set([...G.permissions.ask,...W?.permissions?.ask||[],...this.runtimePermissionOverrides?.ask||[]])),deny:Array.from(new Set([...G.permissions.deny,...W?.permissions?.deny||[],...this.runtimePermissionOverrides?.deny||[]]))};for(let Y of["allow","ask","deny"]){let Z=new Set(Q[Y].filter((F)=>!X[Y].includes(F)));H[Y]=H[Y].filter((F)=>!Z.has(F))}}let K=await this.loadWorkspacePermissionOverrides(J);for(let Q of["allow","ask","deny"])H[Q]=Array.from(new Set([...H[Q],...K[Q]]));return H}async loadWorkspacePermissionOverrides(J){let q={allow:[],ask:[],deny:[]},H=[$.join(J,".blade","settings.json"),$.join(J,".blade","settings.local.json")];for(let K of H){let Q=await this.loadJsonFile(K);if(!Q?.permissions)continue;for(let W of["allow","ask","deny"])q[W]=Array.from(new Set([...q[W],...Q.permissions[W]||[]]))}return q}mergeSettings(J,q){let H={...JSON.parse(JSON.stringify(J)),...JSON.parse(JSON.stringify(q))};if(q.permissions)H.permissions={allow:Array.from(new Set([...J.permissions?.allow||[],...q.permissions.allow||[]])),ask:Array.from(new Set([...J.permissions?.ask||[],...q.permissions.ask||[]])),deny:Array.from(new Set([...J.permissions?.deny||[],...q.permissions.deny||[]]))};if(q.hooks)H.hooks=A({},H.hooks,q.hooks);if(q.env)H.env=A({},H.env,q.env);if(q.mcpServers)H.mcpServers={...H.mcpServers||{},...q.mcpServers};if(q.disableAllHooks!==void 0)H.disableAllHooks=q.disableAllHooks;if(q.permissionMode!==void 0)H.permissionMode=q.permissionMode;if(q.maxTurns!==void 0)H.maxTurns=q.maxTurns;return H}resolveEnvInterpolation(J){let q=/\$\{?([A-Z_][A-Z0-9_]*)(:-([^}]+))?\}?/g,H=(Q)=>{if(typeof Q==="string")return Q.replace(q,(W,X,Y,Z)=>{return process.env[X]||Z||W});if(Array.isArray(Q))return Q.map(H);if(typeof Q==="object"&&Q!==null){let W=Q;for(let[X,Y]of Object.entries(W))W[X]=H(Y);return W}return Q},K=J;for(let[Q,W]of Object.entries(K))K[Q]=H(W)}async loadJsonFile(J){try{if(await this.fileExists(J)){let q=await T.readFile(J,"utf-8");return JSON.parse(q)}}catch(q){console.warn(`[ConfigManager] Failed to load ${J}:`,q)}return null}async fileExists(J){try{return await T.access(J),!0}catch{return!1}}normalizeConfig(J){let q=JSON.parse(JSON.stringify(J)),H=(Q)=>Q.trim().replace(/^`|`$/g,""),K=(Q)=>{for(let[W,X]of Object.entries(Q))if(typeof X==="string")Q[W]=H(X);else if(Array.isArray(X))X.forEach((Y,Z)=>{if(typeof Y==="string")X[Z]=H(Y);else if(typeof Y==="object"&&Y!==null)K(Y)});else if(typeof X==="object"&&X!==null)K(X)};return K(q),q}validateConfig(J){let q=[];if(!J.models||J.models.length===0)q.push("没有可用的模型配置");if(!L(J.maxTurns))q.push(`maxTurns 必须是 ${M()}`);if(J.models&&J.models.length>0){if(!J.currentModelId)q.push("未设置当前模型 ID");else if(!J.models.find((K)=>K.id===J.currentModelId))q.push(`当前模型 ID "${J.currentModelId}" 在 models 列表中不存在`);for(let H of J.models){let K=`模型 "${H.displayName||H.id}"`,Q=["name","apiKey","baseUrl","maxContextTokens","maxOutputTokens","supportsThinking","thinkingBudget","thinkingMode"].filter((W)=>(W in H));if(Q.length>0)q.push(`${K}: 不再支持旧字段 ${Q.join(", ")};请重新配置模型`);if(!H.model)q.push(`${K}: model 字段必填`);if(!H.provider)q.push(`${K}: provider 字段必填`);if(H.overrides?.baseUrl&&!H.overrides.baseUrl.startsWith("http"))q.push(`${K}: overrides.baseUrl "${H.overrides.baseUrl}" 不是有效的 HTTP URL`);try{E().getModel(H.provider,H.model)}catch{q.push(`${K}: 内置 catalog 中不存在 ${H.provider}/${H.model}`)}}}if(q.length>0)throw Error(`配置验证失败:
|
|
2
|
-
${q.map((H)=>` - ${H}`).join(`
|
|
3
|
-
`)}
|
|
4
|
-
|
|
5
|
-
`+`请通过以下方式之一提供配置:
|
|
6
|
-
`+` 1. 首次启动: 运行 blade,系统会自动引导配置
|
|
7
|
-
`+` 2. 添加模型: blade 后输入 /model add
|
|
8
|
-
`+` 3. 初始化向导: 输入 /init
|
|
9
|
-
|
|
10
|
-
`+`配置文件示例 (~/.blade/config.json):
|
|
11
|
-
`+`{
|
|
12
|
-
"currentModelId": "model-id-123",
|
|
13
|
-
"models": [
|
|
14
|
-
{
|
|
15
|
-
"id": "model-id-123",
|
|
16
|
-
`+` "displayName": "默认模型",
|
|
17
|
-
`+` "provider": "deepseek",
|
|
18
|
-
"model": "deepseek-v4-pro"
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|
|
22
|
-
`)}}function y(J,q={}){let H={...J};if(q.debug!==void 0)H.debug=q.debug===""?!0:q.debug;if(q.model){if(!J.models.some((Q)=>Q.id===q.model))throw Error(`模型配置未找到: ${q.model}`);H.currentModelId=q.model}if(q.yolo===!0)H.permissionMode="yolo";else if(q.permissionMode!==void 0)H.permissionMode=q.permissionMode;if(q.maxTurns!==void 0)H.maxTurns=q.maxTurns;return H.systemPrompt=q.systemPrompt,H.appendSystemPrompt=q.appendSystemPrompt,H.model=q.model,H.resumeSessionId=q.sessionId,H.forkSession=q.forkSession,H.allowedTools=q.allowedTools,H.disallowedTools=q.disallowedTools,H.mcpConfigPaths=q.mcpConfig,H.strictMcpConfig=q.strictMcpConfig,H.addDirs=q.addDir,H.outputFormat=q.outputFormat,H.inputFormat=q.inputFormat,H.print=q.print,H.includePartialMessages=q.includePartialMessages,H.replayUserMessages=q.replayUserMessages,H.agentsConfig=q.agents,H.settingSources=q.settingSources,H}import{promises as D}from"node:fs";import w from"node:os";import B from"node:path";import{Mutex as j}from"async-mutex";import{merge as k}from"lodash-es";import C from"write-file-atomic";var S=b("Service"),U={models:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},currentModelId:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},temperature:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},maxOutputTokens:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},timeout:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},theme:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},uiTheme:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},language:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},debug:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},fontSize:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},autoSaveSessions:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},notifyBuild:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},notifyErrors:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},notifySounds:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},privacyTelemetry:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},privacyCrash:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},permissionMode:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},permissions:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},hooks:{target:"settings",defaultScope:"local",mergeStrategy:"deep-merge",persistable:!0},env:{target:"settings",defaultScope:"local",mergeStrategy:"deep-merge",persistable:!0},disableAllHooks:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},maxTurns:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},mcpServers:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},stream:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},topP:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},topK:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},mcpEnabled:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},systemPrompt:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},appendSystemPrompt:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},initialMessage:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},resumeSessionId:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},forkSession:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},allowedTools:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},disallowedTools:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},mcpConfigPaths:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},strictMcpConfig:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},addDirs:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},outputFormat:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},inputFormat:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},print:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},includePartialMessages:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},replayUserMessages:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},agentsConfig:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},settingSources:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1}},Yq=new Set(Object.entries(U).filter(([J,q])=>q.persistable).map(([J])=>J)),Zq=new Set(Object.entries(U).filter(([J,q])=>!q.persistable).map(([J])=>J));class z{static instance=null;pendingUpdates=new Map;timers=new Map;fileLocks=new Map;lastSaveError=null;debounceDelay=300;constructor(){}static getInstance(){if(!z.instance)z.instance=new z;return z.instance}static resetInstance(){if(z.instance)for(let J of z.instance.timers.values())clearTimeout(J);z.instance=null}async save(J,q={}){this.validatePersistableFields(J);let H=this.groupUpdatesByTarget(J,q.scope,q.projectDir);if(q.immediate)await Promise.all(Array.from(H.entries()).map(([K,Q])=>this.flushTarget(K,Q)));else for(let[K,Q]of H)this.scheduleSave(K,Q)}async flush(){for(let q of this.timers.values())clearTimeout(q);this.timers.clear();let J=Array.from(this.pendingUpdates.entries()).map(([q,H])=>this.flushTarget(q,H));this.pendingUpdates.clear(),await Promise.all(J)}getLastSaveError(){return this.lastSaveError}clearLastSaveError(){this.lastSaveError=null}async appendPermissionRule(J,q={}){await this.appendPermissionRuleForDecision(J,"allow",q)}async appendPermissionDenyRule(J,q={}){await this.appendPermissionRuleForDecision(J,"deny",q)}async appendPermissionRuleForDecision(J,q,H){let K=H.scope??"local",Q=this.resolveFilePath("settings",K,H.projectDir);await this.flushTargetWithModifier(Q,(W)=>{let X=W.permissions??{allow:[],ask:[],deny:[]},Y={allow:q==="allow"?this.dedupeArray([...X.allow||[],J]):X.allow||[],ask:X.ask||[],deny:q==="deny"?this.dedupeArray([...X.deny||[],J]):X.deny||[]};return{...W,permissions:Y}})}async appendLocalPermissionRule(J,q={}){await this.appendPermissionRule(J,{...q,scope:"local"})}async appendLocalPermissionDenyRule(J,q={}){await this.appendPermissionDenyRule(J,{...q,scope:"local"})}validatePersistableFields(J){for(let q of Object.keys(J)){let H=U[q];if(!H)throw Error(`Unknown config field: ${q}`);if(!H.persistable)throw Error(`Field "${q}" is non-persistable and cannot be saved to config files. Non-persistable fields are runtime-only and only valid for the current session.`)}}groupUpdatesByTarget(J,q,H){let K=new Map;for(let[Q,W]of Object.entries(J)){let X=U[Q];if(!X)continue;let Y=q??X.defaultScope,Z=this.resolveFilePath(X.target,Y,H);if(!K.has(Z))K.set(Z,{});K.get(Z)[Q]=W}return K}resolveFilePath(J,q,H){let K=H??V();if(J==="config")return q==="global"?B.join(w.homedir(),".blade","config.json"):B.join(K,".blade","config.json");switch(q){case"local":return B.join(K,".blade","settings.local.json");case"project":return B.join(K,".blade","settings.json");case"global":return B.join(w.homedir(),".blade","settings.json");default:return B.join(K,".blade","settings.local.json")}}scheduleSave(J,q){let H=this.pendingUpdates.get(J)??{},K=this.mergePendingUpdates(H,q);this.pendingUpdates.set(J,K);let Q=this.timers.get(J);if(Q)clearTimeout(Q);let W=setTimeout(async()=>{let X=this.pendingUpdates.get(J);if(X){this.pendingUpdates.delete(J),this.timers.delete(J);try{await this.flushTarget(J,X),this.lastSaveError=null}catch(Y){let Z=Y instanceof Error?Y:Error(String(Y));this.lastSaveError=Z,S.error(`Failed to save config to ${J}:`,Z.message),S.error("Stack trace:",Z.stack)}}},this.debounceDelay);this.timers.set(J,W)}mergePendingUpdates(J,q){let H={...J};for(let[K,Q]of Object.entries(q)){let W=U[K];if(!W){H[K]=Q;continue}switch(W.mergeStrategy){case"replace":H[K]=Q;break;case"append-dedupe":this.applyAppendDedupe(H,K,Q);break;case"deep-merge":this.applyDeepMerge(H,K,Q);break}}return H}async flushTarget(J,q){let H=this.fileLocks.get(J);if(!H)H=new j,this.fileLocks.set(J,H);await H.runExclusive(async()=>{await this.performWrite(J,q)})}async flushTargetWithModifier(J,q){let H=this.fileLocks.get(J);if(!H)H=new j,this.fileLocks.set(J,H);await H.runExclusive(async()=>{await D.mkdir(B.dirname(J),{recursive:!0,mode:493});let K={};try{let W=await D.readFile(J,"utf-8");K=JSON.parse(W)}catch{K={}}let Q=q(K);await this.atomicWrite(J,Q)})}async performWrite(J,q){await D.mkdir(B.dirname(J),{recursive:!0,mode:493});let H={};try{let Q=await D.readFile(J,"utf-8");H=JSON.parse(Q)}catch{H={}}let K={...H};for(let[Q,W]of Object.entries(q)){let X=U[Q];if(!X){K[Q]=W;continue}switch(X.mergeStrategy){case"replace":K[Q]=W;break;case"append-dedupe":this.applyAppendDedupe(K,Q,W);break;case"deep-merge":this.applyDeepMerge(K,Q,W);break}}await this.atomicWrite(J,K)}applyAppendDedupe(J,q,H){if(q==="permissions"&&typeof H==="object"&&H!==null){let K=J[q]??{allow:[],ask:[],deny:[]},Q=H;J[q]={allow:this.dedupeArray([...K.allow||[],...Q.allow||[]]),ask:this.dedupeArray([...K.ask||[],...Q.ask||[]]),deny:this.dedupeArray([...K.deny||[],...Q.deny||[]])}}else if(Array.isArray(H)){let K=Array.isArray(J[q])?J[q]:[];J[q]=this.dedupeArray([...K,...H])}else J[q]=H}applyDeepMerge(J,q,H){if(typeof H==="object"&&H!==null&&!Array.isArray(H)){let K=typeof J[q]==="object"&&J[q]!==null?J[q]:{};J[q]=k({},K,H)}else J[q]=H}dedupeArray(J){return Array.from(new Set(J))}async atomicWrite(J,q){await C(J,JSON.stringify(q,null,2),{mode:384,encoding:"utf-8"})}}function O(){return z.getInstance()}export{G as Fa,N as Ga,y as Ha,O as Ia};
|
package/dist/chunk-kcjgbbec.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Aa as i,Ba as j,Ca as k,Da as l,Ea as m,sa as a,ta as b,ua as c,va as d,wa as e,xa as f,ya as g,za as h}from"./chunk-8fp3q919.js";import"./chunk-j14rn2dx.js";import"./chunk-81p4kz0b.js";import"./chunk-rxjt7ma7.js";import"./chunk-9xvnrq7m.js";import"./chunk-0g9cb41d.js";import"./chunk-w4xcmzjm.js";export{a as vanillaStore,c as sessionActions,l as getThinkingModeEnabled,b as getState,j as getModelById,e as getMessages,k as getMcpServers,i as getCurrentModel,f as getConfig,h as getAllModels,g as ensureStoreInitialized,m as configActions,d as appActions};
|
package/dist/chunk-q223bq79.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{$a as c,Ya as a,Za as b,ab as d,bb as e,cb as f,db as g,eb as h,fb as i,gb as j,hb as k,ib as l,jb as m,kb as n,lb as o,ob as p,pb as q,qb as r}from"./chunk-6avkjdjc.js";import"./chunk-p4yrmzyr.js";import"./chunk-f3pvwxp8.js";import"./chunk-0z5qe4m2.js";import"./chunk-81p4kz0b.js";import"./chunk-rxjt7ma7.js";import"./chunk-5fw9k1ff.js";import"./chunk-9xvnrq7m.js";import"./chunk-0g9cb41d.js";import"./chunk-w4xcmzjm.js";export{g as saveUserMessage,i as saveToolUse,j as saveToolResult,k as saveCompaction,h as saveAssistantMessage,d as isRootSystemPrompt,l as handleTaskListUpdate,m as handleSkillActivation,n as extractModelSwitch,r as executeLoopGenerator,f as drainLoop,c as checkStopHook,a as checkOutputRecovery,b as checkIncompleteIntent,q as checkAndCompactInLoop,o as applyToolDomainEffects,p as StreamingToolExecutor,e as ConversationState};
|
package/dist/chunk-qwfqp465.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{M as i,N as r}from"./chunk-eycs00af.js";import a from"node:path";function n(e){let t=e.replace(/\s+/g," ").trim();return t.length<=72?t:`${t.slice(0,69)}...`}function c(e){let t=e.replace(/\s+/g," ").trim();return t.length<=500?t:`${t.slice(0,497)}...`}function m(e){return`task/${e.replace(/[^a-zA-Z0-9_-]/g,"-").slice(0,40)}`}class k{static async createSessionTask(e){if(!e.prompt.trim())throw Error("Task prompt must not be blank");if(!a.isAbsolute(e.sourceProjectPath))throw Error("Task source project path must be absolute");let t=a.resolve(e.sourceProjectPath),s;try{return s=e.isolation==="worktree"?await r.enter({sessionId:e.sessionId,workspaceRoot:t,name:m(e.sessionId)}):void 0,{metadata:await i.createSessionMetadata(e.sessionId,s?.workspaceRoot??t,{title:e.title?.trim()||n(e.prompt),taskPromptSummary:c(e.prompt),taskIsolation:e.isolation,taskSourceProjectPath:t,taskWorktree:s}),taskWorktree:s}}catch(o){if(s)await r.exit({sessionId:e.sessionId,action:"remove",discardChanges:!0}).catch(()=>{return});throw o}}}
|
|
2
|
-
export{k as p};
|
package/dist/chunk-rxjt7ma7.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{realpathSync as G}from"fs";import{cwd as b}from"process";var _=null;function T(){let N="";if(typeof process<"u"&&typeof process.cwd==="function"&&typeof G==="function"){let R=b();try{N=G(R).normalize("NFC")}catch{N=R.normalize("NFC")}}return{cwd:N,originalCwd:N,projectRoot:N}}function u(){if(!_)_=T();return _}function U(){return u().cwd}function D(N){u().cwd=N.normalize("NFC")}function X(){return u().originalCwd}function E(){return u().projectRoot}function F(N){u().projectRoot=N.normalize("NFC")}var f;((x)=>{x.DEFAULT="default";x.AUTO_EDIT="autoEdit";x.YOLO="yolo";x.PLAN="plan"})(f||={});import{AsyncLocalStorage as A}from"async_hooks";var V=new A;function $(){return V.getStore()??U()}function M(){try{return $()}catch{return X()}}var Y=100;function Z(N){return Number.isInteger(N)&&N>=-1&&N<=100}function z(){return"-1, 0, or an integer from 1 to 100"}
|
|
2
|
-
export{D as Fb,X as Gb,E as Hb,F as Ib,f as Jb,M as Kb,Y as Lb,Z as Mb,z as Nb};
|
package/dist/chunk-x83a97eh.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{La as a,Ma as b,Na as c,Oa as d,Pa as e,Qa as f}from"./chunk-887qxhn5.js";import"./chunk-w4xcmzjm.js";export{b as getVersion,c as getPackageName,a as getPackageInfo,e as getFormattedVersion,d as getDescription,f as getCopyright};
|
package/dist/chunk-yfcfx0zk.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import{q as A,r as E,s as N,t as f}from"./chunk-w11ht6f9.js";import{u as D}from"./chunk-1evg2hdd.js";import{w as L,x as _,y as x}from"./chunk-8epvwyg8.js";import{z as B}from"./chunk-4fye39a8.js";import{P as $,U as b}from"./chunk-eycs00af.js";import"./chunk-kne7h7p5.js";import"./chunk-6jq8h5s9.js";import"./chunk-fpdqvnmq.js";import"./chunk-8fp3q919.js";import"./chunk-j14rn2dx.js";import"./chunk-11s7t9dp.js";import"./chunk-887qxhn5.js";import{cb as Z}from"./chunk-6avkjdjc.js";import"./chunk-p4yrmzyr.js";import"./chunk-f3pvwxp8.js";import"./chunk-0z5qe4m2.js";import"./chunk-81p4kz0b.js";import{Jb as Y,Kb as T}from"./chunk-rxjt7ma7.js";import"./chunk-5fw9k1ff.js";import"./chunk-9xvnrq7m.js";import"./chunk-0g9cb41d.js";import"./chunk-w4xcmzjm.js";import h from"yargs";import{hideBin as R}from"yargs/helpers";var w=new Set(Object.values(Y));function X(k){if(k&&w.has(k))return k;return}function M(k){return k.command("* [message]","Print response and exit (useful for pipes)",(F)=>F.positional("message",{describe:"Message to process",type:"string"}).option("p",{alias:"print",describe:"Print response and exit (useful for pipes)",type:"boolean"}).option("output-format",{describe:'Output format: "text", "json", "stream-json"',type:"string",default:"text"}).option("include-partial-messages",{describe:"Include partial message chunks as they arrive",type:"boolean"}).option("input-format",{describe:'Input format: "text", "stream-json"',type:"string",default:"text"}).option("model",{describe:"Model for the current session",type:"string"}).option("append-system-prompt",{describe:"Append a system prompt to the default system prompt",type:"string"}).option("system-prompt",{describe:"Replace the default system prompt",type:"string"}).option("max-turns",{alias:["maxTurns"],describe:"Maximum conversation turns (-1: unlimited, N>0: limit to N turns)",type:"number"}),async(F)=>{if(!F.p)return;let q=await O(F);process.exit(q)})}async function O(k,F=process){let q;try{await A();let J=await E({message:k.message,_:k._,defaultMessage:"Hello"}),G=await N(J);if(G.mode==="output"){if(G.content)F.stdout.write(`${G.content}
|
|
2
|
-
`);return G.exitCode??0}let Q=G.content,{sessionId:K,messages:U}=await f({sessionId:k.sessionId,continue:k.continue,resume:k.resume,forkSession:k.forkSession,fallbackSessionPrefix:"print"});q=await $.create({sessionId:K,workspaceRoot:T(),modelId:k.model,mcpConfig:k.mcpConfig,strictMcpConfig:k.strictMcpConfig,agents:k.agents?B(k.agents):void 0});let V=await b.createWithRuntime(q,{sessionId:K,systemPrompt:k.systemPrompt,appendSystemPrompt:k.appendSystemPrompt,maxTurns:k.maxTurns,modelId:k.model,permissionMode:X(k.permissionMode),toolWhitelist:k.allowedTools,toolBlacklist:k.disallowedTools,mcpConfig:k.mcpConfig,strictMcpConfig:k.strictMcpConfig}),H=(await Z(V.chatStream(Q,{messages:[...U],userId:"cli-user",sessionId:K,workspaceRoot:T(),permissionMode:X(k.permissionMode)}))).finalMessage||"";if(k.outputFormat==="json")F.stdout.write(`${JSON.stringify({response:H,input:Q,model:k.model,timestamp:new Date().toISOString()},null,2)}
|
|
3
|
-
`);else if(k.outputFormat==="stream-json")F.stdout.write(`${JSON.stringify({type:"response",content:H})}
|
|
4
|
-
`);else F.stdout.write(`${H}
|
|
5
|
-
`);return 0}catch(J){return F.stderr.write(`Error: ${J instanceof Error?J.message:"未知错误"}
|
|
6
|
-
`),1}finally{await q?.dispose()}}async function d(){if(process.argv.slice(2).findIndex((q)=>q==="--print"||q==="-p")===-1)return!1;try{let{print:q,"output-format":J,"include-partial-messages":G,"input-format":Q,"system-prompt":K,"append-system-prompt":U,"max-turns":V,...W}=D,H=h(R(process.argv)).scriptName("blade").strict(!1).options(W).middleware([_,L,x]);return M(H),await H.parse(),!0}catch(q){console.error(`Print mode error: ${q instanceof Error?q.message:"未知错误"}`),process.exit(1)}}export{O as runPrint,d as handlePrintMode};
|
package/dist/chunk-zns65xsy.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{e as kO,f as EO}from"./chunk-1x3846v7.js";import{p as bO}from"./chunk-qwfqp465.js";import{B as CO,D as XO,E as hS,F as IS,H as yS,I as GS,J as q,K as M,L as _O,M as F,N as qS,P as DO,R as FS,S as CS,U as mO,ba as PO}from"./chunk-eycs00af.js";import{ea as e}from"./chunk-6jq8h5s9.js";import{Aa as eS,Ba as sS,Ea as r,xa as $S,za as rS}from"./chunk-8fp3q919.js";import{Ma as NS}from"./chunk-887qxhn5.js";import{Sa as zO,Ua as DS,cb as ES}from"./chunk-6avkjdjc.js";import{ub as yO}from"./chunk-p4yrmzyr.js";import{Ab as O,Bb as h,Cb as pS,Db as E,yb as t}from"./chunk-0z5qe4m2.js";import{Eb as kS}from"./chunk-81p4kz0b.js";import{Kb as L}from"./chunk-rxjt7ma7.js";import{Vb as W}from"./chunk-9xvnrq7m.js";import{_b as wO,cc as oS,fc as s}from"./chunk-0g9cb41d.js";import{gc as tS}from"./chunk-w4xcmzjm.js";var G0={port:{type:"number",describe:"Port to listen on (0 for auto)",default:0},hostname:{type:"string",describe:"Hostname to listen on",default:"127.0.0.1"},cors:{type:"array",describe:"Additional domains to allow for CORS",default:[]}};function Q0(S){return{port:S.port??0,hostname:S.hostname??"127.0.0.1",cors:S.cors??[]}}import{existsSync as oO,readFileSync as BS}from"node:fs";import{createServer as S0}from"node:http";import{networkInterfaces as O0}from"node:os";import{dirname as x0,extname as j0,join as jS}from"node:path";import{fileURLToPath as $0}from"node:url";import{Hono as N0}from"hono";import{cors as V0}from"hono/cors";import{WebSocketServer as J0}from"ws";class g extends Error{code;statusCode;constructor(S,x,j=500){super(x);this.code=S;this.statusCode=j;this.name="BladeServerError"}toObject(){return{error:{code:this.code,message:this.message}}}}class z extends g{constructor(S,x){super("NOT_FOUND",x?`${S} not found: ${x}`:`${S} not found`,404)}}class m extends g{constructor(S){super("BAD_REQUEST",S,400)}}class I extends g{constructor(S){super("CONFLICT",S,409)}}class o extends g{constructor(){super("AMBIGUOUS_SESSION","Multiple workspaces contain this session ID; projectPath is required",409)}}class u extends g{constructor(S="Internal server error"){super("INTERNAL_ERROR",S,500)}}var f0=O.Object({error:O.Object({code:O.String(),message:O.String()})});import{Hono as eO}from"hono";var HS=W("Service"),sO=O.Object({updates:O.Record(O.String(),O.Any()),options:O.Optional(O.Object({scope:O.Optional(E(["local","project","global"])),immediate:O.Optional(O.Boolean())}))});function Sx(S){return{currentModelId:S.currentModelId,permissionMode:S.permissionMode,language:S.language,theme:S.theme,uiTheme:S.uiTheme,autoSaveSessions:S.autoSaveSessions,notifyBuild:S.notifyBuild,notifyErrors:S.notifyErrors,notifySounds:S.notifySounds,privacyTelemetry:S.privacyTelemetry,privacyCrash:S.privacyCrash}}var dS=()=>{let S=new eO;return S.get("/",async(x)=>{try{let j=$S();return x.json(j?Sx(j):{})}catch(j){return HS.error("[ConfigRoutes] Failed to get config:",j),x.json({})}}),S.put("/",async(x)=>{try{let j=await x.req.json(),$=t(sO,j);if(!$.success)throw new m("Invalid config update format");let{updates:V,options:A}=$.data;return await r().updateConfig(V,A),x.json({success:!0,updates:V})}catch(j){throw HS.error("[ConfigRoutes] Failed to update config:",j),j}}),S.get("/permissions",async(x)=>{try{let j=$S();return x.json(j?.permissions||{})}catch(j){return HS.error("[ConfigRoutes] Failed to get permissions:",j),x.json({})}}),S};import{Hono as Ox}from"hono";import{streamSSE as xx}from"hono/streaming";var jx=15000,$x=new Set(["task.status"]),Nx=new Set(["queued","running","completed","failed","cancelled","interrupted"]);function Vx(S){if(!S||typeof S!=="object"||Array.isArray(S))return;let x=S,j=["changedFiles","additions","deletions","commits"];if(j.some(($)=>typeof x[$]!=="number"||!Number.isInteger(x[$])||x[$]<0))return;return Object.fromEntries(j.map(($)=>[$,x[$]]))}var aS=()=>{let S=new Ox;return S.get("/",(x)=>xx(x,async(j)=>{let $,V,A=!1,Y=()=>{if(V!==void 0)clearInterval(V),V=void 0;$?.(),$=void 0},f=()=>{if(A)return;A=!0,Y()};j.onAbort(f),$=M.subscribe((Z)=>{if(!$x.has(Z.type))return;let w=Z.properties.taskStatus;if(typeof w!=="string"||!Nx.has(w))return;let b=Vx(Z.properties.taskDiffStat);j.writeSSE({data:JSON.stringify({type:Z.type,properties:{sessionId:Z.sessionId,projectPath:Z.projectPath,taskStatus:w,...typeof Z.properties.taskStatusReason==="string"?{taskStatusReason:Z.properties.taskStatusReason}:{},...typeof Z.properties.taskStartedAt==="string"?{taskStartedAt:Z.properties.taskStartedAt}:{},...typeof Z.properties.taskCompletedAt==="string"?{taskCompletedAt:Z.properties.taskCompletedAt}:{},...typeof Z.properties.updatedAt==="string"?{updatedAt:Z.properties.updatedAt}:{},...b?{taskDiffStat:b}:{}}})}).catch(f)});try{if(j.aborted||A)return;if(await j.writeSSE({data:JSON.stringify({type:"connected",properties:{timestamp:Date.now()}})}),j.aborted||A)return;V=setInterval(()=>{if(j.aborted||A)return;j.writeSSE({data:JSON.stringify({type:"heartbeat",properties:{timestamp:Date.now()}})}).catch(f)},jx);while(!j.aborted&&!A)await new Promise((Z)=>setTimeout(Z,1000))}finally{f()}})),S};import{Hono as Jx}from"hono";var iS=()=>{let S=new Jx;return S.get("/health",(x)=>{return x.json({healthy:!0,version:NS()})}),S.get("/info",(x)=>{let j=L();return x.json({version:NS(),platform:process.platform,arch:process.arch,nodeVersion:process.version,cwd:j,gitBranch:oS(j)})}),S};import{Hono as Tx}from"hono";var YS=W("Service"),nS=()=>{let S=new Tx;return S.get("/",async(x)=>{try{let $=e.getInstance().getAllServers(),V=Array.from($.entries()).map(([A,Y])=>({id:A,name:A,status:Y.status==="connected"?"connected":Y.status==="connecting"?"connecting":Y.lastError?"error":"offline",endpoint:Y.config.command?`${Y.config.command} ${(Y.config.args||[]).join(" ")}`.trim():Y.config.url||"Unknown",description:`MCP server: ${A}`,tools:Y.tools.map((f)=>f.name),connectedAt:Y.connectedAt?.toISOString(),error:Y.lastError?.message}));return x.json(V)}catch(j){return YS.error("[McpRoutes] Failed to get MCP servers:",j),x.json([])}}),S.post("/:name/connect",async(x)=>{try{let j=x.req.param("name");return await e.getInstance().connectServer(j),x.json({success:!0})}catch(j){return YS.error("[McpRoutes] Failed to connect MCP server:",j),x.json({success:!1,error:j.message},500)}}),S.post("/:name/disconnect",async(x)=>{try{let j=x.req.param("name");return await e.getInstance().disconnectServer(j),x.json({success:!0})}catch(j){return YS.error("[McpRoutes] Failed to disconnect MCP server:",j),x.json({success:!1,error:j.message},500)}}),S.delete("/:name",async(x)=>{try{let j=x.req.param("name");await e.getInstance().unregisterServer(j);let V=$S();if(V?.mcpServers){let{[j]:A,...Y}=V.mcpServers;await r().updateConfig({mcpServers:Y})}return x.json({success:!0})}catch(j){return YS.error("[McpRoutes] Failed to delete MCP server:",j),x.json({success:!1,error:j.message},500)}}),S.post("/",async(x)=>{try{let j=await x.req.json(),{name:$,config:V}=j;if(!$||!V)return x.json({success:!1,error:"Missing name or config"},400);await e.getInstance().registerServer($,V);let Y=$S();return await r().updateConfig({mcpServers:{...Y?.mcpServers,[$]:V}}),x.json({success:!0})}catch(j){return YS.error("[McpRoutes] Failed to add MCP server:",j),x.json({success:!1,error:j.message},500)}}),S};import{Hono as Ax}from"hono";var US=W("Service");function Yx(S,x){return{id:S.id,displayName:S.displayName,provider:S.provider,model:S.model,overrides:S.overrides,fallbackModels:S.fallbackModels,contextWindow:x.contextWindow,maxTokens:x.maxTokens,reasoning:x.reasoning,input:x.input}}function px(S){let x={displayName:S.displayName||void 0,overrides:S.overrides||void 0};if(S.model)x.model=S.model;return x}var SO=()=>{let S=new Ax;return S.get("/",async(x)=>{try{let j=rS(),$=eS(),V=s(),A=(Y)=>Yx(Y,V.resolveConfig(Y));return x.json({configured:j.map(A),current:$?A($):null})}catch(j){return US.error("[ModelsRoutes] Failed to get models:",j),x.json({configured:[],current:null})}}),S.post("/",async(x)=>{try{let j=await x.req.json(),{provider:$,displayName:V,model:A,overrides:Y,apiKey:f}=j;if(!$||!A)throw new m("provider and model are required");if(s().getModel($,A),f?.trim())await s().setApiKey($,f.trim());let Z=await r().addModel({provider:$,displayName:V||void 0,model:A,overrides:Y||void 0});return x.json({success:!0,model:Z})}catch(j){throw US.error("[ModelsRoutes] Failed to add model:",j),j}}),S.put("/:modelId",async(x)=>{try{let j=x.req.param("modelId"),$=await x.req.json(),{displayName:V,overrides:A,model:Y}=$,f=sS(j);if(!f)throw new m("model config not found");if(Y)s().getModel(f.provider,Y);return await r().updateModel(j,px({displayName:V,overrides:A,model:Y})),x.json({success:!0})}catch(j){throw US.error("[ModelsRoutes] Failed to update model:",j),j}}),S.delete("/:modelId",async(x)=>{try{let j=x.req.param("modelId");return await r().removeModel(j),x.json({success:!0})}catch(j){throw US.error("[ModelsRoutes] Failed to delete model:",j),j}}),S};import{Hono as Fx}from"hono";import ZO from"node:path";import{Mutex as _x}from"async-mutex";import{Hono as Dx}from"hono";import{streamSSE as mx}from"hono/streaming";import{LRUCache as bx}from"lru-cache";import{nanoid as VS}from"nanoid";var KS=h(E(["default","autoEdit","yolo","plan"]));var WS=h(E(["user","assistant","system","tool"])),Gx=h(O.Union([O.Object({type:O.Literal("text"),text:O.String()}),O.Object({type:O.Literal("image_url"),image_url:O.Object({url:O.String()})})])),xO=O.Union([O.String(),O.Array(Gx)]),o0=h(O.Object({id:O.String(),role:WS,content:xO,timestamp:O.Number(),metadata:O.Optional(O.Record(O.String(),O.Unknown())),thinkingContent:O.Optional(O.String()),tool_call_id:O.Optional(O.String()),name:O.Optional(O.String()),tool_calls:O.Optional(O.Unknown())})),Qx=h(E(["queued","running","completed","failed","cancelled","interrupted"])),jO=h(E(["local","worktree"])),Zx=h(O.Object({changedFiles:O.Integer({minimum:0}),additions:O.Integer({minimum:0}),deletions:O.Integer({minimum:0}),commits:O.Integer({minimum:0})})),Ux=h(O.Object({path:O.String({minLength:1}),patch:O.String({maxLength:2097152}),additions:O.Integer({minimum:0}),deletions:O.Integer({minimum:0}),binary:O.Boolean(),truncated:O.Boolean()})),$O=h(O.Object({sessionId:O.String(),projectPath:O.String(),baseCommit:O.String(),files:O.Array(Ux,{maxItems:100}),truncated:O.Boolean()})),NO=h(O.Object({sessionId:O.String(),projectPath:O.String(),title:O.Optional(O.String()),gitBranch:O.Optional(O.String()),rootId:O.String(),parentId:O.Optional(O.String()),relationType:O.Optional(E(["subagent","fork"])),resumedFrom:O.Optional(O.String()),rootAgentId:O.Optional(O.String()),resumeDepth:O.Optional(O.Integer({minimum:0})),taskStatus:pS(Qx,"completed"),taskStatusReason:O.Optional(O.String()),taskStartedAt:O.Optional(O.String()),taskCompletedAt:O.Optional(O.String()),taskPromptSummary:O.Optional(O.String()),taskIsolation:O.Optional(jO),taskSourceProjectPath:O.Optional(O.String()),taskWorktreePath:O.Optional(O.String()),taskWorktreeBranch:O.Optional(O.String()),taskBaseCommit:O.Optional(O.String()),taskDiffStat:O.Optional(Zx),messageCount:O.Number(),firstMessageTime:O.String(),lastMessageTime:O.String(),hasErrors:O.Boolean()})),i0=h(O.Object({version:O.Literal(1),sessionId:O.String(),goalId:O.String(),objective:O.String(),status:E(["active","paused","blocked","usage_limited","budget_limited","complete"]),tokenBudget:O.Optional(O.Number()),tokensUsed:O.Number(),timeUsedSeconds:O.Number(),continuationCount:O.Number(),statusReason:O.Optional(O.String()),createdAt:O.String(),updatedAt:O.String()})),VO=h(O.Object({role:WS,content:xO,metadata:O.Optional(O.Unknown()),reasoningContent:O.Optional(O.String()),thinkingContent:O.Optional(O.String()),tool_call_id:O.Optional(O.String()),name:O.Optional(O.String()),tool_calls:O.Optional(O.Unknown())})),n0=h(O.Object({session:NO,messages:O.Array(VO)})),JO=h(E(["conversation","code","both"])),fx=h(O.Object({messageId:O.String(),preview:O.String(),createdAt:O.String(),fileCount:O.Integer({minimum:0})})),TO=h(O.Object({targetMessageId:O.String({minLength:1}),mode:pS(JO,"conversation")})),r0=h(O.Object({checkpoint:fx,mode:JO,removedTurns:O.Integer({minimum:1}),restoredFiles:O.Array(O.String()),messages:O.Array(VO)})),wx=E(["running","completed","failed","cancelled"]),OO=h(O.Object({id:O.String(),subagentType:O.String(),description:O.String(),status:wx,rootAgentId:O.String(),resumedFrom:O.Optional(O.String()),resumeDepth:O.Integer({minimum:0}),createdAt:O.Number(),lastActiveAt:O.Number(),completedAt:O.Optional(O.Number()),result:O.Optional(O.Object({success:O.Boolean(),message:O.String(),error:O.Optional(O.String()),verificationCommands:O.Optional(O.Array(O.String()))})),stats:O.Optional(O.Object({tokens:O.Optional(O.Number()),toolCalls:O.Optional(O.Number()),duration:O.Optional(O.Number())}))})),AO=h(O.Object({prompt:O.String({minLength:1,maxLength:32000,pattern:"\\S"})})),e0=h(O.Object({source:OO,session:OO})),s0=h(O.Object({sessionId:O.String(),projectPath:O.String()})),S1=h(O.Object({type:O.String(),properties:O.Record(O.String(),O.Unknown())})),YO=O.Object({type:E(["file","image","url"]),path:O.Optional(O.String()),url:O.Optional(O.String()),content:O.Optional(O.String()),mimeType:O.Optional(O.String()),name:O.Optional(O.String())}),pO=h(O.Object({prompt:O.String({minLength:1,maxLength:32000,pattern:"\\S"}),title:O.Optional(O.String({minLength:1,maxLength:200})),projectPath:O.Optional(O.String()),isolation:pS(jO,"worktree"),permissionMode:pS(KS,"default"),attachments:O.Optional(O.Array(YO))})),GO=h(O.Object({session:NO,runId:O.String(),messageId:O.String(),status:O.Literal("running")})),QO=h(O.Object({content:O.String(),projectPath:O.Optional(O.String()),permissionMode:O.Optional(KS),attachments:O.Optional(O.Array(YO))})),O1=h(O.Object({messageId:O.String(),role:WS,content:O.String(),timestamp:O.String()})),x1=h(O.Object({approved:O.Boolean(),remember:O.Optional(O.Boolean()),scope:O.Optional(E(["once","session","project"])),targetMode:O.Optional(KS),feedback:O.Optional(O.String()),answers:O.Optional(O.Record(O.String(),O.Union([O.String(),O.Array(O.String())])))})),j1=h(O.Object({id:O.String(),displayName:O.Optional(O.String()),provider:O.String(),model:O.String(),contextWindow:O.Optional(O.Number()),maxTokens:O.Optional(O.Number()),reasoning:O.Optional(O.Boolean()),input:O.Optional(O.Array(E(["text","image"]))),overrides:O.Optional(O.Object({baseUrl:O.Optional(O.String()),temperature:O.Optional(O.Number()),maxOutputTokens:O.Optional(O.Number()),timeout:O.Optional(O.Number())}))})),$1=h(E(["vs-dark","vs-light","hc-black"])),yx=h(E(["light","dark","system"])),Xx=h(O.Object({language:O.String(),theme:O.String(),uiTheme:yx,autoSaveSessions:O.Boolean(),notifyBuild:O.Boolean(),notifyErrors:O.Boolean(),notifySounds:O.Boolean(),privacyTelemetry:O.Boolean(),privacyCrash:O.Boolean()})),N1=h(O.Partial(Xx));var H=W("Service"),hx=O.Object({title:O.Optional(O.String()),projectPath:O.Optional(O.String())}),Bx=QO,Mx=O.Object({title:O.Optional(O.String()),projectPath:O.Optional(O.String())}),Hx=O.Object({projectPath:O.String()}),Kx=O.Object({objective:O.String({minLength:1}),tokenBudget:O.Optional(O.Integer({minimum:1})),permissionMode:O.Optional(E(["default","autoEdit","plan","yolo"]))}),Wx=O.Union([O.Object({action:O.Literal("pause")}),O.Object({action:O.Literal("resume")}),O.Object({action:O.Literal("edit"),objective:O.String({minLength:1})})]),R=new Map,C=new bx({max:100,ttl:1800000,dispose:(S,x)=>{if(S.status==="running"||S.status==="waiting_permission")S.abortController.abort(),H.debug(`[SessionRoutes] Run ${x} disposed due to cache eviction`)}});function kx(S){return{sessionId:S.sessionId,projectPath:S.projectPath}}function _S(S,x="user-cancel"){if(S.status==="cancelled"||S.status==="completed"||S.status==="failed")return!1;let j=S.pendingPermission;return S.pendingPermission=void 0,j?.resolve({approved:!1,reason:yO}),S.abortController.abort(x),S.status="cancelled",M.publish(kx(S),"run.cancelled",{runId:S.id}),!0}function hO(S,x=!1){let{permissionId:j,details:$}=S;if($.type==="askUserQuestion"&&$.questions)return{type:"question.required",properties:{requestId:j,toolCallId:j,questions:$.questions,details:$,...x?{replayed:!0}:{}}};return{type:"permission.asked",properties:{requestId:j,toolName:$.toolName,description:$.message,args:$.args,details:$,...x?{replayed:!0}:{}}}}function Ex(){for(let S of C.values())_S(S,"route-reset");C.clear(),R.clear()}var BO=(S)=>{if(!S||typeof S!=="object")return S;let x={...S},j=200000;if(typeof x.oldContent==="string"&&x.oldContent.length>j)delete x.oldContent;if(typeof x.newContent==="string"&&x.newContent.length>j)delete x.newContent;return x};function qx(S,x,j){switch(j.kind){case"tool_start":if("function"in j.toolCall)M.publish(S,"subagent.update",{subagentSessionId:x,toolName:j.toolCall.function.name}),M.publish(S,"subagent.tool.start",{subagentSessionId:x,toolCallId:j.toolCall.id,toolName:j.toolCall.function.name,arguments:j.toolCall.function.arguments,toolKind:j.toolKind});break;case"tool_result":if("function"in j.toolCall)M.publish(S,"subagent.tool.result",{subagentSessionId:x,toolCallId:j.toolCall.id,toolName:j.toolCall.function.name,success:!j.result.error,summary:j.result.metadata?.summary,output:CS(FS(j.toolCall.function.name,j.result)),metadata:BO(j.result.metadata)});break;case"content_delta":M.publish(S,"subagent.delta",{subagentSessionId:x,delta:j.delta});break;case"thinking_delta":M.publish(S,"subagent.thinking.delta",{subagentSessionId:x,delta:j.delta});break;case"stream_end":M.publish(S,"subagent.stream.end",{subagentSessionId:x});break;default:break}}function XS(S,x="projectPath"){if(!ZO.isAbsolute(S))throw new m(`${x} must be absolute`);return ZO.resolve(S)}function zS(S){try{wO(S)}catch(x){throw new m(x instanceof Error?x.message:`Invalid session ID: ${S}`)}}function v(S){return{sessionId:S.id,projectPath:S.projectPath}}function fS(S,x,j){return{id:S.sessionId,projectPath:S.projectPath,title:S.title??`Session ${S.sessionId.slice(0,6)}`,createdAt:new Date(S.firstMessageTime),updatedAt:new Date(S.lastMessageTime),rootId:S.rootId,parentId:S.parentId,relationType:S.relationType,taskStatus:S.taskStatus,taskStatusReason:S.taskStatusReason,taskStartedAt:S.taskStartedAt,taskCompletedAt:S.taskCompletedAt,taskPromptSummary:S.taskPromptSummary,taskIsolation:S.taskIsolation,taskSourceProjectPath:S.taskSourceProjectPath,taskWorktreePath:S.taskWorktreePath,taskWorktreeBranch:S.taskWorktreeBranch,taskBaseCommit:S.taskBaseCommit,taskDiffStat:S.taskDiffStat,taskWorktree:j,messages:x}}function zx(S,x){S.taskStatus=x.taskStatus,S.taskStatusReason=x.taskStatusReason,S.taskStartedAt=x.taskStartedAt,S.taskCompletedAt=x.taskCompletedAt,S.taskPromptSummary=x.taskPromptSummary,S.taskIsolation=x.taskIsolation,S.taskSourceProjectPath=x.taskSourceProjectPath,S.taskWorktreePath=x.taskWorktreePath,S.taskWorktreeBranch=x.taskWorktreeBranch,S.taskBaseCommit=x.taskBaseCommit,S.taskDiffStat=x.taskDiffStat,S.updatedAt=new Date(x.lastMessageTime)}async function UO(S){let x=await F.findSessionMetadata(S.id,S.projectPath);if(x)zx(S,x)}function wS(S){let x=S.currentRunId?C.get(S.currentRunId):void 0,j=x?.status==="waiting_permission"?"running":x?.status??S.taskStatus;return{sessionId:S.id,projectPath:S.projectPath,title:S.title,rootId:S.rootId,parentId:S.parentId,relationType:S.relationType,status:void 0,taskStatus:j,taskStatusReason:S.taskStatusReason,taskStartedAt:S.taskStartedAt,taskCompletedAt:S.taskCompletedAt,taskPromptSummary:S.taskPromptSummary,taskIsolation:S.taskIsolation,taskSourceProjectPath:S.taskSourceProjectPath,taskWorktreePath:S.taskWorktreePath,taskWorktreeBranch:S.taskWorktreeBranch,taskBaseCommit:S.taskBaseCommit,taskDiffStat:S.taskDiffStat,agentType:void 0,model:void 0,messageCount:S.messages.length,firstMessageTime:S.createdAt.toISOString(),lastMessageTime:S.updatedAt.toISOString(),hasErrors:!1,isActive:!0}}async function n(S,x){if(zS(S),x!==void 0){let $=GS({sessionId:S,projectPath:XS(x)});if(R.has(q($)))return $;let V=await F.findSessionMetadata($.sessionId,$.projectPath);if(!V)throw new z("Session",S);return GS({sessionId:V.sessionId,projectPath:V.projectPath})}let j=new Map;for(let $ of R.values()){if($.id!==S)continue;let V=v($);j.set(q(V),V)}for(let $ of await F.listSessions()){if($.sessionId!==S)continue;let V=GS({sessionId:$.sessionId,projectPath:$.projectPath});j.set(q(V),V)}if(j.size===0)try{let $=await F.findSessionMetadata(S);if(!$)throw new z("Session",S);return GS({sessionId:$.sessionId,projectPath:$.projectPath})}catch($){if($ instanceof z)throw $;if($ instanceof Error&&$.message.startsWith("Ambiguous session ID:"))throw new o;throw $}if(j.size>1)throw new o;return j.values().next().value}function LS(S){if(typeof S==="string")return S;return S.filter((x)=>x.type==="text").map((x)=>x.text).join(`
|
|
2
|
-
`)}function fO(S,x){let j=(x??[]).filter((V)=>V.type==="image"&&typeof V.content==="string").map((V)=>({type:"image_url",image_url:{url:V.content}}));if(j.length===0)return S;let $=[];if(S.trim())$.push({type:"text",text:S});return $.push(...j),$}var MO=()=>{Ex();let S=new Dx;S.onError((N,T)=>{if(N instanceof g)return T.json(N.toObject(),N.statusCode);return H.error("[SessionRoutes] Unhandled route error:",N),T.json({error:{code:"INTERNAL_ERROR",message:"Internal server error"}},500)});let x=new Map,j=new Map,$=new Map,V=new Map,A=(N)=>{let T=q(N),J=V.get(T);if(!J)J=new _x,V.set(T,J);return J},Y=async(N)=>{let T=q(v(N)),J=x.get(T);if(J)return J;let G=j.get(T);if(!G)G=DO.create({sessionId:N.id,workspaceRoot:N.projectPath,...N.taskWorktree?{taskWorktree:N.taskWorktree}:{}}),j.set(T,G);try{let p=await G;return x.set(T,p),p}finally{if(j.get(T)===G)j.delete(T)}},f=async(N)=>{let T=q(N),J=R.get(T);if(J)return J;let G=$.get(T);if(!G)G=(async()=>{let p=await F.findSessionMetadata(N.sessionId,N.projectPath);if(!p)throw new z("Session",N.sessionId);let[X,U]=await Promise.all([F.loadSession(N.sessionId,N.projectPath),F.findSessionTaskWorktree(N.sessionId,N.projectPath)]),_=fS(p,X,U);return R.set(T,_),_})(),$.set(T,G);try{return await G}finally{if($.get(T)===G)$.delete(T)}},Z=async(N,T)=>{return f(await n(N,T))},w=(N,T,J,G={})=>{let p=VS(12),X={id:p,sessionId:N.id,projectPath:N.projectPath,status:"running",abortController:new AbortController,createdAt:new Date};return C.set(p,X),N.currentRunId=p,X.completion=Lx(X,N,T,J,Y,{pendingInputOnly:G.pendingInputOnly,preparedInputTurn:G.preparedInputTurn,goalContinuationOnly:G.goalContinuationOnly}).catch((U)=>{H.error(`[SessionRoutes] Run ${p} failed:`,U)}),X},b=async(N)=>{let T=kS("task",12),J=XS(N.sourceProjectPath),G,p;try{let X=await bO.createSessionTask({sessionId:T,prompt:N.prompt,title:N.title,sourceProjectPath:J,isolation:N.isolation}),{metadata:U}=X;G=X.taskWorktree,p=fS(U,[],G);let _=v(p);R.set(q(_),p),M.publish(_,"task.status",{taskStatus:U.taskStatus,updatedAt:U.lastMessageTime});let D=fO(N.prompt,N.attachments),y=await(await Y(p)).prepareInputTurn(D);if(!y.accepted)throw new I(`Task prompt was not accepted: ${y.reason}`);let l=w(p,D,N.permissionMode,{preparedInputTurn:y});return{session:wS(p),runId:l.id,messageId:y.messageId,status:"running"}}catch(X){if(p){let U=await F.findSessionMetadata(p.id,p.projectPath).catch(()=>{return});if(!U||U.taskStatus==="queued"){let _=await F.updateSessionMetadata(p.id,p.projectPath,{taskStatus:"failed",taskStatusReason:"Task dispatch failed",taskCompletedAt:new Date().toISOString(),taskOwnerPid:null}).catch(()=>{return});p.taskStatus=_?.taskStatus??"failed",p.taskStatusReason=_?.taskStatusReason??"Task dispatch failed",p.taskCompletedAt=_?.taskCompletedAt}else p.taskStatus=U.taskStatus,p.taskStatusReason=U.taskStatusReason,p.taskCompletedAt=U.taskCompletedAt}throw X}},B=async(N,T)=>{let J=await Z(N,T);if(!J.taskWorktree)throw new m("Session does not have a task worktree");try{await qS.restoreSession(J.taskWorktree);let G=await qS.getDiffArtifact(J.id);if(!G)throw new I("Task diff artifact is unavailable");return{sessionId:J.id,projectPath:J.projectPath,...G}}catch(G){if(G instanceof I)throw G;throw H.error("[SessionRoutes] Failed to load task diff artifact:",G),new I("Task diff artifact is unavailable")}},K=async(N)=>{let T=N.currentRunId?C.get(N.currentRunId):void 0;if(T&&(T.status==="running"||T.status==="waiting_permission"))return;let J=await Y(N),G=N.currentRunId?C.get(N.currentRunId):void 0;if(G&&(G.status==="running"||G.status==="waiting_permission"))return;let p=J.getPendingSteeringCount()>0,U=(p?null:await J.getGoal())?.status==="active";if(!p&&!U||J.hasTurnOwner())return;w(N,"","default",{pendingInputOnly:p,goalContinuationOnly:U})};return S.get("/",async(N)=>{try{let T=await F.listSessions(),J=new Set(T.filter((Q)=>Q.relationType==="subagent").map((Q)=>q({sessionId:Q.sessionId,projectPath:Q.projectPath}))),G=Array.from(R.values()).filter((Q)=>!J.has(q(v(Q)))&&Q.relationType!=="subagent").map((Q)=>wS(Q)),p=new Set(G.map((Q)=>q({sessionId:Q.sessionId,projectPath:Q.projectPath}))),X=T.filter((Q)=>{if(Q.relationType==="subagent")return!1;return!p.has(q({sessionId:Q.sessionId,projectPath:Q.projectPath}))}),U=new Set(p),_=X.filter((Q)=>{let y=q({sessionId:Q.sessionId,projectPath:Q.projectPath});if(U.has(y))return!1;return U.add(y),!0}),D=[...G,..._];return N.json(D)}catch(T){throw H.error("[SessionRoutes] Failed to list sessions:",T),new u("Failed to list sessions")}}),S.post("/",async(N)=>{try{let T=await N.req.json(),J=t(hx,T);if(!J.success)throw new m("Invalid request body");let{title:G,projectPath:p}=J.data,X=kS("web",12),U=XS(p||N.get("directory")||L(),p?"projectPath":"directory"),_=await F.createSessionMetadata(X,U,{title:G}),D=fS(_,[]),Q=v(D);return R.set(q(Q),D),M.publish(Q,"task.status",{taskStatus:_.taskStatus,updatedAt:_.lastMessageTime}),N.json({...wS(D),status:void 0,agentType:void 0,model:void 0})}catch(T){if(H.error("[SessionRoutes] Failed to create session:",T),T instanceof m)throw T;throw new u("Failed to create session")}}),S.post("/:sessionId/fork",async(N)=>{let T=N.req.param("sessionId");try{zS(T);let J=await N.req.json(),G=t(Hx,J);if(!G.success)throw new m("Invalid request body");let p=XS(G.data.projectPath),X=await F.findSessionMetadata(T,p);if(!X)throw new z("Session",T);let U=await F.forkSession(T,{sourceProjectPath:X.projectPath,targetProjectPath:X.projectPath}),_=fS(U.metadata,U.messages),D=v(_);return R.set(q(D),_),M.publish(D,"task.status",{taskStatus:U.metadata.taskStatus,...U.metadata.taskCompletedAt?{taskCompletedAt:U.metadata.taskCompletedAt}:{},updatedAt:U.metadata.lastMessageTime}),N.json({session:U.metadata,messages:U.messages},201)}catch(J){if(J instanceof m||J instanceof z||J instanceof I)throw J;if(J instanceof _O)throw new I("Session has no durable creation record");throw H.error("[SessionRoutes] Failed to fork session:",J),new u("Failed to fork session")}}),S.get("/:sessionId",async(N)=>{let T=N.req.param("sessionId");try{let J=await n(T,N.req.query("projectPath")),G=R.get(q(J));if(G)return N.json(wS(G));let p=await F.findSessionMetadata(J.sessionId,J.projectPath);if(!p)throw new z("Session",T);return N.json(p)}catch(J){if(J instanceof m||J instanceof z||J instanceof o)throw J;throw H.error("[SessionRoutes] Failed to get session:",J),new u("Failed to get session")}}),S.patch("/:sessionId",async(N)=>{let T=N.req.param("sessionId");try{let J=await N.req.json(),G=t(Mx,J);if(!G.success)throw new m("Invalid request body");if(G.data.title===void 0)throw new m("title is required");let p=await n(T,G.data.projectPath),X=await F.updateSessionMetadata(p.sessionId,p.projectPath,{title:G.data.title}),U=R.get(q(p));if(U)U.title=X.title??U.title,U.updatedAt=new Date(X.lastMessageTime);return N.json({success:!0,title:X.title})}catch(J){if(H.error("[SessionRoutes] Failed to update session:",J),J instanceof m||J instanceof z||J instanceof o)throw J;throw new u("Failed to update session")}}),S.get("/:sessionId/rewind",async(N)=>{let T=await Z(N.req.param("sessionId"),N.req.query("projectPath")),J=await Y(T);return N.json({checkpoints:await J.listRewindCheckpoints()})}),S.post("/:sessionId/rewind",async(N)=>{let T=t(TO,await N.req.json());if(!T.success)throw new m("Invalid rewind request");let J=await Z(N.req.param("sessionId"),N.req.query("projectPath")),G=v(J);return A(G).runExclusive(async()=>{let p=J.currentRunId?C.get(J.currentRunId):void 0;if(p&&(p.status==="running"||p.status==="waiting_permission"))throw new I("Cannot rewind while a run is active");let X=await Y(J),U;try{U=await X.rewindSession(T.data)}catch(_){if(_ instanceof Error&&_.message.startsWith("Cannot rewind while"))throw new I(_.message);throw _}return J.messages=[...U.messages],J.updatedAt=new Date,M.publish(G,"session.rewound",{targetMessageId:U.checkpoint.messageId,mode:U.mode,removedTurns:U.removedTurns,restoredFiles:U.restoredFiles,messages:U.messages}),N.json(U)})}),S.get("/:sessionId/subagents",async(N)=>{let T=await Z(N.req.param("sessionId"),N.req.query("projectPath")),J=await Y(T);return N.json({subagents:J.listSubagents().map(yS)})}),S.post("/:sessionId/subagents/:agentId/resume",async(N)=>{zS(N.req.param("agentId"));let T=AO.safeParse(await N.req.json());if(!T.success)throw new m("Invalid subagent resume request");let J=await Z(N.req.param("sessionId"),N.req.query("projectPath")),G=v(J);return A(G).runExclusive(async()=>{let p=J.currentRunId?C.get(J.currentRunId):void 0;if(p&&(p.status==="running"||p.status==="waiting_permission"))throw new I("Cannot resume a subagent while a parent run is active");let X=await Y(J),U=!1,_,D=(y)=>{M.publish(G,"subagent.complete",{subagentSessionId:y.id,success:y.status==="completed",status:y.status,summary:y.result?.message?.slice(0,500),resumedFrom:y.resumedFrom,rootAgentId:y.rootAgentId,resumeDepth:y.resumeDepth})},Q;try{Q=X.resumeSubagent({agentId:N.req.param("agentId"),prompt:T.data.prompt,onEvent:(y,l)=>{qx(G,l,y)},onCompleted:(y)=>{if(U)D(y);else _=y}})}catch(y){if(y instanceof Error&&(y.message.startsWith("Cannot resume")||y.message.startsWith("Subagent cannot")))throw new I(y.message);if(y instanceof Error&&y.message.startsWith("Subagent not found"))throw new z(y.message);throw y}if(M.publish(G,"subagent.start",{subagentSessionId:Q.session.id,type:Q.session.subagentType,description:Q.session.description,resumedFrom:Q.source.id,rootAgentId:Q.session.rootAgentId,resumeDepth:Q.session.resumeDepth}),U=!0,_)D(_);return N.json({source:yS(Q.source),session:yS(Q.session)})})}),S.get("/:sessionId/goal",async(N)=>{let T=await Z(N.req.param("sessionId"),N.req.query("projectPath"));return N.json({goal:await new XO(T.projectPath,T.id).get()})}),S.put("/:sessionId/goal",async(N)=>{let T=t(Kx,await N.req.json());if(!T.success)throw new m("Invalid goal request");let J=await Z(N.req.param("sessionId"),N.req.query("projectPath")),G=v(J);return A(G).runExclusive(async()=>{let p=J.currentRunId?C.get(J.currentRunId):void 0;if(p&&(p.status==="running"||p.status==="waiting_permission"))return N.json({status:"rejected",reason:"run_active"},409);let U=await(await Y(J)).createGoal(T.data);M.publish(G,"goal.updated",{goal:U});let _=T.data.permissionMode??"default",D=w(J,"",_,{goalContinuationOnly:!0});return N.json({status:"running",runId:D.id,goal:U},202)})}),S.patch("/:sessionId/goal",async(N)=>{let T=t(Wx,await N.req.json());if(!T.success)throw new m("Invalid goal update");let J=await Z(N.req.param("sessionId"),N.req.query("projectPath")),G=v(J);return A(G).runExclusive(async()=>{let p=await Y(J),X;if(T.data.action==="pause")X=await p.pauseGoal();else if(T.data.action==="edit")X=await p.editGoal(T.data.objective);else X=await p.resumeGoal();if(M.publish(G,"goal.updated",{goal:X}),X.status==="active"&&(!J.currentRunId||!["running","waiting_permission"].includes(C.get(J.currentRunId)?.status??""))){let U=w(J,"","default",{goalContinuationOnly:!0});return N.json({status:"running",runId:U.id,goal:X},202)}return N.json({status:X.status,goal:X})})}),S.delete("/:sessionId/goal",async(N)=>{let T=await Z(N.req.param("sessionId"),N.req.query("projectPath")),J=v(T),p=await(await Y(T)).clearGoal();if(p)M.publish(J,"goal.cleared",{});return N.json({cleared:p})}),S.delete("/:sessionId",async(N)=>{let T=N.req.param("sessionId"),J=N.req.query("projectPath");try{let G=await n(T,J),p=q(G),X=R.get(p),U=x.get(p),_;if(X?.currentRunId){let D=C.get(X.currentRunId);if(D)_S(D),await D.completion,_=D.id}if(U)await U.clearGoal().catch((D)=>{H.warn("[SessionRoutes] Failed to clear session goal:",D)});if(await F.deleteSession(G.sessionId,G.projectPath),_)C.delete(_);if(R.delete(p),$.delete(p),j.delete(p),V.delete(p),U){if(await U.dispose(),x.delete(p),x.size===0)await e.getInstance().disconnectAll()}return N.json({success:!0})}catch(G){if(H.error("[SessionRoutes] Failed to delete session:",G),G instanceof m||G instanceof z||G instanceof o)throw G;throw new u("Failed to delete session")}}),S.get("/:sessionId/message",async(N)=>{let T=N.req.param("sessionId");try{let J=await n(T,N.req.query("projectPath")),G=R.get(q(J)),p=G?.messages?G.messages:await F.loadSession(J.sessionId,J.projectPath);return N.json(p)}catch(J){if(H.error("[SessionRoutes] Failed to get messages:",J),J instanceof m||J instanceof z||J instanceof o)throw J;throw new u("Failed to get messages")}}),S.get("/:sessionId/events",async(N)=>{let T=N.req.param("sessionId"),J=await n(T,N.req.query("projectPath")),G=await f(J);return mx(N,async(p)=>{let U,_,D=!1,Q=()=>{if(_!==void 0)clearInterval(_),_=void 0;U?.(),U=void 0},y=()=>{if(D)return;D=!0,Q()},l=new Set;p.onAbort(y),U=M.subscribe((k)=>{if(k.sessionId!==J.sessionId||k.projectPath!==J.projectPath)return;let d=k.properties.requestId;if((k.type==="permission.asked"||k.type==="question.required")&&typeof d==="string"){if(l.has(d))return;l.add(d)}p.writeSSE({data:JSON.stringify({type:k.type,properties:{...k.properties,sessionId:k.sessionId,projectPath:k.projectPath}})}).catch(y)});try{if(p.aborted||D)return;if(await p.writeSSE({data:JSON.stringify({type:"connected",properties:{sessionId:J.sessionId,projectPath:J.projectPath,timestamp:Date.now()}})}).catch((P)=>{throw y(),P}),p.aborted||D)return;let d=(G.currentRunId?C.get(G.currentRunId):void 0)?.pendingPermission;if(d){l.add(d.permissionId);let P=hO(d,!0);await p.writeSSE({data:JSON.stringify({type:P.type,properties:{...P.properties,sessionId:J.sessionId,projectPath:J.projectPath}})})}K(G).catch((P)=>{H.error(`[SessionRoutes] Failed to resume pending input for ${T}:`,P)}),_=setInterval(()=>{if(!p.aborted)p.writeSSE({data:JSON.stringify({type:"heartbeat",properties:{timestamp:Date.now()}})}).catch(y)},15000);while(!p.aborted&&!D)await new Promise((P)=>setTimeout(P,1000))}finally{y()}})}),S.post("/:sessionId/message",async(N)=>{let T=N.req.param("sessionId"),J=await N.req.json(),G=t(Bx,J);if(!G.success)throw new m("Invalid message format");let{content:p,attachments:X,permissionMode:U,projectPath:_}=G.data,D=U||"default",Q=fO(p,X),y=await Z(T,_??N.req.query("projectPath")),l=v(y);return A(l).runExclusive(async()=>{let k=y.currentRunId?C.get(y.currentRunId):void 0;if(k&&(k.status==="running"||k.status==="waiting_permission")){let a=await(await Y(y)).enqueueSteering(Q,{allowBeforeTurn:!0});if(!a.accepted)return N.json({status:"rejected",reason:a.reason??"turn_unavailable"},409);let AS=a.messageId??VS(12),lS=a.queued;M.publish(l,"message.created",{messageId:AS,role:"user",content:LS(Q)});let nO=a.delivery==="next_turn"?"follow_up.queued":"steering.queued";if(M.publish(l,nO,{runId:k.id,messageId:AS,queued:lS}),a.delivery==="next_turn"&&k.status!=="running"&&k.status!=="waiting_permission")K(y).catch((rO)=>{H.error(`[SessionRoutes] Failed to wake queued follow-up for ${T}:`,rO)});if(a.delivery==="next_turn")k.pendingFollowUpRequested=!0;return N.json({runId:k.id,messageId:AS,status:a.delivery==="next_turn"?"follow_up_queued":"steering_queued",queued:lS},202)}let P=await(await Y(y)).prepareInputTurn(Q);if(!P.accepted)return N.json({status:"rejected",reason:P.reason},P.reason==="queue_full"?429:409);let ZS=w(y,Q,D,{preparedInputTurn:P});return N.json({runId:ZS.id,messageId:P.messageId,status:"running"},202)})}),S.post("/:sessionId/abort",async(N)=>{let T=N.req.param("sessionId"),J=await n(T,N.req.query("projectPath")),G=R.get(q(J));if(G?.currentRunId){let p=C.get(G.currentRunId);if(p)_S(p),await p.completion}return N.json({success:!0})}),S.get("/:sessionId/status",async(N)=>{let T=N.req.param("sessionId"),J=await n(T,N.req.query("projectPath")),G=R.get(q(J));if(!G?.currentRunId)return N.json({sessionId:T,projectPath:J.projectPath,status:"idle"});let p=C.get(G.currentRunId);return N.json({sessionId:T,projectPath:J.projectPath,runId:G.currentRunId,status:p?.status||"idle"})}),{app:S,dispatchTask:b,getTaskDiff:B}};async function Lx(S,x,j,$,V,A={}){let{abortController:Y,sessionId:f,id:Z}=S,w=A.preparedInputTurn?.messageId??VS(12),B=A.pendingInputOnly===!0||A.preparedInputTurn?.mode==="pending"||A.goalContinuationOnly===!0?void 0:VS(12),K,N=v(x),T=(J,G)=>{M.publish(N,J,G)};try{if(x.taskStatus="running",x.taskStatusReason=void 0,x.taskStartedAt=new Date().toISOString(),x.taskCompletedAt=void 0,!A.pendingInputOnly&&!A.goalContinuationOnly)T("message.created",{messageId:w,role:"user",content:LS(j)});if(T("session.status",{status:"running"}),B)T("message.created",{messageId:B,role:"assistant",content:""});K=await V(x);let J=K,G=await mO.createWithRuntime(J,{sessionId:f,...x.taskWorktree?{toolBlacklist:["EnterWorktree","ExitWorktree"]}:{}}),p=async(Q)=>{let y=VS(12),l=300000;S.status="waiting_permission";let k=new Promise((MS)=>{let a=setTimeout(()=>{H.warn(`[SessionRoutes] Permission ${y} timed out after 300000ms`),T("permission.timeout",{requestId:y}),MS({approved:!1,reason:"timeout"})},300000);S.pendingPermission={permissionId:y,resolve:(AS)=>{clearTimeout(a),MS(AS)},details:Q}}),d=S.pendingPermission;if(!d)throw Error("Permission request was not registered");let P=hO(d);T(P.type,P.properties),H.info(`[SessionRoutes] Permission request created: ${y}, runId: ${Z}`);let ZS=await k;if(H.info(`[SessionRoutes] Permission response received: ${y}, approved: ${ZS.approved}`),!Y.signal.aborted)S.status="running";if(S.pendingPermission===d)S.pendingPermission=void 0;return ZS},X={messages:[...x.messages],userId:"web-user",sessionId:f,workspaceRoot:x.projectPath,signal:Y.signal,permissionMode:$,...x.taskWorktree?{worktreeActive:!0}:{},confirmationHandler:{requestConfirmation:p}},U=()=>{if(!B)B=VS(12),T("message.created",{messageId:B,role:"assistant",content:""});return B},_=async(Q)=>{switch(Q.kind){case"content_delta":T("message.delta",{messageId:U(),delta:Q.delta});break;case"thinking_delta":T("thinking.delta",{delta:Q.delta});break;case"tool_start":if("function"in Q.toolCall)T("tool.start",{messageId:U(),toolName:Q.toolCall.function.name,toolCallId:Q.toolCall.id,arguments:Q.toolCall.function.arguments,toolKind:Q.toolKind});break;case"tool_result":if("function"in Q.toolCall)T("tool.result",{messageId:U(),toolName:Q.toolCall.function.name,toolCallId:Q.toolCall.id,success:Q.result.success,summary:Q.result.metadata?.summary,output:CS(FS(Q.toolCall.function.name,Q.result)),metadata:BO(Q.result.metadata)});break;case"token_usage":T("token.usage",{...Q.usage});break;case"turn_start":T("turn.started",{turn:Q.turn,maxTurns:Q.maxTurns});break;case"steering_applied":T("steering.applied",{runId:Z,messageIds:Q.messageIds,count:Q.count,recovered:Q.recovered,delivery:Q.delivery,queued:J.getPendingSteeringCount()});break;case"follow_up_started":{if(B)T("message.complete",{messageId:B}),B=void 0;for(let y of Q.messages){if(!y.recovered||y.persisted)continue;T("message.created",{messageId:y.id,role:"user",content:LS(y.content),recovered:!0})}T("follow_up.started",{runId:Z,queued:Q.queued,recovered:Q.recovered}),U();break}case"goal_updated":T("goal.updated",{goal:Q.goal});break;case"goal_continuation_started":T("goal.continuation.started",{goal:Q.goal,continuation:Q.continuation}),U();break;case"compaction":T(Q.phase==="start"?"compaction.started":"compaction.completed",{});break;case"model_fallback":T("model.fallback",{});break;case"task_update":T("task.updated",{tasks:Q.tasks});break;default:break}},D=await ES(G.chatStream(j,X,{stream:!0,pendingInputOnly:A.pendingInputOnly,preparedInputTurn:A.preparedInputTurn,goalContinuationOnly:A.goalContinuationOnly}),_);if(!D.success)throw Error(D.error?.message??"Agent run failed");for(let Q=0;Q<20;Q++){let y=S.pendingFollowUpRequested===!0;if(S.pendingFollowUpRequested=!1,J.getPendingSteeringCount()===0){if(!y)break;continue}if(Y.signal.aborted)break;if(D=await ES(G.chatStream("",X,{stream:!0,pendingInputOnly:!0}),_),!D.success)throw Error(D.error?.message??"Agent follow-up failed")}if(x.messages=[...X.messages],x.updatedAt=new Date,await UO(x),Y.signal.aborted||S.status==="cancelled"){x.taskStatus="cancelled",x.taskCompletedAt??=new Date().toISOString(),T("session.status",{status:"idle"});return}if(B)T("message.complete",{messageId:B});T("thinking.completed",{}),S.status="completed",x.taskStatus="completed",x.taskCompletedAt??=new Date().toISOString(),T("session.completed",{runId:Z,outputTruncated:D.metadata?.outputTruncated??!1}),T("session.status",{status:"idle"})}catch(J){if(K&&A.preparedInputTurn)await K.finishTurn(A.preparedInputTurn.handle).catch(()=>{return});if(await UO(x).catch(()=>{return}),Y.signal.aborted||S.status==="cancelled"){_S(S,"runtime-abort"),x.taskStatus="cancelled",x.taskCompletedAt??=new Date().toISOString(),T("session.status",{status:"idle"});return}H.error("[SessionRoutes] Agent execution error:",J),S.status="failed",x.taskStatus="failed",x.taskStatusReason??="Agent execution failed",x.taskCompletedAt??=new Date().toISOString(),T("session.error",{error:J instanceof Error?J.message:"Unknown error"}),T("session.status",{status:"error"})}}function HO(S,x,j){H.info(`[SessionRoutes] Looking for permission ${x} in session ${S.sessionId}`),H.info(`[SessionRoutes] Active runs: ${C.size}`);for(let[$,V]of C.entries())if(H.info(`[SessionRoutes] Checking run ${$}: sessionId=${V.sessionId}, projectPath=${V.projectPath}, pendingPermission=${V.pendingPermission?.permissionId}`),V.sessionId===S.sessionId&&V.projectPath===S.projectPath&&V.pendingPermission?.permissionId===x)return V.pendingPermission.resolve(j),H.info(`[SessionRoutes] Permission ${x} responded, runId: ${V.id}`),!0;return H.error(`[SessionRoutes] Permission not found: ${x}`),!1}var PS=W("Service"),Cx=O.Object({approved:O.Boolean(),remember:O.Optional(O.Boolean()),scope:O.Optional(E(["once","session","project"])),targetMode:O.Optional(E(["default","autoEdit","plan","yolo"])),feedback:O.Optional(O.String()),answers:O.Optional(O.Record(O.String(),O.Union([O.String(),O.Array(O.String())])))}),KO=()=>{let S=new Fx;return S.post("/:permissionId",async(x)=>{let j=x.req.param("permissionId"),$=x.req.query("sessionId"),V=x.req.query("projectPath");PS.info(`[PermissionRoutes] Received permission response: permissionId=${j}, sessionId=${$}`);try{let A=await x.req.json(),Y=t(Cx,A);if(!Y.success)throw new m("Invalid permission response format");let{approved:f,remember:Z,scope:w,targetMode:b,feedback:B,answers:K}=Y.data;if(!$)throw new m("sessionId query parameter is required");let N=await n($,V);if(!HO(N,j,{approved:f,reason:B,scope:w,targetMode:b,feedback:B,answers:K}))throw new z("Permission request",j);return PS.info(`[PermissionRoutes] Permission ${j} ${f?"approved":"denied"}`),x.json({success:!0,approved:f,remember:Z})}catch(A){if(PS.error("[PermissionRoutes] Failed to respond to permission:",A),A instanceof m||A instanceof o||A instanceof z||A instanceof g)throw A;throw A}}),S};import{Hono as Px}from"hono";var WO=W("Service"),qO=()=>{let S=new Px;return S.get("/",async(x)=>{try{let j=await kO();return x.json(j)}catch(j){return WO.error("[ProviderRoutes] Failed to list providers:",j),x.json([])}}),S.get("/:provider/models",async(x)=>{let j=x.req.param("provider");try{let $=await EO(j);return x.json($)}catch($){return WO.error("[ProviderRoutes] Failed to list models:",$),x.json([])}}),S.put("/:provider/credential",async(x)=>{let j=x.req.param("provider"),$=await x.req.json();if(!$.apiKey?.trim())throw new m("apiKey is required");return await s().setApiKey(j,$.apiKey.trim()),x.json({success:!0})}),S.delete("/:provider/credential",async(x)=>{return await s().clearCredential(x.req.param("provider")),x.json({success:!0})}),S};import{Hono as Rx}from"hono";import*as SS from"node:fs/promises";import{homedir as Ix}from"node:os";import*as mS from"node:path";var xS=W("Service"),RS=mS.join(Ix(),".blade","skills-config.json");async function LO(){try{let S=await SS.readFile(RS,"utf-8");return JSON.parse(S)}catch{return{disabled:[]}}}async function gx(S){await SS.mkdir(mS.dirname(RS),{recursive:!0}),await SS.writeFile(RS,JSON.stringify(S,null,2))}async function tx(S,x){let j=await LO();if(x)j.disabled=j.disabled.filter(($)=>$!==S);else if(!j.disabled.includes(S))j.disabled.push(S);await gx(j)}var JS=null,ux=300000;async function vx(){if(JS&&Date.now()-JS.timestamp<ux)return JS.data;try{let S=await fetch("https://api.github.com/repos/anthropics/skills/contents/skills",{headers:{Accept:"application/vnd.github.v3+json","User-Agent":"Blade-Skills-Catalog"}});if(!S.ok)return xS.warn(`GitHub API returned ${S.status}`),JS?.data||[];let x=await S.json(),j=[];for(let $ of x){if($.type!=="dir")continue;let V=`Official ${$.name} skill`;try{let A=await fetch(`https://raw.githubusercontent.com/anthropics/skills/main/skills/${$.name}/SKILL.md`,{headers:{"User-Agent":"Blade-Skills-Catalog"}});if(A.ok){let f=(await A.text()).match(/^#[^\n]*\n+([^\n#]+)/);if(f)V=f[1].trim().slice(0,100)}}catch{}j.push({name:$.name,description:V,tag:"Official",author:"Anthropic"})}return JS={data:j,timestamp:Date.now()},j}catch(S){return xS.warn("Failed to fetch skills catalog from GitHub:",S),JS?.data||[]}}var FO=()=>{let S=new Rx;return S.get("/",async(x)=>{try{let j=DS();await j.initialize();let $=j.getAll(),V=await LO(),A=$.map((Y)=>({id:Y.name,name:Y.name,enabled:!V.disabled.includes(Y.name),description:Y.description||"",version:Y.version||"1.0.0",provider:"Local",location:Y.source==="builtin"?"Built-in":Y.basePath,capabilities:["prompts"],allowedTools:Y.allowedTools||[]}));return x.json(A)}catch(j){return xS.error("[SkillsRoutes] Failed to get skills:",j),x.json([])}}),S.post("/:name/toggle",async(x)=>{try{let j=x.req.param("name"),$=await x.req.json();return await tx(j,$.enabled),x.json({success:!0,enabled:$.enabled})}catch(j){return xS.error("[SkillsRoutes] Failed to toggle skill:",j),x.json({success:!1,error:j.message},500)}}),S.delete("/:name",async(x)=>{try{let j=x.req.param("name"),$=`${process.env.HOME}/.blade/skills/${j}`;return await SS.rm($,{recursive:!0,force:!0}),await DS().refresh(),x.json({success:!0})}catch(j){return xS.error("[SkillsRoutes] Failed to uninstall skill:",j),x.json({success:!1,error:j.message},500)}}),S.post("/install",async(x)=>{try{let j=await x.req.json(),$=zO(),V=DS(),A=!1;if(j.source==="catalog"&&j.name){if(A=await $.installOfficialSkill(j.name),!A)return x.json({success:!1,error:"Failed to install skill from catalog"},500)}else if(j.source==="repo"&&j.url){if(A=await $.installFromRepo(j.url,j.name),!A)return x.json({success:!1,error:"Failed to install skill from repository. Make sure the repo contains a SKILL.md file."},500)}else if(j.source==="local"&&j.path){if(A=await $.installFromLocal(j.path,j.name),!A)return x.json({success:!1,error:"Failed to install skill from local path. Make sure the path exists and contains a SKILL.md file."},500)}else return x.json({success:!1,error:"Invalid install parameters. Required: source with corresponding url/path/name"},400);return await V.refresh(),x.json({success:!0})}catch(j){return xS.error("[SkillsRoutes] Failed to install skill:",j),x.json({success:!1,error:j.message},500)}}),S.get("/catalog",async(x)=>{try{let j=await vx();return x.json(j)}catch(j){return xS.error("[SkillsRoutes] Failed to get catalog:",j),x.json([])}}),S};import cx from"fast-glob";import{Hono as lx}from"hono";import{execSync as dx}from"node:child_process";import{readdir as ax}from"node:fs/promises";import bS from"node:path";var QS=W("Service"),ox=(S)=>{try{return dx("git rev-parse --abbrev-ref HEAD",{cwd:S,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}},ix=[...hS.map((S)=>`${S}/**`),...hS,...IS.map((S)=>`**/${S}`)],nx=new Set(["/theme","/model","/permissions","/mcp","/skills","/exit","/resume","/ide","/login","/logout"]),RO=()=>{let S=new lx;return S.get("/commands",async(x)=>{try{let j=x.req.query("q")||"",$=PO(j).filter((V)=>!nx.has(V.command));return x.json($)}catch(j){return QS.error("[SuggestionsRoutes] Failed to get command suggestions:",j),x.json([])}}),S.get("/files",async(x)=>{try{let j=x.req.query("q")||"",$=x.get("directory")||L(),V=Math.min(Number(x.req.query("limit"))||100,1000),Y=(await cx("**/*",{cwd:$,dot:!1,followSymbolicLinks:!1,onlyFiles:!1,markDirectories:!0,unique:!0,ignore:ix})).map((w)=>w.replace(/\\/g,"/"));if(!j)return x.json(Y.slice(0,V));let f=j.toLowerCase(),Z=Y.filter((w)=>w.toLowerCase().includes(f)).slice(0,V);return x.json(Z)}catch(j){return QS.error("[SuggestionsRoutes] Failed to get file suggestions:",j),x.json([])}}),S.get("/files/tree",async(x)=>{try{let j=x.get("directory")||L(),$=x.req.query("path")||"",V=$?bS.join(j,$):j,Y=(await ax(V,{withFileTypes:!0})).map((w)=>({name:w.name,path:$?`${$}/${w.name}`:w.name,type:w.isDirectory()?"dir":"file"}));Y.sort((w,b)=>{if(w.type!==b.type)return w.type==="dir"?-1:1;return w.name.localeCompare(b.name)});let f=new Set(hS),Z=Y.filter((w)=>{let b=w.name;if(b.startsWith("."))return!1;if(f.has(b))return!1;for(let B of IS)if(b.match(new RegExp(B.replace("*",".*"))))return!1;return!0});return x.json(Z)}catch(j){return QS.error("[SuggestionsRoutes] Failed to get file tree:",j),x.json([])}}),S.get("/files/content",async(x)=>{try{let j=x.req.query("path");if(!j)return x.json({error:"Missing file path"},400);let $=x.get("directory")||L(),V=bS.resolve($,j),A=bS.relative($,V);if(A.startsWith("..")||bS.isAbsolute(A))return x.json({error:"Invalid file path"},400);let Y=CO(),f=await Y.stat(V);if(!f?.isFile)return x.json({error:"File not found"},404);let Z=200000,w=await Y.readTextFile(V),b=w.length>Z;return x.json({path:j,content:b?w.slice(0,Z):w,truncated:b,size:f.size})}catch(j){return QS.error("[SuggestionsRoutes] Failed to get file content:",j),x.json({error:"Failed to read file"},500)}}),S.get("/git-info",async(x)=>{try{let j=x.get("directory")||L(),$=ox(j);return x.json({branch:$})}catch(j){return QS.error("[SuggestionsRoutes] Failed to get git info:",j),x.json({branch:null})}}),S};import{Hono as rx}from"hono";var gS=W("Service"),IO=(S)=>{let x=new rx;return x.onError((j,$)=>{if(j instanceof g)return $.json(j.toObject(),j.statusCode);return gS.error("[TaskRoutes] Unhandled route error:",j),$.json(new u("Failed to dispatch task").toObject(),500)}),x.post("/",async(j)=>{let $;try{$=await j.req.json()}catch{throw new m("Invalid request body")}let V=t(pO,$);if(!V.success)throw new m("Invalid task request");try{let A=await S.dispatchTask({prompt:V.data.prompt,title:V.data.title,sourceProjectPath:V.data.projectPath||j.get("directory")||L(),isolation:V.data.isolation,permissionMode:V.data.permissionMode,attachments:V.data.attachments});return j.json(GO.parse(A),202)}catch(A){if(A instanceof m||A instanceof I)throw A;throw gS.error("[TaskRoutes] Failed to dispatch task:",A),new u("Failed to dispatch task")}}),x.get("/:sessionId/diff",async(j)=>{try{let $=await S.getTaskDiff(j.req.param("sessionId"),j.req.query("projectPath"));return j.json($O.parse($))}catch($){if($ instanceof m||$ instanceof z||$ instanceof I)throw $;throw gS.error("[TaskRoutes] Failed to load task diff:",$),new u("Failed to load task diff")}}),x};import{Hono as ex}from"hono";var OS=W("Service"),TS=new Map,gO=2097152,tO=65536;function uO(){return typeof globalThis.Bun<"u"}async function sx(S,x,j){if(uO()){let{spawn:A}=await import("bun-pty"),Y=A(S,x,{name:"xterm-256color",cwd:j.cwd,env:j.env});return{pid:Y.pid,write:(f)=>Y.write(f),resize:(f,Z)=>Y.resize(f,Z),kill:()=>Y.kill(),onData:(f)=>Y.onData(f),onExit:(f)=>Y.onExit(f)}}let V=(await import("node-pty")).spawn(S,x,{name:"xterm-256color",cwd:j.cwd,env:j.env,cols:80,rows:24});return{pid:V.pid,write:(A)=>V.write(A),resize:(A,Y)=>V.resize(A,Y),kill:()=>V.kill(),onData:(A)=>{V.onData(A)},onExit:(A)=>{V.onExit(A)}}}var vS=void 0,uS;if(uO())try{let{createBunWebSocket:S}=await import("hono/bun"),x=S();uS=x.upgradeWebSocket,vS=x.websocket}catch(S){OS.warn("[Terminal] Failed to initialize Bun WebSocket support:",S)}async function vO(S,x){let j=`term-${Date.now()}`;OS.info(`[Terminal] New connection: ${j}, cwd: ${S}`);let $=process.platform==="win32"?"powershell.exe":process.env.SHELL||"/bin/zsh",V=$.endsWith("sh")?["-l"]:[],A=await sx($,V,{cwd:S,env:{...process.env,TERM:"xterm-256color",COLORTERM:"truecolor"}}),Y={id:j,process:A,cwd:S,buffer:"",subscribers:new Set};if(TS.set(j,Y),Y.subscribers.add(x),A.onData((f)=>{let Z=!1;for(let w of Y.subscribers)try{w.send(f),Z=!0}catch{Y.subscribers.delete(w)}if(Z)return;if(Y.buffer+=f,Y.buffer.length>gO)Y.buffer=Y.buffer.slice(-gO)}),A.onExit(({exitCode:f})=>{OS.info(`[Terminal] Process exited: ${j}, code: ${f}`);for(let Z of Y.subscribers)try{Z.close()}catch{}TS.delete(j)}),Y.buffer){let f=Y.buffer;Y.buffer="";for(let Z=0;Z<f.length;Z+=tO)x.send(f.slice(Z,Z+tO))}return{session:Y,cleanup:()=>{if(OS.info(`[Terminal] Connection closed: ${j}`),Y.subscribers.delete(x),Y.subscribers.size===0){try{Y.process.kill()}catch{}TS.delete(j)}}}}function cO(S,x){S.on("connection",async(j,$)=>{let V=new URL($.url||"/",`http://${$.headers.host}`);if(!V.pathname.endsWith("/terminal/ws")){j.close();return}let A=V.searchParams.get("cwd")||x()||L();try{let{session:Y,cleanup:f}=await vO(A,{send:(Z)=>j.send(Z),close:()=>j.close()});j.on("message",(Z)=>{try{Y.process.write(String(Z))}catch(w){OS.error("[Terminal] Failed to write to PTY:",w)}}),j.on("close",f),j.on("error",f)}catch(Y){OS.error("[Terminal] Failed to spawn PTY:",Y),j.close()}})}var lO=()=>{let S=new ex;if(S.get("/status",(x)=>{let j=Array.from(TS.values()).map(($)=>({id:$.id,cwd:$.cwd}));return x.json({active:j.length,terminals:j})}),S.post("/kill/:terminalId",(x)=>{let j=x.req.param("terminalId"),$=TS.get(j);if($){try{$.process.kill()}catch{}for(let V of $.subscribers)V.close();return TS.delete(j),x.json({success:!0})}return x.json({success:!1,error:"Terminal not found"},404)}),uS)S.get("/ws",uS((x)=>{let j=x.req.query("cwd")||x.get("directory")||L(),$;return{async onOpen(V,A){try{$=await vO(j,{send:(Y)=>A.send(Y),close:()=>A.close()})}catch(Y){OS.error("[Terminal] Failed to spawn PTY:",Y),A.close()}},onMessage(V){if(!$)return;try{$.session.process.write(String(V.data))}catch(A){OS.error("[Terminal] Failed to write to PTY:",A)}},onClose(){$?.cleanup()}}}));else S.get("/ws",(x)=>{return x.json({message:"WebSocket endpoint - connect via ws:// protocol",hint:"Use WebSocket client to connect to this endpoint"})});return S};var c=W("Service"),cS=[];function T0(){let S=x0($0(import.meta.url)),x=[jS(S,"web"),jS(L(),"dist/web"),jS(L(),"packages/cli/dist/web")];for(let j of x){let $=jS(j,"index.html");if(oO($)){if(BS($,"utf-8").includes("/assets/"))return c.debug(`[Server] Found web dist at: ${j}`),j}}return null}function A0(){let S=new N0;S.onError(($,V)=>{if(c.error("[Server] Request error:",$),$ instanceof g)return V.json($.toObject(),$.statusCode);let A=$ instanceof Error?$.message:String($);return V.json({error:{code:"INTERNAL_ERROR",message:A}},500)}),S.use(async($,V)=>{let A=process.env.BLADE_SERVER_PASSWORD;if(!A)return V();let Y=$.req.path;if(Y==="/"||Y.startsWith("/assets/")||Y.endsWith(".html")||Y.endsWith(".js")||Y.endsWith(".css"))return V();let f=$.req.header("Authorization");if(!f?.startsWith("Basic "))return $.header("WWW-Authenticate",'Basic realm="Blade Server"'),$.json({error:{code:"UNAUTHORIZED",message:"Authentication required"}},401);let Z=Buffer.from(f.slice(6),"base64").toString(),[w,b]=Z.split(":"),B=process.env.BLADE_SERVER_USERNAME??"blade";if(w!==B||b!==A)return $.json({error:{code:"UNAUTHORIZED",message:"Invalid credentials"}},401);return V()}),S.use(async($,V)=>{let A=$.req.path==="/health"||$.req.path==="/global/health"||$.req.path.startsWith("/assets/");if(!A)c.debug(`[Server] ${$.req.method} ${$.req.path}`);let Y=Date.now();if(await V(),!A){let f=Date.now()-Y;c.debug(`[Server] ${$.req.method} ${$.req.path} - ${$.res.status} (${f}ms)`)}}),S.use(V0({origin($){if(!$)return;if($.startsWith("http://localhost:"))return $;if($.startsWith("http://127.0.0.1:"))return $;if($==="tauri://localhost"||$==="http://tauri.localhost")return $;if(cS.includes($))return $;return}})),S.use(async($,V)=>{let A=$.req.query("directory")||$.req.header("x-blade-directory")||L();try{A=decodeURIComponent(A)}catch{}return $.set("directory",A),V()});let x=MO();S.route("/global",iS()),S.route("/events",aS()),S.route("/sessions",x.app),S.route("/tasks",IO(x)),S.route("/configs",dS()),S.route("/permissions",KO()),S.route("/providers",qO()),S.route("/models",SO()),S.route("/suggestions",RO()),S.route("/terminal",lO()),S.route("/mcp",nS()),S.route("/skills",FO()),S.get("/health",($)=>{return $.json({healthy:!0,version:NS()})});let j=T0();if(j)c.info(`[Server] Serving static files from ${j}`),S.get("/assets/*",($)=>{let V=jS(j,$.req.path);if(!oO(V))return $.json({error:{code:"NOT_FOUND",message:`File not found: ${$.req.path}`}},404);let A=BS(V),Y=j0(V).toLowerCase(),Z={".js":"application/javascript",".css":"text/css",".html":"text/html",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".eot":"application/vnd.ms-fontobject"}[Y]||"application/octet-stream";return new Response(A,{headers:{"Content-Type":Z,"Cache-Control":"public, max-age=31536000, immutable"}})}),S.get("/",($)=>{let V=jS(j,"index.html"),A=BS(V,"utf-8");return $.html(A)}),S.get("*",($)=>{let V=$.req.path;if(V.includes("."))return $.json({error:{code:"NOT_FOUND",message:`File not found: ${V}`}},404);let A=jS(j,"index.html"),Y=BS(A,"utf-8");return $.html(Y)});else c.warn('[Server] Web UI not found. Run "cd packages/cli/web && bun run build" to enable web interface.'),S.get("/",($)=>{return $.json({message:"Blade API Server",version:NS(),webUI:!1,hint:'Web UI not built. Run "cd packages/cli/web && bun run build" to enable.',endpoints:{health:"/health",sessions:"/sessions",configs:"/configs",permissions:"/permissions",providers:"/providers"}})}),S.all("*",($)=>{return $.json({error:{code:"NOT_FOUND",message:`Route not found: ${$.req.path}`}},404)});return S}function Y0(){let S=O0(),x=[];for(let j of Object.keys(S)){let $=S[j];if(!$)continue;for(let V of $){if(V.internal||V.family!=="IPv4")continue;if(V.address.startsWith("172."))continue;x.push(V.address)}}return x}function dO(){return typeof globalThis.Bun<"u"}function aO(S,x){let j=globalThis.Bun,$=(A)=>{try{return j.serve({hostname:x.hostname,port:A,fetch:S.fetch,idleTimeout:0,websocket:vS})}catch(Y){c.error("Failed to start Bun server:",Y);return}},V=x.port===0?$(4096)??$(0):$(x.port);if(!V)throw Error(`Failed to start Bun server on port ${x.port}`);return{url:V.url,port:V.port,hostname:V.hostname,stop:async()=>{V.stop(!0)}}}function p0(S,x){return new Promise((j,$)=>{let V=S0(async(w,b)=>{let B=new URL(w.url||"/",`http://${w.headers.host}`),K=new Headers;for(let[J,G]of Object.entries(w.headers))if(G)if(Array.isArray(G))for(let p of G)K.append(J,p);else K.set(J,G);let N;if(w.method!=="GET"&&w.method!=="HEAD")N=(await new Promise((G)=>{let p=[];w.on("data",(X)=>p.push(X)),w.on("end",()=>G(Buffer.concat(p)))})).toString();let T=new Request(B.toString(),{method:w.method,headers:K,body:N});try{let J=await S.fetch(T);if(b.statusCode=J.status,J.headers.forEach((G,p)=>{b.setHeader(p,G)}),J.body){let G=J.body.getReader(),p=async()=>{let{done:X,value:U}=await G.read();if(X){b.end();return}return b.write(U),p()};await p()}else{let G=await J.text();b.end(G)}}catch(J){c.error("[Server] Node request error:",J),b.statusCode=500,b.end(JSON.stringify({error:{code:"INTERNAL_ERROR",message:"Internal server error"}}))}}),A=new J0({noServer:!0}),Y=L();cO(A,()=>Y),V.on("upgrade",(w,b,B)=>{if(new URL(w.url||"/",`http://${w.headers.host}`).pathname==="/terminal/ws")A.handleUpgrade(w,b,B,(N)=>{A.emit("connection",N,w)});else b.destroy()});let f=(w)=>{return new Promise((b,B)=>{V.once("error",(K)=>{if(K.code==="EADDRINUSE")B(K);else B(K)}),V.listen(w,x.hostname,()=>{let K=V.address();if(K&&typeof K==="object")b(K.port);else b(w)})})};(async()=>{let w;if(x.port===0)try{w=await f(4096)}catch{w=await f(0)}else w=await f(x.port);let b=new URL(`http://${x.hostname==="0.0.0.0"?"localhost":x.hostname}:${w}`);j({url:b,port:w,hostname:x.hostname,stop:async()=>{return new Promise((B)=>{A.close(()=>{V.close(()=>B())})})}})})().catch($)})}var iO;((aj)=>{let S,x;function j(){if(!x)x=A0();return x}aj.getApp=j;function $(Y){cS=Y.cors??[];let f=j();if(dO())S=aO(f,Y),c.info(`[Server] Blade server listening on ${S.url} (Bun runtime)`);else throw Error("Blade web server requires Bun runtime. Please run with Bun: `bun run blade web` or install Bun from https://bun.sh");let Z=S;return{url:Z.url,port:Z.port,hostname:Z.hostname,stop:async()=>{if(S)await S.stop(),S=void 0,x=void 0,c.info("[Server] Blade server stopped")}}}aj.listen=$;async function V(Y){cS=Y.cors??[];let f=j();if(dO())S=aO(f,Y),c.info(`[Server] Blade server listening on ${S.url} (Bun runtime)`);else S=await p0(f,Y),c.info(`[Server] Blade server listening on ${S.url} (Node.js runtime)`);let Z=S;return{url:Z.url,port:Z.port,hostname:Z.hostname,stop:async()=>{if(S)await S.stop(),S=void 0,x=void 0,c.info("[Server] Blade server stopped")}}}aj.listenAsync=V;function A(){return S!==void 0}aj.isRunning=A})(iO||={});export{G0 as a,Q0 as b,Y0 as c,iO as d};
|