@blade-ai/agent-sdk 0.1.8 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/index.js +427 -437
  3. package/package.json +5 -6
package/dist/index.js CHANGED
@@ -1,148 +1,32 @@
1
- import{createRequire as J8}from"node:module";var O0=J8(import.meta.url);import*as P2 from"os";import*as h2 from"path";import{nanoid as G0}from"nanoid";var rb={DEFAULT:"default",AUTO_EDIT:"autoEdit",YOLO:"yolo",BYPASSALL:"bypassAll",PLAN:"plan",SPEC:"spec"},v0;((q)=>{q.PreToolUse="PreToolUse";q.PostToolUse="PostToolUse";q.PostToolUseFailure="PostToolUseFailure";q.PermissionRequest="PermissionRequest";q.UserPromptSubmit="UserPromptSubmit";q.SessionStart="SessionStart";q.SessionEnd="SessionEnd";q.Stop="Stop";q.SubagentStart="SubagentStart";q.SubagentStop="SubagentStop";q.TaskCompleted="TaskCompleted";q.Notification="Notification";q.Compaction="Compaction"})(v0||={});var fw={SYSTEM:"system",USER:"user",ASSISTANT:"assistant",TOOL:"tool"},X8={TURN_START:"turn_start",TURN_END:"turn_end",CONTENT:"content",THINKING:"thinking",TOOL_USE:"tool_use",TOOL_RESULT:"tool_result",USAGE:"usage",RESULT:"result",ERROR:"error"},O8={READONLY:"readonly",WRITE:"write",EXECUTE:"execute"},G8={ALLOW:"allow",DENY:"deny",ASK:"ask"},B8={APPROVE:"approve",BLOCK:"block",ASYNC:"async"},K8={ALLOW:"allow",DENY:"deny",ASK:"ask"},q8={COMMAND:"command",PROMPT:"prompt"},A8={SUCCESS:0,NON_BLOCKING_ERROR:1,BLOCKING_ERROR:2,TIMEOUT:124},U8={VALIDATION_ERROR:"validation_error",PERMISSION_DENIED:"permission_denied",EXECUTION_ERROR:"execution_error",TIMEOUT_ERROR:"timeout_error",NETWORK_ERROR:"network_error"};var v=rb;import{nanoid as J$}from"nanoid";var ab={enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],PostToolUseFailure:[],PermissionRequest:[],UserPromptSubmit:[],SessionStart:[],SessionEnd:[],Stop:[],SubagentStart:[],SubagentStop:[],TaskCompleted:[],Notification:[],Compaction:[]};function ob($,b){return{...$,...b,PreToolUse:b.PreToolUse??$.PreToolUse,PostToolUse:b.PostToolUse??$.PostToolUse,PostToolUseFailure:b.PostToolUseFailure??$.PostToolUseFailure,PermissionRequest:b.PermissionRequest??$.PermissionRequest,UserPromptSubmit:b.UserPromptSubmit??$.UserPromptSubmit,SessionStart:b.SessionStart??$.SessionStart,SessionEnd:b.SessionEnd??$.SessionEnd,Stop:b.Stop??$.Stop,SubagentStart:b.SubagentStart??$.SubagentStart,SubagentStop:b.SubagentStop??$.SubagentStop,TaskCompleted:b.TaskCompleted??$.TaskCompleted,Notification:b.Notification??$.Notification,Compaction:b.Compaction??$.Compaction}}function Iw(){let $={};if(process.env.BLADE_DISABLE_HOOKS==="true")$.enabled=!1;if(process.env.BLADE_HOOK_TIMEOUT){let b=parseInt(process.env.BLADE_HOOK_TIMEOUT,10);if(!isNaN(b)&&b>0)$.defaultTimeout=b}return $}class tb{executedHooks=new Map;canExecute($,b){if(!this.executedHooks.has($))this.executedHooks.set($,new Set);if(this.executedHooks.get($).has(b))return console.warn(`[HookGuard] Hook ${b} for tool ${$} already executed, skipping`),!1;return!0}markExecuted($,b){let w=this.executedHooks.get($);if(w)w.add(b)}cleanup($){this.executedHooks.delete($)}cleanupAll(){this.executedHooks.clear()}}import{z as A}from"zod";var eb;((V)=>{V.Approve="approve";V.Block="block";V.Async="async"})(eb||={});var $1;((V)=>{V.Allow="allow";V.Deny="deny";V.Ask="ask"})($1||={});var Y$=A.object({hook_event_name:A.nativeEnum(v0),hook_execution_id:A.string(),timestamp:A.string(),project_dir:A.string(),session_id:A.string(),permission_mode:A.enum(["default","autoEdit","yolo","plan"]),_metadata:A.object({blade_version:A.string(),hook_timeout_ms:A.number()}).optional()}),F8=Y$.extend({hook_event_name:A.literal("PreToolUse"),tool_name:A.string(),tool_use_id:A.string(),tool_input:A.record(A.unknown())}),H8=Y$.extend({hook_event_name:A.literal("PostToolUse"),tool_name:A.string(),tool_use_id:A.string(),tool_input:A.record(A.unknown()),tool_response:A.unknown()}),_8=Y$.extend({hook_event_name:A.literal("Stop"),reason:A.string().optional()}),R8=Y$.extend({hook_event_name:A.literal("PostToolUseFailure"),tool_name:A.string(),tool_use_id:A.string(),tool_input:A.record(A.unknown()),error:A.string(),error_type:A.string().optional(),is_interrupt:A.boolean(),is_timeout:A.boolean()}),E8=Y$.extend({hook_event_name:A.literal("PermissionRequest"),tool_name:A.string(),tool_use_id:A.string(),tool_input:A.record(A.unknown())}),D8=Y$.extend({hook_event_name:A.literal("UserPromptSubmit"),user_prompt:A.string(),has_images:A.boolean(),image_count:A.number()}),L8=Y$.extend({hook_event_name:A.literal("SessionStart"),is_resume:A.boolean(),resume_session_id:A.string().optional()}),j8=Y$.extend({hook_event_name:A.literal("SessionEnd"),reason:A.enum(["user_exit","error","max_turns","idle_timeout","ctrl_c","clear","logout","other"])}),N8=Y$.extend({hook_event_name:A.literal("SubagentStart"),agent_type:A.string(),task_description:A.string().optional(),parent_agent_id:A.string().optional()}),S8=Y$.extend({hook_event_name:A.literal("SubagentStop"),agent_type:A.string(),task_description:A.string().optional(),success:A.boolean(),result_summary:A.string().optional(),error:A.string().optional()}),M8=Y$.extend({hook_event_name:A.literal("TaskCompleted"),task_id:A.string(),task_description:A.string(),result_summary:A.string().optional(),success:A.boolean()}),y8=Y$.extend({hook_event_name:A.literal("Notification"),notification_type:A.enum(["permission_prompt","idle_prompt","auth_success","elicitation_dialog","info","warning","error"]),title:A.string().optional(),message:A.string()}),z8=Y$.extend({hook_event_name:A.literal("Compaction"),trigger:A.enum(["manual","auto"]),messages_before:A.number(),tokens_before:A.number()}),MW=A.discriminatedUnion("hook_event_name",[F8,H8,_8,R8,E8,D8,L8,j8,N8,S8,M8,y8,z8]),v8=A.object({hookEventName:A.literal("PreToolUse"),permissionDecision:A.nativeEnum($1).optional(),permissionDecisionReason:A.string().optional(),updatedInput:A.record(A.unknown()).optional()}),T8=A.object({hookEventName:A.literal("PostToolUse"),additionalContext:A.string().optional(),updatedOutput:A.unknown().optional()}),k8=A.object({hookEventName:A.literal("Stop"),continue:A.boolean().optional(),continueReason:A.string().optional()}),f8=A.object({hookEventName:A.literal("SubagentStart"),additionalContext:A.string().optional()}),I8=A.object({hookEventName:A.literal("SubagentStop"),continue:A.boolean().optional(),continueReason:A.string().optional(),additionalContext:A.string().optional()}),P8=A.object({hookEventName:A.literal("TaskCompleted"),blockCompletion:A.boolean().optional(),blockReason:A.string().optional()}),h8=A.object({hookEventName:A.literal("PermissionRequest"),permissionDecision:A.enum(["approve","deny","ask"]).optional(),permissionDecisionReason:A.string().optional()}),x8=A.object({hookEventName:A.literal("UserPromptSubmit"),updatedPrompt:A.string().optional(),contextInjection:A.string().optional()}),p8=A.object({hookEventName:A.literal("SessionStart"),env:A.record(A.string()).optional()}),d8=A.object({hookEventName:A.literal("Compaction"),blockCompaction:A.boolean().optional(),blockReason:A.string().optional()}),u8=A.object({decision:A.object({behavior:A.nativeEnum(eb)}).optional(),systemMessage:A.string().optional(),hookSpecificOutput:A.discriminatedUnion("hookEventName",[v8,T8,k8,f8,I8,P8,h8,x8,p8,d8]).optional(),suppressOutput:A.boolean().optional()}),g8=A.object({type:A.literal("command"),command:A.string(),timeout:A.number().positive().optional(),statusMessage:A.string().optional()}),m8=A.object({type:A.literal("prompt"),prompt:A.string(),timeout:A.number().positive().optional()}),c8=A.discriminatedUnion("type",[g8,m8]),b1=A.union([A.string(),A.array(A.string())]),i8=A.object({tools:b1.optional(),paths:b1.optional(),commands:b1.optional()}),Z$=A.object({name:A.string().optional(),matcher:i8.optional(),hooks:A.array(c8)}),yW=A.object({enabled:A.boolean().optional(),defaultTimeout:A.number().positive().optional(),timeoutBehavior:A.enum(["ignore","deny","ask"]).optional(),failureBehavior:A.enum(["ignore","deny","ask"]).optional(),maxConcurrentHooks:A.number().positive().optional(),PreToolUse:A.array(Z$).optional(),PostToolUse:A.array(Z$).optional(),PostToolUseFailure:A.array(Z$).optional(),PermissionRequest:A.array(Z$).optional(),UserPromptSubmit:A.array(Z$).optional(),SessionStart:A.array(Z$).optional(),SessionEnd:A.array(Z$).optional(),Stop:A.array(Z$).optional(),SubagentStart:A.array(Z$).optional(),SubagentStop:A.array(Z$).optional(),TaskCompleted:A.array(Z$).optional(),Notification:A.array(Z$).optional(),Compaction:A.array(Z$).optional()});function Pw($){let b=u8.safeParse($);if(b.success)return{success:!0,data:b.data};return{success:!1,error:b.error}}class w1{parse($,b,w){if($.timedOut){let W=w?.timeoutBehavior||"ignore",Q="Hook timeout";if(W==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};else if(W==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b}}let V=this.tryParseJSON($.stdout);if(V){let W=Pw(V);if(!W.success){let Z="error"in W?W.error.message:"Unknown validation error",Y=w?.failureBehavior||"ignore",J=`Invalid hook output JSON: ${Z}`;if(Y==="deny")return{success:!1,blocking:!0,error:J,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};else if(Y==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${J}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};else return{success:!1,blocking:!1,warning:J,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b}}let Q=W.data;if(Q.decision?.behavior==="block")return{success:!1,blocking:!0,error:Q.systemMessage||"Hook blocked execution",output:Q,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};if(Q.decision?.behavior==="async")return{success:!0,output:Q,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};return{success:!0,output:Q,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b}}return this.parseByExitCode($,b,w)}parseByExitCode($,b,w){let V=$.exitCode;switch(V){case 0:return{success:!0,stdout:$.stdout,stderr:$.stderr,exitCode:V,hook:b};case 2:return{success:!1,blocking:!0,error:$.stderr||$.stdout||"Hook returned exit code 2",stdout:$.stdout,stderr:$.stderr,exitCode:V,hook:b};case 124:{let W=w?.timeoutBehavior||"ignore",Q="Hook timeout";if(W==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:V,hook:b};else if(W==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:V,hook:b};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:V,hook:b}}default:{let W=w?.failureBehavior||"ignore",Q=$.stderr||$.stdout||`Hook failed with exit code ${V}`;if(W==="deny")return{success:!1,blocking:!0,error:Q,stdout:$.stdout,stderr:$.stderr,exitCode:V,hook:b};else if(W==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${Q}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:V,hook:b};else return{success:!1,blocking:!1,warning:Q,stdout:$.stdout,stderr:$.stderr,exitCode:V,hook:b}}}}tryParseJSON($){try{let b=$.trim();if(!b)return null;let w=b.match(/^\s*(\{[\s\S]*\})\s*$/);if(!w)return null;return JSON.parse(w[1])}catch{return null}}}import{spawn as l8}from"child_process";class V1{content="";maxSize;constructor($){this.maxSize=$}append($){if(this.content.length<this.maxSize){let b=this.maxSize-this.content.length;this.content+=$.substring(0,b)}}getContent(){return this.content}isFull(){return this.content.length>=this.maxSize}}class W1{MAX_STDOUT_SIZE=1048576;MAX_STDERR_SIZE=1048576;MAX_INPUT_SIZE=102400;async execute($,b,w,V){let W=JSON.stringify(b);if(W.length>this.MAX_INPUT_SIZE)throw Error(`Hook input too large: ${W.length} bytes (max ${this.MAX_INPUT_SIZE})`);let Q=this.createSafeEnv(b),Z=l8($,[],{shell:!0,env:Q,cwd:w.projectDir,timeout:V}),Y=new V1(this.MAX_STDOUT_SIZE),J=new V1(this.MAX_STDERR_SIZE);Z.stdout.setEncoding("utf8"),Z.stderr.setEncoding("utf8"),Z.stdout.on("data",(X)=>{Y.append(X)}),Z.stderr.on("data",(X)=>{J.append(X)});try{Z.stdin.write(W),Z.stdin.end()}catch(X){throw Z.kill("SIGTERM"),Error(`Failed to write hook input: ${X}`)}return new Promise((X,O)=>{let G=!1,B=!1,q=null,U=()=>{if(q&&w.abortSignal)w.abortSignal.removeEventListener("abort",q),q=null},K=setTimeout(()=>{G=!0,Z.kill("SIGKILL")},V);if(Z.on("close",(_)=>{if(B)return;B=!0,clearTimeout(K),U(),X({stdout:Y.getContent(),stderr:J.getContent(),exitCode:G?124:_??1,timedOut:G})}),Z.on("error",(_)=>{if(B)return;B=!0,clearTimeout(K),U(),O(_)}),w.abortSignal)q=()=>{if(B)return;B=!0,clearTimeout(K),U(),Z.kill("SIGTERM"),X({stdout:Y.getContent(),stderr:"Hook cancelled by abort signal",exitCode:1,timedOut:!1})},w.abortSignal.addEventListener("abort",q)})}createSafeEnv($){return{BLADE_PROJECT_DIR:$.project_dir,BLADE_SESSION_ID:$.session_id,BLADE_HOOK_EVENT:$.hook_event_name,BLADE_TOOL_NAME:"tool_name"in $?$.tool_name:"",BLADE_TOOL_USE_ID:"tool_use_id"in $?$.tool_use_id:"",PATH:process.env.PATH||"",HOME:process.env.HOME||"",USER:process.env.USER||"",SHELL:process.env.SHELL||"/bin/sh"}}}class Q1{processExecutor=new W1;outputParser=new w1;async executePreToolHooks($,b,w){if($.length===0)return{decision:"allow"};let V="tool_input"in b?b.tool_input:{},W=[];for(let Q of $)try{let Z={...b,...V&&{tool_input:V}},Y=await this.executeHook(Q,Z,w);if(!Y.success){if(Y.blocking)return{decision:"deny",reason:Y.error};if(Y.needsConfirmation)return{decision:"ask",reason:Y.warning||Y.error};if(Y.warning)W.push(Y.warning);continue}let J=Y.output?.hookSpecificOutput;if(J&&"permissionDecision"in J){switch(J.permissionDecision){case"deny":return{decision:"deny",reason:J.permissionDecisionReason};case"ask":return{decision:"ask",reason:J.permissionDecisionReason};case"allow":break}if("updatedInput"in J&&J.updatedInput)V={...V,...J.updatedInput}}}catch(Z){let Y=Z instanceof Error?Z.message:String(Z);if(W.push(`Hook failed: ${Y}`),w.config.failureBehavior==="deny")return{decision:"deny",reason:Y};else if(w.config.failureBehavior==="ask")return{decision:"ask",reason:`Hook failed: ${Y}. Continue?`}}return{decision:"allow",modifiedInput:V,warning:W.length>0?W.join(`
2
- `):void 0}}async executePostToolHooks($,b,w){if($.length===0)return{};let V=w.config.maxConcurrentHooks||5,W=await this.executeHooksConcurrently($,b,w,V),Q=[],Z,Y=[];for(let J of W){if(!J.success&&J.warning){Y.push(J.warning);continue}let X=J.output?.hookSpecificOutput;if(X&&"additionalContext"in X){if(X.additionalContext)Q.push(X.additionalContext);if("updatedOutput"in X&&X.updatedOutput!==void 0)Z=X.updatedOutput}}return{additionalContext:Q.length>0?Q.join(`
3
-
4
- `):void 0,modifiedOutput:Z,warning:Y.length>0?Y.join(`
5
- `):void 0}}async executeStopHooks($,b,w){if($.length===0)return{shouldStop:!0};let V=[];for(let W of $)try{let Q=await this.executeHook(W,b,w);if(!Q.success){if(Q.warning)V.push(Q.warning);continue}let Z=Q.output?.hookSpecificOutput;if(Z&&"continue"in Z&&Z.continue===!1)return{shouldStop:!1,continueReason:Z.continueReason,warning:V.length>0?V.join(`
6
- `):void 0}}catch(Q){let Z=Q instanceof Error?Q.message:String(Q);V.push(`Hook failed: ${Z}`)}return{shouldStop:!0,warning:V.length>0?V.join(`
7
- `):void 0}}async executeSubagentStartHooks($,b,w){if($.length===0)return{proceed:!0};let V=[],W=[];for(let Q of $)try{let Z=await this.executeHook(Q,b,w);if(!Z.success){if(Z.blocking)return{proceed:!1,warning:Z.error};if(Z.warning)V.push(Z.warning);continue}let Y=Z.output?.hookSpecificOutput;if(Y&&"additionalContext"in Y&&Y.additionalContext)W.push(Y.additionalContext)}catch(Z){let Y=Z instanceof Error?Z.message:String(Z);V.push(`Hook failed: ${Y}`)}return{proceed:!0,additionalContext:W.length>0?W.join(`
8
-
9
- `):void 0,warning:V.length>0?V.join(`
10
- `):void 0}}async executeSubagentStopHooks($,b,w){if($.length===0)return{shouldStop:!0};let V=[],W=[];for(let Q of $)try{let Z=await this.executeHook(Q,b,w);if(!Z.success){if(Z.warning)V.push(Z.warning);continue}let Y=Z.output?.hookSpecificOutput;if(Y&&"continue"in Y){if(Y.continue===!1)return{shouldStop:!1,continueReason:Y.continueReason,warning:V.length>0?V.join(`
11
- `):void 0};if("additionalContext"in Y&&Y.additionalContext)W.push(Y.additionalContext)}}catch(Z){let Y=Z instanceof Error?Z.message:String(Z);V.push(`Hook failed: ${Y}`)}return{shouldStop:!0,additionalContext:W.length>0?W.join(`
12
-
13
- `):void 0,warning:V.length>0?V.join(`
14
- `):void 0}}async executeTaskCompletedHooks($,b,w){if($.length===0)return{allowCompletion:!0};let V=[];for(let W of $)try{let Q=await this.executeHook(W,b,w);if(!Q.success){if(Q.blocking)return{allowCompletion:!1,blockReason:Q.error,warning:V.length>0?V.join(`
15
- `):void 0};if(Q.warning)V.push(Q.warning);continue}let Z=Q.output?.hookSpecificOutput;if(Z&&"blockCompletion"in Z&&Z.blockCompletion)return{allowCompletion:!1,blockReason:Z.blockReason,warning:V.length>0?V.join(`
16
- `):void 0}}catch(Q){let Z=Q instanceof Error?Q.message:String(Q);V.push(`Hook failed: ${Z}`)}return{allowCompletion:!0,warning:V.length>0?V.join(`
17
- `):void 0}}async executePermissionRequestHooks($,b,w){if($.length===0)return{decision:"ask"};let V=[];for(let W of $)try{let Q=await this.executeHook(W,b,w);if(!Q.success){if(Q.warning)V.push(Q.warning);continue}let Z=Q.output?.hookSpecificOutput;if(Z&&"permissionDecision"in Z){let Y=Z.permissionDecision;if(Y==="approve"||Y==="deny")return{decision:Y,reason:Z.permissionDecisionReason,warning:V.length>0?V.join(`
18
- `):void 0}}}catch(Q){let Z=Q instanceof Error?Q.message:String(Q);V.push(`Hook failed: ${Z}`)}return{decision:"ask",warning:V.length>0?V.join(`
19
- `):void 0}}async executeUserPromptSubmitHooks($,b,w){if($.length===0)return{proceed:!0};let V=[],W=[],Q;for(let Z of $)try{let Y=await this.executeHook(Z,b,w);if(!Y.success){if(Y.blocking)return{proceed:!1,warning:Y.error};if(Y.warning)V.push(Y.warning);continue}if(Y.stdout&&Y.stdout.trim())W.push(Y.stdout.trim());let J=Y.output?.hookSpecificOutput;if(J&&"updatedPrompt"in J){if(J.updatedPrompt)Q=J.updatedPrompt;if(J.contextInjection)W.push(J.contextInjection)}}catch(Y){let J=Y instanceof Error?Y.message:String(Y);V.push(`Hook failed: ${J}`)}return{proceed:!0,updatedPrompt:Q,contextInjection:W.length>0?W.join(`
20
-
21
- `):void 0,warning:V.length>0?V.join(`
22
- `):void 0}}async executeSessionStartHooks($,b,w){if($.length===0)return{proceed:!0};let V=[],W={};for(let Q of $)try{let Z=await this.executeHook(Q,b,w);if(!Z.success){if(Z.blocking)return{proceed:!1,warning:Z.error};if(Z.warning)V.push(Z.warning);continue}let Y=Z.output?.hookSpecificOutput;if(Y&&"env"in Y&&Y.env)Object.assign(W,Y.env)}catch(Z){let Y=Z instanceof Error?Z.message:String(Z);V.push(`Hook failed: ${Y}`)}return{proceed:!0,env:Object.keys(W).length>0?W:void 0,warning:V.length>0?V.join(`
23
- `):void 0}}async executeSessionEndHooks($,b,w){if($.length===0)return{};let V=[],W=w.config.maxConcurrentHooks||5,Q=await this.executeHooksConcurrently($,b,w,W);for(let Z of Q)if(!Z.success&&Z.warning)V.push(Z.warning);return{warning:V.length>0?V.join(`
24
- `):void 0}}async executePostToolUseFailureHooks($,b,w){if($.length===0)return{};let V=[],W=[],Q=w.config.maxConcurrentHooks||5,Z=await this.executeHooksConcurrently($,b,w,Q);for(let Y of Z){if(!Y.success&&Y.warning){V.push(Y.warning);continue}if(Y.stdout&&Y.stdout.trim())W.push(Y.stdout.trim())}return{additionalContext:W.length>0?W.join(`
25
-
26
- `):void 0,warning:V.length>0?V.join(`
27
- `):void 0}}async executeNotificationHooks($,b,w){let V="message"in b?b.message:"";if($.length===0)return{suppress:!1,message:V};let W=[],Q=!1,Z=V;for(let Y of $)try{let J=await this.executeHook(Y,b,w);if(!J.success){if(J.warning)W.push(J.warning);continue}if(J.output?.suppressOutput){Q=!0;break}if(J.stdout&&J.stdout.trim())Z=J.stdout.trim()}catch(J){let X=J instanceof Error?J.message:String(J);W.push(`Hook failed: ${X}`)}return{suppress:Q,message:Z,warning:W.length>0?W.join(`
28
- `):void 0}}async executeCompactionHooks($,b,w){if($.length===0)return{blockCompaction:!1};let V=[];for(let W of $)try{let Q=await this.executeHook(W,b,w);if(!Q.success){if(Q.warning)V.push(Q.warning);continue}let Z=Q.output?.hookSpecificOutput;if(Z&&"blockCompaction"in Z&&Z.blockCompaction)return{blockCompaction:!0,blockReason:Z.blockReason,warning:V.length>0?V.join(`
29
- `):void 0}}catch(Q){let Z=Q instanceof Error?Q.message:String(Q);V.push(`Hook failed: ${Z}`)}return{blockCompaction:!1,warning:V.length>0?V.join(`
30
- `):void 0}}async executeHook($,b,w){if($.type==="command")return this.executeCommandHook($,b,w);throw Error(`Hook type ${$.type} not yet implemented`)}async executeCommandHook($,b,w){let V=($.timeout??w.config.defaultTimeout??60)*1000;try{let W=await this.processExecutor.execute($.command,b,w,V);return this.outputParser.parse(W,$,{timeoutBehavior:w.config.timeoutBehavior,failureBehavior:w.config.failureBehavior})}catch(W){return{success:!1,blocking:!1,error:W instanceof Error?W.message:String(W),hook:$}}}async executeHooksConcurrently($,b,w,V){let W=[],Q=new Set;for(let Z of $){if(Q.size>=V)await Promise.race(Q);let Y=this.executeHook(Z,b,w).catch((X)=>({success:!1,blocking:!1,error:X instanceof Error?X.message:String(X),hook:Z})),J=Y.then(()=>{Q.delete(J)}).catch(()=>{Q.delete(J)});Q.add(J),W.push(Y)}return Promise.all(W)}}import Z1 from"picomatch";var n8=/^([A-Za-z0-9_|]+)\((.+)\)$/;class Y1{matches($,b){if(!$)return!0;if($.tools&&b.toolName){if(!this.matchTools($.tools,b))return!1}if($.paths&&b.filePath){if(!this.matchPaths($.paths,b.filePath))return!1}if($.commands&&b.command){if(!this.matchCommands($.commands,b.command))return!1}return!0}matchTools($,b){if(Array.isArray($))return $.some((w)=>this.matchToolWithParams(w,b));return this.matchToolWithParams($,b)}matchPaths($,b){if(Array.isArray($))return $.some((V)=>{return Z1(V)(b)});return Z1($)(b)}matchCommands($,b){if(Array.isArray($))return $.some((w)=>this.matchPattern(b,w));return this.matchPattern(b,$)}matchToolWithParams($,b){let{toolName:w,command:V,filePath:W}=b,Q=n8.exec($);if(!Q)return this.matchPattern(w,$);let[,Z,Y]=Q;if(!this.matchPattern(w,Z))return!1;let J=this.getArgValue(w,V,W);if(!J)return!1;return this.matchGlobOrPattern(J,Y)}getArgValue($,b,w){if($==="Bash"||$==="BashTool")return b;if(["Read","Edit","Write","Glob","Grep"].includes($))return w;return b||w}matchGlobOrPattern($,b){if(/[*?[\]{}!]/.test(b))try{return Z1(b,{bash:!0,dot:!0})($)}catch{}if(b.endsWith("*")){let w=b.slice(0,-1);return $.startsWith(w)}return $===b}matchPattern($,b){if(b==="*")return!0;if(!b.includes("|")&&!/[.*+?^${}()|[\]\\]/.test(b))return $===b;if(b.includes("|"))return b.split("|").map((V)=>V.trim()).includes($);try{return new RegExp(b).test($)}catch{return $===b}}}class m{static instance=null;config=ab;executor=new Q1;guard=new tb;matcher=new Y1;sessionDisabled=!1;constructor(){}static getInstance(){if(!m.instance)m.instance=new m;return m.instance}loadConfig($){let b=ob(ab,$),w=Iw();b=ob(b,w),this.config=b}isEnabled(){if(!this.config.enabled)return!1;if(this.sessionDisabled)return!1;return!0}disable(){this.sessionDisabled=!0,console.log("[HookManager] Hooks disabled for this session")}enable(){this.sessionDisabled=!1,console.log("[HookManager] Hooks enabled for this session")}getConfig(){return this.config}async reloadConfig(){let $=await import("node:fs/promises"),b=await import("node:path");try{let w=b.join(process.cwd(),".blade","settings.local.json"),V=await $.readFile(w,"utf-8"),W=JSON.parse(V);if(W.hooks)this.loadConfig(W.hooks)}catch{}}async executePreToolHooks($,b,w,V){if(!this.isEnabled())return{decision:"allow"};if(V.permissionMode==="plan")return{decision:"allow"};if(!this.guard.canExecute(b,"PreToolUse"))return{decision:"allow"};let W={hook_event_name:"PreToolUse",hook_execution_id:J$(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:b,tool_input:w,project_dir:V.projectDir,session_id:V.sessionId,permission_mode:V.permissionMode},Q=this.getMatchingHooks("PreToolUse",{toolName:$,filePath:this.extractFilePath(w),command:this.extractCommand($,w)});if(Q.length===0)return{decision:"allow"};let Z={projectDir:V.projectDir,sessionId:V.sessionId,permissionMode:V.permissionMode,config:this.config,abortSignal:V.abortSignal};try{let Y=await this.executor.executePreToolHooks(Q,W,Z);if(this.guard.markExecuted(b,"PreToolUse"),V.permissionMode==="yolo"){if(Y.decision==="deny")return Y;return{decision:"allow",modifiedInput:Y.modifiedInput,warning:Y.warning,reason:Y.reason}}return Y}catch(Y){return console.error("[HookManager] Error executing PreToolUse hooks:",Y),{decision:"allow",warning:`Hook execution failed: ${Y instanceof Error?Y.message:String(Y)}`}}}async executePostToolHooks($,b,w,V,W){if(!this.isEnabled())return{};if(W.permissionMode==="plan")return{};if(!this.guard.canExecute(b,"PostToolUse"))return{};let Q={hook_event_name:"PostToolUse",hook_execution_id:J$(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:b,tool_input:w,tool_response:V,project_dir:W.projectDir,session_id:W.sessionId,permission_mode:W.permissionMode},Z=this.getMatchingHooks("PostToolUse",{toolName:$,filePath:this.extractFilePath(w),command:this.extractCommand($,w)});if(Z.length===0)return{};let Y={projectDir:W.projectDir,sessionId:W.sessionId,permissionMode:W.permissionMode,config:this.config,abortSignal:W.abortSignal};try{let J=await this.executor.executePostToolHooks(Z,Q,Y);return this.guard.markExecuted(b,"PostToolUse"),J}catch(J){return console.error("[HookManager] Error executing PostToolUse hooks:",J),{warning:`Hook execution failed: ${J instanceof Error?J.message:String(J)}`}}finally{this.guard.cleanup(b)}}async executeStopHooks($){if(!this.isEnabled())return{shouldStop:!0};let b={hook_event_name:"Stop",hook_execution_id:J$(),timestamp:new Date().toISOString(),project_dir:$.projectDir,session_id:$.sessionId,permission_mode:$.permissionMode,reason:$.reason},w=this.getMatchingHooks("Stop",{});if(w.length===0)return{shouldStop:!0};let V={projectDir:$.projectDir,sessionId:$.sessionId,permissionMode:$.permissionMode,config:this.config,abortSignal:$.abortSignal};try{return await this.executor.executeStopHooks(w,b,V)}catch(W){return console.error("[HookManager] Error executing Stop hooks:",W),{shouldStop:!0,warning:`Hook execution failed: ${W instanceof Error?W.message:String(W)}`}}}async executeSubagentStartHooks($,b){if(!this.isEnabled())return{proceed:!0};let w={hook_event_name:"SubagentStart",hook_execution_id:J$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,agent_type:$,task_description:b.taskDescription,parent_agent_id:b.parentAgentId},V=this.getMatchingHooks("SubagentStart",{toolName:$});if(V.length===0)return{proceed:!0};let W={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeSubagentStartHooks(V,w,W)}catch(Q){return console.error("[HookManager] Error executing SubagentStart hooks:",Q),{proceed:!0,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executeSubagentStopHooks($,b){if(!this.isEnabled())return{shouldStop:!0};let w={hook_event_name:"SubagentStop",hook_execution_id:J$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,agent_type:$,task_description:b.taskDescription,success:b.success,result_summary:b.resultSummary,error:b.error},V=this.getMatchingHooks("SubagentStop",{});if(V.length===0)return{shouldStop:!0};let W={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeSubagentStopHooks(V,w,W)}catch(Q){return console.error("[HookManager] Error executing SubagentStop hooks:",Q),{shouldStop:!0,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executeTaskCompletedHooks($,b){if(!this.isEnabled())return{allowCompletion:!0};let w={hook_event_name:"TaskCompleted",hook_execution_id:J$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,task_id:$,task_description:b.taskDescription,result_summary:b.resultSummary,success:b.success},V=this.getMatchingHooks("TaskCompleted",{});if(V.length===0)return{allowCompletion:!0};let W={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeTaskCompletedHooks(V,w,W)}catch(Q){return console.error("[HookManager] Error executing TaskCompleted hooks:",Q),{allowCompletion:!0,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executePermissionRequestHooks($,b,w,V){if(!this.isEnabled())return{decision:"ask"};let W={hook_event_name:"PermissionRequest",hook_execution_id:J$(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:b,tool_input:w,project_dir:V.projectDir,session_id:V.sessionId,permission_mode:V.permissionMode},Q=this.getMatchingHooks("PermissionRequest",{toolName:$,filePath:this.extractFilePath(w),command:this.extractCommand($,w)});if(Q.length===0)return{decision:"ask"};let Z={projectDir:V.projectDir,sessionId:V.sessionId,permissionMode:V.permissionMode,config:this.config,abortSignal:V.abortSignal};try{return await this.executor.executePermissionRequestHooks(Q,W,Z)}catch(Y){return console.error("[HookManager] Error executing PermissionRequest hooks:",Y),{decision:"ask",warning:`Hook execution failed: ${Y instanceof Error?Y.message:String(Y)}`}}}async executeUserPromptSubmitHooks($,b){if(!this.isEnabled())return{proceed:!0};let w={hook_event_name:"UserPromptSubmit",hook_execution_id:J$(),timestamp:new Date().toISOString(),user_prompt:$,has_images:b.hasImages,image_count:b.imageCount,project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode},V=this.getMatchingHooks("UserPromptSubmit",{});if(V.length===0)return{proceed:!0};let W={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeUserPromptSubmitHooks(V,w,W)}catch(Q){return console.error("[HookManager] Error executing UserPromptSubmit hooks:",Q),{proceed:!0,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executeSessionStartHooks($){if(!this.isEnabled())return{proceed:!0};let b={hook_event_name:"SessionStart",hook_execution_id:J$(),timestamp:new Date().toISOString(),project_dir:$.projectDir,session_id:$.sessionId,permission_mode:$.permissionMode,is_resume:$.isResume,resume_session_id:$.resumeSessionId},w=this.getMatchingHooks("SessionStart",{});if(w.length===0)return{proceed:!0};let V={projectDir:$.projectDir,sessionId:$.sessionId,permissionMode:$.permissionMode,config:this.config,abortSignal:$.abortSignal};try{return await this.executor.executeSessionStartHooks(w,b,V)}catch(W){return console.error("[HookManager] Error executing SessionStart hooks:",W),{proceed:!0,warning:`Hook execution failed: ${W instanceof Error?W.message:String(W)}`}}}async executeSessionEndHooks($,b){if(!this.isEnabled())return{};let w={hook_event_name:"SessionEnd",hook_execution_id:J$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,reason:$},V=this.getMatchingHooks("SessionEnd",{});if(V.length===0)return{};let W={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeSessionEndHooks(V,w,W),{}}catch(Q){return console.error("[HookManager] Error executing SessionEnd hooks:",Q),{warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executePostToolUseFailureHooks($,b,w,V,W){if(!this.isEnabled())return{};let Q={hook_event_name:"PostToolUseFailure",hook_execution_id:J$(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:b,tool_input:w,error:V,error_type:W.errorType,is_interrupt:W.isInterrupt,is_timeout:W.isTimeout,project_dir:W.projectDir,session_id:W.sessionId,permission_mode:W.permissionMode},Z=this.getMatchingHooks("PostToolUseFailure",{toolName:$,filePath:this.extractFilePath(w),command:this.extractCommand($,w)});if(Z.length===0)return{};let Y={projectDir:W.projectDir,sessionId:W.sessionId,permissionMode:W.permissionMode,config:this.config,abortSignal:W.abortSignal};try{return await this.executor.executePostToolUseFailureHooks(Z,Q,Y)}catch(J){return console.error("[HookManager] Error executing PostToolUseFailure hooks:",J),{warning:`Hook execution failed: ${J instanceof Error?J.message:String(J)}`}}}async executeNotificationHooks($,b,w){if(!this.isEnabled())return{suppress:!1,message:b};let V={hook_event_name:"Notification",hook_execution_id:J$(),timestamp:new Date().toISOString(),project_dir:w.projectDir,session_id:w.sessionId,permission_mode:w.permissionMode,notification_type:$,title:w.title,message:b},W=this.getMatchingHooks("Notification",{});if(W.length===0)return{suppress:!1,message:b};let Q={projectDir:w.projectDir,sessionId:w.sessionId,permissionMode:w.permissionMode,config:this.config,abortSignal:w.abortSignal};try{return await this.executor.executeNotificationHooks(W,V,Q)}catch(Z){return console.error("[HookManager] Error executing Notification hooks:",Z),{suppress:!1,message:b,warning:`Hook execution failed: ${Z instanceof Error?Z.message:String(Z)}`}}}async executeCompactionHooks($,b){if(!this.isEnabled())return{blockCompaction:!1};let w={hook_event_name:"Compaction",hook_execution_id:J$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,trigger:$,messages_before:b.messagesBefore,tokens_before:b.tokensBefore},V=this.getMatchingHooks("Compaction",{});if(V.length===0)return{blockCompaction:!1};let W={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeCompactionHooks(V,w,W)}catch(Q){return console.error("[HookManager] Error executing Compaction hooks:",Q),{blockCompaction:!1,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}getMatchingHooks($,b){let w=this.config[$]||[],V=[];for(let W of w)if(this.matcher.matches(W.matcher,b))V.push(...W.hooks);return V}extractFilePath($){let b=["file_path","path","filePath","source","target"];for(let w of b){let V=$[w];if(typeof V==="string")return V}return}extractCommand($,b){if($==="Bash"||$==="BashTool"){let w=b.command;if(typeof w==="string")return w}return}cleanup(){this.guard.cleanupAll()}}import{appendFileSync as s8,existsSync as r8,mkdirSync as a8,readdirSync as o8,statSync as pw,unlinkSync as t8}from"node:fs";import e8 from"node:os";import X1 from"node:path";var O1;((W)=>{W[W.DEBUG=0]="DEBUG";W[W.INFO=1]="INFO";W[W.WARN=2]="WARN";W[W.ERROR=3]="ERROR"})(O1||={});var p;((B)=>{B.AGENT="Agent";B.UI="UI";B.TOOL="Tool";B.SERVICE="Service";B.CONFIG="Config";B.CONTEXT="Context";B.EXECUTION="Execution";B.LOOP="Loop";B.CHAT="Chat";B.GENERAL="General";B.PROMPTS="Prompts";B.SPEC="Spec"})(p||={});var J1=null,hw=null,xw=!1;function oW($){if(J1!==$)J1=$}async function tW(){}function $5(){if(xw)return hw;xw=!0;try{let $=X1.join(e8.homedir(),".blade","logs");if(!r8($))a8($,{recursive:!0,mode:493});if(pw($).uid===0&&process.getuid&&process.getuid()!==0)return console.error(""),console.error("❌ 权限错误:~/.blade/logs 目录属于 root 用户"),console.error(""),console.error("这通常是因为您曾经使用 sudo 运行过 blade。"),console.error(""),console.error("解决方法:"),console.error(" sudo chown -R $USER:$USER ~/.blade/"),console.error(""),console.error("然后重新运行 blade(不要使用 sudo)"),console.error(""),null;return b5($,30),hw=$,$}catch($){return console.error("[Logger] 无法创建日志目录:",$),null}}function b5($,b){try{let w=o8($),V=Date.now(),W=b*24*60*60*1000;for(let Q of w){if(!Q.startsWith("blade-")||!Q.endsWith(".log")&&!Q.endsWith(".jsonl"))continue;let Z=X1.join($,Q);try{let Y=pw(Z);if(V-Y.mtimeMs>W)t8(Z)}catch(Y){}}}catch(w){}}function w5(){let $=$5();if(!$)return null;let b=J1||"default";return X1.join($,`blade-${b}.jsonl`)}function V5($,b,w){let V=w5();if(!V)return;try{let W={timestamp:new Date().toISOString(),level:O1[b],category:$,message:w};s8(V,JSON.stringify(W)+`
31
- `)}catch(W){}}class T${static globalDebugConfig=null;enabled;minLevel;category;constructor($={}){if($.enabled!==void 0)this.enabled=$.enabled;else if(T$.globalDebugConfig!==null)this.enabled=Boolean(T$.globalDebugConfig);else this.enabled=!1;this.minLevel=$.minLevel??0,this.category=$.category??"General"}static setGlobalDebug($){T$.globalDebugConfig=$}static clearGlobalDebug(){T$.globalDebugConfig=null}setEnabled($){this.enabled=$}parseDebugFilter($){if(!$)return{enabled:!1};if($===!0||$==="true"||$==="1")return{enabled:!0};let b=String($).trim();if(!b)return{enabled:!0};if(b.startsWith("!"))return{enabled:!0,filter:{mode:"exclude",categories:b.split(",").map((W)=>W.trim().replace(/^!/,"")).filter(Boolean)}};return{enabled:!0,filter:{mode:"include",categories:b.split(",").map((V)=>V.trim()).filter(Boolean)}}}shouldLogCategory($){if(!$)return!0;let b=this.category.toLowerCase();if($.mode==="include")return $.categories.some((w)=>b.includes(w.toLowerCase()));return!$.categories.some((w)=>b.includes(w.toLowerCase()))}shouldLogToConsole($){if(T$.globalDebugConfig!==null){let{enabled:b,filter:w}=this.parseDebugFilter(T$.globalDebugConfig);if(!b)return!1;if($<this.minLevel)return!1;return this.shouldLogCategory(w)}return this.enabled&&$>=this.minLevel}log($,...b){let w=b.map((V)=>typeof V==="object"?JSON.stringify(V):String(V)).join(" ");if(V5(this.category,$,w),this.shouldLogToConsole($)){let V=O1[$],W=`[${this.category}] [${V}]`;console.error(W,...b)}}debug(...$){this.log(0,...$)}info(...$){this.log(1,...$)}warn(...$){this.log(2,...$)}error(...$){this.log(3,...$)}}function N($,b){return new T$({...b,category:$})}var I=new T$({category:"General"});import{ProxyAgent as W5,fetch as Q5}from"undici";function Z5(){return process.env.HTTPS_PROXY||process.env.HTTP_PROXY||process.env.https_proxy||process.env.http_proxy}function Y5(){let $=Z5();if($)try{return new W5($)}catch(b){console.warn(`[proxyFetch] Invalid proxy URL: ${$}`)}return}async function dw($,b={}){let{timeout:w=30000,signal:V,...W}=b;if(V?.aborted)throw new DOMException("The operation was aborted.","AbortError");let Q=Y5(),Z=new AbortController,Y=!1,J=setTimeout(()=>{Y=!0,Z.abort()},w),X=()=>Z.abort();V?.addEventListener("abort",X);try{let O={method:W.method,headers:W.headers,body:W.body,signal:Z.signal,dispatcher:Q};return await Q5($.toString(),O)}catch(O){if(O instanceof Error&&O.name==="AbortError"){if(Y)throw Error(`Request timeout after ${w}ms`);throw O}throw O}finally{clearTimeout(J),V?.removeEventListener("abort",X)}}var T0=N("Service"),J5="https://blade-api-proxy.137844255.workers.dev/v1/get-zhipu-key",uw="blade-free-tier",Qb=null;async function gw($){if($!==uw)return $;if(Qb)return T0.debug("使用缓存的内置 API Key"),Qb;try{T0.info("\uD83D\uDD11 正在从代理服务获取内置 API Key...");let b=await dw(J5,{method:"GET",headers:{Authorization:`Bearer ${uw}`,"Content-Type":"application/json"},timeout:1e4});if(!b.ok){let V=await b.text();throw Error(`获取 API Key 失败: ${b.status} - ${V}`)}let w=await b.json();if(!w.apiKey)throw Error("代理服务返回的数据中没有 apiKey");if(Qb=w.apiKey,T0.info("✅ 成功获取内置 API Key"),w.message)T0.debug(`提示: ${w.message}`);return Qb}catch(b){throw T0.error("❌ 获取内置 API Key 失败:",b),Error(`无法获取内置模型的 API Key: ${b instanceof Error?b.message:"未知错误"}
32
- `+"请检查网络连接或使用自己的 API Key (/config)")}}import{createAnthropic as X5}from"@ai-sdk/anthropic";import{createAzure as O5}from"@ai-sdk/azure";import{createDeepSeek as G5}from"@ai-sdk/deepseek";import{createGoogleGenerativeAI as B5}from"@ai-sdk/google";import{createOpenAICompatible as G1}from"@ai-sdk/openai-compatible";import{generateText as K5,jsonSchema as mw,Output as q5,streamText as A5}from"ai";var H$=N("Chat");function cw($){let b=new Set;for(let w of $)if(w.role==="assistant"&&w.tool_calls)for(let V of w.tool_calls)b.add(V.id);return $.filter((w)=>{if(w.role==="tool"){if(!w.tool_call_id)return!1;return b.has(w.tool_call_id)}return!0})}function Zb($){if(typeof $==="string")return $;return $.filter((b)=>b.type==="text").map((b)=>b.text).join(`
33
- `)}function U5($,b={}){try{return JSON.parse($)}catch{return H$.warn("⚠️ [VercelAIChatService] Failed to parse JSON, using fallback",{str:$}),b}}class B1{model;config;constructor($){this.config=$,this.model=this.createModel($),H$.debug("\uD83D\uDE80 [VercelAIChatService] Initialized",{provider:$.provider,model:$.model,providerId:$.providerId})}createModel($){let{provider:b,apiKey:w,baseUrl:V,model:W,customHeaders:Q,providerId:Z,apiVersion:Y}=$;switch(b){case"anthropic":return X5({apiKey:w,baseURL:V||void 0,headers:Q})(W);case"gemini":{if(V&&!this.isGeminiOfficialUrl(V))return G1({name:"gemini",apiKey:w,baseURL:V,headers:Q})(W);return B5({apiKey:w,baseURL:V||void 0})(W)}case"azure-openai":{let J=this.extractAzureResourceName(V);if(J)return O5({apiKey:w,resourceName:J,apiVersion:Y||"2024-08-01-preview"})(W);let X=this.buildAzureBaseUrl(V,W);return G1({name:"azure-openai",apiKey:w,baseURL:X,headers:{...Q,"api-key":w},queryParams:{"api-version":Y||"2024-08-01-preview"}})(W)}default:{if(Z==="deepseek")return G5({apiKey:w,baseURL:V||void 0,headers:Q})(W);return G1({name:Z||"custom",apiKey:w,baseURL:V,headers:Q})(W)}}}extractAzureResourceName($){if(!$)return;let b=$.match(/https:\/\/([^.]+)\.openai\.azure(?:\.com|\.us|\.cn|\.de)/);return b?b[1]:void 0}buildAzureBaseUrl($,b){if(!$)return"";let w=$.replace(/\/$/,"").replace(/\?.*$/,"");if(w.includes("/openai/deployments/"))return w;return`${w}/openai/deployments/${b}`}isGeminiOfficialUrl($){return $.includes("generativelanguage.googleapis.com")||$.includes("aiplatform.googleapis.com")}convertMessages($){let b=[];for(let w of $)if(w.role==="system")if(Array.isArray(w.content)){let V=w.content.find((Q)=>Q.type==="text"),W={role:"system",content:Zb(w.content)};if(V?.providerOptions)W.providerOptions=V.providerOptions;b.push(W)}else b.push({role:"system",content:w.content});else if(w.role==="user")if(Array.isArray(w.content)){let V=w.content.map((W)=>{if(W.type==="text"){let Q={type:"text",text:W.text};if(W.providerOptions)Q.providerOptions=W.providerOptions;return Q}return{type:"image",image:W.image_url.url}});b.push({role:"user",content:V})}else b.push({role:"user",content:w.content});else if(w.role==="assistant")if(w.tool_calls&&w.tool_calls.length>0){let V=w.tool_calls.map((Q)=>{let Z=Q.function;return{type:"tool-call",toolCallId:Q.id,toolName:Z?.name||"",input:U5(Z?.arguments||"{}",{})}}),W=Zb(w.content);if(W)b.push({role:"assistant",content:[{type:"text",text:W},...V]});else b.push({role:"assistant",content:V})}else b.push({role:"assistant",content:Zb(w.content)});else if(w.role==="tool")b.push({role:"tool",content:[{type:"tool-result",toolCallId:w.tool_call_id,toolName:w.name||"unknown",output:{type:"text",value:Zb(w.content)}}]});return b}convertTools($){if(!$||$.length===0)return;let b={};for(let w of $)b[w.name]={description:w.description,inputSchema:mw(w.parameters)};return b}convertToolCalls($){return $.map((b)=>({id:b.toolCallId,type:"function",function:{name:b.toolName,arguments:JSON.stringify(b.args??b.input??{})}}))}convertOutputFormat($){if(!$||$.type!=="json_schema")return;let{json_schema:b}=$;return q5.object({schema:mw(b.schema)})}convertUsage($,b){if(!$)return;let w=$.promptTokens??0,V=$.completionTokens??0,W={promptTokens:w,completionTokens:V,totalTokens:$.totalTokens??w+V};if(b?.anthropic){if(b.anthropic.cacheCreationInputTokens!==void 0)W.cacheCreationInputTokens=b.anthropic.cacheCreationInputTokens;if(b.anthropic.cacheReadInputTokens!==void 0)W.cacheReadInputTokens=b.anthropic.cacheReadInputTokens}return W}async chat($,b,w){let V=Date.now();H$.debug("\uD83D\uDE80 [VercelAIChatService] Starting chat request");let W=cw($),Q=this.convertMessages(W),Z=this.convertTools(b),Y=this.convertOutputFormat(this.config.outputFormat);try{let J=await K5({model:this.model,messages:Q,tools:Z,maxOutputTokens:this.config.maxOutputTokens,temperature:this.config.temperature??0,abortSignal:w,experimental_output:Y}),X=Date.now()-V;H$.debug("\uD83D\uDCE5 [VercelAIChatService] Response received in",X,"ms");let O=J.toolCalls&&J.toolCalls.length>0?this.convertToolCalls(J.toolCalls):void 0,G=Array.isArray(J.reasoning)?J.reasoning.map((B)=>B.text).join(""):void 0;return{content:J.text,reasoningContent:G,toolCalls:O,usage:this.convertUsage(J.usage,J.providerMetadata)}}catch(J){let X=Date.now()-V;throw H$.error("❌ [VercelAIChatService] Chat failed after",X,"ms"),J}}async*streamChat($,b,w){let V=Date.now();H$.debug("\uD83D\uDE80 [VercelAIChatService] Starting stream request");let W=cw($),Q=this.convertMessages(W),Z=this.convertTools(b),Y=this.convertOutputFormat(this.config.outputFormat);try{let J=A5({model:this.model,messages:Q,tools:Z,maxOutputTokens:this.config.maxOutputTokens,temperature:this.config.temperature??0,abortSignal:w,experimental_output:Y});H$.debug("\uD83D\uDCE5 [VercelAIChatService] Stream started");let X=0;for await(let G of J.fullStream)switch(G.type){case"text-delta":yield{content:G.text??G.textDelta};break;case"reasoning-delta":yield{reasoningContent:G.textDelta};break;case"tool-call":yield{toolCalls:[{index:X++,id:G.toolCallId,type:"function",function:{name:G.toolName,arguments:JSON.stringify(G.args??G.input??{})}}]};break;case"finish":yield{finishReason:G.finishReason,usage:this.convertUsage(G.totalUsage,G.providerMetadata)};break}let O=Date.now()-V;H$.debug("✅ [VercelAIChatService] Stream completed in",O,"ms")}catch(J){let X=Date.now()-V;throw H$.error("❌ [VercelAIChatService] Stream failed after",X,"ms"),J}}getConfig(){return{...this.config}}updateConfig($){H$.debug("\uD83D\uDD04 [VercelAIChatService] Updating configuration"),this.config={...this.config,...$},this.model=this.createModel(this.config),H$.debug("✅ [VercelAIChatService] Configuration updated")}}var iw=N("Service"),C5="blade-free-tier";function F5($){return $===C5}function H5($){return{}}async function Yb($){let b=$;if(F5($.apiKey)){iw.info("\uD83D\uDD11 检测到内置 API Key,正在获取...");let w=await gw($.apiKey);b={...$,apiKey:w}}if(b.providerId){let w=H5(b.providerId);if(Object.keys(w).length>0)b={...b,customHeaders:{...w,...b.customHeaders}},iw.debug(`\uD83D\uDD27 注入 ${b.providerId} 特定 headers:`,Object.keys(w))}return _5(b)}function _5($){return new B1($)}import{readFile as R5}from"node:fs/promises";import{basename as E5}from"node:path";class s{static MAX_FILES=5;static MAX_LINES_PER_FILE=1000;static analyzeFiles($){let b=new Map;return $.forEach((V,W)=>{let Q=typeof V.content==="string"?V.content:(V.content||[]).filter((Y)=>Y.type==="text").map((Y)=>Y.text).join(`
34
- `);if(s.extractFilePathsFromContent(Q).forEach((Y)=>{s.updateFileReference(b,Y,W,!1)}),V.tool_calls&&Array.isArray(V.tool_calls))V.tool_calls.forEach((Y)=>{let J=s.extractFilePathsFromToolCall(Y),X=Y.type==="function"&&"function"in Y?Y.function?.name:"",O=["Write","Edit"].includes(X||"");J.forEach((G)=>{s.updateFileReference(b,G,W,O)})})}),Array.from(b.values()).sort((V,W)=>{if(V.wasModified!==W.wasModified)return V.wasModified?-1:1;if(V.mentions!==W.mentions)return W.mentions-V.mentions;return W.lastMentioned-V.lastMentioned}).slice(0,s.MAX_FILES)}static async readFilesContent($){let b=[];for(let w of $)try{let V=await R5(w,"utf-8"),W=V.split(`
35
- `),Q=W.length,Z=V,Y=!1,J=Q;if(Q>s.MAX_LINES_PER_FILE)Z=W.slice(0,s.MAX_LINES_PER_FILE).join(`
36
- `),Z+=`
37
-
38
- ... (truncated ${Q-s.MAX_LINES_PER_FILE} lines)`,Y=!0,J=s.MAX_LINES_PER_FILE;b.push({path:w,content:Z,truncated:Y,lines:Q,includedLines:J})}catch(V){console.warn(`[FileAnalyzer] 无法读取文件: ${w}`,V)}return b}static extractFilePathsFromContent($){let b=new Set,w=/```(?:\w+)?\s*\n?([\s\S]*?)```/g,V=Array.from($.matchAll(w));for(let Q of V){let Z=Q[1];s.extractPathsFromText(Z).forEach((J)=>b.add(J))}return s.extractPathsFromText($).forEach((Q)=>b.add(Q)),Array.from(b)}static extractPathsFromText($){let b=[],w=[/(?:src|tests?|docs?|lib|config|scripts?|bin|utils?|components?|services?|hooks?)\/[\w\-/.]+\.[\w]+/g,/(?:package|tsconfig|vite\.config|webpack\.config|next\.config|babel\.config)\.[\w]+/g,/(?:\.\.?\/|\/)[a-zA-Z0-9\-_/.]+\.[\w]+/g];for(let V of w){let W=Array.from($.matchAll(V));for(let Q of W){let Z=Q[0];if(Z=Z.replace(/[,。;:!?""''()【】《》]$/g,""),Z=Z.replace(/[,.;:!?"'()[\]<>]$/g,""),s.isValidFilePath(Z))b.push(Z)}}return b}static extractFilePathsFromToolCall($){let b=[];if($.type!=="function"||!$.function)return b;try{let w=$.function.name,V=JSON.parse($.function.arguments||"{}");if(["Read","Write","Edit","Glob","Grep","NotebookEdit","mcp__github__get_file_contents","mcp__github__create_or_update_file"].includes(w)){let Q=["file_path","path","notebook_path","filePath"];for(let Z of Q)if(V[Z]&&typeof V[Z]==="string")b.push(V[Z])}}catch{}return b}static updateFileReference($,b,w,V){let W=$.get(b);if(W)W.mentions++,W.lastMentioned=w,W.wasModified=W.wasModified||V;else $.set(b,{path:b,mentions:1,lastMentioned:w,wasModified:V})}static isValidFilePath($){if(!$.includes("/"))return!1;let b=E5($);if(!b.includes("."))return!1;let w=["ts","tsx","js","jsx","json","md","py","java","go","rs","c","cpp","h","css","scss","html","xml","yaml","yml","toml","sh","bash","sql","graphql","vue","svelte"],V=b.split(".").pop()?.toLowerCase();if(!V||!w.includes(V))return!1;return!0}}import{encodingForModel as lw}from"js-tiktoken";class $${static encodingCache=new Map;static countTokens($,b){let w=$$.getEncoding(b),V=0;for(let W of $){if(V+=4,W.role)V+=w.encode(W.role).length;if(W.content)if(typeof W.content==="string")V+=w.encode(W.content).length;else V+=w.encode(JSON.stringify(W.content)).length;if(W.tool_calls&&Array.isArray(W.tool_calls))V+=$$.countToolCallTokens(W.tool_calls,w);if(W.name)V+=w.encode(W.name).length}return V}static getTokenLimit($){return $}static shouldCompact($,b,w,V=0.8){let W=$$.countTokens($,b),Q=Math.floor(w*V);return W>=Q}static getEncoding($){if(!$$.encodingCache.has($))try{let b=lw($);$$.encodingCache.set($,b)}catch{try{let b=lw("gpt-4");$$.encodingCache.set($,b)}catch{console.warn(`[TokenCounter] 无法为模型 ${$} 获取 encoding,使用粗略估算`),$$.encodingCache.set($,{encode:(b)=>{return Array(Math.ceil(b.length/4))}})}}return $$.encodingCache.get($)}static countToolCallTokens($,b){let w=0;for(let V of $){if(w+=4,V.type==="function"&&V.function?.name)w+=b.encode(V.function.name).length;if(V.type==="function"&&V.function?.arguments)w+=b.encode(V.function.arguments).length;if(V.id)w+=b.encode(V.id).length}return w}static clearCache(){$$.encodingCache.clear()}static estimateTokens($){let b=($.match(/[\u4e00-\u9fa5]/g)||[]).length,w=$.length-b;return Math.ceil(b/1.5+w/4)}}class r{static THRESHOLD_PERCENT=0.8;static RETAIN_PERCENT=0.2;static FALLBACK_RETAIN_PERCENT=0.3;static async compact($,b){let w=b.actualPreTokens??$$.countTokens($,b.modelName),V=b.actualPreTokens?"actual (from LLM usage)":"estimated";console.log(`[CompactionService] preTokens source: ${V}`);try{let Q=await m.getInstance().executeCompactionHooks(b.trigger,{projectDir:process.cwd(),sessionId:b.sessionId||"unknown",permissionMode:b.permissionMode||v.DEFAULT,messagesBefore:$.length,tokensBefore:w});if(Q.blockCompaction)return console.log(`[CompactionService] Compaction hook 阻止压缩: ${Q.blockReason||"(无原因)"}`),{success:!1,summary:"",preTokens:w,postTokens:w,filesIncluded:[],compactedMessages:$,boundaryMessage:{role:"system",content:""},summaryMessage:{role:"user",content:""},error:Q.blockReason||"Compaction blocked by hook"};if(Q.warning)console.warn(`[CompactionService] Compaction hook warning: ${Q.warning}`)}catch(W){console.warn("[CompactionService] Compaction hook execution failed:",W)}try{console.log("[CompactionService] 开始压缩,消息数:",$.length),console.log("[CompactionService] 压缩前 tokens:",w);let Q=s.analyzeFiles($).map((H)=>H.path);console.log("[CompactionService] 提取重点文件:",Q);let Z=await s.readFilesContent(Q);console.log("[CompactionService] 成功读取文件:",Z.length);let Y=await r.generateSummary($,Z,b);console.log("[CompactionService] 生成总结,长度:",Y.length);let J=Math.ceil($.length*r.RETAIN_PERCENT),X=$.slice(-J),O=new Set;for(let H of X)if(H.role==="assistant"&&H.tool_calls)for(let F of H.tool_calls)O.add(F.id);let G=X.filter((H)=>{if(H.role==="tool"&&H.tool_call_id)return O.has(H.tool_call_id);return!0});console.log("[CompactionService] 保留消息数:",J),console.log("[CompactionService] 过滤后保留消息数:",G.length);let B=G0(),q=r.createBoundaryMessage(B,b.trigger,w),U=G0(),K=r.createSummaryMessage(U,Y),_=[K,...G],C=$$.countTokens(_,b.modelName);return console.log("[CompactionService] 压缩完成!"),console.log("[CompactionService] Token 变化:",w,"→",C,`(-${((1-C/w)*100).toFixed(1)}%)`),{success:!0,summary:Y,preTokens:w,postTokens:C,filesIncluded:Q,compactedMessages:_,boundaryMessage:q,summaryMessage:K}}catch(W){return console.error("[CompactionService] 压缩失败,使用降级策略",W),r.fallbackCompact($,b,w,W)}}static async generateSummary($,b,w){let V=r.buildCompactionPrompt($,b);console.log("[CompactionService] 使用压缩模型:",w.modelName);let Z=(await(await Yb({apiKey:w.apiKey||process.env.BLADE_API_KEY||"",baseUrl:w.baseURL||process.env.BLADE_BASE_URL||"https://api.openai.com/v1",model:w.modelName,temperature:0.3,maxOutputTokens:8000,timeout:60000,provider:"openai-compatible"})).chat([{role:"user",content:V}])).content||"",Y=Z.match(/<summary>([\s\S]*?)<\/summary>/);if(!Y)return console.warn("[CompactionService] 总结格式不正确,使用完整响应"),Z;return Y[1].trim()}static buildCompactionPrompt($,b){let w=$.map((Q,Z)=>{let Y=Q.role||"unknown",J=typeof Q.content==="string"?Q.content:JSON.stringify(Q.content),X=5000,O=J.length>5000?J.substring(0,5000)+"...":J;return`[${Z+1}] ${Y}: ${O}`}).join(`
39
-
40
- `),V=b.map((Q)=>{return`### ${Q.path}
41
- \`\`\`
42
- ${Q.content}
43
- \`\`\``}).join(`
44
-
45
- `),W=`Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
46
- This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.
47
-
48
- Before providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:
49
-
50
- 1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:
51
- - The user's explicit requests and intents
52
- - Your approach to addressing the user's requests
53
- - Key decisions, technical concepts and code patterns
54
- - Specific details like:
55
- - file names
56
- - full code snippets
57
- - function signatures
58
- - file edits
59
- - Errors that you ran into and how you fixed them
60
- - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
61
- 2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.
62
-
63
- Your summary should include the following sections:
64
-
65
- 1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail
66
- 2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.
67
- 3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
68
- 4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
69
- 5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
70
- 6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.
71
- 7. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
72
- 8. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
73
- 9. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request.`;return`Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
74
- This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.
75
-
76
- Before providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:
77
-
78
- 1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:
79
- - The user's explicit requests and intents
80
- - Your approach to addressing the user's requests
81
- - Key decisions, technical concepts and code patterns
82
- - Specific details like:
83
- - file names
84
- - full code snippets
85
- - function signatures
86
- - file edits
87
- - Errors that you ran into and how you fixed them
88
- - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
89
- 2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.
90
-
91
- Your summary should include the following sections:
92
-
93
- 1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail
94
- 2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.
95
- 3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
96
- 4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
97
- 5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
98
- 6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.
99
- 7. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
100
- 8. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
101
- 9. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request.
102
-
103
- ## Conversation History
104
-
105
- ${w}
106
-
107
- ${b.length>0?`## Important Files
108
-
109
- ${V}`:""}
110
-
111
- Please provide your summary following the structure specified above, with both <analysis> and <summary> sections.`}static createBoundaryMessage($,b,w){return{id:G0(),role:"system",content:"Conversation compacted",metadata:{type:"system",subtype:"compact_boundary",parentId:$,compactMetadata:{trigger:b,preTokens:w}}}}static createSummaryMessage($,b){return{id:G0(),role:"user",content:b,metadata:{parentId:$,isCompactSummary:!0}}}static fallbackCompact($,b,w,V){let W=Math.ceil($.length*r.FALLBACK_RETAIN_PERCENT),Q=$.slice(-W),Z=new Set;for(let K of Q)if(K.role==="assistant"&&K.tool_calls)for(let _ of K.tool_calls)Z.add(_.id);let Y=Q.filter((K)=>{if(K.role==="tool"&&K.tool_call_id)return Z.has(K.tool_call_id);return!0}),J=G0(),X=r.createBoundaryMessage(J,b.trigger,w),O=V instanceof Error?V.message:String(V),G=G0(),B=r.createSummaryMessage(G,`[Automatic compaction failed; using fallback]
112
-
113
- An error occurred during compaction. Retained the latest ${W} messages (~30%).
114
-
115
- Error: ${O}
116
-
117
- The conversation can continue, but consider retrying compaction later with /compact.`),q=[B,...Y],U=$$.countTokens(q,b.modelName);return{success:!1,summary:typeof B.content==="string"?B.content:B.content.filter((K)=>K.type==="text").map((K)=>K.text).join(`
118
- `),preTokens:w,postTokens:U,filesIncluded:[],compactedMessages:q,boundaryMessage:X,summaryMessage:B,error:O}}}import{EventEmitter as h5}from"events";import{z as B$}from"zod";function y9($){return $!==void 0&&typeof $.pattern==="string"&&typeof $.search_path==="string"}function z9($){return $!==void 0&&$.kind==="edit"&&typeof $.matches_found==="number"}function B0($){return $==="readonly"}import{isPlainObject as D5}from"lodash-es";class K1{toolName;params;context;aborted=!1;result;_internal={};constructor($,b,w){this.toolName=$;this.params=b;this.context=w}shouldAbort(){return this.aborted||(this.context.signal?.aborted??!1)}abort($,b){this.aborted=!0,this.result={success:!1,llmContent:`Tool execution aborted: ${$||"Unknown reason"}`,displayContent:`执行已中止: ${$||"未知原因"}`,error:{type:"execution_error",message:$||"Execution aborted"},metadata:b?.shouldExitLoop?{shouldExitLoop:!0}:void 0}}setResult($){this.result=$}getResult(){if(!this.result)throw Error("Tool execution result not set");return this.result}}function k0($){if($===void 0)return"undefined";if(typeof $==="string")return $;try{let b=JSON.stringify($);return b===void 0?String($):b}catch{return String($)}}class nw extends Error{issues;type;constructor($,b,w="validation_error"){super($);this.issues=b;this.type=w;this.name="ToolValidationError"}}function L5($){let{code:b}=$,w=$,V=w.received;switch(b){case"invalid_type":{let W=w.expected;return`类型错误:期望 ${k0(W)},实际收到 ${k0(V)}`}case"too_small":{let{minimum:W,inclusive:Q}=w,Z=typeof w.type==="string"?w.type:void 0;if(Z==="string"&&typeof W==="number")return`长度不能少于 ${W} 个字符`;if(Z==="number"&&typeof W==="number")return`不能小于${Q?"等于":""} ${W}`;if(Z==="array"&&typeof W==="number")return`数组长度不能少于 ${W}`;return"值太小"}case"too_big":{let{maximum:W,inclusive:Q}=w,Z=typeof w.type==="string"?w.type:void 0;if(Z==="string"&&typeof W==="number")return`长度不能超过 ${W} 个字符`;if(Z==="number"&&typeof W==="number")return`不能大于${Q?"等于":""} ${W}`;if(Z==="array"&&typeof W==="number")return`数组长度不能超过 ${W}`;return"值太大"}case"invalid_string":{let W=w.validation;if(W==="email")return"必须是有效的电子邮件地址";if(W==="url")return"必须是有效的 URL";if(W==="uuid")return"必须是有效的 UUID";if(D5(W)){let Q=W;if(typeof Q.includes==="string")return`必须包含 "${Q.includes}"`;if(typeof Q.startsWith==="string")return`必须以 "${Q.startsWith}" 开头`;if(typeof Q.endsWith==="string")return`必须以 "${Q.endsWith}" 结尾`}return"字符串格式不正确"}case"invalid_enum_value":{let W=w.options;if(Array.isArray(W))return`必须是以下值之一:${W.map((Q)=>k0(Q)).join(", ")}`;return"必须是枚举允许的值之一"}case"invalid_literal":{let W=w.expected;return`必须是字面量值:${k0(W)}`}case"unrecognized_keys":{let W=w.keys;if(Array.isArray(W))return`包含未知的参数:${W.map((Q)=>k0(Q)).join(", ")}`;return"包含未知的参数"}case"invalid_union":return"不符合任何有效的类型定义";case"invalid_date":return"必须是有效的日期";case"custom":return $.message||"自定义验证失败";default:return $.message||"验证失败"}}function j5($){let b=$.issues.map((V)=>{let W=V.path.join("."),Q=L5(V),Z=V.received;return{field:W||"root",message:Q,value:Z}}),w=b.length===1?`参数验证失败 [${b[0].field}]: ${b[0].message}`:`参数验证失败 (${b.length} 个错误):
119
- ${b.map((V)=>` - ${V.field}: ${V.message}`).join(`
120
- `)}`;return new nw(w,b)}function sw($,b){let w=$.safeParse(b);if(!w.success)throw j5(w.error);return w.data}import{zodToJsonSchema as N5}from"zod-to-json-schema";function q1($){return N5($,{target:"jsonSchema7",$refStrategy:"none"})}class Jb{toolName;params;executeFn;descriptionFn;affectedPathsFn;constructor($,b,w,V,W){this.toolName=$;this.params=b;this.executeFn=w;this.descriptionFn=V;this.affectedPathsFn=W}getDescription(){if(this.descriptionFn)return this.descriptionFn(this.params);return`执行工具: ${this.toolName}`}getAffectedPaths(){if(this.affectedPathsFn)return this.affectedPathsFn(this.params);return[]}async execute($,b,w){let V={signal:$,updateOutput:b,...w};return this.executeFn(this.params,V)}}function E($){return{name:$.name,displayName:$.displayName,kind:$.kind,isReadOnly:$.isReadOnly??B0($.kind),isConcurrencySafe:$.isConcurrencySafe??!0,strict:$.strict??!1,description:$.description,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],getFunctionDeclaration(){let b=q1($.schema),w=$.description.short;if($.description.long)w+=`
1
+ import{createRequire as S8}from"node:module";var L8=Object.create;var{getPrototypeOf:E8,defineProperty:lw,getOwnPropertyNames:j8}=Object;var N8=Object.prototype.hasOwnProperty;var I$=($,b,w)=>{w=$!=null?L8(E8($)):{};let W=b||!$||!$.__esModule?lw(w,"default",{value:$,enumerable:!0}):w;for(let V of j8($))if(!N8.call(W,V))lw(W,V,{get:()=>$[V],enumerable:!0});return W};var S$=S8(import.meta.url);import*as o2 from"os";import*as t2 from"path";import{appendFileSync as y8,existsSync as M8,mkdirSync as z8,readdirSync as v8,statSync as rw,unlinkSync as T8}from"node:fs";import k8 from"node:os";import V1 from"node:path";var Q1;((V)=>{V[V.DEBUG=0]="DEBUG";V[V.INFO=1]="INFO";V[V.WARN=2]="WARN";V[V.ERROR=3]="ERROR"})(Q1||={});var x;((B)=>{B.AGENT="Agent";B.UI="UI";B.TOOL="Tool";B.SERVICE="Service";B.CONFIG="Config";B.CONTEXT="Context";B.EXECUTION="Execution";B.LOOP="Loop";B.CHAT="Chat";B.GENERAL="General";B.PROMPTS="Prompts";B.SPEC="Spec"})(x||={});var W1=null,nw=null,sw=!1;function mV($){if(W1!==$)W1=$}async function cV(){}function f8(){if(sw)return nw;sw=!0;try{let $=V1.join(k8.homedir(),".blade","logs");if(!M8($))z8($,{recursive:!0,mode:493});if(rw($).uid===0&&process.getuid&&process.getuid()!==0)return console.error(""),console.error("❌ 权限错误:~/.blade/logs 目录属于 root 用户"),console.error(""),console.error("这通常是因为您曾经使用 sudo 运行过 blade。"),console.error(""),console.error("解决方法:"),console.error(" sudo chown -R $USER:$USER ~/.blade/"),console.error(""),console.error("然后重新运行 blade(不要使用 sudo)"),console.error(""),null;return I8($,30),nw=$,$}catch($){return console.error("[Logger] 无法创建日志目录:",$),null}}function I8($,b){try{let w=v8($),W=Date.now(),V=b*24*60*60*1000;for(let Q of w){if(!Q.startsWith("blade-")||!Q.endsWith(".log")&&!Q.endsWith(".jsonl"))continue;let Z=V1.join($,Q);try{let J=rw(Z);if(W-J.mtimeMs>V)T8(Z)}catch(J){}}}catch(w){}}function P8(){let $=f8();if(!$)return null;let b=W1||"default";return V1.join($,`blade-${b}.jsonl`)}function h8($,b,w){let W=P8();if(!W)return;try{let V={timestamp:new Date().toISOString(),level:Q1[b],category:$,message:w};y8(W,JSON.stringify(V)+`
2
+ `)}catch(V){}}class P${static globalDebugConfig=null;enabled;minLevel;category;constructor($={}){if($.enabled!==void 0)this.enabled=$.enabled;else if(P$.globalDebugConfig!==null)this.enabled=Boolean(P$.globalDebugConfig);else this.enabled=!1;this.minLevel=$.minLevel??0,this.category=$.category??"General"}static setGlobalDebug($){P$.globalDebugConfig=$}static clearGlobalDebug(){P$.globalDebugConfig=null}setEnabled($){this.enabled=$}parseDebugFilter($){if(!$)return{enabled:!1};if($===!0||$==="true"||$==="1")return{enabled:!0};let b=String($).trim();if(!b)return{enabled:!0};if(b.startsWith("!"))return{enabled:!0,filter:{mode:"exclude",categories:b.split(",").map((V)=>V.trim().replace(/^!/,"")).filter(Boolean)}};return{enabled:!0,filter:{mode:"include",categories:b.split(",").map((W)=>W.trim()).filter(Boolean)}}}shouldLogCategory($){if(!$)return!0;let b=this.category.toLowerCase();if($.mode==="include")return $.categories.some((w)=>b.includes(w.toLowerCase()));return!$.categories.some((w)=>b.includes(w.toLowerCase()))}shouldLogToConsole($){if(P$.globalDebugConfig!==null){let{enabled:b,filter:w}=this.parseDebugFilter(P$.globalDebugConfig);if(!b)return!1;if($<this.minLevel)return!1;return this.shouldLogCategory(w)}return this.enabled&&$>=this.minLevel}log($,...b){let w=b.map((W)=>typeof W==="object"?JSON.stringify(W):String(W)).join(" ");if(h8(this.category,$,w),this.shouldLogToConsole($)){let W=Q1[$],V=`[${this.category}] [${W}]`;console.error(V,...b)}}debug(...$){this.log(0,...$)}info(...$){this.log(1,...$)}warn(...$){this.log(2,...$)}error(...$){this.log(3,...$)}}function E($,b){return new P$({...b,category:$})}var I=new P$({category:"General"});import{EventEmitter as $W}from"events";function _($){if($ instanceof Error)return $.message;if(typeof $==="string")return $;return String($)}function d($){if($ instanceof Error)return $.name;return"Error"}function I0($){if($ instanceof Error)return $;return Error(_($))}function x8($){return"code"in $&&typeof $.code==="string"}function p8($){return $ instanceof Error&&x8($)}function n($){if(p8($))return $.code;return}import{z as b$}from"zod";function nV($){return $!==void 0&&typeof $.pattern==="string"&&typeof $.search_path==="string"}function sV($){return $!==void 0&&$.kind==="edit"&&typeof $.matches_found==="number"}function F0($){return $==="readonly"}import{isPlainObject as d8}from"lodash-es";class Z1{toolName;params;context;aborted=!1;result;_internal={};constructor($,b,w){this.toolName=$;this.params=b;this.context=w}shouldAbort(){return this.aborted||(this.context.signal?.aborted??!1)}abort($,b){this.aborted=!0,this.result={success:!1,llmContent:`Tool execution aborted: ${$||"Unknown reason"}`,displayContent:`执行已中止: ${$||"未知原因"}`,error:{type:"execution_error",message:$||"Execution aborted"},metadata:b?.shouldExitLoop?{shouldExitLoop:!0}:void 0}}setResult($){this.result=$}getResult(){if(!this.result)throw Error("Tool execution result not set");return this.result}}function P0($){if($===void 0)return"undefined";if(typeof $==="string")return $;try{let b=JSON.stringify($);return b===void 0?String($):b}catch{return String($)}}class aw extends Error{issues;type;constructor($,b,w="validation_error"){super($);this.issues=b;this.type=w;this.name="ToolValidationError"}}function u8($){let{code:b}=$,w=$,W=w.received;switch(b){case"invalid_type":{let V=w.expected;return`类型错误:期望 ${P0(V)},实际收到 ${P0(W)}`}case"too_small":{let{minimum:V,inclusive:Q}=w,Z=typeof w.type==="string"?w.type:void 0;if(Z==="string"&&typeof V==="number")return`长度不能少于 ${V} 个字符`;if(Z==="number"&&typeof V==="number")return`不能小于${Q?"等于":""} ${V}`;if(Z==="array"&&typeof V==="number")return`数组长度不能少于 ${V}`;return"值太小"}case"too_big":{let{maximum:V,inclusive:Q}=w,Z=typeof w.type==="string"?w.type:void 0;if(Z==="string"&&typeof V==="number")return`长度不能超过 ${V} 个字符`;if(Z==="number"&&typeof V==="number")return`不能大于${Q?"等于":""} ${V}`;if(Z==="array"&&typeof V==="number")return`数组长度不能超过 ${V}`;return"值太大"}case"invalid_string":{let V=w.validation;if(V==="email")return"必须是有效的电子邮件地址";if(V==="url")return"必须是有效的 URL";if(V==="uuid")return"必须是有效的 UUID";if(d8(V)){let Q=V;if(typeof Q.includes==="string")return`必须包含 "${Q.includes}"`;if(typeof Q.startsWith==="string")return`必须以 "${Q.startsWith}" 开头`;if(typeof Q.endsWith==="string")return`必须以 "${Q.endsWith}" 结尾`}return"字符串格式不正确"}case"invalid_enum_value":{let V=w.options;if(Array.isArray(V))return`必须是以下值之一:${V.map((Q)=>P0(Q)).join(", ")}`;return"必须是枚举允许的值之一"}case"invalid_literal":{let V=w.expected;return`必须是字面量值:${P0(V)}`}case"unrecognized_keys":{let V=w.keys;if(Array.isArray(V))return`包含未知的参数:${V.map((Q)=>P0(Q)).join(", ")}`;return"包含未知的参数"}case"invalid_union":return"不符合任何有效的类型定义";case"invalid_date":return"必须是有效的日期";case"custom":return $.message||"自定义验证失败";default:return $.message||"验证失败"}}function g8($){let b=$.issues.map((W)=>{let V=W.path.join("."),Q=u8(W),Z=W.received;return{field:V||"root",message:Q,value:Z}}),w=b.length===1?`参数验证失败 [${b[0].field}]: ${b[0].message}`:`参数验证失败 (${b.length} 个错误):
3
+ ${b.map((W)=>` - ${W.field}: ${W.message}`).join(`
4
+ `)}`;return new aw(w,b)}function ow($,b){let w=$.safeParse(b);if(!w.success)throw g8(w.error);return w.data}import{zodToJsonSchema as m8}from"zod-to-json-schema";function J1($){return m8($,{target:"jsonSchema7",$refStrategy:"none"})}class Gb{toolName;params;executeFn;descriptionFn;affectedPathsFn;constructor($,b,w,W,V){this.toolName=$;this.params=b;this.executeFn=w;this.descriptionFn=W;this.affectedPathsFn=V}getDescription(){if(this.descriptionFn)return this.descriptionFn(this.params);return`执行工具: ${this.toolName}`}getAffectedPaths(){if(this.affectedPathsFn)return this.affectedPathsFn(this.params);return[]}async execute($,b,w){let W={signal:$,updateOutput:b,...w};return this.executeFn(this.params,W)}}function L($){return{name:$.name,displayName:$.displayName,kind:$.kind,isReadOnly:$.isReadOnly??F0($.kind),isConcurrencySafe:$.isConcurrencySafe??!0,strict:$.strict??!1,description:$.description,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],getFunctionDeclaration(){let b=J1($.schema),w=$.description.short;if($.description.long)w+=`
121
5
 
122
6
  ${$.description.long}`;if($.description.usageNotes&&$.description.usageNotes.length>0)w+=`
123
7
 
124
8
  Usage Notes:
125
- ${$.description.usageNotes.map((V)=>`- ${V}`).join(`
9
+ ${$.description.usageNotes.map((W)=>`- ${W}`).join(`
126
10
  `)}`;if($.description.important&&$.description.important.length>0)w+=`
127
11
 
128
12
  Important:
129
- ${$.description.important.map((V)=>`⚠️ ${V}`).join(`
130
- `)}`;return{name:$.name,description:w,parameters:b}},getMetadata(){return{name:$.name,displayName:$.displayName,kind:$.kind,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],description:$.description,schema:q1($.schema)}},build(b){let w=sw($.schema,b);return new Jb($.name,w,$.execute)},async execute(b,w){return this.build(b).execute(w||new AbortController().signal)},extractSignatureContent:$.extractSignatureContent?(b)=>$.extractSignatureContent(b):void 0,abstractPermissionRule:$.abstractPermissionRule?(b)=>$.abstractPermissionRule(b):void 0}}function S5($){let b=typeof $.description==="string"?{short:$.description}:$.description;return{name:$.name,displayName:$.displayName||$.name,kind:$.kind||"execute",isReadOnly:$.kind?B0($.kind):!1,isConcurrencySafe:!0,strict:!1,description:b,version:"1.0.0",tags:[],getFunctionDeclaration(){let w=b.short;if(b.long)w+=`
13
+ ${$.description.important.map((W)=>`⚠️ ${W}`).join(`
14
+ `)}`;return{name:$.name,description:w,parameters:b}},getMetadata(){return{name:$.name,displayName:$.displayName,kind:$.kind,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],description:$.description,schema:J1($.schema)}},build(b){let w=ow($.schema,b);return new Gb($.name,w,$.execute)},async execute(b,w){return this.build(b).execute(w||new AbortController().signal)},extractSignatureContent:$.extractSignatureContent?(b)=>$.extractSignatureContent(b):void 0,abstractPermissionRule:$.abstractPermissionRule?(b)=>$.abstractPermissionRule(b):void 0}}function c8($){let b=typeof $.description==="string"?{short:$.description}:$.description;return{name:$.name,displayName:$.displayName||$.name,kind:$.kind||"execute",isReadOnly:$.kind?F0($.kind):!1,isConcurrencySafe:!0,strict:!1,description:b,version:"1.0.0",tags:[],getFunctionDeclaration(){let w=b.short;if(b.long)w+=`
131
15
 
132
16
  ${b.long}`;if(b.usageNotes&&b.usageNotes.length>0)w+=`
133
17
 
134
18
  Usage Notes:
135
- ${b.usageNotes.map((V)=>`- ${V}`).join(`
19
+ ${b.usageNotes.map((W)=>`- ${W}`).join(`
136
20
  `)}`;if(b.important&&b.important.length>0)w+=`
137
21
 
138
22
  Important:
139
- ${b.important.map((V)=>`⚠️ ${V}`).join(`
140
- `)}`;return{name:$.name,description:w,parameters:$.parameters}},getMetadata(){return{name:$.name,displayName:$.displayName||$.name,kind:$.kind||"execute",version:"1.0.0",description:b,schema:$.parameters}},build(w){return new Jb($.name,w,async(V,W)=>$.execute(V,W))},async execute(w,V){let W={signal:V};return $.execute(w,W)}}}function M5($){return $}function I0($,b,w,V){let W;try{W=f0(w.inputSchema)}catch(Z){console.warn(`[createMcpTool] Schema 转换失败,使用降级 schema: ${w.name}`,Z),W=B$.any()}let Q=V||w.name;return E({name:Q,displayName:`${b}: ${w.name}`,kind:"execute",schema:W,description:{short:w.description||`MCP Tool: ${w.name}`,important:[`From MCP server: ${b}`,"Executes external tools; user confirmation required"]},category:"MCP tool",tags:["mcp","external",b],async execute(Z,Y){try{let J=await $.callTool(w.name,Z),X="",O="";if(J.content&&Array.isArray(J.content)){for(let G of J.content)if(G.type==="text"&&G.text)X+=G.text,O+=G.text;else if(G.type==="image")O+=`[图片: ${G.mimeType||"unknown"}]
23
+ ${b.important.map((W)=>`⚠️ ${W}`).join(`
24
+ `)}`;return{name:$.name,description:w,parameters:$.parameters}},getMetadata(){return{name:$.name,displayName:$.displayName||$.name,kind:$.kind||"execute",version:"1.0.0",description:b,schema:$.parameters}},build(w){return new Gb($.name,w,(W,V)=>$.execute(W,V))},async execute(w,W){let V={signal:W};return $.execute(w,V)}}}function i8($){return $}function x0($,b,w,W){let V;try{V=h0(w.inputSchema)}catch(Z){console.warn(`[createMcpTool] Schema 转换失败,使用降级 schema: ${w.name}`,Z),V=b$.record(b$.string(),b$.unknown())}let Q=W||w.name;return L({name:Q,displayName:`${b}: ${w.name}`,kind:"execute",schema:V,description:{short:w.description||`MCP Tool: ${w.name}`,important:[`From MCP server: ${b}`,"Executes external tools; user confirmation required"]},category:"MCP tool",tags:["mcp","external",b],async execute(Z,J){try{let Y=await $.callTool(w.name,Z),X="",O="";if(Y.content&&Array.isArray(Y.content)){for(let G of Y.content)if(G.type==="text"&&G.text)X+=G.text,O+=G.text;else if(G.type==="image")O+=`[图片: ${G.mimeType||"unknown"}]
141
25
  `,X+=`[image: ${G.mimeType||"unknown"}]
142
26
  `;else if(G.type==="resource")O+=`[资源: ${G.mimeType||"unknown"}]
143
27
  `,X+=`[resource: ${G.mimeType||"unknown"}]
144
- `}if(J.isError)return{success:!1,llmContent:X||"MCP tool execution failed",displayContent:`❌ ${O||"MCP工具执行失败"}`,error:{type:"execution_error",message:X||"MCP tool execution failed"}};return{success:!0,llmContent:X||"Execution succeeded",displayContent:`✅ MCP工具 ${w.name} 执行成功
145
- ${O}`,metadata:{serverName:b,toolName:w.name,mcpResult:J}}}catch(J){return{success:!1,llmContent:`MCP tool execution failed: ${J.message}`,displayContent:`❌ ${J.message}`,error:{type:"execution_error",message:J.message}}}}})}function f0($){if($.type==="object"||$.properties){let b={},w=$.required||[];if($.properties){for(let[V,W]of Object.entries($.properties))if(typeof W==="object"&&W!==null){let Q=f0(W);if(!w.includes(V))Q=Q.optional();b[V]=Q}}return B$.object(b)}if($.type==="array"&&$.items){if(typeof $.items==="object"&&!Array.isArray($.items)&&$.items!==null)return B$.array(f0($.items));return B$.array(B$.any())}if($.type==="string"){let b=B$.string();if($.minLength!==void 0)b=b.min($.minLength);if($.maxLength!==void 0)b=b.max($.maxLength);if($.pattern)b=b.regex(new RegExp($.pattern));if($.enum)return B$.enum($.enum);return b}if($.type==="number"||$.type==="integer"){let b=B$.number();if($.minimum!==void 0)b=b.min($.minimum);if($.maximum!==void 0)b=b.max($.maximum);return b}if($.type==="boolean")return B$.boolean();if($.oneOf&&$.oneOf.length>0){let b=$.oneOf.filter((w)=>typeof w==="object"&&w!==null).map((w)=>f0(w));if(b.length>=2)return B$.union(b)}if($.anyOf&&$.anyOf.length>0){let b=$.anyOf.filter((w)=>typeof w==="object"&&w!==null).map((w)=>f0(w));if(b.length>=2)return B$.union(b)}return B$.any()}import{Client as k5}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as f5}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as I5}from"@modelcontextprotocol/sdk/client/stdio.js";import{EventEmitter as P5}from"events";var A1={name:"@blade-ai/agent-sdk",version:"0.1.8",private:!1,description:"Blade AI Agent SDK",type:"module",main:"./dist/index.js",types:"./dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"}},files:["dist","vendor/ripgrep/**","README.md","CHANGELOG.md"],scripts:{build:"bun run scripts/build.ts",test:"bun test",lint:"biome lint src","lint:fix":"biome lint --write src","type-check":"bun x tsc --noEmit",release:"bun run scripts/release.js","release:dry":"bun run scripts/release.js --dry-run","release:major":"bun run scripts/release.js --major","release:minor":"bun run scripts/release.js --minor","release:patch":"bun run scripts/release.js --patch"},keywords:["sdk","blade","ai","assistant","agent","llm","bun"],author:"echoVic",license:"MIT",optionalDependencies:{"@vscode/ripgrep":"^1.17.0","bun-pty":"^0.4.8","node-pty":"1.0.0"},dependencies:{"@agentclientprotocol/sdk":"^0.12.0","@ai-sdk/anthropic":"^3.0.7","@ai-sdk/azure":"^3.0.5","@ai-sdk/deepseek":"^2.0.4","@ai-sdk/google":"^3.0.4","@ai-sdk/openai-compatible":"^2.0.4","@modelcontextprotocol/sdk":"^1.17.4",ai:"^6.0.39","async-mutex":"^0.5.0",axios:"^1.12.2",chalk:"^5.4.1",diff:"^8.0.2","fast-glob":"^3.3.3","fuse.js":"^7.1.0","gray-matter":"^4.0.3",hono:"^4.7.10","js-tiktoken":"^1.0.21","lodash-es":"^4.17.21","lru-cache":"^11.2.4",nanoid:"^5.1.6",open:"^10.1.2",openai:"^6.2.0",picomatch:"^4.0.3",semver:"^7.7.3",undici:"^7.16.0","write-file-atomic":"^7.0.0",ws:"^8.18.0",yaml:"^2.8.1",zod:"^3.24.2","zod-to-json-schema":"^3.24.6",zustand:"^5.0.9"},devDependencies:{"@biomejs/biome":"^2.2.4","@types/json-schema":"^7.0.15","@types/lodash-es":"^4.17.12","@types/picomatch":"^4.0.2","@types/semver":"^7.7.1","@types/write-file-atomic":"^4.0.3","@types/ws":"^8.5.12","bun-types":"latest",typescript:"^5.9.2"}};function rw(){return A1.version}function aw(){return A1.name}import{spawn as v5}from"child_process";import*as h0 from"crypto";import*as ew from"http";import{URL as ow}from"url";import{promises as U1}from"fs";import z5 from"os";import C1 from"path";class F1{tokenFilePath;constructor(){let $=z5.homedir(),b=C1.join($,".blade");this.tokenFilePath=C1.join(b,"mcp-oauth-tokens.json")}async ensureConfigDir(){let $=C1.dirname(this.tokenFilePath);try{await U1.mkdir($,{recursive:!0,mode:493})}catch{}}async loadAllCredentials(){let $=new Map;try{let b=await U1.readFile(this.tokenFilePath,"utf-8"),w=JSON.parse(b);for(let V of w)$.set(V.serverName,V)}catch(b){if(b.code!=="ENOENT")console.warn("[OAuthTokenStorage] 加载令牌失败:",b)}return $}async saveAllCredentials($){await this.ensureConfigDir();let b=Array.from($.values());await U1.writeFile(this.tokenFilePath,JSON.stringify(b,null,2),{mode:384})}async saveToken($,b,w,V){let W=await this.loadAllCredentials(),Q={serverName:$,token:b,clientId:w,tokenUrl:V,updatedAt:Date.now()};W.set($,Q),await this.saveAllCredentials(W)}async getCredentials($){return(await this.loadAllCredentials()).get($)||null}async deleteCredentials($){let b=await this.loadAllCredentials();b.delete($),await this.saveAllCredentials(b)}async listServers(){let $=await this.loadAllCredentials();return Array.from($.keys())}isTokenExpired($){if(!$.expiresAt)return!1;let b=300000;return Date.now()>=$.expiresAt-b}}var P0=7777,H1="/oauth/callback",tw=200;class Xb{tokenStorage;constructor($=new F1){this.tokenStorage=$}generatePKCEParams(){let $=h0.randomBytes(32).toString("base64url"),b=h0.createHash("sha256").update($).digest("base64url"),w=h0.randomBytes(16).toString("base64url");return{codeVerifier:$,codeChallenge:b,state:w}}buildAuthorizationUrl($,b){let w=$.redirectUri||`http://localhost:${P0}${H1}`,V=new URLSearchParams({client_id:$.clientId,response_type:"code",redirect_uri:w,state:b.state,code_challenge:b.codeChallenge,code_challenge_method:"S256"});if($.scopes&&$.scopes.length>0)V.append("scope",$.scopes.join(" "));let W=new ow($.authorizationUrl);return V.forEach((Q,Z)=>{W.searchParams.append(Z,Q)}),W.toString()}async startCallbackServer($){return new Promise((b,w)=>{let V=ew.createServer((W,Q)=>{try{let Z=new ow(W.url,`http://localhost:${P0}`);if(Z.pathname!==H1){Q.writeHead(404),Q.end("Not found");return}let Y=Z.searchParams.get("code"),J=Z.searchParams.get("state"),X=Z.searchParams.get("error");if(X){Q.writeHead(tw,{"Content-Type":"text/html"}),Q.end(`
28
+ `}if(Y.isError)return{success:!1,llmContent:X||"MCP tool execution failed",displayContent:`❌ ${O||"MCP工具执行失败"}`,error:{type:"execution_error",message:X||"MCP tool execution failed"}};return{success:!0,llmContent:X||"Execution succeeded",displayContent:`✅ MCP工具 ${w.name} 执行成功
29
+ ${O}`,metadata:{serverName:b,toolName:w.name,mcpResult:Y}}}catch(Y){return{success:!1,llmContent:`MCP tool execution failed: ${_(Y)}`,displayContent:`❌ ${_(Y)}`,error:{type:"execution_error",message:_(Y)}}}}})}function h0($){if($.type==="object"||$.properties){let b={},w=$.required||[];if($.properties){for(let[W,V]of Object.entries($.properties))if(typeof V==="object"&&V!==null){let Q=h0(V);if(!w.includes(W))Q=Q.optional();b[W]=Q}}return b$.object(b)}if($.type==="array"&&$.items){if(typeof $.items==="object"&&!Array.isArray($.items)&&$.items!==null)return b$.array(h0($.items));return b$.array(b$.unknown())}if($.type==="string"){let b=b$.string();if($.minLength!==void 0)b=b.min($.minLength);if($.maxLength!==void 0)b=b.max($.maxLength);if($.pattern)b=b.regex(new RegExp($.pattern));if($.enum)return b$.enum($.enum);return b}if($.type==="number"||$.type==="integer"){let b=b$.number();if($.minimum!==void 0)b=b.min($.minimum);if($.maximum!==void 0)b=b.max($.maximum);return b}if($.type==="boolean")return b$.boolean();if($.oneOf&&$.oneOf.length>0){let b=$.oneOf.filter((w)=>typeof w==="object"&&w!==null).map((w)=>h0(w));if(b.length>=2)return b$.union(b)}if($.anyOf&&$.anyOf.length>0){let b=$.anyOf.filter((w)=>typeof w==="object"&&w!==null).map((w)=>h0(w));if(b.length>=2)return b$.union(b)}return b$.unknown()}import{Client as a8}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as o8}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as t8}from"@modelcontextprotocol/sdk/client/stdio.js";import{EventEmitter as e8}from"events";var Y1={name:"@blade-ai/agent-sdk",version:"0.1.11",private:!1,description:"Blade AI Agent SDK",type:"module",main:"./dist/index.js",types:"./dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"}},files:["dist","vendor/ripgrep/**","README.md","CHANGELOG.md"],scripts:{build:"bun run scripts/build.ts",test:"bun test",lint:"biome lint src","lint:fix":"biome lint --write src","type-check":"bun x tsc --noEmit",release:"bun run scripts/release.js","release:dry":"bun run scripts/release.js --dry-run","release:major":"bun run scripts/release.js --major","release:minor":"bun run scripts/release.js --minor","release:patch":"bun run scripts/release.js --patch"},keywords:["sdk","blade","ai","assistant","agent","llm","bun"],author:"echoVic",license:"MIT",optionalDependencies:{"@ai-sdk/anthropic":"^3.0.7","@ai-sdk/azure":"^3.0.5","@ai-sdk/deepseek":"^2.0.4","@ai-sdk/google":"^3.0.4","@vscode/ripgrep":"^1.17.0","bun-pty":"^0.4.8","node-pty":"1.0.0"},dependencies:{"@agentclientprotocol/sdk":"^0.12.0","@ai-sdk/openai-compatible":"^2.0.4","@modelcontextprotocol/sdk":"^1.17.4",ai:"^6.0.39","async-mutex":"^0.5.0",axios:"^1.12.2",chalk:"^5.4.1",diff:"^8.0.2","fast-glob":"^3.3.3","fuse.js":"^7.1.0","gray-matter":"^4.0.3",hono:"^4.7.10","js-tiktoken":"^1.0.21","lodash-es":"^4.17.21","lru-cache":"^11.2.4",nanoid:"^5.1.6",open:"^10.1.2",picomatch:"^4.0.3",semver:"^7.7.3",undici:"^7.16.0","write-file-atomic":"^7.0.0",ws:"^8.18.0",yaml:"^2.8.1",zod:"^3.24.2","zod-to-json-schema":"^3.24.6",zustand:"^5.0.9"},devDependencies:{"@biomejs/biome":"^2.2.4","@types/json-schema":"^7.0.15","@types/lodash-es":"^4.17.12","@types/picomatch":"^4.0.2","@types/semver":"^7.7.1","@types/write-file-atomic":"^4.0.3","@types/ws":"^8.5.12","bun-types":"latest",typescript:"^5.9.2"}};function tw(){return Y1.version}function ew(){return Y1.name}import{spawn as s8}from"child_process";import*as d0 from"crypto";import*as w4 from"http";import{URL as $4}from"url";import{promises as X1}from"fs";import n8 from"os";import O1 from"path";class G1{tokenFilePath;constructor(){let $=n8.homedir(),b=O1.join($,".blade");this.tokenFilePath=O1.join(b,"mcp-oauth-tokens.json")}async ensureConfigDir(){let $=O1.dirname(this.tokenFilePath);try{await X1.mkdir($,{recursive:!0,mode:493})}catch{}}async loadAllCredentials(){let $=new Map;try{let b=await X1.readFile(this.tokenFilePath,"utf-8"),w=JSON.parse(b);for(let W of w)$.set(W.serverName,W)}catch(b){if(n(b)!=="ENOENT")console.warn("[OAuthTokenStorage] 加载令牌失败:",b)}return $}async saveAllCredentials($){await this.ensureConfigDir();let b=Array.from($.values());await X1.writeFile(this.tokenFilePath,JSON.stringify(b,null,2),{mode:384})}async saveToken($,b,w,W){let V=await this.loadAllCredentials(),Q={serverName:$,token:b,clientId:w,tokenUrl:W,updatedAt:Date.now()};V.set($,Q),await this.saveAllCredentials(V)}async getCredentials($){return(await this.loadAllCredentials()).get($)||null}async deleteCredentials($){let b=await this.loadAllCredentials();b.delete($),await this.saveAllCredentials(b)}async listServers(){let $=await this.loadAllCredentials();return Array.from($.keys())}isTokenExpired($){if(!$.expiresAt)return!1;let b=300000;return Date.now()>=$.expiresAt-b}}var p0=7777,B1="/oauth/callback",b4=200;class Bb{tokenStorage;constructor($=new G1){this.tokenStorage=$}generatePKCEParams(){let $=d0.randomBytes(32).toString("base64url"),b=d0.createHash("sha256").update($).digest("base64url"),w=d0.randomBytes(16).toString("base64url");return{codeVerifier:$,codeChallenge:b,state:w}}buildAuthorizationUrl($,b){let w=$.redirectUri||`http://localhost:${p0}${B1}`,W=new URLSearchParams({client_id:$.clientId,response_type:"code",redirect_uri:w,state:b.state,code_challenge:b.codeChallenge,code_challenge_method:"S256"});if($.scopes&&$.scopes.length>0)W.append("scope",$.scopes.join(" "));let V=new $4($.authorizationUrl);return W.forEach((Q,Z)=>{V.searchParams.append(Z,Q)}),V.toString()}async startCallbackServer($){return new Promise((b,w)=>{let W=w4.createServer((V,Q)=>{try{let Z=new $4(V.url,`http://localhost:${p0}`);if(Z.pathname!==B1){Q.writeHead(404),Q.end("Not found");return}let J=Z.searchParams.get("code"),Y=Z.searchParams.get("state"),X=Z.searchParams.get("error");if(X){Q.writeHead(b4,{"Content-Type":"text/html"}),Q.end(`
146
30
  <html>
147
31
  <body>
148
32
  <h1>Authentication Failed</h1>
@@ -150,7 +34,7 @@ ${O}`,metadata:{serverName:b,toolName:w.name,mcpResult:J}}}catch(J){return{succe
150
34
  <p>You can close this window.</p>
151
35
  </body>
152
36
  </html>
153
- `),V.close(),w(Error(`OAuth error: ${X}`));return}if(!Y||!J){Q.writeHead(400),Q.end("Missing code or state parameter");return}if(J!==$){Q.writeHead(400),Q.end("Invalid state parameter"),V.close(),w(Error("State mismatch - possible CSRF attack"));return}Q.writeHead(tw,{"Content-Type":"text/html"}),Q.end(`
37
+ `),W.close(),w(Error(`OAuth error: ${X}`));return}if(!J||!Y){Q.writeHead(400),Q.end("Missing code or state parameter");return}if(Y!==$){Q.writeHead(400),Q.end("Invalid state parameter"),W.close(),w(Error("State mismatch - possible CSRF attack"));return}Q.writeHead(b4,{"Content-Type":"text/html"}),Q.end(`
154
38
  <html>
155
39
  <body>
156
40
  <h1>Authentication Successful!</h1>
@@ -158,9 +42,9 @@ ${O}`,metadata:{serverName:b,toolName:w.name,mcpResult:J}}}catch(J){return{succe
158
42
  <script>window.close();</script>
159
43
  </body>
160
44
  </html>
161
- `),V.close(),b(Y)}catch(Z){V.close(),w(Z)}});V.on("error",w),V.listen(P0,()=>{console.log(`[OAuth] Callback server listening on port ${P0}`)}),setTimeout(()=>{V.close(),w(Error("OAuth callback timeout"))},300000)})}async exchangeCodeForToken($,b,w){let V=$.redirectUri||`http://localhost:${P0}${H1}`,W=new URLSearchParams({grant_type:"authorization_code",code:b,redirect_uri:V,code_verifier:w,client_id:$.clientId});if($.clientSecret)W.append("client_secret",$.clientSecret);let Q=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:W.toString()});if(!Q.ok){let Z=await Q.text();throw Error(`Token exchange failed: ${Q.status} - ${Z}`)}return await Q.json()}async refreshAccessToken($,b){let w=new URLSearchParams({grant_type:"refresh_token",refresh_token:b,client_id:$.clientId});if($.clientSecret)w.append("client_secret",$.clientSecret);if($.scopes&&$.scopes.length>0)w.append("scope",$.scopes.join(" "));let V=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:w.toString()});if(!V.ok){let W=await V.text();throw Error(`Token refresh failed: ${V.status} - ${W}`)}return await V.json()}async authenticate($,b){if(!b.clientId||!b.authorizationUrl||!b.tokenUrl)throw Error("Missing required OAuth configuration");let w=this.generatePKCEParams(),V=this.buildAuthorizationUrl(b,w);console.log(`
45
+ `),W.close(),b(J)}catch(Z){W.close(),w(Z)}});W.on("error",w),W.listen(p0,()=>{console.log(`[OAuth] Callback server listening on port ${p0}`)}),setTimeout(()=>{W.close(),w(Error("OAuth callback timeout"))},300000)})}async exchangeCodeForToken($,b,w){let W=$.redirectUri||`http://localhost:${p0}${B1}`,V=new URLSearchParams({grant_type:"authorization_code",code:b,redirect_uri:W,code_verifier:w,client_id:$.clientId});if($.clientSecret)V.append("client_secret",$.clientSecret);let Q=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:V.toString()});if(!Q.ok){let Z=await Q.text();throw Error(`Token exchange failed: ${Q.status} - ${Z}`)}return await Q.json()}async refreshAccessToken($,b){let w=new URLSearchParams({grant_type:"refresh_token",refresh_token:b,client_id:$.clientId});if($.clientSecret)w.append("client_secret",$.clientSecret);if($.scopes&&$.scopes.length>0)w.append("scope",$.scopes.join(" "));let W=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:w.toString()});if(!W.ok){let V=await W.text();throw Error(`Token refresh failed: ${W.status} - ${V}`)}return await W.json()}async authenticate($,b){if(!b.clientId||!b.authorizationUrl||!b.tokenUrl)throw Error("Missing required OAuth configuration");let w=this.generatePKCEParams(),W=this.buildAuthorizationUrl(b,w);console.log(`
162
46
  [OAuth] Opening browser for authentication...`),console.log(`
163
- If the browser does not open automatically, copy and paste this URL:`),console.log(V),console.log("");let W=this.startCallbackServer(w.state);try{await this.openAuthorizationUrl(V)}catch(J){console.warn("[OAuth] Failed to open browser automatically:",J)}let Q=await W;console.log("[OAuth] Authorization code received, exchanging for tokens...");let Z=await this.exchangeCodeForToken(b,Q,w.codeVerifier),Y={accessToken:Z.access_token,tokenType:Z.token_type||"Bearer",refreshToken:Z.refresh_token,scope:Z.scope};if(Z.expires_in)Y.expiresAt=Date.now()+Z.expires_in*1000;return await this.tokenStorage.saveToken($,Y,b.clientId,b.tokenUrl),console.log("[OAuth] Authentication successful! Token saved."),Y}async openAuthorizationUrl($){let{command:b,args:w}=this.getBrowserCommand($);await new Promise((V,W)=>{let Q=v5(b,w,{stdio:"ignore"});Q.once("error",W),Q.once("close",(Z)=>{if(Z===0||Z===null)V();else W(Error(`Failed to open browser (exit code ${Z})`))})})}getBrowserCommand($){if(process.platform==="darwin")return{command:"open",args:[$]};if(process.platform==="win32")return{command:"cmd",args:["/c","start","",$]};return{command:"xdg-open",args:[$]}}async getValidToken($,b){let w=await this.tokenStorage.getCredentials($);if(!w)return null;let{token:V}=w;if(!this.tokenStorage.isTokenExpired(V))return V.accessToken;if(V.refreshToken&&b.clientId&&w.tokenUrl)try{console.log(`[OAuth] Refreshing expired token for server: ${$}`);let W=await this.refreshAccessToken(b,V.refreshToken),Q={accessToken:W.access_token,tokenType:W.token_type,refreshToken:W.refresh_token||V.refreshToken,scope:W.scope||V.scope};if(W.expires_in)Q.expiresAt=Date.now()+W.expires_in*1000;return await this.tokenStorage.saveToken($,Q,b.clientId,w.tokenUrl),Q.accessToken}catch(W){console.error("[OAuth] Failed to refresh token:",W),await this.tokenStorage.deleteCredentials($)}return null}}import{EventEmitter as T5}from"events";var r$;((W)=>{W.DISCONNECTED="disconnected";W.CONNECTING="connecting";W.CONNECTED="connected";W.ERROR="error"})(r$||={});var _1;((W)=>{W.HEALTHY="healthy";W.DEGRADED="degraded";W.UNHEALTHY="unhealthy";W.CHECKING="checking"})(_1||={});class x0 extends T5{client;config;checkTimer=null;isChecking=!1;consecutiveFailures=0;lastCheckTime=0;currentStatus="healthy";constructor($,b={}){super();this.client=$,this.config={interval:b.interval??30000,timeout:b.timeout??1e4,enabled:b.enabled??!1,failureThreshold:b.failureThreshold??3}}start(){if(this.checkTimer){console.warn("[HealthMonitor] 健康监控已在运行");return}if(!this.config.enabled){console.log("[HealthMonitor] 健康监控未启用");return}console.log(`[HealthMonitor] 启动健康监控(间隔: ${this.config.interval}ms)`),this.scheduleNextCheck()}stop(){if(this.checkTimer)clearTimeout(this.checkTimer),this.checkTimer=null,console.log("[HealthMonitor] 停止健康监控")}scheduleNextCheck(){this.checkTimer=setTimeout(async()=>{await this.performHealthCheck(),this.scheduleNextCheck()},this.config.interval)}async performHealthCheck(){if(this.isChecking)return console.warn("[HealthMonitor] 上一次检查仍在进行中"),this.getLastResult();this.isChecking=!0,this.lastCheckTime=Date.now(),this.setStatus("checking");try{let $=this.client.connectionStatus;if($==="connected"){await this.pingServer(),this.consecutiveFailures=0,this.setStatus("healthy");let b={status:"healthy",timestamp:Date.now(),consecutiveFailures:0};return this.emit("healthCheck",b),b}else throw Error(`连接状态异常: ${$}`)}catch($){this.consecutiveFailures++;let b=$;console.warn(`[HealthMonitor] 健康检查失败(${this.consecutiveFailures}/${this.config.failureThreshold}):`,b.message);let w;if(this.consecutiveFailures>=this.config.failureThreshold)w="unhealthy",this.emit("unhealthy",this.consecutiveFailures,b),console.log("[HealthMonitor] 达到失败阈值,触发重连..."),this.triggerReconnection().catch((W)=>{console.error("[HealthMonitor] 重连失败:",W)});else w="degraded";this.setStatus(w);let V={status:w,timestamp:Date.now(),consecutiveFailures:this.consecutiveFailures,lastError:b};return this.emit("healthCheck",V),V}finally{this.isChecking=!1}}async pingServer(){let $=new Promise((w,V)=>{setTimeout(()=>V(Error("Health check timeout")),this.config.timeout)}),b=(async()=>{if(this.client.availableTools.length===0){if(!this.client.server)throw Error("Server info not available")}})();await Promise.race([b,$])}async triggerReconnection(){try{await this.client.disconnect(),await new Promise(($)=>setTimeout($,1000)),await this.client.connect(),console.log("[HealthMonitor] 重连成功"),this.consecutiveFailures=0,this.setStatus("healthy"),this.emit("reconnected")}catch($){throw console.error("[HealthMonitor] 重连失败:",$),$}}setStatus($){if(this.currentStatus!==$){let b=this.currentStatus;this.currentStatus=$,this.emit("statusChanged",$,b)}}getStatus(){return this.currentStatus}getLastResult(){return{status:this.currentStatus,timestamp:this.lastCheckTime,consecutiveFailures:this.consecutiveFailures}}getStatistics(){return{status:this.currentStatus,consecutiveFailures:this.consecutiveFailures,lastCheckTime:this.lastCheckTime,isChecking:this.isChecking,config:this.config}}async checkNow(){return this.performHealthCheck()}resetFailureCount(){if(this.consecutiveFailures=0,this.currentStatus!=="checking")this.setStatus("healthy")}}var R1;((Z)=>{Z.NETWORK_TEMPORARY="network_temporary";Z.NETWORK_PERMANENT="network_permanent";Z.CONFIG_ERROR="config_error";Z.AUTH_ERROR="auth_error";Z.PROTOCOL_ERROR="protocol_error";Z.UNKNOWN="unknown"})(R1||={});function $4($){if(!($ instanceof Error))return{type:"unknown",isRetryable:!1,originalError:Error(String($))};let b=$.message.toLowerCase();if(["command not found","no such file","permission denied","invalid configuration","malformed","syntax error"].some((W)=>b.includes(W)))return{type:"config_error",isRetryable:!1,originalError:$};if(b.includes("unauthorized")||b.includes("401")||b.includes("authentication failed"))return{type:"auth_error",isRetryable:!1,originalError:$};if(["timeout","connection refused","network error","temporary","try again","rate limit","too many requests","service unavailable","socket hang up","econnreset","enotfound","econnrefused","etimedout","503","429"].some((W)=>b.includes(W)))return{type:"network_temporary",isRetryable:!0,originalError:$};return{type:"unknown",isRetryable:!0,originalError:$}}class K0 extends P5{config;status="disconnected";sdkClient=null;tools=new Map;serverInfo=null;reconnectAttempts=0;MAX_RECONNECT_ATTEMPTS=5;reconnectTimer=null;isManualDisconnect=!1;oauthProvider=null;serverName;healthMonitor=null;inProcessHandle=null;constructor($,b,w,V){super();this.config=$;if(this.serverName=b||"default",this.inProcessHandle=V||null,$.oauth?.enabled)this.oauthProvider=new Xb;if(w?.enabled)this.healthMonitor=new x0(this,w),this.healthMonitor.on("unhealthy",(W,Q)=>{this.emit("unhealthy",W,Q)}),this.healthMonitor.on("reconnected",()=>{this.emit("healthMonitorReconnected")})}get connectionStatus(){return this.status}get availableTools(){return Array.from(this.tools.values())}get server(){return this.serverInfo}get healthCheck(){return this.healthMonitor}async connect(){return this.connectWithRetry(3,1000)}async connectWithRetry($=3,b=1000){if(this.status!=="disconnected"&&this.status!=="error")throw Error("客户端已连接或正在连接中");if(this.status==="error"){if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected")}let w=null;for(let V=1;V<=$;V++)try{await this.doConnect(),this.reconnectAttempts=0;return}catch(W){w=W;let Q=$4(W);if(!Q.isRetryable)throw console.error("[McpClient] 检测到永久性错误,放弃重试:",Q.type),W;if(V<$){let Z=b*2**(V-1);console.warn(`[McpClient] 连接失败(${V}/${$}),${Z}ms 后重试...`),await new Promise((Y)=>setTimeout(Y,Z))}}throw w||Error("连接失败")}async doConnect(){try{this.setStatus("connecting"),this.sdkClient=new k5({name:aw(),version:rw()},{capabilities:{roots:{listChanged:!0},sampling:{}}}),this.sdkClient.onclose=()=>{this.handleUnexpectedClose()};let $=await this.createTransport();await this.sdkClient.connect($);let b=this.sdkClient.getServerVersion();if(this.serverInfo={name:b?.name||"Unknown",version:b?.version||"0.0.0"},await this.loadTools(),this.setStatus("connected"),this.emit("connected",this.serverInfo),this.healthMonitor)this.healthMonitor.start()}catch($){throw this.setStatus("error"),this.emit("error",$),$}}handleUnexpectedClose(){if(this.isManualDisconnect)return;if(this.status==="connected")console.warn("[McpClient] 检测到意外断连,准备重连..."),this.setStatus("error"),this.emit("error",Error("MCP服务器连接意外关闭")),this.scheduleReconnect()}scheduleReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.reconnectAttempts>=this.MAX_RECONNECT_ATTEMPTS){console.error("[McpClient] 达到最大重连次数,放弃重连"),this.emit("reconnectFailed");return}let $=Math.min(1000*2**this.reconnectAttempts,30000);this.reconnectAttempts++,console.log(`[McpClient] 将在 ${$}ms 后进行第 ${this.reconnectAttempts} 次重连...`),this.reconnectTimer=setTimeout(async()=>{try{if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected"),await this.doConnect(),console.log("[McpClient] 重连成功"),this.reconnectAttempts=0,this.emit("reconnected")}catch(b){if(console.error("[McpClient] 重连失败:",b),$4(b).isRetryable)this.scheduleReconnect();else console.error("[McpClient] 检测到永久性错误,停止重连"),this.emit("reconnectFailed")}},$)}async disconnect(){if(this.isManualDisconnect=!0,this.healthMonitor)this.healthMonitor.stop();if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.sdkClient){try{await this.sdkClient.close()}catch($){console.warn("[McpClient] 断开连接时出错:",$)}this.sdkClient=null}this.tools.clear(),this.serverInfo=null,this.reconnectAttempts=0,this.setStatus("disconnected"),this.emit("disconnected"),this.isManualDisconnect=!1}async callTool($,b={}){if(!this.sdkClient)throw Error("客户端未连接到服务器");if(!this.tools.has($))throw Error(`工具 "${$}" 不存在`);try{return await this.sdkClient.callTool({name:$,arguments:b})}catch(w){throw console.error(`[McpClient] 调用工具 "${$}" 失败:`,w),w}}async createTransport(){let{type:$,command:b,args:w,env:V,url:W,headers:Q,oauth:Z}=this.config,Y={...Q};if(Z?.enabled&&this.oauthProvider&&($==="sse"||$==="http"))try{let J=await this.oauthProvider.getValidToken(this.serverName,Z);if(!J){console.log(`[McpClient] 服务器 "${this.serverName}" 需要 OAuth 认证`);let X=await this.oauthProvider.authenticate(this.serverName,Z);Y.Authorization=`Bearer ${X.accessToken}`}else Y.Authorization=`Bearer ${J}`}catch(J){throw console.error("[McpClient] OAuth 认证失败:",J),Error(`OAuth 认证失败: ${J instanceof Error?J.message:String(J)}`)}if(this.inProcessHandle)return this.inProcessHandle.createClientTransport();if($==="stdio"){if(!b)throw Error("stdio 传输需要 command 参数");let J={};for(let[X,O]of Object.entries(process.env))if(O!==void 0)J[X]=O;return new I5({command:b,args:w||[],env:{...J,...V},stderr:"ignore"})}else if($==="sse"){if(!W)throw Error("sse 传输需要 url 参数");return new f5(new URL(W),{requestInit:{headers:Y}})}else if($==="http"){if(!W)throw Error("http 传输需要 url 参数");let{StreamableHTTPClientTransport:J}=await import("@modelcontextprotocol/sdk/client/streamableHttp.js");return new J(new URL(W),{requestInit:{headers:Y}})}throw Error(`不支持的传输类型: ${$}`)}async loadTools(){if(!this.sdkClient)return;try{let $=await this.sdkClient.listTools();if(this.tools.clear(),$.tools)for(let b of $.tools)this.tools.set(b.name,b);this.emit("toolsUpdated",this.availableTools)}catch($){throw console.error("[McpClient] 加载工具失败:",$),$}}setStatus($){let b=this.status;this.status=$,this.emit("statusChanged",$,b)}async initialize(){return this.connect()}async destroy(){return this.disconnect()}async connectToServer($){return this.connect()}async disconnectFromServer($){return this.disconnect()}async listResources($){if(!this.sdkClient)return[];try{return(await this.sdkClient.listResources()).resources||[]}catch{return[]}}async listTools($){return this.availableTools}async readResource($,b){if(!this.sdkClient)throw Error("客户端未连接");return(await this.sdkClient.readResource({uri:$})).contents?.[0]||{uri:$,text:""}}}class h extends h5{static instance=null;servers=new Map;isDiscovering=!1;constructor(){super()}static getInstance(){if(!h.instance)h.instance=new h;return h.instance}async registerServer($,b){if(this.servers.has($))throw Error(`MCP服务器 "${$}" 已经注册`);let w=new K0(b,$,b.healthCheck),V={config:b,client:w,status:"disconnected",tools:[]};this.setupClientEventHandlers(w,V,$),this.servers.set($,V),this.emit("serverRegistered",$,V);try{await this.connectServer($)}catch(W){console.warn(`MCP服务器 "${$}" 连接失败:`,W)}}async registerInProcessServer($,b){let w=this.servers.get($);if(w){if(w.inProcessHandle===b){if(w.status==="connecting")await this.waitForServerConnected($);else if(w.status!=="connected")await this.connectServer($);return}throw Error(`MCP server "${$}" is already registered with a different handle. In-process servers cannot be replaced while other sessions may be using them.`)}let V={command:""},W=new K0(V,$,void 0,b),Q={config:V,client:W,status:"disconnected",tools:[],inProcessHandle:b};this.setupClientEventHandlers(W,Q,$),this.servers.set($,Q),this.emit("serverRegistered",$,Q);try{await this.connectServer($)}catch(Z){console.warn(`In-process MCP服务器 "${$}" 连接失败:`,Z)}}async unregisterServer($){let b=this.servers.get($);if(!b)return;try{await b.client.disconnect()}catch(w){console.warn(`断开MCP服务器 "${$}" 时出错:`,w)}this.servers.delete($),this.emit("serverUnregistered",$)}async connectServer($){let b=this.servers.get($);if(!b)throw Error(`MCP服务器 "${$}" 未注册`);if(b.status==="connected")return;if(b.status==="connecting"){await this.waitForServerConnected($);return}try{b.status="connecting",await b.client.connect(),b.status="connected",b.connectedAt=new Date,b.lastError=void 0,b.tools=b.client.availableTools}catch(w){throw b.lastError=w,b.status="error",w}}async disconnectServer($){let b=this.servers.get($);if(!b)return;await b.client.disconnect(),b.connectedAt=void 0}async reconnectServer($){let b=this.servers.get($);if(!b)throw Error(`MCP服务器 "${$}" 未注册`);if(b.status==="connected")await b.client.disconnect();try{b.status="connecting",await b.client.connect(),b.status="connected",b.connectedAt=new Date,b.lastError=void 0,b.tools=b.client.availableTools}catch(w){throw b.lastError=w,b.status="error",w}}async getAvailableTools(){return this.getAvailableToolsByServerNames(Array.from(this.servers.keys()))}async getAvailableToolsByServerNames($){let b=[],w=new Map,V=new Set($);for(let[W,Q]of this.servers){if(!V.has(W))continue;if(Q.status==="connected")for(let Z of Q.tools){let Y=w.get(Z.name)||0;w.set(Z.name,Y+1)}}for(let[W,Q]of this.servers){if(!V.has(W))continue;if(Q.status==="connected")for(let Z of Q.tools){let J=(w.get(Z.name)||0)>1?`${W}__${Z.name}`:Z.name,X=I0(Q.client,W,Z,J);b.push(X)}}return b}async waitForServerConnected($,b=1e4){let w=this.servers.get($);if(!w)throw Error(`MCP服务器 "${$}" 未注册`);if(w.status==="connected")return;if(w.status==="error")throw w.lastError||Error(`MCP服务器 "${$}" 连接失败`);await new Promise((V,W)=>{let Q=(X,O)=>{if(X!==$)return;if(O==="connected"){Z(),V();return}if(O==="error"||O==="disconnected"){Z();let G=this.servers.get($);W(G?.lastError||Error(`MCP服务器 "${$}" 连接失败`))}},Z=()=>{clearTimeout(Y),this.off("serverStatusChanged",Q)},Y=setTimeout(()=>{Z(),W(Error(`等待MCP服务器 "${$}" 连接超时`))},b);this.on("serverStatusChanged",Q);let J=this.servers.get($)?.status;if(J==="connected")Z(),V();else if(J==="error"||J==="disconnected"){Z();let X=this.servers.get($);W(X?.lastError||Error(`MCP服务器 "${$}" 连接失败`))}})}async findTool($){for(let[b,w]of this.servers)if(w.status==="connected"){let V=w.tools.find((W)=>W.name===$);if(V)return I0(w.client,b,V)}return null}getToolsByServer($){let b=this.servers.get($);if(!b||b.status!=="connected")return[];return b.tools.map((w)=>I0(b.client,$,w))}getServerStatus($){return this.servers.get($)||null}getAllServers(){return new Map(this.servers)}async refreshAllTools(){let $=[];for(let[b,w]of this.servers)if(w.status==="connected")$.push(this.refreshServerTools(b));await Promise.allSettled($)}async refreshServerTools($){let b=this.servers.get($);if(!b||b.status!=="connected")return;try{let w=b.client.availableTools,V=b.tools.length;b.tools=w,this.emit("toolsUpdated",$,w,V)}catch(w){console.warn(`刷新服务器 "${$}" 工具列表失败:`,w)}}setupClientEventHandlers($,b,w){$.on("connected",(V)=>{b.status="connected",b.connectedAt=new Date,b.tools=$.availableTools,this.emit("serverConnected",w,V)}),$.on("disconnected",()=>{b.status="disconnected",b.connectedAt=void 0,b.tools=[],this.emit("serverDisconnected",w)}),$.on("error",(V)=>{b.status="error",b.lastError=V,this.emit("serverError",w,V)}),$.on("toolsUpdated",(V)=>{let W=b.tools.length;b.tools=V,this.emit("toolsUpdated",w,V,W)}),$.on("statusChanged",(V,W)=>{b.status=V,this.emit("serverStatusChanged",w,V,W)})}async discoverServers(){if(this.isDiscovering)return Array.from(this.servers.values());this.isDiscovering=!0,this.emit("discoveryStarted");try{return Array.from(this.servers.values())}finally{this.isDiscovering=!1,this.emit("discoveryCompleted")}}async registerServers($){let b=Object.entries($).map(([w,V])=>this.registerServer(w,V).catch((W)=>{return console.warn(`注册MCP服务器 "${w}" 失败:`,W),W}));await Promise.allSettled(b)}getStatistics(){let $=0,b=0,w=0;for(let V of this.servers.values())if(V.status==="connected")$++,b+=V.tools.length;else if(V.status==="error")w++;return{totalServers:this.servers.size,connectedServers:$,errorServers:w,totalTools:b,isDiscovering:this.isDiscovering}}async disconnectAll(){let $=[];for(let[b,w]of this.servers)if(w.status==="connected")$.push(w.client.disconnect().catch((V)=>{console.warn(`断开 MCP 服务器 "${b}" 时出错:`,V)}));await Promise.allSettled($),this.servers.clear()}}import{promises as K4}from"fs";import t5 from"path";import*as Ab from"node:fs/promises";import{homedir as X4}from"node:os";import*as j$ from"node:path";var Ob={name:"skill-creator",description:"Create new Skills interactively. Use when the user wants to create a new Skill, define a custom workflow, or add a specialized capability to Blade.",allowedTools:["Read","Write","Glob","Bash","AskUserQuestion"],version:"1.0.0",argumentHint:void 0,userInvocable:!0,disableModelInvocation:!1,model:void 0,whenToUse:"User wants to create a new skill, define a custom workflow, or add a specialized capability.",path:"builtin://skill-creator",basePath:"",source:"builtin"};function b4(){return{metadata:Ob,instructions:`# Skill Creator
47
+ If the browser does not open automatically, copy and paste this URL:`),console.log(W),console.log("");let V=this.startCallbackServer(w.state);try{await this.openAuthorizationUrl(W)}catch(Y){console.warn("[OAuth] Failed to open browser automatically:",Y)}let Q=await V;console.log("[OAuth] Authorization code received, exchanging for tokens...");let Z=await this.exchangeCodeForToken(b,Q,w.codeVerifier),J={accessToken:Z.access_token,tokenType:Z.token_type||"Bearer",refreshToken:Z.refresh_token,scope:Z.scope};if(Z.expires_in)J.expiresAt=Date.now()+Z.expires_in*1000;return await this.tokenStorage.saveToken($,J,b.clientId,b.tokenUrl),console.log("[OAuth] Authentication successful! Token saved."),J}async openAuthorizationUrl($){let{command:b,args:w}=this.getBrowserCommand($);await new Promise((W,V)=>{let Q=s8(b,w,{stdio:"ignore"});Q.once("error",V),Q.once("close",(Z)=>{if(Z===0||Z===null)W();else V(Error(`Failed to open browser (exit code ${Z})`))})})}getBrowserCommand($){if(process.platform==="darwin")return{command:"open",args:[$]};if(process.platform==="win32")return{command:"cmd",args:["/c","start","",$]};return{command:"xdg-open",args:[$]}}async getValidToken($,b){let w=await this.tokenStorage.getCredentials($);if(!w)return null;let{token:W}=w;if(!this.tokenStorage.isTokenExpired(W))return W.accessToken;if(W.refreshToken&&b.clientId&&w.tokenUrl)try{console.log(`[OAuth] Refreshing expired token for server: ${$}`);let V=await this.refreshAccessToken(b,W.refreshToken),Q={accessToken:V.access_token,tokenType:V.token_type,refreshToken:V.refresh_token||W.refreshToken,scope:V.scope||W.scope};if(V.expires_in)Q.expiresAt=Date.now()+V.expires_in*1000;return await this.tokenStorage.saveToken($,Q,b.clientId,w.tokenUrl),Q.accessToken}catch(V){console.error("[OAuth] Failed to refresh token:",V),await this.tokenStorage.deleteCredentials($)}return null}}import{EventEmitter as r8}from"events";var t$;((V)=>{V.DISCONNECTED="disconnected";V.CONNECTING="connecting";V.CONNECTED="connected";V.ERROR="error"})(t$||={});var K1;((V)=>{V.HEALTHY="healthy";V.DEGRADED="degraded";V.UNHEALTHY="unhealthy";V.CHECKING="checking"})(K1||={});class u0 extends r8{client;config;checkTimer=null;isChecking=!1;consecutiveFailures=0;lastCheckTime=0;currentStatus="healthy";constructor($,b={}){super();this.client=$,this.config={interval:b.interval??30000,timeout:b.timeout??1e4,enabled:b.enabled??!1,failureThreshold:b.failureThreshold??3}}start(){if(this.checkTimer){console.warn("[HealthMonitor] 健康监控已在运行");return}if(!this.config.enabled){console.log("[HealthMonitor] 健康监控未启用");return}console.log(`[HealthMonitor] 启动健康监控(间隔: ${this.config.interval}ms)`),this.scheduleNextCheck()}stop(){if(this.checkTimer)clearTimeout(this.checkTimer),this.checkTimer=null,console.log("[HealthMonitor] 停止健康监控")}scheduleNextCheck(){this.checkTimer=setTimeout(async()=>{await this.performHealthCheck(),this.scheduleNextCheck()},this.config.interval)}async performHealthCheck(){if(this.isChecking)return console.warn("[HealthMonitor] 上一次检查仍在进行中"),this.getLastResult();this.isChecking=!0,this.lastCheckTime=Date.now(),this.setStatus("checking");try{let $=this.client.connectionStatus;if($==="connected"){await this.pingServer(),this.consecutiveFailures=0,this.setStatus("healthy");let b={status:"healthy",timestamp:Date.now(),consecutiveFailures:0};return this.emit("healthCheck",b),b}else throw Error(`连接状态异常: ${$}`)}catch($){this.consecutiveFailures++,console.warn(`[HealthMonitor] 健康检查失败(${this.consecutiveFailures}/${this.config.failureThreshold}):`,_($));let b;if(this.consecutiveFailures>=this.config.failureThreshold)b="unhealthy",this.emit("unhealthy",this.consecutiveFailures,$),console.log("[HealthMonitor] 达到失败阈值,触发重连..."),this.triggerReconnection().catch((W)=>{console.error("[HealthMonitor] 重连失败:",W)});else b="degraded";this.setStatus(b);let w={status:b,timestamp:Date.now(),consecutiveFailures:this.consecutiveFailures,lastError:$ instanceof Error?$:Error(_($))};return this.emit("healthCheck",w),w}finally{this.isChecking=!1}}async pingServer(){let $=new Promise((w,W)=>{setTimeout(()=>W(Error("Health check timeout")),this.config.timeout)}),b=(async()=>{if(this.client.availableTools.length===0){if(!this.client.server)throw Error("Server info not available")}})();await Promise.race([b,$])}async triggerReconnection(){try{await this.client.disconnect(),await new Promise(($)=>setTimeout($,1000)),await this.client.connect(),console.log("[HealthMonitor] 重连成功"),this.consecutiveFailures=0,this.setStatus("healthy"),this.emit("reconnected")}catch($){throw console.error("[HealthMonitor] 重连失败:",$),$}}setStatus($){if(this.currentStatus!==$){let b=this.currentStatus;this.currentStatus=$,this.emit("statusChanged",$,b)}}getStatus(){return this.currentStatus}getLastResult(){return{status:this.currentStatus,timestamp:this.lastCheckTime,consecutiveFailures:this.consecutiveFailures}}getStatistics(){return{status:this.currentStatus,consecutiveFailures:this.consecutiveFailures,lastCheckTime:this.lastCheckTime,isChecking:this.isChecking,config:this.config}}async checkNow(){return this.performHealthCheck()}resetFailureCount(){if(this.consecutiveFailures=0,this.currentStatus!=="checking")this.setStatus("healthy")}}var q1;((Z)=>{Z.NETWORK_TEMPORARY="network_temporary";Z.NETWORK_PERMANENT="network_permanent";Z.CONFIG_ERROR="config_error";Z.AUTH_ERROR="auth_error";Z.PROTOCOL_ERROR="protocol_error";Z.UNKNOWN="unknown"})(q1||={});function W4($){if(!($ instanceof Error))return{type:"unknown",isRetryable:!1,originalError:Error(String($))};let b=$.message.toLowerCase();if(["command not found","no such file","permission denied","invalid configuration","malformed","syntax error"].some((V)=>b.includes(V)))return{type:"config_error",isRetryable:!1,originalError:$};if(b.includes("unauthorized")||b.includes("401")||b.includes("authentication failed"))return{type:"auth_error",isRetryable:!1,originalError:$};if(["timeout","connection refused","network error","temporary","try again","rate limit","too many requests","service unavailable","socket hang up","econnreset","enotfound","econnrefused","etimedout","503","429"].some((V)=>b.includes(V)))return{type:"network_temporary",isRetryable:!0,originalError:$};return{type:"unknown",isRetryable:!0,originalError:$}}class C0 extends e8{config;status="disconnected";sdkClient=null;tools=new Map;serverInfo=null;reconnectAttempts=0;MAX_RECONNECT_ATTEMPTS=5;reconnectTimer=null;isManualDisconnect=!1;oauthProvider=null;serverName;healthMonitor=null;inProcessHandle=null;constructor($,b,w,W){super();this.config=$;if(this.serverName=b||"default",this.inProcessHandle=W||null,$.oauth?.enabled)this.oauthProvider=new Bb;if(w?.enabled)this.healthMonitor=new u0(this,w),this.healthMonitor.on("unhealthy",(V,Q)=>{this.emit("unhealthy",V,Q)}),this.healthMonitor.on("reconnected",()=>{this.emit("healthMonitorReconnected")})}get connectionStatus(){return this.status}get availableTools(){return Array.from(this.tools.values())}get server(){return this.serverInfo}get healthCheck(){return this.healthMonitor}async connect(){return this.connectWithRetry(3,1000)}async connectWithRetry($=3,b=1000){if(this.status!=="disconnected"&&this.status!=="error")throw Error("客户端已连接或正在连接中");if(this.status==="error"){if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected")}let w=null;for(let W=1;W<=$;W++)try{await this.doConnect(),this.reconnectAttempts=0;return}catch(V){w=I0(V);let Q=W4(V);if(!Q.isRetryable)throw console.error("[McpClient] 检测到永久性错误,放弃重试:",Q.type),V;if(W<$){let Z=b*2**(W-1);console.warn(`[McpClient] 连接失败(${W}/${$}),${Z}ms 后重试...`),await new Promise((J)=>setTimeout(J,Z))}}throw w||Error("连接失败")}async doConnect(){try{this.setStatus("connecting"),this.sdkClient=new a8({name:ew(),version:tw()},{capabilities:{roots:{listChanged:!0},sampling:{}}}),this.sdkClient.onclose=()=>{this.handleUnexpectedClose()};let $=await this.createTransport();await this.sdkClient.connect($);let b=this.sdkClient.getServerVersion();if(this.serverInfo={name:b?.name||"Unknown",version:b?.version||"0.0.0"},await this.loadTools(),this.setStatus("connected"),this.emit("connected",this.serverInfo),this.healthMonitor)this.healthMonitor.start()}catch($){throw this.setStatus("error"),this.emit("error",$),$}}handleUnexpectedClose(){if(this.isManualDisconnect)return;if(this.status==="connected")console.warn("[McpClient] 检测到意外断连,准备重连..."),this.setStatus("error"),this.emit("error",Error("MCP服务器连接意外关闭")),this.scheduleReconnect()}scheduleReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.reconnectAttempts>=this.MAX_RECONNECT_ATTEMPTS){console.error("[McpClient] 达到最大重连次数,放弃重连"),this.emit("reconnectFailed");return}let $=Math.min(1000*2**this.reconnectAttempts,30000);this.reconnectAttempts++,console.log(`[McpClient] 将在 ${$}ms 后进行第 ${this.reconnectAttempts} 次重连...`),this.reconnectTimer=setTimeout(async()=>{try{if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected"),await this.doConnect(),console.log("[McpClient] 重连成功"),this.reconnectAttempts=0,this.emit("reconnected")}catch(b){if(console.error("[McpClient] 重连失败:",b),W4(b).isRetryable)this.scheduleReconnect();else console.error("[McpClient] 检测到永久性错误,停止重连"),this.emit("reconnectFailed")}},$)}async disconnect(){if(this.isManualDisconnect=!0,this.healthMonitor)this.healthMonitor.stop();if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.sdkClient){try{await this.sdkClient.close()}catch($){console.warn("[McpClient] 断开连接时出错:",$)}this.sdkClient=null}this.tools.clear(),this.serverInfo=null,this.reconnectAttempts=0,this.setStatus("disconnected"),this.emit("disconnected"),this.isManualDisconnect=!1}async callTool($,b={}){if(!this.sdkClient)throw Error("客户端未连接到服务器");if(!this.tools.has($))throw Error(`工具 "${$}" 不存在`);try{return await this.sdkClient.callTool({name:$,arguments:b})}catch(w){throw console.error(`[McpClient] 调用工具 "${$}" 失败:`,w),w}}async createTransport(){let{type:$,command:b,args:w,env:W,url:V,headers:Q,oauth:Z}=this.config,J={...Q};if(Z?.enabled&&this.oauthProvider&&($==="sse"||$==="http"))try{let Y=await this.oauthProvider.getValidToken(this.serverName,Z);if(!Y){console.log(`[McpClient] 服务器 "${this.serverName}" 需要 OAuth 认证`);let X=await this.oauthProvider.authenticate(this.serverName,Z);J.Authorization=`Bearer ${X.accessToken}`}else J.Authorization=`Bearer ${Y}`}catch(Y){throw console.error("[McpClient] OAuth 认证失败:",Y),Error(`OAuth 认证失败: ${Y instanceof Error?Y.message:String(Y)}`)}if(this.inProcessHandle)return this.inProcessHandle.createClientTransport();if($==="stdio"){if(!b)throw Error("stdio 传输需要 command 参数");let Y={};for(let[X,O]of Object.entries(process.env))if(O!==void 0)Y[X]=O;return new t8({command:b,args:w||[],env:{...Y,...W},stderr:"ignore"})}else if($==="sse"){if(!V)throw Error("sse 传输需要 url 参数");return new o8(new URL(V),{requestInit:{headers:J}})}else if($==="http"){if(!V)throw Error("http 传输需要 url 参数");let{StreamableHTTPClientTransport:Y}=await import("@modelcontextprotocol/sdk/client/streamableHttp.js");return new Y(new URL(V),{requestInit:{headers:J}})}throw Error(`不支持的传输类型: ${$}`)}async loadTools(){if(!this.sdkClient)return;try{let $=await this.sdkClient.listTools();if(this.tools.clear(),$.tools)for(let b of $.tools)this.tools.set(b.name,b);this.emit("toolsUpdated",this.availableTools)}catch($){throw console.error("[McpClient] 加载工具失败:",$),$}}setStatus($){let b=this.status;this.status=$,this.emit("statusChanged",$,b)}async initialize(){return this.connect()}async destroy(){return this.disconnect()}async connectToServer($){return this.connect()}async disconnectFromServer($){return this.disconnect()}async listResources($){if(!this.sdkClient)return[];try{return(await this.sdkClient.listResources()).resources||[]}catch{return[]}}async listTools($){return this.availableTools}async readResource($,b){if(!this.sdkClient)throw Error("客户端未连接");return(await this.sdkClient.readResource({uri:$})).contents?.[0]||{uri:$,text:""}}}class e$ extends $W{servers=new Map;isDiscovering=!1;constructor(){super()}async registerServer($,b){if(this.servers.has($))throw Error(`MCP服务器 "${$}" 已经注册`);let w=new C0(b,$,b.healthCheck),W={config:b,client:w,status:"disconnected",tools:[]};this.setupClientEventHandlers(w,W,$),this.servers.set($,W),this.emit("serverRegistered",$,W);try{await this.connectServer($)}catch(V){console.warn(`MCP服务器 "${$}" 连接失败:`,V)}}async registerInProcessServer($,b){let w=this.servers.get($);if(w){if(w.inProcessHandle===b){if(w.status==="connecting")await this.waitForServerConnected($);else if(w.status!=="connected")await this.connectServer($);return}throw Error(`MCP server "${$}" is already registered with a different handle. In-process servers cannot be replaced while other sessions may be using them.`)}let W={command:""},V=new C0(W,$,void 0,b),Q={config:W,client:V,status:"disconnected",tools:[],inProcessHandle:b};this.setupClientEventHandlers(V,Q,$),this.servers.set($,Q),this.emit("serverRegistered",$,Q);try{await this.connectServer($)}catch(Z){console.warn(`In-process MCP服务器 "${$}" 连接失败:`,Z)}}async unregisterServer($){let b=this.servers.get($);if(!b)return;try{await b.client.disconnect()}catch(w){console.warn(`断开MCP服务器 "${$}" 时出错:`,w)}this.servers.delete($),this.emit("serverUnregistered",$)}async connectServer($){let b=this.servers.get($);if(!b)throw Error(`MCP服务器 "${$}" 未注册`);if(b.status==="connected")return;if(b.status==="connecting"){await this.waitForServerConnected($);return}try{b.status="connecting",await b.client.connect(),b.status="connected",b.connectedAt=new Date,b.lastError=void 0,b.tools=b.client.availableTools}catch(w){throw b.lastError=I0(w),b.status="error",w}}async disconnectServer($){let b=this.servers.get($);if(!b)return;await b.client.disconnect(),b.connectedAt=void 0}async reconnectServer($){let b=this.servers.get($);if(!b)throw Error(`MCP服务器 "${$}" 未注册`);if(b.status==="connected")await b.client.disconnect();try{b.status="connecting",await b.client.connect(),b.status="connected",b.connectedAt=new Date,b.lastError=void 0,b.tools=b.client.availableTools}catch(w){throw b.lastError=I0(w),b.status="error",w}}async getAvailableTools(){return this.getAvailableToolsByServerNames(Array.from(this.servers.keys()))}async getAvailableToolsByServerNames($){let b=[],w=new Map,W=new Set($);for(let[V,Q]of this.servers){if(!W.has(V))continue;if(Q.status==="connected")for(let Z of Q.tools){let J=w.get(Z.name)||0;w.set(Z.name,J+1)}}for(let[V,Q]of this.servers){if(!W.has(V))continue;if(Q.status==="connected")for(let Z of Q.tools){let Y=(w.get(Z.name)||0)>1?`${V}__${Z.name}`:Z.name,X=x0(Q.client,V,Z,Y);b.push(X)}}return b}async waitForServerConnected($,b=1e4){let w=this.servers.get($);if(!w)throw Error(`MCP服务器 "${$}" 未注册`);if(w.status==="connected")return;if(w.status==="error")throw w.lastError||Error(`MCP服务器 "${$}" 连接失败`);await new Promise((W,V)=>{let Q=(X,O)=>{if(X!==$)return;if(O==="connected"){Z(),W();return}if(O==="error"||O==="disconnected"){Z();let G=this.servers.get($);V(G?.lastError||Error(`MCP服务器 "${$}" 连接失败`))}},Z=()=>{clearTimeout(J),this.off("serverStatusChanged",Q)},J=setTimeout(()=>{Z(),V(Error(`等待MCP服务器 "${$}" 连接超时`))},b);this.on("serverStatusChanged",Q);let Y=this.servers.get($)?.status;if(Y==="connected")Z(),W();else if(Y==="error"||Y==="disconnected"){Z();let X=this.servers.get($);V(X?.lastError||Error(`MCP服务器 "${$}" 连接失败`))}})}async findTool($){for(let[b,w]of this.servers)if(w.status==="connected"){let W=w.tools.find((V)=>V.name===$);if(W)return x0(w.client,b,W)}return null}getToolsByServer($){let b=this.servers.get($);if(!b||b.status!=="connected")return[];return b.tools.map((w)=>x0(b.client,$,w))}getServerStatus($){return this.servers.get($)||null}getAllServers(){return new Map(this.servers)}async refreshAllTools(){let $=[];for(let[b,w]of this.servers)if(w.status==="connected")$.push(this.refreshServerTools(b));await Promise.allSettled($)}async refreshServerTools($){let b=this.servers.get($);if(!b||b.status!=="connected")return;try{let w=b.client.availableTools,W=b.tools.length;b.tools=w,this.emit("toolsUpdated",$,w,W)}catch(w){console.warn(`刷新服务器 "${$}" 工具列表失败:`,w)}}setupClientEventHandlers($,b,w){$.on("connected",(W)=>{b.status="connected",b.connectedAt=new Date,b.tools=$.availableTools,this.emit("serverConnected",w,W)}),$.on("disconnected",()=>{b.status="disconnected",b.connectedAt=void 0,b.tools=[],this.emit("serverDisconnected",w)}),$.on("error",(W)=>{b.status="error",b.lastError=W,this.emit("serverError",w,W)}),$.on("toolsUpdated",(W)=>{let V=b.tools.length;b.tools=W,this.emit("toolsUpdated",w,W,V)}),$.on("statusChanged",(W,V)=>{b.status=W,this.emit("serverStatusChanged",w,W,V)})}async discoverServers(){if(this.isDiscovering)return Array.from(this.servers.values());this.isDiscovering=!0,this.emit("discoveryStarted");try{return Array.from(this.servers.values())}finally{this.isDiscovering=!1,this.emit("discoveryCompleted")}}async registerServers($){let b=Object.entries($).map(([w,W])=>this.registerServer(w,W).catch((V)=>{return console.warn(`注册MCP服务器 "${w}" 失败:`,V),V}));await Promise.allSettled(b)}getStatistics(){let $=0,b=0,w=0;for(let W of this.servers.values())if(W.status==="connected")$++,b+=W.tools.length;else if(W.status==="error")w++;return{totalServers:this.servers.size,connectedServers:$,errorServers:w,totalTools:b,isDiscovering:this.isDiscovering}}async disconnectAll(){let $=[];for(let[b,w]of this.servers)if(w.status==="connected")$.push(w.client.disconnect().catch((W)=>{console.warn(`断开 MCP 服务器 "${b}" 时出错:`,W)}));await Promise.allSettled($),this.servers.clear()}}import{promises as C4}from"fs";import LW from"path";var A1={DEFAULT:"default",AUTO_EDIT:"autoEdit",YOLO:"yolo",BYPASSALL:"bypassAll",PLAN:"plan",SPEC:"spec"},g0;((K)=>{K.PreToolUse="PreToolUse";K.PostToolUse="PostToolUse";K.PostToolUseFailure="PostToolUseFailure";K.PermissionRequest="PermissionRequest";K.UserPromptSubmit="UserPromptSubmit";K.SessionStart="SessionStart";K.SessionEnd="SessionEnd";K.Stop="Stop";K.SubagentStart="SubagentStart";K.SubagentStop="SubagentStop";K.TaskCompleted="TaskCompleted";K.Notification="Notification";K.Compaction="Compaction"})(g0||={});var V4={SYSTEM:"system",USER:"user",ASSISTANT:"assistant",TOOL:"tool"},bW={TURN_START:"turn_start",TURN_END:"turn_end",CONTENT:"content",THINKING:"thinking",TOOL_USE:"tool_use",TOOL_RESULT:"tool_result",USAGE:"usage",RESULT:"result",ERROR:"error"},wW={READONLY:"readonly",WRITE:"write",EXECUTE:"execute"},WW={ALLOW:"allow",DENY:"deny",ASK:"ask"},VW={APPROVE:"approve",BLOCK:"block",ASYNC:"async"},QW={ALLOW:"allow",DENY:"deny",ASK:"ask"},ZW={COMMAND:"command",PROMPT:"prompt"},JW={SUCCESS:0,NON_BLOCKING_ERROR:1,BLOCKING_ERROR:2,TIMEOUT:124},YW={VALIDATION_ERROR:"validation_error",PERMISSION_DENIED:"permission_denied",EXECUTION_ERROR:"execution_error",TIMEOUT_ERROR:"timeout_error",NETWORK_ERROR:"network_error"};var z=A1;import*as Ub from"node:fs/promises";import{homedir as K4}from"node:os";import*as y$ from"node:path";var Kb={name:"skill-creator",description:"Create new Skills interactively. Use when the user wants to create a new Skill, define a custom workflow, or add a specialized capability to Blade.",allowedTools:["Read","Write","Glob","Bash","AskUserQuestion"],version:"1.0.0",argumentHint:void 0,userInvocable:!0,disableModelInvocation:!1,model:void 0,whenToUse:"User wants to create a new skill, define a custom workflow, or add a specialized capability.",path:"builtin://skill-creator",basePath:"",source:"builtin"};function Q4(){return{metadata:Kb,instructions:`# Skill Creator
164
48
 
165
49
  帮助用户创建新的 Blade Skills。
166
50
 
@@ -343,10 +227,10 @@ user-invocable: true
343
227
  <footer>
344
228
  \`\`\`
345
229
  \`\`\`
346
- `}}import{exec as x5}from"node:child_process";import*as z from"node:fs/promises";import{homedir as p5}from"node:os";import*as u from"node:path";import{promisify as d5}from"node:util";var Gb=d5(x5),d=N("General"),E1={url:"https://github.com/anthropics/skills.git",branch:"main",defaultSkills:["skill-creator"]};class w4{skillsDir;constructor($){this.skillsDir=$||u.join(p5(),".blade","skills")}async isInstalled($){let b=u.join(this.skillsDir,$,"SKILL.md");try{return await z.access(b),!0}catch{return!1}}async isGitAvailable(){try{return await Gb("git --version"),!0}catch{return!1}}async installOfficialSkill($){let{url:b,branch:w}=E1,V=u.join(this.skillsDir,$),W=u.join(this.skillsDir,`.tmp-${$}-${Date.now()}`);try{if(!await this.isGitAvailable())return d.warn("Git not available, skipping skill installation"),!1;d.info(`Installing official skill: ${$}...`),await z.mkdir(this.skillsDir,{recursive:!0,mode:493}),await Gb(`git clone --depth 1 --branch ${w} --single-branch ${b} "${W}"`,{timeout:30000});let Q=u.join(W,"skills",$);try{await z.access(Q)}catch{return d.warn(`Skill ${$} not found in official repository`),await z.rm(W,{recursive:!0,force:!0}),!1}try{await z.rm(V,{recursive:!0,force:!0})}catch{}return await z.cp(Q,V,{recursive:!0}),await z.rm(W,{recursive:!0,force:!0}),d.info(`Successfully installed: ${$}`),!0}catch(Q){try{await z.rm(W,{recursive:!0,force:!0})}catch{}return d.warn(`Failed to install ${$}: ${Q instanceof Error?Q.message:"Unknown error"}`),!1}}async ensureDefaultSkillsInstalled(){await z.mkdir(this.skillsDir,{recursive:!0,mode:493});for(let $ of E1.defaultSkills)if(!await this.isInstalled($))await this.installOfficialSkill($)}async installFromRepo($,b){let w=b||this.extractRepoName($),V=u.join(this.skillsDir,w),W=u.join(this.skillsDir,`.tmp-repo-${w}-${Date.now()}`);try{if(!await this.isGitAvailable())return d.warn("Git not available, cannot install from repo"),!1;d.info(`Installing skill from repo: ${$}...`),await z.mkdir(this.skillsDir,{recursive:!0,mode:493}),await Gb(`git clone --depth 1 "${$}" "${W}"`,{timeout:60000});let Q=u.join(W,"SKILL.md");try{await z.access(Q)}catch{return d.warn(`No SKILL.md found in repository ${$}`),await z.rm(W,{recursive:!0,force:!0}),!1}await z.rm(V,{recursive:!0,force:!0}),await z.rename(W,V);try{await z.rm(u.join(V,".git"),{recursive:!0,force:!0})}catch{}return d.info(`Successfully installed skill from repo: ${w}`),!0}catch(Q){try{await z.rm(W,{recursive:!0,force:!0})}catch{}return d.warn(`Failed to install from repo ${$}: ${Q instanceof Error?Q.message:"Unknown error"}`),!1}}async installFromLocal($,b,w=!0){let V=b||u.basename($),W=u.join(this.skillsDir,V);try{let Q=u.resolve($);try{await z.access(Q)}catch{return d.warn(`Local path does not exist: ${Q}`),!1}let Z=u.join(Q,"SKILL.md");try{await z.access(Z)}catch{return d.warn(`No SKILL.md found in local path: ${Q}`),!1}if(d.info(`Installing skill from local path: ${Q}...`),await z.mkdir(this.skillsDir,{recursive:!0,mode:493}),await z.rm(W,{recursive:!0,force:!0}),w)await z.symlink(Q,W,"dir"),d.info(`Created symlink for skill: ${V}`);else await z.cp(Q,W,{recursive:!0}),d.info(`Copied skill to: ${V}`);return!0}catch(Q){return d.warn(`Failed to install from local path ${$}: ${Q instanceof Error?Q.message:"Unknown error"}`),!1}}extractRepoName($){return $.match(/\/([^/]+?)(\.git)?$/)?.[1]||"unknown-skill"}async installAllOfficialSkills(){let{url:$,branch:b}=E1,w=u.join(this.skillsDir,`.tmp-all-${Date.now()}`),V=[],W=[];try{if(!await this.isGitAvailable())return d.warn("Git not available, skipping skill installation"),{installed:V,failed:W};await z.mkdir(this.skillsDir,{recursive:!0,mode:493}),d.info("Cloning official skills repository..."),await Gb(`git clone --depth 1 --branch ${b} --single-branch ${$} "${w}"`,{timeout:60000});let Q=u.join(w,"skills"),Z=await z.readdir(Q,{withFileTypes:!0});for(let Y of Z){if(!Y.isDirectory())continue;let J=Y.name,X=u.join(Q,J),O=u.join(this.skillsDir,J);try{await z.access(u.join(X,"SKILL.md")),await z.rm(O,{recursive:!0,force:!0}),await z.cp(X,O,{recursive:!0}),d.info(`Installed: ${J}`),V.push(J)}catch(G){d.warn(`Failed to install ${J}`),W.push(J)}}await z.rm(w,{recursive:!0,force:!0})}catch(Q){try{await z.rm(w,{recursive:!0,force:!0})}catch{}d.warn(`Failed to install skills: ${Q instanceof Error?Q.message:"Unknown error"}`)}return{installed:V,failed:W}}}var D1=null;function V4($){if(!D1)D1=new w4($);return D1}import*as p0 from"node:fs/promises";import*as Bb from"node:path";import{parse as u5}from"yaml";var g5=/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/,m5=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]?$/,W4=1024;function c5($){if(!$)return;if(typeof $==="string")return $.split(",").map((b)=>b.trim()).filter(Boolean);if(Array.isArray($))return $.map((b)=>String(b).trim()).filter(Boolean);return}function Q4($){if($===void 0)return;if(typeof $==="boolean")return $;if(typeof $==="string"){let b=$.toLowerCase().trim();if(b==="true"||b==="yes"||b==="1")return!0;if(b==="false"||b==="no"||b==="0")return!1}return}function i5($,b){if(!$.name)return{valid:!1,error:"Missing required field: name"};if(!m5.test($.name))return{valid:!1,error:`Invalid name "${$.name}": must be lowercase letters, numbers, and hyphens only, 1-64 characters`};if(!$.description)return{valid:!1,error:"Missing required field: description"};if($.description.length>W4)return{valid:!1,error:`Description too long: ${$.description.length} characters (max ${W4})`};let w;if($.model)w=$.model==="inherit"?"inherit":$.model;return{valid:!0,metadata:{name:$.name,description:$.description.trim(),allowedTools:c5($["allowed-tools"]),version:$.version,argumentHint:$["argument-hint"]?.trim(),userInvocable:Q4($["user-invocable"]),disableModelInvocation:Q4($["disable-model-invocation"]),model:w,whenToUse:$.when_to_use?.trim()}}}function Z4($,b,w){let V=$.match(g5);if(!V)return{success:!1,error:"Invalid SKILL.md format: missing YAML frontmatter (must start with ---)"};let[,W,Q]=V,Z;try{Z=u5(W)}catch(X){return{success:!1,error:`Failed to parse YAML frontmatter: ${X instanceof Error?X.message:String(X)}`}}let Y=i5(Z,b);if(!Y.valid)return{success:!1,error:Y.error};let J=Bb.dirname(b);return{success:!0,content:{metadata:{...Y.metadata,path:b,basePath:J,source:w},instructions:Q.trim()}}}async function Kb($,b){try{let w=await p0.readFile($,"utf-8");return Z4(w,$,b)}catch(w){if(w.code==="ENOENT")return{success:!1,error:`File not found: ${$}`};return{success:!1,error:`Failed to read file: ${w instanceof Error?w.message:String(w)}`}}}async function Y4($){try{let b=await p0.readFile($.path,"utf-8"),w=Z4(b,$.path,$.source);return w.success?w.content:null}catch{return null}}async function J4($){try{return await p0.access(Bb.join($,"SKILL.md")),!0}catch{return!1}}var l5={userSkillsDir:j$.join(X4(),".blade","skills"),projectSkillsDir:".blade/skills",claudeUserSkillsDir:j$.join(X4(),".claude","skills"),claudeProjectSkillsDir:".claude/skills",cwd:process.cwd()},qb=null;class L1{skills=new Map;pluginSkills=new Map;config;initialized=!1;constructor($){this.config={...l5,...$}}static getInstance($){if(!qb)qb=new L1($);return qb}static resetInstance(){qb=null}async initialize(){if(this.initialized)return{skills:Array.from(this.skills.values()),errors:[]};let $=[],b=[];try{await V4(this.config.userSkillsDir).ensureDefaultSkillsInstalled()}catch(J){$.push({path:"SkillInstaller",error:`Failed to install default skills: ${J instanceof Error?J.message:"Unknown error"}`})}this.loadBuiltinSkills();let w=await this.scanDirectory(this.config.claudeUserSkillsDir,"user");b.push(...w.skills),$.push(...w.errors);let V=await this.scanDirectory(this.config.userSkillsDir,"user");b.push(...V.skills),$.push(...V.errors);let W=j$.isAbsolute(this.config.claudeProjectSkillsDir)?this.config.claudeProjectSkillsDir:j$.join(this.config.cwd,this.config.claudeProjectSkillsDir),Q=await this.scanDirectory(W,"project");b.push(...Q.skills),$.push(...Q.errors);let Z=j$.isAbsolute(this.config.projectSkillsDir)?this.config.projectSkillsDir:j$.join(this.config.cwd,this.config.projectSkillsDir),Y=await this.scanDirectory(Z,"project");b.push(...Y.skills),$.push(...Y.errors);for(let J of b)this.skills.set(J.name,J);return this.initialized=!0,{skills:Array.from(this.skills.values()),errors:$}}loadBuiltinSkills(){this.skills.set(Ob.name,Ob)}async scanDirectory($,b){let w=[],V=[];try{await Ab.access($)}catch{return{skills:w,errors:V}}try{let W=await Ab.readdir($,{withFileTypes:!0});for(let Q of W){if(!Q.isDirectory())continue;let Z=j$.join($,Q.name),Y=j$.join(Z,"SKILL.md");if(!await J4(Z))continue;let J=await Kb(Y,b);if(J.success&&J.content)w.push(J.content.metadata);else V.push({path:Y,error:J.error||"Unknown error"})}}catch(W){V.push({path:$,error:`Failed to scan directory: ${W instanceof Error?W.message:String(W)}`})}return{skills:w,errors:V}}getAll(){return Array.from(this.skills.values())}get($){return this.skills.get($)}has($){return this.skills.has($)}async loadContent($){let b=this.skills.get($);if(!b)return null;if(b.source==="builtin")return this.loadBuiltinContent($);return Y4(b)}loadBuiltinContent($){switch($){case"skill-creator":return b4();default:return null}}getModelInvocableSkills(){return Array.from(this.skills.values()).filter(($)=>!$.disableModelInvocation)}getUserInvocableSkills(){return Array.from(this.skills.values()).filter(($)=>$.userInvocable===!0)}generateAvailableSkillsList(){let $=this.getModelInvocableSkills();if($.length===0)return"";let b=[];for(let w of $){let V=w.description.length>100?`${w.description.substring(0,97)}...`:w.description,W=w.argumentHint?`${w.name} ${w.argumentHint}`:w.name;b.push(`- ${W}: ${V}`)}return b.join(`
347
- `)}get size(){return this.skills.size}async refresh(){return this.skills.clear(),this.pluginSkills.clear(),this.initialized=!1,this.initialize()}registerPluginSkill($){this.pluginSkills.set($.namespacedName,$),this.skills.set($.namespacedName,$.metadata)}findPluginSkill($){let b=this.pluginSkills.get($);if(b)return b;let w=[];for(let V of this.pluginSkills.values())if(V.originalName===$)w.push(V);if(w.length===1)return w[0];return}getAllPluginSkills(){return Array.from(this.pluginSkills.values())}clearPluginSkills(){for(let $ of this.pluginSkills.values())this.skills.delete($.namespacedName);this.pluginSkills.clear()}getPluginSkillCount(){return this.pluginSkills.size}}function _$($){return L1.getInstance($)}async function Ub($){return _$($).initialize()}var n5="Skill",s5=/<available_skills>\s*<\/available_skills>/;function Cb($){let w=_$().generateAvailableSkillsList();if(!w)return $;return $.map((V)=>{if(V.name!==n5)return V;let W=V.description.replace(s5,`<available_skills>
230
+ `}}import{exec as XW}from"node:child_process";import*as M from"node:fs/promises";import{homedir as OW}from"node:os";import*as g from"node:path";import{promisify as GW}from"node:util";var qb=GW(XW),u=E("General"),F1={url:"https://github.com/anthropics/skills.git",branch:"main",defaultSkills:["skill-creator"]};class Z4{skillsDir;constructor($){this.skillsDir=$||g.join(OW(),".blade","skills")}async isInstalled($){let b=g.join(this.skillsDir,$,"SKILL.md");try{return await M.access(b),!0}catch{return!1}}async isGitAvailable(){try{return await qb("git --version"),!0}catch{return!1}}async installOfficialSkill($){let{url:b,branch:w}=F1,W=g.join(this.skillsDir,$),V=g.join(this.skillsDir,`.tmp-${$}-${Date.now()}`);try{if(!await this.isGitAvailable())return u.warn("Git not available, skipping skill installation"),!1;u.info(`Installing official skill: ${$}...`),await M.mkdir(this.skillsDir,{recursive:!0,mode:493}),await qb(`git clone --depth 1 --branch ${w} --single-branch ${b} "${V}"`,{timeout:30000});let Q=g.join(V,"skills",$);try{await M.access(Q)}catch{return u.warn(`Skill ${$} not found in official repository`),await M.rm(V,{recursive:!0,force:!0}),!1}try{await M.rm(W,{recursive:!0,force:!0})}catch{}return await M.cp(Q,W,{recursive:!0}),await M.rm(V,{recursive:!0,force:!0}),u.info(`Successfully installed: ${$}`),!0}catch(Q){try{await M.rm(V,{recursive:!0,force:!0})}catch{}return u.warn(`Failed to install ${$}: ${Q instanceof Error?Q.message:"Unknown error"}`),!1}}async ensureDefaultSkillsInstalled(){await M.mkdir(this.skillsDir,{recursive:!0,mode:493});for(let $ of F1.defaultSkills)if(!await this.isInstalled($))await this.installOfficialSkill($)}async installFromRepo($,b){let w=b||this.extractRepoName($),W=g.join(this.skillsDir,w),V=g.join(this.skillsDir,`.tmp-repo-${w}-${Date.now()}`);try{if(!await this.isGitAvailable())return u.warn("Git not available, cannot install from repo"),!1;u.info(`Installing skill from repo: ${$}...`),await M.mkdir(this.skillsDir,{recursive:!0,mode:493}),await qb(`git clone --depth 1 "${$}" "${V}"`,{timeout:60000});let Q=g.join(V,"SKILL.md");try{await M.access(Q)}catch{return u.warn(`No SKILL.md found in repository ${$}`),await M.rm(V,{recursive:!0,force:!0}),!1}await M.rm(W,{recursive:!0,force:!0}),await M.rename(V,W);try{await M.rm(g.join(W,".git"),{recursive:!0,force:!0})}catch{}return u.info(`Successfully installed skill from repo: ${w}`),!0}catch(Q){try{await M.rm(V,{recursive:!0,force:!0})}catch{}return u.warn(`Failed to install from repo ${$}: ${Q instanceof Error?Q.message:"Unknown error"}`),!1}}async installFromLocal($,b,w=!0){let W=b||g.basename($),V=g.join(this.skillsDir,W);try{let Q=g.resolve($);try{await M.access(Q)}catch{return u.warn(`Local path does not exist: ${Q}`),!1}let Z=g.join(Q,"SKILL.md");try{await M.access(Z)}catch{return u.warn(`No SKILL.md found in local path: ${Q}`),!1}if(u.info(`Installing skill from local path: ${Q}...`),await M.mkdir(this.skillsDir,{recursive:!0,mode:493}),await M.rm(V,{recursive:!0,force:!0}),w)await M.symlink(Q,V,"dir"),u.info(`Created symlink for skill: ${W}`);else await M.cp(Q,V,{recursive:!0}),u.info(`Copied skill to: ${W}`);return!0}catch(Q){return u.warn(`Failed to install from local path ${$}: ${Q instanceof Error?Q.message:"Unknown error"}`),!1}}extractRepoName($){return $.match(/\/([^/]+?)(\.git)?$/)?.[1]||"unknown-skill"}async installAllOfficialSkills(){let{url:$,branch:b}=F1,w=g.join(this.skillsDir,`.tmp-all-${Date.now()}`),W=[],V=[];try{if(!await this.isGitAvailable())return u.warn("Git not available, skipping skill installation"),{installed:W,failed:V};await M.mkdir(this.skillsDir,{recursive:!0,mode:493}),u.info("Cloning official skills repository..."),await qb(`git clone --depth 1 --branch ${b} --single-branch ${$} "${w}"`,{timeout:60000});let Q=g.join(w,"skills"),Z=await M.readdir(Q,{withFileTypes:!0});for(let J of Z){if(!J.isDirectory())continue;let Y=J.name,X=g.join(Q,Y),O=g.join(this.skillsDir,Y);try{await M.access(g.join(X,"SKILL.md")),await M.rm(O,{recursive:!0,force:!0}),await M.cp(X,O,{recursive:!0}),u.info(`Installed: ${Y}`),W.push(Y)}catch(G){u.warn(`Failed to install ${Y}`),V.push(Y)}}await M.rm(w,{recursive:!0,force:!0})}catch(Q){try{await M.rm(w,{recursive:!0,force:!0})}catch{}u.warn(`Failed to install skills: ${Q instanceof Error?Q.message:"Unknown error"}`)}return{installed:W,failed:V}}}var C1=null;function J4($){if(!C1)C1=new Z4($);return C1}import*as m0 from"node:fs/promises";import*as Ab from"node:path";import{parse as BW}from"yaml";var KW=/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/,qW=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]?$/,Y4=1024;function AW($){if(!$)return;if(typeof $==="string")return $.split(",").map((b)=>b.trim()).filter(Boolean);if(Array.isArray($))return $.map((b)=>String(b).trim()).filter(Boolean);return}function X4($){if($===void 0)return;if(typeof $==="boolean")return $;if(typeof $==="string"){let b=$.toLowerCase().trim();if(b==="true"||b==="yes"||b==="1")return!0;if(b==="false"||b==="no"||b==="0")return!1}return}function FW($,b){if(!$.name)return{valid:!1,error:"Missing required field: name"};if(!qW.test($.name))return{valid:!1,error:`Invalid name "${$.name}": must be lowercase letters, numbers, and hyphens only, 1-64 characters`};if(!$.description)return{valid:!1,error:"Missing required field: description"};if($.description.length>Y4)return{valid:!1,error:`Description too long: ${$.description.length} characters (max ${Y4})`};let w;if($.model)w=$.model==="inherit"?"inherit":$.model;return{valid:!0,metadata:{name:$.name,description:$.description.trim(),allowedTools:AW($["allowed-tools"]),version:$.version,argumentHint:$["argument-hint"]?.trim(),userInvocable:X4($["user-invocable"]),disableModelInvocation:X4($["disable-model-invocation"]),model:w,whenToUse:$.when_to_use?.trim()}}}function O4($,b,w){let W=$.match(KW);if(!W)return{success:!1,error:"Invalid SKILL.md format: missing YAML frontmatter (must start with ---)"};let[,V,Q]=W,Z;try{Z=BW(V)}catch(X){return{success:!1,error:`Failed to parse YAML frontmatter: ${X instanceof Error?X.message:String(X)}`}}let J=FW(Z,b);if(!J.valid)return{success:!1,error:J.error};let Y=Ab.dirname(b);return{success:!0,content:{metadata:{...J.metadata,path:b,basePath:Y,source:w},instructions:Q.trim()}}}async function Fb($,b){try{let w=await m0.readFile($,"utf-8");return O4(w,$,b)}catch(w){if(n(w)==="ENOENT")return{success:!1,error:`File not found: ${$}`};return{success:!1,error:`Failed to read file: ${w instanceof Error?w.message:String(w)}`}}}async function G4($){try{let b=await m0.readFile($.path,"utf-8"),w=O4(b,$.path,$.source);return w.success?w.content:null}catch{return null}}async function B4($){try{return await m0.access(Ab.join($,"SKILL.md")),!0}catch{return!1}}var CW={userSkillsDir:y$.join(K4(),".blade","skills"),projectSkillsDir:".blade/skills",claudeUserSkillsDir:y$.join(K4(),".claude","skills"),claudeProjectSkillsDir:".claude/skills",cwd:process.cwd()},Cb=null;class U1{skills=new Map;pluginSkills=new Map;config;initialized=!1;constructor($){this.config={...CW,...$}}static getInstance($){if(!Cb)Cb=new U1($);return Cb}static resetInstance(){Cb=null}async initialize(){if(this.initialized)return{skills:Array.from(this.skills.values()),errors:[]};let $=[],b=[];try{await J4(this.config.userSkillsDir).ensureDefaultSkillsInstalled()}catch(Y){$.push({path:"SkillInstaller",error:`Failed to install default skills: ${Y instanceof Error?Y.message:"Unknown error"}`})}this.loadBuiltinSkills();let w=await this.scanDirectory(this.config.claudeUserSkillsDir,"user");b.push(...w.skills),$.push(...w.errors);let W=await this.scanDirectory(this.config.userSkillsDir,"user");b.push(...W.skills),$.push(...W.errors);let V=y$.isAbsolute(this.config.claudeProjectSkillsDir)?this.config.claudeProjectSkillsDir:y$.join(this.config.cwd,this.config.claudeProjectSkillsDir),Q=await this.scanDirectory(V,"project");b.push(...Q.skills),$.push(...Q.errors);let Z=y$.isAbsolute(this.config.projectSkillsDir)?this.config.projectSkillsDir:y$.join(this.config.cwd,this.config.projectSkillsDir),J=await this.scanDirectory(Z,"project");b.push(...J.skills),$.push(...J.errors);for(let Y of b)this.skills.set(Y.name,Y);return this.initialized=!0,{skills:Array.from(this.skills.values()),errors:$}}loadBuiltinSkills(){this.skills.set(Kb.name,Kb)}async scanDirectory($,b){let w=[],W=[];try{await Ub.access($)}catch{return{skills:w,errors:W}}try{let V=await Ub.readdir($,{withFileTypes:!0});for(let Q of V){if(!Q.isDirectory())continue;let Z=y$.join($,Q.name),J=y$.join(Z,"SKILL.md");if(!await B4(Z))continue;let Y=await Fb(J,b);if(Y.success&&Y.content)w.push(Y.content.metadata);else W.push({path:J,error:Y.error||"Unknown error"})}}catch(V){W.push({path:$,error:`Failed to scan directory: ${V instanceof Error?V.message:String(V)}`})}return{skills:w,errors:W}}getAll(){return Array.from(this.skills.values())}get($){return this.skills.get($)}has($){return this.skills.has($)}async loadContent($){let b=this.skills.get($);if(!b)return null;if(b.source==="builtin")return this.loadBuiltinContent($);return G4(b)}loadBuiltinContent($){switch($){case"skill-creator":return Q4();default:return null}}getModelInvocableSkills(){return Array.from(this.skills.values()).filter(($)=>!$.disableModelInvocation)}getUserInvocableSkills(){return Array.from(this.skills.values()).filter(($)=>$.userInvocable===!0)}generateAvailableSkillsList(){let $=this.getModelInvocableSkills();if($.length===0)return"";let b=[];for(let w of $){let W=w.description.length>100?`${w.description.substring(0,97)}...`:w.description,V=w.argumentHint?`${w.name} ${w.argumentHint}`:w.name;b.push(`- ${V}: ${W}`)}return b.join(`
231
+ `)}get size(){return this.skills.size}async refresh(){return this.skills.clear(),this.pluginSkills.clear(),this.initialized=!1,this.initialize()}registerPluginSkill($){this.pluginSkills.set($.namespacedName,$),this.skills.set($.namespacedName,$.metadata)}findPluginSkill($){let b=this.pluginSkills.get($);if(b)return b;let w=[];for(let W of this.pluginSkills.values())if(W.originalName===$)w.push(W);if(w.length===1)return w[0];return}getAllPluginSkills(){return Array.from(this.pluginSkills.values())}clearPluginSkills(){for(let $ of this.pluginSkills.values())this.skills.delete($.namespacedName);this.pluginSkills.clear()}getPluginSkillCount(){return this.pluginSkills.size}}function _$($){return U1.getInstance($)}async function Rb($){return _$($).initialize()}var UW="Skill",RW=/<available_skills>\s*<\/available_skills>/;function Hb($){let w=_$().generateAvailableSkillsList();if(!w)return $;return $.map((W)=>{if(W.name!==UW)return W;let V=W.description.replace(RW,`<available_skills>
348
232
  ${w}
349
- </available_skills>`);if(W===V.description)return V;return{...V,description:W}})}import{execSync as r5}from"child_process";import*as A0 from"os";import*as q0 from"path";function a5(){let $=process.cwd(),b=o5($);return{workingDirectory:$,projectRoot:b,platform:`${A0.platform()} (${A0.arch()})`,nodeVersion:process.version,currentDate:new Date().toISOString().split("T")[0],homeDirectory:A0.homedir()}}function d0(){let $=a5();return`# Environment Context
233
+ </available_skills>`);if(V===W.description)return W;return{...W,description:V}})}import{execSync as HW}from"child_process";import*as R0 from"os";import*as U0 from"path";function _W(){let $=process.cwd(),b=DW($);return{workingDirectory:$,projectRoot:b,platform:`${R0.platform()} (${R0.arch()})`,nodeVersion:process.version,currentDate:new Date().toISOString().split("T")[0],homeDirectory:R0.homedir()}}function _b(){let $=_W();return`# Environment Context
350
234
 
351
235
  ## Working Directory
352
236
  **Current**: \`${$.workingDirectory}\`
@@ -364,7 +248,7 @@ When using file tools (read, write, edit), provide **absolute paths**:
364
248
  - ❌ Incorrect: \`/package.json\` (root directory)
365
249
  - ❌ Incorrect: \`package.json\` (relative path without context)
366
250
 
367
- **Always use** \`${$.workingDirectory}/\` as the base for file paths.`}function o5($){let b=$;while(b!==q0.dirname(b)){if(O4(q0.join(b,".git")))return b;if(O4(q0.join(b,"package.json")))return b;b=q0.dirname(b)}return $}function O4($){try{return r5(`test -e "${$}"`,{stdio:"ignore"}),!0}catch{return!1}}var G4=`You are Blade Code, an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
251
+ **Always use** \`${$.workingDirectory}/\` as the base for file paths.`}function DW($){let b=$;while(b!==U0.dirname(b)){if(q4(U0.join(b,".git")))return b;if(q4(U0.join(b,"package.json")))return b;b=U0.dirname(b)}return $}function q4($){try{return HW(`test -e "${$}"`,{stdio:"ignore"}),!0}catch{return!1}}var A4=`You are Blade Code, an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
368
252
 
369
253
  IMPORTANT: Assist with authorized security testing, defensive security, CTF challenges, and educational contexts. Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes. Dual-use security tools (C2 frameworks, credential testing, exploit development) require clear authorization context: pentesting engagements, CTF competitions, security research, or defensive use cases.
370
254
  IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.
@@ -522,7 +406,7 @@ assistant: Clients are marked as failed in the \`connectToServer\` function in s
522
406
  </example>
523
407
 
524
408
  # Language Requirement
525
- {{LANGUAGE_INSTRUCTION}}`,B4=`You are in **PLAN MODE** - a read-only research phase for designing implementation plans.
409
+ {{LANGUAGE_INSTRUCTION}}`,F4=`You are in **PLAN MODE** - a read-only research phase for designing implementation plans.
526
410
 
527
411
  ## Core Objective
528
412
 
@@ -562,69 +446,69 @@ Your plan should include:
562
446
  3. **Steps** - Detailed implementation steps with file paths
563
447
  4. **Testing** - How to verify changes
564
448
  5. **Risks** - Potential issues and mitigations
565
- `;function u$($){return`<system-reminder>Plan mode is active. You MUST NOT make any file changes or run non-readonly tools. Research only, then call ExitPlanMode with your plan.</system-reminder>
449
+ `;function c0($){return`<system-reminder>Plan mode is active. You MUST NOT make any file changes or run non-readonly tools. Research only, then call ExitPlanMode with your plan.</system-reminder>
566
450
 
567
- `+$}var e5=/<available_skills>\s*<\/available_skills>/;async function U0($={}){let{projectPath:b,replaceDefault:w,append:V,mode:W,includeEnvironment:Q=!0,language:Z}=$,Y=[],J=[];if(Q){let q=d0();if(q)Y.push(q),J.push({name:"environment",loaded:!0,length:q.length})}let X=W===v.PLAN,O,G;if(X)O=B4,G="plan_mode_prompt";else O=w??G4,G=w?"replace_default":"default";if(Y.push(O),J.push({name:G,loaded:!0,length:O.length}),b){let q=await V7(b);if(q)Y.push(q),J.push({name:"blade_md",loaded:!0,length:q.length});else J.push({name:"blade_md",loaded:!1})}if(V?.trim())Y.push(V.trim()),J.push({name:"append",loaded:!0,length:V.trim().length});let B=Y.join(`
451
+ `+$}var EW=/<available_skills>\s*<\/available_skills>/;async function $0($={}){let{projectPath:b,replaceDefault:w,append:W,mode:V,includeEnvironment:Q=!0,language:Z}=$,J=[],Y=[];if(Q){let K=_b();if(K)J.push(K),Y.push({name:"environment",loaded:!0,length:K.length})}let X=V===z.PLAN,O,G;if(X)O=F4,G="plan_mode_prompt";else O=w??A4,G=w?"replace_default":"default";if(J.push(O),Y.push({name:G,loaded:!0,length:O.length}),b){let K=await yW(b);if(K)J.push(K),Y.push({name:"blade_md",loaded:!0,length:K.length});else Y.push({name:"blade_md",loaded:!1})}if(W?.trim())J.push(W.trim()),Y.push({name:"append",loaded:!0,length:W.trim().length});let B=J.join(`
568
452
 
569
453
  ---
570
454
 
571
- `);return B=$7(B),B=w7(B,Z),{prompt:B,sources:J}}function $7($){let w=_$().generateAvailableSkillsList();if(!w)return $;return $.replace(e5,`<available_skills>
455
+ `);return B=jW(B),B=SW(B,Z),{prompt:B,sources:Y}}function jW($){let w=_$().generateAvailableSkillsList();if(!w)return $;return $.replace(EW,`<available_skills>
572
456
  ${w}
573
- </available_skills>`)}var b7={"zh-CN":"Chinese (Simplified Chinese)","zh-TW":"Chinese (Traditional Chinese)","en-US":"English","en-GB":"English (British)","ja-JP":"Japanese","ko-KR":"Korean","es-ES":"Spanish","fr-FR":"French","de-DE":"German","pt-BR":"Portuguese (Brazilian)","ru-RU":"Russian"};function w7($,b){let w=b||"zh-CN",V=b7[w]||w,W=`IMPORTANT: Always respond in ${V}. All your responses must be in ${V}.`;return $.replace("{{LANGUAGE_INSTRUCTION}}",W)}async function V7($){let b=t5.join($,"BLADE.md");try{return(await K4.readFile(b,"utf-8")).trim()||null}catch{return null}}import*as R2 from"os";import*as E2 from"path";import{basename as B7,extname as K7}from"path";import{z as Hb}from"zod";function g$(){return!1}function q4(){throw Error("ACP mode is not available")}import{existsSync as j1,readFileSync as W7,unlinkSync as Q7,writeFileSync as Z7}from"fs";import{dirname as Y7}from"path";import{mkdirSync as J7}from"fs";var N$=N("Tool");class k${static instance=null;config={enabled:!1};checkpoints=new Map;checkpointOrder=[];currentFileSnapshots=new Map;pendingChanges=[];constructor(){}static getInstance(){if(!k$.instance)k$.instance=new k$;return k$.instance}static resetInstance(){k$.instance=null}configure($){if(this.config={...this.config,...$},!this.config.enabled)this.clear();N$.debug(`[CheckpointService] Configured: enabled=${this.config.enabled}`)}isEnabled(){return this.config.enabled}clear(){this.checkpoints.clear(),this.checkpointOrder=[],this.currentFileSnapshots.clear(),this.pendingChanges=[],N$.debug("[CheckpointService] Cleared all checkpoints")}shouldExclude($){if(!this.config.excludePatterns||this.config.excludePatterns.length===0)return!1;return this.config.excludePatterns.some((b)=>{if(b.includes("*"))return new RegExp("^"+b.replace(/\*/g,".*")+"$").test($);return $.includes(b)})}captureSnapshot($){let b=j1($),w=null;if(b)try{w=W7($,"utf-8")}catch{w=null}return{filePath:$,content:w,exists:b,timestamp:new Date}}trackFileChange($,b){if(!this.config.enabled)return;if(this.shouldExclude($)){N$.debug(`[CheckpointService] Excluded file: ${$}`);return}let w=this.currentFileSnapshots.get($)||null,V=this.captureSnapshot($),W={filePath:$,operation:b,beforeSnapshot:w,afterSnapshot:V,timestamp:new Date};this.pendingChanges.push(W),this.currentFileSnapshots.set($,V),N$.debug(`[CheckpointService] Tracked ${b}: ${$}`)}captureBeforeWrite($){if(!this.config.enabled)return;if(this.shouldExclude($))return;if(!this.currentFileSnapshots.has($)){let b=this.captureSnapshot($);this.currentFileSnapshots.set($,b),N$.debug(`[CheckpointService] Captured before-write snapshot: ${$}`)}}createCheckpoint($,b){if(!this.config.enabled)return;let w={messageUuid:$,messageRole:b,timestamp:new Date,fileChanges:[...this.pendingChanges],fileSnapshots:new Map(this.currentFileSnapshots)};if(this.checkpoints.set($,w),this.checkpointOrder.push($),this.pendingChanges=[],this.config.maxCheckpoints&&this.checkpointOrder.length>this.config.maxCheckpoints){let V=this.checkpointOrder.shift();if(V)this.checkpoints.delete(V)}N$.debug(`[CheckpointService] Created checkpoint: ${$} (${b})`)}getCheckpoint($){return this.checkpoints.get($)}getAllCheckpoints(){return this.checkpointOrder.map(($)=>this.checkpoints.get($)).filter(Boolean)}async rewindFiles($){if(!this.config.enabled)return{success:!1,restoredFiles:[],deletedFiles:[],errors:[{filePath:"",error:"File checkpointing is not enabled"}]};let b=this.checkpoints.get($);if(!b)return{success:!1,restoredFiles:[],deletedFiles:[],errors:[{filePath:"",error:`Checkpoint not found: ${$}`}]};let w=[],V=[],W=[],Q=this.checkpointOrder.indexOf($),Z=this.checkpointOrder.slice(Q+1),Y=new Map;for(let J=Z.length-1;J>=0;J--){let X=Z[J],O=this.checkpoints.get(X);if(!O)continue;for(let G of O.fileChanges)if(!Y.has(G.filePath)&&G.beforeSnapshot)Y.set(G.filePath,G.beforeSnapshot)}for(let[J,X]of b.fileSnapshots)if(!Y.has(J))Y.set(J,X);for(let[J,X]of Y)try{if(X.exists&&X.content!==null){let O=Y7(J);if(!j1(O))J7(O,{recursive:!0});Z7(J,X.content,"utf-8"),w.push(J),N$.debug(`[CheckpointService] Restored: ${J}`)}else if(!X.exists&&j1(J))Q7(J),V.push(J),N$.debug(`[CheckpointService] Deleted: ${J}`)}catch(O){let G=O instanceof Error?O.message:String(O);W.push({filePath:J,error:G}),N$.error(`[CheckpointService] Failed to restore ${J}: ${G}`)}for(let J of Z)this.checkpoints.delete(J);return this.checkpointOrder=this.checkpointOrder.slice(0,Q+1),this.currentFileSnapshots=new Map(b.fileSnapshots),this.pendingChanges=[],N$.info(`[CheckpointService] Rewound to ${$}: restored=${w.length}, deleted=${V.length}, errors=${W.length}`),{success:W.length===0,restoredFiles:w,deletedFiles:V,errors:W}}getChangedFilesSince($){let b=this.checkpointOrder.indexOf($);if(b===-1)return[];let w=new Set,V=this.checkpointOrder.slice(b+1);for(let W of V){let Q=this.checkpoints.get(W);if(!Q)continue;for(let Z of Q.fileChanges)w.add(Z.filePath)}return Array.from(w)}getStatistics(){return{checkpointCount:this.checkpoints.size,trackedFileCount:this.currentFileSnapshots.size,pendingChangeCount:this.pendingChanges.length}}}function S$(){return k$.getInstance()}import*as R$ from"fs/promises";class A4{async readTextFile($){return R$.readFile($,"utf-8")}async writeTextFile($,b){await R$.writeFile($,b,"utf-8")}async exists($){try{return await R$.access($),!0}catch{return!1}}async readBinaryFile($){return R$.readFile($)}async stat($){try{let b=await R$.stat($);return{size:b.size,isDirectory:b.isDirectory(),isFile:b.isFile(),mtime:b.mtime}}catch{return null}}async mkdir($,b){await R$.mkdir($,{recursive:b?.recursive??!1,mode:b?.mode??493})}}var X7=new A4;function C0(){return X7}import{isAbsolute as U4}from"path";import{z as i}from"zod";var P={filePath:($)=>i.string().min(1,"File path is required").refine((b)=>U4(b),{message:"Path must be absolute"}).describe($?.description||"Absolute file path"),encoding:()=>i.enum(["utf8","base64","binary"]).default("utf8").describe("File encoding"),timeout:($=1000,b=300000,w=30000)=>i.number().int("Must be an integer").min($,`Cannot be less than ${$}ms`).max(b,`Cannot exceed ${b}ms`).default(w).describe(`Timeout in milliseconds (default ${w}ms)`),pattern:($)=>i.string().min(1,"Pattern is required").describe($?.description||"Regex or glob pattern"),glob:($)=>i.string().min(1,"Glob pattern is required").describe($?.description||'Glob pattern (e.g., "*.js", "**/*.ts")'),lineNumber:($)=>i.number().int("Line number must be an integer").min($?.min??0,`Line number cannot be less than ${$?.min??0}`).describe($?.description||"Line number"),lineLimit:($)=>i.number().int("Line count must be an integer").min($?.min??1,`Line count cannot be less than ${$?.min??1}`).max($?.max??1e4,`Line count cannot exceed ${$?.max??1e4}`).describe($?.description||"Limit on lines to read"),workingDirectory:()=>i.string().min(1,"Working directory is required").refine(($)=>U4($),{message:"Path must be absolute"}).describe("Absolute working directory"),environment:()=>i.record(i.string(),i.string()).describe("Environment variables (key-value)").optional(),outputMode:($,b)=>{let w=i.enum($);return b?w.default(b):w},flag:($)=>i.boolean().default($?.defaultValue??!1).describe($?.description||"Boolean flag"),url:($)=>i.string().url("Must be a valid URL").describe($?.description||"URL"),port:()=>i.number().int("Port must be an integer").min(1,"Port cannot be less than 1").max(65535,"Port cannot exceed 65535").describe("Port number"),command:($)=>i.string().min(1,"Command is required").describe($?.description||"Command to execute"),sessionId:()=>i.string().min(1,"Session ID is required").uuid("Must be a valid UUID").optional().describe("Session identifier (UUID)"),nonNegativeInt:($)=>i.number().int("Must be an integer").min(0,"Cannot be negative").describe($?.description||"Non-negative integer"),positiveInt:($)=>i.number().int("Must be an integer").min(1,"Must be greater than 0").describe($?.description||"Positive integer")};import*as N1 from"diff";function C4($,b,w=4){if($===b)return null;let V=N1.createPatch("file",$,b,"","",{context:w}),W=V.split(`
574
- `),Q=1;for(let Z of W){let Y=Z.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);if(Y){Q=parseInt(Y[1],10);break}}return`
457
+ </available_skills>`)}var NW={"zh-CN":"Chinese (Simplified Chinese)","zh-TW":"Chinese (Traditional Chinese)","en-US":"English","en-GB":"English (British)","ja-JP":"Japanese","ko-KR":"Korean","es-ES":"Spanish","fr-FR":"French","de-DE":"German","pt-BR":"Portuguese (Brazilian)","ru-RU":"Russian"};function SW($,b){let w=b||"zh-CN",W=NW[w]||w,V=`IMPORTANT: Always respond in ${W}. All your responses must be in ${W}.`;return $.replace("{{LANGUAGE_INSTRUCTION}}",V)}async function yW($){let b=LW.join($,"BLADE.md");try{return(await C4.readFile(b,"utf-8")).trim()||null}catch{return null}}import*as y2 from"os";import*as M2 from"path";import{basename as hW,extname as xW}from"path";import{z as Lb}from"zod";function i$(){return!1}function U4(){throw Error("ACP mode is not available")}import{existsSync as R1,readFileSync as MW,unlinkSync as zW,writeFileSync as vW}from"fs";import{dirname as TW}from"path";import{mkdirSync as kW}from"fs";var M$=E("Tool");class h${static instance=null;config={enabled:!1};checkpoints=new Map;checkpointOrder=[];currentFileSnapshots=new Map;pendingChanges=[];constructor(){}static getInstance(){if(!h$.instance)h$.instance=new h$;return h$.instance}static resetInstance(){h$.instance=null}configure($){if(this.config={...this.config,...$},!this.config.enabled)this.clear();M$.debug(`[CheckpointService] Configured: enabled=${this.config.enabled}`)}isEnabled(){return this.config.enabled}clear(){this.checkpoints.clear(),this.checkpointOrder=[],this.currentFileSnapshots.clear(),this.pendingChanges=[],M$.debug("[CheckpointService] Cleared all checkpoints")}shouldExclude($){if(!this.config.excludePatterns||this.config.excludePatterns.length===0)return!1;return this.config.excludePatterns.some((b)=>{if(b.includes("*"))return new RegExp("^"+b.replace(/\*/g,".*")+"$").test($);return $.includes(b)})}captureSnapshot($){let b=R1($),w=null;if(b)try{w=MW($,"utf-8")}catch{w=null}return{filePath:$,content:w,exists:b,timestamp:new Date}}trackFileChange($,b){if(!this.config.enabled)return;if(this.shouldExclude($)){M$.debug(`[CheckpointService] Excluded file: ${$}`);return}let w=this.currentFileSnapshots.get($)||null,W=this.captureSnapshot($),V={filePath:$,operation:b,beforeSnapshot:w,afterSnapshot:W,timestamp:new Date};this.pendingChanges.push(V),this.currentFileSnapshots.set($,W),M$.debug(`[CheckpointService] Tracked ${b}: ${$}`)}captureBeforeWrite($){if(!this.config.enabled)return;if(this.shouldExclude($))return;if(!this.currentFileSnapshots.has($)){let b=this.captureSnapshot($);this.currentFileSnapshots.set($,b),M$.debug(`[CheckpointService] Captured before-write snapshot: ${$}`)}}createCheckpoint($,b){if(!this.config.enabled)return;let w={messageUuid:$,messageRole:b,timestamp:new Date,fileChanges:[...this.pendingChanges],fileSnapshots:new Map(this.currentFileSnapshots)};if(this.checkpoints.set($,w),this.checkpointOrder.push($),this.pendingChanges=[],this.config.maxCheckpoints&&this.checkpointOrder.length>this.config.maxCheckpoints){let W=this.checkpointOrder.shift();if(W)this.checkpoints.delete(W)}M$.debug(`[CheckpointService] Created checkpoint: ${$} (${b})`)}getCheckpoint($){return this.checkpoints.get($)}getAllCheckpoints(){return this.checkpointOrder.map(($)=>this.checkpoints.get($)).filter(Boolean)}async rewindFiles($){if(!this.config.enabled)return{success:!1,restoredFiles:[],deletedFiles:[],errors:[{filePath:"",error:"File checkpointing is not enabled"}]};let b=this.checkpoints.get($);if(!b)return{success:!1,restoredFiles:[],deletedFiles:[],errors:[{filePath:"",error:`Checkpoint not found: ${$}`}]};let w=[],W=[],V=[],Q=this.checkpointOrder.indexOf($),Z=this.checkpointOrder.slice(Q+1),J=new Map;for(let Y=Z.length-1;Y>=0;Y--){let X=Z[Y],O=this.checkpoints.get(X);if(!O)continue;for(let G of O.fileChanges)if(!J.has(G.filePath)&&G.beforeSnapshot)J.set(G.filePath,G.beforeSnapshot)}for(let[Y,X]of b.fileSnapshots)if(!J.has(Y))J.set(Y,X);for(let[Y,X]of J)try{if(X.exists&&X.content!==null){let O=TW(Y);if(!R1(O))kW(O,{recursive:!0});vW(Y,X.content,"utf-8"),w.push(Y),M$.debug(`[CheckpointService] Restored: ${Y}`)}else if(!X.exists&&R1(Y))zW(Y),W.push(Y),M$.debug(`[CheckpointService] Deleted: ${Y}`)}catch(O){let G=O instanceof Error?O.message:String(O);V.push({filePath:Y,error:G}),M$.error(`[CheckpointService] Failed to restore ${Y}: ${G}`)}for(let Y of Z)this.checkpoints.delete(Y);return this.checkpointOrder=this.checkpointOrder.slice(0,Q+1),this.currentFileSnapshots=new Map(b.fileSnapshots),this.pendingChanges=[],M$.info(`[CheckpointService] Rewound to ${$}: restored=${w.length}, deleted=${W.length}, errors=${V.length}`),{success:V.length===0,restoredFiles:w,deletedFiles:W,errors:V}}getChangedFilesSince($){let b=this.checkpointOrder.indexOf($);if(b===-1)return[];let w=new Set,W=this.checkpointOrder.slice(b+1);for(let V of W){let Q=this.checkpoints.get(V);if(!Q)continue;for(let Z of Q.fileChanges)w.add(Z.filePath)}return Array.from(w)}getStatistics(){return{checkpointCount:this.checkpoints.size,trackedFileCount:this.currentFileSnapshots.size,pendingChangeCount:this.pendingChanges.length}}}function z$(){return h$.getInstance()}import*as D$ from"fs/promises";class R4{async readTextFile($){return D$.readFile($,"utf-8")}async writeTextFile($,b){await D$.writeFile($,b,"utf-8")}async exists($){try{return await D$.access($),!0}catch{return!1}}async readBinaryFile($){return D$.readFile($)}async stat($){try{let b=await D$.stat($);return{size:b.size,isDirectory:b.isDirectory(),isFile:b.isFile(),mtime:b.mtime}}catch{return null}}async mkdir($,b){await D$.mkdir($,{recursive:b?.recursive??!1,mode:b?.mode??493})}}var fW=new R4;function H0(){return fW}import{isAbsolute as H4}from"path";import{z as i}from"zod";var P={filePath:($)=>i.string().min(1,"File path is required").refine((b)=>H4(b),{message:"Path must be absolute"}).describe($?.description||"Absolute file path"),encoding:()=>i.enum(["utf8","base64","binary"]).default("utf8").describe("File encoding"),timeout:($=1000,b=300000,w=30000)=>i.number().int("Must be an integer").min($,`Cannot be less than ${$}ms`).max(b,`Cannot exceed ${b}ms`).default(w).describe(`Timeout in milliseconds (default ${w}ms)`),pattern:($)=>i.string().min(1,"Pattern is required").describe($?.description||"Regex or glob pattern"),glob:($)=>i.string().min(1,"Glob pattern is required").describe($?.description||'Glob pattern (e.g., "*.js", "**/*.ts")'),lineNumber:($)=>i.number().int("Line number must be an integer").min($?.min??0,`Line number cannot be less than ${$?.min??0}`).describe($?.description||"Line number"),lineLimit:($)=>i.number().int("Line count must be an integer").min($?.min??1,`Line count cannot be less than ${$?.min??1}`).max($?.max??1e4,`Line count cannot exceed ${$?.max??1e4}`).describe($?.description||"Limit on lines to read"),workingDirectory:()=>i.string().min(1,"Working directory is required").refine(($)=>H4($),{message:"Path must be absolute"}).describe("Absolute working directory"),environment:()=>i.record(i.string(),i.string()).describe("Environment variables (key-value)").optional(),outputMode:($,b)=>{let w=i.enum($);return b?w.default(b):w},flag:($)=>i.boolean().default($?.defaultValue??!1).describe($?.description||"Boolean flag"),url:($)=>i.string().url("Must be a valid URL").describe($?.description||"URL"),port:()=>i.number().int("Port must be an integer").min(1,"Port cannot be less than 1").max(65535,"Port cannot exceed 65535").describe("Port number"),command:($)=>i.string().min(1,"Command is required").describe($?.description||"Command to execute"),sessionId:()=>i.string().min(1,"Session ID is required").uuid("Must be a valid UUID").optional().describe("Session identifier (UUID)"),nonNegativeInt:($)=>i.number().int("Must be an integer").min(0,"Cannot be negative").describe($?.description||"Non-negative integer"),positiveInt:($)=>i.number().int("Must be an integer").min(1,"Must be greater than 0").describe($?.description||"Positive integer")};import*as H1 from"diff";function _4($,b,w=4){if($===b)return null;let W=H1.createPatch("file",$,b,"","",{context:w}),V=W.split(`
458
+ `),Q=1;for(let Z of V){let J=Z.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);if(J){Q=parseInt(J[1],10);break}}return`
575
459
  <<<DIFF>>>
576
- ${JSON.stringify({patch:V,startLine:Math.max(1,Q-w),matchLine:Q})}
460
+ ${JSON.stringify({patch:W,startLine:Math.max(1,Q-w),matchLine:Q})}
577
461
  <<</DIFF>>>
578
- `}function F4($,b,w,V,W=4){let Q=$.indexOf(w);if(Q===-1)return null;let Y=$.substring(0,Q).split(`
579
- `).length-1,J=$.split(`
462
+ `}function D4($,b,w,W,V=4){let Q=$.indexOf(w);if(Q===-1)return null;let J=$.substring(0,Q).split(`
463
+ `).length-1,Y=$.split(`
580
464
  `),X=b.split(`
581
465
  `),O=w.split(`
582
- `),G=V.split(`
583
- `),B=Math.max(0,Y-W),q=Math.min(J.length,Y+O.length+W),U=Math.min(X.length,Y+G.length+W),K=J.slice(B,q).join(`
584
- `),_=X.slice(B,U).join(`
585
- `),C=N1.createPatch("file",K,_,"","",{context:W});return`
466
+ `),G=W.split(`
467
+ `),B=Math.max(0,J-V),K=Math.min(Y.length,J+O.length+V),C=Math.min(X.length,J+G.length+V),q=Y.slice(B,K).join(`
468
+ `),F=X.slice(B,C).join(`
469
+ `),U=H1.createPatch("file",q,F,"","",{context:V});return`
586
470
  <<<DIFF>>>
587
- ${JSON.stringify({patch:C,startLine:B+1,matchLine:Y+1})}
471
+ ${JSON.stringify({patch:U,startLine:B+1,matchLine:J+1})}
588
472
  <<</DIFF>>>
589
- `}function H4($){return $.replace(/\\+(n|t|r|'|"|`|\\|\n)/g,(b,w)=>{switch(w){case"n":return`
473
+ `}function L4($){return $.replace(/\\+(n|t|r|'|"|`|\\|\n)/g,(b,w)=>{switch(w){case"n":return`
590
474
  `;case"t":return"\t";case"r":return"\r";case"'":return"'";case'"':return'"';case"`":return"`";case"\\":return"\\";case`
591
475
  `:return`
592
- `;default:return b}})}function _4($,b){let w=b.split(`
593
- `);if(w.length===1)return null;let W=w[0].match(/^(\s+)/);if(!W)return null;let Q=W[1],Y=w.map((X)=>{if(X.startsWith(Q))return X.slice(Q.length);return X}).join(`
594
- `),J=$.split(`
595
- `);for(let X=0;X<=J.length-w.length;X++){let O=J[X].match(/^(\s+)/),G=O?O[1]:"",B=J.slice(X,X+w.length);if(B.map((K)=>{if(K.startsWith(G))return K.slice(G.length);return K}).join(`
596
- `)===Y)return B.join(`
597
- `)}return null}import{promises as Fb}from"node:fs";var u0=N("Tool");class b${static instance=null;accessedFiles=new Map;constructor(){}static getInstance(){if(!b$.instance)b$.instance=new b$;return b$.instance}async recordFileRead($,b){try{let w=await Fb.stat($),V={filePath:$,accessTime:Date.now(),mtime:w.mtimeMs,sessionId:b,lastOperation:"read"};this.accessedFiles.set($,V),u0.debug(`记录文件读取: ${$}`)}catch(w){u0.warn(`记录文件读取失败: ${$}`,w)}}async recordFileEdit($,b,w="edit"){try{let V=await Fb.stat($),W={filePath:$,accessTime:Date.now(),mtime:V.mtimeMs,sessionId:b,lastOperation:w};this.accessedFiles.set($,W),u0.debug(`记录文件${w==="edit"?"编辑":"写入"}: ${$}`)}catch(V){u0.warn(`记录文件${w==="edit"?"编辑":"写入"}失败: ${$}`,V)}}hasFileBeenRead($,b){let w=this.accessedFiles.get($);if(!w)return!1;if(b&&w.sessionId!==b)return!1;return!0}async checkFileModification($){let b=this.accessedFiles.get($);if(!b)return{modified:!1,message:"文件未被跟踪"};try{let w=await Fb.stat($);if(Math.abs(w.mtimeMs-b.mtime)>1)return{modified:!0,message:`文件在访问后被修改(访问时间: ${new Date(b.accessTime).toISOString()}, 当前修改时间: ${w.mtime.toISOString()})`};return{modified:!1}}catch(w){let V=w;if(V.code==="ENOENT")return{modified:!0,message:"文件已被删除"};return{modified:!1,message:`无法检查文件状态: ${V.message}`}}}async checkExternalModification($){let b=this.accessedFiles.get($);if(!b)return{isExternal:!1,message:"文件未被跟踪"};try{let w=await Fb.stat($);if(w.mtimeMs-b.mtime>2000)return{isExternal:!0,message:`文件在 ${new Date(b.accessTime).toISOString()} (${b.lastOperation}) 之后被外部程序修改(当前修改时间: ${w.mtime.toISOString()})`};return{isExternal:!1}}catch(w){let V=w;if(V.code==="ENOENT")return{isExternal:!0,message:"文件已被删除"};return u0.warn(`检查文件外部修改失败: ${$}`,w),{isExternal:!1,message:`无法检查文件状态: ${V.message}`}}}getFileRecord($){return this.accessedFiles.get($)}clearFileRecord($){this.accessedFiles.delete($)}clearAll(){this.accessedFiles.clear()}clearSession($){for(let[b,w]of this.accessedFiles.entries())if(w.sessionId===$)this.accessedFiles.delete(b)}getTrackedFiles(){return Array.from(this.accessedFiles.keys())}getTrackedFileCount(){return this.accessedFiles.size}static resetInstance(){b$.instance=null}}import*as D4 from"node:crypto";import{promises as M$}from"node:fs";import*as o$ from"node:path";import{execSync as O7}from"node:child_process";import*as S1 from"node:os";import*as a$ from"node:path";function G7($){return a$.resolve($).replace(/[/\\]/g,"-").replace(/:/g,"_")}function g0($){let b=S1.homedir(),w=G7($);return a$.join(b,".blade","projects",w)}function X$($,b){return a$.join(g0($),`${b}.jsonl`)}function R4($){try{return O7("git rev-parse --abbrev-ref HEAD",{cwd:$,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{return}}function m0(){return a$.join(S1.homedir(),".blade")}async function E4(){let{readdir:$}=await import("node:fs/promises");try{let b=a$.join(m0(),"projects");return(await $(b,{withFileTypes:!0})).filter((V)=>V.isDirectory()).map((V)=>V.name)}catch{return[]}}class c0{sessionId;enableCheckpoints;maxSnapshots;snapshotDir;trackedFileBackups=new Map;snapshots=[];constructor($){this.sessionId=$.sessionId,this.enableCheckpoints=$.enableCheckpoints??!0,this.maxSnapshots=$.maxSnapshots??10;let b=m0();this.snapshotDir=o$.join(b,"file-history",this.sessionId)}async initialize(){if(!this.enableCheckpoints)return;try{await M$.mkdir(this.snapshotDir,{recursive:!0,mode:493}),console.log(`[SnapshotManager] 初始化快照目录: ${this.snapshotDir}`)}catch($){throw console.warn("[SnapshotManager] 创建快照目录失败:",$),$}}async createSnapshot($,b){if(!this.enableCheckpoints)return console.log("[SnapshotManager] 检查点已禁用,跳过快照创建"),{backupFileName:"",version:0,backupTime:new Date};try{await M$.access($)}catch{return console.warn(`[SnapshotManager] 文件不存在,跳过快照: ${$}`),{backupFileName:"",version:0,backupTime:new Date}}let w=this.trackedFileBackups.get($),V=w?w.version+1:1,W=this.generateFileHash($,V),Q=o$.join(this.snapshotDir,`${W}@v${V}`);try{let Z=await M$.readFile($,{encoding:"utf-8"});await M$.writeFile(Q,Z,{encoding:"utf-8"});let Y={backupFileName:W,version:V,backupTime:new Date};return this.trackedFileBackups.set($,Y),this.snapshots.push({messageId:b,backupFileName:W,timestamp:new Date,filePath:$}),console.log(`[SnapshotManager] 创建快照: ${$} -> ${W}@v${V}`),await this.cleanupOldSnapshots($),Y}catch(Z){throw console.error(`[SnapshotManager] 创建快照失败: ${$}`,Z),Z}}async restoreSnapshot($,b){let w=this.snapshots.slice().reverse().find((Q)=>Q.messageId===b&&Q.filePath===$);if(!w)throw Error(`未找到快照: messageId=${b}, filePath=${$}`);let V=this.trackedFileBackups.get($);if(!V)throw Error(`未找到文件追踪信息: ${$}`);let W=o$.join(this.snapshotDir,`${w.backupFileName}@v${V.version}`);try{let Q=await M$.readFile(W,{encoding:"utf-8"});await M$.writeFile($,Q,{encoding:"utf-8"}),console.log(`[SnapshotManager] 恢复快照: ${$} <- ${w.backupFileName}@v${V.version}`)}catch(Q){throw console.error(`[SnapshotManager] 恢复快照失败: ${$}`,Q),Q}}async listSnapshots($){return this.snapshots.filter((b)=>b.filePath===$)}async cleanupOldSnapshots($){let b=this.snapshots.filter((W)=>W.filePath===$);if(b.length<=this.maxSnapshots)return;let V=b.sort((W,Q)=>W.timestamp.getTime()-Q.timestamp.getTime()).slice(0,b.length-this.maxSnapshots);for(let W of V){let Q=this.trackedFileBackups.get(W.filePath);if(!Q)continue;let Z=o$.join(this.snapshotDir,`${W.backupFileName}@v${Q.version}`);try{await M$.unlink(Z),console.log(`[SnapshotManager] 删除旧快照: ${Z}`)}catch(J){console.warn(`[SnapshotManager] 删除快照失败: ${Z}`,J)}let Y=this.snapshots.indexOf(W);if(Y>-1)this.snapshots.splice(Y,1)}}async cleanup($=0){try{let b=await M$.readdir(this.snapshotDir);if(b.length<=$)return;let w=await Promise.all(b.map(async(W)=>{let Q=o$.join(this.snapshotDir,W),Z=await M$.stat(Q);return{file:W,mtime:Z.mtime.getTime()}}));w.sort((W,Q)=>Q.mtime-W.mtime);let V=w.slice($);for(let{file:W}of V){let Q=o$.join(this.snapshotDir,W);await M$.unlink(Q),console.log(`[SnapshotManager] 清理快照: ${Q}`)}}catch(b){console.warn("[SnapshotManager] 清理快照失败:",b)}}generateFileHash($,b){let w=D4.createHash("md5");return w.update(`${$}:${b}`),w.digest("hex").substring(0,16)}getSnapshotDir(){return this.snapshotDir}getSessionId(){return this.sessionId}getTrackedFileCount(){return this.trackedFileBackups.size}getSnapshotCount(){return this.snapshots.length}}var M1=E({name:"Edit",displayName:"File Edit",kind:"write",strict:!0,isConcurrencySafe:!1,schema:Hb.object({file_path:P.filePath({description:"Absolute path of the file to edit"}),old_string:Hb.string().min(1,"old_string cannot be empty").describe("String to replace"),new_string:Hb.string().describe("Replacement string (can be empty)"),replace_all:Hb.boolean().default(!1).describe("Replace all matches (default: first only)")}),description:{short:"Performs exact string replacements in files",long:"Performs exact string replacements in files.",usageNotes:["You must use your Read tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file.","When editing text from Read tool output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: spaces + line number + tab. Everything after that tab is the actual file content to match. Never include any part of the line number prefix in the old_string or new_string.","ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.","Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.","The edit will FAIL if old_string is not unique in the file. Either provide a larger string with more surrounding context to make it unique or use replace_all to change every instance of old_string.","Use replace_all for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance."]},async execute($,b){let{file_path:w,old_string:V,new_string:W,replace_all:Q}=$,{updateOutput:Z,sessionId:Y,messageId:J}=b,X=b.signal??new AbortController().signal;try{Z?.("Starting to read file...");let O=C0(),G=g$(),B;try{if(G)Z?.("通过 IDE 读取文件...");B=await O.readTextFile(w)}catch(y){let l=y;if(l.code==="ENOENT"||l.message?.includes("not found"))return{success:!1,llmContent:`File not found: ${w}`,displayContent:`❌ 文件不存在: ${w}`,error:{type:"execution_error",message:"文件不存在"}};throw y}if(typeof X.throwIfAborted==="function")X.throwIfAborted();if(Y){let y=b$.getInstance();if(!y.hasFileBeenRead(w,Y))return{success:!1,llmContent:"You must use your Read tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file.",displayContent:"\uD83D\uDCD6 我需要先读取文件内容,然后再进行编辑。",error:{type:"validation_error",message:"File not read before edit"},metadata:{requiresRead:!0}};let l=await y.checkExternalModification(w);if(l.isExternal)return{success:!1,llmContent:`The file has been modified by an external program since you last read it. You must use the Read tool again to see the current content before editing.
598
-
599
- Details: ${l.message}`,displayContent:`❌ 编辑失败:文件已被外部程序修改
600
-
601
- ${l.message}
602
-
603
- \uD83D\uDCA1 我需要重新读取文件内容后再编辑`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:l.message}}}}if(Y&&J)try{let y=new c0({sessionId:Y});await y.initialize(),await y.createSnapshot(w,J)}catch(y){console.warn("[EditTool] 创建快照失败:",y)}if(V===W)return{success:!1,llmContent:"New string is identical; no replacement needed",displayContent:"⚠️ 新字符串与旧字符串相同,无需进行替换",error:{type:"validation_error",message:"新旧字符串相同"}};let q=q7(B,V);if(!q.matched){let y=C7(B,V,w);return{success:!1,llmContent:y.llmContent,displayContent:y.displayContent,error:{type:"execution_error",message:"未找到匹配内容",details:y.metadata}}}let U=q.matched;if(q.strategy!=="exact")console.log(`[SmartEdit] 使用策略: ${q.strategy}`);let K=A7(B,U);if(K.length>1&&!Q){let y=B.split(`
604
- `),l=0,F$=[];for(let Q$=0;Q$<y.length;Q$++){let z0=y[Q$],Tw=l,kw=l+z0.length;for(let sb of K)if(sb>=Tw&&sb<kw){let W8=Math.max(0,Q$-1),Q8=Math.min(y.length-1,Q$+1),Z8=y.slice(W8,Q8+1).map((Y8)=>Y8.trim()).join(" ").slice(0,80);F$.push({line:Q$+1,column:sb-Tw+1,context:Z8})}l=kw+1}let nb=[`⚠️ EDIT PAUSED: old_string matches ${K.length} locations (must be unique).`,"","**Matches found at:**",...F$.map((Q$,z0)=>` ${z0+1}. Line ${Q$.line}`),"","**Action Required:** Add 3-5 lines of surrounding context to make old_string unique.","","**Tips for quick success:**","• Include the function/class name that wraps the target code","• Add 2-3 lines before and after the target","• Include unique comments or variable names nearby",`• Or use replace_all=true to change all ${K.length} occurrences`,"","\uD83E\uDD16 **Auto-retry expected** - This usually resolves in 1-2 attempts."].join(`
605
- `),V8=["⚠️ 编辑暂停:需要更精确的定位","",`在文件中找到 ${K.length} 处相似代码:`,...F$.map((Q$,z0)=>` • 第 ${Q$.line} 行 (匹配 ${z0+1}/${K.length})`),"","AI 正在自动调整,添加更多上下文以精确定位...","通常需要 1-2 次尝试即可成功","","\uD83D\uDCA1 如果多次失败,可能需要:"," • 包含函数/类名等独特标识符"," • 添加目标代码前后 3-5 行完整上下文",` • 或使用 replace_all=true 同时替换所有 ${K.length} 处匹配`].join(`
606
- `);return{success:!1,llmContent:nb,displayContent:V8,error:{type:"validation_error",message:"old_string is not unique",details:{matches:F$.map((Q$)=>({line:Q$.line,column:Q$.column})),count:K.length}}}}else Z?.(`找到 ${K.length} 个匹配项,开始替换...`);let _,C;if(Q)_=B.split(U).join(W),C=K.length;else{let y=B.indexOf(U);_=B.substring(0,y)+W+B.substring(y+U.length),C=1}if(typeof X.throwIfAborted==="function")X.throwIfAborted();let H=S$();if(H.captureBeforeWrite(w),G)Z?.("通过 IDE 写入文件...");if(await O.writeTextFile(w,_),H.trackFileChange(w,"modify"),Y)await b$.getInstance().recordFileEdit(w,Y,"edit");let F=await O.stat(w),M=F4(B,_,U,W,4),L=B7(w),R=C===1?`替换 1 处匹配到 ${L}`:`替换 ${C} 处匹配到 ${L}`,D={file_path:w,matches_found:K.length,replacements_made:C,replace_all:Q,old_string_length:V.length,new_string_length:W.length,original_size:B.length,new_size:_.length,size_diff:_.length-B.length,last_modified:F?.mtime instanceof Date?F.mtime.toISOString():void 0,snapshot_created:!!(Y&&J),session_id:Y,message_id:J,diff_snippet:M,summary:R,kind:"edit",oldContent:B,newContent:_},c=U7(D,M);return{success:!0,llmContent:{file_path:w,replacements:C,total_matches:K.length},displayContent:c,metadata:D}}catch(O){let G=O;if(G.name==="AbortError")return{success:!1,llmContent:"File edit aborted",displayContent:"⚠️ 文件编辑被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File edit failed: ${G.message}`,displayContent:`❌ 编辑文件失败: ${G.message}`,error:{type:"execution_error",message:G.message,details:G}}}},version:"2.0.0",category:"文件操作",tags:["file","edit","replace","modify"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let b=K7($.file_path);return b?`**/*${b}`:"**/*"}});function L4($){return $.replaceAll("‘","'").replaceAll("’","'").replaceAll("“",'"').replaceAll("”",'"')}function q7($,b){if($.includes(b))return{matched:b,strategy:"exact"};let w=L4(b),W=L4($).indexOf(w);if(W!==-1)return{matched:$.substring(W,W+b.length),strategy:"normalize_quotes"};let Q=H4(b);if(Q!==b&&$.includes(Q))return{matched:Q,strategy:"unescape"};let Z=_4($,b);if(Z)return{matched:Z,strategy:"flexible"};return{matched:null,strategy:"failed"}}function A7($,b){if(b.length===0)return[];let w=[],V=$.indexOf(b);while(V!==-1)w.push(V),V=$.indexOf(b,V+b.length);return w}function U7($,b){let{file_path:w,matches_found:V,replacements_made:W,replace_all:Q,size_diff:Z}=$,Y=`✅ 成功编辑文件: ${w}`;if(Y+=`
607
- \uD83D\uDCDD 替换了 ${W} 个匹配项`,!Q&&V>1)Y+=` (共找到 ${V} 个匹配项)`;if(Z!==0){let J=Z>0?`增加${Z}`:`减少${Math.abs(Z)}`;Y+=`
608
- \uD83D\uDCCA 文件大小${J}个字符`}if(b)Y+=b;return Y}function C7($,b,w){let V=$.split(`
609
- `),W=V.length,Q=F7($,b,3),Z=0,Y=Math.min(20,W);if(Q.length>0){let q=Q[0];Z=Math.max(0,q.lineNumber-10),Y=Math.min(W,q.lineNumber+10)}let X=V.slice(Z,Y).map((q,U)=>{return` ${(Z+U+1).toString().padStart(4)}: ${q}`}).join(`
476
+ `;default:return b}})}function E4($,b){let w=b.split(`
477
+ `);if(w.length===1)return null;let V=w[0].match(/^(\s+)/);if(!V)return null;let Q=V[1],J=w.map((X)=>{if(X.startsWith(Q))return X.slice(Q.length);return X}).join(`
478
+ `),Y=$.split(`
479
+ `);for(let X=0;X<=Y.length-w.length;X++){let O=Y[X].match(/^(\s+)/),G=O?O[1]:"",B=Y.slice(X,X+w.length);if(B.map((q)=>{if(q.startsWith(G))return q.slice(G.length);return q}).join(`
480
+ `)===J)return B.join(`
481
+ `)}return null}import{promises as Db}from"node:fs";var i0=E("Tool");class w${static instance=null;accessedFiles=new Map;constructor(){}static getInstance(){if(!w$.instance)w$.instance=new w$;return w$.instance}async recordFileRead($,b){try{let w=await Db.stat($),W={filePath:$,accessTime:Date.now(),mtime:w.mtimeMs,sessionId:b,lastOperation:"read"};this.accessedFiles.set($,W),i0.debug(`记录文件读取: ${$}`)}catch(w){i0.warn(`记录文件读取失败: ${$}`,w)}}async recordFileEdit($,b,w="edit"){try{let W=await Db.stat($),V={filePath:$,accessTime:Date.now(),mtime:W.mtimeMs,sessionId:b,lastOperation:w};this.accessedFiles.set($,V),i0.debug(`记录文件${w==="edit"?"编辑":"写入"}: ${$}`)}catch(W){i0.warn(`记录文件${w==="edit"?"编辑":"写入"}失败: ${$}`,W)}}hasFileBeenRead($,b){let w=this.accessedFiles.get($);if(!w)return!1;if(b&&w.sessionId!==b)return!1;return!0}async checkFileModification($){let b=this.accessedFiles.get($);if(!b)return{modified:!1,message:"文件未被跟踪"};try{let w=await Db.stat($);if(Math.abs(w.mtimeMs-b.mtime)>1)return{modified:!0,message:`文件在访问后被修改(访问时间: ${new Date(b.accessTime).toISOString()}, 当前修改时间: ${w.mtime.toISOString()})`};return{modified:!1}}catch(w){if(n(w)==="ENOENT")return{modified:!0,message:"文件已被删除"};return{modified:!1,message:`无法检查文件状态: ${_(w)}`}}}async checkExternalModification($){let b=this.accessedFiles.get($);if(!b)return{isExternal:!1,message:"文件未被跟踪"};try{let w=await Db.stat($);if(w.mtimeMs-b.mtime>2000)return{isExternal:!0,message:`文件在 ${new Date(b.accessTime).toISOString()} (${b.lastOperation}) 之后被外部程序修改(当前修改时间: ${w.mtime.toISOString()})`};return{isExternal:!1}}catch(w){if(n(w)==="ENOENT")return{isExternal:!0,message:"文件已被删除"};return i0.warn(`检查文件外部修改失败: ${$}`,w),{isExternal:!1,message:`无法检查文件状态: ${_(w)}`}}}getFileRecord($){return this.accessedFiles.get($)}clearFileRecord($){this.accessedFiles.delete($)}clearAll(){this.accessedFiles.clear()}clearSession($){for(let[b,w]of this.accessedFiles.entries())if(w.sessionId===$)this.accessedFiles.delete(b)}getTrackedFiles(){return Array.from(this.accessedFiles.keys())}getTrackedFileCount(){return this.accessedFiles.size}static resetInstance(){w$.instance=null}}import*as S4 from"node:crypto";import{promises as v$}from"node:fs";import*as w0 from"node:path";import{execSync as IW}from"node:child_process";import*as _1 from"node:os";import*as b0 from"node:path";function PW($){return b0.resolve($).replace(/[/\\]/g,"-").replace(/:/g,"_")}function l0($){let b=_1.homedir(),w=PW($);return b0.join(b,".blade","projects",w)}function Y$($,b){return b0.join(l0($),`${b}.jsonl`)}function j4($){try{return IW("git rev-parse --abbrev-ref HEAD",{cwd:$,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{return}}function n0(){return b0.join(_1.homedir(),".blade")}async function N4(){let{readdir:$}=await import("node:fs/promises");try{let b=b0.join(n0(),"projects");return(await $(b,{withFileTypes:!0})).filter((W)=>W.isDirectory()).map((W)=>W.name)}catch{return[]}}class s0{sessionId;enableCheckpoints;maxSnapshots;snapshotDir;trackedFileBackups=new Map;snapshots=[];constructor($){this.sessionId=$.sessionId,this.enableCheckpoints=$.enableCheckpoints??!0,this.maxSnapshots=$.maxSnapshots??10;let b=n0();this.snapshotDir=w0.join(b,"file-history",this.sessionId)}async initialize(){if(!this.enableCheckpoints)return;try{await v$.mkdir(this.snapshotDir,{recursive:!0,mode:493}),console.log(`[SnapshotManager] 初始化快照目录: ${this.snapshotDir}`)}catch($){throw console.warn("[SnapshotManager] 创建快照目录失败:",$),$}}async createSnapshot($,b){if(!this.enableCheckpoints)return console.log("[SnapshotManager] 检查点已禁用,跳过快照创建"),{backupFileName:"",version:0,backupTime:new Date};try{await v$.access($)}catch{return console.warn(`[SnapshotManager] 文件不存在,跳过快照: ${$}`),{backupFileName:"",version:0,backupTime:new Date}}let w=this.trackedFileBackups.get($),W=w?w.version+1:1,V=this.generateFileHash($,W),Q=w0.join(this.snapshotDir,`${V}@v${W}`);try{let Z=await v$.readFile($,{encoding:"utf-8"});await v$.writeFile(Q,Z,{encoding:"utf-8"});let J={backupFileName:V,version:W,backupTime:new Date};return this.trackedFileBackups.set($,J),this.snapshots.push({messageId:b,backupFileName:V,timestamp:new Date,filePath:$}),console.log(`[SnapshotManager] 创建快照: ${$} -> ${V}@v${W}`),await this.cleanupOldSnapshots($),J}catch(Z){throw console.error(`[SnapshotManager] 创建快照失败: ${$}`,Z),Z}}async restoreSnapshot($,b){let w=this.snapshots.slice().reverse().find((Q)=>Q.messageId===b&&Q.filePath===$);if(!w)throw Error(`未找到快照: messageId=${b}, filePath=${$}`);let W=this.trackedFileBackups.get($);if(!W)throw Error(`未找到文件追踪信息: ${$}`);let V=w0.join(this.snapshotDir,`${w.backupFileName}@v${W.version}`);try{let Q=await v$.readFile(V,{encoding:"utf-8"});await v$.writeFile($,Q,{encoding:"utf-8"}),console.log(`[SnapshotManager] 恢复快照: ${$} <- ${w.backupFileName}@v${W.version}`)}catch(Q){throw console.error(`[SnapshotManager] 恢复快照失败: ${$}`,Q),Q}}async listSnapshots($){return this.snapshots.filter((b)=>b.filePath===$)}async cleanupOldSnapshots($){let b=this.snapshots.filter((V)=>V.filePath===$);if(b.length<=this.maxSnapshots)return;let W=b.sort((V,Q)=>V.timestamp.getTime()-Q.timestamp.getTime()).slice(0,b.length-this.maxSnapshots);for(let V of W){let Q=this.trackedFileBackups.get(V.filePath);if(!Q)continue;let Z=w0.join(this.snapshotDir,`${V.backupFileName}@v${Q.version}`);try{await v$.unlink(Z),console.log(`[SnapshotManager] 删除旧快照: ${Z}`)}catch(Y){console.warn(`[SnapshotManager] 删除快照失败: ${Z}`,Y)}let J=this.snapshots.indexOf(V);if(J>-1)this.snapshots.splice(J,1)}}async cleanup($=0){try{let b=await v$.readdir(this.snapshotDir);if(b.length<=$)return;let w=await Promise.all(b.map(async(V)=>{let Q=w0.join(this.snapshotDir,V),Z=await v$.stat(Q);return{file:V,mtime:Z.mtime.getTime()}}));w.sort((V,Q)=>Q.mtime-V.mtime);let W=w.slice($);for(let{file:V}of W){let Q=w0.join(this.snapshotDir,V);await v$.unlink(Q),console.log(`[SnapshotManager] 清理快照: ${Q}`)}}catch(b){console.warn("[SnapshotManager] 清理快照失败:",b)}}generateFileHash($,b){let w=S4.createHash("md5");return w.update(`${$}:${b}`),w.digest("hex").substring(0,16)}getSnapshotDir(){return this.snapshotDir}getSessionId(){return this.sessionId}getTrackedFileCount(){return this.trackedFileBackups.size}getSnapshotCount(){return this.snapshots.length}}var D1=L({name:"Edit",displayName:"File Edit",kind:"write",strict:!0,isConcurrencySafe:!1,schema:Lb.object({file_path:P.filePath({description:"Absolute path of the file to edit"}),old_string:Lb.string().min(1,"old_string cannot be empty").describe("String to replace"),new_string:Lb.string().describe("Replacement string (can be empty)"),replace_all:Lb.boolean().default(!1).describe("Replace all matches (default: first only)")}),description:{short:"Performs exact string replacements in files",long:"Performs exact string replacements in files.",usageNotes:["You must use your Read tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file.","When editing text from Read tool output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: spaces + line number + tab. Everything after that tab is the actual file content to match. Never include any part of the line number prefix in the old_string or new_string.","ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.","Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.","The edit will FAIL if old_string is not unique in the file. Either provide a larger string with more surrounding context to make it unique or use replace_all to change every instance of old_string.","Use replace_all for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance."]},async execute($,b){let{file_path:w,old_string:W,new_string:V,replace_all:Q}=$,{updateOutput:Z,sessionId:J,messageId:Y}=b,X=b.signal??new AbortController().signal;try{Z?.("Starting to read file...");let O=H0(),G=i$(),B;try{if(G)Z?.("通过 IDE 读取文件...");B=await O.readTextFile(w)}catch(y){if(n(y)==="ENOENT"||_(y)?.includes("not found"))return{success:!1,llmContent:`File not found: ${w}`,displayContent:`❌ 文件不存在: ${w}`,error:{type:"execution_error",message:"文件不存在"}};throw y}if(typeof X.throwIfAborted==="function")X.throwIfAborted();if(J){let y=w$.getInstance();if(!y.hasFileBeenRead(w,J))return{success:!1,llmContent:"You must use your Read tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file.",displayContent:"\uD83D\uDCD6 我需要先读取文件内容,然后再进行编辑。",error:{type:"validation_error",message:"File not read before edit"},metadata:{requiresRead:!0}};let q$=await y.checkExternalModification(w);if(q$.isExternal)return{success:!1,llmContent:`The file has been modified by an external program since you last read it. You must use the Read tool again to see the current content before editing.
482
+
483
+ Details: ${q$.message}`,displayContent:`❌ 编辑失败:文件已被外部程序修改
484
+
485
+ ${q$.message}
486
+
487
+ \uD83D\uDCA1 我需要重新读取文件内容后再编辑`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:q$.message}}}}if(J&&Y)try{let y=new s0({sessionId:J});await y.initialize(),await y.createSnapshot(w,Y)}catch(y){console.warn("[EditTool] 创建快照失败:",y)}if(W===V)return{success:!1,llmContent:"New string is identical; no replacement needed",displayContent:"⚠️ 新字符串与旧字符串相同,无需进行替换",error:{type:"validation_error",message:"新旧字符串相同"}};let K=pW(B,W);if(!K.matched){let y=gW(B,W,w);return{success:!1,llmContent:y.llmContent,displayContent:y.displayContent,error:{type:"execution_error",message:"未找到匹配内容",details:y.metadata}}}let C=K.matched;if(K.strategy!=="exact")console.log(`[SmartEdit] 使用策略: ${K.strategy}`);let q=dW(B,C);if(q.length>1&&!Q){let y=B.split(`
488
+ `),q$=0,A0=[];for(let J$=0;J$<y.length;J$++){let f0=y[J$],cw=q$,iw=q$+f0.length;for(let w1 of q)if(w1>=cw&&w1<iw){let R8=Math.max(0,J$-1),H8=Math.min(y.length-1,J$+1),_8=y.slice(R8,H8+1).map((D8)=>D8.trim()).join(" ").slice(0,80);A0.push({line:J$+1,column:w1-cw+1,context:_8})}q$=iw+1}let b1=[`⚠️ EDIT PAUSED: old_string matches ${q.length} locations (must be unique).`,"","**Matches found at:**",...A0.map((J$,f0)=>` ${f0+1}. Line ${J$.line}`),"","**Action Required:** Add 3-5 lines of surrounding context to make old_string unique.","","**Tips for quick success:**","• Include the function/class name that wraps the target code","• Add 2-3 lines before and after the target","• Include unique comments or variable names nearby",`• Or use replace_all=true to change all ${q.length} occurrences`,"","\uD83E\uDD16 **Auto-retry expected** - This usually resolves in 1-2 attempts."].join(`
489
+ `),U8=["⚠️ 编辑暂停:需要更精确的定位","",`在文件中找到 ${q.length} 处相似代码:`,...A0.map((J$,f0)=>` • 第 ${J$.line} 行 (匹配 ${f0+1}/${q.length})`),"","AI 正在自动调整,添加更多上下文以精确定位...","通常需要 1-2 次尝试即可成功","","\uD83D\uDCA1 如果多次失败,可能需要:"," • 包含函数/类名等独特标识符"," • 添加目标代码前后 3-5 行完整上下文",` • 或使用 replace_all=true 同时替换所有 ${q.length} 处匹配`].join(`
490
+ `);return{success:!1,llmContent:b1,displayContent:U8,error:{type:"validation_error",message:"old_string is not unique",details:{matches:A0.map((J$)=>({line:J$.line,column:J$.column})),count:q.length}}}}else Z?.(`找到 ${q.length} 个匹配项,开始替换...`);let F,U;if(Q)F=B.split(C).join(V),U=q.length;else{let y=B.indexOf(C);F=B.substring(0,y)+V+B.substring(y+C.length),U=1}if(typeof X.throwIfAborted==="function")X.throwIfAborted();let H=z$();if(H.captureBeforeWrite(w),G)Z?.("通过 IDE 写入文件...");if(await O.writeTextFile(w,F),H.trackFileChange(w,"modify"),J)await w$.getInstance().recordFileEdit(w,J,"edit");let R=await O.stat(w),T=D4(B,F,C,V,4),N=hW(w),D=U===1?`替换 1 处匹配到 ${N}`:`替换 ${U} 处匹配到 ${N}`,S={file_path:w,matches_found:q.length,replacements_made:U,replace_all:Q,old_string_length:W.length,new_string_length:V.length,original_size:B.length,new_size:F.length,size_diff:F.length-B.length,last_modified:R?.mtime instanceof Date?R.mtime.toISOString():void 0,snapshot_created:!!(J&&Y),session_id:J,message_id:Y,diff_snippet:T,summary:D,kind:"edit",oldContent:B,newContent:F},l=uW(S,T);return{success:!0,llmContent:{file_path:w,replacements:U,total_matches:q.length},displayContent:l,metadata:S}}catch(O){if(d(O)==="AbortError")return{success:!1,llmContent:"File edit aborted",displayContent:"⚠️ 文件编辑被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File edit failed: ${_(O)}`,displayContent:`❌ 编辑文件失败: ${_(O)}`,error:{type:"execution_error",message:_(O),details:O}}}},version:"2.0.0",category:"文件操作",tags:["file","edit","replace","modify"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let b=xW($.file_path);return b?`**/*${b}`:"**/*"}});function y4($){return $.replaceAll("‘","'").replaceAll("’","'").replaceAll("“",'"').replaceAll("”",'"')}function pW($,b){if($.includes(b))return{matched:b,strategy:"exact"};let w=y4(b),V=y4($).indexOf(w);if(V!==-1)return{matched:$.substring(V,V+b.length),strategy:"normalize_quotes"};let Q=L4(b);if(Q!==b&&$.includes(Q))return{matched:Q,strategy:"unescape"};let Z=E4($,b);if(Z)return{matched:Z,strategy:"flexible"};return{matched:null,strategy:"failed"}}function dW($,b){if(b.length===0)return[];let w=[],W=$.indexOf(b);while(W!==-1)w.push(W),W=$.indexOf(b,W+b.length);return w}function uW($,b){let{file_path:w,matches_found:W,replacements_made:V,replace_all:Q,size_diff:Z}=$,J=`✅ 成功编辑文件: ${w}`;if(J+=`
491
+ \uD83D\uDCDD 替换了 ${V} 个匹配项`,!Q&&W>1)J+=` (共找到 ${W} 个匹配项)`;if(Z!==0){let Y=Z>0?`增加${Z}`:`减少${Math.abs(Z)}`;J+=`
492
+ \uD83D\uDCCA 文件大小${Y}个字符`}if(b)J+=b;return J}function gW($,b,w){let W=$.split(`
493
+ `),V=W.length,Q=mW($,b,3),Z=0,J=Math.min(20,V);if(Q.length>0){let K=Q[0];Z=Math.max(0,K.lineNumber-10),J=Math.min(V,K.lineNumber+10)}let X=W.slice(Z,J).map((K,C)=>{return` ${(Z+C+1).toString().padStart(4)}: ${K}`}).join(`
610
494
  `),O=`String not found in file.
611
495
 
612
496
  File: ${w}
613
- Total lines: ${W}
497
+ Total lines: ${V}
614
498
 
615
499
  `,G=b.length>300?b.substring(0,300)+`
616
500
  ... (truncated)`:b;if(O+=`You tried to match:
617
501
  ${G}
618
502
 
619
- `,Q.length>0)O+=`File content around possible matches (lines ${Z+1}-${Y}):
503
+ `,Q.length>0)O+=`File content around possible matches (lines ${Z+1}-${J}):
620
504
  ${X}
621
505
 
622
- `;else O+=`File content preview (lines ${Z+1}-${Y}):
506
+ `;else O+=`File content preview (lines ${Z+1}-${J}):
623
507
  ${X}
624
508
 
625
509
  `;if(Q.length>0)O+=`Possible similar matches found:
626
- `,Q.forEach((q,U)=>{let K=q.text.length>100?q.text.substring(0,100)+"...":q.text;O+=` ${U+1}. Line ${q.lineNumber} (similarity: ${Math.round(q.similarity*100)}%)
627
- ${K.replace(/\n/g,"\\n")}
510
+ `,Q.forEach((K,C)=>{let q=K.text.length>100?K.text.substring(0,100)+"...":K.text;O+=` ${C+1}. Line ${K.lineNumber} (similarity: ${Math.round(K.similarity*100)}%)
511
+ ${q.replace(/\n/g,"\\n")}
628
512
  `}),O+=`
629
513
  `;O+=`Recovery suggestions:
630
514
  1. Use the Read tool to verify the current file content
@@ -642,52 +526,52 @@ Common issues:
642
526
  搜索字符串长度: ${b.length} 字符
643
527
  `;if(Q.length>0)B+=`
644
528
  \uD83D\uDCA1 找到 ${Q.length} 个相似匹配项:
645
- `,Q.forEach((q,U)=>{B+=` ${U+1}. 第 ${q.lineNumber} 行 (相似度: ${Math.round(q.similarity*100)}%)
529
+ `,Q.forEach((K,C)=>{B+=` ${C+1}. 第 ${K.lineNumber} 行 (相似度: ${Math.round(K.similarity*100)}%)
646
530
  `});else B+=`
647
531
  ⚠️ 未找到相似的匹配项
648
532
  `;return B+=`
649
- \uD83D\uDCC4 文件内容摘录 (${Z+1}-${Y} 行):
533
+ \uD83D\uDCC4 文件内容摘录 (${Z+1}-${J} 行):
650
534
  ${X}
651
535
  `,B+=`
652
536
  \uD83D\uDD27 接下来我会:
653
537
  `,B+=` 1. 重新读取文件内容
654
538
  `,B+=` 2. 仔细核对空格、换行符、引号
655
- `,B+=" 3. 使用更多上下文代码确保唯一性",{llmContent:O,displayContent:B,metadata:{searchStringLength:b.length,fuzzyMatches:Q.map((q)=>({line:q.lineNumber,similarity:q.similarity,preview:q.text.substring(0,100)})),excerptRange:[Z+1,Y],totalLines:W}}}function F7($,b,w=3){let V=$.split(`
656
- `),W=b.split(`
657
- `);if(W.length===1)return V.map((J,X)=>({text:J,lineNumber:X+1,similarity:j4(b.trim(),J.trim())})).filter((J)=>J.similarity>0.5).sort((J,X)=>X.similarity-J.similarity).slice(0,w);let Q=W.length,Z=[];for(let Y=0;Y<=V.length-Q;Y++){let J=V.slice(Y,Y+Q).join(`
658
- `),X=j4(b,J);if(X>0.5)Z.push({text:J,lineNumber:Y+1,similarity:X})}return Z.sort((Y,J)=>J.similarity-Y.similarity).slice(0,w)}function j4($,b){let w=(B)=>B.trim().replace(/\s+/g," ").replace(/[\u201c\u201d"]/g,'"').replace(/[\u2018\u2019']/g,"'"),V=w($),W=w(b);if(V===W)return 1;let Q=V.length,Z=W.length;if(Q===0)return Z===0?1:0;if(Z===0)return 0;let Y=200,J=V.substring(0,Y),X=W.substring(0,Y),O=H7(J,X),G=Math.max(J.length,X.length);return 1-O/G}function H7($,b){let w=$.length,V=b.length,W=Array(w+1).fill(null).map(()=>Array(V+1).fill(0));for(let Q=0;Q<=w;Q++)W[Q][0]=Q;for(let Q=0;Q<=V;Q++)W[0][Q]=Q;for(let Q=1;Q<=w;Q++)for(let Z=1;Z<=V;Z++){let Y=$[Q-1]===b[Z-1]?0:1;W[Q][Z]=Math.min(W[Q-1][Z]+1,W[Q][Z-1]+1,W[Q-1][Z-1]+Y)}return W[w][V]}import{basename as _7,extname as N4}from"path";import{z as R7}from"zod";var y1=E({name:"Read",displayName:"File Read",kind:"readonly",schema:R7.object({file_path:P.filePath({description:"File path to read (must be absolute)"}),offset:P.lineNumber({description:"Starting line number (0-based, text files only)"}).optional(),limit:P.lineLimit({description:"Number of lines to read (text files only)"}).optional(),encoding:P.encoding()}),description:{short:"Read files from the local filesystem",long:"Reads a file from the local filesystem. You can access any file directly by using this tool. Assume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.",usageNotes:["The file_path parameter must be an absolute path, not a relative path","By default, it reads up to 2000 lines starting from the beginning of the file","You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters","Any lines longer than 2000 characters will be truncated","Results are returned using cat -n format, with line numbers starting at 1","This tool allows reading images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as this is a multimodal LLM.","This tool can read PDF files (.pdf). PDFs are processed page by page, extracting both text and visual content for analysis.","This tool can read Jupyter notebooks (.ipynb files) and returns all cells with their outputs, combining code, text, and visualizations.","This tool can only read files, not directories. To read a directory, use an ls command via the Bash tool.","You can call multiple tools in a single response. It is always better to speculatively read multiple potentially useful files in parallel.","You will regularly be asked to read screenshots. If the user provides a path to a screenshot, ALWAYS use this tool to view the file at the path. This tool will work with all temporary file paths.","If you read a file that exists but has empty contents you will receive a system reminder warning in place of file contents."],examples:[{description:"Read the entire file (recommended)",params:{file_path:"/path/to/file.ts"}},{description:"Read the first 100 lines",params:{file_path:"/path/to/file.txt",limit:100}},{description:"Read 100 lines starting at line 50 (large file)",params:{file_path:"/path/to/large-file.log",offset:50,limit:100}}],important:["file_path must be absolute","Prefer reading the entire file (omit offset and limit)","Use offset/limit only for very large files","Line numbers start at 1 (cat -n format)"]},async execute($,b){let{file_path:w,offset:V,limit:W,encoding:Q="utf8"}=$,{updateOutput:Z,sessionId:Y}=b,J=b.signal??new AbortController().signal;try{Z?.("Starting file read...");let X=C0(),O=g$();try{if(!await X.exists(w))throw Error("File not found")}catch(L){return{success:!1,llmContent:`File not found: ${w}`,displayContent:`❌ 文件不存在: ${w}`,error:{type:"execution_error",message:`File not found: ${w}`}}}if(typeof J.throwIfAborted==="function")J.throwIfAborted();if(Y)await b$.getInstance().recordFileRead(w,Y);let G=await X.stat(w);if(G?.isDirectory)return{success:!1,llmContent:`Cannot read a directory: ${w}`,displayContent:`❌ 无法读取目录: ${w}`,error:{type:"execution_error",message:"Target is a directory, not a file"}};let B=N4(w).toLowerCase(),q=E7(B),U=D7(B),K,_={file_path:w,file_size:G?.size,file_type:B,last_modified:G?.mtime instanceof Date?G.mtime.toISOString():void 0,encoding:Q,acp_mode:O};if(U&&Q==="utf8"){if(O)Z?.("⚠️ 二进制文件通过本地读取(ACP 不支持)..."),_.acp_fallback=!0;else Z?.("检测到二进制文件,使用 base64 编码...");K=(await X.readBinaryFile(w)).toString("base64"),_.encoding="base64",_.is_binary=!0}else if(q){if(O)Z?.("通过 IDE 读取文件...");K=await X.readTextFile(w)}else{if(O)_.acp_fallback=!0;let L=await X.readBinaryFile(w);if(Q==="base64")K=L.toString("base64");else if(Q==="binary")K=L.toString("binary");else K=L.toString("utf8")}if(typeof J.throwIfAborted==="function")J.throwIfAborted();if((V!==void 0||W!==void 0)&&Q==="utf8"&&q){let L=K.split(`
659
- `),R=V||0,D=W!==void 0?R+W:L.length,c=L.slice(R,D);K=c.map((y,l)=>{let F$=R+l+1,nb=y.length>2000?`${y.substring(0,2000)}...`:y;return`${F$.toString().padStart(6)}→${nb}`}).join(`
660
- `),_.lines_read=c.length,_.total_lines=L.length,_.start_line=R+1,_.end_line=Math.min(D,L.length)}let C=_7(w),H=_.lines_read||_.total_lines,F=H?`读取 ${H} 行从 ${C}`:`读取 ${C}`;_.summary=F;let M=L7(w,_);return{success:!0,llmContent:K,displayContent:M,metadata:_}}catch(X){let O=X;if(O.name==="AbortError")return{success:!1,llmContent:"File read aborted",displayContent:"⚠️ 文件读取被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`File read failed: ${O.message}`,displayContent:`❌ 读取文件失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"文件操作",tags:["file","io","read"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let b=N4($.file_path);return b?`**/*${b}`:"**/*"}});function E7($){return[".txt",".md",".js",".ts",".jsx",".tsx",".json",".xml",".html",".htm",".css",".scss",".sass",".less",".yml",".yaml",".toml",".ini",".cfg",".py",".rb",".php",".java",".cpp",".c",".h",".hpp",".rs",".go",".sh",".bash",".zsh",".fish",".ps1",".bat",".cmd",".sql",".graphql",".vue",".svelte",".astro",".dockerfile",".gitignore",".env"].includes($)||$===""}function D7($){return[".jpg",".jpeg",".png",".gif",".bmp",".svg",".ico",".webp",".mp3",".wav",".mp4",".avi",".mov",".wmv",".flv",".webm",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".zip",".tar",".gz",".rar",".7z",".exe",".dll",".so",".ttf",".otf",".woff",".woff2",".eot"].includes($)}function L7($,b){let w=`✅ 成功读取文件: ${$}`;if(b.file_size!==void 0&&typeof b.file_size==="number")w+=` (${j7(b.file_size)})`;if(b.lines_read!==void 0)w+=`
539
+ `,B+=" 3. 使用更多上下文代码确保唯一性",{llmContent:O,displayContent:B,metadata:{searchStringLength:b.length,fuzzyMatches:Q.map((K)=>({line:K.lineNumber,similarity:K.similarity,preview:K.text.substring(0,100)})),excerptRange:[Z+1,J],totalLines:V}}}function mW($,b,w=3){let W=$.split(`
540
+ `),V=b.split(`
541
+ `);if(V.length===1)return W.map((Y,X)=>({text:Y,lineNumber:X+1,similarity:M4(b.trim(),Y.trim())})).filter((Y)=>Y.similarity>0.5).sort((Y,X)=>X.similarity-Y.similarity).slice(0,w);let Q=V.length,Z=[];for(let J=0;J<=W.length-Q;J++){let Y=W.slice(J,J+Q).join(`
542
+ `),X=M4(b,Y);if(X>0.5)Z.push({text:Y,lineNumber:J+1,similarity:X})}return Z.sort((J,Y)=>Y.similarity-J.similarity).slice(0,w)}function M4($,b){let w=(B)=>B.trim().replace(/\s+/g," ").replace(/[\u201c\u201d"]/g,'"').replace(/[\u2018\u2019']/g,"'"),W=w($),V=w(b);if(W===V)return 1;let Q=W.length,Z=V.length;if(Q===0)return Z===0?1:0;if(Z===0)return 0;let J=200,Y=W.substring(0,J),X=V.substring(0,J),O=cW(Y,X),G=Math.max(Y.length,X.length);return 1-O/G}function cW($,b){let w=$.length,W=b.length,V=Array(w+1).fill(null).map(()=>Array(W+1).fill(0));for(let Q=0;Q<=w;Q++)V[Q][0]=Q;for(let Q=0;Q<=W;Q++)V[0][Q]=Q;for(let Q=1;Q<=w;Q++)for(let Z=1;Z<=W;Z++){let J=$[Q-1]===b[Z-1]?0:1;V[Q][Z]=Math.min(V[Q-1][Z]+1,V[Q][Z-1]+1,V[Q-1][Z-1]+J)}return V[w][W]}import{basename as iW,extname as z4}from"path";import{z as lW}from"zod";var L1=L({name:"Read",displayName:"File Read",kind:"readonly",schema:lW.object({file_path:P.filePath({description:"File path to read (must be absolute)"}),offset:P.lineNumber({description:"Starting line number (0-based, text files only)"}).optional(),limit:P.lineLimit({description:"Number of lines to read (text files only)"}).optional(),encoding:P.encoding()}),description:{short:"Read files from the local filesystem",long:"Reads a file from the local filesystem. You can access any file directly by using this tool. Assume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.",usageNotes:["The file_path parameter must be an absolute path, not a relative path","By default, it reads up to 2000 lines starting from the beginning of the file","You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters","Any lines longer than 2000 characters will be truncated","Results are returned using cat -n format, with line numbers starting at 1","This tool allows reading images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as this is a multimodal LLM.","This tool can read PDF files (.pdf). PDFs are processed page by page, extracting both text and visual content for analysis.","This tool can read Jupyter notebooks (.ipynb files) and returns all cells with their outputs, combining code, text, and visualizations.","This tool can only read files, not directories. To read a directory, use an ls command via the Bash tool.","You can call multiple tools in a single response. It is always better to speculatively read multiple potentially useful files in parallel.","You will regularly be asked to read screenshots. If the user provides a path to a screenshot, ALWAYS use this tool to view the file at the path. This tool will work with all temporary file paths.","If you read a file that exists but has empty contents you will receive a system reminder warning in place of file contents."],examples:[{description:"Read the entire file (recommended)",params:{file_path:"/path/to/file.ts"}},{description:"Read the first 100 lines",params:{file_path:"/path/to/file.txt",limit:100}},{description:"Read 100 lines starting at line 50 (large file)",params:{file_path:"/path/to/large-file.log",offset:50,limit:100}}],important:["file_path must be absolute","Prefer reading the entire file (omit offset and limit)","Use offset/limit only for very large files","Line numbers start at 1 (cat -n format)"]},async execute($,b){let{file_path:w,offset:W,limit:V,encoding:Q="utf8"}=$,{updateOutput:Z,sessionId:J}=b,Y=b.signal??new AbortController().signal;try{Z?.("Starting file read...");let X=H0(),O=i$();try{if(!await X.exists(w))throw Error("File not found")}catch(N){return{success:!1,llmContent:`File not found: ${w}`,displayContent:`❌ 文件不存在: ${w}`,error:{type:"execution_error",message:`File not found: ${w}`}}}if(typeof Y.throwIfAborted==="function")Y.throwIfAborted();if(J)await w$.getInstance().recordFileRead(w,J);let G=await X.stat(w);if(G?.isDirectory)return{success:!1,llmContent:`Cannot read a directory: ${w}`,displayContent:`❌ 无法读取目录: ${w}`,error:{type:"execution_error",message:"Target is a directory, not a file"}};let B=z4(w).toLowerCase(),K=nW(B),C=sW(B),q,F={file_path:w,file_size:G?.size,file_type:B,last_modified:G?.mtime instanceof Date?G.mtime.toISOString():void 0,encoding:Q,acp_mode:O};if(C&&Q==="utf8"){if(O)Z?.("⚠️ 二进制文件通过本地读取(ACP 不支持)..."),F.acp_fallback=!0;else Z?.("检测到二进制文件,使用 base64 编码...");q=(await X.readBinaryFile(w)).toString("base64"),F.encoding="base64",F.is_binary=!0}else if(K){if(O)Z?.("通过 IDE 读取文件...");q=await X.readTextFile(w)}else{if(O)F.acp_fallback=!0;let N=await X.readBinaryFile(w);if(Q==="base64")q=N.toString("base64");else if(Q==="binary")q=N.toString("binary");else q=N.toString("utf8")}if(typeof Y.throwIfAborted==="function")Y.throwIfAborted();if((W!==void 0||V!==void 0)&&Q==="utf8"&&K){let N=q.split(`
543
+ `),D=W||0,S=V!==void 0?D+V:N.length,l=N.slice(D,S);q=l.map((y,q$)=>{let A0=D+q$+1,b1=y.length>2000?`${y.substring(0,2000)}...`:y;return`${A0.toString().padStart(6)}→${b1}`}).join(`
544
+ `),F.lines_read=l.length,F.total_lines=N.length,F.start_line=D+1,F.end_line=Math.min(S,N.length)}let U=iW(w),H=F.lines_read||F.total_lines,R=H?`读取 ${H} 行从 ${U}`:`读取 ${U}`;F.summary=R;let T=rW(w,F);return{success:!0,llmContent:q,displayContent:T,metadata:F}}catch(X){if(d(X)==="AbortError")return{success:!1,llmContent:"File read aborted",displayContent:"⚠️ 文件读取被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`File read failed: ${_(X)}`,displayContent:`❌ 读取文件失败: ${_(X)}`,error:{type:"execution_error",message:_(X),details:X}}}},version:"2.0.0",category:"文件操作",tags:["file","io","read"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let b=z4($.file_path);return b?`**/*${b}`:"**/*"}});function nW($){return[".txt",".md",".js",".ts",".jsx",".tsx",".json",".xml",".html",".htm",".css",".scss",".sass",".less",".yml",".yaml",".toml",".ini",".cfg",".py",".rb",".php",".java",".cpp",".c",".h",".hpp",".rs",".go",".sh",".bash",".zsh",".fish",".ps1",".bat",".cmd",".sql",".graphql",".vue",".svelte",".astro",".dockerfile",".gitignore",".env"].includes($)||$===""}function sW($){return[".jpg",".jpeg",".png",".gif",".bmp",".svg",".ico",".webp",".mp3",".wav",".mp4",".avi",".mov",".wmv",".flv",".webm",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".zip",".tar",".gz",".rar",".7z",".exe",".dll",".so",".ttf",".otf",".woff",".woff2",".eot"].includes($)}function rW($,b){let w=`✅ 成功读取文件: ${$}`;if(b.file_size!==void 0&&typeof b.file_size==="number")w+=` (${aW(b.file_size)})`;if(b.lines_read!==void 0)w+=`
661
545
  \uD83D\uDCC4 读取了 ${b.lines_read} 行 (第${b.start_line}-${b.end_line}行,共${b.total_lines}行)`;if(b.is_binary)w+=`
662
- \uD83D\uDD10 文件以 base64 编码显示`;return w}function j7($){let b=["B","KB","MB","GB"],w=$,V=0;while(w>=1024&&V<b.length-1)w/=1024,V++;return`${w.toFixed(1)}${b[V]}`}import{promises as N7}from"fs";import{basename as S7,dirname as M7,extname as S4}from"path";import{z as z1}from"zod";var v1=E({name:"Write",displayName:"File Write",kind:"write",strict:!0,isConcurrencySafe:!1,schema:z1.object({file_path:P.filePath({description:"Absolute file path to write"}),content:z1.string().describe("Content to write"),encoding:P.encoding(),create_directories:z1.boolean().default(!0).describe("Automatically create missing parent directories")}),description:{short:"Writes a file to the local filesystem",long:"Writes a file to the local filesystem.",usageNotes:["This tool will overwrite the existing file if there is one at the provided path.","If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.","ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.","NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.","Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked."]},async execute($,b){let{file_path:w,content:V,encoding:W,create_directories:Q}=$,{updateOutput:Z,sessionId:Y,messageId:J}=b,X=b.signal??new AbortController().signal;try{Z?.("开始写入文件...");let O=C0(),G=g$();if(Q){let R=M7(w);try{await O.mkdir(R,{recursive:!0,mode:493})}catch(D){if(D.code!=="EEXIST")throw D}}if(typeof X.throwIfAborted==="function")X.throwIfAborted();let B=!1,q=null;try{if(B=await O.exists(w),B&&W==="utf8")try{q=await O.readTextFile(w)}catch(R){console.warn("[WriteTool] 读取旧文件内容失败:",R)}}catch{}if(B&&Y){let R=b$.getInstance();if(!R.hasFileBeenRead(w,Y))return{success:!1,llmContent:"If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.",displayContent:"\uD83D\uDCD6 我需要先读取文件内容,然后再进行写入。",error:{type:"validation_error",message:"File not read before write"},metadata:{requiresRead:!0}};let D=await R.checkExternalModification(w);if(D.isExternal)return{success:!1,llmContent:`The file has been modified by an external program since you last read it. You must use the Read tool again to see the current content before writing.
546
+ \uD83D\uDD10 文件以 base64 编码显示`;return w}function aW($){let b=["B","KB","MB","GB"],w=$,W=0;while(w>=1024&&W<b.length-1)w/=1024,W++;return`${w.toFixed(1)}${b[W]}`}import{promises as oW}from"fs";import{basename as tW,dirname as eW,extname as v4}from"path";import{z as E1}from"zod";var j1=L({name:"Write",displayName:"File Write",kind:"write",strict:!0,isConcurrencySafe:!1,schema:E1.object({file_path:P.filePath({description:"Absolute file path to write"}),content:E1.string().describe("Content to write"),encoding:P.encoding(),create_directories:E1.boolean().default(!0).describe("Automatically create missing parent directories")}),description:{short:"Writes a file to the local filesystem",long:"Writes a file to the local filesystem.",usageNotes:["This tool will overwrite the existing file if there is one at the provided path.","If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.","ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.","NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.","Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked."]},async execute($,b){let{file_path:w,content:W,encoding:V,create_directories:Q}=$,{updateOutput:Z,sessionId:J,messageId:Y}=b,X=b.signal??new AbortController().signal;try{Z?.("开始写入文件...");let O=H0(),G=i$();if(Q){let D=eW(w);try{await O.mkdir(D,{recursive:!0,mode:493})}catch(S){if(n(S)!=="EEXIST")throw S}}if(typeof X.throwIfAborted==="function")X.throwIfAborted();let B=!1,K=null;try{if(B=await O.exists(w),B&&V==="utf8")try{K=await O.readTextFile(w)}catch(D){console.warn("[WriteTool] 读取旧文件内容失败:",D)}}catch{}if(B&&J){let D=w$.getInstance();if(!D.hasFileBeenRead(w,J))return{success:!1,llmContent:"If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.",displayContent:"\uD83D\uDCD6 我需要先读取文件内容,然后再进行写入。",error:{type:"validation_error",message:"File not read before write"},metadata:{requiresRead:!0}};let S=await D.checkExternalModification(w);if(S.isExternal)return{success:!1,llmContent:`The file has been modified by an external program since you last read it. You must use the Read tool again to see the current content before writing.
663
547
 
664
- Details: ${D.message}`,displayContent:`❌ 写入失败:文件已被外部程序修改
548
+ Details: ${S.message}`,displayContent:`❌ 写入失败:文件已被外部程序修改
665
549
 
666
- ${D.message}
550
+ ${S.message}
667
551
 
668
- \uD83D\uDCA1 我需要重新读取文件内容后再写入`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:D.message}}}}let U=!1;if(B&&Y&&J)try{let R=new c0({sessionId:Y});await R.initialize(),await R.createSnapshot(w,J),U=!0}catch(R){console.warn("[WriteTool] 创建快照失败:",R)}let K=S$();if(K.captureBeforeWrite(w),typeof X.throwIfAborted==="function")X.throwIfAborted();if(W==="utf8"){if(G)Z?.("通过 IDE 写入文件...");await O.writeTextFile(w,V)}else{if(G)return{success:!1,llmContent:"Binary file writes are not supported in ACP mode. The IDE only supports text file operations. Please use encoding='utf8' for text files, or ask the user to write the file manually.",displayContent:`❌ ACP 模式不支持二进制文件写入
552
+ \uD83D\uDCA1 我需要重新读取文件内容后再写入`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:S.message}}}}let C=!1;if(B&&J&&Y)try{let D=new s0({sessionId:J});await D.initialize(),await D.createSnapshot(w,Y),C=!0}catch(D){console.warn("[WriteTool] 创建快照失败:",D)}let q=z$();if(q.captureBeforeWrite(w),typeof X.throwIfAborted==="function")X.throwIfAborted();if(V==="utf8"){if(G)Z?.("通过 IDE 写入文件...");await O.writeTextFile(w,W)}else{if(G)return{success:!1,llmContent:"Binary file writes are not supported in ACP mode. The IDE only supports text file operations. Please use encoding='utf8' for text files, or ask the user to write the file manually.",displayContent:`❌ ACP 模式不支持二进制文件写入
669
553
 
670
554
  当前通过 IDE 执行文件操作,但 IDE 仅支持文本文件。
671
555
 
672
- \uD83D\uDCA1 如果是文本文件,我会使用 encoding='utf8' 重试;如果必须写入二进制文件,需要在本地终端执行`,error:{type:"validation_error",message:"Binary writes not supported in ACP mode"}};let R;if(W==="base64")R=Buffer.from(V,"base64");else if(W==="binary")R=Buffer.from(V,"binary");else R=Buffer.from(V,"utf8");await N7.writeFile(w,R)}if(Y)await b$.getInstance().recordFileEdit(w,Y,"write");if(K.trackFileChange(w,B?"modify":"create"),typeof X.throwIfAborted==="function")X.throwIfAborted();let _=await O.stat(w),C=W==="utf8"?V.split(`
673
- `).length:0,H=S7(w),F=null;if(q&&W==="utf8"&&q!==V){if(q.length<1048576&&V.length<1048576)F=C4(q,V,4)}let M={file_path:w,content_size:V.length,file_size:_?.size,encoding:W,created_directories:Q,snapshot_created:U,session_id:Y,message_id:J,last_modified:_?.mtime instanceof Date?_.mtime.toISOString():void 0,has_diff:!!F,summary:W==="utf8"?`写入 ${C} 行到 ${H}`:`写入 ${_?.size?M4(_.size):"unknown"} 到 ${H}`,kind:"edit",oldContent:q||"",newContent:W==="utf8"?V:void 0},L=y7(w,M,V,F);return{success:!0,llmContent:{file_path:w,size:_?.size,modified:_?.mtime instanceof Date?_.mtime.toISOString():void 0},displayContent:L,metadata:M}}catch(O){let G=O;if(G.name==="AbortError")return{success:!1,llmContent:"File write aborted",displayContent:"⚠️ 文件写入被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File write failed: ${G.message}`,displayContent:`❌ 写入文件失败: ${G.message}`,error:{type:"execution_error",message:G.message,details:G}}}},version:"2.0.0",category:"文件操作",tags:["file","io","write","create"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let b=S4($.file_path);return b?`**/*${b}`:"**/*"}});function y7($,b,w,V){let W=`✅ 成功写入文件: ${$}`;if(b.file_size!==void 0)W+=` (${M4(b.file_size)})`;if(b.snapshot_created)W+=`
674
- \uD83D\uDCF8 已创建快照 (可回滚)`;if(b.encoding!=="utf8")W+=`
675
- \uD83D\uDD10 使用编码: ${b.encoding}`;if(V)W+=V;if(w&&b.encoding==="utf8"&&!V){let Q=z7($,w);if(Q)W+=`
556
+ \uD83D\uDCA1 如果是文本文件,我会使用 encoding='utf8' 重试;如果必须写入二进制文件,需要在本地终端执行`,error:{type:"validation_error",message:"Binary writes not supported in ACP mode"}};let D;if(V==="base64")D=Buffer.from(W,"base64");else if(V==="binary")D=Buffer.from(W,"binary");else D=Buffer.from(W,"utf8");await oW.writeFile(w,D)}if(J)await w$.getInstance().recordFileEdit(w,J,"write");if(q.trackFileChange(w,B?"modify":"create"),typeof X.throwIfAborted==="function")X.throwIfAborted();let F=await O.stat(w),U=V==="utf8"?W.split(`
557
+ `).length:0,H=tW(w),R=null;if(K&&V==="utf8"&&K!==W){if(K.length<1048576&&W.length<1048576)R=_4(K,W,4)}let T={file_path:w,content_size:W.length,file_size:F?.size,encoding:V,created_directories:Q,snapshot_created:C,session_id:J,message_id:Y,last_modified:F?.mtime instanceof Date?F.mtime.toISOString():void 0,has_diff:!!R,summary:V==="utf8"?`写入 ${U} 行到 ${H}`:`写入 ${F?.size?T4(F.size):"unknown"} 到 ${H}`,kind:"edit",oldContent:K||"",newContent:V==="utf8"?W:void 0},N=$5(w,T,W,R);return{success:!0,llmContent:{file_path:w,size:F?.size,modified:F?.mtime instanceof Date?F.mtime.toISOString():void 0},displayContent:N,metadata:T}}catch(O){if(d(O)==="AbortError")return{success:!1,llmContent:"File write aborted",displayContent:"⚠️ 文件写入被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File write failed: ${_(O)}`,displayContent:`❌ 写入文件失败: ${_(O)}`,error:{type:"execution_error",message:_(O),details:O}}}},version:"2.0.0",category:"文件操作",tags:["file","io","write","create"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let b=v4($.file_path);return b?`**/*${b}`:"**/*"}});function $5($,b,w,W){let V=`✅ 成功写入文件: ${$}`;if(b.file_size!==void 0)V+=` (${T4(b.file_size)})`;if(b.snapshot_created)V+=`
558
+ \uD83D\uDCF8 已创建快照 (可回滚)`;if(b.encoding!=="utf8")V+=`
559
+ \uD83D\uDD10 使用编码: ${b.encoding}`;if(W)V+=W;if(w&&b.encoding==="utf8"&&!W){let Q=b5($,w);if(Q)V+=`
676
560
 
677
- `+Q}return W}function z7($,b){let w=S4($).toLowerCase(),W={".ts":"typescript",".tsx":"tsx",".js":"javascript",".jsx":"jsx",".py":"python",".go":"go",".rs":"rust",".java":"java",".c":"c",".cpp":"cpp",".h":"c",".hpp":"cpp",".cs":"csharp",".rb":"ruby",".php":"php",".swift":"swift",".kt":"kotlin",".scala":"scala",".sh":"bash",".bash":"bash",".zsh":"zsh",".json":"json",".yaml":"yaml",".yml":"yaml",".toml":"toml",".xml":"xml",".html":"html",".css":"css",".scss":"scss",".sass":"sass",".less":"less",".md":"markdown",".sql":"sql",".graphql":"graphql",".proto":"protobuf"}[w]||"",Q=100,Z=5000,Y=b,J=!1,X=b.split(`
678
- `);if(X.length>100)Y=X.slice(0,100).join(`
679
- `),J=!0;if(Y.length>5000)Y=Y.substring(0,5000),J=!0;let O=`\uD83D\uDCC4 文件内容:
561
+ `+Q}return V}function b5($,b){let w=v4($).toLowerCase(),V={".ts":"typescript",".tsx":"tsx",".js":"javascript",".jsx":"jsx",".py":"python",".go":"go",".rs":"rust",".java":"java",".c":"c",".cpp":"cpp",".h":"c",".hpp":"cpp",".cs":"csharp",".rb":"ruby",".php":"php",".swift":"swift",".kt":"kotlin",".scala":"scala",".sh":"bash",".bash":"bash",".zsh":"zsh",".json":"json",".yaml":"yaml",".yml":"yaml",".toml":"toml",".xml":"xml",".html":"html",".css":"css",".scss":"scss",".sass":"sass",".less":"less",".md":"markdown",".sql":"sql",".graphql":"graphql",".proto":"protobuf"}[w]||"",Q=100,Z=5000,J=b,Y=!1,X=b.split(`
562
+ `);if(X.length>100)J=X.slice(0,100).join(`
563
+ `),Y=!0;if(J.length>5000)J=J.substring(0,5000),Y=!0;let O=`\uD83D\uDCC4 文件内容:
680
564
 
681
- `;if(O+="```"+W+`
682
- `,O+=Y,!Y.endsWith(`
565
+ `;if(O+="```"+V+`
566
+ `,O+=J,!J.endsWith(`
683
567
  `))O+=`
684
- `;if(O+="```",J)O+=`
568
+ `;if(O+="```",Y)O+=`
685
569
 
686
- ⚠️ 内容已截断(完整文件共 ${X.length} 行,${b.length} 字符)`;return O}function M4($){let b=["B","KB","MB","GB"],w=$,V=0;while(w>=1024&&V<b.length-1)w/=1024,V++;return`${w.toFixed(1)}${b[V]}`}import*as _b from"fs/promises";import{z as F0}from"zod";var Rb=E({name:"NotebookEdit",displayName:"Notebook Edit",kind:"write",schema:F0.object({notebook_path:F0.string().describe("The absolute path to the Jupyter notebook file to edit (must be absolute, not relative)"),cell_id:F0.string().optional().describe("The ID of the cell to edit. When inserting a new cell, the new cell will be inserted after the cell with this ID, or at the beginning if not specified."),new_source:F0.string().describe("The new source for the cell"),cell_type:F0.enum(["code","markdown"]).optional().describe("The type of the cell (code or markdown). If not specified, it defaults to the current cell type. If using edit_mode=insert, this is required."),edit_mode:F0.enum(["replace","insert","delete"]).optional().default("replace").describe("The type of edit to make (replace, insert, delete). Defaults to replace.")}),description:{short:"Completely replaces the contents of a specific cell in a Jupyter notebook",long:"Completely replaces the contents of a specific cell in a Jupyter notebook (.ipynb file) with new source. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path. The cell_number is 0-indexed. Use edit_mode=insert to add a new cell at the index specified by cell_number. Use edit_mode=delete to delete the cell at the index specified by cell_number."},async execute($,b){let{notebook_path:w,cell_id:V,new_source:W,cell_type:Q,edit_mode:Z="replace"}=$;try{let Y=await _b.readFile(w,"utf-8"),J=JSON.parse(Y);if(!J.cells||!Array.isArray(J.cells))return{success:!1,llmContent:"Invalid notebook format: no cells array found",displayContent:"Invalid notebook format",error:{type:"validation_error",message:"Invalid notebook format"}};let X=-1;if(V){if(X=J.cells.findIndex((G)=>G.id===V),X===-1&&Z!=="insert")return{success:!1,llmContent:`Cell with ID "${V}" not found`,displayContent:"Cell not found",error:{type:"validation_error",message:`Cell ID "${V}" not found`}}}switch(Z){case"replace":{if(X===-1)return{success:!1,llmContent:"Cell ID required for replace operation",displayContent:"Cell ID required",error:{type:"validation_error",message:"Cell ID required for replace"}};let G=J.cells[X];if(G.source=W.split(`
687
- `).map((B,q,U)=>q<U.length-1?B+`
688
- `:B),Q)G.cell_type=Q;break}case"insert":{if(!Q)return{success:!1,llmContent:"cell_type is required for insert operation",displayContent:"cell_type required",error:{type:"validation_error",message:"cell_type required for insert"}};let G={cell_type:Q,source:W.split(`
689
- `).map((q,U,K)=>U<K.length-1?q+`
690
- `:q),metadata:{},...Q==="code"?{execution_count:null,outputs:[]}:{}},B=X===-1?0:X+1;J.cells.splice(B,0,G);break}case"delete":{if(X===-1)return{success:!1,llmContent:"Cell ID required for delete operation",displayContent:"Cell ID required",error:{type:"validation_error",message:"Cell ID required for delete"}};J.cells.splice(X,1);break}}await _b.writeFile(w,JSON.stringify(J,null,2));let O=Z==="replace"?"replaced":Z==="insert"?"inserted":"deleted";return{success:!0,llmContent:`Successfully ${O} cell in ${w}`,displayContent:`Cell ${O} in notebook`,metadata:{notebook_path:w,edit_mode:Z,cell_id:V}}}catch(Y){let J=Y instanceof Error?Y.message:"Unknown error";return{success:!1,llmContent:`Failed to edit notebook: ${J}`,displayContent:"Notebook edit failed",error:{type:"execution_error",message:J}}}}});import{z as v7}from"zod";var T1=E({name:"EnterPlanMode",displayName:"Enter Plan Mode",kind:"readonly",schema:v7.object({}),description:{short:"Use this tool to enter plan mode for complex tasks requiring careful planning",long:`Use this tool when you encounter a complex task that requires careful planning and exploration before implementation. This tool transitions you into plan mode where you can thoroughly explore the codebase and design an implementation approach.
570
+ ⚠️ 内容已截断(完整文件共 ${X.length} 行,${b.length} 字符)`;return O}function T4($){let b=["B","KB","MB","GB"],w=$,W=0;while(w>=1024&&W<b.length-1)w/=1024,W++;return`${w.toFixed(1)}${b[W]}`}import*as Eb from"fs/promises";import{z as _0}from"zod";var jb=L({name:"NotebookEdit",displayName:"Notebook Edit",kind:"write",schema:_0.object({notebook_path:_0.string().describe("The absolute path to the Jupyter notebook file to edit (must be absolute, not relative)"),cell_id:_0.string().optional().describe("The ID of the cell to edit. When inserting a new cell, the new cell will be inserted after the cell with this ID, or at the beginning if not specified."),new_source:_0.string().describe("The new source for the cell"),cell_type:_0.enum(["code","markdown"]).optional().describe("The type of the cell (code or markdown). If not specified, it defaults to the current cell type. If using edit_mode=insert, this is required."),edit_mode:_0.enum(["replace","insert","delete"]).optional().default("replace").describe("The type of edit to make (replace, insert, delete). Defaults to replace.")}),description:{short:"Completely replaces the contents of a specific cell in a Jupyter notebook",long:"Completely replaces the contents of a specific cell in a Jupyter notebook (.ipynb file) with new source. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path. The cell_number is 0-indexed. Use edit_mode=insert to add a new cell at the index specified by cell_number. Use edit_mode=delete to delete the cell at the index specified by cell_number."},async execute($,b){let{notebook_path:w,cell_id:W,new_source:V,cell_type:Q,edit_mode:Z="replace"}=$;try{let J=await Eb.readFile(w,"utf-8"),Y=JSON.parse(J);if(!Y.cells||!Array.isArray(Y.cells))return{success:!1,llmContent:"Invalid notebook format: no cells array found",displayContent:"Invalid notebook format",error:{type:"validation_error",message:"Invalid notebook format"}};let X=-1;if(W){if(X=Y.cells.findIndex((G)=>G.id===W),X===-1&&Z!=="insert")return{success:!1,llmContent:`Cell with ID "${W}" not found`,displayContent:"Cell not found",error:{type:"validation_error",message:`Cell ID "${W}" not found`}}}switch(Z){case"replace":{if(X===-1)return{success:!1,llmContent:"Cell ID required for replace operation",displayContent:"Cell ID required",error:{type:"validation_error",message:"Cell ID required for replace"}};let G=Y.cells[X];if(G.source=V.split(`
571
+ `).map((B,K,C)=>K<C.length-1?B+`
572
+ `:B),Q)G.cell_type=Q;break}case"insert":{if(!Q)return{success:!1,llmContent:"cell_type is required for insert operation",displayContent:"cell_type required",error:{type:"validation_error",message:"cell_type required for insert"}};let G={cell_type:Q,source:V.split(`
573
+ `).map((K,C,q)=>C<q.length-1?K+`
574
+ `:K),metadata:{},...Q==="code"?{execution_count:null,outputs:[]}:{}},B=X===-1?0:X+1;Y.cells.splice(B,0,G);break}case"delete":{if(X===-1)return{success:!1,llmContent:"Cell ID required for delete operation",displayContent:"Cell ID required",error:{type:"validation_error",message:"Cell ID required for delete"}};Y.cells.splice(X,1);break}}await Eb.writeFile(w,JSON.stringify(Y,null,2));let O=Z==="replace"?"replaced":Z==="insert"?"inserted":"deleted";return{success:!0,llmContent:`Successfully ${O} cell in ${w}`,displayContent:`Cell ${O} in notebook`,metadata:{notebook_path:w,edit_mode:Z,cell_id:W}}}catch(J){let Y=J instanceof Error?J.message:"Unknown error";return{success:!1,llmContent:`Failed to edit notebook: ${Y}`,displayContent:"Notebook edit failed",error:{type:"execution_error",message:Y}}}}});import{z as w5}from"zod";var N1=L({name:"EnterPlanMode",displayName:"Enter Plan Mode",kind:"readonly",schema:w5.object({}),description:{short:"Use this tool to enter plan mode for complex tasks requiring careful planning",long:`Use this tool when you encounter a complex task that requires careful planning and exploration before implementation. This tool transitions you into plan mode where you can thoroughly explore the codebase and design an implementation approach.
691
575
 
692
576
  ## When to Use This Tool
693
577
 
@@ -779,7 +663,7 @@ Begin your research now.`,displayContent:"✅ Entering Plan mode",metadata:{appr
779
663
 
780
664
  `+"Proceed with the task directly without planning phase. You can still use search tools to understand the codebase as needed, but implement the solution directly.",displayContent:"⚠️ Plan mode declined, proceeding directly",metadata:{approved:!1,enterPlanMode:!1}}}catch(w){return{success:!1,llmContent:`Confirmation flow error: ${w instanceof Error?w.message:"Unknown error"}`,displayContent:"❌ Failed to request confirmation",error:{type:"execution_error",message:"Confirmation flow error"}}}return{success:!0,llmContent:`Plan mode requested but no interactive confirmation available.
781
665
 
782
- Proceeding with research phase. Use read-only tools to explore the codebase, then call ExitPlanMode with your implementation plan when ready.`,displayContent:"Plan mode (non-interactive)",metadata:{approved:null,enterPlanMode:!0}}}});import{promises as y4}from"node:fs";import{homedir as T7}from"node:os";import*as k1 from"node:path";import{z as z4}from"zod";var f1=E({name:"ExitPlanMode",displayName:"Exit Plan Mode",kind:"readonly",schema:z4.object({plan:z4.string().describe("The complete implementation plan in markdown format")}),description:{short:"Use this tool when you are in plan mode and have finished creating your plan and are ready for user approval",long:`Use this tool when you are in plan mode and have finished creating your implementation plan and are ready for user approval.
666
+ Proceeding with research phase. Use read-only tools to explore the codebase, then call ExitPlanMode with your implementation plan when ready.`,displayContent:"Plan mode (non-interactive)",metadata:{approved:null,enterPlanMode:!0}}}});import{promises as k4}from"node:fs";import{homedir as W5}from"node:os";import*as S1 from"node:path";import{z as f4}from"zod";var y1=L({name:"ExitPlanMode",displayName:"Exit Plan Mode",kind:"readonly",schema:f4.object({plan:f4.string().describe("The complete implementation plan in markdown format")}),description:{short:"Use this tool when you are in plan mode and have finished creating your plan and are ready for user approval",long:`Use this tool when you are in plan mode and have finished creating your implementation plan and are ready for user approval.
783
667
 
784
668
  ## \uD83D\uDEA8 PREREQUISITES (MUST be satisfied before calling)
785
669
 
@@ -814,7 +698,7 @@ Before using this tool, ensure your plan is clear and unambiguous. If there are
814
698
  1. Initial task: "Search for and understand the implementation of vim mode in the codebase" - Do not use the exit plan mode tool because you are not planning the implementation steps of a task.
815
699
  2. Initial task: "Help me implement yank mode for vim" - Use the exit plan mode tool after you have finished planning the implementation steps of the task.
816
700
  3. Initial task: "Add a new feature to handle user authentication" - If unsure about auth method (OAuth, JWT, etc.), use AskUserQuestion first, then use exit plan mode tool after clarifying the approach.
817
- `},async execute($,b){let w=$.plan||"";if(w&&b.sessionId)try{let V=k1.join(T7(),".blade","plans");await y4.mkdir(V,{recursive:!0,mode:493});let W=k1.join(V,`plan_${b.sessionId}.md`);await y4.writeFile(W,w,"utf-8")}catch(V){console.warn("Failed to save plan file:",V)}if(b.confirmationHandler)try{let V=await b.confirmationHandler.requestConfirmation({type:"exitPlanMode",message:`The assistant has finished planning and is ready for your review.
701
+ `},async execute($,b){let w=$.plan||"";if(w&&b.sessionId)try{let W=S1.join(W5(),".blade","plans");await k4.mkdir(W,{recursive:!0,mode:493});let V=S1.join(W,`plan_${b.sessionId}.md`);await k4.writeFile(V,w,"utf-8")}catch(W){console.warn("Failed to save plan file:",W)}if(b.confirmationHandler)try{let W=await b.confirmationHandler.requestConfirmation({type:"exitPlanMode",message:`The assistant has finished planning and is ready for your review.
818
702
 
819
703
  `+`⚠️ Before approving, please verify:
820
704
  `+`1. The assistant has written a detailed plan to the plan file
@@ -822,45 +706,45 @@ Before using this tool, ensure your plan is clear and unambiguous. If there are
822
706
  3. You have seen text explanations from the assistant (not just tool calls)
823
707
 
824
708
  If the assistant only made tool calls without presenting a plan summary,
825
- please reject and ask for a proper plan.`,details:"After approval, the assistant will exit Plan mode and begin implementation.",planContent:w||void 0});if(V.approved)return{success:!0,llmContent:"✅ Plan approved by user. Plan mode exited; you can proceed to code changes.",displayContent:"✅ Plan approved, exiting Plan mode",metadata:{approved:!0,shouldExitLoop:!0,targetMode:V.targetMode,planContent:w}};else return{success:!0,llmContent:`⚠️ Plan rejected by user. Awaiting user feedback.
709
+ please reject and ask for a proper plan.`,details:"After approval, the assistant will exit Plan mode and begin implementation.",planContent:w||void 0});if(W.approved)return{success:!0,llmContent:"✅ Plan approved by user. Plan mode exited; you can proceed to code changes.",displayContent:"✅ Plan approved, exiting Plan mode",metadata:{approved:!0,shouldExitLoop:!0,targetMode:W.targetMode,planContent:w}};else return{success:!0,llmContent:`⚠️ Plan rejected by user. Awaiting user feedback.
826
710
 
827
- `+(V.feedback||"No specific feedback provided.")+`
711
+ `+(W.feedback||"No specific feedback provided.")+`
828
712
 
829
- The agent has stopped and control is returned to the user. The user can now provide additional information or clarification.`,displayContent:"⚠️ 方案被拒绝,等待用户补充信息",metadata:{approved:!1,shouldExitLoop:!0,feedback:V.feedback,awaitingUserInput:!0}}}catch(V){return{success:!1,llmContent:`Confirmation flow error: ${V instanceof Error?V.message:"Unknown error"}`,displayContent:"❌ Confirmation failed",error:{type:"execution_error",message:"Confirmation flow error"}}}return{success:!0,llmContent:`✅ Plan mode exit requested. No interactive confirmation available.
830
- `+"Proceeding with implementation.",displayContent:"Plan mode exit (non-interactive)",metadata:{approved:null}}}});import g7 from"fast-glob";import{stat as m7}from"node:fs/promises";import{join as c7,resolve as i7}from"path";import{z as Db}from"zod";import{existsSync as k7,readFileSync as f7}from"node:fs";import{readFile as I7}from"node:fs/promises";import{dirname as P7,join as T4}from"node:path";import h7 from"fast-glob";import{LRUCache as x7}from"lru-cache";import l0 from"picomatch";function i0($){return $.replace(/\\/g,"/").split("/").filter(Boolean)}var t$=["node_modules",".git","dist","build","out",".next",".nuxt",".cache",".parcel-cache","coverage",".nyc_output",".idea",".vscode",".vs","bower_components","jspm_packages"],p7=["*.log","npm-debug.log*","yarn-debug.log*","pnpm-debug.log*","*.lock","package-lock.json","yarn.lock","pnpm-lock.yaml","*.tmp","*.temp","*.swp","*.bak","*~",".DS_Store","Thumbs.db","*.pid","*.seed"];function d7($){if(!k7($))return{patterns:[],negatePatterns:[]};try{let b=f7($,"utf-8"),w=[],V=[];for(let W of b.split(`
831
- `)){let Q=W.trim();if(!Q||Q.startsWith("#"))continue;if(Q.startsWith("!"))V.push(Q.slice(1));else w.push(Q)}return{patterns:w,negatePatterns:V}}catch(b){return console.warn(`Failed to read .gitignore: ${b}`),{patterns:[],negatePatterns:[]}}}var v4=new x7({max:100,ttl:30000,updateAgeOnGet:!0});async function u7($,b){let w=[...t$.map((J)=>`${J}/**`),...b?.scanIgnore??[]],V=`${$}|${w.join(",")}`,W=v4.get(V);if(W)return W;let Q=await h7("**/.gitignore",{cwd:$,dot:!0,onlyFiles:!0,followSymbolicLinks:!1,unique:!0,ignore:w});Q.sort((J,X)=>i0(J).length-i0(X).length);let Z=[];for(let J of Q){let X=P7(J).replace(/\\/g,"/"),O=X==="."?"":X,B=(await I7(T4($,J),"utf-8")).split(`
832
- `);for(let q of B){let U=q.trim();if(!U||U.startsWith("#"))continue;let K=U.startsWith("!"),C=(K?U.slice(1):U).trim();if(!C)continue;let H="";if(C.startsWith("/")){let F=C.slice(1).replace(/\\/g,"/");if(H=(O?O+"/":"")+F,Z.push({type:K?"negate":"ignore",pattern:H}),C.endsWith("/")){let M=H+"**";Z.push({type:K?"negate":"ignore",pattern:M});let L=H.replace(/\/$/,"");if(L!==H)Z.push({type:K?"negate":"ignore",pattern:L})}}else{let F=C.replace(/\\/g,"/");if(F.includes("/")){if(H=(O?O+"/":"")+F,Z.push({type:K?"negate":"ignore",pattern:H}),F.endsWith("/")){let M=H+"**";Z.push({type:K?"negate":"ignore",pattern:M});let L=H.replace(/\/$/,"");if(L!==H)Z.push({type:K?"negate":"ignore",pattern:L})}}else H=(O?O+"/**/":"**/")+F,Z.push({type:K?"negate":"ignore",pattern:H})}}}let Y=b?.cacheTTL??30000;return v4.set(V,Z,{ttl:Y}),Z}class Eb{orderedRules=[];ignorePatterns=[];negatePatterns=[];constructor($={}){this.initialize($)}static async create($={}){let b=new Eb({...$,useGitignore:!1}),{cwd:w=process.cwd(),useGitignore:V=!0,gitignoreScanMode:W="root",customScanIgnore:Q=[],cacheTTL:Z}=$;if(V&&W==="recursive"){let Y=await u7(w,{scanIgnore:Q,cacheTTL:Z});for(let J of Y)if(b.orderedRules.push({type:J.type,matcher:l0(J.pattern,{dot:!0})}),J.type==="ignore")b.ignorePatterns.push(J.pattern);else b.negatePatterns.push(J.pattern)}return b}initialize($){let{cwd:b=process.cwd(),useGitignore:w=!0,useDefaults:V=!0,customPatterns:W=[]}=$,Q=[],Z=[];if(V){let Y=[...t$.map((J)=>`${J}/**`),...t$,...p7];Q.push(...Y);for(let J of Y)this.orderedRules.push({type:"ignore",matcher:l0(J,{dot:!0})})}if(w){let Y=T4(b,".gitignore"),{patterns:J,negatePatterns:X}=d7(Y);for(let O of J)this.orderedRules.push({type:"ignore",matcher:l0(O,{dot:!0})}),Q.push(O);for(let O of X)this.orderedRules.push({type:"negate",matcher:l0(O,{dot:!0})}),Z.push(O)}Q.push(...W);for(let Y of W)this.orderedRules.push({type:"ignore",matcher:l0(Y,{dot:!0})});this.ignorePatterns=Q,this.negatePatterns=Z}shouldIgnore($){let b=$.replace(/\\/g,"/"),w;for(let V of this.orderedRules)if(V.matcher(b))w=V.type==="ignore";return w===!0}shouldIgnoreDirectory($){let b=$.replace(/\\/g,"/");return this.shouldIgnore(b)||this.shouldIgnore(`${b}/`)}filter($){return $.filter((b)=>!this.shouldIgnore(b))}getIgnorePatterns(){return this.ignorePatterns}getNegatePatterns(){return this.negatePatterns}}function I1($){let b=Error($);return b.name="AbortError",b}var P1=E({name:"Glob",displayName:"File Pattern Match",kind:"readonly",schema:Db.object({pattern:P.glob({description:"Glob pattern string (supports *, ?, ** wildcards)"}),path:Db.string().optional().describe("Search path (optional, defaults to cwd)"),max_results:P.positiveInt({description:"Maximum number of results"}).max(1000,"At most 1000 results can be returned").default(100),include_directories:Db.boolean().default(!1).describe("Include directories in results"),case_sensitive:Db.boolean().default(!1).describe("Case sensitive matching")}),description:{short:"Fast file pattern matching tool that works with any codebase size",long:'Fast file pattern matching tool that works with any codebase size. Supports glob patterns like "**/*.js" or "src/**/*.ts". Returns matching file paths sorted by modification time.',usageNotes:["Use this tool when you need to find files by name patterns","When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead","You can call multiple tools in a single response. It is always better to speculatively perform multiple searches in parallel if they are potentially useful."]},async execute($,b){let{pattern:w,path:V=process.cwd(),max_results:W,include_directories:Q,case_sensitive:Z}=$,{updateOutput:Y}=b,J=b.signal??new AbortController().signal;try{Y?.(`Searching in ${V} for pattern "${w}"...`);let X=i7(V);try{if(!(await m7(X)).isDirectory())return{success:!1,llmContent:`Search path must be a directory: ${X}`,displayContent:`❌ 搜索路径必须是目录: ${X}`,error:{type:"validation_error",message:"搜索路径必须是目录"}}}catch(C){if(C.code==="ENOENT")return{success:!1,llmContent:`Search path does not exist: ${X}`,displayContent:`❌ 搜索路径不存在: ${X}`,error:{type:"execution_error",message:"搜索路径不存在"}};throw C}J.throwIfAborted();let O=await Eb.create({cwd:X,useGitignore:!0,useDefaults:!0,gitignoreScanMode:"recursive",customScanIgnore:[],cacheTTL:30000}),{matches:G,wasTruncated:B}=await l7(X,w,{maxResults:W,includeDirectories:Q,caseSensitive:Z,signal:J},O),q=n7(G),U={search_path:X,pattern:w,total_matches:G.length,returned_matches:G.length,max_results:W,include_directories:Q,case_sensitive:Z,truncated:B},K=s7(U),_;if(q.length>0)_=`${B?`Found at least ${q.length} file(s) matching "${w}" (truncated)`:`Found ${q.length} file(s) matching "${w}"`}:
713
+ The agent has stopped and control is returned to the user. The user can now provide additional information or clarification.`,displayContent:"⚠️ 方案被拒绝,等待用户补充信息",metadata:{approved:!1,shouldExitLoop:!0,feedback:W.feedback,awaitingUserInput:!0}}}catch(W){return{success:!1,llmContent:`Confirmation flow error: ${W instanceof Error?W.message:"Unknown error"}`,displayContent:"❌ Confirmation failed",error:{type:"execution_error",message:"Confirmation flow error"}}}return{success:!0,llmContent:`✅ Plan mode exit requested. No interactive confirmation available.
714
+ `+"Proceeding with implementation.",displayContent:"Plan mode exit (non-interactive)",metadata:{approved:null}}}});import K5 from"fast-glob";import{stat as q5}from"node:fs/promises";import{join as A5,resolve as F5}from"path";import{z as Sb}from"zod";import{existsSync as V5,readFileSync as Q5}from"node:fs";import{readFile as Z5}from"node:fs/promises";import{dirname as J5,join as P4}from"node:path";import Y5 from"fast-glob";import{LRUCache as X5}from"lru-cache";import a0 from"picomatch";function r0($){return $.replace(/\\/g,"/").split("/").filter(Boolean)}var W0=["node_modules",".git","dist","build","out",".next",".nuxt",".cache",".parcel-cache","coverage",".nyc_output",".idea",".vscode",".vs","bower_components","jspm_packages"],O5=["*.log","npm-debug.log*","yarn-debug.log*","pnpm-debug.log*","*.lock","package-lock.json","yarn.lock","pnpm-lock.yaml","*.tmp","*.temp","*.swp","*.bak","*~",".DS_Store","Thumbs.db","*.pid","*.seed"];function G5($){if(!V5($))return{patterns:[],negatePatterns:[]};try{let b=Q5($,"utf-8"),w=[],W=[];for(let V of b.split(`
715
+ `)){let Q=V.trim();if(!Q||Q.startsWith("#"))continue;if(Q.startsWith("!"))W.push(Q.slice(1));else w.push(Q)}return{patterns:w,negatePatterns:W}}catch(b){return console.warn(`Failed to read .gitignore: ${b}`),{patterns:[],negatePatterns:[]}}}var I4=new X5({max:100,ttl:30000,updateAgeOnGet:!0});async function B5($,b){let w=[...W0.map((Y)=>`${Y}/**`),...b?.scanIgnore??[]],W=`${$}|${w.join(",")}`,V=I4.get(W);if(V)return V;let Q=await Y5("**/.gitignore",{cwd:$,dot:!0,onlyFiles:!0,followSymbolicLinks:!1,unique:!0,ignore:w});Q.sort((Y,X)=>r0(Y).length-r0(X).length);let Z=[];for(let Y of Q){let X=J5(Y).replace(/\\/g,"/"),O=X==="."?"":X,B=(await Z5(P4($,Y),"utf-8")).split(`
716
+ `);for(let K of B){let C=K.trim();if(!C||C.startsWith("#"))continue;let q=C.startsWith("!"),U=(q?C.slice(1):C).trim();if(!U)continue;let H="";if(U.startsWith("/")){let R=U.slice(1).replace(/\\/g,"/");if(H=(O?O+"/":"")+R,Z.push({type:q?"negate":"ignore",pattern:H}),U.endsWith("/")){let T=H+"**";Z.push({type:q?"negate":"ignore",pattern:T});let N=H.replace(/\/$/,"");if(N!==H)Z.push({type:q?"negate":"ignore",pattern:N})}}else{let R=U.replace(/\\/g,"/");if(R.includes("/")){if(H=(O?O+"/":"")+R,Z.push({type:q?"negate":"ignore",pattern:H}),R.endsWith("/")){let T=H+"**";Z.push({type:q?"negate":"ignore",pattern:T});let N=H.replace(/\/$/,"");if(N!==H)Z.push({type:q?"negate":"ignore",pattern:N})}}else H=(O?O+"/**/":"**/")+R,Z.push({type:q?"negate":"ignore",pattern:H})}}}let J=b?.cacheTTL??30000;return I4.set(W,Z,{ttl:J}),Z}class Nb{orderedRules=[];ignorePatterns=[];negatePatterns=[];constructor($={}){this.initialize($)}static async create($={}){let b=new Nb({...$,useGitignore:!1}),{cwd:w=process.cwd(),useGitignore:W=!0,gitignoreScanMode:V="root",customScanIgnore:Q=[],cacheTTL:Z}=$;if(W&&V==="recursive"){let J=await B5(w,{scanIgnore:Q,cacheTTL:Z});for(let Y of J)if(b.orderedRules.push({type:Y.type,matcher:a0(Y.pattern,{dot:!0})}),Y.type==="ignore")b.ignorePatterns.push(Y.pattern);else b.negatePatterns.push(Y.pattern)}return b}initialize($){let{cwd:b=process.cwd(),useGitignore:w=!0,useDefaults:W=!0,customPatterns:V=[]}=$,Q=[],Z=[];if(W){let J=[...W0.map((Y)=>`${Y}/**`),...W0,...O5];Q.push(...J);for(let Y of J)this.orderedRules.push({type:"ignore",matcher:a0(Y,{dot:!0})})}if(w){let J=P4(b,".gitignore"),{patterns:Y,negatePatterns:X}=G5(J);for(let O of Y)this.orderedRules.push({type:"ignore",matcher:a0(O,{dot:!0})}),Q.push(O);for(let O of X)this.orderedRules.push({type:"negate",matcher:a0(O,{dot:!0})}),Z.push(O)}Q.push(...V);for(let J of V)this.orderedRules.push({type:"ignore",matcher:a0(J,{dot:!0})});this.ignorePatterns=Q,this.negatePatterns=Z}shouldIgnore($){let b=$.replace(/\\/g,"/"),w;for(let W of this.orderedRules)if(W.matcher(b))w=W.type==="ignore";return w===!0}shouldIgnoreDirectory($){let b=$.replace(/\\/g,"/");return this.shouldIgnore(b)||this.shouldIgnore(`${b}/`)}filter($){return $.filter((b)=>!this.shouldIgnore(b))}getIgnorePatterns(){return this.ignorePatterns}getNegatePatterns(){return this.negatePatterns}}function C5($){let b=$.stats;if(!b||typeof b!=="object")return;if(typeof b.isDirectory!=="function")return;return b}function M1($){let b=Error($);return b.name="AbortError",b}var z1=L({name:"Glob",displayName:"File Pattern Match",kind:"readonly",schema:Sb.object({pattern:P.glob({description:"Glob pattern string (supports *, ?, ** wildcards)"}),path:Sb.string().optional().describe("Search path (optional, defaults to cwd)"),max_results:P.positiveInt({description:"Maximum number of results"}).max(1000,"At most 1000 results can be returned").default(100),include_directories:Sb.boolean().default(!1).describe("Include directories in results"),case_sensitive:Sb.boolean().default(!1).describe("Case sensitive matching")}),description:{short:"Fast file pattern matching tool that works with any codebase size",long:'Fast file pattern matching tool that works with any codebase size. Supports glob patterns like "**/*.js" or "src/**/*.ts". Returns matching file paths sorted by modification time.',usageNotes:["Use this tool when you need to find files by name patterns","When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead","You can call multiple tools in a single response. It is always better to speculatively perform multiple searches in parallel if they are potentially useful."]},async execute($,b){let{pattern:w,path:W=process.cwd(),max_results:V,include_directories:Q,case_sensitive:Z}=$,{updateOutput:J}=b,Y=b.signal??new AbortController().signal;try{J?.(`Searching in ${W} for pattern "${w}"...`);let X=F5(W);try{if(!(await q5(X)).isDirectory())return{success:!1,llmContent:`Search path must be a directory: ${X}`,displayContent:`❌ 搜索路径必须是目录: ${X}`,error:{type:"validation_error",message:"搜索路径必须是目录"}}}catch(U){if(n(U)==="ENOENT")return{success:!1,llmContent:`Search path does not exist: ${X}`,displayContent:`❌ 搜索路径不存在: ${X}`,error:{type:"execution_error",message:"搜索路径不存在"}};throw U}Y.throwIfAborted();let O=await Nb.create({cwd:X,useGitignore:!0,useDefaults:!0,gitignoreScanMode:"recursive",customScanIgnore:[],cacheTTL:30000}),{matches:G,wasTruncated:B}=await U5(X,w,{maxResults:V,includeDirectories:Q,caseSensitive:Z,signal:Y},O),K=R5(G),C={search_path:X,pattern:w,total_matches:G.length,returned_matches:G.length,max_results:V,include_directories:Q,case_sensitive:Z,truncated:B},q=H5(C),F;if(K.length>0)F=`${B?`Found at least ${K.length} file(s) matching "${w}" (truncated)`:`Found ${K.length} file(s) matching "${w}"`}:
833
717
 
834
- `+q.map((H)=>`- ${H.relative_path}`).join(`
718
+ `+K.map((H)=>`- ${H.relative_path}`).join(`
835
719
  `)+`
836
720
 
837
- Use the relative_path values above for Read/Edit operations.`;else _=`No files found matching "${w}"`;return{success:!0,llmContent:_,displayContent:K,metadata:{...U,matches:q}}}catch(X){let O=X;if(O.name==="AbortError")return{success:!1,llmContent:"File search aborted",displayContent:"⚠️ 文件搜索被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Search failed: ${O.message}`,displayContent:`❌ 搜索失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"搜索工具",tags:["file","search","glob","pattern","wildcard"],extractSignatureContent:($)=>$.pattern,abstractPermissionRule:()=>"*"});async function l7($,b,w,V){let W=V.getIgnorePatterns(),Q=[],Z=!1;return await new Promise((Y,J)=>{if(w.signal.aborted){J(I1("文件搜索被用户中止"));return}let X=g7.stream(b,{cwd:$,dot:!0,followSymbolicLinks:!1,unique:!0,caseSensitiveMatch:w.caseSensitive,objectMode:!0,stats:!0,onlyFiles:!w.includeDirectories,ignore:W}),O=!1,G=null,B=()=>{if(G){if(w.signal.removeEventListener)w.signal.removeEventListener("abort",G);else if("onabort"in w.signal)w.signal.onabort=null;G=null}},q=()=>{if(!O)O=!0,Z=!0,X.destroy(),B(),Y({matches:Q,wasTruncated:Z})},U=(K)=>{if(w.signal.aborted){if(!O)O=!0,X.destroy(I1("文件搜索被用户中止"));return}if(Q.length>=w.maxResults){q();return}let _=K.path.replace(/\\/g,"/"),C=c7($,_);if(V.shouldIgnore(_))return;let H=K.stats?K.stats.isDirectory():!1;if(H&&V.shouldIgnoreDirectory(_))return;let F=K.stats&&K.stats.isFile()?K.stats.size:void 0,M=K.stats?K.stats.mtime.toISOString():void 0;if(Q.push({path:C,relative_path:_,is_directory:H,size:F,modified:M}),Q.length>=w.maxResults)q()};if(X.on("data",U),G=()=>{if(!O)O=!0,B(),X.destroy(I1("文件搜索被用户中止"))},w.signal.addEventListener)w.signal.addEventListener("abort",G);else if("onabort"in w.signal)w.signal.onabort=G;X.once("error",(K)=>{if(!O)O=!0,B(),J(K)}),X.once("end",()=>{if(!O)O=!0,B(),Y({matches:Q,wasTruncated:Z})})})}function n7($){return $.sort((b,w)=>{if(b.is_directory!==w.is_directory)return b.is_directory?1:-1;if(b.modified&&w.modified)return new Date(w.modified).getTime()-new Date(b.modified).getTime();return b.relative_path.localeCompare(w.relative_path)})}function s7($){let{search_path:b,pattern:w,total_matches:V,returned_matches:W,truncated:Q}=$,Z;if(Q)Z=`✅ 在 ${b} 中找到至少 ${V} 个匹配 "${w}" 的文件(已截断)`,Z+=`
838
- \uD83D\uDCCB 显示前 ${W} 个结果`;else Z=`✅ 在 ${b} 中找到 ${V} 个匹配 "${w}" 的文件`;return Z}import{execSync as h1,spawn as x1}from"child_process";import{existsSync as Lb}from"fs";import{readdir as r7,readFile as a7}from"fs/promises";import{join as k4,relative as o7}from"path";import t7 from"picomatch";import{z as m$}from"zod";function e7(){let{platform:$,arch:b}=process,w={"darwin-arm64":"darwin-arm64/rg","darwin-x64":"darwin-x64/rg","linux-arm64":"linux-arm64/rg","linux-x64":"linux-x64/rg","win32-x64":"win32-x64/rg.exe"},V=`${$}-${b}`,W=w[V];if(!W)return null;let Q=k4(process.cwd(),"vendor","ripgrep",W);if(Lb(Q))return Q;try{let Z=new URL("../../../../vendor/ripgrep/"+W,import.meta.url).pathname;if(Lb(Z))return Z}catch{}return null}function f4(){try{let b=process.platform==="win32"?"where rg":"command -v rg 2>/dev/null || which rg 2>/dev/null",w=h1(b,{encoding:"utf8",stdio:["pipe","pipe","ignore"]}).split(/\r?\n/)[0].trim();if(w)return w}catch{}let $=e7();if($&&Lb($))return $;try{let b=O0("@vscode/ripgrep");if(b?.rgPath&&Lb(b.rgPath))return b.rgPath}catch{}return null}async function $6($){try{return h1("git rev-parse --git-dir",{cwd:$,stdio:"ignore"}),!0}catch{return!1}}function b6(){try{return h1("grep --version",{stdio:"ignore"}),!0}catch{return!1}}async function w6($,b,w,V){let W=f4();if(!W)throw Error("ripgrep not available");return new Promise((Q,Z)=>{let Y=x1(W,$,{stdio:["pipe","pipe","pipe"]}),J="",X="";Y.stdout.on("data",(G)=>{J+=G.toString()}),Y.stderr.on("data",(G)=>{X+=G.toString()}),Y.on("close",(G)=>{Q({stdout:J,stderr:X,exitCode:G||0})}),Y.on("error",(G)=>{Z(G)});let O=()=>{Y.kill("SIGTERM"),Z(Error("搜索被用户中止"))};w.addEventListener("abort",O),Y.on("close",()=>{w.removeEventListener("abort",O)})})}async function V6($,b,w,V){let W=["grep","-n"];if(w.caseInsensitive)W.push("-i");if(w.contextLines!==void 0)W.push(`-C${w.contextLines}`);if(W.push("-e",$),w.glob)W.push("--",w.glob);return new Promise((Q,Z)=>{let Y=x1("git",W,{cwd:b,stdio:["pipe","pipe","pipe"]}),J="",X="";Y.stdout.on("data",(G)=>{J+=G.toString()}),Y.stderr.on("data",(G)=>{X+=G.toString()}),Y.on("close",(G)=>{Q({stdout:J,stderr:X,exitCode:G||0})}),Y.on("error",(G)=>{Z(G)});let O=()=>{Y.kill("SIGTERM"),Z(Error("搜索被用户中止"))};V.addEventListener("abort",O),Y.on("close",()=>{V.removeEventListener("abort",O)})})}async function W6($,b,w,V){let W=["-rn"];if(w.caseInsensitive)W.push("-i");if(w.contextLines!==void 0)W.push(`-C${w.contextLines}`);for(let Q of t$)W.push("--exclude-dir="+Q.replace(/^\./,""));return W.push("-e",$,b),new Promise((Q,Z)=>{let Y=x1("grep",W,{stdio:["pipe","pipe","pipe"]}),J="",X="";Y.stdout.on("data",(G)=>{J+=G.toString()}),Y.stderr.on("data",(G)=>{X+=G.toString()}),Y.on("close",(G)=>{Q({stdout:J,stderr:X,exitCode:G||0})}),Y.on("error",(G)=>{Z(G)});let O=()=>{Y.kill("SIGTERM"),Z(Error("搜索被用户中止"))};V.addEventListener("abort",O),Y.on("close",()=>{V.removeEventListener("abort",O)})})}async function Q6($,b,w,V){let W=[],Q=new RegExp($,w.caseInsensitive?"gi":"g"),Z=await Z6(b,V),Y=0;for(let J of Z){if(V.throwIfAborted(),I4(J))continue;if(w.glob&&!Y6(J,w.glob))continue;try{(await a7(J,"utf-8")).split(`
839
- `).forEach((G,B)=>{if(Q.test(G))W.push({file_path:o7(b,J),line_number:B+1,content:G})}),Y++}catch(X){}}return{matches:W,totalFiles:Y}}async function Z6($,b){let w=[];async function V(W){b.throwIfAborted();try{let Q=await r7(W,{withFileTypes:!0});for(let Z of Q){b.throwIfAborted();let Y=k4(W,Z.name);if(Z.isDirectory()){if(!I4(Y))await V(Y)}else if(Z.isFile())w.push(Y)}}catch(Q){}}return await V($),w}function I4($){for(let b of t$)if($.includes(b))return!0;return!1}function Y6($,b){return t7(b)($)}function J6($){let b=[];if($.case_insensitive)b.push("-i");if($.multiline)b.push("-U","--multiline-dotall");switch($.output_mode){case"files_with_matches":b.push("-l");break;case"count":b.push("-c");break;case"content":if($.line_numbers)b.push("-n");break}if($.context!==void 0&&$.output_mode==="content")b.push("-C",$.context.toString());else{if($.context_before!==void 0&&$.output_mode==="content")b.push("-B",$.context_before.toString());if($.context_after!==void 0&&$.output_mode==="content")b.push("-A",$.context_after.toString())}if($.type)b.push("--type",$.type);for(let w of t$)b.push("--glob",`!${w}/**`);if($.glob)b.push("--glob",$.glob);if($.head_limit!==void 0){let w=($.offset??0)+$.head_limit;b.push("-m",w.toString())}return b.push($.pattern),b.push($.path),b}function X6($,b){if(!$.trim())return[];let w=$.trim().split(`
840
- `),V=[];switch(b){case"files_with_matches":return w.map((W)=>({file_path:W.trim()}));case"count":return w.map((W)=>{let[Q,Z]=W.split(":");return{file_path:Q,count:parseInt(Z,10)}});case"content":for(let W of w){let Q=O6(W);if(Q)V.push(Q)}return V;default:return[]}}function O6($){let b=$.indexOf(":");if(b===-1)return null;let w=$.substring(0,b),V=$.substring(b+1),W=V.indexOf(":");if(W!==-1&&/^\d+$/.test(V.substring(0,W))){let Q=parseInt(V.substring(0,W),10),Z=V.substring(W+1);return{file_path:w,line_number:Q,content:Z}}else return{file_path:w,content:V}}function G6($){let{search_pattern:b,search_path:w,output_mode:V,total_matches:W,strategy:Q}=$,Z=`✅ 在 ${w} 中搜索 "${b}"`;if(Q)Z+=`
841
- \uD83D\uDD27 使用策略: ${Q}`;switch(V){case"files_with_matches":Z+=`
842
- \uD83D\uDCC1 找到 ${W} 个包含匹配内容的文件`;break;case"count":Z+=`
843
- \uD83D\uDD22 统计了 ${W} 个文件的匹配数量`;break;case"content":Z+=`
844
- \uD83D\uDCDD 找到 ${W} 个匹配行`;break}return Z}var p1=E({name:"Grep",displayName:"内容搜索",kind:"readonly",schema:m$.object({pattern:P.pattern({description:"The regular expression pattern to search for in file contents"}),path:m$.string().optional().describe("File or directory to search in (rg PATH). Defaults to current working directory"),glob:m$.string().optional().describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}") - maps to rg --glob'),type:m$.string().optional().describe("File type to search (rg --type). Common types: js, py, rust, go, java, etc. More efficient than include for standard file types"),output_mode:m$.enum(["content","files_with_matches","count"]).default("files_with_matches").describe('Output mode: "content" shows matching lines (supports -A/-B/-C context, -n line numbers, head_limit), "files_with_matches" shows file paths (supports head_limit), "count" shows match counts (supports head_limit). Defaults to "files_with_matches"'),"-i":m$.boolean().optional().describe("Case insensitive search (rg -i)"),"-n":m$.boolean().default(!0).describe('Show line numbers in output (rg -n). Requires output_mode: "content", ignored otherwise. Defaults to true'),"-B":P.nonNegativeInt().optional().describe('Number of lines to show before each match (rg -B). Requires output_mode: "content", ignored otherwise'),"-A":P.nonNegativeInt().optional().describe('Number of lines to show after each match (rg -A). Requires output_mode: "content", ignored otherwise'),"-C":P.nonNegativeInt().optional().describe('Number of lines to show before and after each match (rg -C). Requires output_mode: "content", ignored otherwise'),head_limit:P.positiveInt().optional().describe('Limit output to first N lines/entries, equivalent to "| head -N". Works across all output modes: content (limits output lines), files_with_matches (limits file paths), count (limits count entries). Defaults based on "cap" experiment value: 0 (unlimited), 20, or 100'),offset:P.nonNegativeInt().optional().describe('Skip first N lines/entries before applying head_limit, equivalent to "| tail -n +N | head -N". Works across all output modes. Defaults to 0'),multiline:m$.boolean().default(!1).describe("Enable multiline mode where . matches newlines and patterns can span lines (rg -U --multiline-dotall). Default: false")}),description:{short:"A powerful search tool built on ripgrep",long:'A powerful search tool built on ripgrep\n\n Usage:\n - ALWAYS use Grep for search tasks. NEVER invoke `grep` or `rg` as a Bash command. The Grep tool has been optimized for correct permissions and access.\n - Supports full regex syntax (e.g., "log.*Error", "function\\s+\\w+")\n - Filter files with glob parameter (e.g., "*.js", "**/*.tsx") or type parameter (e.g., "js", "py", "rust")\n - Output modes: "content" shows matching lines, "files_with_matches" shows only file paths (default), "count" shows match counts\n - Use Task tool for open-ended searches requiring multiple rounds\n - Pattern syntax: Uses ripgrep (not grep) - literal braces need escaping (use `interface\\{\\}` to find `interface{}` in Go code)\n - Multiline matching: By default patterns match within single lines only. For cross-line patterns like `struct \\{[\\s\\S]*?field`, use `multiline: true`\n'},async execute($,b){let{pattern:w,path:V=process.cwd(),glob:W,type:Q,output_mode:Z,"-i":Y,"-n":J=!0,"-B":X,"-A":O,"-C":G,head_limit:B,offset:q,multiline:U}=$,{updateOutput:K}=b,_=b.signal??new AbortController().signal;try{K?.(`使用智能搜索策略查找模式 "${w}"...`);let C=null,H="ripgrep",F=[],M=f4();if(M)try{K?.(`\uD83D\uDE80 使用 ripgrep (${M})`);let c=J6({pattern:w,path:V,glob:W,type:Q,output_mode:Z,case_insensitive:Y??!1,line_numbers:J,context_before:X,context_after:O,context:G,head_limit:B,offset:q,multiline:U??!1});C=await w6(c,Z,_,K),H="ripgrep"}catch{K?.("⚠️ ripgrep 失败,尝试降级策略..."),C=null}if(!C&&await $6(V))try{K?.("\uD83D\uDCE6 使用 git grep"),C=await V6(w,V,{caseInsensitive:Y??!1,glob:W,contextLines:G},_),H="git-grep"}catch{K?.("⚠️ git grep 失败,继续尝试其他策略..."),C=null}if(!C&&b6())try{K?.("\uD83D\uDD27 使用系统 grep"),C=await W6(w,V,{caseInsensitive:Y??!1,contextLines:G},_),H="system-grep"}catch{K?.("⚠️ 系统 grep 失败,使用纯 JavaScript 实现..."),C=null}if(!C)K?.("\uD83D\uDCA1 使用纯 JavaScript 搜索实现"),F=(await Q6(w,V,{caseInsensitive:Y??!1,glob:W,multiline:U??!1},_)).matches,H="fallback",C={stdout:"",stderr:"",exitCode:0};else F=X6(C.stdout,Z);let L=F.length;if(q!==void 0&&q>0)F=F.slice(q);if(B!==void 0&&F.length>B)F=F.slice(0,B);let R={search_pattern:w,search_path:V,output_mode:Z,case_insensitive:Y??!1,total_matches:F.length,original_total:L,offset:q,head_limit:B,strategy:H,exit_code:C?.exitCode};if(C&&C.exitCode!==0&&C.stderr)return{success:!1,llmContent:`Search execution failed: ${C.stderr}`,displayContent:`❌ 搜索执行失败: ${C.stderr}`,error:{type:"execution_error",message:C.stderr}};let D=G6(R);return{success:!0,llmContent:F,displayContent:D,metadata:R}}catch(C){let H=C;if(H.name==="AbortError")return{success:!1,llmContent:"Search aborted",displayContent:"⚠️ 搜索被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Search failed: ${H.message}`,displayContent:`❌ 搜索失败: ${H.message}`,error:{type:"execution_error",message:H.message,details:H}}}},version:"3.0.0",category:"搜索工具",tags:["search","grep","ripgrep","regex","text","fallback"],extractSignatureContent:($)=>$.pattern,abstractPermissionRule:()=>"*"});import{spawn as _6}from"child_process";import{randomUUID as R6}from"crypto";import{z as d1}from"zod";import{execSync as B6}from"child_process";import{existsSync as K$,mkdtempSync as K6,writeFileSync as q6}from"fs";import{tmpdir as A6}from"os";import{join as n0}from"path";var jb=N("Tool");class f${static instance=null;capabilities=null;settings={};constructor(){}static getInstance(){if(!f$.instance)f$.instance=new f$;return f$.instance}static resetInstance(){f$.instance=null}configure($){this.settings={...$}}getCapabilities(){if(this.capabilities)return this.capabilities;return this.capabilities=this.detectCapabilities(),this.capabilities}detectCapabilities(){let $=process.platform;if($==="linux")return this.detectLinuxCapabilities();else if($==="darwin")return this.detectMacOSCapabilities();return{available:!1,type:"none",features:{fileSystemIsolation:!1,networkIsolation:!1,processIsolation:!1}}}detectLinuxCapabilities(){try{let $=B6("bwrap --version 2>/dev/null",{encoding:"utf-8"}).trim();return jb.debug(`[SandboxExecutor] Detected bubblewrap: ${$}`),{available:!0,type:"bubblewrap",version:$,features:{fileSystemIsolation:!0,networkIsolation:!0,processIsolation:!0}}}catch{return jb.debug("[SandboxExecutor] bubblewrap not available on Linux"),{available:!1,type:"none",features:{fileSystemIsolation:!1,networkIsolation:!1,processIsolation:!1}}}}detectMacOSCapabilities(){try{if(K$("/usr/bin/sandbox-exec"))return jb.debug("[SandboxExecutor] Detected macOS sandbox-exec (Seatbelt)"),{available:!0,type:"seatbelt",version:"macOS built-in",features:{fileSystemIsolation:!0,networkIsolation:!0,processIsolation:!0}}}catch{jb.debug("[SandboxExecutor] sandbox-exec not available on macOS")}return{available:!1,type:"none",features:{fileSystemIsolation:!1,networkIsolation:!1,processIsolation:!1}}}isEnabled(){return this.settings.enabled===!0}canUseSandbox(){return this.isEnabled()&&this.getCapabilities().available}wrapCommand($,b){if(!this.canUseSandbox())return $;let w=this.getCapabilities();if(w.type==="bubblewrap")return this.wrapWithBubblewrap($,b);else if(w.type==="seatbelt")return this.wrapWithSeatbelt($,b);return $}wrapWithBubblewrap($,b){let w=[];if(w.push("--ro-bind /usr /usr"),w.push("--ro-bind /bin /bin"),K$("/lib"))w.push("--ro-bind /lib /lib");if(K$("/lib64"))w.push("--ro-bind /lib64 /lib64");if(K$("/etc/resolv.conf"))w.push("--ro-bind /etc/resolv.conf /etc/resolv.conf");if(K$("/etc/hosts"))w.push("--ro-bind /etc/hosts /etc/hosts");if(K$("/etc/ssl"))w.push("--ro-bind /etc/ssl /etc/ssl");if(K$("/etc/ca-certificates"))w.push("--ro-bind /etc/ca-certificates /etc/ca-certificates");if(w.push("--proc /proc"),w.push("--dev /dev"),w.push("--tmpfs /tmp"),w.push(`--bind ${b.workDir} ${b.workDir}`),w.push(`--chdir ${b.workDir}`),b.allowedWritePaths){for(let Q of b.allowedWritePaths)if(K$(Q)&&Q!==b.workDir)w.push(`--bind ${Q} ${Q}`)}if(b.allowedReadPaths){for(let Q of b.allowedReadPaths)if(K$(Q))w.push(`--ro-bind ${Q} ${Q}`)}let V=process.env.HOME;if(V){let Q=n0(V,".nvm");if(K$(Q))w.push(`--ro-bind ${Q} ${Q}`);let Z=n0(V,".npm");if(K$(Z))w.push(`--bind ${Z} ${Z}`);let Y=n0(V,".pnpm");if(K$(Y))w.push(`--bind ${Y} ${Y}`)}if(!b.allowNetwork)w.push("--unshare-net");w.push("--unshare-user"),w.push("--unshare-pid"),w.push("--unshare-uts"),w.push("--unshare-cgroup"),w.push("--die-with-parent"),w.push("--new-session");let W=$.replace(/'/g,"'\\''");return`bwrap ${w.join(" ")} -- /bin/bash -c '${W}'`}wrapWithSeatbelt($,b){let w=this.generateSeatbeltProfile(b),V=K6(n0(A6(),"sandbox-")),W=n0(V,"sandbox.sb");q6(W,w,"utf-8");let Q=$.replace(/'/g,"'\\''");return`sandbox-exec -f '${W}' /bin/bash -c '${Q}'; EXIT_CODE=$?; rm -rf '${V}'; exit $EXIT_CODE`}generateSeatbeltProfile($){let b=[];b.push("(version 1)"),b.push("(deny default)"),b.push("(allow process-exec)"),b.push("(allow process-fork)"),b.push("(allow signal)"),b.push("(allow sysctl-read)"),b.push("(allow mach-lookup)"),b.push("(allow mach-register)"),b.push("(allow ipc-posix-shm)"),b.push("(allow file-read-metadata)"),b.push('(allow file-read* (subpath "/usr"))'),b.push('(allow file-read* (subpath "/bin"))'),b.push('(allow file-read* (subpath "/sbin"))'),b.push('(allow file-read* (subpath "/Library"))'),b.push('(allow file-read* (subpath "/System"))'),b.push('(allow file-read* (subpath "/private/var/db"))'),b.push('(allow file-read* (subpath "/private/etc"))'),b.push('(allow file-read* (subpath "/dev"))'),b.push('(allow file-read* (subpath "/var"))'),b.push('(allow file-read* (subpath "/opt/homebrew"))'),b.push('(allow file-read* (subpath "/usr/local"))');let w=process.env.HOME;if(w)b.push(`(allow file-read* (subpath "${w}/.nvm"))`),b.push(`(allow file-read* (subpath "${w}/.npm"))`),b.push(`(allow file-read* (subpath "${w}/.pnpm"))`),b.push(`(allow file-read* (subpath "${w}/.config"))`),b.push(`(allow file-write* (subpath "${w}/.npm"))`),b.push(`(allow file-write* (subpath "${w}/.pnpm"))`);if(b.push(`(allow file-read* (subpath "${$.workDir}"))`),b.push(`(allow file-write* (subpath "${$.workDir}"))`),$.allowedReadPaths)for(let V of $.allowedReadPaths)b.push(`(allow file-read* (subpath "${V}"))`);if($.allowedWritePaths)for(let V of $.allowedWritePaths)b.push(`(allow file-write* (subpath "${V}"))`);if(b.push('(allow file-read* (subpath "/private/tmp"))'),b.push('(allow file-write* (subpath "/private/tmp"))'),b.push('(allow file-read* (subpath "/tmp"))'),b.push('(allow file-write* (subpath "/tmp"))'),$.allowNetwork!==!1)b.push("(allow network*)");else b.push("(allow network-outbound (remote unix-socket))");return b.join(`
845
- `)}buildExecutionOptions($,b){let w={workDir:$,allowedReadPaths:[],allowedWritePaths:[],allowNetwork:!0};if(b){if(b.allowLocalBinding===!1)w.allowNetwork=!1}let V=process.env.HOME;if(V)w.allowedReadPaths?.push(V);return w}}function H0(){return f$.getInstance()}class I${static instance=null;settings={};constructor(){}static getInstance(){if(!I$.instance)I$.instance=new I$;return I$.instance}static resetInstance(){I$.instance=null}configure($){this.settings={...$},H0().configure($)}getSettings(){return{...this.settings}}isEnabled(){return this.settings.enabled===!0}shouldAutoAllowBash(){return this.isEnabled()&&this.settings.autoAllowBashIfSandboxed===!0}isCommandExcluded($){if(!this.settings.excludedCommands||this.settings.excludedCommands.length===0)return!1;let b=this.extractCommandName($);return this.settings.excludedCommands.some((w)=>b===w||$.startsWith(w+" "))}allowsUnsandboxedCommands(){return this.settings.allowUnsandboxedCommands===!0}checkCommand($){let{command:b,dangerouslyDisableSandbox:w}=$;if(!this.isEnabled())return{allowed:!0,reason:"Sandbox is disabled"};if(this.isCommandExcluded(b))return{allowed:!0,reason:"Command is in excluded list",isExcluded:!0};if(w)if(this.allowsUnsandboxedCommands())return{allowed:!1,reason:"Command requests unsandboxed execution",requiresPermission:!0};else return{allowed:!1,reason:"Unsandboxed commands are not allowed"};return{allowed:!0,reason:"Command will run in sandbox"}}shouldIgnoreFileViolation($){if(!this.settings.ignoreViolations?.file)return!1;return this.settings.ignoreViolations.file.some((b)=>{if(b.includes("*"))return new RegExp("^"+b.replace(/\*/g,".*")+"$").test($);return $.startsWith(b)})}shouldIgnoreNetworkViolation($){if(!this.settings.ignoreViolations?.network)return!1;return this.settings.ignoreViolations.network.some((b)=>{if(b.includes("*"))return new RegExp("^"+b.replace(/\*/g,".*")+"$").test($);return $===b||$.startsWith(b)})}getNetworkSettings(){return this.settings.network||{}}allowsLocalBinding(){return this.settings.network?.allowLocalBinding===!0}isUnixSocketAllowed($){let b=this.settings.network;if(!b)return!1;if(b.allowAllUnixSockets)return!0;if(b.allowUnixSockets&&b.allowUnixSockets.length>0)return b.allowUnixSockets.includes($);return!1}extractCommandName($){return $.trim().split(/\s+/)[0]||""}wrapCommandForSandbox($,b){if(!this.isEnabled())return $;let w=H0();if(!w.canUseSandbox())return $;let V=b||process.cwd(),W=w.buildExecutionOptions(V,this.settings.network);return w.wrapCommand($,W)}getCapabilities(){return H0().getCapabilities()}}function _0(){return I$.getInstance()}import{spawn as U6}from"child_process";import{randomUUID as C6}from"crypto";class O${static instance=null;processes=new Map;static getInstance(){if(!O$.instance)O$.instance=new O$;return O$.instance}startBackgroundProcess($){let b=`bash_${C6()}`,w={};for(let[Q,Z]of Object.entries({...process.env,...$.env,BLADE_CLI:"1"}))if(Z!==void 0)w[Q]=Z;let V=U6("bash",["-c",$.command],{cwd:$.cwd||process.cwd(),env:w,stdio:["ignore","pipe","pipe"]}),W={id:b,command:$.command,sessionId:$.sessionId,cwd:$.cwd,env:$.env,process:V,pid:V.pid,status:"running",startTime:Date.now(),pendingStdout:"",pendingStderr:""};return V.stdout?.setEncoding("utf8"),V.stderr?.setEncoding("utf8"),V.stdout?.on("data",(Q)=>{W.pendingStdout+=Q.toString()}),V.stderr?.on("data",(Q)=>{W.pendingStderr+=Q.toString()}),V.on("close",(Q,Z)=>{W.status=W.status==="killed"?"killed":"exited",W.exitCode=Q,W.signal=Z,W.endTime=Date.now(),W.process=void 0}),V.on("error",(Q)=>{W.status="error",W.errorMessage=Q.message,W.endTime=Date.now(),W.process=void 0,W.pendingStderr+=`
846
- [error] ${Q.message}`}),this.processes.set(b,W),W}consumeOutput($){let b=this.processes.get($);if(!b)return;let w={id:b.id,command:b.command,status:b.status,stdout:b.pendingStdout,stderr:b.pendingStderr,exitCode:b.exitCode,signal:b.signal,pid:b.pid,startedAt:b.startTime,endedAt:b.endTime,errorMessage:b.errorMessage};return b.pendingStdout="",b.pendingStderr="",w}getProcess($){return this.processes.get($)}kill($){let b=this.processes.get($);if(!b)return;if(b.status!=="running"||!b.process)return{success:!1,alreadyExited:!0,status:b.status,pid:b.pid,exitCode:b.exitCode,signal:b.signal};if(!b.process.kill("SIGTERM"))return{success:!1,alreadyExited:!1,status:b.status,pid:b.pid,exitCode:b.exitCode,signal:b.signal};return b.status="killed",b.endTime=Date.now(),b.process=void 0,{success:!0,alreadyExited:!1,status:b.status,pid:b.pid,exitCode:b.exitCode,signal:b.signal}}killAll(){for(let[$,b]of this.processes)if(b.status==="running"&&b.process)try{b.process.kill("SIGTERM"),b.status="killed",b.endTime=Date.now(),b.process=void 0}catch{}this.processes.clear()}}var Nb={maxLines:30,maxChars:3000,keepHead:10,keepTail:10,summarize:!0},e$={maxLines:100,maxChars:1e4,keepHead:40,keepTail:40,summarize:!0},P4={maxLines:200,maxChars:20000,keepHead:80,keepTail:80,summarize:!1},F6={maxLines:150,maxChars:15000,keepHead:50,keepTail:50,summarize:!0},H6=[{pattern:/^git\s+(rm|add)\s+(-r|--cached|-rf|-f)?\s*/i,config:Nb,summaryTemplate:($)=>`Successfully processed ${$} files`},{pattern:/^(npm|pnpm|yarn|bun)\s+(install|i|add|remove|uninstall)/i,config:Nb,summaryTemplate:($)=>`Package operation completed (${$} lines of output)`},{pattern:/^(npm|pnpm|yarn|bun)\s+(run|exec)\s+(build|compile|bundle)/i,config:e$,summaryTemplate:($)=>`Build completed (${$} lines of output)`},{pattern:/^(npm|pnpm|yarn|bun)\s+(run|exec)\s+(test|lint|check)/i,config:P4},{pattern:/^git\s+(status|branch|remote)/i,config:e$},{pattern:/^git\s+(log|diff|show)/i,config:P4},{pattern:/^(ls|dir|tree)\s+/i,config:e$,summaryTemplate:($)=>`Listed ${$} items`},{pattern:/^find\s+/i,config:e$,summaryTemplate:($)=>`Found ${$} matches`},{pattern:/^(grep|rg|ag)\s+/i,config:e$,summaryTemplate:($)=>`Found ${$} matching lines`},{pattern:/^(docker|podman)\s+(build|pull|push)/i,config:Nb,summaryTemplate:($)=>`Docker operation completed (${$} lines)`},{pattern:/^(pip|pip3|poetry|pipenv)\s+(install|uninstall)/i,config:Nb,summaryTemplate:($)=>`Python package operation completed (${$} lines)`},{pattern:/^(cargo|rustup)\s+(build|install|update)/i,config:e$,summaryTemplate:($)=>`Rust operation completed (${$} lines)`},{pattern:/^(go)\s+(build|get|mod)/i,config:e$,summaryTemplate:($)=>`Go operation completed (${$} lines)`}];class y${static getConfigForCommand($){for(let{pattern:b,config:w,summaryTemplate:V}of H6)if(b.test($))return{config:w,summaryTemplate:V};return{config:F6}}static truncate($,b){let{config:w,summaryTemplate:V}=y$.getConfigForCommand(b);return y$.truncateWithConfig($,w,V)}static truncateWithConfig($,b,w){let V=$.length,W=$.split(`
847
- `),Q=W.length;if(Q<=b.maxLines&&V<=b.maxChars)return{content:$,truncated:!1,originalLines:Q,originalChars:V};let Z=W.slice(0,b.keepHead),Y=W.slice(-b.keepTail),J=Q-b.keepHead-b.keepTail,X=Z.join(`
721
+ Use the relative_path values above for Read/Edit operations.`;else F=`No files found matching "${w}"`;return{success:!0,llmContent:F,displayContent:q,metadata:{...C,matches:K}}}catch(X){if(d(X)==="AbortError")return{success:!1,llmContent:"File search aborted",displayContent:"⚠️ 文件搜索被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Search failed: ${_(X)}`,displayContent:`❌ 搜索失败: ${_(X)}`,error:{type:"execution_error",message:_(X),details:X}}}},version:"2.0.0",category:"搜索工具",tags:["file","search","glob","pattern","wildcard"],extractSignatureContent:($)=>$.pattern,abstractPermissionRule:()=>"*"});async function U5($,b,w,W){let V=W.getIgnorePatterns(),Q=[],Z=!1;return await new Promise((J,Y)=>{if(w.signal.aborted){Y(M1("文件搜索被用户中止"));return}let X=K5.stream(b,{cwd:$,dot:!0,followSymbolicLinks:!1,unique:!0,caseSensitiveMatch:w.caseSensitive,objectMode:!0,stats:!0,onlyFiles:!w.includeDirectories,ignore:V}),O=!1,G=null,B=()=>{if(G){if(w.signal.removeEventListener)w.signal.removeEventListener("abort",G);else if("onabort"in w.signal)w.signal.onabort=null;G=null}},K=()=>{if(!O)O=!0,Z=!0,X.destroy(),B(),J({matches:Q,wasTruncated:Z})},C=(q)=>{if(w.signal.aborted){if(!O)O=!0,X.destroy(M1("文件搜索被用户中止"));return}if(Q.length>=w.maxResults){K();return}let F=q.path.replace(/\\/g,"/"),U=A5($,F);if(W.shouldIgnore(F))return;let H=C5(q),R=H?.isDirectory()??!1;if(R&&W.shouldIgnoreDirectory(F))return;let T=H?.isFile()?H.size:void 0,N=H?.mtime.toISOString();if(Q.push({path:U,relative_path:F,is_directory:R,size:T,modified:N}),Q.length>=w.maxResults)K()};if(X.on("data",C),G=()=>{if(!O)O=!0,B(),X.destroy(M1("文件搜索被用户中止"))},w.signal.addEventListener)w.signal.addEventListener("abort",G);else if("onabort"in w.signal)w.signal.onabort=G;X.once("error",(q)=>{if(!O)O=!0,B(),Y(q)}),X.once("end",()=>{if(!O)O=!0,B(),J({matches:Q,wasTruncated:Z})})})}function R5($){return $.sort((b,w)=>{if(b.is_directory!==w.is_directory)return b.is_directory?1:-1;if(b.modified&&w.modified)return new Date(w.modified).getTime()-new Date(b.modified).getTime();return b.relative_path.localeCompare(w.relative_path)})}function H5($){let{search_path:b,pattern:w,total_matches:W,returned_matches:V,truncated:Q}=$,Z;if(Q)Z=`✅ 在 ${b} 中找到至少 ${W} 个匹配 "${w}" 的文件(已截断)`,Z+=`
722
+ \uD83D\uDCCB 显示前 ${V} 个结果`;else Z=`✅ 在 ${b} 中找到 ${W} 个匹配 "${w}" 的文件`;return Z}import{execSync as v1,spawn as T1}from"child_process";import{existsSync as yb}from"fs";import{readdir as _5,readFile as D5}from"fs/promises";import{join as h4,relative as L5}from"path";import E5 from"picomatch";import{z as l$}from"zod";function j5(){let{platform:$,arch:b}=process,w={"darwin-arm64":"darwin-arm64/rg","darwin-x64":"darwin-x64/rg","linux-arm64":"linux-arm64/rg","linux-x64":"linux-x64/rg","win32-x64":"win32-x64/rg.exe"},W=`${$}-${b}`,V=w[W];if(!V)return null;let Q=h4(process.cwd(),"vendor","ripgrep",V);if(yb(Q))return Q;try{let Z=new URL("../../../../vendor/ripgrep/"+V,import.meta.url).pathname;if(yb(Z))return Z}catch{}return null}function x4(){try{let b=process.platform==="win32"?"where rg":"command -v rg 2>/dev/null || which rg 2>/dev/null",w=v1(b,{encoding:"utf8",stdio:["pipe","pipe","ignore"]}).split(/\r?\n/)[0].trim();if(w)return w}catch{}let $=j5();if($&&yb($))return $;try{let b=S$("@vscode/ripgrep");if(b?.rgPath&&yb(b.rgPath))return b.rgPath}catch{}return null}async function N5($){try{return v1("git rev-parse --git-dir",{cwd:$,stdio:"ignore"}),!0}catch{return!1}}function S5(){try{return v1("grep --version",{stdio:"ignore"}),!0}catch{return!1}}async function y5($,b,w,W){let V=x4();if(!V)throw Error("ripgrep not available");return new Promise((Q,Z)=>{let J=T1(V,$,{stdio:["pipe","pipe","pipe"]}),Y="",X="";J.stdout.on("data",(G)=>{Y+=G.toString()}),J.stderr.on("data",(G)=>{X+=G.toString()}),J.on("close",(G)=>{Q({stdout:Y,stderr:X,exitCode:G||0})}),J.on("error",(G)=>{Z(G)});let O=()=>{J.kill("SIGTERM"),Z(Error("搜索被用户中止"))};w.addEventListener("abort",O),J.on("close",()=>{w.removeEventListener("abort",O)})})}async function M5($,b,w,W){let V=["grep","-n"];if(w.caseInsensitive)V.push("-i");if(w.contextLines!==void 0)V.push(`-C${w.contextLines}`);if(V.push("-e",$),w.glob)V.push("--",w.glob);return new Promise((Q,Z)=>{let J=T1("git",V,{cwd:b,stdio:["pipe","pipe","pipe"]}),Y="",X="";J.stdout.on("data",(G)=>{Y+=G.toString()}),J.stderr.on("data",(G)=>{X+=G.toString()}),J.on("close",(G)=>{Q({stdout:Y,stderr:X,exitCode:G||0})}),J.on("error",(G)=>{Z(G)});let O=()=>{J.kill("SIGTERM"),Z(Error("搜索被用户中止"))};W.addEventListener("abort",O),J.on("close",()=>{W.removeEventListener("abort",O)})})}async function z5($,b,w,W){let V=["-rn"];if(w.caseInsensitive)V.push("-i");if(w.contextLines!==void 0)V.push(`-C${w.contextLines}`);for(let Q of W0)V.push("--exclude-dir="+Q.replace(/^\./,""));return V.push("-e",$,b),new Promise((Q,Z)=>{let J=T1("grep",V,{stdio:["pipe","pipe","pipe"]}),Y="",X="";J.stdout.on("data",(G)=>{Y+=G.toString()}),J.stderr.on("data",(G)=>{X+=G.toString()}),J.on("close",(G)=>{Q({stdout:Y,stderr:X,exitCode:G||0})}),J.on("error",(G)=>{Z(G)});let O=()=>{J.kill("SIGTERM"),Z(Error("搜索被用户中止"))};W.addEventListener("abort",O),J.on("close",()=>{W.removeEventListener("abort",O)})})}async function v5($,b,w,W){let V=[],Q=new RegExp($,w.caseInsensitive?"gi":"g"),Z=await T5(b,W),J=0;for(let Y of Z){if(W.throwIfAborted(),p4(Y))continue;if(w.glob&&!k5(Y,w.glob))continue;try{(await D5(Y,"utf-8")).split(`
723
+ `).forEach((G,B)=>{if(Q.test(G))V.push({file_path:L5(b,Y),line_number:B+1,content:G})}),J++}catch(X){}}return{matches:V,totalFiles:J}}async function T5($,b){let w=[];async function W(V){b.throwIfAborted();try{let Q=await _5(V,{withFileTypes:!0});for(let Z of Q){b.throwIfAborted();let J=h4(V,Z.name);if(Z.isDirectory()){if(!p4(J))await W(J)}else if(Z.isFile())w.push(J)}}catch(Q){}}return await W($),w}function p4($){for(let b of W0)if($.includes(b))return!0;return!1}function k5($,b){return E5(b)($)}function f5($){let b=[];if($.case_insensitive)b.push("-i");if($.multiline)b.push("-U","--multiline-dotall");switch($.output_mode){case"files_with_matches":b.push("-l");break;case"count":b.push("-c");break;case"content":if($.line_numbers)b.push("-n");break}if($.context!==void 0&&$.output_mode==="content")b.push("-C",$.context.toString());else{if($.context_before!==void 0&&$.output_mode==="content")b.push("-B",$.context_before.toString());if($.context_after!==void 0&&$.output_mode==="content")b.push("-A",$.context_after.toString())}if($.type)b.push("--type",$.type);for(let w of W0)b.push("--glob",`!${w}/**`);if($.glob)b.push("--glob",$.glob);if($.head_limit!==void 0){let w=($.offset??0)+$.head_limit;b.push("-m",w.toString())}return b.push($.pattern),b.push($.path),b}function I5($,b){if(!$.trim())return[];let w=$.trim().split(`
724
+ `),W=[];switch(b){case"files_with_matches":return w.map((V)=>({file_path:V.trim()}));case"count":return w.map((V)=>{let[Q,Z]=V.split(":");return{file_path:Q,count:parseInt(Z,10)}});case"content":for(let V of w){let Q=P5(V);if(Q)W.push(Q)}return W;default:return[]}}function P5($){let b=$.indexOf(":");if(b===-1)return null;let w=$.substring(0,b),W=$.substring(b+1),V=W.indexOf(":");if(V!==-1&&/^\d+$/.test(W.substring(0,V))){let Q=parseInt(W.substring(0,V),10),Z=W.substring(V+1);return{file_path:w,line_number:Q,content:Z}}else return{file_path:w,content:W}}function h5($){let{search_pattern:b,search_path:w,output_mode:W,total_matches:V,strategy:Q}=$,Z=`✅ 在 ${w} 中搜索 "${b}"`;if(Q)Z+=`
725
+ \uD83D\uDD27 使用策略: ${Q}`;switch(W){case"files_with_matches":Z+=`
726
+ \uD83D\uDCC1 找到 ${V} 个包含匹配内容的文件`;break;case"count":Z+=`
727
+ \uD83D\uDD22 统计了 ${V} 个文件的匹配数量`;break;case"content":Z+=`
728
+ \uD83D\uDCDD 找到 ${V} 个匹配行`;break}return Z}var k1=L({name:"Grep",displayName:"内容搜索",kind:"readonly",schema:l$.object({pattern:P.pattern({description:"The regular expression pattern to search for in file contents"}),path:l$.string().optional().describe("File or directory to search in (rg PATH). Defaults to current working directory"),glob:l$.string().optional().describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}") - maps to rg --glob'),type:l$.string().optional().describe("File type to search (rg --type). Common types: js, py, rust, go, java, etc. More efficient than include for standard file types"),output_mode:l$.enum(["content","files_with_matches","count"]).default("files_with_matches").describe('Output mode: "content" shows matching lines (supports -A/-B/-C context, -n line numbers, head_limit), "files_with_matches" shows file paths (supports head_limit), "count" shows match counts (supports head_limit). Defaults to "files_with_matches"'),"-i":l$.boolean().optional().describe("Case insensitive search (rg -i)"),"-n":l$.boolean().default(!0).describe('Show line numbers in output (rg -n). Requires output_mode: "content", ignored otherwise. Defaults to true'),"-B":P.nonNegativeInt().optional().describe('Number of lines to show before each match (rg -B). Requires output_mode: "content", ignored otherwise'),"-A":P.nonNegativeInt().optional().describe('Number of lines to show after each match (rg -A). Requires output_mode: "content", ignored otherwise'),"-C":P.nonNegativeInt().optional().describe('Number of lines to show before and after each match (rg -C). Requires output_mode: "content", ignored otherwise'),head_limit:P.positiveInt().optional().describe('Limit output to first N lines/entries, equivalent to "| head -N". Works across all output modes: content (limits output lines), files_with_matches (limits file paths), count (limits count entries). Defaults based on "cap" experiment value: 0 (unlimited), 20, or 100'),offset:P.nonNegativeInt().optional().describe('Skip first N lines/entries before applying head_limit, equivalent to "| tail -n +N | head -N". Works across all output modes. Defaults to 0'),multiline:l$.boolean().default(!1).describe("Enable multiline mode where . matches newlines and patterns can span lines (rg -U --multiline-dotall). Default: false")}),description:{short:"A powerful search tool built on ripgrep",long:'A powerful search tool built on ripgrep\n\n Usage:\n - ALWAYS use Grep for search tasks. NEVER invoke `grep` or `rg` as a Bash command. The Grep tool has been optimized for correct permissions and access.\n - Supports full regex syntax (e.g., "log.*Error", "function\\s+\\w+")\n - Filter files with glob parameter (e.g., "*.js", "**/*.tsx") or type parameter (e.g., "js", "py", "rust")\n - Output modes: "content" shows matching lines, "files_with_matches" shows only file paths (default), "count" shows match counts\n - Use Task tool for open-ended searches requiring multiple rounds\n - Pattern syntax: Uses ripgrep (not grep) - literal braces need escaping (use `interface\\{\\}` to find `interface{}` in Go code)\n - Multiline matching: By default patterns match within single lines only. For cross-line patterns like `struct \\{[\\s\\S]*?field`, use `multiline: true`\n'},async execute($,b){let{pattern:w,path:W=process.cwd(),glob:V,type:Q,output_mode:Z,"-i":J,"-n":Y=!0,"-B":X,"-A":O,"-C":G,head_limit:B,offset:K,multiline:C}=$,{updateOutput:q}=b,F=b.signal??new AbortController().signal;try{q?.(`使用智能搜索策略查找模式 "${w}"...`);let U=null,H="ripgrep",R=[],T=x4();if(T)try{q?.(`\uD83D\uDE80 使用 ripgrep (${T})`);let l=f5({pattern:w,path:W,glob:V,type:Q,output_mode:Z,case_insensitive:J??!1,line_numbers:Y,context_before:X,context_after:O,context:G,head_limit:B,offset:K,multiline:C??!1});U=await y5(l,Z,F,q),H="ripgrep"}catch{q?.("⚠️ ripgrep 失败,尝试降级策略..."),U=null}if(!U&&await N5(W))try{q?.("\uD83D\uDCE6 使用 git grep"),U=await M5(w,W,{caseInsensitive:J??!1,glob:V,contextLines:G},F),H="git-grep"}catch{q?.("⚠️ git grep 失败,继续尝试其他策略..."),U=null}if(!U&&S5())try{q?.("\uD83D\uDD27 使用系统 grep"),U=await z5(w,W,{caseInsensitive:J??!1,contextLines:G},F),H="system-grep"}catch{q?.("⚠️ 系统 grep 失败,使用纯 JavaScript 实现..."),U=null}if(!U)q?.("\uD83D\uDCA1 使用纯 JavaScript 搜索实现"),R=(await v5(w,W,{caseInsensitive:J??!1,glob:V,multiline:C??!1},F)).matches,H="fallback",U={stdout:"",stderr:"",exitCode:0};else R=I5(U.stdout,Z);let N=R.length;if(K!==void 0&&K>0)R=R.slice(K);if(B!==void 0&&R.length>B)R=R.slice(0,B);let D={search_pattern:w,search_path:W,output_mode:Z,case_insensitive:J??!1,total_matches:R.length,original_total:N,offset:K,head_limit:B,strategy:H,exit_code:U?.exitCode};if(U&&U.exitCode!==0&&U.stderr)return{success:!1,llmContent:`Search execution failed: ${U.stderr}`,displayContent:`❌ 搜索执行失败: ${U.stderr}`,error:{type:"execution_error",message:U.stderr}};let S=h5(D);return{success:!0,llmContent:R,displayContent:S,metadata:D}}catch(U){if(d(U)==="AbortError")return{success:!1,llmContent:"Search aborted",displayContent:"⚠️ 搜索被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Search failed: ${_(U)}`,displayContent:`❌ 搜索失败: ${_(U)}`,error:{type:"execution_error",message:_(U),details:U}}}},version:"3.0.0",category:"搜索工具",tags:["search","grep","ripgrep","regex","text","fallback"],extractSignatureContent:($)=>$.pattern,abstractPermissionRule:()=>"*"});import{spawn as l5}from"child_process";import{randomUUID as n5}from"crypto";import{z as f1}from"zod";import{execSync as x5}from"child_process";import{existsSync as A$,mkdtempSync as p5,writeFileSync as d5}from"fs";import{tmpdir as u5}from"os";import{join as o0}from"path";var Mb=E("Tool");class x${static instance=null;capabilities=null;settings={};constructor(){}static getInstance(){if(!x$.instance)x$.instance=new x$;return x$.instance}static resetInstance(){x$.instance=null}configure($){this.settings={...$}}getCapabilities(){if(this.capabilities)return this.capabilities;return this.capabilities=this.detectCapabilities(),this.capabilities}detectCapabilities(){let $=process.platform;if($==="linux")return this.detectLinuxCapabilities();else if($==="darwin")return this.detectMacOSCapabilities();return{available:!1,type:"none",features:{fileSystemIsolation:!1,networkIsolation:!1,processIsolation:!1}}}detectLinuxCapabilities(){try{let $=x5("bwrap --version 2>/dev/null",{encoding:"utf-8"}).trim();return Mb.debug(`[SandboxExecutor] Detected bubblewrap: ${$}`),{available:!0,type:"bubblewrap",version:$,features:{fileSystemIsolation:!0,networkIsolation:!0,processIsolation:!0}}}catch{return Mb.debug("[SandboxExecutor] bubblewrap not available on Linux"),{available:!1,type:"none",features:{fileSystemIsolation:!1,networkIsolation:!1,processIsolation:!1}}}}detectMacOSCapabilities(){try{if(A$("/usr/bin/sandbox-exec"))return Mb.debug("[SandboxExecutor] Detected macOS sandbox-exec (Seatbelt)"),{available:!0,type:"seatbelt",version:"macOS built-in",features:{fileSystemIsolation:!0,networkIsolation:!0,processIsolation:!0}}}catch{Mb.debug("[SandboxExecutor] sandbox-exec not available on macOS")}return{available:!1,type:"none",features:{fileSystemIsolation:!1,networkIsolation:!1,processIsolation:!1}}}isEnabled(){return this.settings.enabled===!0}canUseSandbox(){return this.isEnabled()&&this.getCapabilities().available}wrapCommand($,b){if(!this.canUseSandbox())return $;let w=this.getCapabilities();if(w.type==="bubblewrap")return this.wrapWithBubblewrap($,b);else if(w.type==="seatbelt")return this.wrapWithSeatbelt($,b);return $}wrapWithBubblewrap($,b){let w=[];if(w.push("--ro-bind /usr /usr"),w.push("--ro-bind /bin /bin"),A$("/lib"))w.push("--ro-bind /lib /lib");if(A$("/lib64"))w.push("--ro-bind /lib64 /lib64");if(A$("/etc/resolv.conf"))w.push("--ro-bind /etc/resolv.conf /etc/resolv.conf");if(A$("/etc/hosts"))w.push("--ro-bind /etc/hosts /etc/hosts");if(A$("/etc/ssl"))w.push("--ro-bind /etc/ssl /etc/ssl");if(A$("/etc/ca-certificates"))w.push("--ro-bind /etc/ca-certificates /etc/ca-certificates");if(w.push("--proc /proc"),w.push("--dev /dev"),w.push("--tmpfs /tmp"),w.push(`--bind ${b.workDir} ${b.workDir}`),w.push(`--chdir ${b.workDir}`),b.allowedWritePaths){for(let Q of b.allowedWritePaths)if(A$(Q)&&Q!==b.workDir)w.push(`--bind ${Q} ${Q}`)}if(b.allowedReadPaths){for(let Q of b.allowedReadPaths)if(A$(Q))w.push(`--ro-bind ${Q} ${Q}`)}let W=process.env.HOME;if(W){let Q=o0(W,".nvm");if(A$(Q))w.push(`--ro-bind ${Q} ${Q}`);let Z=o0(W,".npm");if(A$(Z))w.push(`--bind ${Z} ${Z}`);let J=o0(W,".pnpm");if(A$(J))w.push(`--bind ${J} ${J}`)}if(!b.allowNetwork)w.push("--unshare-net");w.push("--unshare-user"),w.push("--unshare-pid"),w.push("--unshare-uts"),w.push("--unshare-cgroup"),w.push("--die-with-parent"),w.push("--new-session");let V=$.replace(/'/g,"'\\''");return`bwrap ${w.join(" ")} -- /bin/bash -c '${V}'`}wrapWithSeatbelt($,b){let w=this.generateSeatbeltProfile(b),W=p5(o0(u5(),"sandbox-")),V=o0(W,"sandbox.sb");d5(V,w,"utf-8");let Q=$.replace(/'/g,"'\\''");return`sandbox-exec -f '${V}' /bin/bash -c '${Q}'; EXIT_CODE=$?; rm -rf '${W}'; exit $EXIT_CODE`}generateSeatbeltProfile($){let b=[];b.push("(version 1)"),b.push("(deny default)"),b.push("(allow process-exec)"),b.push("(allow process-fork)"),b.push("(allow signal)"),b.push("(allow sysctl-read)"),b.push("(allow mach-lookup)"),b.push("(allow mach-register)"),b.push("(allow ipc-posix-shm)"),b.push("(allow file-read-metadata)"),b.push('(allow file-read* (subpath "/usr"))'),b.push('(allow file-read* (subpath "/bin"))'),b.push('(allow file-read* (subpath "/sbin"))'),b.push('(allow file-read* (subpath "/Library"))'),b.push('(allow file-read* (subpath "/System"))'),b.push('(allow file-read* (subpath "/private/var/db"))'),b.push('(allow file-read* (subpath "/private/etc"))'),b.push('(allow file-read* (subpath "/dev"))'),b.push('(allow file-read* (subpath "/var"))'),b.push('(allow file-read* (subpath "/opt/homebrew"))'),b.push('(allow file-read* (subpath "/usr/local"))');let w=process.env.HOME;if(w)b.push(`(allow file-read* (subpath "${w}/.nvm"))`),b.push(`(allow file-read* (subpath "${w}/.npm"))`),b.push(`(allow file-read* (subpath "${w}/.pnpm"))`),b.push(`(allow file-read* (subpath "${w}/.config"))`),b.push(`(allow file-write* (subpath "${w}/.npm"))`),b.push(`(allow file-write* (subpath "${w}/.pnpm"))`);if(b.push(`(allow file-read* (subpath "${$.workDir}"))`),b.push(`(allow file-write* (subpath "${$.workDir}"))`),$.allowedReadPaths)for(let W of $.allowedReadPaths)b.push(`(allow file-read* (subpath "${W}"))`);if($.allowedWritePaths)for(let W of $.allowedWritePaths)b.push(`(allow file-write* (subpath "${W}"))`);if(b.push('(allow file-read* (subpath "/private/tmp"))'),b.push('(allow file-write* (subpath "/private/tmp"))'),b.push('(allow file-read* (subpath "/tmp"))'),b.push('(allow file-write* (subpath "/tmp"))'),$.allowNetwork!==!1)b.push("(allow network*)");else b.push("(allow network-outbound (remote unix-socket))");return b.join(`
729
+ `)}buildExecutionOptions($,b){let w={workDir:$,allowedReadPaths:[],allowedWritePaths:[],allowNetwork:!0};if(b){if(b.allowLocalBinding===!1)w.allowNetwork=!1}let W=process.env.HOME;if(W)w.allowedReadPaths?.push(W);return w}}function D0(){return x$.getInstance()}class p${static instance=null;settings={};constructor(){}static getInstance(){if(!p$.instance)p$.instance=new p$;return p$.instance}static resetInstance(){p$.instance=null}configure($){this.settings={...$},D0().configure($)}getSettings(){return{...this.settings}}isEnabled(){return this.settings.enabled===!0}shouldAutoAllowBash(){return this.isEnabled()&&this.settings.autoAllowBashIfSandboxed===!0}isCommandExcluded($){if(!this.settings.excludedCommands||this.settings.excludedCommands.length===0)return!1;let b=this.extractCommandName($);return this.settings.excludedCommands.some((w)=>b===w||$.startsWith(w+" "))}allowsUnsandboxedCommands(){return this.settings.allowUnsandboxedCommands===!0}checkCommand($){let{command:b,dangerouslyDisableSandbox:w}=$;if(!this.isEnabled())return{allowed:!0,reason:"Sandbox is disabled"};if(this.isCommandExcluded(b))return{allowed:!0,reason:"Command is in excluded list",isExcluded:!0};if(w)if(this.allowsUnsandboxedCommands())return{allowed:!1,reason:"Command requests unsandboxed execution",requiresPermission:!0};else return{allowed:!1,reason:"Unsandboxed commands are not allowed"};return{allowed:!0,reason:"Command will run in sandbox"}}shouldIgnoreFileViolation($){if(!this.settings.ignoreViolations?.file)return!1;return this.settings.ignoreViolations.file.some((b)=>{if(b.includes("*"))return new RegExp("^"+b.replace(/\*/g,".*")+"$").test($);return $.startsWith(b)})}shouldIgnoreNetworkViolation($){if(!this.settings.ignoreViolations?.network)return!1;return this.settings.ignoreViolations.network.some((b)=>{if(b.includes("*"))return new RegExp("^"+b.replace(/\*/g,".*")+"$").test($);return $===b||$.startsWith(b)})}getNetworkSettings(){return this.settings.network||{}}allowsLocalBinding(){return this.settings.network?.allowLocalBinding===!0}isUnixSocketAllowed($){let b=this.settings.network;if(!b)return!1;if(b.allowAllUnixSockets)return!0;if(b.allowUnixSockets&&b.allowUnixSockets.length>0)return b.allowUnixSockets.includes($);return!1}extractCommandName($){return $.trim().split(/\s+/)[0]||""}wrapCommandForSandbox($,b){if(!this.isEnabled())return $;let w=D0();if(!w.canUseSandbox())return $;let W=b||process.cwd(),V=w.buildExecutionOptions(W,this.settings.network);return w.wrapCommand($,V)}getCapabilities(){return D0().getCapabilities()}}function L0(){return p$.getInstance()}import{spawn as g5}from"child_process";import{randomUUID as m5}from"crypto";class X${static instance=null;processes=new Map;static getInstance(){if(!X$.instance)X$.instance=new X$;return X$.instance}startBackgroundProcess($){let b=`bash_${m5()}`,w={};for(let[Q,Z]of Object.entries({...process.env,...$.env,BLADE_CLI:"1"}))if(Z!==void 0)w[Q]=Z;let W=g5("bash",["-c",$.command],{cwd:$.cwd||process.cwd(),env:w,stdio:["ignore","pipe","pipe"]}),V={id:b,command:$.command,sessionId:$.sessionId,cwd:$.cwd,env:$.env,process:W,pid:W.pid,status:"running",startTime:Date.now(),pendingStdout:"",pendingStderr:""};return W.stdout?.setEncoding("utf8"),W.stderr?.setEncoding("utf8"),W.stdout?.on("data",(Q)=>{V.pendingStdout+=Q.toString()}),W.stderr?.on("data",(Q)=>{V.pendingStderr+=Q.toString()}),W.on("close",(Q,Z)=>{V.status=V.status==="killed"?"killed":"exited",V.exitCode=Q,V.signal=Z,V.endTime=Date.now(),V.process=void 0}),W.on("error",(Q)=>{V.status="error",V.errorMessage=Q.message,V.endTime=Date.now(),V.process=void 0,V.pendingStderr+=`
730
+ [error] ${Q.message}`}),this.processes.set(b,V),V}consumeOutput($){let b=this.processes.get($);if(!b)return;let w={id:b.id,command:b.command,status:b.status,stdout:b.pendingStdout,stderr:b.pendingStderr,exitCode:b.exitCode,signal:b.signal,pid:b.pid,startedAt:b.startTime,endedAt:b.endTime,errorMessage:b.errorMessage};return b.pendingStdout="",b.pendingStderr="",w}getProcess($){return this.processes.get($)}kill($){let b=this.processes.get($);if(!b)return;if(b.status!=="running"||!b.process)return{success:!1,alreadyExited:!0,status:b.status,pid:b.pid,exitCode:b.exitCode,signal:b.signal};if(!b.process.kill("SIGTERM"))return{success:!1,alreadyExited:!1,status:b.status,pid:b.pid,exitCode:b.exitCode,signal:b.signal};return b.status="killed",b.endTime=Date.now(),b.process=void 0,{success:!0,alreadyExited:!1,status:b.status,pid:b.pid,exitCode:b.exitCode,signal:b.signal}}killAll(){for(let[$,b]of this.processes)if(b.status==="running"&&b.process)try{b.process.kill("SIGTERM"),b.status="killed",b.endTime=Date.now(),b.process=void 0}catch{}this.processes.clear()}}var zb={maxLines:30,maxChars:3000,keepHead:10,keepTail:10,summarize:!0},V0={maxLines:100,maxChars:1e4,keepHead:40,keepTail:40,summarize:!0},d4={maxLines:200,maxChars:20000,keepHead:80,keepTail:80,summarize:!1},c5={maxLines:150,maxChars:15000,keepHead:50,keepTail:50,summarize:!0},i5=[{pattern:/^git\s+(rm|add)\s+(-r|--cached|-rf|-f)?\s*/i,config:zb,summaryTemplate:($)=>`Successfully processed ${$} files`},{pattern:/^(npm|pnpm|yarn|bun)\s+(install|i|add|remove|uninstall)/i,config:zb,summaryTemplate:($)=>`Package operation completed (${$} lines of output)`},{pattern:/^(npm|pnpm|yarn|bun)\s+(run|exec)\s+(build|compile|bundle)/i,config:V0,summaryTemplate:($)=>`Build completed (${$} lines of output)`},{pattern:/^(npm|pnpm|yarn|bun)\s+(run|exec)\s+(test|lint|check)/i,config:d4},{pattern:/^git\s+(status|branch|remote)/i,config:V0},{pattern:/^git\s+(log|diff|show)/i,config:d4},{pattern:/^(ls|dir|tree)\s+/i,config:V0,summaryTemplate:($)=>`Listed ${$} items`},{pattern:/^find\s+/i,config:V0,summaryTemplate:($)=>`Found ${$} matches`},{pattern:/^(grep|rg|ag)\s+/i,config:V0,summaryTemplate:($)=>`Found ${$} matching lines`},{pattern:/^(docker|podman)\s+(build|pull|push)/i,config:zb,summaryTemplate:($)=>`Docker operation completed (${$} lines)`},{pattern:/^(pip|pip3|poetry|pipenv)\s+(install|uninstall)/i,config:zb,summaryTemplate:($)=>`Python package operation completed (${$} lines)`},{pattern:/^(cargo|rustup)\s+(build|install|update)/i,config:V0,summaryTemplate:($)=>`Rust operation completed (${$} lines)`},{pattern:/^(go)\s+(build|get|mod)/i,config:V0,summaryTemplate:($)=>`Go operation completed (${$} lines)`}];class T${static getConfigForCommand($){for(let{pattern:b,config:w,summaryTemplate:W}of i5)if(b.test($))return{config:w,summaryTemplate:W};return{config:c5}}static truncate($,b){let{config:w,summaryTemplate:W}=T$.getConfigForCommand(b);return T$.truncateWithConfig($,w,W)}static truncateWithConfig($,b,w){let W=$.length,V=$.split(`
731
+ `),Q=V.length;if(Q<=b.maxLines&&W<=b.maxChars)return{content:$,truncated:!1,originalLines:Q,originalChars:W};let Z=V.slice(0,b.keepHead),J=V.slice(-b.keepTail),Y=Q-b.keepHead-b.keepTail,X=Z.join(`
848
732
  `);if(X+=`
849
733
 
850
- ... (${J} lines truncated, showing first ${b.keepHead} and last ${b.keepTail} of ${Q} total) ...
734
+ ... (${Y} lines truncated, showing first ${b.keepHead} and last ${b.keepTail} of ${Q} total) ...
851
735
 
852
- `,X+=Y.join(`
853
- `),X.length>b.maxChars){let G=Math.floor(b.maxChars/2)-50,B=X.slice(0,G),q=X.slice(-G);X=`${B}
736
+ `,X+=J.join(`
737
+ `),X.length>b.maxChars){let G=Math.floor(b.maxChars/2)-50,B=X.slice(0,G),K=X.slice(-G);X=`${B}
854
738
 
855
739
  ... (content truncated to ${b.maxChars} chars) ...
856
740
 
857
- ${q}`}let O=b.summarize&&w?w(Q,V):void 0;if(O)X+=`
741
+ ${K}`}let O=b.summarize&&w?w(Q,W):void 0;if(O)X+=`
858
742
 
859
- [Summary: ${O}]`;return{content:X,truncated:!0,originalLines:Q,originalChars:V,summary:O}}static truncateForLLM($,b,w){let V=y$.truncate($,w),W=y$.truncate(b,w),Q;if(V.truncated||W.truncated){let Z=[];if(V.truncated)Z.push(`stdout: ${V.originalLines} lines → ${V.content.split(`
860
- `).length} lines`);if(W.truncated)Z.push(`stderr: ${W.originalLines} lines → ${W.content.split(`
861
- `).length} lines`);Q=`Output truncated: ${Z.join(", ")}`}return{stdout:V.content,stderr:W.content,truncationInfo:Q}}static shouldTruncate($,b){let{config:w}=y$.getConfigForCommand(b);return $.split(`
743
+ [Summary: ${O}]`;return{content:X,truncated:!0,originalLines:Q,originalChars:W,summary:O}}static truncateForLLM($,b,w){let W=T$.truncate($,w),V=T$.truncate(b,w),Q;if(W.truncated||V.truncated){let Z=[];if(W.truncated)Z.push(`stdout: ${W.originalLines} lines → ${W.content.split(`
744
+ `).length} lines`);if(V.truncated)Z.push(`stderr: ${V.originalLines} lines → ${V.content.split(`
745
+ `).length} lines`);Q=`Output truncated: ${Z.join(", ")}`}return{stdout:W.content,stderr:V.content,truncationInfo:Q}}static shouldTruncate($,b){let{config:w}=T$.getConfigForCommand(b);return $.split(`
862
746
  `).length>w.maxLines||$.length>w.maxChars}static getStats($){return{lines:$.split(`
863
- `).length,chars:$.length,words:$.split(/\s+/).filter(Boolean).length}}}var u1=E({name:"Bash",displayName:"Bash Command",kind:"execute",schema:d1.object({command:P.command({description:"Bash command to execute"}),timeout:P.timeout(1000,300000,30000),cwd:d1.string().optional().describe("Working directory (optional; applies only to this command). To persist, use cd"),env:P.environment(),run_in_background:d1.boolean().default(!1).describe("Run in background (suitable for long-running commands)")}),description:{short:"Execute bash commands in a persistent shell session with optional timeout",long:`Executes bash commands with proper handling and security measures.
747
+ `).length,chars:$.length,words:$.split(/\s+/).filter(Boolean).length}}}var I1=L({name:"Bash",displayName:"Bash Command",kind:"execute",schema:f1.object({command:P.command({description:"Bash command to execute"}),timeout:P.timeout(1000,300000,30000),cwd:f1.string().optional().describe("Working directory (optional; applies only to this command). To persist, use cd"),env:P.environment(),run_in_background:f1.boolean().default(!1).describe("Run in background (suitable for long-running commands)")}),description:{short:"Execute bash commands in a persistent shell session with optional timeout",long:`Executes bash commands with proper handling and security measures.
864
748
 
865
749
  IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.
866
750
 
@@ -876,37 +760,37 @@ Before executing commands:
876
760
  * cd "/Users/name/My Documents" (correct)
877
761
  * cd /Users/name/My Documents (incorrect - will fail)
878
762
  * python "/path/with spaces/script.py" (correct)
879
- * python /path/with spaces/script.py (incorrect - will fail)`,usageNotes:["The command argument is required","You can specify an optional timeout in milliseconds (up to 600000ms / 10 minutes). If not specified, commands will timeout after 30000ms (30 seconds)","It is very helpful if you write a clear, concise description of what this command does in 5-10 words","If the output exceeds 30000 characters, output will be truncated before being returned to you",'You can use the run_in_background parameter to run the command in the background, which allows you to continue working while the command runs. You can monitor the output using the TaskOutput tool. You do not need to use "&" at the end of the command when using this parameter',"Avoid using Bash with the find, grep, cat, head, tail, sed, awk, or echo commands, unless explicitly instructed or when these commands are truly necessary for the task. Instead, always prefer using the dedicated tools for these commands:"," - File search: Use Glob (NOT find or ls)"," - Content search: Use Grep (NOT grep or rg)"," - Read files: Use Read (NOT cat/head/tail)"," - Edit files: Use Edit (NOT sed/awk)"," - Write files: Use Write (NOT echo >/cat <<EOF)"," - Communication: Output text directly (NOT echo/printf)","When issuing multiple commands:",' - If the commands are independent and can run in parallel, make multiple Bash tool calls in a single message. For example, if you need to run "git status" and "git diff", send a single message with two Bash tool calls in parallel',' - If the commands depend on each other and must run sequentially, use a single Bash call with "&&" to chain them together (e.g., git add . && git commit -m "message" && git push). For instance, if one operation must complete before another starts (like mkdir before cp, Write before Bash for git operations, or git add before git commit), run these operations sequentially instead',` - Use ";" only when you need to run commands sequentially but don't care if earlier commands fail`," - DO NOT use newlines to separate commands (newlines are ok in quoted strings)","Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of cd. You may use cd if the User explicitly requests it"," Good example: pytest /foo/bar/tests"," Bad example: cd /foo/bar && pytest tests"],examples:[{description:"Run a simple command",params:{command:"ls -la",description:"List files in current directory"}},{description:"Temporarily change working directory (this command only)",params:{command:"npm install",cwd:"/path/to/project",description:"Install package dependencies"}},{description:"Persistently change working directory",params:{command:"cd /path/to/project && npm install",description:"Change directory and install dependencies"}},{description:"Run a long-running command in background",params:{command:"npm run dev",run_in_background:!0,description:"Start development server in background"}},{description:"Run multiple independent commands in parallel",params:{command:"git status",description:"Show working tree status"}}],important:["Committing changes with git:"," - Only create commits when requested by the user. If unclear, ask first"," - Git Safety Protocol:"," * NEVER update the git config"," * NEVER run destructive/irreversible git commands (like push --force, hard reset, etc) unless the user explicitly requests them"," * NEVER skip hooks (--no-verify, --no-gpg-sign, etc) unless the user explicitly requests it"," * NEVER run force push to main/master, warn the user if they request it"," * Avoid git commit --amend. ONLY use --amend when either (1) user explicitly requested amend OR (2) adding edits from pre-commit hook",' * Before amending: ALWAYS check authorship (git log -1 --format="%an %ae")'," * NEVER commit changes unless the user explicitly asks you to"," - When creating commits:"," 1. Run git status, git diff, and git log in parallel to understand changes",' 2. Analyze staged changes and draft a concise commit message (1-2 sentences) focusing on "why" rather than "what"'," 3. Add relevant untracked files, create the commit, and run git status to verify"," 4. Always pass commit message via HEREDOC format"," - DO NOT push to remote repository unless explicitly requested"," - NEVER use git commands with the -i flag (no interactive input supported)"," - If no changes to commit, do not create an empty commit","Creating pull requests:"," - Use the gh command for ALL GitHub-related tasks"," - When creating a PR:"," 1. Run git status, git diff, and git log in parallel to understand branch changes"," 2. Analyze all commits (not just the latest) and draft a PR summary"," 3. Create new branch if needed, push with -u flag, and create PR using gh pr create with HEREDOC body format"," - Return the PR URL when done","Other important notes:"," - Dangerous commands (rm -rf, sudo, etc.) require user confirmation"," - Background commands require manual termination using KillShell"," - NEVER use find, grep, cat, sed, etc. — use dedicated tools instead"]},async execute($,b){let{command:w,timeout:V=30000,cwd:W,env:Q,run_in_background:Z=!1}=$,{updateOutput:Y}=b,J=b.signal??new AbortController().signal;try{let X=_0(),O=X.checkCommand({command:w});if(!O.allowed){if(O.requiresPermission)return{success:!1,llmContent:`Command requires permission: ${O.reason}`,displayContent:"⚠️ Command requires user permission",error:{type:"permission_denied",message:O.reason||"Permission required"}};return{success:!1,llmContent:`Command blocked by sandbox: ${O.reason}`,displayContent:"\uD83D\uDD12 Command blocked by sandbox",error:{type:"permission_denied",message:O.reason||"Blocked by sandbox"}}}let G=W||process.cwd(),B=X.wrapCommandForSandbox(w,G);if(X.isEnabled()&&B!==w)Y?.(`\uD83D\uDD12 Executing in sandbox: ${w}`);else Y?.(`Executing Bash command: ${w}`);if(Z)return E6(B,W,Q);if(g$())return Y?.("通过 IDE 终端执行命令..."),D6(B,W,Q,V,J,Y);else return L6(B,W,Q,V,J,Y)}catch(X){let O=X;if(O.name==="AbortError")return{success:!1,llmContent:"Command execution aborted",displayContent:"⚠️ 命令执行被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`Command execution failed: ${O.message}`,displayContent:`❌ 命令执行失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"命令工具",tags:["bash","shell","non-interactive","event-driven"],extractSignatureContent:($)=>{return $.command.trim()},abstractPermissionRule:($)=>{let w=$.command.trim().split(/\s+/);if(w.length===1)return w[0];if(["run","exec","test","start","build","dev"].includes(w[1])){if(w.length===2)return`${w[0]} ${w[1]}`;return`${w[0]} ${w[1]} *`}if(w.length===2)return`${w[0]} ${w[1]}`;return`${w[0]} ${w[1]} *`}});function E6($,b,w){let W=O$.getInstance().startBackgroundProcess({command:$,sessionId:R6(),cwd:b||process.cwd(),env:w}),Z=`后台启动命令: ${$.length>30?`${$.substring(0,30)}...`:$}`,Y={command:$,background:!0,pid:W.pid??0,bash_id:W.id,shell_id:W.id,message:"命令已在后台启动",summary:Z},J=`✅ 命令已在后台启动
880
- `+`\uD83C\uDD94 进程 ID: ${W.pid}
881
- `+`\uD83D\uDCA1 Bash ID: ${W.id}
882
- `+"⚠️ 使用 TaskOutput/KillShell 管理后台进程";return{success:!0,llmContent:{command:$,background:!0,pid:W.pid,bash_id:W.id,shell_id:W.id},displayContent:J,metadata:Y}}async function D6($,b,w,V,W,Q){let Z=Date.now();try{let J=await q4().execute($,{cwd:b||process.cwd(),env:w,timeout:V,signal:W,onOutput:(K)=>{Q?.(K)}}),X=Date.now()-Z;if(W.aborted||J.error==="Command was aborted"||J.error==="Command was terminated")return{success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
883
- 输出: ${J.stdout}
884
- 错误: ${J.stderr}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:J.stdout,stderr:J.stderr,execution_time:X}};if(J.error==="Command timed out")return{success:!1,llmContent:`Command execution timed out (${V}ms)`,displayContent:`⏱️ 命令执行超时 (${V}ms)
885
- 输出: ${J.stdout}
886
- 错误: ${J.stderr}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:J.stdout,stderr:J.stderr,execution_time:X}};let O=$.length>30?`${$.substring(0,30)}...`:$,G=J.exitCode===0?`执行命令成功 (${X}ms): ${O}`:`执行命令完成 (退出码 ${J.exitCode}, ${X}ms): ${O}`,B={command:$,execution_time:X,exit_code:J.exitCode,stdout_length:J.stdout.length,stderr_length:J.stderr.length,has_stderr:J.stderr.length>0,acp_mode:!0,summary:G},q=h4({stdout:J.stdout,stderr:J.stderr,command:$,execution_time:X,exit_code:J.exitCode,signal:null}),U=y$.truncateForLLM(J.stdout.trim(),J.stderr.trim(),$);return{success:J.success,llmContent:{stdout:U.stdout,stderr:U.stderr,execution_time:X,exit_code:J.exitCode,...U.truncationInfo&&{truncation_info:U.truncationInfo}},displayContent:q,metadata:B}}catch(Y){let J=Y,X=Date.now()-Z;return{success:!1,llmContent:`Command execution failed: ${J.message}`,displayContent:`❌ 命令执行失败: ${J.message}`,error:{type:"execution_error",message:J.message,details:J},metadata:{command:$,execution_time:X,error:J.message}}}}async function L6($,b,w,V,W,Q){return new Promise((Z)=>{let Y=Date.now(),J="",X="",O=!1,G=_6("bash",["-c",$],{cwd:b||process.cwd(),env:{...process.env,...w,BLADE_CLI:"1"},stdio:["pipe","pipe","pipe"]});G.stdout.on("data",(U)=>{J+=U.toString()}),G.stderr.on("data",(U)=>{X+=U.toString()});let B=setTimeout(()=>{O=!0,G.kill("SIGTERM"),setTimeout(()=>{if(!G.killed)G.kill("SIGKILL")},1000)},V),q=()=>{G.kill("SIGTERM"),clearTimeout(B)};if(W.addEventListener)W.addEventListener("abort",q);else if("onabort"in W)W.onabort=q;G.on("close",(U,K)=>{if(clearTimeout(B),W.removeEventListener)W.removeEventListener("abort",q);else if("onabort"in W)W.onabort=null;let _=Date.now()-Y;if(O){Z({success:!1,llmContent:`Command execution timed out (${V}ms)`,displayContent:`⏱️ 命令执行超时 (${V}ms)
887
- 输出: ${J}
888
- 错误: ${X}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:J,stderr:X,execution_time:_}});return}if(W.aborted){Z({success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
889
- 输出: ${J}
890
- 错误: ${X}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:J,stderr:X,execution_time:_}});return}let C=$.length>30?`${$.substring(0,30)}...`:$,H=U===0?`执行命令成功 (${_}ms): ${C}`:`执行命令完成 (退出码 ${U}, ${_}ms): ${C}`,F={command:$,execution_time:_,exit_code:U,signal:K,stdout_length:J.length,stderr_length:X.length,has_stderr:X.length>0,summary:H},M=h4({stdout:J,stderr:X,command:$,execution_time:_,exit_code:U,signal:K}),L=y$.truncateForLLM(J.trim(),X.trim(),$);Z({success:!0,llmContent:{stdout:L.stdout,stderr:L.stderr,execution_time:_,exit_code:U,signal:K,...L.truncationInfo&&{truncation_info:L.truncationInfo}},displayContent:M,metadata:F})}),G.on("error",(U)=>{if(clearTimeout(B),W.removeEventListener)W.removeEventListener("abort",q);else if("onabort"in W)W.onabort=null;Z({success:!1,llmContent:`Command execution failed: ${U.message}`,displayContent:`❌ 命令执行失败: ${U.message}`,error:{type:"execution_error",message:U.message,details:U}})})})}function h4($){let{stdout:b,stderr:w,command:V,execution_time:W,exit_code:Q,signal:Z}=$,Y=`✅ Bash 命令执行完成: ${V}`;if(Y+=`
891
- ⏱️ 执行时间: ${W}ms`,Y+=`
892
- \uD83D\uDCCA 退出码: ${Q??"N/A"}`,Z)Y+=`
893
- ⚡ 信号: ${Z}`;if(b&&b.trim())Y+=`
763
+ * python /path/with spaces/script.py (incorrect - will fail)`,usageNotes:["The command argument is required","You can specify an optional timeout in milliseconds (up to 600000ms / 10 minutes). If not specified, commands will timeout after 30000ms (30 seconds)","It is very helpful if you write a clear, concise description of what this command does in 5-10 words","If the output exceeds 30000 characters, output will be truncated before being returned to you",'You can use the run_in_background parameter to run the command in the background, which allows you to continue working while the command runs. You can monitor the output using the TaskOutput tool. You do not need to use "&" at the end of the command when using this parameter',"Avoid using Bash with the find, grep, cat, head, tail, sed, awk, or echo commands, unless explicitly instructed or when these commands are truly necessary for the task. Instead, always prefer using the dedicated tools for these commands:"," - File search: Use Glob (NOT find or ls)"," - Content search: Use Grep (NOT grep or rg)"," - Read files: Use Read (NOT cat/head/tail)"," - Edit files: Use Edit (NOT sed/awk)"," - Write files: Use Write (NOT echo >/cat <<EOF)"," - Communication: Output text directly (NOT echo/printf)","When issuing multiple commands:",' - If the commands are independent and can run in parallel, make multiple Bash tool calls in a single message. For example, if you need to run "git status" and "git diff", send a single message with two Bash tool calls in parallel',' - If the commands depend on each other and must run sequentially, use a single Bash call with "&&" to chain them together (e.g., git add . && git commit -m "message" && git push). For instance, if one operation must complete before another starts (like mkdir before cp, Write before Bash for git operations, or git add before git commit), run these operations sequentially instead',` - Use ";" only when you need to run commands sequentially but don't care if earlier commands fail`," - DO NOT use newlines to separate commands (newlines are ok in quoted strings)","Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of cd. You may use cd if the User explicitly requests it"," Good example: pytest /foo/bar/tests"," Bad example: cd /foo/bar && pytest tests"],examples:[{description:"Run a simple command",params:{command:"ls -la",description:"List files in current directory"}},{description:"Temporarily change working directory (this command only)",params:{command:"npm install",cwd:"/path/to/project",description:"Install package dependencies"}},{description:"Persistently change working directory",params:{command:"cd /path/to/project && npm install",description:"Change directory and install dependencies"}},{description:"Run a long-running command in background",params:{command:"npm run dev",run_in_background:!0,description:"Start development server in background"}},{description:"Run multiple independent commands in parallel",params:{command:"git status",description:"Show working tree status"}}],important:["Committing changes with git:"," - Only create commits when requested by the user. If unclear, ask first"," - Git Safety Protocol:"," * NEVER update the git config"," * NEVER run destructive/irreversible git commands (like push --force, hard reset, etc) unless the user explicitly requests them"," * NEVER skip hooks (--no-verify, --no-gpg-sign, etc) unless the user explicitly requests it"," * NEVER run force push to main/master, warn the user if they request it"," * Avoid git commit --amend. ONLY use --amend when either (1) user explicitly requested amend OR (2) adding edits from pre-commit hook",' * Before amending: ALWAYS check authorship (git log -1 --format="%an %ae")'," * NEVER commit changes unless the user explicitly asks you to"," - When creating commits:"," 1. Run git status, git diff, and git log in parallel to understand changes",' 2. Analyze staged changes and draft a concise commit message (1-2 sentences) focusing on "why" rather than "what"'," 3. Add relevant untracked files, create the commit, and run git status to verify"," 4. Always pass commit message via HEREDOC format"," - DO NOT push to remote repository unless explicitly requested"," - NEVER use git commands with the -i flag (no interactive input supported)"," - If no changes to commit, do not create an empty commit","Creating pull requests:"," - Use the gh command for ALL GitHub-related tasks"," - When creating a PR:"," 1. Run git status, git diff, and git log in parallel to understand branch changes"," 2. Analyze all commits (not just the latest) and draft a PR summary"," 3. Create new branch if needed, push with -u flag, and create PR using gh pr create with HEREDOC body format"," - Return the PR URL when done","Other important notes:"," - Dangerous commands (rm -rf, sudo, etc.) require user confirmation"," - Background commands require manual termination using KillShell"," - NEVER use find, grep, cat, sed, etc. — use dedicated tools instead"]},async execute($,b){let{command:w,timeout:W=30000,cwd:V,env:Q,run_in_background:Z=!1}=$,{updateOutput:J}=b,Y=b.signal??new AbortController().signal;try{let X=L0(),O=X.checkCommand({command:w});if(!O.allowed){if(O.requiresPermission)return{success:!1,llmContent:`Command requires permission: ${O.reason}`,displayContent:"⚠️ Command requires user permission",error:{type:"permission_denied",message:O.reason||"Permission required"}};return{success:!1,llmContent:`Command blocked by sandbox: ${O.reason}`,displayContent:"\uD83D\uDD12 Command blocked by sandbox",error:{type:"permission_denied",message:O.reason||"Blocked by sandbox"}}}let G=V||process.cwd(),B=X.wrapCommandForSandbox(w,G);if(X.isEnabled()&&B!==w)J?.(`\uD83D\uDD12 Executing in sandbox: ${w}`);else J?.(`Executing Bash command: ${w}`);if(Z)return s5(B,V,Q);if(i$())return J?.("通过 IDE 终端执行命令..."),r5(B,V,Q,W,Y,J);else return a5(B,V,Q,W,Y,J)}catch(X){if(d(X)==="AbortError")return{success:!1,llmContent:"Command execution aborted",displayContent:"⚠️ 命令执行被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`Command execution failed: ${_(X)}`,displayContent:`❌ 命令执行失败: ${_(X)}`,error:{type:"execution_error",message:_(X),details:X}}}},version:"2.0.0",category:"命令工具",tags:["bash","shell","non-interactive","event-driven"],extractSignatureContent:($)=>{return $.command.trim()},abstractPermissionRule:($)=>{let w=$.command.trim().split(/\s+/);if(w.length===1)return w[0];if(["run","exec","test","start","build","dev"].includes(w[1])){if(w.length===2)return`${w[0]} ${w[1]}`;return`${w[0]} ${w[1]} *`}if(w.length===2)return`${w[0]} ${w[1]}`;return`${w[0]} ${w[1]} *`}});function s5($,b,w){let V=X$.getInstance().startBackgroundProcess({command:$,sessionId:n5(),cwd:b||process.cwd(),env:w}),Z=`后台启动命令: ${$.length>30?`${$.substring(0,30)}...`:$}`,J={command:$,background:!0,pid:V.pid??0,bash_id:V.id,shell_id:V.id,message:"命令已在后台启动",summary:Z},Y=`✅ 命令已在后台启动
764
+ `+`\uD83C\uDD94 进程 ID: ${V.pid}
765
+ `+`\uD83D\uDCA1 Bash ID: ${V.id}
766
+ `+"⚠️ 使用 TaskOutput/KillShell 管理后台进程";return{success:!0,llmContent:{command:$,background:!0,pid:V.pid,bash_id:V.id,shell_id:V.id},displayContent:Y,metadata:J}}async function r5($,b,w,W,V,Q){let Z=Date.now();try{let Y=await U4().execute($,{cwd:b||process.cwd(),env:w,timeout:W,signal:V,onOutput:(q)=>{Q?.(q)}}),X=Date.now()-Z;if(V.aborted||Y.error==="Command was aborted"||Y.error==="Command was terminated")return{success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
767
+ 输出: ${Y.stdout}
768
+ 错误: ${Y.stderr}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:Y.stdout,stderr:Y.stderr,execution_time:X}};if(Y.error==="Command timed out")return{success:!1,llmContent:`Command execution timed out (${W}ms)`,displayContent:`⏱️ 命令执行超时 (${W}ms)
769
+ 输出: ${Y.stdout}
770
+ 错误: ${Y.stderr}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:Y.stdout,stderr:Y.stderr,execution_time:X}};let O=$.length>30?`${$.substring(0,30)}...`:$,G=Y.exitCode===0?`执行命令成功 (${X}ms): ${O}`:`执行命令完成 (退出码 ${Y.exitCode}, ${X}ms): ${O}`,B={command:$,execution_time:X,exit_code:Y.exitCode,stdout_length:Y.stdout.length,stderr_length:Y.stderr.length,has_stderr:Y.stderr.length>0,acp_mode:!0,summary:G},K=u4({stdout:Y.stdout,stderr:Y.stderr,command:$,execution_time:X,exit_code:Y.exitCode,signal:null}),C=T$.truncateForLLM(Y.stdout.trim(),Y.stderr.trim(),$);return{success:Y.success,llmContent:{stdout:C.stdout,stderr:C.stderr,execution_time:X,exit_code:Y.exitCode,...C.truncationInfo&&{truncation_info:C.truncationInfo}},displayContent:K,metadata:B}}catch(J){let Y=Date.now()-Z;return{success:!1,llmContent:`Command execution failed: ${_(J)}`,displayContent:`❌ 命令执行失败: ${_(J)}`,error:{type:"execution_error",message:_(J),details:J},metadata:{command:$,execution_time:Y,error:_(J)}}}}async function a5($,b,w,W,V,Q){return new Promise((Z)=>{let J=Date.now(),Y="",X="",O=!1,G=l5("bash",["-c",$],{cwd:b||process.cwd(),env:{...process.env,...w,BLADE_CLI:"1"},stdio:["pipe","pipe","pipe"]});G.stdout.on("data",(C)=>{Y+=C.toString()}),G.stderr.on("data",(C)=>{X+=C.toString()});let B=setTimeout(()=>{O=!0,G.kill("SIGTERM"),setTimeout(()=>{if(!G.killed)G.kill("SIGKILL")},1000)},W),K=()=>{G.kill("SIGTERM"),clearTimeout(B)};if(V.addEventListener)V.addEventListener("abort",K);else if("onabort"in V)V.onabort=K;G.on("close",(C,q)=>{if(clearTimeout(B),V.removeEventListener)V.removeEventListener("abort",K);else if("onabort"in V)V.onabort=null;let F=Date.now()-J;if(O){Z({success:!1,llmContent:`Command execution timed out (${W}ms)`,displayContent:`⏱️ 命令执行超时 (${W}ms)
771
+ 输出: ${Y}
772
+ 错误: ${X}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:Y,stderr:X,execution_time:F}});return}if(V.aborted){Z({success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
773
+ 输出: ${Y}
774
+ 错误: ${X}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:Y,stderr:X,execution_time:F}});return}let U=$.length>30?`${$.substring(0,30)}...`:$,H=C===0?`执行命令成功 (${F}ms): ${U}`:`执行命令完成 (退出码 ${C}, ${F}ms): ${U}`,R={command:$,execution_time:F,exit_code:C,signal:q,stdout_length:Y.length,stderr_length:X.length,has_stderr:X.length>0,summary:H},T=u4({stdout:Y,stderr:X,command:$,execution_time:F,exit_code:C,signal:q}),N=T$.truncateForLLM(Y.trim(),X.trim(),$);Z({success:!0,llmContent:{stdout:N.stdout,stderr:N.stderr,execution_time:F,exit_code:C,signal:q,...N.truncationInfo&&{truncation_info:N.truncationInfo}},displayContent:T,metadata:R})}),G.on("error",(C)=>{if(clearTimeout(B),V.removeEventListener)V.removeEventListener("abort",K);else if("onabort"in V)V.onabort=null;Z({success:!1,llmContent:`Command execution failed: ${C.message}`,displayContent:`❌ 命令执行失败: ${C.message}`,error:{type:"execution_error",message:C.message,details:C}})})})}function u4($){let{stdout:b,stderr:w,command:W,execution_time:V,exit_code:Q,signal:Z}=$,J=`✅ Bash 命令执行完成: ${W}`;if(J+=`
775
+ ⏱️ 执行时间: ${V}ms`,J+=`
776
+ \uD83D\uDCCA 退出码: ${Q??"N/A"}`,Z)J+=`
777
+ ⚡ 信号: ${Z}`;if(b&&b.trim())J+=`
894
778
  \uD83D\uDCE4 输出:
895
- ${b.trim()}`;if(w&&w.trim())Y+=`
779
+ ${b.trim()}`;if(w&&w.trim())J+=`
896
780
  ⚠️ 错误输出:
897
- ${w.trim()}`;return Y}import{z as x4}from"zod";var g1=E({name:"KillShell",displayName:"终止后台 Shell",kind:"execute",schema:x4.object({shell_id:x4.string().min(1).describe("Background Shell ID to terminate")}),description:{short:"Kills a running background bash shell by its ID",long:`
781
+ ${w.trim()}`;return J}import{z as g4}from"zod";var P1=L({name:"KillShell",displayName:"终止后台 Shell",kind:"execute",schema:g4.object({shell_id:g4.string().min(1).describe("Background Shell ID to terminate")}),description:{short:"Kills a running background bash shell by its ID",long:`
898
782
  - Kills a running background bash shell by its ID
899
783
  - Takes a shell_id parameter identifying the shell to kill
900
784
  - Returns a success or failure status
901
785
  - Use this tool when you need to terminate a long-running shell
902
786
  - Shell IDs can be found using the /tasks command
903
- `},async execute($,b){let V=O$.getInstance().kill($.shell_id);if(!V)return{success:!1,llmContent:`Shell not found: ${$.shell_id}`,displayContent:`❌ 未找到 Shell: ${$.shell_id}`,error:{type:"execution_error",message:"Shell ID 不存在或已清理"}};if(!V.success&&!V.alreadyExited)return{success:!1,llmContent:`Failed to terminate Shell: ${$.shell_id}`,displayContent:`❌ 无法终止 Shell (${$.shell_id})`,error:{type:"execution_error",message:"发送终止信号失败"},metadata:{...V}};let W=V.alreadyExited?`Shell ${$.shell_id} 已经处于 ${V.status} 状态`:`已向 Shell ${$.shell_id} 发送终止信号`;return{success:!0,llmContent:{shell_id:$.shell_id,status:V.status,already_exited:V.alreadyExited,pid:V.pid,exit_code:V.exitCode,signal:V.signal},displayContent:V.alreadyExited?`ℹ️ ${W}`:`✂️ ${W}`,metadata:{...V}}},version:"1.0.0",category:"命令工具",tags:["bash","shell","terminate"],extractSignatureContent:($)=>$.shell_id,abstractPermissionRule:()=>"*"});import{z as c$}from"zod";import{nanoid as y6}from"nanoid";import{promises as n}from"node:fs";import*as f from"node:path";import{fileURLToPath as j6}from"node:url";import{nanoid as N6}from"nanoid";var p4={proposal:"proposal.md",spec:"spec.md",requirements:"requirements.md",design:"design.md",tasks:"tasks.md",meta:".meta.json"},$0={SPECS:"specs",CHANGES:"changes",ARCHIVE:"archive",STEERING:"steering",SPEC_DELTA:"specs"},b0={CONSTITUTION:"constitution.md",PRODUCT:"product.md",TECH:"tech.md",STRUCTURE:"structure.md"},lY=["init","requirements","design","tasks","implementation","done"],s0={init:["requirements"],requirements:["design","tasks"],design:["tasks"],tasks:["implementation"],implementation:["done","tasks"],done:[]},q$={init:"初始化",requirements:"需求定义",design:"架构设计",tasks:"任务分解",implementation:"实现中",done:"已完成"},d4={init:"proposal",requirements:"requirements",design:"design",tasks:"tasks",implementation:"tasks",done:null};var S6=j6(import.meta.url),M6=f.dirname(S6),u4=f.join(M6,"templates");class r0{workspaceRoot;bladeDir;constructor($){this.workspaceRoot=$,this.bladeDir=f.join($,".blade")}getSpecsDir(){return f.join(this.bladeDir,$0.SPECS)}getChangesDir(){return f.join(this.bladeDir,$0.CHANGES)}getArchiveDir(){return f.join(this.bladeDir,$0.ARCHIVE)}getSteeringDir(){return f.join(this.bladeDir,$0.STEERING)}getChangePath($){return f.join(this.getChangesDir(),$)}getChangeFilePath($,b){return f.join(this.getChangePath($),p4[b])}async initializeDirectories(){await n.mkdir(this.getChangesDir(),{recursive:!0,mode:493})}async createChangeDir($){let b=this.getChangePath($);return await n.mkdir(b,{recursive:!0,mode:493}),await n.mkdir(f.join(b,$0.SPEC_DELTA),{recursive:!0,mode:493}),b}async readFile($){try{return await n.readFile($,"utf-8")}catch(b){if(b.code==="ENOENT")return null;throw b}}async writeFile($,b){let w=f.dirname($);await n.mkdir(w,{recursive:!0,mode:493}),await n.writeFile($,b,"utf-8")}async fileExists($){try{return await n.access($),!0}catch{return!1}}async dirExists($){try{return(await n.stat($)).isDirectory()}catch{return!1}}createMetadata($,b){let w=new Date().toISOString();return{id:N6(),name:$,description:b,phase:"init",createdAt:w,updatedAt:w,tasks:[]}}async readMetadata($){let b=this.getChangeFilePath($,"meta"),w=await this.readFile(b);if(!w)return null;try{return JSON.parse(w)}catch{return null}}async writeMetadata($,b){let w=this.getChangeFilePath($,"meta");b.updatedAt=new Date().toISOString(),await this.writeFile(w,JSON.stringify(b,null,2))}async updatePhase($,b){let w=await this.readMetadata($);if(!w)return null;return w.phase=b,await this.writeMetadata($,w),w}async readSpecFile($,b){let w=this.getChangeFilePath($,b);return this.readFile(w)}async writeSpecFile($,b,w){let V=this.getChangeFilePath($,b);await this.writeFile(V,w);let W=await this.readMetadata($);if(W)await this.writeMetadata($,W)}async getPhaseContent($,b){let w=d4[b];if(!w)return null;return this.readSpecFile($,w)}async readSteeringContext(){let $=this.getSteeringDir(),[b,w,V,W]=await Promise.all([this.readFile(f.join($,b0.CONSTITUTION)),this.readFile(f.join($,b0.PRODUCT)),this.readFile(f.join($,b0.TECH)),this.readFile(f.join($,b0.STRUCTURE))]);return{constitution:b||void 0,product:w||void 0,tech:V||void 0,structure:W||void 0}}async writeSteeringFile($,b){let w=f.join(this.getSteeringDir(),b0[$]);await this.writeFile(w,b)}async hasSteeringDocs(){let $=this.getSteeringDir();if(!await this.dirExists($))return!1;return(await n.readdir($)).length>0}async listActiveChanges(){let $=this.getChangesDir();if(!await this.dirExists($))return[];return(await n.readdir($,{withFileTypes:!0})).filter((w)=>w.isDirectory()).map((w)=>w.name)}async listArchivedChanges(){let $=this.getArchiveDir();if(!await this.dirExists($))return[];return(await n.readdir($,{withFileTypes:!0})).filter((w)=>w.isDirectory()).map((w)=>w.name)}async changeExists($){return this.dirExists(this.getChangePath($))}async archiveChange($){let b=this.getChangePath($),w=f.join(this.getArchiveDir(),$);await n.mkdir(f.dirname(w),{recursive:!0,mode:493}),await n.rename(b,w)}async restoreChange($){let b=f.join(this.getArchiveDir(),$),w=this.getChangePath($);await n.rename(b,w)}async listSpecDomains(){let $=this.getSpecsDir();if(!await this.dirExists($))return[];return(await n.readdir($,{withFileTypes:!0})).filter((w)=>w.isDirectory()).map((w)=>w.name)}async readAuthorativeSpec($){let b=f.join(this.getSpecsDir(),$,"spec.md");return this.readFile(b)}async writeAuthorativeSpec($,b){let w=f.join(this.getSpecsDir(),$,"spec.md");await this.writeFile(w,b)}async mergeSpecDeltas($){let b=f.join(this.getChangePath($),$0.SPEC_DELTA);if(!await this.dirExists(b))return[];let w=[],V=await n.readdir(b,{withFileTypes:!0});for(let W of V){if(!W.isDirectory())continue;let Q=f.join(b,W.name,"spec.md"),Z=await this.readFile(Q);if(Z){let Y=await this.readAuthorativeSpec(W.name),J=Y?`${Y}
787
+ `},async execute($,b){let W=X$.getInstance().kill($.shell_id);if(!W)return{success:!1,llmContent:`Shell not found: ${$.shell_id}`,displayContent:`❌ 未找到 Shell: ${$.shell_id}`,error:{type:"execution_error",message:"Shell ID 不存在或已清理"}};if(!W.success&&!W.alreadyExited)return{success:!1,llmContent:`Failed to terminate Shell: ${$.shell_id}`,displayContent:`❌ 无法终止 Shell (${$.shell_id})`,error:{type:"execution_error",message:"发送终止信号失败"},metadata:{...W}};let V=W.alreadyExited?`Shell ${$.shell_id} 已经处于 ${W.status} 状态`:`已向 Shell ${$.shell_id} 发送终止信号`;return{success:!0,llmContent:{shell_id:$.shell_id,status:W.status,already_exited:W.alreadyExited,pid:W.pid,exit_code:W.exitCode,signal:W.signal},displayContent:W.alreadyExited?`ℹ️ ${V}`:`✂️ ${V}`,metadata:{...W}}},version:"1.0.0",category:"命令工具",tags:["bash","shell","terminate"],extractSignatureContent:($)=>$.shell_id,abstractPermissionRule:()=>"*"});import{z as n$}from"zod";import{nanoid as b7}from"nanoid";import{nanoid as o5}from"nanoid";import{promises as s}from"node:fs";import*as f from"node:path";import{fileURLToPath as t5}from"node:url";var m4=["init","requirements","design","tasks","implementation","done"],c4=["pending","in_progress","completed","blocked","skipped"],i4=["low","medium","high"],l4={proposal:"proposal.md",spec:"spec.md",requirements:"requirements.md",design:"design.md",tasks:"tasks.md",meta:".meta.json"},Q0={SPECS:"specs",CHANGES:"changes",ARCHIVE:"archive",STEERING:"steering",SPEC_DELTA:"specs"},Z0={CONSTITUTION:"constitution.md",PRODUCT:"product.md",TECH:"tech.md",STRUCTURE:"structure.md"},zJ=["init","requirements","design","tasks","implementation","done"],t0={init:["requirements"],requirements:["design","tasks"],design:["tasks"],tasks:["implementation"],implementation:["done","tasks"],done:[]},F$={init:"初始化",requirements:"需求定义",design:"架构设计",tasks:"任务分解",implementation:"实现中",done:"已完成"},n4={init:"proposal",requirements:"requirements",design:"design",tasks:"tasks",implementation:"tasks",done:null};var e5=t5(import.meta.url),$7=f.dirname(e5),s4=f.join($7,"templates");class e0{workspaceRoot;bladeDir;constructor($){this.workspaceRoot=$,this.bladeDir=f.join($,".blade")}getSpecsDir(){return f.join(this.bladeDir,Q0.SPECS)}getChangesDir(){return f.join(this.bladeDir,Q0.CHANGES)}getArchiveDir(){return f.join(this.bladeDir,Q0.ARCHIVE)}getSteeringDir(){return f.join(this.bladeDir,Q0.STEERING)}getChangePath($){return f.join(this.getChangesDir(),$)}getChangeFilePath($,b){return f.join(this.getChangePath($),l4[b])}async initializeDirectories(){await s.mkdir(this.getChangesDir(),{recursive:!0,mode:493})}async createChangeDir($){let b=this.getChangePath($);return await s.mkdir(b,{recursive:!0,mode:493}),await s.mkdir(f.join(b,Q0.SPEC_DELTA),{recursive:!0,mode:493}),b}async readFile($){try{return await s.readFile($,"utf-8")}catch(b){if(n(b)==="ENOENT")return null;throw b}}async writeFile($,b){let w=f.dirname($);await s.mkdir(w,{recursive:!0,mode:493}),await s.writeFile($,b,"utf-8")}async fileExists($){try{return await s.access($),!0}catch{return!1}}async dirExists($){try{return(await s.stat($)).isDirectory()}catch{return!1}}createMetadata($,b){let w=new Date().toISOString();return{id:o5(),name:$,description:b,phase:"init",createdAt:w,updatedAt:w,tasks:[]}}async readMetadata($){let b=this.getChangeFilePath($,"meta"),w=await this.readFile(b);if(!w)return null;try{return JSON.parse(w)}catch{return null}}async writeMetadata($,b){let w=this.getChangeFilePath($,"meta");b.updatedAt=new Date().toISOString(),await this.writeFile(w,JSON.stringify(b,null,2))}async updatePhase($,b){let w=await this.readMetadata($);if(!w)return null;return w.phase=b,await this.writeMetadata($,w),w}async readSpecFile($,b){let w=this.getChangeFilePath($,b);return this.readFile(w)}async writeSpecFile($,b,w){let W=this.getChangeFilePath($,b);await this.writeFile(W,w);let V=await this.readMetadata($);if(V)await this.writeMetadata($,V)}async getPhaseContent($,b){let w=n4[b];if(!w)return null;return this.readSpecFile($,w)}async readSteeringContext(){let $=this.getSteeringDir(),[b,w,W,V]=await Promise.all([this.readFile(f.join($,Z0.CONSTITUTION)),this.readFile(f.join($,Z0.PRODUCT)),this.readFile(f.join($,Z0.TECH)),this.readFile(f.join($,Z0.STRUCTURE))]);return{constitution:b||void 0,product:w||void 0,tech:W||void 0,structure:V||void 0}}async writeSteeringFile($,b){let w=f.join(this.getSteeringDir(),Z0[$]);await this.writeFile(w,b)}async hasSteeringDocs(){let $=this.getSteeringDir();if(!await this.dirExists($))return!1;return(await s.readdir($)).length>0}async listActiveChanges(){let $=this.getChangesDir();if(!await this.dirExists($))return[];return(await s.readdir($,{withFileTypes:!0})).filter((w)=>w.isDirectory()).map((w)=>w.name)}async listArchivedChanges(){let $=this.getArchiveDir();if(!await this.dirExists($))return[];return(await s.readdir($,{withFileTypes:!0})).filter((w)=>w.isDirectory()).map((w)=>w.name)}async changeExists($){return this.dirExists(this.getChangePath($))}async archiveChange($){let b=this.getChangePath($),w=f.join(this.getArchiveDir(),$);await s.mkdir(f.dirname(w),{recursive:!0,mode:493}),await s.rename(b,w)}async restoreChange($){let b=f.join(this.getArchiveDir(),$),w=this.getChangePath($);await s.rename(b,w)}async listSpecDomains(){let $=this.getSpecsDir();if(!await this.dirExists($))return[];return(await s.readdir($,{withFileTypes:!0})).filter((w)=>w.isDirectory()).map((w)=>w.name)}async readAuthorativeSpec($){let b=f.join(this.getSpecsDir(),$,"spec.md");return this.readFile(b)}async writeAuthorativeSpec($,b){let w=f.join(this.getSpecsDir(),$,"spec.md");await this.writeFile(w,b)}async mergeSpecDeltas($){let b=f.join(this.getChangePath($),Q0.SPEC_DELTA);if(!await this.dirExists(b))return[];let w=[],W=await s.readdir(b,{withFileTypes:!0});for(let V of W){if(!V.isDirectory())continue;let Q=f.join(b,V.name,"spec.md"),Z=await this.readFile(Q);if(Z){let J=await this.readAuthorativeSpec(V.name),Y=J?`${J}
904
788
 
905
789
  ---
906
790
 
907
791
  <!-- Merged from ${$} -->
908
792
 
909
- ${Z}`:Z;await this.writeAuthorativeSpec(W.name,J),w.push(W.name)}}return w}static TEMPLATE_NAMES={proposal:"proposal.md.template",spec:"spec.md.template",requirements:"requirements.md.template",design:"design.md.template",tasks:"tasks.md.template",meta:""};static STEERING_TEMPLATE_NAMES={CONSTITUTION:"steering/constitution.md.template",PRODUCT:"steering/product.md.template",TECH:"steering/tech.md.template",STRUCTURE:"steering/structure.md.template"};async readTemplate($){let b=r0.TEMPLATE_NAMES[$];if(!b)return null;let w=f.join(u4,b);return this.readFile(w)}async readSteeringTemplate($){let b=r0.STEERING_TEMPLATE_NAMES[$],w=f.join(u4,b);return this.readFile(w)}fillTemplate($,b){let w=$;for(let[V,W]of Object.entries(b))w=w.replace(new RegExp(`\\{\\{${V}\\}\\}`,"g"),W);return w}async createFromTemplate($,b,w){let V=await this.readTemplate(b);if(!V)return null;let W=this.fillTemplate(V,{name:$,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),...w});return await this.writeSpecFile($,b,W),W}async createSteeringFromTemplate($,b={}){let w=await this.readSteeringTemplate($);if(!w)return null;let V=this.fillTemplate(w,{createdAt:new Date().toISOString(),...b});return await this.writeSteeringFile($,V),V}async initializeSteeringDocs(){let $=[],b=this.getSteeringDir();for(let[w,V]of Object.entries(b0)){let W=f.join(b,V);if(!await this.fileExists(W))await this.createSteeringFromTemplate(w),$.push(V)}return $}}var m1=N("Spec");class x{static instance=null;fileManager=null;state={currentSpec:null,specPath:null,isActive:!1,recentSpecs:[],steeringContext:null};stateChangeCallbacks=[];constructor(){}static getInstance(){if(!x.instance)x.instance=new x;return x.instance}static resetInstance(){x.instance=null}onStateChange($){return this.stateChangeCallbacks.push($),()=>{let b=this.stateChangeCallbacks.indexOf($);if(b>-1)this.stateChangeCallbacks.splice(b,1)}}notifyStateChange(){for(let $ of this.stateChangeCallbacks)$(this.state)}updateState($){this.state={...this.state,...$},this.notifyStateChange()}async initialize($){if(this.fileManager){m1.debug("SpecManager already initialized, skipping...");return}this.fileManager=new r0($),await this.fileManager.initializeDirectories();let b=await this.fileManager.readSteeringContext();this.updateState({steeringContext:b}),m1.debug("SpecManager initialized successfully")}getFileManager(){if(!this.fileManager)throw Error("SpecManager not initialized. Call initialize() first.");return this.fileManager}getState(){return{...this.state}}getCurrentSpec(){return this.state.currentSpec}isActive(){return this.state.isActive}getSteeringContext(){return this.state.steeringContext}async getSteeringContextString(){let $=this.state.steeringContext;if(!$)return null;let b=[];if($.constitution)b.push(`## Constitution (Project Governance)
793
+ ${Z}`:Z;await this.writeAuthorativeSpec(V.name,Y),w.push(V.name)}}return w}static TEMPLATE_NAMES={proposal:"proposal.md.template",spec:"spec.md.template",requirements:"requirements.md.template",design:"design.md.template",tasks:"tasks.md.template",meta:""};static STEERING_TEMPLATE_NAMES={CONSTITUTION:"steering/constitution.md.template",PRODUCT:"steering/product.md.template",TECH:"steering/tech.md.template",STRUCTURE:"steering/structure.md.template"};async readTemplate($){let b=e0.TEMPLATE_NAMES[$];if(!b)return null;let w=f.join(s4,b);return this.readFile(w)}async readSteeringTemplate($){let b=e0.STEERING_TEMPLATE_NAMES[$],w=f.join(s4,b);return this.readFile(w)}fillTemplate($,b){let w=$;for(let[W,V]of Object.entries(b))w=w.replace(new RegExp(`\\{\\{${W}\\}\\}`,"g"),V);return w}async createFromTemplate($,b,w){let W=await this.readTemplate(b);if(!W)return null;let V=this.fillTemplate(W,{name:$,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),...w});return await this.writeSpecFile($,b,V),V}async createSteeringFromTemplate($,b={}){let w=await this.readSteeringTemplate($);if(!w)return null;let W=this.fillTemplate(w,{createdAt:new Date().toISOString(),...b});return await this.writeSteeringFile($,W),W}async initializeSteeringDocs(){let $=[],b=this.getSteeringDir();for(let[w,W]of Object.entries(Z0)){let V=f.join(b,W);if(!await this.fileExists(V))await this.createSteeringFromTemplate(w),$.push(W)}return $}}var h1=E("Spec");class p{static instance=null;fileManager=null;state={currentSpec:null,specPath:null,isActive:!1,recentSpecs:[],steeringContext:null};stateChangeCallbacks=[];constructor(){}static getInstance(){if(!p.instance)p.instance=new p;return p.instance}static resetInstance(){p.instance=null}onStateChange($){return this.stateChangeCallbacks.push($),()=>{let b=this.stateChangeCallbacks.indexOf($);if(b>-1)this.stateChangeCallbacks.splice(b,1)}}notifyStateChange(){for(let $ of this.stateChangeCallbacks)$(this.state)}updateState($){this.state={...this.state,...$},this.notifyStateChange()}async initialize($){if(this.fileManager){h1.debug("SpecManager already initialized, skipping...");return}this.fileManager=new e0($),await this.fileManager.initializeDirectories();let b=await this.fileManager.readSteeringContext();this.updateState({steeringContext:b}),h1.debug("SpecManager initialized successfully")}getFileManager(){if(!this.fileManager)throw Error("SpecManager not initialized. Call initialize() first.");return this.fileManager}getState(){return{...this.state}}getCurrentSpec(){return this.state.currentSpec}isActive(){return this.state.isActive}getSteeringContext(){return this.state.steeringContext}async getSteeringContextString(){let $=this.state.steeringContext;if(!$)return null;let b=[];if($.constitution)b.push(`## Constitution (Project Governance)
910
794
 
911
795
  ${$.constitution}`);if($.product)b.push(`## Product Vision
912
796
 
@@ -918,7 +802,7 @@ ${$.structure}`);return b.length>0?b.join(`
918
802
 
919
803
  ---
920
804
 
921
- `):null}async createSpec($,b){let w=this.getFileManager();if(await w.changeExists($))return{success:!1,message:`Spec "${$}" already exists`,error:"SPEC_EXISTS"};let V=await w.createChangeDir($),W=w.createMetadata($,b);await w.writeMetadata($,W);let Q=this.generateProposalTemplate($,b);await w.writeSpecFile($,"proposal",Q);let Z=this.state.recentSpecs.filter((Y)=>Y!==$);return Z.unshift($),this.updateState({currentSpec:W,specPath:V,isActive:!0,recentSpecs:Z.slice(0,10)}),{success:!0,message:`Spec "${$}" created successfully`,data:{spec:W,path:V}}}async loadSpec($){let b=this.getFileManager(),w=await b.readMetadata($);if(!w)return{success:!1,message:`Spec "${$}" not found`,error:"SPEC_NOT_FOUND"};let V=b.getChangePath($),W=this.state.recentSpecs.filter((Q)=>Q!==$);return W.unshift($),this.updateState({currentSpec:w,specPath:V,isActive:!0,recentSpecs:W.slice(0,10)}),{success:!0,message:`Spec "${$}" loaded successfully`,data:{spec:w,path:V}}}closeSpec(){this.updateState({currentSpec:null,specPath:null,isActive:!1})}exitSpecMode(){this.closeSpec()}async transitionPhase($){let b=this.getCurrentSpec();if(!b)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};if(!s0[b.phase].includes($))return{success:!1,message:`Cannot transition from "${b.phase}" to "${$}"`,error:"INVALID_TRANSITION"};let W=await this.getFileManager().updatePhase(b.name,$);if(!W)return{success:!1,message:"Failed to update phase",error:"UPDATE_FAILED"};if(this.updateState({currentSpec:W}),$==="done")m1.info("Spec completed");return{success:!0,message:`Transitioned to "${$}" phase`,data:{spec:W,phase:$}}}getAllowedTransitions(){let $=this.getCurrentSpec();if(!$)return[];return s0[$.phase]}async addTask($,b,w){let V=this.getCurrentSpec();if(!V)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let W={id:y6(8),title:$,description:b,status:"pending",dependencies:w?.dependencies||[],affectedFiles:w?.affectedFiles||[],complexity:w?.complexity||"medium"},Q={...V,tasks:[...V.tasks,W],updatedAt:new Date().toISOString()};return await this.getFileManager().writeMetadata(V.name,Q),this.updateState({currentSpec:Q}),{success:!0,message:`Task "${$}" added`,data:{task:W}}}async updateTaskStatus($,b){let w=this.getCurrentSpec();if(!w)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let V=w.tasks.find((Y)=>Y.id===$);if(!V)return{success:!1,message:`Task "${$}" not found`,error:"TASK_NOT_FOUND"};let W={...V,status:b,completedAt:b==="completed"?new Date().toISOString():V.completedAt},Q=w.tasks.map((Y)=>Y.id===$?W:Y),Z={...w,tasks:Q,currentTaskId:b==="in_progress"?$:w.currentTaskId===$?void 0:w.currentTaskId,updatedAt:new Date().toISOString()};return await this.getFileManager().writeMetadata(w.name,Z),this.updateState({currentSpec:Z}),{success:!0,message:`Task status updated to "${b}"`,data:{task:W}}}getNextTask(){let $=this.getCurrentSpec();if(!$)return null;return $.tasks.find((b)=>{if(b.status!=="pending")return!1;return b.dependencies.every((w)=>{return $.tasks.find((W)=>W.id===w)?.status==="completed"})})||null}getTaskProgress(){let $=this.getCurrentSpec();if(!$||$.tasks.length===0)return{total:0,completed:0,percentage:0};let b=$.tasks.length,w=$.tasks.filter((W)=>W.status==="completed").length,V=Math.round(w/b*100);return{total:b,completed:w,percentage:V}}async listSpecs($){let b=this.getFileManager(),w=[],V=await b.listActiveChanges();for(let W of V){let Q=await b.readMetadata(W);if(!Q)continue;if($?.phase&&Q.phase!==$.phase)continue;if($?.tags&&!$.tags.some((Y)=>Q.tags?.includes(Y)))continue;if($?.query&&!Q.name.toLowerCase().includes($.query.toLowerCase())&&!Q.description.toLowerCase().includes($.query.toLowerCase()))continue;let Z=this.calculateTaskProgress(Q.tasks);w.push({name:Q.name,description:Q.description,phase:Q.phase,updatedAt:Q.updatedAt,path:b.getChangePath(W),isArchived:!1,taskProgress:Z})}if($?.includeArchived){let W=await b.listArchivedChanges();for(let Q of W)w.push({name:Q,description:"(archived)",phase:"done",updatedAt:"",path:`${b.getArchiveDir()}/${Q}`,isArchived:!0,taskProgress:{total:0,completed:0}})}return w.sort((W,Q)=>{if(W.isArchived!==Q.isArchived)return W.isArchived?1:-1;return new Date(Q.updatedAt).getTime()-new Date(W.updatedAt).getTime()}),w}async archiveCurrentSpec(){let $=this.getCurrentSpec();if(!$)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let b=this.getFileManager();return await b.mergeSpecDeltas($.name),await b.updatePhase($.name,"done"),await b.archiveChange($.name),this.closeSpec(),{success:!0,message:`Spec "${$.name}" archived successfully`,data:{spec:{...$,phase:"done"}}}}async validateCurrentSpec(){let $=this.getCurrentSpec();if(!$)return{valid:!1,phase:"init",completeness:{proposal:!1,spec:!1,requirements:!1,design:!1,tasks:!1},issues:[{severity:"error",file:"meta",message:"No active spec"}],suggestions:["Create a new spec with /spec proposal <name>"]};let b=this.getFileManager(),w=[],V=[],[W,Q,Z,Y,J]=await Promise.all([b.readSpecFile($.name,"proposal"),b.readSpecFile($.name,"spec"),b.readSpecFile($.name,"requirements"),b.readSpecFile($.name,"design"),b.readSpecFile($.name,"tasks")]),X={proposal:!!W,spec:!!Q,requirements:!!Z,design:!!Y,tasks:!!J};if($.phase==="requirements"&&!X.requirements)w.push({severity:"warning",file:"requirements",message:"Requirements document is missing"}),V.push("Generate requirements using EARS format");if($.phase==="design"&&!X.design)w.push({severity:"warning",file:"design",message:"Design document is missing"}),V.push("Create architecture diagrams and API contracts");if($.phase==="tasks"&&$.tasks.length===0)w.push({severity:"warning",file:"tasks",message:"No tasks defined"}),V.push("Break down the spec into atomic tasks");if($.phase==="implementation"){let O=this.getTaskProgress();if(O.completed<O.total)w.push({severity:"info",file:"tasks",message:`${O.total-O.completed} tasks remaining`})}return{valid:w.filter((O)=>O.severity==="error").length===0,phase:$.phase,completeness:X,issues:w,suggestions:V}}generateProposalTemplate($,b){return`# ${$}
805
+ `):null}async createSpec($,b){let w=this.getFileManager();if(await w.changeExists($))return{success:!1,message:`Spec "${$}" already exists`,error:"SPEC_EXISTS"};let W=await w.createChangeDir($),V=w.createMetadata($,b);await w.writeMetadata($,V);let Q=this.generateProposalTemplate($,b);await w.writeSpecFile($,"proposal",Q);let Z=this.state.recentSpecs.filter((J)=>J!==$);return Z.unshift($),this.updateState({currentSpec:V,specPath:W,isActive:!0,recentSpecs:Z.slice(0,10)}),{success:!0,message:`Spec "${$}" created successfully`,data:{spec:V,path:W}}}async loadSpec($){let b=this.getFileManager(),w=await b.readMetadata($);if(!w)return{success:!1,message:`Spec "${$}" not found`,error:"SPEC_NOT_FOUND"};let W=b.getChangePath($),V=this.state.recentSpecs.filter((Q)=>Q!==$);return V.unshift($),this.updateState({currentSpec:w,specPath:W,isActive:!0,recentSpecs:V.slice(0,10)}),{success:!0,message:`Spec "${$}" loaded successfully`,data:{spec:w,path:W}}}closeSpec(){this.updateState({currentSpec:null,specPath:null,isActive:!1})}exitSpecMode(){this.closeSpec()}async transitionPhase($){let b=this.getCurrentSpec();if(!b)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};if(!t0[b.phase].includes($))return{success:!1,message:`Cannot transition from "${b.phase}" to "${$}"`,error:"INVALID_TRANSITION"};let V=await this.getFileManager().updatePhase(b.name,$);if(!V)return{success:!1,message:"Failed to update phase",error:"UPDATE_FAILED"};if(this.updateState({currentSpec:V}),$==="done")h1.info("Spec completed");return{success:!0,message:`Transitioned to "${$}" phase`,data:{spec:V,phase:$}}}getAllowedTransitions(){let $=this.getCurrentSpec();if(!$)return[];return t0[$.phase]}async addTask($,b,w){let W=this.getCurrentSpec();if(!W)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let V={id:b7(8),title:$,description:b,status:"pending",dependencies:w?.dependencies||[],affectedFiles:w?.affectedFiles||[],complexity:w?.complexity||"medium"},Q={...W,tasks:[...W.tasks,V],updatedAt:new Date().toISOString()};return await this.getFileManager().writeMetadata(W.name,Q),this.updateState({currentSpec:Q}),{success:!0,message:`Task "${$}" added`,data:{task:V}}}async updateTaskStatus($,b){let w=this.getCurrentSpec();if(!w)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let W=w.tasks.find((J)=>J.id===$);if(!W)return{success:!1,message:`Task "${$}" not found`,error:"TASK_NOT_FOUND"};let V={...W,status:b,completedAt:b==="completed"?new Date().toISOString():W.completedAt},Q=w.tasks.map((J)=>J.id===$?V:J),Z={...w,tasks:Q,currentTaskId:b==="in_progress"?$:w.currentTaskId===$?void 0:w.currentTaskId,updatedAt:new Date().toISOString()};return await this.getFileManager().writeMetadata(w.name,Z),this.updateState({currentSpec:Z}),{success:!0,message:`Task status updated to "${b}"`,data:{task:V}}}getNextTask(){let $=this.getCurrentSpec();if(!$)return null;return $.tasks.find((b)=>{if(b.status!=="pending")return!1;return b.dependencies.every((w)=>{return $.tasks.find((V)=>V.id===w)?.status==="completed"})})||null}getTaskProgress(){let $=this.getCurrentSpec();if(!$||$.tasks.length===0)return{total:0,completed:0,percentage:0};let b=$.tasks.length,w=$.tasks.filter((V)=>V.status==="completed").length,W=Math.round(w/b*100);return{total:b,completed:w,percentage:W}}async listSpecs($){let b=this.getFileManager(),w=[],W=await b.listActiveChanges();for(let V of W){let Q=await b.readMetadata(V);if(!Q)continue;if($?.phase&&Q.phase!==$.phase)continue;if($?.tags&&!$.tags.some((J)=>Q.tags?.includes(J)))continue;if($?.query&&!Q.name.toLowerCase().includes($.query.toLowerCase())&&!Q.description.toLowerCase().includes($.query.toLowerCase()))continue;let Z=this.calculateTaskProgress(Q.tasks);w.push({name:Q.name,description:Q.description,phase:Q.phase,updatedAt:Q.updatedAt,path:b.getChangePath(V),isArchived:!1,taskProgress:Z})}if($?.includeArchived){let V=await b.listArchivedChanges();for(let Q of V)w.push({name:Q,description:"(archived)",phase:"done",updatedAt:"",path:`${b.getArchiveDir()}/${Q}`,isArchived:!0,taskProgress:{total:0,completed:0}})}return w.sort((V,Q)=>{if(V.isArchived!==Q.isArchived)return V.isArchived?1:-1;return new Date(Q.updatedAt).getTime()-new Date(V.updatedAt).getTime()}),w}async archiveCurrentSpec(){let $=this.getCurrentSpec();if(!$)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let b=this.getFileManager();return await b.mergeSpecDeltas($.name),await b.updatePhase($.name,"done"),await b.archiveChange($.name),this.closeSpec(),{success:!0,message:`Spec "${$.name}" archived successfully`,data:{spec:{...$,phase:"done"}}}}async validateCurrentSpec(){let $=this.getCurrentSpec();if(!$)return{valid:!1,phase:"init",completeness:{proposal:!1,spec:!1,requirements:!1,design:!1,tasks:!1},issues:[{severity:"error",file:"meta",message:"No active spec"}],suggestions:["Create a new spec with /spec proposal <name>"]};let b=this.getFileManager(),w=[],W=[],[V,Q,Z,J,Y]=await Promise.all([b.readSpecFile($.name,"proposal"),b.readSpecFile($.name,"spec"),b.readSpecFile($.name,"requirements"),b.readSpecFile($.name,"design"),b.readSpecFile($.name,"tasks")]),X={proposal:!!V,spec:!!Q,requirements:!!Z,design:!!J,tasks:!!Y};if($.phase==="requirements"&&!X.requirements)w.push({severity:"warning",file:"requirements",message:"Requirements document is missing"}),W.push("Generate requirements using EARS format");if($.phase==="design"&&!X.design)w.push({severity:"warning",file:"design",message:"Design document is missing"}),W.push("Create architecture diagrams and API contracts");if($.phase==="tasks"&&$.tasks.length===0)w.push({severity:"warning",file:"tasks",message:"No tasks defined"}),W.push("Break down the spec into atomic tasks");if($.phase==="implementation"){let O=this.getTaskProgress();if(O.completed<O.total)w.push({severity:"info",file:"tasks",message:`${O.total-O.completed} tasks remaining`})}return{valid:w.filter((O)=>O.severity==="error").length===0,phase:$.phase,completeness:X,issues:w,suggestions:W}}generateProposalTemplate($,b){return`# ${$}
922
806
 
923
807
  ## Summary
924
808
 
@@ -952,7 +836,7 @@ ${b}
952
836
  <!-- What needs to be clarified before proceeding? -->
953
837
 
954
838
  1.
955
- `}calculateTaskProgress($){let b=$.length,w=$.filter((V)=>V.status==="completed").length;return{total:b,completed:w}}}var g4=E({name:"AddTask",displayName:"Add Task",kind:"write",schema:c$.object({title:c$.string().min(1).describe("Brief title of the task"),description:c$.string().min(1).describe("Detailed description of what needs to be done"),complexity:c$.enum(["low","medium","high"]).optional().default("medium").describe("Estimated complexity of the task"),affectedFiles:c$.array(c$.string()).optional().default([]).describe("List of files that will be modified by this task"),dependencies:c$.array(c$.string()).optional().default([]).describe("IDs of tasks that must be completed before this one")}),description:{short:"Add a task to the current Spec project",long:`Use this tool to add tasks to the current Spec-Driven Development project.
839
+ `}calculateTaskProgress($){let b=$.length,w=$.filter((W)=>W.status==="completed").length;return{total:b,completed:w}}}var r4=L({name:"AddTask",displayName:"Add Task",kind:"write",schema:n$.object({title:n$.string().min(1).describe("Brief title of the task"),description:n$.string().min(1).describe("Detailed description of what needs to be done"),complexity:n$.enum(i4).optional().default("medium").describe("Estimated complexity of the task"),affectedFiles:n$.array(n$.string()).optional().default([]).describe("List of files that will be modified by this task"),dependencies:n$.array(n$.string()).optional().default([]).describe("IDs of tasks that must be completed before this one")}),description:{short:"Add a task to the current Spec project",long:`Use this tool to add tasks to the current Spec-Driven Development project.
956
840
 
957
841
  ## Task Structure
958
842
 
@@ -987,16 +871,16 @@ AddTask({
987
871
  - Tasks are tracked in .meta.json, not tasks.md
988
872
  - Use UpdateTaskStatus to mark tasks as completed
989
873
  - Use GetSpecContext to see current tasks and progress
990
- `},async execute($,b){let{title:w,description:V,complexity:W,affectedFiles:Q,dependencies:Z}=$,Y=x.getInstance();if(!Y.getCurrentSpec())return{success:!1,llmContent:"No active spec. Use EnterSpecMode to start a new spec project, or use the /spec command to load an existing one.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};let X=await Y.addTask(w,V,{complexity:W,affectedFiles:Q,dependencies:Z});if(!X.success)return{success:!1,llmContent:`Failed to add task: ${X.message}`,displayContent:`❌ Failed to add task: ${X.message}`,error:{type:"execution_error",message:X.message}};let O=X.data?.task,G=Y.getTaskProgress();return{success:!0,llmContent:`✅ Task added: "${w}"
874
+ `},async execute($,b){let{title:w,description:W,complexity:V,affectedFiles:Q,dependencies:Z}=$,J=p.getInstance();if(!J.getCurrentSpec())return{success:!1,llmContent:"No active spec. Use EnterSpecMode to start a new spec project, or use the /spec command to load an existing one.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};let X=await J.addTask(w,W,{complexity:V,affectedFiles:Q,dependencies:Z});if(!X.success)return{success:!1,llmContent:`Failed to add task: ${X.message}`,displayContent:`❌ Failed to add task: ${X.message}`,error:{type:"execution_error",message:X.message}};let O=X.data?.task,G=J.getTaskProgress();return{success:!0,llmContent:`✅ Task added: "${w}"
991
875
 
992
876
  `+`\uD83D\uDCCB Task ID: ${O?.id}
993
- `+`\uD83D\uDCCA Complexity: ${W}
877
+ `+`\uD83D\uDCCA Complexity: ${V}
994
878
  `+`\uD83D\uDCC1 Affected files: ${Q?.length?Q.join(", "):"None specified"}
995
879
  `+`\uD83D\uDD17 Dependencies: ${Z?.length?Z.join(", "):"None"}
996
880
 
997
881
  `+`\uD83D\uDCC8 Progress: ${G.completed}/${G.total} tasks (${G.percentage}%)
998
882
 
999
- `+"\uD83D\uDCA1 Use AddTask to add more tasks, or use /spec apply to start implementation.",displayContent:`✅ Added task: ${w} (ID: ${O?.id})`,metadata:{taskId:O?.id,title:w,complexity:W,affectedFiles:Q,dependencies:Z,totalTasks:G.total}}}});import{z as c1}from"zod";var m4=E({name:"EnterSpecMode",displayName:"Enter Spec Mode",kind:"readonly",schema:c1.object({featureName:c1.string().min(1).describe("The name of the feature/change (used as directory name)"),description:c1.string().min(1).describe("Brief description of what this feature/change does")}),description:{short:"Enter Spec-Driven Development mode for complex features",long:`Use this tool to enter Spec mode when you need to implement a complex feature that benefits from structured planning.
883
+ `+"\uD83D\uDCA1 Use AddTask to add more tasks, or use /spec apply to start implementation.",displayContent:`✅ Added task: ${w} (ID: ${O?.id})`,metadata:{taskId:O?.id,title:w,complexity:V,affectedFiles:Q,dependencies:Z,totalTasks:G.total}}}});import{z as x1}from"zod";var a4=L({name:"EnterSpecMode",displayName:"Enter Spec Mode",kind:"readonly",schema:x1.object({featureName:x1.string().min(1).describe("The name of the feature/change (used as directory name)"),description:x1.string().min(1).describe("Brief description of what this feature/change does")}),description:{short:"Enter Spec-Driven Development mode for complex features",long:`Use this tool to enter Spec mode when you need to implement a complex feature that benefits from structured planning.
1000
884
 
1001
885
  ## Spec-Driven Development (SDD)
1002
886
 
@@ -1054,16 +938,16 @@ For simpler planning needs, consider using EnterPlanMode instead.
1054
938
  ├── tasks.md # Task breakdown
1055
939
  └── .meta.json # Metadata and progress
1056
940
  \`\`\`
1057
- `},async execute($,b){let{featureName:w,description:V}=$;if(!/^[a-zA-Z0-9_-]+$/.test(w))return{success:!1,llmContent:"Invalid feature name. Use only letters, numbers, underscores, and hyphens.",displayContent:"❌ Invalid feature name",error:{type:"validation_error",message:"Feature name must be alphanumeric with underscores/hyphens only"}};if(b.confirmationHandler)try{if((await b.confirmationHandler.requestConfirmation({title:"Enter Spec Mode",message:`The assistant requests to enter Spec mode for: **${w}**
941
+ `},async execute($,b){let{featureName:w,description:W}=$;if(!/^[a-zA-Z0-9_-]+$/.test(w))return{success:!1,llmContent:"Invalid feature name. Use only letters, numbers, underscores, and hyphens.",displayContent:"❌ Invalid feature name",error:{type:"validation_error",message:"Feature name must be alphanumeric with underscores/hyphens only"}};if(b.confirmationHandler)try{if((await b.confirmationHandler.requestConfirmation({title:"Enter Spec Mode",message:`The assistant requests to enter Spec mode for: **${w}**
1058
942
 
1059
- Description: ${V}
943
+ Description: ${W}
1060
944
 
1061
945
  In Spec mode, the assistant will:
1062
946
  1. Create structured specification documents
1063
947
  `+`2. Guide you through Requirements → Design → Tasks → Implementation
1064
948
  `+`3. Track progress and maintain documentation
1065
949
 
1066
- Do you want to enter Spec mode?`,details:`Will create: .blade/changes/${w}/`})).approved){let Q=b.workspaceRoot||process.cwd(),Z=x.getInstance();try{await Z.initialize(Q);let Y=await Z.createSpec(w,V);if(!Y.success)return{success:!1,llmContent:`Failed to create Spec: ${Y.message}`,displayContent:`❌ Failed to create Spec: ${Y.message}`,error:{type:"execution_error",message:Y.message}};return{success:!0,llmContent:`✅ Created Spec: "${w}"
950
+ Do you want to enter Spec mode?`,details:`Will create: .blade/changes/${w}/`})).approved){let Q=b.workspaceRoot||process.cwd(),Z=p.getInstance();try{await Z.initialize(Q);let J=await Z.createSpec(w,W);if(!J.success)return{success:!1,llmContent:`Failed to create Spec: ${J.message}`,displayContent:`❌ Failed to create Spec: ${J.message}`,error:{type:"execution_error",message:J.message}};return{success:!0,llmContent:`✅ Created Spec: "${w}"
1067
951
 
1068
952
  `+`\uD83D\uDCC1 Location: .blade/changes/${w}/
1069
953
 
@@ -1087,12 +971,12 @@ You are now in SPEC MODE. Your workflow:
1087
971
  - Use UpdateTaskStatus to track progress
1088
972
  - Call ExitSpecMode when done
1089
973
 
1090
- Start by asking the user for more details about their requirements.`,displayContent:`✅ Created Spec: ${w}`,metadata:{approved:!0,enterSpecMode:!0,featureName:w,description:V,specPath:`.blade/changes/${w}/`}}}catch(Y){return{success:!1,llmContent:`Failed to initialize Spec: ${Y instanceof Error?Y.message:"Unknown error"}`,displayContent:"❌ Failed to initialize Spec",error:{type:"execution_error",message:Y instanceof Error?Y.message:"Initialization failed"}}}}else return{success:!0,llmContent:`⚠️ User declined to enter Spec mode.
974
+ Start by asking the user for more details about their requirements.`,displayContent:`✅ Created Spec: ${w}`,metadata:{approved:!0,enterSpecMode:!0,featureName:w,description:W,specPath:`.blade/changes/${w}/`}}}catch(J){return{success:!1,llmContent:`Failed to initialize Spec: ${J instanceof Error?J.message:"Unknown error"}`,displayContent:"❌ Failed to initialize Spec",error:{type:"execution_error",message:J instanceof Error?J.message:"Initialization failed"}}}}else return{success:!0,llmContent:`⚠️ User declined to enter Spec mode.
1091
975
 
1092
- `+"Proceed with the task using regular workflow. You can use Plan mode for lighter planning, or implement directly if the task is straightforward.",displayContent:"⚠️ Spec mode declined",metadata:{approved:!1,enterSpecMode:!1}}}catch(W){return{success:!1,llmContent:`Confirmation error: ${W instanceof Error?W.message:"Unknown error"}`,displayContent:"❌ Confirmation failed",error:{type:"execution_error",message:"Confirmation flow error"}}}return{success:!0,llmContent:`Spec mode requested for "${w}" but no interactive confirmation available.
976
+ `+"Proceed with the task using regular workflow. You can use Plan mode for lighter planning, or implement directly if the task is straightforward.",displayContent:"⚠️ Spec mode declined",metadata:{approved:!1,enterSpecMode:!1}}}catch(V){return{success:!1,llmContent:`Confirmation error: ${V instanceof Error?V.message:"Unknown error"}`,displayContent:"❌ Confirmation failed",error:{type:"execution_error",message:"Confirmation flow error"}}}return{success:!0,llmContent:`Spec mode requested for "${w}" but no interactive confirmation available.
1093
977
 
1094
978
  Proceeding with spec creation. Follow the structured workflow:
1095
- `+"1. Requirements → 2. Design → 3. Tasks → 4. Implementation",displayContent:`Spec mode: ${w} (non-interactive)`,metadata:{approved:null,enterSpecMode:!0,featureName:w,description:V}}}});import{z as i1}from"zod";var c4=E({name:"ExitSpecMode",displayName:"Exit Spec Mode",kind:"readonly",schema:i1.object({archive:i1.boolean().optional().default(!1).describe("If true, archive the spec (mark as done and move to archive)"),summary:i1.string().optional().describe("Optional summary of what was accomplished")}),description:{short:"Exit Spec mode and optionally archive the completed spec",long:`Use this tool to exit Spec-Driven Development mode.
979
+ `+"1. Requirements → 2. Design → 3. Tasks → 4. Implementation",displayContent:`Spec mode: ${w} (non-interactive)`,metadata:{approved:null,enterSpecMode:!0,featureName:w,description:W}}}});import{z as p1}from"zod";var o4=L({name:"ExitSpecMode",displayName:"Exit Spec Mode",kind:"readonly",schema:p1.object({archive:p1.boolean().optional().default(!1).describe("If true, archive the spec (mark as done and move to archive)"),summary:p1.string().optional().describe("Optional summary of what was accomplished")}),description:{short:"Exit Spec mode and optionally archive the completed spec",long:`Use this tool to exit Spec-Driven Development mode.
1096
980
 
1097
981
  ## Options
1098
982
 
@@ -1126,30 +1010,30 @@ ExitSpecMode({})
1126
1010
  // Complete and archive
1127
1011
  ExitSpecMode({ archive: true, summary: "Implemented OAuth2 authentication" })
1128
1012
  \`\`\`
1129
- `},async execute($,b){let{archive:w,summary:V}=$,W=x.getInstance(),Q=W.getCurrentSpec();if(!Q)return{success:!1,llmContent:"No active spec to exit from.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};try{let{name:Z,phase:Y}=Q,J=W.getTaskProgress();if(w&&b.confirmationHandler){let X=J.total>0&&J.completed<J.total?`
1013
+ `},async execute($,b){let{archive:w,summary:W}=$,V=p.getInstance(),Q=V.getCurrentSpec();if(!Q)return{success:!1,llmContent:"No active spec to exit from.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};try{let{name:Z,phase:J}=Q,Y=V.getTaskProgress();if(w&&b.confirmationHandler){let X=Y.total>0&&Y.completed<Y.total?`
1130
1014
 
1131
- ⚠️ Warning: ${J.total-J.completed} tasks are not completed.`:"";if(!(await b.confirmationHandler.requestConfirmation({title:"Archive Spec",message:`Archive spec "${Z}"?
1015
+ ⚠️ Warning: ${Y.total-Y.completed} tasks are not completed.`:"";if(!(await b.confirmationHandler.requestConfirmation({title:"Archive Spec",message:`Archive spec "${Z}"?
1132
1016
 
1133
- Phase: ${q$[Y]}
1134
- Tasks: ${J.completed}/${J.total} completed`+X,details:"This will move the spec to archive and merge any spec deltas."})).approved)return{success:!0,llmContent:"Archive cancelled. Still in Spec mode.",displayContent:"⚠️ Archive cancelled",metadata:{archived:!1,stillActive:!0}}}if(w){let X=await W.archiveCurrentSpec();if(!X.success)return{success:!1,llmContent:`Failed to archive: ${X.message}`,displayContent:"❌ Archive failed",error:{type:"execution_error",message:X.error||"Archive failed"}};return{success:!0,llmContent:`✅ Spec "${Z}" archived successfully!
1017
+ Phase: ${F$[J]}
1018
+ Tasks: ${Y.completed}/${Y.total} completed`+X,details:"This will move the spec to archive and merge any spec deltas."})).approved)return{success:!0,llmContent:"Archive cancelled. Still in Spec mode.",displayContent:"⚠️ Archive cancelled",metadata:{archived:!1,stillActive:!0}}}if(w){let X=await V.archiveCurrentSpec();if(!X.success)return{success:!1,llmContent:`Failed to archive: ${X.message}`,displayContent:"❌ Archive failed",error:{type:"execution_error",message:X.error||"Archive failed"}};return{success:!0,llmContent:`✅ Spec "${Z}" archived successfully!
1135
1019
 
1136
1020
  `+`\uD83D\uDCCA Final Status:
1137
- `+`- Phase: ${q$[Y]}
1138
- - Tasks: ${J.completed}/${J.total} completed
1139
- `+(V?`- Summary: ${V}
1021
+ `+`- Phase: ${F$[J]}
1022
+ - Tasks: ${Y.completed}/${Y.total} completed
1023
+ `+(W?`- Summary: ${W}
1140
1024
  `:"")+`
1141
1025
  \uD83D\uDCC1 Location: .blade/archive/${Z}/
1142
1026
 
1143
- Exited Spec mode. You can start a new spec or continue with regular work.`,displayContent:`✅ Archived: ${Z}`,metadata:{archived:!0,featureName:Z,phase:Y,taskProgress:J,summary:V,shouldExitSpecMode:!0}}}return W.exitSpecMode(),{success:!0,llmContent:`✅ Exited Spec mode for "${Z}"
1027
+ Exited Spec mode. You can start a new spec or continue with regular work.`,displayContent:`✅ Archived: ${Z}`,metadata:{archived:!0,featureName:Z,phase:J,taskProgress:Y,summary:W,shouldExitSpecMode:!0}}}return V.exitSpecMode(),{success:!0,llmContent:`✅ Exited Spec mode for "${Z}"
1144
1028
 
1145
1029
  `+`\uD83D\uDCCA Current Status:
1146
- `+`- Phase: ${q$[Y]}
1147
- - Tasks: ${J.completed}/${J.total} completed
1030
+ `+`- Phase: ${F$[J]}
1031
+ - Tasks: ${Y.completed}/${Y.total} completed
1148
1032
 
1149
1033
  `+`\uD83D\uDCC1 Spec preserved at: .blade/changes/${Z}/
1150
1034
  `+`\uD83D\uDCA1 Resume later with: /spec load ${Z}
1151
1035
 
1152
- You can now work on other tasks or start a new spec.`,displayContent:`✅ Exited: ${Z} (preserved)`,metadata:{archived:!1,featureName:Z,phase:Y,taskProgress:J,shouldExitSpecMode:!0}}}catch(Z){return{success:!1,llmContent:`Exit failed: ${Z instanceof Error?Z.message:"Unknown error"}`,displayContent:"❌ Exit failed",error:{type:"execution_error",message:Z instanceof Error?Z.message:"Exit error"}}}}});import{z as l1}from"zod";var i4=E({name:"GetSpecContext",displayName:"Get Spec Context",kind:"readonly",schema:l1.object({includeFiles:l1.boolean().optional().default(!0).describe("Whether to include file contents in the context"),includeSteering:l1.boolean().optional().default(!0).describe("Whether to include steering documents")}),description:{short:"Get the current Spec context including metadata, files, and steering docs",long:`Use this tool to retrieve the complete context of the current Spec project.
1036
+ You can now work on other tasks or start a new spec.`,displayContent:`✅ Exited: ${Z} (preserved)`,metadata:{archived:!1,featureName:Z,phase:J,taskProgress:Y,shouldExitSpecMode:!0}}}catch(Z){return{success:!1,llmContent:`Exit failed: ${Z instanceof Error?Z.message:"Unknown error"}`,displayContent:"❌ Exit failed",error:{type:"execution_error",message:Z instanceof Error?Z.message:"Exit error"}}}}});import{z as d1}from"zod";var t4=L({name:"GetSpecContext",displayName:"Get Spec Context",kind:"readonly",schema:d1.object({includeFiles:d1.boolean().optional().default(!0).describe("Whether to include file contents in the context"),includeSteering:d1.boolean().optional().default(!0).describe("Whether to include steering documents")}),description:{short:"Get the current Spec context including metadata, files, and steering docs",long:`Use this tool to retrieve the complete context of the current Spec project.
1153
1037
 
1154
1038
  ## What's Included
1155
1039
 
@@ -1175,8 +1059,8 @@ You can now work on other tasks or start a new spec.`,displayContent:`✅ Exited
1175
1059
 
1176
1060
  [File contents and steering docs follow...]
1177
1061
  \`\`\`
1178
- `},async execute($,b){let{includeFiles:w,includeSteering:V}=$,W=x.getInstance(),Q=W.getCurrentSpec();if(!Q)return{success:!1,llmContent:"No active spec. Use EnterSpecMode or /spec load <name> first.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};try{let Z=W.getFileManager(),Y=[];Y.push(`# \uD83D\uDCCB Spec: ${Q.name}`),Y.push(`**Description**: ${Q.description}`),Y.push(`**Phase**: ${q$[Q.phase]} (${Q.phase})`),Y.push(`**Created**: ${new Date(Q.createdAt).toLocaleString()}`),Y.push(`**Updated**: ${new Date(Q.updatedAt).toLocaleString()}`);let J=W.getTaskProgress();if(J.total>0){if(Y.push(`**Tasks**: ${J.completed}/${J.total} completed (${J.percentage}%)`),Q.currentTaskId){let G=Q.tasks.find((B)=>B.id===Q.currentTaskId);if(G)Y.push(`**Current Task**: ${G.title}`)}let O=Q.tasks.filter((G)=>G.status==="blocked");if(O.length>0)Y.push(`**⚠️ Blocked**: ${O.map((G)=>G.title).join(", ")}`)}if(Y.push(""),V){let O=await W.getSteeringContextString();if(O)Y.push("---"),Y.push("## \uD83D\uDCD6 Steering Documents"),Y.push(""),Y.push(O),Y.push("")}if(w){let O=["proposal","spec","requirements","design","tasks"];for(let G of O){let B=await Z.readSpecFile(Q.name,G);if(B)Y.push("---"),Y.push(`## \uD83D\uDCC4 ${G}.md`),Y.push(""),Y.push(B),Y.push("")}}if(Q.tasks.length>0){Y.push("---"),Y.push("## \uD83D\uDCDD Task List"),Y.push("");for(let O of Q.tasks){let G={pending:"⏳",in_progress:"\uD83D\uDD04",completed:"✅",blocked:"\uD83D\uDEAB",skipped:"⏭️"}[O.status];if(Y.push(`- ${G} **${O.title}** (${O.complexity}) - ${O.status}`),O.description)Y.push(` ${O.description}`)}}return{success:!0,llmContent:Y.join(`
1179
- `),displayContent:`\uD83D\uDCCB Spec context: ${Q.name} (${Q.phase})`,metadata:{featureName:Q.name,phase:Q.phase,taskProgress:J,filesIncluded:w,steeringIncluded:V}}}catch(Z){return{success:!1,llmContent:`Failed to get spec context: ${Z instanceof Error?Z.message:"Unknown error"}`,displayContent:"❌ Failed to get spec context",error:{type:"execution_error",message:Z instanceof Error?Z.message:"Read error"}}}}});import{z as l4}from"zod";function z6($){switch($){case"requirements":return`## Requirements Phase Instructions
1062
+ `},async execute($,b){let{includeFiles:w,includeSteering:W}=$,V=p.getInstance(),Q=V.getCurrentSpec();if(!Q)return{success:!1,llmContent:"No active spec. Use EnterSpecMode or /spec load <name> first.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};try{let Z=V.getFileManager(),J=[];J.push(`# \uD83D\uDCCB Spec: ${Q.name}`),J.push(`**Description**: ${Q.description}`),J.push(`**Phase**: ${F$[Q.phase]} (${Q.phase})`),J.push(`**Created**: ${new Date(Q.createdAt).toLocaleString()}`),J.push(`**Updated**: ${new Date(Q.updatedAt).toLocaleString()}`);let Y=V.getTaskProgress();if(Y.total>0){if(J.push(`**Tasks**: ${Y.completed}/${Y.total} completed (${Y.percentage}%)`),Q.currentTaskId){let G=Q.tasks.find((B)=>B.id===Q.currentTaskId);if(G)J.push(`**Current Task**: ${G.title}`)}let O=Q.tasks.filter((G)=>G.status==="blocked");if(O.length>0)J.push(`**⚠️ Blocked**: ${O.map((G)=>G.title).join(", ")}`)}if(J.push(""),W){let O=await V.getSteeringContextString();if(O)J.push("---"),J.push("## \uD83D\uDCD6 Steering Documents"),J.push(""),J.push(O),J.push("")}if(w){let O=["proposal","spec","requirements","design","tasks"];for(let G of O){let B=await Z.readSpecFile(Q.name,G);if(B)J.push("---"),J.push(`## \uD83D\uDCC4 ${G}.md`),J.push(""),J.push(B),J.push("")}}if(Q.tasks.length>0){J.push("---"),J.push("## \uD83D\uDCDD Task List"),J.push("");for(let O of Q.tasks){let G={pending:"⏳",in_progress:"\uD83D\uDD04",completed:"✅",blocked:"\uD83D\uDEAB",skipped:"⏭️"}[O.status];if(J.push(`- ${G} **${O.title}** (${O.complexity}) - ${O.status}`),O.description)J.push(` ${O.description}`)}}return{success:!0,llmContent:J.join(`
1063
+ `),displayContent:`\uD83D\uDCCB Spec context: ${Q.name} (${Q.phase})`,metadata:{featureName:Q.name,phase:Q.phase,taskProgress:Y,filesIncluded:w,steeringIncluded:W}}}catch(Z){return{success:!1,llmContent:`Failed to get spec context: ${Z instanceof Error?Z.message:"Unknown error"}`,displayContent:"❌ Failed to get spec context",error:{type:"execution_error",message:Z instanceof Error?Z.message:"Read error"}}}}});import{z as e4}from"zod";function w7($){switch($){case"requirements":return`## Requirements Phase Instructions
1180
1064
 
1181
1065
  1. Use UpdateSpec to write requirements.md
1182
1066
  2. Use EARS format:
@@ -1213,7 +1097,7 @@ You can now work on other tasks or start a new spec.`,displayContent:`✅ Exited
1213
1097
  The spec has been marked as complete. Next steps:
1214
1098
  1. The spec will be archived to .blade/archive/
1215
1099
  2. Any spec deltas will be merged to .blade/specs/
1216
- 3. You can start a new spec or exit Spec mode`;default:return""}}var n4=E({name:"TransitionSpecPhase",displayName:"Transition Spec Phase",kind:"write",schema:l4.object({targetPhase:l4.enum(["requirements","design","tasks","implementation","done"]).describe("The phase to transition to")}),description:{short:"Transition the current Spec to a new workflow phase",long:`Use this tool to move the Spec project to the next phase in the workflow.
1100
+ 3. You can start a new spec or exit Spec mode`;default:return""}}var $2=L({name:"TransitionSpecPhase",displayName:"Transition Spec Phase",kind:"write",schema:e4.object({targetPhase:e4.enum(m4).describe("The phase to transition to")}),description:{short:"Transition the current Spec to a new workflow phase",long:`Use this tool to move the Spec project to the next phase in the workflow.
1217
1101
 
1218
1102
  ## Workflow Phases
1219
1103
 
@@ -1242,9 +1126,9 @@ Before transitioning, ensure:
1242
1126
  \`\`\`
1243
1127
  TransitionSpecPhase({ targetPhase: "design" })
1244
1128
  \`\`\`
1245
- `},async execute($,b){let{targetPhase:w}=$,V=x.getInstance(),W=V.getCurrentSpec();if(!W)return{success:!1,llmContent:"No active spec. Use EnterSpecMode or /spec load <name> first.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};let Q=s0[W.phase];if(!Q.includes(w))return{success:!1,llmContent:`Cannot transition from "${W.phase}" to "${w}".
1129
+ `},async execute($,b){let{targetPhase:w}=$,W=p.getInstance(),V=W.getCurrentSpec();if(!V)return{success:!1,llmContent:"No active spec. Use EnterSpecMode or /spec load <name> first.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};let Q=t0[V.phase];if(!Q.includes(w))return{success:!1,llmContent:`Cannot transition from "${V.phase}" to "${w}".
1246
1130
 
1247
- Allowed transitions from ${W.phase}: ${Q.join(", ")||"none"}`,displayContent:"❌ Invalid phase transition",error:{type:"validation_error",message:`Invalid transition: ${W.phase} → ${w}`}};if(W.phase==="tasks"&&w==="implementation"){if(V.getTaskProgress().total===0)return{success:!1,llmContent:`❌ Cannot transition to implementation: No tasks defined!
1131
+ Allowed transitions from ${V.phase}: ${Q.join(", ")||"none"}`,displayContent:"❌ Invalid phase transition",error:{type:"validation_error",message:`Invalid transition: ${V.phase} → ${w}`}};if(V.phase==="tasks"&&w==="implementation"){if(W.getTaskProgress().total===0)return{success:!1,llmContent:`❌ Cannot transition to implementation: No tasks defined!
1248
1132
 
1249
1133
  `+`You MUST use the **AddTask** tool to add tasks before starting implementation.
1250
1134
 
@@ -1258,16 +1142,16 @@ AddTask({
1258
1142
  })
1259
1143
  \`\`\`
1260
1144
 
1261
- After adding tasks, try transitioning again.`,displayContent:"❌ No tasks defined - 我需要先添加任务",error:{type:"validation_error",message:"No tasks defined. Use AddTask tool to add tasks first."}}}if(w==="done"){let Z=V.getTaskProgress();if(Z.total>0&&Z.completed<Z.total){if(b.confirmationHandler){if(!(await b.confirmationHandler.requestConfirmation({title:"Incomplete Tasks",message:`⚠️ ${Z.total-Z.completed} tasks are not completed.
1145
+ After adding tasks, try transitioning again.`,displayContent:"❌ No tasks defined - 我需要先添加任务",error:{type:"validation_error",message:"No tasks defined. Use AddTask tool to add tasks first."}}}if(w==="done"){let Z=W.getTaskProgress();if(Z.total>0&&Z.completed<Z.total){if(b.confirmationHandler){if(!(await b.confirmationHandler.requestConfirmation({title:"Incomplete Tasks",message:`⚠️ ${Z.total-Z.completed} tasks are not completed.
1262
1146
 
1263
- Are you sure you want to mark this spec as done?`,details:`Completed: ${Z.completed}/${Z.total}`})).approved)return{success:!1,llmContent:"User cancelled transition to done phase.",displayContent:"⚠️ Transition cancelled",error:{type:"validation_error",message:"User cancelled"}}}}}try{let Z=await V.transitionPhase(w);if(!Z.success)return{success:!1,llmContent:Z.message,displayContent:`❌ ${Z.message}`,error:{type:"execution_error",message:Z.error||"Transition failed"}};let Y=q$[W.phase],J=q$[w];return{success:!0,llmContent:`✅ Transitioned from "${Y}" to "${J}"
1147
+ Are you sure you want to mark this spec as done?`,details:`Completed: ${Z.completed}/${Z.total}`})).approved)return{success:!1,llmContent:"User cancelled transition to done phase.",displayContent:"⚠️ Transition cancelled",error:{type:"validation_error",message:"User cancelled"}}}}}try{let Z=await W.transitionPhase(w);if(!Z.success)return{success:!1,llmContent:Z.message,displayContent:`❌ ${Z.message}`,error:{type:"execution_error",message:Z.error||"Transition failed"}};let J=F$[V.phase],Y=F$[w];return{success:!0,llmContent:`✅ Transitioned from "${J}" to "${Y}"
1264
1148
 
1265
- `+z6(w),displayContent:`✅ Phase: ${Y} → ${J}`,metadata:{fromPhase:W.phase,toPhase:w,featureName:W.name}}}catch(Z){return{success:!1,llmContent:`Transition failed: ${Z instanceof Error?Z.message:"Unknown error"}`,displayContent:"❌ Transition failed",error:{type:"execution_error",message:Z instanceof Error?Z.message:"Transition error"}}}}});import{z as Sb}from"zod";function v6($,b){let w=["init","requirements","design","tasks","implementation"],W={proposal:"init",requirements:"requirements",design:"design",tasks:"tasks"}[$];if(!W)return"";let Q=w.indexOf(b);if(w.indexOf(W)>Q)return`
1266
- \uD83D\uDCA1 Consider transitioning to "${W}" phase using TransitionSpecPhase tool.`;switch($){case"proposal":return`
1149
+ `+w7(w),displayContent:`✅ Phase: ${J} → ${Y}`,metadata:{fromPhase:V.phase,toPhase:w,featureName:V.name}}}catch(Z){return{success:!1,llmContent:`Transition failed: ${Z instanceof Error?Z.message:"Unknown error"}`,displayContent:"❌ Transition failed",error:{type:"execution_error",message:Z instanceof Error?Z.message:"Transition error"}}}}});import{z as vb}from"zod";function W7($,b){let w=["init","requirements","design","tasks","implementation"],V={proposal:"init",requirements:"requirements",design:"design",tasks:"tasks"}[$];if(!V)return"";let Q=w.indexOf(b);if(w.indexOf(V)>Q)return`
1150
+ \uD83D\uDCA1 Consider transitioning to "${V}" phase using TransitionSpecPhase tool.`;switch($){case"proposal":return`
1267
1151
  \uD83D\uDCDD Next: Define requirements in requirements.md using EARS format.`;case"requirements":return`
1268
1152
  \uD83D\uDCDD Next: Create technical design in design.md (diagrams, API contracts).`;case"design":return`
1269
1153
  \uD83D\uDCDD Next: Break down into tasks in tasks.md (atomic, with dependencies).`;case"tasks":return`
1270
- \uD83D\uDCDD Next: Start implementation. Update task status as you progress.`;default:return""}}var s4=E({name:"UpdateSpec",displayName:"Update Spec",kind:"write",schema:Sb.object({fileType:Sb.enum(["proposal","spec","requirements","design","tasks"]).describe("The type of spec file to update"),content:Sb.string().min(1).describe("The content to write to the file"),append:Sb.boolean().optional().default(!1).describe("If true, append to existing content instead of replacing")}),description:{short:"Update a spec file in the current Spec project",long:`Use this tool to update spec files in the current Spec-Driven Development project.
1154
+ \uD83D\uDCDD Next: Start implementation. Update task status as you progress.`;default:return""}}var b2=L({name:"UpdateSpec",displayName:"Update Spec",kind:"write",schema:vb.object({fileType:vb.enum(["proposal","spec","requirements","design","tasks"]).describe("The type of spec file to update"),content:vb.string().min(1).describe("The content to write to the file"),append:vb.boolean().optional().default(!1).describe("If true, append to existing content instead of replacing")}),description:{short:"Update a spec file in the current Spec project",long:`Use this tool to update spec files in the current Spec-Driven Development project.
1271
1155
 
1272
1156
  ## Available File Types
1273
1157
 
@@ -1300,14 +1184,14 @@ UpdateSpec({
1300
1184
  - You must be in Spec mode (have an active spec) to use this tool
1301
1185
  - Content overwrites existing file by default
1302
1186
  - Use append: true to add to existing content
1303
- `},async execute($,b){let{fileType:w,content:V,append:W}=$,Q=x.getInstance(),Z=Q.getCurrentSpec();if(!Z)return{success:!1,llmContent:"No active spec. Use EnterSpecMode to start a new spec project, or use the /spec command to load an existing one.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};try{let Y=Q.getFileManager(),J=V;if(W){let G=await Y.readSpecFile(Z.name,w);J=G?`${G}
1187
+ `},async execute($,b){let{fileType:w,content:W,append:V}=$,Q=p.getInstance(),Z=Q.getCurrentSpec();if(!Z)return{success:!1,llmContent:"No active spec. Use EnterSpecMode to start a new spec project, or use the /spec command to load an existing one.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};try{let J=Q.getFileManager(),Y=W;if(V){let G=await J.readSpecFile(Z.name,w);Y=G?`${G}
1304
1188
 
1305
- ${V}`:V}await Y.writeSpecFile(Z.name,w,J);let X=J.split(`
1306
- `).length,O=J.length;return{success:!0,llmContent:`✅ Updated ${w}.md for "${Z.name}"
1189
+ ${W}`:W}await J.writeSpecFile(Z.name,w,Y);let X=Y.split(`
1190
+ `).length,O=Y.length;return{success:!0,llmContent:`✅ Updated ${w}.md for "${Z.name}"
1307
1191
 
1308
1192
  `+`\uD83D\uDCCA Stats: ${X} lines, ${O} characters
1309
1193
 
1310
- `+v6(w,Z.phase),displayContent:`✅ Updated ${w}.md (${X} lines)`,metadata:{featureName:Z.name,fileType:w,lines:X,chars:O,append:W}}}catch(Y){return{success:!1,llmContent:`Failed to update ${w}.md: ${Y instanceof Error?Y.message:"Unknown error"}`,displayContent:`❌ Failed to update ${w}.md`,error:{type:"execution_error",message:Y instanceof Error?Y.message:"Write error"}}}}});import{z as Mb}from"zod";var r4={pending:"⏳ 待处理",in_progress:"\uD83D\uDD04 进行中",completed:"✅ 已完成",blocked:"\uD83D\uDEAB 已阻塞",skipped:"⏭️ 已跳过"},a4=E({name:"UpdateTaskStatus",displayName:"Update Task Status",kind:"write",schema:Mb.object({taskId:Mb.string().min(1).describe("The ID of the task to update"),status:Mb.enum(["pending","in_progress","completed","blocked","skipped"]).describe("The new status for the task"),notes:Mb.string().optional().describe("Optional notes about the status change (e.g., why blocked)")}),description:{short:"Update the status of a task in the current Spec",long:`Use this tool to update the status of tasks in the current Spec project.
1194
+ `+W7(w,Z.phase),displayContent:`✅ Updated ${w}.md (${X} lines)`,metadata:{featureName:Z.name,fileType:w,lines:X,chars:O,append:V}}}catch(J){return{success:!1,llmContent:`Failed to update ${w}.md: ${J instanceof Error?J.message:"Unknown error"}`,displayContent:`❌ Failed to update ${w}.md`,error:{type:"execution_error",message:J instanceof Error?J.message:"Write error"}}}}});import{z as Tb}from"zod";var w2={pending:"⏳ 待处理",in_progress:"\uD83D\uDD04 进行中",completed:"✅ 已完成",blocked:"\uD83D\uDEAB 已阻塞",skipped:"⏭️ 已跳过"},W2=L({name:"UpdateTaskStatus",displayName:"Update Task Status",kind:"write",schema:Tb.object({taskId:Tb.string().min(1).describe("The ID of the task to update"),status:Tb.enum(c4).describe("The new status for the task"),notes:Tb.string().optional().describe("Optional notes about the status change (e.g., why blocked)")}),description:{short:"Update the status of a task in the current Spec",long:`Use this tool to update the status of tasks in the current Spec project.
1311
1195
 
1312
1196
  ## Task Statuses
1313
1197
 
@@ -1338,21 +1222,21 @@ UpdateTaskStatus({
1338
1222
  - Use GetSpecContext to see all tasks and their current statuses
1339
1223
  - Only one task should be "in_progress" at a time
1340
1224
  - Completing a task may unblock dependent tasks
1341
- `},async execute($,b){let{taskId:w,status:V,notes:W}=$,Q=x.getInstance(),Z=Q.getCurrentSpec();if(!Z)return{success:!1,llmContent:"No active spec. Use EnterSpecMode to start a new spec project, or use the /spec command to load an existing one.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};let Y=Z.tasks.find((B)=>B.id===w);if(!Y)return{success:!1,llmContent:`Task "${w}" not found.
1225
+ `},async execute($,b){let{taskId:w,status:W,notes:V}=$,Q=p.getInstance(),Z=Q.getCurrentSpec();if(!Z)return{success:!1,llmContent:"No active spec. Use EnterSpecMode to start a new spec project, or use the /spec command to load an existing one.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};let J=Z.tasks.find((B)=>B.id===w);if(!J)return{success:!1,llmContent:`Task "${w}" not found.
1342
1226
 
1343
1227
  Available tasks:
1344
1228
  ${Z.tasks.map((B)=>`- ${B.id}: ${B.title}`).join(`
1345
- `)||"No tasks"}`,displayContent:`❌ Task not found: ${w}`,error:{type:"validation_error",message:"Task not found"}};let J=await Q.updateTaskStatus(w,V);if(!J.success)return{success:!1,llmContent:`Failed to update task status: ${J.message}`,displayContent:`❌ Failed to update: ${J.message}`,error:{type:"execution_error",message:J.message}};let X=Q.getTaskProgress(),O=Q.getNextTask(),G="";if(V==="completed"&&O)G=`
1229
+ `)||"No tasks"}`,displayContent:`❌ Task not found: ${w}`,error:{type:"validation_error",message:"Task not found"}};let Y=await Q.updateTaskStatus(w,W);if(!Y.success)return{success:!1,llmContent:`Failed to update task status: ${Y.message}`,displayContent:`❌ Failed to update: ${Y.message}`,error:{type:"execution_error",message:Y.message}};let X=Q.getTaskProgress(),O=Q.getNextTask(),G="";if(W==="completed"&&O)G=`
1346
1230
 
1347
- \uD83C\uDFAF Next task: "${O.title}" (${O.id})`;else if(V==="completed"&&X.completed===X.total)G=`
1231
+ \uD83C\uDFAF Next task: "${O.title}" (${O.id})`;else if(W==="completed"&&X.completed===X.total)G=`
1348
1232
 
1349
- \uD83C\uDF89 All tasks completed! Use /spec archive to archive this spec.`;return{success:!0,llmContent:`✅ Updated task "${Y.title}"
1233
+ \uD83C\uDF89 All tasks completed! Use /spec archive to archive this spec.`;return{success:!0,llmContent:`✅ Updated task "${J.title}"
1350
1234
 
1351
1235
  `+`\uD83D\uDCCB Task ID: ${w}
1352
- `+`\uD83D\uDCCA Status: ${r4[V]}
1353
- `+(W?`\uD83D\uDCDD Notes: ${W}
1236
+ `+`\uD83D\uDCCA Status: ${w2[W]}
1237
+ `+(V?`\uD83D\uDCDD Notes: ${V}
1354
1238
  `:"")+`
1355
- \uD83D\uDCC8 Progress: ${X.completed}/${X.total} tasks (${X.percentage}%)`+G,displayContent:`✅ ${Y.title}: ${r4[V]}`,metadata:{taskId:w,title:Y.title,status:V,notes:W,progress:{completed:X.completed,total:X.total,percentage:X.percentage}}}}});import{z as T6}from"zod";var o4=E({name:"ValidateSpec",displayName:"Validate Spec",kind:"readonly",schema:T6.object({}),description:{short:"Validate the completeness and consistency of the current Spec",long:`Use this tool to check if the current Spec project is complete and ready for the next phase.
1239
+ \uD83D\uDCC8 Progress: ${X.completed}/${X.total} tasks (${X.percentage}%)`+G,displayContent:`✅ ${J.title}: ${w2[W]}`,metadata:{taskId:w,title:J.title,status:W,notes:V,progress:{completed:X.completed,total:X.total,percentage:X.percentage}}}}});import{z as V7}from"zod";var V2=L({name:"ValidateSpec",displayName:"Validate Spec",kind:"readonly",schema:V7.object({}),description:{short:"Validate the completeness and consistency of the current Spec",long:`Use this tool to check if the current Spec project is complete and ready for the next phase.
1356
1240
 
1357
1241
  ## What's Validated
1358
1242
 
@@ -1373,8 +1257,8 @@ ${Z.tasks.map((B)=>`- ${B.id}: ${B.title}`).join(`
1373
1257
  - To review what's missing
1374
1258
  - Before marking spec as done
1375
1259
  - To get improvement suggestions
1376
- `},async execute($,b){let w=x.getInstance(),V=w.getCurrentSpec();if(!V)return{success:!1,llmContent:"No active spec. Use EnterSpecMode or /spec load <name> first.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};try{let W=await w.validateCurrentSpec(),Q=[];Q.push(`# \uD83D\uDD0D Spec Validation: ${V.name}`),Q.push(""),Q.push(`**Phase**: ${q$[W.phase]}`),Q.push(`**Status**: ${W.valid?"✅ Valid":"⚠️ Has Issues"}`),Q.push(""),Q.push("## \uD83D\uDCC4 File Completeness"),Q.push("");let Z=[["proposal.md",W.completeness.proposal],["spec.md",W.completeness.spec],["requirements.md",W.completeness.requirements],["design.md",W.completeness.design],["tasks.md",W.completeness.tasks]];for(let[X,O]of Z)Q.push(`- ${O?"✅":"❌"} ${X}`);if(Q.push(""),W.issues.length>0){Q.push("## ⚠️ Issues"),Q.push("");for(let X of W.issues){let O={error:"\uD83D\uDD34",warning:"\uD83D\uDFE1",info:"\uD83D\uDD35"}[X.severity];Q.push(`- ${O} **${X.file}**: ${X.message}`)}Q.push("")}if(W.suggestions.length>0){Q.push("## \uD83D\uDCA1 Suggestions"),Q.push("");for(let X of W.suggestions)Q.push(`- ${X}`);Q.push("")}let Y=w.getTaskProgress();if(Y.total>0){Q.push("## \uD83D\uDCCA Task Progress"),Q.push(""),Q.push(`- Total: ${Y.total}`),Q.push(`- Completed: ${Y.completed}`),Q.push(`- Remaining: ${Y.total-Y.completed}`),Q.push(`- Progress: ${Y.percentage}%`),Q.push("");let X=Math.round(Y.percentage/5),O=20-X;Q.push(`[${"█".repeat(X)}${"░".repeat(O)}]`)}if(Q.push(""),Q.push("## \uD83D\uDE80 Next Steps"),Q.push(""),!W.valid)Q.push("1. Address the issues listed above"),Q.push("2. Re-run ValidateSpec to verify fixes");else{let X=w.getAllowedTransitions();if(X.length>0)Q.push(`1. Ready to transition to: ${X.map((O)=>q$[O]).join(", ")}`),Q.push("2. Use TransitionSpecPhase to proceed");else Q.push("1. All phases complete!"),Q.push("2. Use ExitSpecMode to finish and archive")}return{success:!0,llmContent:Q.join(`
1377
- `),displayContent:W.valid?`✅ Spec valid: ${V.name}`:`⚠️ Spec has ${W.issues.length} issue(s)`,metadata:{valid:W.valid,phase:W.phase,completeness:W.completeness,issueCount:W.issues.length,taskProgress:Y}}}catch(W){return{success:!1,llmContent:`Validation failed: ${W instanceof Error?W.message:"Unknown error"}`,displayContent:"❌ Validation failed",error:{type:"execution_error",message:W instanceof Error?W.message:"Validation error"}}}}});var t4=[m4,s4,i4,n4,g4,a4,o4,c4];import{z as z$}from"zod";var k6=z$.object({label:z$.string().describe("The display text for this option that the user will see and select. Should be concise (1-5 words) and clearly describe the choice."),description:z$.string().describe("Explanation of what this option means or what will happen if chosen. Useful for providing context about trade-offs or implications.")}),f6=z$.object({question:z$.string().describe('The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: "Which library should we use for date formatting?" If multiSelect is true, phrase it accordingly, e.g. "Which features do you want to enable?"'),header:z$.string().max(12).describe('Very short label displayed as a chip/tag (max 12 chars). Examples: "Auth method", "Library", "Approach".'),multiSelect:z$.boolean().describe("Set to true to allow the user to select multiple options instead of just one. Use when choices are not mutually exclusive."),options:z$.array(k6).min(2).max(4).describe('The available choices for this question. Must have 2-4 options. Each option should be a distinct, mutually exclusive choice (unless multiSelect is enabled). There should be no "Other" option, that will be provided automatically.')}),I6=z$.object({questions:z$.array(f6).min(1).max(4).describe("Questions to ask the user (1-4 questions)")}),yb=E({name:"AskUserQuestion",displayName:"Ask User Question",kind:"readonly",schema:I6,description:{short:"Ask user questions to gather preferences or clarify requirements",long:`Use this tool when you need to ask the user questions during execution. This allows you to:
1260
+ `},async execute($,b){let w=p.getInstance(),W=w.getCurrentSpec();if(!W)return{success:!1,llmContent:"No active spec. Use EnterSpecMode or /spec load <name> first.",displayContent:"❌ No active spec",error:{type:"validation_error",message:"No active spec project"}};try{let V=await w.validateCurrentSpec(),Q=[];Q.push(`# \uD83D\uDD0D Spec Validation: ${W.name}`),Q.push(""),Q.push(`**Phase**: ${F$[V.phase]}`),Q.push(`**Status**: ${V.valid?"✅ Valid":"⚠️ Has Issues"}`),Q.push(""),Q.push("## \uD83D\uDCC4 File Completeness"),Q.push("");let Z=[["proposal.md",V.completeness.proposal],["spec.md",V.completeness.spec],["requirements.md",V.completeness.requirements],["design.md",V.completeness.design],["tasks.md",V.completeness.tasks]];for(let[X,O]of Z)Q.push(`- ${O?"✅":"❌"} ${X}`);if(Q.push(""),V.issues.length>0){Q.push("## ⚠️ Issues"),Q.push("");for(let X of V.issues){let O={error:"\uD83D\uDD34",warning:"\uD83D\uDFE1",info:"\uD83D\uDD35"}[X.severity];Q.push(`- ${O} **${X.file}**: ${X.message}`)}Q.push("")}if(V.suggestions.length>0){Q.push("## \uD83D\uDCA1 Suggestions"),Q.push("");for(let X of V.suggestions)Q.push(`- ${X}`);Q.push("")}let J=w.getTaskProgress();if(J.total>0){Q.push("## \uD83D\uDCCA Task Progress"),Q.push(""),Q.push(`- Total: ${J.total}`),Q.push(`- Completed: ${J.completed}`),Q.push(`- Remaining: ${J.total-J.completed}`),Q.push(`- Progress: ${J.percentage}%`),Q.push("");let X=Math.round(J.percentage/5),O=20-X;Q.push(`[${"█".repeat(X)}${"░".repeat(O)}]`)}if(Q.push(""),Q.push("## \uD83D\uDE80 Next Steps"),Q.push(""),!V.valid)Q.push("1. Address the issues listed above"),Q.push("2. Re-run ValidateSpec to verify fixes");else{let X=w.getAllowedTransitions();if(X.length>0)Q.push(`1. Ready to transition to: ${X.map((O)=>F$[O]).join(", ")}`),Q.push("2. Use TransitionSpecPhase to proceed");else Q.push("1. All phases complete!"),Q.push("2. Use ExitSpecMode to finish and archive")}return{success:!0,llmContent:Q.join(`
1261
+ `),displayContent:V.valid?`✅ Spec valid: ${W.name}`:`⚠️ Spec has ${V.issues.length} issue(s)`,metadata:{valid:V.valid,phase:V.phase,completeness:V.completeness,issueCount:V.issues.length,taskProgress:J}}}catch(V){return{success:!1,llmContent:`Validation failed: ${V instanceof Error?V.message:"Unknown error"}`,displayContent:"❌ Validation failed",error:{type:"execution_error",message:V instanceof Error?V.message:"Validation error"}}}}});var Q2=[a4,b2,t4,$2,r4,W2,V2,o4];import{z as k$}from"zod";var Q7=k$.object({label:k$.string().describe("The display text for this option that the user will see and select. Should be concise (1-5 words) and clearly describe the choice."),description:k$.string().describe("Explanation of what this option means or what will happen if chosen. Useful for providing context about trade-offs or implications.")}),Z7=k$.object({question:k$.string().describe('The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: "Which library should we use for date formatting?" If multiSelect is true, phrase it accordingly, e.g. "Which features do you want to enable?"'),header:k$.string().max(12).describe('Very short label displayed as a chip/tag (max 12 chars). Examples: "Auth method", "Library", "Approach".'),multiSelect:k$.boolean().describe("Set to true to allow the user to select multiple options instead of just one. Use when choices are not mutually exclusive."),options:k$.array(Q7).min(2).max(4).describe('The available choices for this question. Must have 2-4 options. Each option should be a distinct, mutually exclusive choice (unless multiSelect is enabled). There should be no "Other" option, that will be provided automatically.')}),J7=k$.object({questions:k$.array(Z7).min(1).max(4).describe("Questions to ask the user (1-4 questions)")}),kb=L({name:"AskUserQuestion",displayName:"Ask User Question",kind:"readonly",schema:J7,description:{short:"Ask user questions to gather preferences or clarify requirements",long:`Use this tool when you need to ask the user questions during execution. This allows you to:
1378
1262
  1. Gather user preferences or requirements
1379
1263
  2. Clarify ambiguous instructions
1380
1264
  3. Get decisions on implementation choices as you work
@@ -1384,8 +1268,8 @@ Usage notes:
1384
1268
  - Users will always be able to select "Other" to provide custom text input
1385
1269
  - Use multiSelect: true to allow multiple answers to be selected for a question
1386
1270
  - If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label`},async execute($,b){if(b.confirmationHandler)try{let w=await b.confirmationHandler.requestConfirmation({type:"askUserQuestion",kind:"readonly",message:"Please answer the following questions:",questions:$.questions});if(!w.approved)return{success:!0,llmContent:"User cancelled the question prompt without providing answers.",displayContent:"❌ 用户取消了问题",metadata:{cancelled:!0}};if(w.answers&&Object.keys(w.answers).length>0)return{success:!0,llmContent:`User answers:
1387
- ${Object.entries(w.answers).map(([W,Q])=>{let Z=Array.isArray(Q)?Q.join(", "):Q;return`${W}: ${Z}`}).join(`
1388
- `)}`,displayContent:"✅ 用户已回答问题",metadata:{answers:w.answers}};return{success:!0,llmContent:"The question was approved but no answers were collected. This typically happens in IDE/ACP sessions where structured question UI is not available. Please ask the user directly in your response or make reasonable assumptions based on context.",displayContent:"⚠️ ACP 模式:无法收集答案",metadata:{acpMode:!0,noAnswersCollected:!0}}}catch(w){return{success:!1,llmContent:`Failed to ask user questions: ${w instanceof Error?w.message:"Unknown error"}`,displayContent:"❌ 问题显示失败",error:{type:"execution_error",message:"Failed to display questions"}}}return{success:!1,llmContent:"No confirmation handler available. Cannot ask user questions in non-interactive mode.",displayContent:"❌ 非交互模式,无法提问",error:{type:"execution_error",message:"No confirmation handler available"}}}});import{z as n1}from"zod";var s1=E({name:"Skill",displayName:"Skill",kind:"execute",schema:n1.object({skill:n1.string().describe('The skill name. E.g., "commit-message" or "code-review"'),args:n1.string().optional().describe("Optional arguments for the skill")}),description:{short:"Execute a skill within the main conversation",long:`Execute a skill within the main conversation
1271
+ ${Object.entries(w.answers).map(([V,Q])=>{let Z=Array.isArray(Q)?Q.join(", "):Q;return`${V}: ${Z}`}).join(`
1272
+ `)}`,displayContent:"✅ 用户已回答问题",metadata:{answers:w.answers}};return{success:!0,llmContent:"The question was approved but no answers were collected. This typically happens in IDE/ACP sessions where structured question UI is not available. Please ask the user directly in your response or make reasonable assumptions based on context.",displayContent:"⚠️ ACP 模式:无法收集答案",metadata:{acpMode:!0,noAnswersCollected:!0}}}catch(w){return{success:!1,llmContent:`Failed to ask user questions: ${w instanceof Error?w.message:"Unknown error"}`,displayContent:"❌ 问题显示失败",error:{type:"execution_error",message:"Failed to display questions"}}}return{success:!1,llmContent:"No confirmation handler available. Cannot ask user questions in non-interactive mode.",displayContent:"❌ 非交互模式,无法提问",error:{type:"execution_error",message:"No confirmation handler available"}}}});import{z as u1}from"zod";var g1=L({name:"Skill",displayName:"Skill",kind:"execute",schema:u1.object({skill:u1.string().describe('The skill name. E.g., "commit-message" or "code-review"'),args:u1.string().optional().describe("Optional arguments for the skill")}),description:{short:"Execute a skill within the main conversation",long:`Execute a skill within the main conversation
1389
1273
 
1390
1274
  <skills_instructions>
1391
1275
  When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
@@ -1404,7 +1288,7 @@ Important:
1404
1288
  <available_skills>
1405
1289
 
1406
1290
  </available_skills>
1407
- `},async execute($,b){let{skill:w}=$,V=_$();if(!V.has(w))return{success:!1,llmContent:`Skill "${w}" not found. Available skills: ${V.getAll().map((Y)=>Y.name).join(", ")||"none"}`,displayContent:`❌ Skill "${w}" not found`,error:{type:"validation_error",message:`Skill "${w}" is not registered`}};let W=await V.loadContent(w);if(!W)return{success:!1,llmContent:`Failed to load skill "${w}" content`,displayContent:`❌ Failed to load skill "${w}"`,error:{type:"execution_error",message:`Could not read SKILL.md for "${w}"`}};let Q=P6(W.metadata.name,W.instructions,W.metadata.basePath),Z=typeof W.metadata.model==="string"&&W.metadata.model!=="inherit"&&W.metadata.model.trim()!==""?W.metadata.model:void 0;return{success:!0,llmContent:Q,displayContent:`<command-message>The "${w}" skill is loading</command-message>`,metadata:{skillName:w,basePath:W.metadata.basePath,version:W.metadata.version,allowedTools:W.metadata.allowedTools,modelId:Z}}}});function P6($,b,w){return`# Skill: ${$}
1291
+ `},async execute($,b){let{skill:w}=$,W=_$();if(!W.has(w))return{success:!1,llmContent:`Skill "${w}" not found. Available skills: ${W.getAll().map((J)=>J.name).join(", ")||"none"}`,displayContent:`❌ Skill "${w}" not found`,error:{type:"validation_error",message:`Skill "${w}" is not registered`}};let V=await W.loadContent(w);if(!V)return{success:!1,llmContent:`Failed to load skill "${w}" content`,displayContent:`❌ Failed to load skill "${w}"`,error:{type:"execution_error",message:`Could not read SKILL.md for "${w}"`}};let Q=Y7(V.metadata.name,V.instructions,V.metadata.basePath),Z=typeof V.metadata.model==="string"&&V.metadata.model!=="inherit"&&V.metadata.model.trim()!==""?V.metadata.model:void 0;return{success:!0,llmContent:Q,displayContent:`<command-message>The "${w}" skill is loading</command-message>`,metadata:{skillName:w,basePath:V.metadata.basePath,version:V.metadata.version,allowedTools:V.metadata.allowedTools,modelId:Z}}}});function Y7($,b,w){return`# Skill: ${$}
1408
1292
 
1409
1293
  You are now operating in the "${$}" skill mode. Follow the instructions below to complete the task.
1410
1294
 
@@ -1417,7 +1301,7 @@ ${b}
1417
1301
 
1418
1302
  ---
1419
1303
 
1420
- Remember: Follow the above instructions carefully to complete the user's request.`}import{nanoid as u6}from"nanoid";import{z as W0}from"zod";import{nanoid as x6}from"nanoid";import i$ from"node:fs";import h6 from"node:os";import e4 from"node:path";var R0=N("Agent");class w0{static instance=null;sessionsDir;cache=new Map;constructor(){this.sessionsDir=e4.join(h6.homedir(),".blade","agents","sessions"),this.ensureDirectory()}static getInstance(){if(!w0.instance)w0.instance=new w0;return w0.instance}ensureDirectory(){if(!i$.existsSync(this.sessionsDir))i$.mkdirSync(this.sessionsDir,{recursive:!0,mode:493})}getSessionPath($){let b=$.replace(/[^a-zA-Z0-9_-]/g,"_");return e4.join(this.sessionsDir,`${b}.json`)}saveSession($){try{let b=this.getSessionPath($.id),w=JSON.stringify($,null,2);i$.writeFileSync(b,w,"utf-8"),this.cache.set($.id,$),R0.debug(`Session saved: ${$.id}`)}catch(b){R0.warn(`Failed to save session ${$.id}:`,b)}}loadSession($){if(this.cache.has($))return this.cache.get($);try{let b=this.getSessionPath($);if(!i$.existsSync(b))return;let w=i$.readFileSync(b,"utf-8"),V=JSON.parse(w);return this.cache.set($,V),V}catch(b){R0.warn(`Failed to load session ${$}:`,b);return}}updateSession($,b){let w=this.loadSession($);if(!w)return;let V={...w,...b,lastActiveAt:Date.now()};return this.saveSession(V),V}appendMessages($,b){let w=this.loadSession($);if(!w)return;return this.updateSession($,{messages:[...w.messages,...b]})}markCompleted($,b,w){return this.updateSession($,{status:b.success?"completed":"failed",result:b,stats:w,completedAt:Date.now()})}deleteSession($){try{let b=this.getSessionPath($);if(i$.existsSync(b))i$.unlinkSync(b);return this.cache.delete($),!0}catch(b){return R0.warn(`Failed to delete session ${$}:`,b),!1}}listSessions(){try{let $=i$.readdirSync(this.sessionsDir),b=[];for(let w of $){if(!w.endsWith(".json"))continue;let V=w.replace(".json",""),W=this.loadSession(V);if(W)b.push(W)}return b.sort((w,V)=>V.lastActiveAt-w.lastActiveAt)}catch($){return R0.warn("Failed to list sessions:",$),[]}}listRunningSessions(){return this.listSessions().filter(($)=>$.status==="running")}cleanupExpiredSessions($=604800000){let b=Date.now(),w=this.listSessions(),V=0;for(let W of w){if(W.status==="running")continue;if(b-W.lastActiveAt>$){if(this.deleteSession(W.id))V++}}if(V>0)R0.info(`Cleaned up ${V} expired agent sessions`);return V}clearCache(){this.cache.clear()}}var V0=N("Agent");class E${static instance=null;runningAgents=new Map;sessionStore=w0.getInstance();constructor(){this.cleanupOrphanedSessions()}static getInstance(){if(!E$.instance)E$.instance=new E$;return E$.instance}cleanupOrphanedSessions(){let $=this.sessionStore.listSessions(),b=Date.now(),w=1800000;for(let V of $)if(V.status==="running"){let W=this.runningAgents.has(V.id),Q=b-V.lastActiveAt;if(!W||Q>1800000)V0.warn(`Cleaning up orphaned agent session: ${V.id}`),this.sessionStore.updateSession(V.id,{status:"failed",result:{success:!1,message:"",error:"Session was orphaned (process restart or timeout)"},completedAt:b})}}startBackgroundAgent($){let{config:b,bladeConfig:w,description:V,prompt:W,parentSessionId:Q,permissionMode:Z,agentId:Y,existingMessages:J}=$,X=Y||x6(),O=new AbortController,G={id:X,subagentType:b.name,description:V,prompt:W,messages:J||[],status:"running",createdAt:Date.now(),lastActiveAt:Date.now(),parentSessionId:Q};this.sessionStore.saveSession(G);let B=Date.now(),q=this.executeAgent(X,b,w,W,Q,Z,O.signal,J);return this.runningAgents.set(X,{id:X,promise:q,abortController:O,startTime:B}),q.finally(()=>{this.runningAgents.delete(X)}),V0.info(`Background agent started: ${X} (${b.name})`),X}async executeAgent($,b,w,V,W,Q,Z,Y){let J=Date.now();try{if(Z.aborted)throw Error("Agent execution was cancelled");let X=b.systemPrompt||"",O=b.model&&b.model!=="inherit"?b.model:void 0,G=await P$.create(w,{systemPrompt:X,toolWhitelist:b.tools,modelId:O}),B={messages:Y||[],userId:"subagent",sessionId:$,workspaceRoot:process.cwd(),permissionMode:Q,subagentInfo:{parentSessionId:W||"",subagentType:b.name,isSidechain:!1}},q=await G.runAgenticLoop(V,B,{signal:Z});this.sessionStore.updateSession($,{messages:B.messages});let U=Date.now()-J,K=q.success?{success:!0,message:q.finalMessage||"",agentId:$,stats:{tokens:q.metadata?.tokensUsed||0,toolCalls:q.metadata?.toolCallsCount||0,duration:U}}:{success:!1,message:"",agentId:$,error:q.error?.message||"Unknown error",stats:{duration:U}};return this.sessionStore.markCompleted($,{success:K.success,message:K.message,error:K.error},K.stats),V0.info(`Background agent completed: ${$} (success=${K.success})`),K}catch(X){let O=Date.now()-J,G=X instanceof Error?X.message:String(X);return this.sessionStore.markCompleted($,{success:!1,message:"",error:G},{duration:O}),V0.warn(`Background agent failed: ${$}`,X),{success:!1,message:"",agentId:$,error:G,stats:{duration:O}}}}getAgent($){return this.sessionStore.loadSession($)}isRunning($){return this.runningAgents.has($)}async waitForCompletion($,b=30000){let w=this.runningAgents.get($);if(!w)return this.sessionStore.loadSession($);if(b>0){let V=new Promise((Q)=>setTimeout(()=>Q("timeout"),b));if(await Promise.race([w.promise,V])==="timeout")return this.sessionStore.loadSession($)}else await w.promise;return this.sessionStore.loadSession($)}resumeAgent($,b,w,V,W,Q){let Z=this.sessionStore.loadSession($);if(!Z){V0.warn(`Cannot resume agent ${$}: session not found`);return}if(this.isRunning($)){V0.warn(`Cannot resume agent ${$}: still running`);return}return this.startBackgroundAgent({config:w,bladeConfig:V,description:Z.description,prompt:b,parentSessionId:W||Z.parentSessionId,permissionMode:Q,agentId:$,existingMessages:Z.messages})}killAgent($){let b=this.runningAgents.get($);if(!b){let w=this.sessionStore.loadSession($);if(w&&w.status==="running")this.sessionStore.updateSession($,{status:"cancelled"});return!1}return b.abortController.abort(),this.sessionStore.updateSession($,{status:"cancelled"}),V0.info(`Background agent cancelled: ${$}`),!0}listAll(){return this.sessionStore.listSessions()}listRunning(){return this.sessionStore.listRunningSessions()}getRunningCount(){return this.runningAgents.size}killAll(){for(let[$]of this.runningAgents)this.killAgent($)}cleanupExpiredSessions($){return this.sessionStore.cleanupExpiredSessions($)}}import{nanoid as p6}from"nanoid";class r1{config;bladeConfig;constructor($,b){this.config=$;this.bladeConfig=b}async execute($){let b=Date.now(),w=$.subagentSessionId??p6();try{let V=this.buildSystemPrompt($),W=this.config.model&&this.config.model!=="inherit"?this.config.model:void 0,Q=await P$.create(this.bladeConfig,{toolWhitelist:this.config.tools,modelId:W}),Z="",Y=0,J=0,X={parentSessionId:$.parentSessionId||"",subagentType:this.config.name,isSidechain:!1},O=await Q.runAgenticLoop($.prompt,{messages:[],userId:"subagent",sessionId:w,workspaceRoot:process.cwd(),permissionMode:$.permissionMode,systemPrompt:V,subagentInfo:X});if(O.success)Z=O.finalMessage||"",Y=O.metadata?.toolCallsCount||0,J=O.metadata?.tokensUsed||0;else throw Error(O.error?.message||"Subagent execution failed");let G=Date.now()-b;return{success:!0,message:Z,agentId:w,stats:{tokens:J,toolCalls:Y,duration:G}}}catch(V){let W=Date.now()-b;return{success:!1,message:"",agentId:w,error:V instanceof Error?V.message:String(V),stats:{duration:W}}}}buildSystemPrompt($){return this.config.systemPrompt||""}}import o1 from"node:fs";import zb from"node:os";import h$ from"node:path";import d6 from"yaml";var a1=[{name:"general-purpose",description:"General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you.",tools:[]},{name:"Explore",description:'Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. "src/components/**/*.tsx"), search code for keywords (eg. "API endpoints"), or answer questions about the codebase (eg. "how do API endpoints work?"). When calling this agent, specify the desired thoroughness level: "quick" for basic searches, "medium" for moderate exploration, or "very thorough" for comprehensive analysis across multiple locations and naming conventions.',tools:["Glob","Grep","Read","WebFetch","WebSearch"],systemPrompt:`# Explore Subagent
1304
+ Remember: Follow the above instructions carefully to complete the user's request.`}import{nanoid as l7}from"nanoid";import{z as X0}from"zod";import{nanoid as O7}from"nanoid";import s$ from"node:fs";import X7 from"node:os";import Z2 from"node:path";var E0=E("Agent");class J0{static instance=null;sessionsDir;cache=new Map;constructor(){this.sessionsDir=Z2.join(X7.homedir(),".blade","agents","sessions"),this.ensureDirectory()}static getInstance(){if(!J0.instance)J0.instance=new J0;return J0.instance}ensureDirectory(){if(!s$.existsSync(this.sessionsDir))s$.mkdirSync(this.sessionsDir,{recursive:!0,mode:493})}getSessionPath($){let b=$.replace(/[^a-zA-Z0-9_-]/g,"_");return Z2.join(this.sessionsDir,`${b}.json`)}saveSession($){try{let b=this.getSessionPath($.id),w=JSON.stringify($,null,2);s$.writeFileSync(b,w,"utf-8"),this.cache.set($.id,$),E0.debug(`Session saved: ${$.id}`)}catch(b){E0.warn(`Failed to save session ${$.id}:`,b)}}loadSession($){if(this.cache.has($))return this.cache.get($);try{let b=this.getSessionPath($);if(!s$.existsSync(b))return;let w=s$.readFileSync(b,"utf-8"),W=JSON.parse(w);return this.cache.set($,W),W}catch(b){E0.warn(`Failed to load session ${$}:`,b);return}}updateSession($,b){let w=this.loadSession($);if(!w)return;let W={...w,...b,lastActiveAt:Date.now()};return this.saveSession(W),W}appendMessages($,b){let w=this.loadSession($);if(!w)return;return this.updateSession($,{messages:[...w.messages,...b]})}markCompleted($,b,w){return this.updateSession($,{status:b.success?"completed":"failed",result:b,stats:w,completedAt:Date.now()})}deleteSession($){try{let b=this.getSessionPath($);if(s$.existsSync(b))s$.unlinkSync(b);return this.cache.delete($),!0}catch(b){return E0.warn(`Failed to delete session ${$}:`,b),!1}}listSessions(){try{let $=s$.readdirSync(this.sessionsDir),b=[];for(let w of $){if(!w.endsWith(".json"))continue;let W=w.replace(".json",""),V=this.loadSession(W);if(V)b.push(V)}return b.sort((w,W)=>W.lastActiveAt-w.lastActiveAt)}catch($){return E0.warn("Failed to list sessions:",$),[]}}listRunningSessions(){return this.listSessions().filter(($)=>$.status==="running")}cleanupExpiredSessions($=604800000){let b=Date.now(),w=this.listSessions(),W=0;for(let V of w){if(V.status==="running")continue;if(b-V.lastActiveAt>$){if(this.deleteSession(V.id))W++}}if(W>0)E0.info(`Cleaned up ${W} expired agent sessions`);return W}clearCache(){this.cache.clear()}}var Y0=E("Agent");class L${static instance=null;runningAgents=new Map;sessionStore=J0.getInstance();constructor(){this.cleanupOrphanedSessions()}static getInstance(){if(!L$.instance)L$.instance=new L$;return L$.instance}cleanupOrphanedSessions(){let $=this.sessionStore.listSessions(),b=Date.now(),w=1800000;for(let W of $)if(W.status==="running"){let V=this.runningAgents.has(W.id),Q=b-W.lastActiveAt;if(!V||Q>1800000)Y0.warn(`Cleaning up orphaned agent session: ${W.id}`),this.sessionStore.updateSession(W.id,{status:"failed",result:{success:!1,message:"",error:"Session was orphaned (process restart or timeout)"},completedAt:b})}}startBackgroundAgent($){let{config:b,bladeConfig:w,description:W,prompt:V,parentSessionId:Q,permissionMode:Z,agentId:J,existingMessages:Y}=$,X=J||O7(),O=new AbortController,G={id:X,subagentType:b.name,description:W,prompt:V,messages:Y||[],status:"running",createdAt:Date.now(),lastActiveAt:Date.now(),parentSessionId:Q};this.sessionStore.saveSession(G);let B=Date.now(),K=this.executeAgent(X,b,w,V,Q,Z,O.signal,Y);return this.runningAgents.set(X,{id:X,promise:K,abortController:O,startTime:B}),K.finally(()=>{this.runningAgents.delete(X)}),Y0.info(`Background agent started: ${X} (${b.name})`),X}async executeAgent($,b,w,W,V,Q,Z,J){let Y=Date.now();try{if(Z.aborted)throw Error("Agent execution was cancelled");let X=b.systemPrompt||"",O=b.model&&b.model!=="inherit"?b.model:void 0,G=await d$.create(w,{systemPrompt:X,toolWhitelist:b.tools,modelId:O}),B={messages:J||[],userId:"subagent",sessionId:$,workspaceRoot:process.cwd(),permissionMode:Q,subagentInfo:{parentSessionId:V||"",subagentType:b.name,isSidechain:!1}},K=await G.runAgenticLoop(W,B,{signal:Z});this.sessionStore.updateSession($,{messages:B.messages});let C=Date.now()-Y,q=K.success?{success:!0,message:K.finalMessage||"",agentId:$,stats:{tokens:K.metadata?.tokensUsed||0,toolCalls:K.metadata?.toolCallsCount||0,duration:C}}:{success:!1,message:"",agentId:$,error:K.error?.message||"Unknown error",stats:{duration:C}};return this.sessionStore.markCompleted($,{success:q.success,message:q.message,error:q.error},q.stats),Y0.info(`Background agent completed: ${$} (success=${q.success})`),q}catch(X){let O=Date.now()-Y,G=X instanceof Error?X.message:String(X);return this.sessionStore.markCompleted($,{success:!1,message:"",error:G},{duration:O}),Y0.warn(`Background agent failed: ${$}`,X),{success:!1,message:"",agentId:$,error:G,stats:{duration:O}}}}getAgent($){return this.sessionStore.loadSession($)}isRunning($){return this.runningAgents.has($)}async waitForCompletion($,b=30000){let w=this.runningAgents.get($);if(!w)return this.sessionStore.loadSession($);if(b>0){let W=new Promise((Q)=>setTimeout(()=>Q("timeout"),b));if(await Promise.race([w.promise,W])==="timeout")return this.sessionStore.loadSession($)}else await w.promise;return this.sessionStore.loadSession($)}resumeAgent($,b,w,W,V,Q){let Z=this.sessionStore.loadSession($);if(!Z){Y0.warn(`Cannot resume agent ${$}: session not found`);return}if(this.isRunning($)){Y0.warn(`Cannot resume agent ${$}: still running`);return}return this.startBackgroundAgent({config:w,bladeConfig:W,description:Z.description,prompt:b,parentSessionId:V||Z.parentSessionId,permissionMode:Q,agentId:$,existingMessages:Z.messages})}killAgent($){let b=this.runningAgents.get($);if(!b){let w=this.sessionStore.loadSession($);if(w&&w.status==="running")this.sessionStore.updateSession($,{status:"cancelled"});return!1}return b.abortController.abort(),this.sessionStore.updateSession($,{status:"cancelled"}),Y0.info(`Background agent cancelled: ${$}`),!0}listAll(){return this.sessionStore.listSessions()}listRunning(){return this.sessionStore.listRunningSessions()}getRunningCount(){return this.runningAgents.size}killAll(){for(let[$]of this.runningAgents)this.killAgent($)}cleanupExpiredSessions($){return this.sessionStore.cleanupExpiredSessions($)}}import{nanoid as G7}from"nanoid";class m1{config;bladeConfig;constructor($,b){this.config=$;this.bladeConfig=b}async execute($){let b=Date.now(),w=$.subagentSessionId??G7();try{let W=this.buildSystemPrompt($),V=this.config.model&&this.config.model!=="inherit"?this.config.model:void 0,Q=await d$.create(this.bladeConfig,{toolWhitelist:this.config.tools,modelId:V}),Z="",J=0,Y=0,X={parentSessionId:$.parentSessionId||"",subagentType:this.config.name,isSidechain:!1},O=await Q.runAgenticLoop($.prompt,{messages:[],userId:"subagent",sessionId:w,workspaceRoot:process.cwd(),permissionMode:$.permissionMode,systemPrompt:W,subagentInfo:X});if(O.success)Z=O.finalMessage||"",J=O.metadata?.toolCallsCount||0,Y=O.metadata?.tokensUsed||0;else throw Error(O.error?.message||"Subagent execution failed");let G=Date.now()-b;return{success:!0,message:Z,agentId:w,stats:{tokens:Y,toolCalls:J,duration:G}}}catch(W){let V=Date.now()-b;return{success:!1,message:"",agentId:w,error:W instanceof Error?W.message:String(W),stats:{duration:V}}}}buildSystemPrompt($){return this.config.systemPrompt||""}}import i1 from"node:fs";import fb from"node:os";import u$ from"node:path";import B7 from"yaml";var c1=[{name:"general-purpose",description:"General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you.",tools:[]},{name:"Explore",description:'Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. "src/components/**/*.tsx"), search code for keywords (eg. "API endpoints"), or answer questions about the codebase (eg. "how do API endpoints work?"). When calling this agent, specify the desired thoroughness level: "quick" for basic searches, "medium" for moderate exploration, or "very thorough" for comprehensive analysis across multiple locations and naming conventions.',tools:["Glob","Grep","Read","WebFetch","WebSearch"],systemPrompt:`# Explore Subagent
1421
1305
 
1422
1306
  You are a specialized code exploration agent. Your job is to **directly execute searches** using the tools available to you.
1423
1307
 
@@ -1484,17 +1368,46 @@ You are a software architect specializing in implementation planning.
1484
1368
  **Risks**:
1485
1369
  - [Potential issue and mitigation]
1486
1370
 
1487
- Be thorough but concise. Focus on actionable steps.`},{name:"statusline-setup",description:"Use this agent to configure the user's Claude Code status line setting.",tools:["Read","Edit"]}];function $2($){switch($){case"default":case"ignore":case void 0:return v.DEFAULT;case"acceptEdits":return v.AUTO_EDIT;case"dontAsk":case"bypassPermissions":return v.YOLO;case"plan":return v.PLAN;default:return v.DEFAULT}}var t1=N("Agent");class b2{subagents=new Map;register($){if(this.subagents.has($.name))throw Error(`Subagent '${$.name}' already registered`);this.subagents.set($.name,$)}getSubagent($){return this.subagents.get($)}getAllNames(){return Array.from(this.subagents.keys())}getAllSubagents(){return Array.from(this.subagents.values())}getDescriptionsForPrompt(){let $=this.getAllSubagents();if($.length===0)return"No subagents available.";return`Available agent types and the tools they have access to:
1488
- ${$.map((w)=>{let V=!w.tools||w.tools.length===0?"All tools":w.tools.join(", ");return`- ${w.name}: ${w.description} (Tools: ${V})`}).join(`
1489
- `)}`}loadFromDirectory($,b){if(!o1.existsSync($))return;let w=o1.readdirSync($);for(let V of w){if(!V.endsWith(".md"))continue;let W=h$.join($,V);try{let Q=this.parseConfigFile(W,b);this.subagents.set(Q.name,Q)}catch(Q){t1.warn(`Failed to load subagent config from ${W}:`,Q)}}}parseConfigFile($,b){let V=o1.readFileSync($,"utf-8").match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);if(!V)throw Error(`No YAML frontmatter found in ${$}`);let[,W,Q]=V,Z=d6.parse(W);if(!Z.name||!Z.description)throw Error(`Missing required fields (name, description) in ${$}`);let Y=Q.trim(),J=this.parseStringOrArray(Z.tools),X=this.parseStringOrArray(Z.skills),O=$2(Z.permissionMode);return{name:Z.name,description:Z.description,systemPrompt:Y,tools:J,color:Z.color,configPath:$,model:Z.model||"inherit",permissionMode:O,skills:X,source:b}}parseStringOrArray($){if(!$)return;if(Array.isArray($))return $.map((b)=>b.trim()).filter(Boolean);return $.split(",").map((b)=>b.trim()).filter(Boolean)}loadFromStandardLocations(){this.loadBuiltinAgents();let $=h$.join(zb.homedir(),".claude","agents");this.loadFromDirectory($,"claude-code-user");let b=h$.join(process.cwd(),".claude","agents");this.loadFromDirectory(b,"claude-code-project");let w=h$.join(zb.homedir(),".blade","agents");this.loadFromDirectory(w,"blade-user");let V=h$.join(process.cwd(),".blade","agents");this.loadFromDirectory(V,"blade-project");let W=this.getAllNames().length;return t1.debug(`\uD83D\uDCE6 Loaded ${W} subagents from standard locations`),W}loadBuiltinAgents(){for(let $ of a1)this.subagents.set($.name,{...$,model:$.model||"inherit",source:"builtin"});t1.debug(`Loaded ${a1.length} builtin subagents`)}clear(){this.subagents.clear()}getSubagentsBySource(){let $={builtin:[],"claude-code-user":[],"claude-code-project":[],"blade-user":[],"blade-project":[],plugin:[]};for(let b of this.subagents.values()){let w=b.source||"builtin",V=w.startsWith("plugin:")?"plugin":w;$[V].push(b)}return $}clearPluginAgents(){let $=[];for(let[b,w]of this.subagents.entries())if(w.source?.startsWith("plugin:"))$.push(b);for(let b of $)this.subagents.delete(b)}static getClaudeCodeAgentsDir($){if($==="user")return h$.join(zb.homedir(),".claude","agents");return h$.join(process.cwd(),".claude","agents")}static getBladeAgentsDir($){if($==="user")return h$.join(zb.homedir(),".blade","agents");return h$.join(process.cwd(),".blade","agents")}}var w$=new b2;function g6($){let b=$.message||"Unknown error";if(b.includes("Too Many Requests")||b.includes("429")){let w=$.cause;if(w?.responseBody)try{let V=JSON.parse(w.responseBody);if(V.message)return V.message}catch{}return"API 请求过于频繁,请稍后重试"}if(b.includes("ECONNREFUSED")||b.includes("ETIMEDOUT"))return"网络连接失败,请检查网络设置";if(b.includes("401")||b.includes("Unauthorized"))return"API 认证失败,请检查 API Key 配置";return b.split(`
1490
- `)[0]}function m6($){return w$.getAllNames().includes($)}function c6(){let $=w$.getAllNames();return $.length>0?$.join(", "):"none (registry not initialized)"}function i6(){return`
1371
+ Be thorough but concise. Focus on actionable steps.`},{name:"statusline-setup",description:"Use this agent to configure the user's Claude Code status line setting.",tools:["Read","Edit"]}];function J2($){switch($){case"default":case"ignore":case void 0:return z.DEFAULT;case"acceptEdits":return z.AUTO_EDIT;case"dontAsk":case"bypassPermissions":return z.YOLO;case"plan":return z.PLAN;default:return z.DEFAULT}}var l1=E("Agent");class Y2{subagents=new Map;register($){if(this.subagents.has($.name))throw Error(`Subagent '${$.name}' already registered`);this.subagents.set($.name,$)}getSubagent($){return this.subagents.get($)}getAllNames(){return Array.from(this.subagents.keys())}getAllSubagents(){return Array.from(this.subagents.values())}getDescriptionsForPrompt(){let $=this.getAllSubagents();if($.length===0)return"No subagents available.";return`Available agent types and the tools they have access to:
1372
+ ${$.map((w)=>{let W=!w.tools||w.tools.length===0?"All tools":w.tools.join(", ");return`- ${w.name}: ${w.description} (Tools: ${W})`}).join(`
1373
+ `)}`}loadFromDirectory($,b){if(!i1.existsSync($))return;let w=i1.readdirSync($);for(let W of w){if(!W.endsWith(".md"))continue;let V=u$.join($,W);try{let Q=this.parseConfigFile(V,b);this.subagents.set(Q.name,Q)}catch(Q){l1.warn(`Failed to load subagent config from ${V}:`,Q)}}}parseConfigFile($,b){let W=i1.readFileSync($,"utf-8").match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);if(!W)throw Error(`No YAML frontmatter found in ${$}`);let[,V,Q]=W,Z=B7.parse(V);if(!Z.name||!Z.description)throw Error(`Missing required fields (name, description) in ${$}`);let J=Q.trim(),Y=this.parseStringOrArray(Z.tools),X=this.parseStringOrArray(Z.skills),O=J2(Z.permissionMode);return{name:Z.name,description:Z.description,systemPrompt:J,tools:Y,color:Z.color,configPath:$,model:Z.model||"inherit",permissionMode:O,skills:X,source:b}}parseStringOrArray($){if(!$)return;if(Array.isArray($))return $.map((b)=>b.trim()).filter(Boolean);return $.split(",").map((b)=>b.trim()).filter(Boolean)}loadFromStandardLocations(){this.loadBuiltinAgents();let $=u$.join(fb.homedir(),".claude","agents");this.loadFromDirectory($,"claude-code-user");let b=u$.join(process.cwd(),".claude","agents");this.loadFromDirectory(b,"claude-code-project");let w=u$.join(fb.homedir(),".blade","agents");this.loadFromDirectory(w,"blade-user");let W=u$.join(process.cwd(),".blade","agents");this.loadFromDirectory(W,"blade-project");let V=this.getAllNames().length;return l1.debug(`\uD83D\uDCE6 Loaded ${V} subagents from standard locations`),V}loadBuiltinAgents(){for(let $ of c1)this.subagents.set($.name,{...$,model:$.model||"inherit",source:"builtin"});l1.debug(`Loaded ${c1.length} builtin subagents`)}clear(){this.subagents.clear()}getSubagentsBySource(){let $={builtin:[],"claude-code-user":[],"claude-code-project":[],"blade-user":[],"blade-project":[],plugin:[]};for(let b of this.subagents.values()){let w=b.source||"builtin",W=w.startsWith("plugin:")?"plugin":w;$[W].push(b)}return $}clearPluginAgents(){let $=[];for(let[b,w]of this.subagents.entries())if(w.source?.startsWith("plugin:"))$.push(b);for(let b of $)this.subagents.delete(b)}static getClaudeCodeAgentsDir($){if($==="user")return u$.join(fb.homedir(),".claude","agents");return u$.join(process.cwd(),".claude","agents")}static getBladeAgentsDir($){if($==="user")return u$.join(fb.homedir(),".blade","agents");return u$.join(process.cwd(),".blade","agents")}}var W$=new Y2;import{nanoid as B$}from"nanoid";var n1={enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],PostToolUseFailure:[],PermissionRequest:[],UserPromptSubmit:[],SessionStart:[],SessionEnd:[],Stop:[],SubagentStart:[],SubagentStop:[],TaskCompleted:[],Notification:[],Compaction:[]};function s1($,b){return{...$,...b,PreToolUse:b.PreToolUse??$.PreToolUse,PostToolUse:b.PostToolUse??$.PostToolUse,PostToolUseFailure:b.PostToolUseFailure??$.PostToolUseFailure,PermissionRequest:b.PermissionRequest??$.PermissionRequest,UserPromptSubmit:b.UserPromptSubmit??$.UserPromptSubmit,SessionStart:b.SessionStart??$.SessionStart,SessionEnd:b.SessionEnd??$.SessionEnd,Stop:b.Stop??$.Stop,SubagentStart:b.SubagentStart??$.SubagentStart,SubagentStop:b.SubagentStop??$.SubagentStop,TaskCompleted:b.TaskCompleted??$.TaskCompleted,Notification:b.Notification??$.Notification,Compaction:b.Compaction??$.Compaction}}function X2(){let $={};if(process.env.BLADE_DISABLE_HOOKS==="true")$.enabled=!1;if(process.env.BLADE_HOOK_TIMEOUT){let b=parseInt(process.env.BLADE_HOOK_TIMEOUT,10);if(!isNaN(b)&&b>0)$.defaultTimeout=b}return $}class r1{executedHooks=new Map;canExecute($,b){if(!this.executedHooks.has($))this.executedHooks.set($,new Set);if(this.executedHooks.get($).has(b))return console.warn(`[HookGuard] Hook ${b} for tool ${$} already executed, skipping`),!1;return!0}markExecuted($,b){let w=this.executedHooks.get($);if(w)w.add(b)}cleanup($){this.executedHooks.delete($)}cleanupAll(){this.executedHooks.clear()}}import{z as A}from"zod";var a1;((W)=>{W.Approve="approve";W.Block="block";W.Async="async"})(a1||={});var o1;((W)=>{W.Allow="allow";W.Deny="deny";W.Ask="ask"})(o1||={});var t1;((V)=>{V[V.SUCCESS=0]="SUCCESS";V[V.NON_BLOCKING_ERROR=1]="NON_BLOCKING_ERROR";V[V.BLOCKING_ERROR=2]="BLOCKING_ERROR";V[V.TIMEOUT=124]="TIMEOUT"})(t1||={});var G$=A.object({hook_event_name:A.nativeEnum(g0),hook_execution_id:A.string(),timestamp:A.string(),project_dir:A.string(),session_id:A.string(),permission_mode:A.enum(["default","autoEdit","yolo","plan"]),_metadata:A.object({blade_version:A.string(),hook_timeout_ms:A.number()}).optional()}),q7=G$.extend({hook_event_name:A.literal("PreToolUse"),tool_name:A.string(),tool_use_id:A.string(),tool_input:A.record(A.unknown())}),A7=G$.extend({hook_event_name:A.literal("PostToolUse"),tool_name:A.string(),tool_use_id:A.string(),tool_input:A.record(A.unknown()),tool_response:A.unknown()}),F7=G$.extend({hook_event_name:A.literal("Stop"),reason:A.string().optional()}),C7=G$.extend({hook_event_name:A.literal("PostToolUseFailure"),tool_name:A.string(),tool_use_id:A.string(),tool_input:A.record(A.unknown()),error:A.string(),error_type:A.string().optional(),is_interrupt:A.boolean(),is_timeout:A.boolean()}),U7=G$.extend({hook_event_name:A.literal("PermissionRequest"),tool_name:A.string(),tool_use_id:A.string(),tool_input:A.record(A.unknown())}),R7=G$.extend({hook_event_name:A.literal("UserPromptSubmit"),user_prompt:A.string(),has_images:A.boolean(),image_count:A.number()}),H7=G$.extend({hook_event_name:A.literal("SessionStart"),is_resume:A.boolean(),resume_session_id:A.string().optional()}),_7=G$.extend({hook_event_name:A.literal("SessionEnd"),reason:A.enum(["user_exit","error","max_turns","idle_timeout","ctrl_c","clear","logout","other"])}),D7=G$.extend({hook_event_name:A.literal("SubagentStart"),agent_type:A.string(),task_description:A.string().optional(),parent_agent_id:A.string().optional()}),L7=G$.extend({hook_event_name:A.literal("SubagentStop"),agent_type:A.string(),task_description:A.string().optional(),success:A.boolean(),result_summary:A.string().optional(),error:A.string().optional()}),E7=G$.extend({hook_event_name:A.literal("TaskCompleted"),task_id:A.string(),task_description:A.string(),result_summary:A.string().optional(),success:A.boolean()}),j7=G$.extend({hook_event_name:A.literal("Notification"),notification_type:A.enum(["permission_prompt","idle_prompt","auth_success","elicitation_dialog","info","warning","error"]),title:A.string().optional(),message:A.string()}),N7=G$.extend({hook_event_name:A.literal("Compaction"),trigger:A.enum(["manual","auto"]),messages_before:A.number(),tokens_before:A.number()}),TX=A.discriminatedUnion("hook_event_name",[q7,A7,F7,C7,U7,R7,H7,_7,D7,L7,E7,j7,N7]),S7=A.object({hookEventName:A.literal("PreToolUse"),permissionDecision:A.nativeEnum(o1).optional(),permissionDecisionReason:A.string().optional(),updatedInput:A.record(A.unknown()).optional()}),y7=A.object({hookEventName:A.literal("PostToolUse"),additionalContext:A.string().optional(),updatedOutput:A.unknown().optional()}),M7=A.object({hookEventName:A.literal("Stop"),continue:A.boolean().optional(),continueReason:A.string().optional()}),z7=A.object({hookEventName:A.literal("SubagentStart"),additionalContext:A.string().optional()}),v7=A.object({hookEventName:A.literal("SubagentStop"),continue:A.boolean().optional(),continueReason:A.string().optional(),additionalContext:A.string().optional()}),T7=A.object({hookEventName:A.literal("TaskCompleted"),blockCompletion:A.boolean().optional(),blockReason:A.string().optional()}),k7=A.object({hookEventName:A.literal("PermissionRequest"),permissionDecision:A.enum(["approve","deny","ask"]).optional(),permissionDecisionReason:A.string().optional()}),f7=A.object({hookEventName:A.literal("UserPromptSubmit"),updatedPrompt:A.string().optional(),contextInjection:A.string().optional()}),I7=A.object({hookEventName:A.literal("SessionStart"),env:A.record(A.string()).optional()}),P7=A.object({hookEventName:A.literal("Compaction"),blockCompaction:A.boolean().optional(),blockReason:A.string().optional()}),h7=A.object({decision:A.object({behavior:A.nativeEnum(a1)}).optional(),systemMessage:A.string().optional(),hookSpecificOutput:A.discriminatedUnion("hookEventName",[S7,y7,M7,z7,v7,T7,k7,f7,I7,P7]).optional(),suppressOutput:A.boolean().optional()}),x7=A.object({type:A.literal("command"),command:A.string(),timeout:A.number().positive().optional(),statusMessage:A.string().optional()}),p7=A.object({type:A.literal("prompt"),prompt:A.string(),timeout:A.number().positive().optional()}),d7=A.discriminatedUnion("type",[x7,p7]),e1=A.union([A.string(),A.array(A.string())]),u7=A.object({tools:e1.optional(),paths:e1.optional(),commands:e1.optional()}),O$=A.object({name:A.string().optional(),matcher:u7.optional(),hooks:A.array(d7)}),kX=A.object({enabled:A.boolean().optional(),defaultTimeout:A.number().positive().optional(),timeoutBehavior:A.enum(["ignore","deny","ask"]).optional(),failureBehavior:A.enum(["ignore","deny","ask"]).optional(),maxConcurrentHooks:A.number().positive().optional(),PreToolUse:A.array(O$).optional(),PostToolUse:A.array(O$).optional(),PostToolUseFailure:A.array(O$).optional(),PermissionRequest:A.array(O$).optional(),UserPromptSubmit:A.array(O$).optional(),SessionStart:A.array(O$).optional(),SessionEnd:A.array(O$).optional(),Stop:A.array(O$).optional(),SubagentStart:A.array(O$).optional(),SubagentStop:A.array(O$).optional(),TaskCompleted:A.array(O$).optional(),Notification:A.array(O$).optional(),Compaction:A.array(O$).optional()});function O2($){let b=h7.safeParse($);if(b.success)return{success:!0,data:b.data};return{success:!1,error:b.error}}var g7=new Set(Object.values(t1).filter(($)=>typeof $==="number"));function m7($){if(g7.has($))return $;return $>=2?2:1}class $w{parse($,b,w){if($.timedOut){let V=w?.timeoutBehavior||"ignore",Q="Hook timeout";if(V==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};else if(V==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b}}let W=this.tryParseJSON($.stdout);if(W){let V=O2(W);if(!V.success){let Z="error"in V?V.error.message:"Unknown validation error",J=w?.failureBehavior||"ignore",Y=`Invalid hook output JSON: ${Z}`;if(J==="deny")return{success:!1,blocking:!0,error:Y,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};else if(J==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${Y}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};else return{success:!1,blocking:!1,warning:Y,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b}}let Q=V.data;if(Q.decision?.behavior==="block")return{success:!1,blocking:!0,error:Q.systemMessage||"Hook blocked execution",output:Q,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};if(Q.decision?.behavior==="async")return{success:!0,output:Q,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b};return{success:!0,output:Q,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:b}}return this.parseByExitCode($,b,w)}parseByExitCode($,b,w){let W=m7($.exitCode);switch(W){case 0:return{success:!0,stdout:$.stdout,stderr:$.stderr,exitCode:W,hook:b};case 2:return{success:!1,blocking:!0,error:$.stderr||$.stdout||"Hook returned exit code 2",stdout:$.stdout,stderr:$.stderr,exitCode:W,hook:b};case 124:{let V=w?.timeoutBehavior||"ignore",Q="Hook timeout";if(V==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:W,hook:b};else if(V==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:W,hook:b};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:W,hook:b}}default:{let V=w?.failureBehavior||"ignore",Q=$.stderr||$.stdout||`Hook failed with exit code ${W}`;if(V==="deny")return{success:!1,blocking:!0,error:Q,stdout:$.stdout,stderr:$.stderr,exitCode:W,hook:b};else if(V==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${Q}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:W,hook:b};else return{success:!1,blocking:!1,warning:Q,stdout:$.stdout,stderr:$.stderr,exitCode:W,hook:b}}}}tryParseJSON($){try{let b=$.trim();if(!b)return null;let w=b.match(/^\s*(\{[\s\S]*\})\s*$/);if(!w)return null;return JSON.parse(w[1])}catch{return null}}}import{spawn as c7}from"child_process";class bw{content="";maxSize;constructor($){this.maxSize=$}append($){if(this.content.length<this.maxSize){let b=this.maxSize-this.content.length;this.content+=$.substring(0,b)}}getContent(){return this.content}isFull(){return this.content.length>=this.maxSize}}class ww{MAX_STDOUT_SIZE=1048576;MAX_STDERR_SIZE=1048576;MAX_INPUT_SIZE=102400;async execute($,b,w,W){let V=JSON.stringify(b);if(V.length>this.MAX_INPUT_SIZE)throw Error(`Hook input too large: ${V.length} bytes (max ${this.MAX_INPUT_SIZE})`);let Q=this.createSafeEnv(b),Z=c7($,[],{shell:!0,env:Q,cwd:w.projectDir,timeout:W}),J=new bw(this.MAX_STDOUT_SIZE),Y=new bw(this.MAX_STDERR_SIZE);Z.stdout.setEncoding("utf8"),Z.stderr.setEncoding("utf8"),Z.stdout.on("data",(X)=>{J.append(X)}),Z.stderr.on("data",(X)=>{Y.append(X)});try{Z.stdin.write(V),Z.stdin.end()}catch(X){throw Z.kill("SIGTERM"),Error(`Failed to write hook input: ${X}`)}return new Promise((X,O)=>{let G=!1,B=!1,K=null,C=()=>{if(K&&w.abortSignal)w.abortSignal.removeEventListener("abort",K),K=null},q=setTimeout(()=>{G=!0,Z.kill("SIGKILL")},W);if(Z.on("close",(F)=>{if(B)return;B=!0,clearTimeout(q),C(),X({stdout:J.getContent(),stderr:Y.getContent(),exitCode:G?124:F??1,timedOut:G})}),Z.on("error",(F)=>{if(B)return;B=!0,clearTimeout(q),C(),O(F)}),w.abortSignal)K=()=>{if(B)return;B=!0,clearTimeout(q),C(),Z.kill("SIGTERM"),X({stdout:J.getContent(),stderr:"Hook cancelled by abort signal",exitCode:1,timedOut:!1})},w.abortSignal.addEventListener("abort",K)})}createSafeEnv($){return{BLADE_PROJECT_DIR:$.project_dir,BLADE_SESSION_ID:$.session_id,BLADE_HOOK_EVENT:$.hook_event_name,BLADE_TOOL_NAME:"tool_name"in $?$.tool_name:"",BLADE_TOOL_USE_ID:"tool_use_id"in $?$.tool_use_id:"",PATH:process.env.PATH||"",HOME:process.env.HOME||"",USER:process.env.USER||"",SHELL:process.env.SHELL||"/bin/sh"}}}class Ww{processExecutor=new ww;outputParser=new $w;async executePreToolHooks($,b,w){if($.length===0)return{decision:"allow"};let W="tool_input"in b?b.tool_input:{},V=[];for(let Q of $)try{let Z={...b,...W&&{tool_input:W}},J=await this.executeHook(Q,Z,w);if(!J.success){if(J.blocking)return{decision:"deny",reason:J.error};if(J.needsConfirmation)return{decision:"ask",reason:J.warning||J.error};if(J.warning)V.push(J.warning);continue}let Y=J.output?.hookSpecificOutput;if(Y&&"permissionDecision"in Y){switch(Y.permissionDecision){case"deny":return{decision:"deny",reason:Y.permissionDecisionReason};case"ask":return{decision:"ask",reason:Y.permissionDecisionReason};case"allow":break}if("updatedInput"in Y&&Y.updatedInput)W={...W,...Y.updatedInput}}}catch(Z){let J=Z instanceof Error?Z.message:String(Z);if(V.push(`Hook failed: ${J}`),w.config.failureBehavior==="deny")return{decision:"deny",reason:J};else if(w.config.failureBehavior==="ask")return{decision:"ask",reason:`Hook failed: ${J}. Continue?`}}return{decision:"allow",modifiedInput:W,warning:V.length>0?V.join(`
1374
+ `):void 0}}async executePostToolHooks($,b,w){if($.length===0)return{};let W=w.config.maxConcurrentHooks||5,V=await this.executeHooksConcurrently($,b,w,W),Q=[],Z,J=[];for(let Y of V){if(!Y.success&&Y.warning){J.push(Y.warning);continue}let X=Y.output?.hookSpecificOutput;if(X&&"additionalContext"in X){if(X.additionalContext)Q.push(X.additionalContext);if("updatedOutput"in X&&X.updatedOutput!==void 0)Z=X.updatedOutput}}return{additionalContext:Q.length>0?Q.join(`
1375
+
1376
+ `):void 0,modifiedOutput:Z,warning:J.length>0?J.join(`
1377
+ `):void 0}}async executeStopHooks($,b,w){if($.length===0)return{shouldStop:!0};let W=[];for(let V of $)try{let Q=await this.executeHook(V,b,w);if(!Q.success){if(Q.warning)W.push(Q.warning);continue}let Z=Q.output?.hookSpecificOutput;if(Z&&"continue"in Z&&Z.continue===!1)return{shouldStop:!1,continueReason:Z.continueReason,warning:W.length>0?W.join(`
1378
+ `):void 0}}catch(Q){let Z=Q instanceof Error?Q.message:String(Q);W.push(`Hook failed: ${Z}`)}return{shouldStop:!0,warning:W.length>0?W.join(`
1379
+ `):void 0}}async executeSubagentStartHooks($,b,w){if($.length===0)return{proceed:!0};let W=[],V=[];for(let Q of $)try{let Z=await this.executeHook(Q,b,w);if(!Z.success){if(Z.blocking)return{proceed:!1,warning:Z.error};if(Z.warning)W.push(Z.warning);continue}let J=Z.output?.hookSpecificOutput;if(J&&"additionalContext"in J&&J.additionalContext)V.push(J.additionalContext)}catch(Z){let J=Z instanceof Error?Z.message:String(Z);W.push(`Hook failed: ${J}`)}return{proceed:!0,additionalContext:V.length>0?V.join(`
1380
+
1381
+ `):void 0,warning:W.length>0?W.join(`
1382
+ `):void 0}}async executeSubagentStopHooks($,b,w){if($.length===0)return{shouldStop:!0};let W=[],V=[];for(let Q of $)try{let Z=await this.executeHook(Q,b,w);if(!Z.success){if(Z.warning)W.push(Z.warning);continue}let J=Z.output?.hookSpecificOutput;if(J&&"continue"in J){if(J.continue===!1)return{shouldStop:!1,continueReason:J.continueReason,warning:W.length>0?W.join(`
1383
+ `):void 0};if("additionalContext"in J&&J.additionalContext)V.push(J.additionalContext)}}catch(Z){let J=Z instanceof Error?Z.message:String(Z);W.push(`Hook failed: ${J}`)}return{shouldStop:!0,additionalContext:V.length>0?V.join(`
1384
+
1385
+ `):void 0,warning:W.length>0?W.join(`
1386
+ `):void 0}}async executeTaskCompletedHooks($,b,w){if($.length===0)return{allowCompletion:!0};let W=[];for(let V of $)try{let Q=await this.executeHook(V,b,w);if(!Q.success){if(Q.blocking)return{allowCompletion:!1,blockReason:Q.error,warning:W.length>0?W.join(`
1387
+ `):void 0};if(Q.warning)W.push(Q.warning);continue}let Z=Q.output?.hookSpecificOutput;if(Z&&"blockCompletion"in Z&&Z.blockCompletion)return{allowCompletion:!1,blockReason:Z.blockReason,warning:W.length>0?W.join(`
1388
+ `):void 0}}catch(Q){let Z=Q instanceof Error?Q.message:String(Q);W.push(`Hook failed: ${Z}`)}return{allowCompletion:!0,warning:W.length>0?W.join(`
1389
+ `):void 0}}async executePermissionRequestHooks($,b,w){if($.length===0)return{decision:"ask"};let W=[];for(let V of $)try{let Q=await this.executeHook(V,b,w);if(!Q.success){if(Q.warning)W.push(Q.warning);continue}let Z=Q.output?.hookSpecificOutput;if(Z&&"permissionDecision"in Z){let J=Z.permissionDecision;if(J==="approve"||J==="deny")return{decision:J,reason:Z.permissionDecisionReason,warning:W.length>0?W.join(`
1390
+ `):void 0}}}catch(Q){let Z=Q instanceof Error?Q.message:String(Q);W.push(`Hook failed: ${Z}`)}return{decision:"ask",warning:W.length>0?W.join(`
1391
+ `):void 0}}async executeUserPromptSubmitHooks($,b,w){if($.length===0)return{proceed:!0};let W=[],V=[],Q;for(let Z of $)try{let J=await this.executeHook(Z,b,w);if(!J.success){if(J.blocking)return{proceed:!1,warning:J.error};if(J.warning)W.push(J.warning);continue}if(J.stdout&&J.stdout.trim())V.push(J.stdout.trim());let Y=J.output?.hookSpecificOutput;if(Y&&"updatedPrompt"in Y){if(Y.updatedPrompt)Q=Y.updatedPrompt;if(Y.contextInjection)V.push(Y.contextInjection)}}catch(J){let Y=J instanceof Error?J.message:String(J);W.push(`Hook failed: ${Y}`)}return{proceed:!0,updatedPrompt:Q,contextInjection:V.length>0?V.join(`
1392
+
1393
+ `):void 0,warning:W.length>0?W.join(`
1394
+ `):void 0}}async executeSessionStartHooks($,b,w){if($.length===0)return{proceed:!0};let W=[],V={};for(let Q of $)try{let Z=await this.executeHook(Q,b,w);if(!Z.success){if(Z.blocking)return{proceed:!1,warning:Z.error};if(Z.warning)W.push(Z.warning);continue}let J=Z.output?.hookSpecificOutput;if(J&&"env"in J&&J.env)Object.assign(V,J.env)}catch(Z){let J=Z instanceof Error?Z.message:String(Z);W.push(`Hook failed: ${J}`)}return{proceed:!0,env:Object.keys(V).length>0?V:void 0,warning:W.length>0?W.join(`
1395
+ `):void 0}}async executeSessionEndHooks($,b,w){if($.length===0)return{};let W=[],V=w.config.maxConcurrentHooks||5,Q=await this.executeHooksConcurrently($,b,w,V);for(let Z of Q)if(!Z.success&&Z.warning)W.push(Z.warning);return{warning:W.length>0?W.join(`
1396
+ `):void 0}}async executePostToolUseFailureHooks($,b,w){if($.length===0)return{};let W=[],V=[],Q=w.config.maxConcurrentHooks||5,Z=await this.executeHooksConcurrently($,b,w,Q);for(let J of Z){if(!J.success&&J.warning){W.push(J.warning);continue}if(J.stdout&&J.stdout.trim())V.push(J.stdout.trim())}return{additionalContext:V.length>0?V.join(`
1397
+
1398
+ `):void 0,warning:W.length>0?W.join(`
1399
+ `):void 0}}async executeNotificationHooks($,b,w){let W="message"in b?b.message:"";if($.length===0)return{suppress:!1,message:W};let V=[],Q=!1,Z=W;for(let J of $)try{let Y=await this.executeHook(J,b,w);if(!Y.success){if(Y.warning)V.push(Y.warning);continue}if(Y.output?.suppressOutput){Q=!0;break}if(Y.stdout&&Y.stdout.trim())Z=Y.stdout.trim()}catch(Y){let X=Y instanceof Error?Y.message:String(Y);V.push(`Hook failed: ${X}`)}return{suppress:Q,message:Z,warning:V.length>0?V.join(`
1400
+ `):void 0}}async executeCompactionHooks($,b,w){if($.length===0)return{blockCompaction:!1};let W=[];for(let V of $)try{let Q=await this.executeHook(V,b,w);if(!Q.success){if(Q.warning)W.push(Q.warning);continue}let Z=Q.output?.hookSpecificOutput;if(Z&&"blockCompaction"in Z&&Z.blockCompaction)return{blockCompaction:!0,blockReason:Z.blockReason,warning:W.length>0?W.join(`
1401
+ `):void 0}}catch(Q){let Z=Q instanceof Error?Q.message:String(Q);W.push(`Hook failed: ${Z}`)}return{blockCompaction:!1,warning:W.length>0?W.join(`
1402
+ `):void 0}}async executeHook($,b,w){if($.type==="command")return this.executeCommandHook($,b,w);throw Error(`Hook type ${$.type} not yet implemented`)}async executeCommandHook($,b,w){let W=($.timeout??w.config.defaultTimeout??60)*1000;try{let V=await this.processExecutor.execute($.command,b,w,W);return this.outputParser.parse(V,$,{timeoutBehavior:w.config.timeoutBehavior,failureBehavior:w.config.failureBehavior})}catch(V){return{success:!1,blocking:!1,error:V instanceof Error?V.message:String(V),hook:$}}}async executeHooksConcurrently($,b,w,W){let V=[],Q=new Set;for(let Z of $){if(Q.size>=W)await Promise.race(Q);let J=this.executeHook(Z,b,w).catch((X)=>({success:!1,blocking:!1,error:X instanceof Error?X.message:String(X),hook:Z})),Y=J.then(()=>{Q.delete(Y)}).catch(()=>{Q.delete(Y)});Q.add(Y),V.push(J)}return Promise.all(V)}}import Vw from"picomatch";var i7=/^([A-Za-z0-9_|]+)\((.+)\)$/;class Qw{matches($,b){if(!$)return!0;if($.tools&&b.toolName){if(!this.matchTools($.tools,b))return!1}if($.paths&&b.filePath){if(!this.matchPaths($.paths,b.filePath))return!1}if($.commands&&b.command){if(!this.matchCommands($.commands,b.command))return!1}return!0}matchTools($,b){if(Array.isArray($))return $.some((w)=>this.matchToolWithParams(w,b));return this.matchToolWithParams($,b)}matchPaths($,b){if(Array.isArray($))return $.some((W)=>{return Vw(W)(b)});return Vw($)(b)}matchCommands($,b){if(Array.isArray($))return $.some((w)=>this.matchPattern(b,w));return this.matchPattern(b,$)}matchToolWithParams($,b){let{toolName:w,command:W,filePath:V}=b,Q=i7.exec($);if(!Q)return this.matchPattern(w,$);let[,Z,J]=Q;if(!this.matchPattern(w,Z))return!1;let Y=this.getArgValue(w,W,V);if(!Y)return!1;return this.matchGlobOrPattern(Y,J)}getArgValue($,b,w){if($==="Bash"||$==="BashTool")return b;if(["Read","Edit","Write","Glob","Grep"].includes($))return w;return b||w}matchGlobOrPattern($,b){if(/[*?[\]{}!]/.test(b))try{return Vw(b,{bash:!0,dot:!0})($)}catch{}if(b.endsWith("*")){let w=b.slice(0,-1);return $.startsWith(w)}return $===b}matchPattern($,b){if(b==="*")return!0;if(!b.includes("|")&&!/[.*+?^${}()|[\]\\]/.test(b))return $===b;if(b.includes("|"))return b.split("|").map((W)=>W.trim()).includes($);try{return new RegExp(b).test($)}catch{return $===b}}}class c{static instance=null;config=n1;executor=new Ww;guard=new r1;matcher=new Qw;sessionDisabled=!1;constructor(){}static getInstance(){if(!c.instance)c.instance=new c;return c.instance}loadConfig($){let b=s1(n1,$),w=X2();b=s1(b,w),this.config=b}isEnabled(){if(!this.config.enabled)return!1;if(this.sessionDisabled)return!1;return!0}disable(){this.sessionDisabled=!0,console.log("[HookManager] Hooks disabled for this session")}enable(){this.sessionDisabled=!1,console.log("[HookManager] Hooks enabled for this session")}getConfig(){return this.config}async reloadConfig(){let $=await import("node:fs/promises"),b=await import("node:path");try{let w=b.join(process.cwd(),".blade","settings.local.json"),W=await $.readFile(w,"utf-8"),V=JSON.parse(W);if(V.hooks)this.loadConfig(V.hooks)}catch{}}async executePreToolHooks($,b,w,W){if(!this.isEnabled())return{decision:"allow"};if(W.permissionMode==="plan")return{decision:"allow"};if(!this.guard.canExecute(b,"PreToolUse"))return{decision:"allow"};let V={hook_event_name:"PreToolUse",hook_execution_id:B$(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:b,tool_input:w,project_dir:W.projectDir,session_id:W.sessionId,permission_mode:W.permissionMode},Q=this.getMatchingHooks("PreToolUse",{toolName:$,filePath:this.extractFilePath(w),command:this.extractCommand($,w)});if(Q.length===0)return{decision:"allow"};let Z={projectDir:W.projectDir,sessionId:W.sessionId,permissionMode:W.permissionMode,config:this.config,abortSignal:W.abortSignal};try{let J=await this.executor.executePreToolHooks(Q,V,Z);if(this.guard.markExecuted(b,"PreToolUse"),W.permissionMode==="yolo"){if(J.decision==="deny")return J;return{decision:"allow",modifiedInput:J.modifiedInput,warning:J.warning,reason:J.reason}}return J}catch(J){return console.error("[HookManager] Error executing PreToolUse hooks:",J),{decision:"allow",warning:`Hook execution failed: ${J instanceof Error?J.message:String(J)}`}}}async executePostToolHooks($,b,w,W,V){if(!this.isEnabled())return{};if(V.permissionMode==="plan")return{};if(!this.guard.canExecute(b,"PostToolUse"))return{};let Q={hook_event_name:"PostToolUse",hook_execution_id:B$(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:b,tool_input:w,tool_response:W,project_dir:V.projectDir,session_id:V.sessionId,permission_mode:V.permissionMode},Z=this.getMatchingHooks("PostToolUse",{toolName:$,filePath:this.extractFilePath(w),command:this.extractCommand($,w)});if(Z.length===0)return{};let J={projectDir:V.projectDir,sessionId:V.sessionId,permissionMode:V.permissionMode,config:this.config,abortSignal:V.abortSignal};try{let Y=await this.executor.executePostToolHooks(Z,Q,J);return this.guard.markExecuted(b,"PostToolUse"),Y}catch(Y){return console.error("[HookManager] Error executing PostToolUse hooks:",Y),{warning:`Hook execution failed: ${Y instanceof Error?Y.message:String(Y)}`}}finally{this.guard.cleanup(b)}}async executeStopHooks($){if(!this.isEnabled())return{shouldStop:!0};let b={hook_event_name:"Stop",hook_execution_id:B$(),timestamp:new Date().toISOString(),project_dir:$.projectDir,session_id:$.sessionId,permission_mode:$.permissionMode,reason:$.reason},w=this.getMatchingHooks("Stop",{});if(w.length===0)return{shouldStop:!0};let W={projectDir:$.projectDir,sessionId:$.sessionId,permissionMode:$.permissionMode,config:this.config,abortSignal:$.abortSignal};try{return await this.executor.executeStopHooks(w,b,W)}catch(V){return console.error("[HookManager] Error executing Stop hooks:",V),{shouldStop:!0,warning:`Hook execution failed: ${V instanceof Error?V.message:String(V)}`}}}async executeSubagentStartHooks($,b){if(!this.isEnabled())return{proceed:!0};let w={hook_event_name:"SubagentStart",hook_execution_id:B$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,agent_type:$,task_description:b.taskDescription,parent_agent_id:b.parentAgentId},W=this.getMatchingHooks("SubagentStart",{toolName:$});if(W.length===0)return{proceed:!0};let V={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeSubagentStartHooks(W,w,V)}catch(Q){return console.error("[HookManager] Error executing SubagentStart hooks:",Q),{proceed:!0,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executeSubagentStopHooks($,b){if(!this.isEnabled())return{shouldStop:!0};let w={hook_event_name:"SubagentStop",hook_execution_id:B$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,agent_type:$,task_description:b.taskDescription,success:b.success,result_summary:b.resultSummary,error:b.error},W=this.getMatchingHooks("SubagentStop",{});if(W.length===0)return{shouldStop:!0};let V={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeSubagentStopHooks(W,w,V)}catch(Q){return console.error("[HookManager] Error executing SubagentStop hooks:",Q),{shouldStop:!0,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executeTaskCompletedHooks($,b){if(!this.isEnabled())return{allowCompletion:!0};let w={hook_event_name:"TaskCompleted",hook_execution_id:B$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,task_id:$,task_description:b.taskDescription,result_summary:b.resultSummary,success:b.success},W=this.getMatchingHooks("TaskCompleted",{});if(W.length===0)return{allowCompletion:!0};let V={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeTaskCompletedHooks(W,w,V)}catch(Q){return console.error("[HookManager] Error executing TaskCompleted hooks:",Q),{allowCompletion:!0,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executePermissionRequestHooks($,b,w,W){if(!this.isEnabled())return{decision:"ask"};let V={hook_event_name:"PermissionRequest",hook_execution_id:B$(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:b,tool_input:w,project_dir:W.projectDir,session_id:W.sessionId,permission_mode:W.permissionMode},Q=this.getMatchingHooks("PermissionRequest",{toolName:$,filePath:this.extractFilePath(w),command:this.extractCommand($,w)});if(Q.length===0)return{decision:"ask"};let Z={projectDir:W.projectDir,sessionId:W.sessionId,permissionMode:W.permissionMode,config:this.config,abortSignal:W.abortSignal};try{return await this.executor.executePermissionRequestHooks(Q,V,Z)}catch(J){return console.error("[HookManager] Error executing PermissionRequest hooks:",J),{decision:"ask",warning:`Hook execution failed: ${J instanceof Error?J.message:String(J)}`}}}async executeUserPromptSubmitHooks($,b){if(!this.isEnabled())return{proceed:!0};let w={hook_event_name:"UserPromptSubmit",hook_execution_id:B$(),timestamp:new Date().toISOString(),user_prompt:$,has_images:b.hasImages,image_count:b.imageCount,project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode},W=this.getMatchingHooks("UserPromptSubmit",{});if(W.length===0)return{proceed:!0};let V={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeUserPromptSubmitHooks(W,w,V)}catch(Q){return console.error("[HookManager] Error executing UserPromptSubmit hooks:",Q),{proceed:!0,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executeSessionStartHooks($){if(!this.isEnabled())return{proceed:!0};let b={hook_event_name:"SessionStart",hook_execution_id:B$(),timestamp:new Date().toISOString(),project_dir:$.projectDir,session_id:$.sessionId,permission_mode:$.permissionMode,is_resume:$.isResume,resume_session_id:$.resumeSessionId},w=this.getMatchingHooks("SessionStart",{});if(w.length===0)return{proceed:!0};let W={projectDir:$.projectDir,sessionId:$.sessionId,permissionMode:$.permissionMode,config:this.config,abortSignal:$.abortSignal};try{return await this.executor.executeSessionStartHooks(w,b,W)}catch(V){return console.error("[HookManager] Error executing SessionStart hooks:",V),{proceed:!0,warning:`Hook execution failed: ${V instanceof Error?V.message:String(V)}`}}}async executeSessionEndHooks($,b){if(!this.isEnabled())return{};let w={hook_event_name:"SessionEnd",hook_execution_id:B$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,reason:$},W=this.getMatchingHooks("SessionEnd",{});if(W.length===0)return{};let V={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeSessionEndHooks(W,w,V),{}}catch(Q){return console.error("[HookManager] Error executing SessionEnd hooks:",Q),{warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}async executePostToolUseFailureHooks($,b,w,W,V){if(!this.isEnabled())return{};let Q={hook_event_name:"PostToolUseFailure",hook_execution_id:B$(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:b,tool_input:w,error:W,error_type:V.errorType,is_interrupt:V.isInterrupt,is_timeout:V.isTimeout,project_dir:V.projectDir,session_id:V.sessionId,permission_mode:V.permissionMode},Z=this.getMatchingHooks("PostToolUseFailure",{toolName:$,filePath:this.extractFilePath(w),command:this.extractCommand($,w)});if(Z.length===0)return{};let J={projectDir:V.projectDir,sessionId:V.sessionId,permissionMode:V.permissionMode,config:this.config,abortSignal:V.abortSignal};try{return await this.executor.executePostToolUseFailureHooks(Z,Q,J)}catch(Y){return console.error("[HookManager] Error executing PostToolUseFailure hooks:",Y),{warning:`Hook execution failed: ${Y instanceof Error?Y.message:String(Y)}`}}}async executeNotificationHooks($,b,w){if(!this.isEnabled())return{suppress:!1,message:b};let W={hook_event_name:"Notification",hook_execution_id:B$(),timestamp:new Date().toISOString(),project_dir:w.projectDir,session_id:w.sessionId,permission_mode:w.permissionMode,notification_type:$,title:w.title,message:b},V=this.getMatchingHooks("Notification",{});if(V.length===0)return{suppress:!1,message:b};let Q={projectDir:w.projectDir,sessionId:w.sessionId,permissionMode:w.permissionMode,config:this.config,abortSignal:w.abortSignal};try{return await this.executor.executeNotificationHooks(V,W,Q)}catch(Z){return console.error("[HookManager] Error executing Notification hooks:",Z),{suppress:!1,message:b,warning:`Hook execution failed: ${Z instanceof Error?Z.message:String(Z)}`}}}async executeCompactionHooks($,b){if(!this.isEnabled())return{blockCompaction:!1};let w={hook_event_name:"Compaction",hook_execution_id:B$(),timestamp:new Date().toISOString(),project_dir:b.projectDir,session_id:b.sessionId,permission_mode:b.permissionMode,trigger:$,messages_before:b.messagesBefore,tokens_before:b.tokensBefore},W=this.getMatchingHooks("Compaction",{});if(W.length===0)return{blockCompaction:!1};let V={projectDir:b.projectDir,sessionId:b.sessionId,permissionMode:b.permissionMode,config:this.config,abortSignal:b.abortSignal};try{return await this.executor.executeCompactionHooks(W,w,V)}catch(Q){return console.error("[HookManager] Error executing Compaction hooks:",Q),{blockCompaction:!1,warning:`Hook execution failed: ${Q instanceof Error?Q.message:String(Q)}`}}}getMatchingHooks($,b){let w=this.config[$]||[],W=[];for(let V of w)if(this.matcher.matches(V.matcher,b))W.push(...V.hooks);return W}extractFilePath($){let b=["file_path","path","filePath","source","target"];for(let w of b){let W=$[w];if(typeof W==="string")return W}return}extractCommand($,b){if($==="Bash"||$==="BashTool"){let w=b.command;if(typeof w==="string")return w}return}cleanup(){this.guard.cleanupAll()}}function n7($){let b=$.message||"Unknown error";if(b.includes("Too Many Requests")||b.includes("429")){let w=$.cause;if(w?.responseBody)try{let W=JSON.parse(w.responseBody);if(W.message)return W.message}catch{}return"API 请求过于频繁,请稍后重试"}if(b.includes("ECONNREFUSED")||b.includes("ETIMEDOUT"))return"网络连接失败,请检查网络设置";if(b.includes("401")||b.includes("Unauthorized"))return"API 认证失败,请检查 API Key 配置";return b.split(`
1403
+ `)[0]}function s7($){return W$.getAllNames().includes($)}function r7(){let $=W$.getAllNames();return $.length>0?$.join(", "):"none (registry not initialized)"}function a7(){return`
1491
1404
  ## Task
1492
1405
 
1493
1406
  Launch a new agent to handle complex, multi-step tasks autonomously.
1494
1407
 
1495
1408
  The Task tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
1496
1409
 
1497
- ${w$.getDescriptionsForPrompt()}
1410
+ ${W$.getDescriptionsForPrompt()}
1498
1411
 
1499
1412
  When using the Task tool, you must specify a subagent_type parameter to select which agent type to use.
1500
1413
 
@@ -1518,45 +1431,45 @@ Usage notes:
1518
1431
  - Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent
1519
1432
  - If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.
1520
1433
  - If the user specifies that they want you to run agents "in parallel", you MUST send a single message with multiple Task tool use content blocks. For example, if you need to launch both a code-reviewer agent and a test-runner agent in parallel, send a single message with both tool calls.
1521
- `.trim()}var e1=E({name:"Task",displayName:"Subagent Scheduler",kind:"readonly",isReadOnly:!0,schema:W0.object({subagent_type:W0.string().refine(m6,($)=>({message:`Invalid subagent type: "${$}". Available: ${c6()}`})).describe('Subagent type to use (e.g., "Explore", "Plan")'),description:W0.string().min(3).max(100).describe("Short task description (3-5 words)"),prompt:W0.string().min(10).describe("Detailed task instructions"),run_in_background:W0.boolean().default(!1).describe("Set to true to run this agent in the background. Use TaskOutput to read the output later."),resume:W0.string().optional().describe("Optional agent ID to resume from. If provided, the agent will continue from the previous execution transcript."),subagent_session_id:W0.string().optional().describe("Internal subagent session id for tracking")}),description:{short:"Launch a new agent to handle complex, multi-step tasks autonomously",get long(){return i6()},usageNotes:["subagent_type is required - choose from available agent types",'description should be 3-5 words (e.g., "Explore error handling")',"prompt should contain a highly detailed task description and specify exactly what information to return","Launch multiple agents concurrently when possible for better performance"],examples:[{description:"Explore codebase for API endpoints",params:{subagent_type:"Explore",description:"Find API endpoints",prompt:"Search the codebase for all API endpoint definitions. Look for route handlers, REST endpoints, and GraphQL resolvers. Return a structured list with file paths, endpoint URLs, HTTP methods, and descriptions."}},{description:"Plan authentication feature",params:{subagent_type:"Plan",description:"Plan user auth",prompt:"Create a detailed implementation plan for adding user authentication to this project. Analyze the existing architecture, then provide step-by-step instructions including: 1) Database schema changes 2) API routes to create 3) Frontend components needed 4) Security considerations 5) Testing strategy. Be specific about file names and code locations."}}]},async execute($,b){let{subagent_type:w,description:V,prompt:W,run_in_background:Q=!1,resume:Z,subagent_session_id:Y}=$,{updateOutput:J}=b,X=typeof Y==="string"&&Y.length>0?Y:typeof Z==="string"&&Z.length>0?Z:u6();try{let O=w$.getAllNames(),G=w$.getSubagent(w);if(!G)return{success:!1,llmContent:`Unknown subagent type: ${w}. Available types: ${O.join(", ")||"none"}`,displayContent:`❌ 未知的 subagent 类型: ${w}
1434
+ `.trim()}var Zw=L({name:"Task",displayName:"Subagent Scheduler",kind:"readonly",isReadOnly:!0,schema:X0.object({subagent_type:X0.string().refine(s7,($)=>({message:`Invalid subagent type: "${$}". Available: ${r7()}`})).describe('Subagent type to use (e.g., "Explore", "Plan")'),description:X0.string().min(3).max(100).describe("Short task description (3-5 words)"),prompt:X0.string().min(10).describe("Detailed task instructions"),run_in_background:X0.boolean().default(!1).describe("Set to true to run this agent in the background. Use TaskOutput to read the output later."),resume:X0.string().optional().describe("Optional agent ID to resume from. If provided, the agent will continue from the previous execution transcript."),subagent_session_id:X0.string().optional().describe("Internal subagent session id for tracking")}),description:{short:"Launch a new agent to handle complex, multi-step tasks autonomously",get long(){return a7()},usageNotes:["subagent_type is required - choose from available agent types",'description should be 3-5 words (e.g., "Explore error handling")',"prompt should contain a highly detailed task description and specify exactly what information to return","Launch multiple agents concurrently when possible for better performance"],examples:[{description:"Explore codebase for API endpoints",params:{subagent_type:"Explore",description:"Find API endpoints",prompt:"Search the codebase for all API endpoint definitions. Look for route handlers, REST endpoints, and GraphQL resolvers. Return a structured list with file paths, endpoint URLs, HTTP methods, and descriptions."}},{description:"Plan authentication feature",params:{subagent_type:"Plan",description:"Plan user auth",prompt:"Create a detailed implementation plan for adding user authentication to this project. Analyze the existing architecture, then provide step-by-step instructions including: 1) Database schema changes 2) API routes to create 3) Frontend components needed 4) Security considerations 5) Testing strategy. Be specific about file names and code locations."}}]},async execute($,b){let{subagent_type:w,description:W,prompt:V,run_in_background:Q=!1,resume:Z,subagent_session_id:J}=$,{updateOutput:Y}=b,X=typeof J==="string"&&J.length>0?J:typeof Z==="string"&&Z.length>0?Z:l7();try{let O=W$.getAllNames(),G=W$.getSubagent(w);if(!G)return{success:!1,llmContent:`Unknown subagent type: ${w}. Available types: ${O.join(", ")||"none"}`,displayContent:`❌ 未知的 subagent 类型: ${w}
1522
1435
 
1523
- 可用类型: ${O.join(", ")||"无"}`,error:{type:"execution_error",message:`Unknown subagent type: ${w}`}};if(Z)return n6(Z,W,G,V,b);if(Q)return l6(G,V,W,b,X);if(J?.(`\uD83D\uDE80 启动 ${w} subagent: ${V}`),!b.bladeConfig)return{success:!1,llmContent:"BladeConfig is required for subagent execution",displayContent:"❌ 缺少 BladeConfig 配置",error:{type:"execution_error",message:"BladeConfig is required"}};let B=new r1(G,b.bladeConfig),q={prompt:W,parentSessionId:b.sessionId,permissionMode:b.permissionMode,subagentSessionId:X};J?.("⚙️ 执行任务中...");let U=Date.now(),K=await B.execute(q),_=Date.now()-U;try{let H=await m.getInstance().executeSubagentStopHooks(w,{projectDir:process.cwd(),sessionId:b.sessionId||"unknown",permissionMode:b.permissionMode||v.DEFAULT,taskDescription:V,success:K.success,resultSummary:K.message.slice(0,500),error:K.error});if(!H.shouldStop&&H.continueReason){console.log(`[Task] SubagentStop hook 阻止停止,继续执行: ${H.continueReason}`);let F={prompt:H.continueReason,parentSessionId:b.sessionId,permissionMode:b.permissionMode},M=Date.now();K=await B.execute(F),_+=Date.now()-M}if(H.warning)console.warn(`[Task] SubagentStop hook warning: ${H.warning}`)}catch(C){console.warn("[Task] SubagentStop hook execution failed:",C)}if(K.success){let C=K.message.length>1000?K.message.slice(0,1000)+`
1524
- ...(截断)`:K.message;return{success:!0,llmContent:K.message,displayContent:`✅ Subagent 任务完成
1436
+ 可用类型: ${O.join(", ")||"无"}`,error:{type:"execution_error",message:`Unknown subagent type: ${w}`}};if(Z)return t7(Z,V,G,W,b);if(Q)return o7(G,W,V,b,X);if(Y?.(`\uD83D\uDE80 启动 ${w} subagent: ${W}`),!b.bladeConfig)return{success:!1,llmContent:"BladeConfig is required for subagent execution",displayContent:"❌ 缺少 BladeConfig 配置",error:{type:"execution_error",message:"BladeConfig is required"}};let B=new m1(G,b.bladeConfig),K={prompt:V,parentSessionId:b.sessionId,permissionMode:b.permissionMode,subagentSessionId:X};Y?.("⚙️ 执行任务中...");let C=Date.now(),q=await B.execute(K),F=Date.now()-C;try{let H=await c.getInstance().executeSubagentStopHooks(w,{projectDir:process.cwd(),sessionId:b.sessionId||"unknown",permissionMode:b.permissionMode??z.DEFAULT,taskDescription:W,success:q.success,resultSummary:q.message.slice(0,500),error:q.error});if(!H.shouldStop&&H.continueReason){console.log(`[Task] SubagentStop hook 阻止停止,继续执行: ${H.continueReason}`);let R={prompt:H.continueReason,parentSessionId:b.sessionId,permissionMode:b.permissionMode},T=Date.now();q=await B.execute(R),F+=Date.now()-T}if(H.warning)console.warn(`[Task] SubagentStop hook warning: ${H.warning}`)}catch(U){console.warn("[Task] SubagentStop hook execution failed:",U)}if(q.success){let U=q.message.length>1000?q.message.slice(0,1000)+`
1437
+ ...(截断)`:q.message;return{success:!0,llmContent:q.message,displayContent:`✅ Subagent 任务完成
1525
1438
 
1526
1439
  `+`类型: ${w}
1527
- `+`任务: ${V}
1528
- Agent ID: ${K.agentId||"N/A"}
1529
- `+`耗时: ${_}ms
1530
- `+`工具调用: ${K.stats?.toolCalls||0} 次
1531
- `+`Token: ${K.stats?.tokens||0}
1440
+ `+`任务: ${W}
1441
+ Agent ID: ${q.agentId||"N/A"}
1442
+ `+`耗时: ${F}ms
1443
+ `+`工具调用: ${q.stats?.toolCalls||0} 次
1444
+ `+`Token: ${q.stats?.tokens||0}
1532
1445
 
1533
1446
  `+`结果:
1534
- ${C}`,metadata:{subagent_type:w,description:V,duration:_,stats:K.stats,subagentSessionId:X,subagentType:w,subagentStatus:"completed",subagentSummary:K.message.slice(0,500)}}}else return{success:!1,llmContent:`Subagent execution failed: ${K.error}`,displayContent:`⚠️ Subagent 任务失败
1447
+ ${U}`,metadata:{subagent_type:w,description:W,duration:F,stats:q.stats,subagentSessionId:X,subagentType:w,subagentStatus:"completed",subagentSummary:q.message.slice(0,500)}}}else return{success:!1,llmContent:`Subagent execution failed: ${q.error}`,displayContent:`⚠️ Subagent 任务失败
1535
1448
 
1536
1449
  `+`类型: ${w}
1537
- `+`任务: ${V}
1538
- Agent ID: ${K.agentId||"N/A"}
1539
- `+`耗时: ${_}ms
1540
- `+`错误: ${K.error}`,error:{type:"execution_error",message:K.error||"Unknown error"},metadata:{subagentSessionId:X,subagentType:w,subagentStatus:"failed"}}}catch(O){let G=O,B=g6(G);return{success:!1,llmContent:`Subagent execution error: ${G.message}`,displayContent:`❌ Subagent 执行异常
1450
+ `+`任务: ${W}
1451
+ Agent ID: ${q.agentId||"N/A"}
1452
+ `+`耗时: ${F}ms
1453
+ `+`错误: ${q.error}`,error:{type:"execution_error",message:q.error||"Unknown error"},metadata:{subagentSessionId:X,subagentType:w,subagentStatus:"failed"}}}catch(O){let G=n7(O instanceof Error?O:Error(_(O)));return{success:!1,llmContent:`Subagent execution error: ${_(O)}`,displayContent:`❌ Subagent 执行异常
1541
1454
 
1542
- ${B}`,error:{type:"execution_error",message:G.message,details:O}}}},version:"4.0.0",category:"Subagent",tags:["task","subagent","delegation","explore","plan"],extractSignatureContent:($)=>`${$.subagent_type}:${$.description}`,abstractPermissionRule:()=>""});function l6($,b,w,V,W){if(!V.bladeConfig)return{success:!1,llmContent:"BladeConfig is required for background agent execution",displayContent:"❌ 缺少 BladeConfig 配置",error:{type:"execution_error",message:"BladeConfig is required"}};let Z=E$.getInstance().startBackgroundAgent({config:$,bladeConfig:V.bladeConfig,description:b,prompt:w,parentSessionId:V.sessionId,permissionMode:V.permissionMode,agentId:W});return{success:!0,llmContent:{agent_id:Z,status:"running",message:`Agent started in background. Use TaskOutput(task_id: "${Z}") to retrieve results.`},displayContent:`\uD83D\uDE80 后台 Agent 已启动
1455
+ ${G}`,error:{type:"execution_error",message:_(O),details:O}}}},version:"4.0.0",category:"Subagent",tags:["task","subagent","delegation","explore","plan"],extractSignatureContent:($)=>`${$.subagent_type}:${$.description}`,abstractPermissionRule:()=>""});function o7($,b,w,W,V){if(!W.bladeConfig)return{success:!1,llmContent:"BladeConfig is required for background agent execution",displayContent:"❌ 缺少 BladeConfig 配置",error:{type:"execution_error",message:"BladeConfig is required"}};let Z=L$.getInstance().startBackgroundAgent({config:$,bladeConfig:W.bladeConfig,description:b,prompt:w,parentSessionId:W.sessionId,permissionMode:W.permissionMode,agentId:V});return{success:!0,llmContent:{agent_id:Z,status:"running",message:`Agent started in background. Use TaskOutput(task_id: "${Z}") to retrieve results.`},displayContent:`\uD83D\uDE80 后台 Agent 已启动
1543
1456
 
1544
1457
  `+`Agent ID: ${Z}
1545
1458
  `+`类型: ${$.name}
1546
1459
  `+`任务: ${b}
1547
1460
 
1548
- `+"\uD83D\uDCA1 使用 TaskOutput 工具获取结果",metadata:{agent_id:Z,subagent_type:$.name,description:b,background:!0,subagentSessionId:Z,subagentType:$.name,subagentStatus:"running"}}}function n6($,b,w,V,W){if(!W.bladeConfig)return{success:!1,llmContent:"BladeConfig is required for agent resume",displayContent:"❌ 缺少 BladeConfig 配置",error:{type:"execution_error",message:"BladeConfig is required"}};let Q=E$.getInstance();if(!Q.getAgent($))return{success:!1,llmContent:`Cannot resume agent ${$}: session not found`,displayContent:`❌ 无法恢复 Agent: ${$}
1461
+ `+"\uD83D\uDCA1 使用 TaskOutput 工具获取结果",metadata:{agent_id:Z,subagent_type:$.name,description:b,background:!0,subagentSessionId:Z,subagentType:$.name,subagentStatus:"running"}}}function t7($,b,w,W,V){if(!V.bladeConfig)return{success:!1,llmContent:"BladeConfig is required for agent resume",displayContent:"❌ 缺少 BladeConfig 配置",error:{type:"execution_error",message:"BladeConfig is required"}};let Q=L$.getInstance();if(!Q.getAgent($))return{success:!1,llmContent:`Cannot resume agent ${$}: session not found`,displayContent:`❌ 无法恢复 Agent: ${$}
1549
1462
 
1550
1463
  会话不存在或已过期`,error:{type:"execution_error",message:`Agent session not found: ${$}`}};if(Q.isRunning($))return{success:!1,llmContent:`Cannot resume agent ${$}: still running`,displayContent:`❌ 无法恢复 Agent: ${$}
1551
1464
 
1552
- Agent 仍在运行中,我会使用 TaskOutput 获取结果`,error:{type:"execution_error",message:`Agent is still running: ${$}`}};let Y=Q.resumeAgent($,b,w,W.bladeConfig,W.sessionId,W.permissionMode);if(!Y)return{success:!1,llmContent:`Failed to resume agent ${$}`,displayContent:`❌ 恢复 Agent 失败: ${$}`,error:{type:"execution_error",message:`Failed to resume agent: ${$}`}};return{success:!0,llmContent:{agent_id:Y,status:"running",resumed_from:$,message:`Agent resumed in background. Use TaskOutput(task_id: "${Y}") to retrieve results.`},displayContent:`\uD83D\uDD04 Agent 已恢复执行
1465
+ Agent 仍在运行中,我会使用 TaskOutput 获取结果`,error:{type:"execution_error",message:`Agent is still running: ${$}`}};let J=Q.resumeAgent($,b,w,V.bladeConfig,V.sessionId,V.permissionMode);if(!J)return{success:!1,llmContent:`Failed to resume agent ${$}`,displayContent:`❌ 恢复 Agent 失败: ${$}`,error:{type:"execution_error",message:`Failed to resume agent: ${$}`}};return{success:!0,llmContent:{agent_id:J,status:"running",resumed_from:$,message:`Agent resumed in background. Use TaskOutput(task_id: "${J}") to retrieve results.`},displayContent:`\uD83D\uDD04 Agent 已恢复执行
1553
1466
 
1554
- `+`Agent ID: ${Y}
1467
+ `+`Agent ID: ${J}
1555
1468
  `+`恢复自: ${$}
1556
1469
  `+`类型: ${w.name}
1557
- `+`任务: ${V}
1470
+ `+`任务: ${W}
1558
1471
 
1559
- `+"\uD83D\uDCA1 使用 TaskOutput 工具获取结果",metadata:{agent_id:Y,resumed_from:$,subagent_type:w.name,description:V,background:!0,subagentSessionId:Y,subagentType:w.name,subagentStatus:"running"}}}import{z as vb}from"zod";var $w=E({name:"TaskOutput",displayName:"Task Output",kind:"readonly",schema:vb.object({task_id:vb.string().min(1).describe("The task ID to get output from"),block:vb.boolean().default(!0).describe("Whether to wait for completion"),timeout:vb.number().min(0).max(600000).default(30000).describe("Max wait time in ms")}),description:{short:"Retrieves output from a running or completed task",long:`
1472
+ `+"\uD83D\uDCA1 使用 TaskOutput 工具获取结果",metadata:{agent_id:J,resumed_from:$,subagent_type:w.name,description:W,background:!0,subagentSessionId:J,subagentType:w.name,subagentStatus:"running"}}}import{z as Ib}from"zod";var Jw=L({name:"TaskOutput",displayName:"Task Output",kind:"readonly",schema:Ib.object({task_id:Ib.string().min(1).describe("The task ID to get output from"),block:Ib.boolean().default(!0).describe("Whether to wait for completion"),timeout:Ib.number().min(0).max(600000).default(30000).describe("Max wait time in ms")}),description:{short:"Retrieves output from a running or completed task",long:`
1560
1473
  - Retrieves output from a running or completed task (background shell, agent, or remote session)
1561
1474
  - Takes a task_id parameter identifying the task
1562
1475
  - Returns the task output along with status information
@@ -1564,11 +1477,11 @@ Agent 仍在运行中,我会使用 TaskOutput 获取结果`,error:{type:"execu
1564
1477
  - Use block=false for non-blocking check of current status
1565
1478
  - Task IDs can be found using the /tasks command
1566
1479
  - Works with all task types: background shells, async agents, and remote sessions
1567
- `.trim(),usageNotes:["task_id is required - the ID returned when starting a background task","block=true (default) waits for task completion","block=false returns current status immediately","timeout defaults to 30000ms (30 seconds), max 600000ms (10 minutes)"],examples:[{description:"Get output from a background shell",params:{task_id:"bash_abc123",block:!0,timeout:30000}},{description:"Check agent status without blocking",params:{task_id:"session_xyz789",block:!1}}]},async execute($,b){let{task_id:w,block:V,timeout:W}=$;if(w.startsWith("bash_"))return w2(w,V,W);let Q=O$.getInstance(),Z=E$.getInstance();if(Q.getProcess(w))return w2(w,V,W);if(Z.getAgent(w))return s6(w,V,W);return{success:!1,llmContent:`Unknown task ID: ${w}.`,displayContent:`❌ 未知的任务 ID: ${w}
1480
+ `.trim(),usageNotes:["task_id is required - the ID returned when starting a background task","block=true (default) waits for task completion","block=false returns current status immediately","timeout defaults to 30000ms (30 seconds), max 600000ms (10 minutes)"],examples:[{description:"Get output from a background shell",params:{task_id:"bash_abc123",block:!0,timeout:30000}},{description:"Check agent status without blocking",params:{task_id:"session_xyz789",block:!1}}]},async execute($,b){let{task_id:w,block:W,timeout:V}=$;if(w.startsWith("bash_"))return G2(w,W,V);let Q=X$.getInstance(),Z=L$.getInstance();if(Q.getProcess(w))return G2(w,W,V);if(Z.getAgent(w))return e7(w,W,V);return{success:!1,llmContent:`Unknown task ID: ${w}.`,displayContent:`❌ 未知的任务 ID: ${w}
1568
1481
 
1569
1482
  任务 ID 格式:
1570
1483
  - bash_xxx: 后台 shell
1571
- - agent: 后台 agent`,error:{type:"validation_error",message:`Unknown task ID: ${w}`}}},version:"1.0.0",category:"Task",tags:["task","output","background","shell","agent"],extractSignatureContent:($)=>$.task_id,abstractPermissionRule:()=>"*"});async function w2($,b,w){let V=O$.getInstance(),W=V.getProcess($);if(!W)return{success:!1,llmContent:`Shell not found: ${$}`,displayContent:`❌ 未找到 Shell: ${$}`,error:{type:"execution_error",message:"Shell 会话不存在或已清理"}};if(b&&W.status==="running")await r6($,w);let Q=V.consumeOutput($);if(!Q)return{success:!1,llmContent:`Failed to get output for shell: ${$}`,displayContent:`❌ 获取 Shell 输出失败: ${$}`,error:{type:"execution_error",message:"Failed to consume output"}};let Z={task_id:Q.id,type:"shell",status:Q.status,command:Q.command,pid:Q.pid,exit_code:Q.exitCode,signal:Q.signal,started_at:new Date(Q.startedAt).toISOString(),finished_at:Q.endedAt?new Date(Q.endedAt).toISOString():void 0,stdout:Q.stdout,stderr:Q.stderr},J=`${V2(Q.status)} TaskOutput(${$}) - Shell
1484
+ - agent: 后台 agent`,error:{type:"validation_error",message:`Unknown task ID: ${w}`}}},version:"1.0.0",category:"Task",tags:["task","output","background","shell","agent"],extractSignatureContent:($)=>$.task_id,abstractPermissionRule:()=>"*"});async function G2($,b,w){let W=X$.getInstance(),V=W.getProcess($);if(!V)return{success:!1,llmContent:`Shell not found: ${$}`,displayContent:`❌ 未找到 Shell: ${$}`,error:{type:"execution_error",message:"Shell 会话不存在或已清理"}};if(b&&V.status==="running")await $6($,w);let Q=W.consumeOutput($);if(!Q)return{success:!1,llmContent:`Failed to get output for shell: ${$}`,displayContent:`❌ 获取 Shell 输出失败: ${$}`,error:{type:"execution_error",message:"Failed to consume output"}};let Z={task_id:Q.id,type:"shell",status:Q.status,command:Q.command,pid:Q.pid,exit_code:Q.exitCode,signal:Q.signal,started_at:new Date(Q.startedAt).toISOString(),finished_at:Q.endedAt?new Date(Q.endedAt).toISOString():void 0,stdout:Q.stdout,stderr:Q.stderr},Y=`${B2(Q.status)} TaskOutput(${$}) - Shell
1572
1485
  `+`状态: ${Q.status}
1573
1486
  `+`命令: ${Q.command}
1574
1487
  `+(Q.pid?`PID: ${Q.pid}
@@ -1577,41 +1490,41 @@ Agent 仍在运行中,我会使用 TaskOutput 获取结果`,error:{type:"execu
1577
1490
  stdout:
1578
1491
  ${Q.stdout}`:"")+(Q.stderr?`
1579
1492
  stderr:
1580
- ${Q.stderr}`:"");return{success:!0,llmContent:Z,displayContent:J,metadata:Z}}async function s6($,b,w){let V=E$.getInstance(),W=V.getAgent($);if(!W)return{success:!1,llmContent:`Agent not found: ${$}`,displayContent:`❌ 未找到 Agent: ${$}`,error:{type:"execution_error",message:"Agent 会话不存在或已清理"}};if(b&&W.status==="running"){if(W=await V.waitForCompletion($,w),!W)return{success:!1,llmContent:`Failed to wait for agent: ${$}`,displayContent:`❌ 等待 Agent 失败: ${$}`,error:{type:"execution_error",message:"Wait for completion failed"}}}let Q={task_id:W.id,type:"agent",status:W.status,subagent_type:W.subagentType,description:W.description,created_at:new Date(W.createdAt).toISOString(),last_active_at:new Date(W.lastActiveAt).toISOString(),completed_at:W.completedAt?new Date(W.completedAt).toISOString():void 0,result:W.result,stats:W.stats},Z=W.status==="completed"?"completed":W.status==="failed"?"failed":"running",J=`${V2(W.status)} TaskOutput(${$}) - Agent
1581
- `+`状态: ${W.status}
1582
- `+`类型: ${W.subagentType}
1583
- `+`描述: ${W.description}
1584
- `+(W.stats?.duration?`耗时: ${W.stats.duration}ms
1585
- `:"")+(W.stats?.toolCalls?`工具调用: ${W.stats.toolCalls} 次
1586
- `:"")+(W.result?.message?`
1493
+ ${Q.stderr}`:"");return{success:!0,llmContent:Z,displayContent:Y,metadata:Z}}async function e7($,b,w){let W=L$.getInstance(),V=W.getAgent($);if(!V)return{success:!1,llmContent:`Agent not found: ${$}`,displayContent:`❌ 未找到 Agent: ${$}`,error:{type:"execution_error",message:"Agent 会话不存在或已清理"}};if(b&&V.status==="running"){if(V=await W.waitForCompletion($,w),!V)return{success:!1,llmContent:`Failed to wait for agent: ${$}`,displayContent:`❌ 等待 Agent 失败: ${$}`,error:{type:"execution_error",message:"Wait for completion failed"}}}let Q={task_id:V.id,type:"agent",status:V.status,subagent_type:V.subagentType,description:V.description,created_at:new Date(V.createdAt).toISOString(),last_active_at:new Date(V.lastActiveAt).toISOString(),completed_at:V.completedAt?new Date(V.completedAt).toISOString():void 0,result:V.result,stats:V.stats},Z=V.status==="completed"?"completed":V.status==="failed"?"failed":"running",Y=`${B2(V.status)} TaskOutput(${$}) - Agent
1494
+ `+`状态: ${V.status}
1495
+ `+`类型: ${V.subagentType}
1496
+ `+`描述: ${V.description}
1497
+ `+(V.stats?.duration?`耗时: ${V.stats.duration}ms
1498
+ `:"")+(V.stats?.toolCalls?`工具调用: ${V.stats.toolCalls} 次
1499
+ `:"")+(V.result?.message?`
1587
1500
  结果:
1588
- ${W.result.message}`:"")+(W.result?.error?`
1589
- 错误: ${W.result.error}`:"");return{success:!0,llmContent:Q,displayContent:J,metadata:{...Q,subagentSessionId:W.id,subagentType:W.subagentType,subagentStatus:Z,subagentSummary:typeof W.result?.message==="string"?W.result.message.slice(0,500):void 0}}}async function r6($,b){let w=O$.getInstance(),V=Date.now();return new Promise((W)=>{let Q=setInterval(()=>{let Z=w.getProcess($);if(!Z||Z.status!=="running"){clearInterval(Q),W();return}if(Date.now()-V>=b){clearInterval(Q),W();return}},100)})}function V2($){switch($){case"running":return"⏳";case"completed":case"exited":return"✅";case"failed":case"error":return"❌";case"killed":case"cancelled":return"✂️";default:return"❓"}}import{z as W2}from"zod";var a6=W2.object({serverName:W2.string().optional().describe("Optional: Filter resources by MCP server name. If not provided, lists resources from all connected servers.")}),Tb=E({name:"ListMcpResources",displayName:"List MCP Resources",kind:"readonly",description:{short:"List resources available from connected MCP servers",long:`Lists all resources provided by connected MCP (Model Context Protocol) servers.
1501
+ ${V.result.message}`:"")+(V.result?.error?`
1502
+ 错误: ${V.result.error}`:"");return{success:!0,llmContent:Q,displayContent:Y,metadata:{...Q,subagentSessionId:V.id,subagentType:V.subagentType,subagentStatus:Z,subagentSummary:typeof V.result?.message==="string"?V.result.message.slice(0,500):void 0}}}async function $6($,b){let w=X$.getInstance(),W=Date.now();return new Promise((V)=>{let Q=setInterval(()=>{let Z=w.getProcess($);if(!Z||Z.status!=="running"){clearInterval(Q),V();return}if(Date.now()-W>=b){clearInterval(Q),V();return}},100)})}function B2($){switch($){case"running":return"⏳";case"completed":case"exited":return"✅";case"failed":case"error":return"❌";case"killed":case"cancelled":return"✂️";default:return"❓"}}import{z as K2}from"zod";var b6=K2.object({serverName:K2.string().optional().describe("Optional: Filter resources by MCP server name. If not provided, lists resources from all connected servers.")});function Pb($){return L({name:"ListMcpResources",displayName:"List MCP Resources",kind:"readonly",description:{short:"List resources available from connected MCP servers",long:`Lists all resources provided by connected MCP (Model Context Protocol) servers.
1590
1503
  Resources can include files, database records, API endpoints, or any other data sources
1591
1504
  that MCP servers expose for reading.
1592
1505
 
1593
1506
  Use this tool to discover what resources are available before using ReadMcpResource to
1594
- access their contents.`,usageNotes:["List all resources: ListMcpResources({})",'List resources from specific server: ListMcpResources({ serverName: "my-server" })']},schema:a6,async execute($){try{let w=h.getInstance().getAllServers();if(w.size===0)return{success:!0,llmContent:"No MCP servers are currently connected.",displayContent:"No MCP servers connected",metadata:{resources:[],serverCount:0}};let V=[],W=[];for(let[Y,J]of w){if($.serverName&&Y!==$.serverName)continue;if(!J.client)continue;try{let X=await J.client.listResources(Y);for(let O of X)V.push({uri:O.uri,name:O.name,description:O.description,mimeType:O.mimeType,serverName:Y})}catch(X){W.push(`${Y}: ${X instanceof Error?X.message:String(X)}`)}}if(V.length===0){let Y=$.serverName?`No resources found from server "${$.serverName}".`:"No resources found from any connected MCP server.";return{success:!0,llmContent:Y+(W.length>0?`
1507
+ access their contents.`,usageNotes:["List all resources: ListMcpResources({})",'List resources from specific server: ListMcpResources({ serverName: "my-server" })']},schema:b6,async execute(b){try{let w=$.getAllServers();if(w.size===0)return{success:!0,llmContent:"No MCP servers are currently connected.",displayContent:"No MCP servers connected",metadata:{resources:[],serverCount:0}};let W=[],V=[];for(let[J,Y]of w){if(b.serverName&&J!==b.serverName)continue;if(!Y.client)continue;try{let X=await Y.client.listResources(J);for(let O of X)W.push({uri:O.uri,name:O.name,description:O.description,mimeType:O.mimeType,serverName:J})}catch(X){V.push(`${J}: ${X instanceof Error?X.message:String(X)}`)}}if(W.length===0){let J=b.serverName?`No resources found from server "${b.serverName}".`:"No resources found from any connected MCP server.";return{success:!0,llmContent:J+(V.length>0?`
1595
1508
 
1596
1509
  Errors:
1597
- ${W.join(`
1598
- `)}`:""),displayContent:Y,metadata:{resources:[],errors:W}}}let Q=V.map((Y)=>{let J=`- ${Y.uri} (${Y.name})`;if(Y.description)J+=`
1599
- ${Y.description}`;if(Y.mimeType)J+=`
1600
- Type: ${Y.mimeType}`;return J+=`
1601
- Server: ${Y.serverName}`,J}).join(`
1510
+ ${V.join(`
1511
+ `)}`:""),displayContent:J,metadata:{resources:[],errors:V}}}let Q=W.map((J)=>{let Y=`- ${J.uri} (${J.name})`;if(J.description)Y+=`
1512
+ ${J.description}`;if(J.mimeType)Y+=`
1513
+ Type: ${J.mimeType}`;return Y+=`
1514
+ Server: ${J.serverName}`,Y}).join(`
1602
1515
 
1603
- `),Z=`Found ${V.length} resource(s) from ${new Set(V.map((Y)=>Y.serverName)).size} server(s)`;return{success:!0,llmContent:`${Z}
1516
+ `),Z=`Found ${W.length} resource(s) from ${new Set(W.map((J)=>J.serverName)).size} server(s)`;return{success:!0,llmContent:`${Z}
1604
1517
 
1605
- ${Q}`,displayContent:Z,metadata:{resources:V,resourceCount:V.length,errors:W.length>0?W:void 0}}}catch(b){let w=b instanceof Error?b.message:String(b);return{success:!1,llmContent:`Failed to list MCP resources: ${w}`,displayContent:"Failed to list resources",error:{message:w,type:"execution_error"}}}}});import{z as bw}from"zod";var o6=bw.object({uri:bw.string().describe("The URI of the MCP resource to read"),serverName:bw.string().optional().describe("Optional: The name of the MCP server that provides this resource. If not provided, will search all connected servers.")}),kb=E({name:"ReadMcpResource",displayName:"Read MCP Resource",kind:"readonly",description:{short:"Read the contents of an MCP resource by URI",long:`Reads and returns the contents of a resource from a connected MCP (Model Context Protocol) server.
1518
+ ${Q}`,displayContent:Z,metadata:{resources:W,resourceCount:W.length,errors:V.length>0?V:void 0}}}catch(w){let W=w instanceof Error?w.message:String(w);return{success:!1,llmContent:`Failed to list MCP resources: ${W}`,displayContent:"Failed to list resources",error:{message:W,type:"execution_error"}}}}})}import{z as Yw}from"zod";var w6=Yw.object({uri:Yw.string().describe("The URI of the MCP resource to read"),serverName:Yw.string().optional().describe("Optional: The name of the MCP server that provides this resource. If not provided, will search all connected servers.")});function hb($){return L({name:"ReadMcpResource",displayName:"Read MCP Resource",kind:"readonly",description:{short:"Read the contents of an MCP resource by URI",long:`Reads and returns the contents of a resource from a connected MCP (Model Context Protocol) server.
1606
1519
  Resources are identified by their URI, which can be obtained using the ListMcpResources tool.
1607
1520
 
1608
- The resource content can be text (returned as-is) or binary data (returned as base64-encoded blob).`,usageNotes:['Read a resource: ReadMcpResource({ uri: "file:///path/to/resource" })','Read from specific server: ReadMcpResource({ uri: "db://table/record", serverName: "database-server" })']},schema:o6,async execute($){try{let w=h.getInstance().getAllServers();if(w.size===0)return{success:!1,llmContent:"No MCP servers are currently connected.",displayContent:"No MCP servers connected",error:{message:"No MCP servers connected",type:"execution_error"}};let V=null,W=null,Q=[];for(let[J,X]of w){if($.serverName&&J!==$.serverName)continue;if(!X.client)continue;try{V=await X.client.readResource($.uri,J),W=J;break}catch(O){let G=O instanceof Error?O.message:String(O);if(!G.includes("not found")&&!G.includes("does not exist"))Q.push(`${J}: ${G}`)}}if(!V){let J=$.serverName?`Resource "${$.uri}" not found on server "${$.serverName}".`:`Resource "${$.uri}" not found on any connected MCP server.`;return{success:!1,llmContent:J+(Q.length>0?`
1521
+ The resource content can be text (returned as-is) or binary data (returned as base64-encoded blob).`,usageNotes:['Read a resource: ReadMcpResource({ uri: "file:///path/to/resource" })','Read from specific server: ReadMcpResource({ uri: "db://table/record", serverName: "database-server" })']},schema:w6,async execute(b){try{let w=$.getAllServers();if(w.size===0)return{success:!1,llmContent:"No MCP servers are currently connected.",displayContent:"No MCP servers connected",error:{message:"No MCP servers connected",type:"execution_error"}};let W=null,V=null,Q=[];for(let[Y,X]of w){if(b.serverName&&Y!==b.serverName)continue;if(!X.client)continue;try{W=await X.client.readResource(b.uri,Y),V=Y;break}catch(O){let G=O instanceof Error?O.message:String(O);if(!G.includes("not found")&&!G.includes("does not exist"))Q.push(`${Y}: ${G}`)}}if(!W){let Y=b.serverName?`Resource "${b.uri}" not found on server "${b.serverName}".`:`Resource "${b.uri}" not found on any connected MCP server.`;return{success:!1,llmContent:Y+(Q.length>0?`
1609
1522
 
1610
1523
  Errors:
1611
1524
  ${Q.join(`
1612
- `)}`:""),displayContent:"Resource not found",error:{message:J,type:"execution_error"}}}let Z,Y;if(V.text!==void 0)Z=`Read ${V.text.length} characters from ${$.uri}`,Y=V.text;else if(V.blob!==void 0)Z=`Read binary resource from ${$.uri} (base64 encoded)`,Y=`[Binary content, base64 encoded, ${V.blob.length} characters]
1525
+ `)}`:""),displayContent:"Resource not found",error:{message:Y,type:"execution_error"}}}let Z,J;if(W.text!==void 0)Z=`Read ${W.text.length} characters from ${b.uri}`,J=W.text;else if(W.blob!==void 0)Z=`Read binary resource from ${b.uri} (base64 encoded)`,J=`[Binary content, base64 encoded, ${W.blob.length} characters]
1613
1526
 
1614
- ${V.blob.slice(0,1000)}${V.blob.length>1000?"...":""}`;else Z=`Read resource from ${$.uri}`,Y=JSON.stringify(V,null,2);return{success:!0,llmContent:Y,displayContent:Z,metadata:{uri:$.uri,serverName:W,mimeType:V.mimeType,hasText:V.text!==void 0,hasBlob:V.blob!==void 0,contentLength:V.text?.length??V.blob?.length??0}}}catch(b){let w=b instanceof Error?b.message:String(b);return{success:!1,llmContent:`Failed to read MCP resource: ${w}`,displayContent:"Failed to read resource",error:{message:w,type:"execution_error"}}}}});import{z as Z2}from"zod";import{randomUUID as t6}from"crypto";import*as E0 from"fs/promises";import*as fb from"path";class Q0{static instances=new Map;todos=[];filePath;loaded=!1;constructor($,b){this.filePath=fb.join(b,"todos",`${$}-agent-${$}.json`)}static getInstance($,b){let w=`${$}-${b}`;if(!Q0.instances.has(w))Q0.instances.set(w,new Q0($,b));return Q0.instances.get(w)}validate($){if($.filter((w)=>w.status==="in_progress").length>1)return{valid:!1,error:"同时只能有一个任务处于 in_progress 状态"};return{valid:!0}}async updateTodos($){await this.ensureLoaded();let b=new Date().toISOString(),w=$.map((W)=>{let Q=W,Z=this.todos.find((Y)=>Y.id===Q.id||Y.content===W.content);return{...W,id:Q.id||Z?.id||t6(),priority:W.priority||Z?.priority||"medium",createdAt:Z?.createdAt||b,startedAt:W.status==="in_progress"&&!Z?.startedAt?b:Z?.startedAt,completedAt:W.status==="completed"&&!Z?.completedAt?b:Z?.completedAt}}),V=this.validate(w);if(!V.valid)throw Error(V.error);this.todos=w,await this.saveTodos()}getSortedTodos(){let $={completed:0,in_progress:1,pending:2},b={high:0,medium:1,low:2};return[...this.todos].sort((w,V)=>{let W=$[w.status]-$[V.status];if(W!==0)return W;return b[w.priority]-b[V.priority]})}getTodos(){return this.getSortedTodos()}async ensureLoaded(){if(!this.loaded)await this.loadTodos(),this.loaded=!0}async loadTodos(){try{let $=await E0.readFile(this.filePath,"utf-8");this.todos=JSON.parse($)}catch($){if($.code==="ENOENT")this.todos=[];else console.warn("加载 TODO 列表失败:",$),this.todos=[]}}async saveTodos(){try{await E0.mkdir(fb.dirname(this.filePath),{recursive:!0,mode:493}),await E0.writeFile(this.filePath,JSON.stringify(this.todos,null,2),"utf-8")}catch($){throw console.error("保存 TODO 列表失败:",$),$}}}import{z as D0}from"zod";var Q2=D0.object({id:D0.string().optional(),content:D0.string().min(1,"Content cannot be empty"),status:D0.enum(["pending","in_progress","completed"]),activeForm:D0.string().min(1,"ActiveForm cannot be empty"),priority:D0.enum(["high","medium","low"]).default("medium")});function ww($){let{sessionId:b,configDir:w}=$;return E({name:"TodoWrite",displayName:"Todo Write",kind:"readonly",schema:Z2.object({todos:Z2.array(Q2).min(1,"At least one task is required")}),description:{short:"Use this tool to create and manage a structured task list for your current coding session",long:`Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
1527
+ ${W.blob.slice(0,1000)}${W.blob.length>1000?"...":""}`;else Z=`Read resource from ${b.uri}`,J=JSON.stringify(W,null,2);return{success:!0,llmContent:J,displayContent:Z,metadata:{uri:b.uri,serverName:V,mimeType:W.mimeType,hasText:W.text!==void 0,hasBlob:W.blob!==void 0,contentLength:W.text?.length??W.blob?.length??0}}}catch(w){let W=w instanceof Error?w.message:String(w);return{success:!1,llmContent:`Failed to read MCP resource: ${W}`,displayContent:"Failed to read resource",error:{message:W,type:"execution_error"}}}}})}import{z as A2}from"zod";import{randomUUID as W6}from"crypto";import*as j0 from"fs/promises";import*as xb from"path";class O0{static instances=new Map;todos=[];filePath;loaded=!1;constructor($,b){this.filePath=xb.join(b,"todos",`${$}-agent-${$}.json`)}static getInstance($,b){let w=`${$}-${b}`;if(!O0.instances.has(w))O0.instances.set(w,new O0($,b));return O0.instances.get(w)}validate($){if($.filter((w)=>w.status==="in_progress").length>1)return{valid:!1,error:"同时只能有一个任务处于 in_progress 状态"};return{valid:!0}}async updateTodos($){await this.ensureLoaded();let b=new Date().toISOString(),w=$.map((V)=>{let Q=this.todos.find((Z)=>Z.id===V.id||Z.content===V.content);return{...V,id:V.id||Q?.id||W6(),priority:V.priority||Q?.priority||"medium",createdAt:Q?.createdAt||b,startedAt:V.status==="in_progress"&&!Q?.startedAt?b:Q?.startedAt,completedAt:V.status==="completed"&&!Q?.completedAt?b:Q?.completedAt}}),W=this.validate(w);if(!W.valid)throw Error(W.error);this.todos=w,await this.saveTodos()}getSortedTodos(){let $={completed:0,in_progress:1,pending:2},b={high:0,medium:1,low:2};return[...this.todos].sort((w,W)=>{let V=$[w.status]-$[W.status];if(V!==0)return V;return b[w.priority]-b[W.priority]})}getTodos(){return this.getSortedTodos()}async ensureLoaded(){if(!this.loaded)await this.loadTodos(),this.loaded=!0}async loadTodos(){try{let $=await j0.readFile(this.filePath,"utf-8");this.todos=JSON.parse($)}catch($){if(n($)==="ENOENT")this.todos=[];else console.warn("加载 TODO 列表失败:",$),this.todos=[]}}async saveTodos(){try{await j0.mkdir(xb.dirname(this.filePath),{recursive:!0,mode:493}),await j0.writeFile(this.filePath,JSON.stringify(this.todos,null,2),"utf-8")}catch($){throw console.error("保存 TODO 列表失败:",$),$}}}import{z as N0}from"zod";var q2=N0.object({id:N0.string().optional(),content:N0.string().min(1,"Content cannot be empty"),status:N0.enum(["pending","in_progress","completed"]),activeForm:N0.string().min(1,"ActiveForm cannot be empty"),priority:N0.enum(["high","medium","low"]).default("medium")});function Xw($){let{sessionId:b,configDir:w}=$;return L({name:"TodoWrite",displayName:"Todo Write",kind:"readonly",schema:A2.object({todos:A2.array(q2).min(1,"At least one task is required")}),description:{short:"Use this tool to create and manage a structured task list for your current coding session",long:`Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
1615
1528
  It also helps the user understand the progress of the task and overall progress of their requests.
1616
1529
 
1617
1530
  ## When to Use This Tool
@@ -1672,9 +1585,9 @@ NOTE that you should not use this tool if there is only one trivial task to do.
1672
1585
  - activeForm: "Fixing authentication bug"
1673
1586
 
1674
1587
  When in doubt, use this tool. Being proactive with task management demonstrates attentiveness and ensures you complete all requirements successfully.
1675
- `},async execute(V,W){let{todos:Q}=V,{updateOutput:Z}=W;try{let Y=W.sessionId||b,J=Q0.getInstance(Y,w);Z?.("Updating TODO list..."),await J.updateTodos(Q);let X=J.getTodos(),O=e6(X),G=$V(X,O);return Z?.(`✅ TODO list updated (${O.completed}/${O.total} completed)`),{success:!0,llmContent:{todos:X,stats:O},displayContent:G,metadata:{stats:O}}}catch(Y){let J=Y;return{success:!1,llmContent:`Update failed: ${J.message}`,displayContent:`❌ 更新 TODO 列表失败: ${J.message}`,error:{type:"execution_error",message:J.message,details:Y}}}},version:"1.0.0",category:"TODO tools",tags:["todo","task","management","planning"],extractSignatureContent:(V)=>`${V.todos.length} todos`,abstractPermissionRule:()=>"*"})}function e6($){return{total:$.length,completed:$.filter((b)=>b.status==="completed").length,inProgress:$.filter((b)=>b.status==="in_progress").length,pending:$.filter((b)=>b.status==="pending").length}}function $V($,b){let w=[],V=b.total>0?Math.round(b.completed/b.total*100):0;if(w.push(`\uD83D\uDCCB TODO 列表 (${b.completed}/${b.total} 完成,${V}%)`),w.push(""),$.length===0)return w.push(" (暂无任务)"),w.join(`
1676
- `);for(let W of $){let Q=W.status==="completed"?"☑":"☐",Z=`(P${W.priority==="high"?0:W.priority==="medium"?1:2})`,Y=W.status==="in_progress"?" ⚡":"",J=W.status==="completed"?"~~":"";w.push(` ${Q} ${Z} ${J}${W.content}${J}${Y}`)}return w.join(`
1677
- `)}import{z as V$}from"zod";import{isPlainObject as Y2}from"lodash-es";function J2($){if(!Y2($))return;let b=$;return typeof b.name==="string"?b.name:void 0}function bV($){if($ instanceof Error)return $.message;if(typeof $==="string")return $;if(Y2($)){let b=$;if(typeof b.message==="string")return b.message}return String($)}var Ww=E({name:"WebFetch",displayName:"Web Fetch",kind:"readonly",schema:V$.object({url:V$.string().url().describe("URL to request"),method:V$.enum(["GET","POST","PUT","DELETE","HEAD"]).default("GET").describe("HTTP method"),extract_content:V$.boolean().default(!1).describe("Use Jina Reader to extract clean content in Markdown format. Removes HTML clutter, scripts, and styling, returning only the main content."),jina_options:V$.object({with_generated_alt:V$.boolean().default(!1).describe("Generate alt text for images"),with_links_summary:V$.boolean().default(!1).describe("Include summary of all links"),wait_for_selector:V$.string().optional().describe("Wait for specific CSS selector to load")}).optional().describe("Jina Reader advanced options (only used when extract_content is true)"),headers:V$.record(V$.string()).optional().describe("Request headers (optional)"),body:V$.string().optional().describe("Request body (optional)"),timeout:P.timeout(1000,120000,30000),follow_redirects:V$.boolean().default(!0).describe("Follow redirects"),max_redirects:V$.number().int().min(0).max(10).default(5).describe("Maximum redirect hops"),return_headers:V$.boolean().default(!1).describe("Return response headers")}),description:{short:"Fetches content from a specified URL and processes it using an AI model",long:`
1588
+ `},async execute(W,V){let{todos:Q}=W,{updateOutput:Z}=V;try{let J=V.sessionId||b,Y=O0.getInstance(J,w);Z?.("Updating TODO list..."),await Y.updateTodos(Q);let X=Y.getTodos(),O=V6(X),G=Q6(X,O);return Z?.(`✅ TODO list updated (${O.completed}/${O.total} completed)`),{success:!0,llmContent:{todos:X,stats:O},displayContent:G,metadata:{stats:O}}}catch(J){return{success:!1,llmContent:`Update failed: ${_(J)}`,displayContent:`❌ 更新 TODO 列表失败: ${_(J)}`,error:{type:"execution_error",message:_(J),details:J}}}},version:"1.0.0",category:"TODO tools",tags:["todo","task","management","planning"],extractSignatureContent:(W)=>`${W.todos.length} todos`,abstractPermissionRule:()=>"*"})}function V6($){return{total:$.length,completed:$.filter((b)=>b.status==="completed").length,inProgress:$.filter((b)=>b.status==="in_progress").length,pending:$.filter((b)=>b.status==="pending").length}}function Q6($,b){let w=[],W=b.total>0?Math.round(b.completed/b.total*100):0;if(w.push(`\uD83D\uDCCB TODO 列表 (${b.completed}/${b.total} 完成,${W}%)`),w.push(""),$.length===0)return w.push(" (暂无任务)"),w.join(`
1589
+ `);for(let V of $){let Q=V.status==="completed"?"☑":"☐",Z=`(P${V.priority==="high"?0:V.priority==="medium"?1:2})`,J=V.status==="in_progress"?" ⚡":"",Y=V.status==="completed"?"~~":"";w.push(` ${Q} ${Z} ${Y}${V.content}${Y}${J}`)}return w.join(`
1590
+ `)}import{z as V$}from"zod";var Gw=L({name:"WebFetch",displayName:"Web Fetch",kind:"readonly",schema:V$.object({url:V$.string().url().describe("URL to request"),method:V$.enum(["GET","POST","PUT","DELETE","HEAD"]).default("GET").describe("HTTP method"),extract_content:V$.boolean().default(!1).describe("Use Jina Reader to extract clean content in Markdown format. Removes HTML clutter, scripts, and styling, returning only the main content."),jina_options:V$.object({with_generated_alt:V$.boolean().default(!1).describe("Generate alt text for images"),with_links_summary:V$.boolean().default(!1).describe("Include summary of all links"),wait_for_selector:V$.string().optional().describe("Wait for specific CSS selector to load")}).optional().describe("Jina Reader advanced options (only used when extract_content is true)"),headers:V$.record(V$.string()).optional().describe("Request headers (optional)"),body:V$.string().optional().describe("Request body (optional)"),timeout:P.timeout(1000,120000,30000),follow_redirects:V$.boolean().default(!0).describe("Follow redirects"),max_redirects:V$.number().int().min(0).max(10).default(5).describe("Maximum redirect hops"),return_headers:V$.boolean().default(!1).describe("Return response headers")}),description:{short:"Fetches content from a specified URL and processes it using an AI model",long:`
1678
1591
  - Fetches content from a specified URL and processes it using an AI model
1679
1592
  - Takes a URL and a prompt as input
1680
1593
  - Fetches the URL content, converts HTML to markdown
@@ -1691,29 +1604,29 @@ Usage notes:
1691
1604
  - Results may be summarized if the content is very large
1692
1605
  - Includes a self-cleaning 15-minute cache for faster responses when repeatedly accessing the same URL
1693
1606
  - When a URL redirects to a different host, the tool will inform you and provide the redirect URL in a special format. You should then make a new WebFetch request with the redirect URL to fetch the content.
1694
- `},async execute($,b){let{url:w,method:V="GET",extract_content:W=!1,jina_options:Q,headers:Z={},body:Y,timeout:J=30000,follow_redirects:X=!0,max_redirects:O=5,return_headers:G=!1}=$,{updateOutput:B}=b,q=b.signal??new AbortController().signal;try{if(W)try{let H=Date.now(),F=await YV({url:w,jinaOptions:Q,timeout:J,signal:q,updateOutput:B}),M=Date.now()-H;if(F.response_time=M,!G)delete F.headers;let L={url:w,method:"GET",status:F.status,response_time:M,content_length:Buffer.byteLength(F.body||"","utf8"),redirected:F.redirected||!1,redirect_count:F.redirect_count??0,final_url:F.url,content_type:F.content_type,redirect_chain:F.redirect_chain};return{success:!0,llmContent:F,displayContent:Vw(F,L,!1),metadata:L}}catch{B?.("⚠️ Jina Reader 失败,使用标准方式获取")}B?.(`发送 ${V} 请求到: ${w}`);let U=Date.now(),K=await wV({url:w,method:V,headers:Z,body:Y,timeout:J,follow_redirects:X,max_redirects:O,signal:q}),_=Date.now()-U;if(K.response_time=_,!G)delete K.headers;let C={url:w,method:V,status:K.status,response_time:_,content_length:Buffer.byteLength(K.body||"","utf8"),redirected:K.redirected||!1,redirect_count:K.redirect_count??0,final_url:K.url,content_type:K.content_type,redirect_chain:K.redirect_chain};if(K.status>=400)return{success:!1,llmContent:`HTTP error ${K.status}: ${K.status_text}`,displayContent:Vw(K,C,!0),error:{type:"execution_error",message:`HTTP error ${K.status}: ${K.status_text}`,details:{...C,response_body:K.body}},metadata:C};return{success:!0,llmContent:K,displayContent:Vw(K,C,!1),metadata:C}}catch(U){if(J2(U)==="AbortError")return{success:!1,llmContent:"Request aborted",displayContent:"⚠️ 请求被用户中止",error:{type:"execution_error",message:"操作被中止"}};let K=bV(U);return{success:!1,llmContent:`Network request failed: ${K}`,displayContent:`❌ 网络请求失败: ${K}`,error:{type:"execution_error",message:K,details:U}}}},version:"2.0.0",category:"网络工具",tags:["web","http","fetch","request","api"],extractSignatureContent:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return $.url}},abstractPermissionRule:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return"*"}}});async function wV($){let{url:b,method:w,headers:V,body:W,timeout:Q,follow_redirects:Z,max_redirects:Y,signal:J}=$,X={"User-Agent":"Blade-AI/1.0",...V},O=b,G=w,B=W,q=0,U=[];while(!0){let K={...X};if(B&&G!=="GET"&&G!=="HEAD"&&!ZV(K,"content-type"))K["Content-Type"]="application/json";let _=await X2(O,{method:G,headers:K,body:B&&G!=="GET"&&G!=="HEAD"?B:void 0,redirect:"manual"},Q,J),C=_.headers.get("location"),H=_.status>=300&&_.status<400,F=Z&&H&&C&&q<Y;if(H&&Z&&!C)throw Error(`收到状态码 ${_.status} 但响应缺少 Location 头`);if(H&&Z&&q>=Y)throw Error(`超过最大重定向次数 (${Y})`);if(F&&C){q++;let R=QV(C,O);if(U.push(`${_.status} → ${R}`),_.status===303||(_.status===301||_.status===302)&&G!=="GET"&&G!=="HEAD")G="GET",B=void 0;O=R;continue}let M=await _.text(),L=O2(_.headers);return{status:_.status,status_text:_.statusText,headers:L,body:M,url:_.url||O,redirected:q>0,redirect_count:q,redirect_chain:U,content_type:L["content-type"],response_time:0}}}function Vw($,b,w){let{url:V,method:W,status:Q,response_time:Z,content_length:Y}=b,J=w?`❌ ${W} ${V} - ${Q} ${$.status_text}`:`✅ ${W} ${V} - ${Q} ${$.status_text}`;if(J+=`
1695
- 响应时间: ${Z}ms`,J+=`
1696
- 内容长度: ${Y} 字节`,b.content_type)J+=`
1697
- Content-Type: ${b.content_type}`;if($.redirected&&b.final_url&&b.final_url!==V){if(J+=`
1698
- 最终URL: ${b.final_url}`,b.redirect_count)J+=`
1699
- 重定向次数: ${b.redirect_count}`}let X=VV($.body,$.content_type);if(X)J+=`
1607
+ `},async execute($,b){let{url:w,method:W="GET",extract_content:V=!1,jina_options:Q,headers:Z={},body:J,timeout:Y=30000,follow_redirects:X=!0,max_redirects:O=5,return_headers:G=!1}=$,{updateOutput:B}=b,K=b.signal??new AbortController().signal;try{if(V)try{let H=Date.now(),R=await G6({url:w,jinaOptions:Q,timeout:Y,signal:K,updateOutput:B}),T=Date.now()-H;if(R.response_time=T,!G)delete R.headers;let N={url:w,method:"GET",status:R.status,response_time:T,content_length:Buffer.byteLength(R.body||"","utf8"),redirected:R.redirected||!1,redirect_count:R.redirect_count??0,final_url:R.url,content_type:R.content_type,redirect_chain:R.redirect_chain};return{success:!0,llmContent:R,displayContent:Ow(R,N,!1),metadata:N}}catch{B?.("⚠️ Jina Reader 失败,使用标准方式获取")}B?.(`发送 ${W} 请求到: ${w}`);let C=Date.now(),q=await Z6({url:w,method:W,headers:Z,body:J,timeout:Y,follow_redirects:X,max_redirects:O,signal:K}),F=Date.now()-C;if(q.response_time=F,!G)delete q.headers;let U={url:w,method:W,status:q.status,response_time:F,content_length:Buffer.byteLength(q.body||"","utf8"),redirected:q.redirected||!1,redirect_count:q.redirect_count??0,final_url:q.url,content_type:q.content_type,redirect_chain:q.redirect_chain};if(q.status>=400)return{success:!1,llmContent:`HTTP error ${q.status}: ${q.status_text}`,displayContent:Ow(q,U,!0),error:{type:"execution_error",message:`HTTP error ${q.status}: ${q.status_text}`,details:{...U,response_body:q.body}},metadata:U};return{success:!0,llmContent:q,displayContent:Ow(q,U,!1),metadata:U}}catch(C){if(d(C)==="AbortError")return{success:!1,llmContent:"Request aborted",displayContent:"⚠️ 请求被用户中止",error:{type:"execution_error",message:"操作被中止"}};let q=_(C);return{success:!1,llmContent:`Network request failed: ${q}`,displayContent:`❌ 网络请求失败: ${q}`,error:{type:"execution_error",message:q,details:C}}}},version:"2.0.0",category:"网络工具",tags:["web","http","fetch","request","api"],extractSignatureContent:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return $.url}},abstractPermissionRule:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return"*"}}});async function Z6($){let{url:b,method:w,headers:W,body:V,timeout:Q,follow_redirects:Z,max_redirects:J,signal:Y}=$,X={"User-Agent":"Blade-AI/1.0",...W},O=b,G=w,B=V,K=0,C=[];while(!0){let q={...X};if(B&&G!=="GET"&&G!=="HEAD"&&!O6(q,"content-type"))q["Content-Type"]="application/json";let F=await F2(O,{method:G,headers:q,body:B&&G!=="GET"&&G!=="HEAD"?B:void 0,redirect:"manual"},Q,Y),U=F.headers.get("location"),H=F.status>=300&&F.status<400,R=Z&&H&&U&&K<J;if(H&&Z&&!U)throw Error(`收到状态码 ${F.status} 但响应缺少 Location 头`);if(H&&Z&&K>=J)throw Error(`超过最大重定向次数 (${J})`);if(R&&U){K++;let D=X6(U,O);if(C.push(`${F.status} → ${D}`),F.status===303||(F.status===301||F.status===302)&&G!=="GET"&&G!=="HEAD")G="GET",B=void 0;O=D;continue}let T=await F.text(),N=C2(F.headers);return{status:F.status,status_text:F.statusText,headers:N,body:T,url:F.url||O,redirected:K>0,redirect_count:K,redirect_chain:C,content_type:N["content-type"],response_time:0}}}function Ow($,b,w){let{url:W,method:V,status:Q,response_time:Z,content_length:J}=b,Y=w?`❌ ${V} ${W} - ${Q} ${$.status_text}`:`✅ ${V} ${W} - ${Q} ${$.status_text}`;if(Y+=`
1608
+ 响应时间: ${Z}ms`,Y+=`
1609
+ 内容长度: ${J} 字节`,b.content_type)Y+=`
1610
+ Content-Type: ${b.content_type}`;if($.redirected&&b.final_url&&b.final_url!==W){if(Y+=`
1611
+ 最终URL: ${b.final_url}`,b.redirect_count)Y+=`
1612
+ 重定向次数: ${b.redirect_count}`}let X=J6($.body,$.content_type);if(X)Y+=`
1700
1613
  响应内容:
1701
- ${X}`;return J}function VV($,b){if(!$)return"(空响应)";if(WV(b,$))return"[binary content omitted]";let w=$.trim();if(!w)return"(仅包含空白字符)";return w.length>800?`${w.slice(0,800)}...`:w}function WV($,b){if($){let W=$.toLowerCase();if(["image/","audio/","video/","application/pdf","application/zip","application/octet-stream"].some((Z)=>W.startsWith(Z)))return!0}if(!b)return!1;let w=0,V=Math.min(b.length,200);for(let W=0;W<V;W++){let Q=b.charCodeAt(W);if(Q===9||Q===10||Q===13)continue;if(Q<32||Q>126)w++}return w/(V||1)>0.3}async function X2($,b,w,V){let W=new AbortController,Q=setTimeout(()=>W.abort(),w),Z=()=>W.abort();V?.addEventListener("abort",Z);try{return await fetch($,{...b,signal:W.signal})}catch(Y){if(J2(Y)==="AbortError"){if(Y instanceof Error)throw Y.message="请求被中止或超时",Y;let J=Error("请求被中止或超时");throw J.name="AbortError",J}throw Y}finally{clearTimeout(Q),V?.removeEventListener("abort",Z)}}function QV($,b){try{return new URL($,b).toString()}catch{return $}}function O2($){let b={};return $.forEach((w,V)=>{b[V.toLowerCase()]=w}),b}function ZV($,b){let w=b.toLowerCase();return Object.keys($).some((V)=>V.toLowerCase()===w)}async function YV($){let{url:b,jinaOptions:w,timeout:V,signal:W,updateOutput:Q}=$,Z=`https://r.jina.ai/${encodeURIComponent(b)}`;Q?.(`\uD83D\uDD0D 使用 Jina Reader 提取内容: ${b}`);let Y={"User-Agent":"Blade-AI/1.0",Accept:"text/markdown"};if(w?.with_generated_alt)Y["X-With-Generated-Alt"]="true";if(w?.with_links_summary)Y["X-With-Links-Summary"]="true";if(w?.wait_for_selector)Y["X-Wait-For-Selector"]=w.wait_for_selector;try{let J=await X2(Z,{method:"GET",headers:Y},V,W);if(!J.ok)throw Error(`Jina Reader error: ${J.status} ${J.statusText}`);let X=await J.text(),O=JV(X);return Q?.(`✅ Jina Reader 成功提取内容 (${O.content.length} 字符)`),{status:J.status,status_text:J.statusText,headers:O2(J.headers),body:XV(O),url:O.sourceUrl||b,redirected:!1,redirect_count:0,content_type:"text/markdown",response_time:0}}catch(J){throw Q?.("⚠️ Jina Reader 失败,回退到直接获取"),J}}function JV($){let b=$.split(`
1702
- `),w="",V="",W=0;for(let Z=0;Z<b.length;Z++){let Y=b[Z];if(Y.startsWith("Title: "))w=Y.substring(7).trim();else if(Y.startsWith("URL Source: "))V=Y.substring(12).trim();else if(Y.startsWith("Markdown Content:")){W=Z+1;break}}let Q=b.slice(W).join(`
1703
- `).trim();return{title:w||"Untitled",sourceUrl:V||"",content:Q||$}}function XV($){let b="";if($.title)b+=`# ${$.title}
1614
+ ${X}`;return Y}function J6($,b){if(!$)return"(空响应)";if(Y6(b,$))return"[binary content omitted]";let w=$.trim();if(!w)return"(仅包含空白字符)";return w.length>800?`${w.slice(0,800)}...`:w}function Y6($,b){if($){let V=$.toLowerCase();if(["image/","audio/","video/","application/pdf","application/zip","application/octet-stream"].some((Z)=>V.startsWith(Z)))return!0}if(!b)return!1;let w=0,W=Math.min(b.length,200);for(let V=0;V<W;V++){let Q=b.charCodeAt(V);if(Q===9||Q===10||Q===13)continue;if(Q<32||Q>126)w++}return w/(W||1)>0.3}async function F2($,b,w,W){let V=new AbortController,Q=setTimeout(()=>V.abort(),w),Z=()=>V.abort();W?.addEventListener("abort",Z);try{return await fetch($,{...b,signal:V.signal})}catch(J){if(d(J)==="AbortError"){if(J instanceof Error)throw J.message="请求被中止或超时",J;let Y=Error("请求被中止或超时");throw Y.name="AbortError",Y}throw J}finally{clearTimeout(Q),W?.removeEventListener("abort",Z)}}function X6($,b){try{return new URL($,b).toString()}catch{return $}}function C2($){let b={};return $.forEach((w,W)=>{b[W.toLowerCase()]=w}),b}function O6($,b){let w=b.toLowerCase();return Object.keys($).some((W)=>W.toLowerCase()===w)}async function G6($){let{url:b,jinaOptions:w,timeout:W,signal:V,updateOutput:Q}=$,Z=`https://r.jina.ai/${encodeURIComponent(b)}`;Q?.(`\uD83D\uDD0D 使用 Jina Reader 提取内容: ${b}`);let J={"User-Agent":"Blade-AI/1.0",Accept:"text/markdown"};if(w?.with_generated_alt)J["X-With-Generated-Alt"]="true";if(w?.with_links_summary)J["X-With-Links-Summary"]="true";if(w?.wait_for_selector)J["X-Wait-For-Selector"]=w.wait_for_selector;try{let Y=await F2(Z,{method:"GET",headers:J},W,V);if(!Y.ok)throw Error(`Jina Reader error: ${Y.status} ${Y.statusText}`);let X=await Y.text(),O=B6(X);return Q?.(`✅ Jina Reader 成功提取内容 (${O.content.length} 字符)`),{status:Y.status,status_text:Y.statusText,headers:C2(Y.headers),body:K6(O),url:O.sourceUrl||b,redirected:!1,redirect_count:0,content_type:"text/markdown",response_time:0}}catch(Y){throw Q?.("⚠️ Jina Reader 失败,回退到直接获取"),Y}}function B6($){let b=$.split(`
1615
+ `),w="",W="",V=0;for(let Z=0;Z<b.length;Z++){let J=b[Z];if(J.startsWith("Title: "))w=J.substring(7).trim();else if(J.startsWith("URL Source: "))W=J.substring(12).trim();else if(J.startsWith("Markdown Content:")){V=Z+1;break}}let Q=b.slice(V).join(`
1616
+ `).trim();return{title:w||"Untitled",sourceUrl:W||"",content:Q||$}}function K6($){let b="";if($.title)b+=`# ${$.title}
1704
1617
 
1705
1618
  `;if($.sourceUrl)b+=`**Source**: ${$.sourceUrl}
1706
1619
 
1707
1620
  `;return b+=`---
1708
1621
 
1709
- `,b+=$.content,b}import{ProxyAgent as _V,fetch as RV}from"undici";import{z as L0}from"zod";import{LRUCache as G2}from"lru-cache";import OV from"node:crypto";class B2{cache;config;hits=0;misses=0;constructor($){this.config={maxSize:$?.maxSize??100,ttl:$?.ttl??3600000,enabled:$?.enabled??!0},this.cache=new G2({max:this.config.maxSize,ttl:this.config.ttl,updateAgeOnGet:!0,updateAgeOnHas:!1})}generateKey($,b){let w=b.toLowerCase().trim(),V=OV.createHash("md5").update(w).digest("hex").substring(0,8);return`${$}:${V}`}get($,b){if(!this.config.enabled)return null;let w=this.generateKey($,b),V=this.cache.get(w);if(!V)return this.misses++,null;if(Date.now()>V.expiresAt)return this.cache.delete(w),this.misses++,null;return this.hits++,V.results}set($,b,w){if(!this.config.enabled||w.length===0)return;let V=this.generateKey($,b),W=Date.now(),Q={query:b,provider:$,results:w,timestamp:W,expiresAt:W+this.config.ttl};this.cache.set(V,Q)}clear(){this.cache.clear(),this.hits=0,this.misses=0}getStats(){let $=this.hits+this.misses,b=$>0?this.hits/$*100:0;return{size:this.cache.size,maxSize:this.config.maxSize,enabled:this.config.enabled,ttl:this.config.ttl,hits:this.hits,misses:this.misses,hitRate:Number.parseFloat(b.toFixed(2))}}cleanup(){let $=Date.now(),b=0;for(let[w,V]of this.cache.entries())if($>V.expiresAt)this.cache.delete(w),b++;return b}enable(){this.config.enabled=!0}disable(){this.config.enabled=!1}isEnabled(){return this.config.enabled}updateConfig($){if($.maxSize!==void 0&&$.maxSize!==this.config.maxSize){this.config.maxSize=$.maxSize;let b=Array.from(this.cache.entries());this.cache=new G2({max:this.config.maxSize,ttl:this.config.ttl,updateAgeOnGet:!0,updateAgeOnHas:!1});for(let[w,V]of b.slice(-this.config.maxSize))this.cache.set(w,V)}if($.ttl!==void 0)this.config.ttl=$.ttl;if($.enabled!==void 0)this.config.enabled=$.enabled}}var GV=new B2;function K2(){return GV}function BV($){return $.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'")}function q2($){let b=BV($).trim();if(!b.includes(" - "))return{title:b,snippet:b};let[w,...V]=b.split(" - "),W=w.trim(),Q=V.join(" - ").trim()||b;return{title:W,snippet:Q}}function a0($){try{let b=new URL($),w=b.pathname==="/"?"":b.pathname;return`${b.hostname}${w}`}catch{return $}}function o0($){try{return new URL($).hostname.toLowerCase()}catch{return""}}function KV($){if(!$.FirstURL||!$.Text)return null;let{title:b,snippet:w}=q2($.Text);return{title:b,snippet:w,url:$.FirstURL,display_url:a0($.FirstURL),source:o0($.FirstURL)}}function A2($){let b=[];for(let w of $){if(w.Topics&&w.Topics.length>0){b.push(...A2(w.Topics));continue}if(w.FirstURL&&w.Text){let{title:V,snippet:W}=q2(w.Text);b.push({title:V,snippet:W,url:w.FirstURL,display_url:a0(w.FirstURL),source:o0(w.FirstURL)})}}return b}function qV($){let b=$,w=(b.Results??[]).map((W)=>KV(W)).filter((W)=>W!==null),V=A2(b.RelatedTopics??[]);return[...w,...V]}var AV={name:"DuckDuckGo",endpoint:"https://duckduckgo.com/",buildUrl:($)=>{let b=new URL("https://duckduckgo.com/");return b.searchParams.set("q",$),b.searchParams.set("format","json"),b.searchParams.set("no_html","1"),b.searchParams.set("skip_disambig","1"),b.searchParams.set("t","blade-code"),b.searchParams.set("kl","us-en"),b.toString()},parseResponse:qV,getHeaders:()=>({Accept:"application/json, text/plain;q=0.9","User-Agent":"Blade-AI-WebSearch/1.0"})};function UV($){let b=$,w=[];for(let V of b.results??[]){if(!V.url||!V.title)continue;w.push({title:V.title,snippet:V.content||V.title,url:V.url,display_url:a0(V.url),source:o0(V.url)})}return w}var U2=["https://searx.be","https://search.ononoki.org","https://searx.tiekoetter.com","https://searx.work"];function CV($){return{name:`SearXNG(${(()=>{try{return new URL($).hostname}catch{return $}})()})`,endpoint:$,buildUrl:(w)=>{let V=new URL(`${$}/search`);return V.searchParams.set("q",w),V.searchParams.set("format","json"),V.searchParams.set("categories","general"),V.toString()},parseResponse:UV,getHeaders:()=>({Accept:"application/json","User-Agent":"Blade-AI-WebSearch/1.0"})}}var l$={BASE_URL:"https://mcp.exa.ai",ENDPOINT:"/mcp",DEFAULT_NUM_RESULTS:10,TIMEOUT:25000};function FV($){let b=[],w=$.split(`
1710
- `),V={};for(let W=0;W<w.length;W++){let Q=w[W].trim();if(Q.startsWith("Title: ")){if(V.title&&V.url)b.push({title:V.title,url:V.url,snippet:V.snippet||V.title,display_url:a0(V.url),source:o0(V.url)});V={title:Q.substring(7).trim(),snippet:""}}else if(Q.startsWith("URL: "))V.url=Q.substring(5).trim();else if(Q.startsWith("Text: ")){let Y=Q.substring(6).trim().replace(/<[^>]*>/g,"").replace(/\s+/g," ").trim();V.snippet=Y.substring(0,300)}}if(V.title&&V.url)b.push({title:V.title,url:V.url,snippet:V.snippet||V.title,display_url:a0(V.url),source:o0(V.url)});return b}function HV(){return{name:"Exa",endpoint:`${l$.BASE_URL}${l$.ENDPOINT}`,searchFn:async($)=>{let b={jsonrpc:"2.0",id:1,method:"tools/call",params:{name:"web_search_exa",arguments:{query:$,type:"auto",numResults:l$.DEFAULT_NUM_RESULTS,contextMaxCharacters:1e4}}},w=new AbortController,V=setTimeout(()=>w.abort(),l$.TIMEOUT);try{let W=await fetch(`${l$.BASE_URL}${l$.ENDPOINT}`,{method:"POST",headers:{accept:"application/json, text/event-stream","content-type":"application/json"},body:JSON.stringify(b),signal:w.signal});if(clearTimeout(V),!W.ok)throw Error(`MCP error (${W.status})`);let Z=(await W.text()).split(`
1711
- `);for(let Y of Z)if(Y.startsWith("data: ")){let J=JSON.parse(Y.substring(6));if(J.result&&J.result.content&&J.result.content.length>0)return FV(J.result.content[0].text)}throw Error("No search results found")}catch(W){if(clearTimeout(V),W.name==="AbortError")throw Error("MCP request timed out");throw W}},buildUrl:()=>`${l$.BASE_URL}${l$.ENDPOINT}`,parseResponse:()=>[],getHeaders:()=>({})}}function C2(){let $=[];return $.push(HV()),$.push(AV),$.push(...U2.map(CV)),$}function F2(){return 2+U2.length}var EV=15000,DV=8,t0={maxRetries:3,baseDelay:1000,maxDelay:8000};function LV(){let $=process.env.HTTPS_PROXY||process.env.HTTP_PROXY||process.env.https_proxy||process.env.http_proxy;if($)try{return new _V($)}catch(b){console.warn(`Invalid proxy URL: ${$}`)}return}async function jV($,b,w,V,W){let Q=new AbortController,Z=setTimeout(()=>Q.abort(),w),Y=()=>Q.abort();V?.addEventListener("abort",Y);try{return await RV($,{...b,signal:Q.signal,dispatcher:W})}catch(J){if(J.name==="AbortError")throw Error("搜索请求超时或被中止");throw J}finally{clearTimeout(Z),V?.removeEventListener("abort",Y)}}async function NV($,b,w,V,W,Q){let Z=null;for(let Y=0;Y<t0.maxRetries;Y++)try{return await jV($,b,w,V,W)}catch(J){if(Z=J,V?.aborted)throw J;if(Y<t0.maxRetries-1){let X=Math.min(t0.baseDelay*2**Y,t0.maxDelay);Q?.(`⏳ 请求失败,${X/1000}s 后重试 (${Y+1}/${t0.maxRetries})...`),await new Promise((O)=>setTimeout(O,X))}}throw Z}async function SV($,b,w,V,W,Q){let Z=K2(),Y=Z.get($.name,b);if(Y)return Q?.(`\uD83D\uDCBE 使用缓存结果 (${$.name})`),{results:Y,providerName:`${$.name} (cached)`};if($.searchFn)try{Q?.(`\uD83D\uDD0D 搜索中 (${$.name})...`);let _=await $.searchFn(b);return Z.set($.name,b,_),{results:_,providerName:$.name}}catch(_){throw Error(`SDK search failed: ${_.message}`)}Q?.(`\uD83D\uDD0D 搜索中 (${$.name})...`);let J=$.buildUrl(b),X=$.method||"GET",G={headers:$.getHeaders(),method:X};if(X==="POST"&&$.buildBody)G.body=JSON.stringify($.buildBody(b));let B=await NV(J,G,w,V,W,Q);if(!B.ok)throw Error(`HTTP ${B.status}`);let q=await B.text(),U;try{U=JSON.parse(q)}catch{throw Error("Failed to parse search result JSON")}let K=$.parseResponse(U);return Z.set($.name,b,K),{results:K,providerName:$.name}}async function MV($,b,w,V){let W=C2(),Q=LV(),Z=[];for(let Y=0;Y<W.length;Y++){let J=W[Y];if(w?.aborted)throw Error("搜索被用户中止");try{return V?.(`\uD83D\uDD0E 使用 ${J.name} 搜索...`),await SV(J,$,b,w,Q,V)}catch(X){let O=X,G=`${J.name}: ${O.message}`;if(Z.push(G),V?.(`⚠️ ${G}`),Y===W.length-1)throw Error(`所有搜索提供商都失败了:
1622
+ `,b+=$.content,b}import{ProxyAgent as N6,fetch as S6}from"undici";import{z as S0}from"zod";import{LRUCache as U2}from"lru-cache";import q6 from"node:crypto";class R2{cache;config;hits=0;misses=0;constructor($){this.config={maxSize:$?.maxSize??100,ttl:$?.ttl??3600000,enabled:$?.enabled??!0},this.cache=new U2({max:this.config.maxSize,ttl:this.config.ttl,updateAgeOnGet:!0,updateAgeOnHas:!1})}generateKey($,b){let w=b.toLowerCase().trim(),W=q6.createHash("md5").update(w).digest("hex").substring(0,8);return`${$}:${W}`}get($,b){if(!this.config.enabled)return null;let w=this.generateKey($,b),W=this.cache.get(w);if(!W)return this.misses++,null;if(Date.now()>W.expiresAt)return this.cache.delete(w),this.misses++,null;return this.hits++,W.results}set($,b,w){if(!this.config.enabled||w.length===0)return;let W=this.generateKey($,b),V=Date.now(),Q={query:b,provider:$,results:w,timestamp:V,expiresAt:V+this.config.ttl};this.cache.set(W,Q)}clear(){this.cache.clear(),this.hits=0,this.misses=0}getStats(){let $=this.hits+this.misses,b=$>0?this.hits/$*100:0;return{size:this.cache.size,maxSize:this.config.maxSize,enabled:this.config.enabled,ttl:this.config.ttl,hits:this.hits,misses:this.misses,hitRate:Number.parseFloat(b.toFixed(2))}}cleanup(){let $=Date.now(),b=0;for(let[w,W]of this.cache.entries())if($>W.expiresAt)this.cache.delete(w),b++;return b}enable(){this.config.enabled=!0}disable(){this.config.enabled=!1}isEnabled(){return this.config.enabled}updateConfig($){if($.maxSize!==void 0&&$.maxSize!==this.config.maxSize){this.config.maxSize=$.maxSize;let b=Array.from(this.cache.entries());this.cache=new U2({max:this.config.maxSize,ttl:this.config.ttl,updateAgeOnGet:!0,updateAgeOnHas:!1});for(let[w,W]of b.slice(-this.config.maxSize))this.cache.set(w,W)}if($.ttl!==void 0)this.config.ttl=$.ttl;if($.enabled!==void 0)this.config.enabled=$.enabled}}var A6=new R2;function H2(){return A6}function F6($){if(!$||typeof $!=="object")return!1;return!0}function C6($){return $.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'")}function _2($){let b=C6($).trim();if(!b.includes(" - "))return{title:b,snippet:b};let[w,...W]=b.split(" - "),V=w.trim(),Q=W.join(" - ").trim()||b;return{title:V,snippet:Q}}function $b($){try{let b=new URL($),w=b.pathname==="/"?"":b.pathname;return`${b.hostname}${w}`}catch{return $}}function bb($){try{return new URL($).hostname.toLowerCase()}catch{return""}}function U6($){if(!$.FirstURL||!$.Text)return null;let{title:b,snippet:w}=_2($.Text);return{title:b,snippet:w,url:$.FirstURL,display_url:$b($.FirstURL),source:bb($.FirstURL)}}function D2($){let b=[];for(let w of $){if(w.Topics&&w.Topics.length>0){b.push(...D2(w.Topics));continue}if(w.FirstURL&&w.Text){let{title:W,snippet:V}=_2(w.Text);b.push({title:W,snippet:V,url:w.FirstURL,display_url:$b(w.FirstURL),source:bb(w.FirstURL)})}}return b}function R6($){if(!F6($))return[];let b=$,w=(b.Results??[]).map((V)=>U6(V)).filter((V)=>V!==null),W=D2(b.RelatedTopics??[]);return[...w,...W]}var H6={name:"DuckDuckGo",endpoint:"https://duckduckgo.com/",buildUrl:($)=>{let b=new URL("https://duckduckgo.com/");return b.searchParams.set("q",$),b.searchParams.set("format","json"),b.searchParams.set("no_html","1"),b.searchParams.set("skip_disambig","1"),b.searchParams.set("t","blade-code"),b.searchParams.set("kl","us-en"),b.toString()},parseResponse:R6,getHeaders:()=>({Accept:"application/json, text/plain;q=0.9","User-Agent":"Blade-AI-WebSearch/1.0"})};function _6($){if(!$||typeof $!=="object")return!1;return!0}function D6($){if(!_6($))return[];let b=$,w=[];for(let W of b.results??[]){if(!W.url||!W.title)continue;w.push({title:W.title,snippet:W.content||W.title,url:W.url,display_url:$b(W.url),source:bb(W.url)})}return w}var L2=["https://searx.be","https://search.ononoki.org","https://searx.tiekoetter.com","https://searx.work"];function L6($){return{name:`SearXNG(${(()=>{try{return new URL($).hostname}catch{return $}})()})`,endpoint:$,buildUrl:(w)=>{let W=new URL(`${$}/search`);return W.searchParams.set("q",w),W.searchParams.set("format","json"),W.searchParams.set("categories","general"),W.toString()},parseResponse:D6,getHeaders:()=>({Accept:"application/json","User-Agent":"Blade-AI-WebSearch/1.0"})}}var r$={BASE_URL:"https://mcp.exa.ai",ENDPOINT:"/mcp",DEFAULT_NUM_RESULTS:10,TIMEOUT:25000};function E6($){let b=[],w=$.split(`
1623
+ `),W={};for(let V=0;V<w.length;V++){let Q=w[V].trim();if(Q.startsWith("Title: ")){if(W.title&&W.url)b.push({title:W.title,url:W.url,snippet:W.snippet||W.title,display_url:$b(W.url),source:bb(W.url)});W={title:Q.substring(7).trim(),snippet:""}}else if(Q.startsWith("URL: "))W.url=Q.substring(5).trim();else if(Q.startsWith("Text: ")){let J=Q.substring(6).trim().replace(/<[^>]*>/g,"").replace(/\s+/g," ").trim();W.snippet=J.substring(0,300)}}if(W.title&&W.url)b.push({title:W.title,url:W.url,snippet:W.snippet||W.title,display_url:$b(W.url),source:bb(W.url)});return b}function j6(){return{name:"Exa",endpoint:`${r$.BASE_URL}${r$.ENDPOINT}`,searchFn:async($)=>{let b={jsonrpc:"2.0",id:1,method:"tools/call",params:{name:"web_search_exa",arguments:{query:$,type:"auto",numResults:r$.DEFAULT_NUM_RESULTS,contextMaxCharacters:1e4}}},w=new AbortController,W=setTimeout(()=>w.abort(),r$.TIMEOUT);try{let V=await fetch(`${r$.BASE_URL}${r$.ENDPOINT}`,{method:"POST",headers:{accept:"application/json, text/event-stream","content-type":"application/json"},body:JSON.stringify(b),signal:w.signal});if(clearTimeout(W),!V.ok)throw Error(`MCP error (${V.status})`);let Z=(await V.text()).split(`
1624
+ `);for(let J of Z)if(J.startsWith("data: ")){let Y=JSON.parse(J.substring(6));if(Y.result&&Y.result.content&&Y.result.content.length>0)return E6(Y.result.content[0].text)}throw Error("No search results found")}catch(V){if(clearTimeout(W),d(V)==="AbortError")throw Error("MCP request timed out");throw V}},buildUrl:()=>`${r$.BASE_URL}${r$.ENDPOINT}`,parseResponse:()=>[],getHeaders:()=>({})}}function E2(){let $=[];return $.push(j6()),$.push(H6),$.push(...L2.map(L6)),$}function j2(){return 2+L2.length}var y6=15000,M6=8,wb={maxRetries:3,baseDelay:1000,maxDelay:8000};function z6(){let $=process.env.HTTPS_PROXY||process.env.HTTP_PROXY||process.env.https_proxy||process.env.http_proxy;if($)try{return new N6($)}catch(b){console.warn(`Invalid proxy URL: ${$}`)}return}async function v6($,b,w,W,V){let Q=new AbortController,Z=setTimeout(()=>Q.abort(),w),J=()=>Q.abort();W?.addEventListener("abort",J);try{return await S6($,{...b,signal:Q.signal,dispatcher:V})}catch(Y){if(d(Y)==="AbortError")throw Error("搜索请求超时或被中止");throw Y}finally{clearTimeout(Z),W?.removeEventListener("abort",J)}}async function T6($,b,w,W,V,Q){let Z=null;for(let J=0;J<wb.maxRetries;J++)try{return await v6($,b,w,W,V)}catch(Y){if(Z=Y instanceof Error?Y:Error(_(Y)),W?.aborted)throw Y;if(J<wb.maxRetries-1){let X=Math.min(wb.baseDelay*2**J,wb.maxDelay);Q?.(`⏳ 请求失败,${X/1000}s 后重试 (${J+1}/${wb.maxRetries})...`),await new Promise((O)=>setTimeout(O,X))}}throw Z}async function k6($,b,w,W,V,Q){let Z=H2(),J=Z.get($.name,b);if(J)return Q?.(`\uD83D\uDCBE 使用缓存结果 (${$.name})`),{results:J,providerName:`${$.name} (cached)`};if($.searchFn)try{Q?.(`\uD83D\uDD0D 搜索中 (${$.name})...`);let F=await $.searchFn(b);return Z.set($.name,b,F),{results:F,providerName:$.name}}catch(F){throw Error(`SDK search failed: ${_(F)}`)}Q?.(`\uD83D\uDD0D 搜索中 (${$.name})...`);let Y=$.buildUrl(b),X=$.method||"GET",G={headers:$.getHeaders(),method:X};if(X==="POST"&&$.buildBody)G.body=JSON.stringify($.buildBody(b));let B=await T6(Y,G,w,W,V,Q);if(!B.ok)throw Error(`HTTP ${B.status}`);let K=await B.text(),C;try{C=JSON.parse(K)}catch{throw Error("Failed to parse search result JSON")}let q=$.parseResponse(C);return Z.set($.name,b,q),{results:q,providerName:$.name}}async function f6($,b,w,W){let V=E2(),Q=z6(),Z=[];for(let J=0;J<V.length;J++){let Y=V[J];if(w?.aborted)throw Error("搜索被用户中止");try{return W?.(`\uD83D\uDD0E 使用 ${Y.name} 搜索...`),await k6(Y,$,b,w,Q,W)}catch(X){let O=`${Y.name}: ${_(X)}`;if(Z.push(O),W?.(`⚠️ ${O}`),J===V.length-1)throw Error(`所有搜索提供商都失败了:
1712
1625
  ${Z.join(`
1713
- `)}`)}}throw Error("No search providers available")}function yV($){try{return new URL($).hostname.toLowerCase()}catch{return null}}function zV($){return $.trim().toLowerCase()}function H2($){if(!$||$.length===0)return[];return $.map(zV).filter(Boolean)}function _2($,b){return $===b||$.endsWith(`.${b}`)}function vV($,b,w){return $.filter((V)=>{let W=yV(V.url);if(!W)return!1;if(w.length>0&&w.some((Q)=>_2(W,Q)))return!1;if(b.length>0&&!b.some((Q)=>_2(W,Q)))return!1;return!0})}function TV($,b,w,V){let W=`\uD83D\uDD0E WebSearch("${$}") via ${V} - 返回 ${b.length}/${w} 条结果`,Q=b.map((Z,Y)=>`${Y+1}. ${Z.title}
1626
+ `)}`)}}throw Error("No search providers available")}function I6($){try{return new URL($).hostname.toLowerCase()}catch{return null}}function P6($){return $.trim().toLowerCase()}function N2($){if(!$||$.length===0)return[];return $.map(P6).filter(Boolean)}function S2($,b){return $===b||$.endsWith(`.${b}`)}function h6($,b,w){return $.filter((W)=>{let V=I6(W.url);if(!V)return!1;if(w.length>0&&w.some((Q)=>S2(V,Q)))return!1;if(b.length>0&&!b.some((Q)=>S2(V,Q)))return!1;return!0})}function x6($,b,w,W){let V=`\uD83D\uDD0E WebSearch("${$}") via ${W} - 返回 ${b.length}/${w} 条结果`,Q=b.map((Z,J)=>`${J+1}. ${Z.title}
1714
1627
  ${Z.display_url}
1715
- ${Z.snippet}`);return[W,...Q].join(`
1716
- `)}function kV($){let b=$.trim().toLowerCase();return b.length>80?b.slice(0,80):b}var Qw=E({name:"WebSearch",displayName:"Web Search",kind:"readonly",schema:L0.object({query:L0.string().min(2,"Search query must be at least 2 characters").describe("Search query"),allowed_domains:L0.array(L0.string().min(1)).optional().describe("Return results only from these domains (optional)"),blocked_domains:L0.array(L0.string().min(1)).optional().describe("Exclude results from these domains (optional)")}),description:{short:"Search the web and use the results to inform responses",long:`
1628
+ ${Z.snippet}`);return[V,...Q].join(`
1629
+ `)}function p6($){let b=$.trim().toLowerCase();return b.length>80?b.slice(0,80):b}var Bw=L({name:"WebSearch",displayName:"Web Search",kind:"readonly",schema:S0.object({query:S0.string().min(2,"Search query must be at least 2 characters").describe("Search query"),allowed_domains:S0.array(S0.string().min(1)).optional().describe("Return results only from these domains (optional)"),blocked_domains:S0.array(S0.string().min(1)).optional().describe("Exclude results from these domains (optional)")}),description:{short:"Search the web and use the results to inform responses",long:`
1717
1630
  - Search the web and use the results to inform responses
1718
1631
  - Provides up-to-date information for current events and recent data
1719
1632
  - Returns search result information formatted as search result blocks, including links as markdown hyperlinks
@@ -1741,19 +1654,11 @@ Usage notes:
1741
1654
  IMPORTANT - Use the correct year in search queries:
1742
1655
  - You MUST use the current year when searching for recent information, documentation, or current events.
1743
1656
  - Example: If the user asks for "latest React docs", search for "React documentation 2025", NOT "React documentation 2024"
1744
- `},async execute($,b){let{query:w}=$,V=H2($.allowed_domains),W=H2($.blocked_domains),{updateOutput:Q}=b,Z=b.signal??new AbortController().signal;Q?.(`\uD83D\uDD0E Searching: "${w}" (${F2()} providers available)`);try{let{results:Y,providerName:J}=await MV(w,EV,Z,Q),X=vV(Y,V,W),O=X.slice(0,DV),G={query:w,results:O,provider:J,total_results:X.length,fetched_at:new Date().toISOString()},B={query:w,provider:J,fetched_at:G.fetched_at,total_results:X.length,returned_results:O.length,allowed_domains:V,blocked_domains:W};if(O.length===0)return{success:!0,llmContent:G,displayContent:`\uD83D\uDD0D WebSearch("${w}") via ${J} - 未找到匹配结果`,metadata:B};return{success:!0,llmContent:G,displayContent:TV(w,O,X.length,J),metadata:B}}catch(Y){let J=Y;return{success:!1,llmContent:`WebSearch call failed: ${J.message}`,displayContent:`❌ WebSearch 调用失败: ${J.message}`,error:{type:"execution_error",message:J.message,details:{query:w,allowedDomains:V,blockedDomains:W}}}}},version:"2.0.0",category:"网络工具",tags:["web","search","internet","news"],extractSignatureContent:($)=>`search:${kV($.query)}`,abstractPermissionRule:()=>"search:*"});async function fV(){try{return await h.getInstance().getAvailableTools()}catch($){return console.warn("MCP协议工具加载失败:",$),[]}}async function Zw($){let b=$?.sessionId||`session_${Date.now()}`,w=$?.configDir||E2.join(R2.homedir(),".blade"),V=[y1,M1,v1,Rb,P1,p1,u1,g1,Ww,Qw,e1,$w,ww({sessionId:b,configDir:w}),T1,f1,...t4,yb,s1,Tb,kb],W=await fV();return[...V,...W]}var IV=N("Agent"),PV=[/:\s*$/,/:\s*$/,/\.\.\.\s*$/,/让我(先|来|开始|查看|检查|修复)/,/Let me (first|start|check|look|fix)/i],D2="请执行你提到的操作,不要只是描述。";function hV($){return PV.some((b)=>b.test($))}function xV($){return $.slice(-10).filter((b)=>b.role==="user"&&b.content===D2).length}async function*Yw($){let{chatService:b,streamHandler:w,executionPipeline:V,tools:W,messages:Q,maxTurns:Z,isYoloMode:Y,signal:J,permissionMode:X,maxContextTokens:O,executionContext:G}=$,B=100,q=Y?100:Z,U=Date.now(),K=0,_=[],C=0,H;yield{type:"agent_start"};while(!0){if(J?.aborted)return yield{type:"agent_end"},e0(K,_.length,U);if($.onBeforeTurn){let R=$.onBeforeTurn({turn:K,messages:Q,lastPromptTokens:H});while(!0){let{value:D,done:c}=await R.next();if(c)break;yield D}}if(K++,yield{type:"turn_start",turn:K,maxTurns:q},J?.aborted)return yield{type:"agent_end"},e0(K-1,_.length,U);let F;if(w){let R=w.streamResponse(Q,W,J);while(!0){let{value:D,done:c}=await R.next();if(c){F=D;break}if(D.type==="content_delta")yield{type:"content_delta",delta:D.delta};else yield{type:"thinking_delta",delta:D.delta}}}else F=await b.chat(Q,W,J);if(F.usage){if(F.usage.totalTokens)C+=F.usage.totalTokens;H=F.usage.promptTokens,yield{type:"token_usage",usage:{inputTokens:F.usage.promptTokens??0,outputTokens:F.usage.completionTokens??0,totalTokens:C,maxContextTokens:O}}}if(J?.aborted)return yield{type:"agent_end"},e0(K-1,_.length,U);if(F.reasoningContent&&!J?.aborted)yield{type:"thinking",content:F.reasoningContent};if(F.content?.trim()&&!J?.aborted)yield{type:"stream_end"};if(!F.toolCalls||F.toolCalls.length===0){let R=F.content||"";if(hV(R)&&xV(Q)<2){Q.push({role:"user",content:D2}),yield{type:"turn_end",turn:K,hasToolCalls:!1};continue}if($.onStopCheck){let D=await $.onStopCheck({content:R,turn:K});if(!D.shouldStop){let c=D.continueReason?`
1745
-
1746
- <system-reminder>
1747
- ${D.continueReason}
1748
- </system-reminder>`:`
1749
-
1750
- <system-reminder>
1751
- Please continue the conversation from where we left it off without asking the user any further questions. Continue with the last task that you were asked to work on.
1752
- </system-reminder>`;Q.push({role:"user",content:c}),yield{type:"turn_end",turn:K,hasToolCalls:!1};continue}}return await $.onComplete?.({content:R,turn:K}),yield{type:"turn_end",turn:K,hasToolCalls:!1},yield{type:"agent_end"},{success:!0,finalMessage:F.content,metadata:{turnsCount:K,toolCallsCount:_.length,duration:Date.now()-U,tokensUsed:C}}}Q.push({role:"assistant",content:F.content||"",reasoningContent:F.reasoningContent,tool_calls:F.toolCalls}),await $.onAssistantMessage?.({content:F.content||"",reasoningContent:F.reasoningContent,toolCalls:F.toolCalls,turn:K});let M=F.toolCalls.filter((R)=>R.type==="function");for(let R of M){let c=V.getRegistry().get(R.function.name)?.kind;yield{type:"tool_start",toolCall:R,toolKind:c}}if(J?.aborted)return yield{type:"agent_end"},e0(K,_.length,U);let L=await Promise.all(M.map((R)=>pV(R,V,G,$,J)));for(let{toolCall:R,result:D,toolUseUuid:c}of L){if(_.push(D),D.metadata?.shouldExitLoop){let l=typeof D.llmContent==="string"?D.llmContent:"循环已退出";return yield{type:"tool_result",toolCall:R,result:D},yield{type:"turn_end",turn:K,hasToolCalls:!0},yield{type:"agent_end"},{success:D.success,finalMessage:l,metadata:{turnsCount:K,toolCallsCount:_.length,duration:Date.now()-U,shouldExitLoop:!0,targetMode:D.metadata?.targetMode}}}yield{type:"tool_result",toolCall:R,result:D},await $.onAfterToolExec?.({toolCall:R,result:D,toolUseUuid:c});let y=D.success?D.llmContent||D.displayContent||"":D.error?.message||"执行失败";if(typeof y==="object"&&y!==null)y=JSON.stringify(y,null,2);Q.push({role:"tool",tool_call_id:R.id,name:R.function.name,content:typeof y==="string"?y:JSON.stringify(y)})}if(yield{type:"turn_end",turn:K,hasToolCalls:!0},J?.aborted)return yield{type:"agent_end"},e0(K,_.length,U);if(K>=q&&!Y){let R=await dV($,Q,K,_.length,U,C,H);if(R.action==="stop")return yield{type:"agent_end"},R.result;K=0;continue}}}function e0($,b,w){return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:$,toolCallsCount:b,duration:Date.now()-w}}}async function pV($,b,w,V,W){try{let Q=JSON.parse($.function.arguments);if($.function.name==="Task"&&(typeof Q.subagent_session_id!=="string"||Q.subagent_session_id.length===0)){let{nanoid:J}=await import("nanoid");Q.subagent_session_id=typeof Q.resume==="string"&&Q.resume.length>0?Q.resume:J()}if(Q.todos&&typeof Q.todos==="string")try{Q.todos=JSON.parse(Q.todos)}catch{}let Z=await V.onBeforeToolExec?.({toolCall:$,params:Q})??null,Y=await b.execute($.function.name,Q,{sessionId:w.sessionId,userId:w.userId,workspaceRoot:w.workspaceRoot,signal:W,confirmationHandler:w.confirmationHandler,permissionMode:V.permissionMode});return{toolCall:$,result:Y,toolUseUuid:Z}}catch(Q){return IV.error(`Tool execution failed for ${$.function.name}:`,Q),{toolCall:$,result:{success:!1,llmContent:"",displayContent:"",error:{type:"execution_error",message:Q instanceof Error?Q.message:"Unknown error"}},toolUseUuid:null}}}async function dV($,b,w,V,W,Q,Z){if($.onTurnLimitReached){if((await $.onTurnLimitReached({turnsCount:w}))?.continue){if($.onTurnLimitCompact){let J=await $.onTurnLimitCompact({messages:b,contextMessages:b.filter((X)=>X.role!=="system")});if(J.success&&J.compactedMessages){let X=b.find((O)=>O.role==="system");if(b.length=0,X)b.push(X);if(b.push(...J.compactedMessages),J.continueMessage)b.push(J.continueMessage)}}return{action:"continue",result:{success:!0,metadata:{turnsCount:w,toolCallsCount:V,duration:Date.now()-W}}}}return{action:"stop",result:{success:!0,metadata:{turnsCount:w,toolCallsCount:V,duration:Date.now()-W,tokensUsed:Q,configuredMaxTurns:$.maxTurns,actualMaxTurns:$.maxTurns}}}}return{action:"stop",result:{success:!1,error:{type:"max_turns_exceeded",message:`达到最大轮次限制 (${$.maxTurns})`},metadata:{turnsCount:w,toolCallsCount:V,duration:Date.now()-W,tokensUsed:Q}}}}import{EventEmitter as iV}from"events";import{nanoid as uV}from"nanoid";class Jw{name="hook";hookManager;constructor(){this.hookManager=m.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let b=$._internal.tool;if(!b)return;try{let w=$.context.messageId||`tool_${uV()}`;$._internal.hookToolUseId=w;let V=$.context.workspaceRoot||process.cwd(),W=await this.hookManager.executePreToolHooks(b.name,w,$.params,{projectDir:V,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode??v.DEFAULT,abortSignal:$.context.signal});if(W.decision==="deny"){$.abort(W.reason||"Hook blocked execution");return}if(W.decision==="ask"){$._internal.needsConfirmation=!0,$._internal.confirmationReason=W.reason||"Hook requires confirmation";return}if(W.modifiedInput){let Q={...$.params,...W.modifiedInput};if(b.build)try{b.build(Q),$.params=Q}catch(Z){$.abort(`Hook modified parameters are invalid: ${Z instanceof Error?Z.message:String(Z)}`);return}}if(W.warning)console.warn(`[Hook Warning] ${W.warning}`)}catch(w){console.error("[HookStage] Error executing hooks:",w)}}}import{nanoid as gV}from"nanoid";function mV($){return typeof $==="object"&&$!==null&&!Array.isArray($)}class Xw{name="post-hook";hookManager;constructor(){this.hookManager=m.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let b=$._internal.tool;if(!b)return;let w=$.getResult();if(!w)return;try{let V=$._internal.hookToolUseId||$.context.messageId||`tool_${gV()}`,W=$.context.workspaceRoot||process.cwd(),Q=await this.hookManager.executePostToolHooks(b.name,V,$.params,w,{projectDir:W,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode??v.DEFAULT,abortSignal:$.context.signal});if(Q.additionalContext){let Z=w.llmContent||w.displayContent||"";w.llmContent=`${Z}
1657
+ `},async execute($,b){let{query:w}=$,W=N2($.allowed_domains),V=N2($.blocked_domains),{updateOutput:Q}=b,Z=b.signal??new AbortController().signal;Q?.(`\uD83D\uDD0E Searching: "${w}" (${j2()} providers available)`);try{let{results:J,providerName:Y}=await f6(w,y6,Z,Q),X=h6(J,W,V),O=X.slice(0,M6),G={query:w,results:O,provider:Y,total_results:X.length,fetched_at:new Date().toISOString()},B={query:w,provider:Y,fetched_at:G.fetched_at,total_results:X.length,returned_results:O.length,allowed_domains:W,blocked_domains:V};if(O.length===0)return{success:!0,llmContent:G,displayContent:`\uD83D\uDD0D WebSearch("${w}") via ${Y} - 未找到匹配结果`,metadata:B};return{success:!0,llmContent:G,displayContent:x6(w,O,X.length,Y),metadata:B}}catch(J){return{success:!1,llmContent:`WebSearch call failed: ${_(J)}`,displayContent:`❌ WebSearch 调用失败: ${_(J)}`,error:{type:"execution_error",message:_(J),details:{query:w,allowedDomains:W,blockedDomains:V}}}}},version:"2.0.0",category:"网络工具",tags:["web","search","internet","news"],extractSignatureContent:($)=>`search:${p6($.query)}`,abstractPermissionRule:()=>"search:*"});async function d6($){try{return await $.getAvailableTools()}catch(b){return console.warn("MCP协议工具加载失败:",b),[]}}async function Kw($){let b=$?.sessionId||`session_${Date.now()}`,w=$?.configDir||M2.join(y2.homedir(),".blade"),W=[L1,D1,j1,jb,z1,k1,I1,P1,Gw,Bw,Zw,Jw,Xw({sessionId:b,configDir:w}),N1,y1,...Q2,kb,g1,...$?.mcpRegistry?[Pb($.mcpRegistry),hb($.mcpRegistry)]:[]],V=$?.mcpRegistry?await d6($.mcpRegistry):[];return[...W,...V]}import{EventEmitter as i6}from"events";import{nanoid as u6}from"nanoid";class qw{name="hook";hookManager;constructor(){this.hookManager=c.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let b=$._internal.tool;if(!b)return;try{let w=$.context.messageId||`tool_${u6()}`;$._internal.hookToolUseId=w;let W=$.context.workspaceRoot||process.cwd(),V=await this.hookManager.executePreToolHooks(b.name,w,$.params,{projectDir:W,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode??z.DEFAULT,abortSignal:$.context.signal});if(V.decision==="deny"){$.abort(V.reason||"Hook blocked execution");return}if(V.decision==="ask"){$._internal.needsConfirmation=!0,$._internal.confirmationReason=V.reason||"Hook requires confirmation";return}if(V.modifiedInput){let Q={...$.params,...V.modifiedInput};if(b.build)try{b.build(Q),$.params=Q}catch(Z){$.abort(`Hook modified parameters are invalid: ${Z instanceof Error?Z.message:String(Z)}`);return}}if(V.warning)console.warn(`[Hook Warning] ${V.warning}`)}catch(w){console.error("[HookStage] Error executing hooks:",w)}}}import{nanoid as g6}from"nanoid";function m6($){return typeof $==="object"&&$!==null&&!Array.isArray($)}class Aw{name="post-hook";hookManager;constructor(){this.hookManager=c.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let b=$._internal.tool;if(!b)return;let w=$.getResult();if(!w)return;try{let W=$._internal.hookToolUseId||$.context.messageId||`tool_${g6()}`,V=$.context.workspaceRoot||process.cwd(),Q=await this.hookManager.executePostToolHooks(b.name,W,$.params,w,{projectDir:V,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode??z.DEFAULT,abortSignal:$.context.signal});if(Q.additionalContext){let Z=w.llmContent||w.displayContent||"";w.llmContent=`${Z}
1753
1658
 
1754
1659
  ---
1755
1660
  **Hook Context:**
1756
- ${Q.additionalContext}`}if(Q.modifiedOutput!==void 0){let Z=Q.modifiedOutput;if(mV(Z))Object.assign(w,Z)}if(Q.warning)console.warn(`[PostToolUseHook Warning] ${Q.warning}`)}catch(V){console.error("[PostToolUseHookStage] Error executing post-tool hooks:",V)}}}var Ow=N("Execution");class n${static instance=null;locks=new Map;constructor(){}static getInstance(){if(!n$.instance)n$.instance=new n$;return n$.instance}async acquireLock($,b){let w=this.locks.get($);if(w)try{await w}catch{}let V=this.executeWithLock($,b);return this.locks.set($,V.then(()=>{return})),V}async executeWithLock($,b){Ow.debug(`获取文件锁: ${$}`);try{let w=await b();return Ow.debug(`释放文件锁: ${$}`),w}catch(w){throw Ow.debug(`操作失败,释放文件锁: ${$}`),w}}isLocked($){return this.locks.has($)}clearLock($){this.locks.delete($)}clearAll(){this.locks.clear()}getLockedFiles(){return Array.from(this.locks.keys())}getLockedFileCount(){return this.locks.size}static resetInstance(){n$.instance=null}}import cV from"node:os";import Gw from"node:path";class A${static SENSITIVE_PATTERNS=[{pattern:/^\.?id_rsa$/i,level:"high",description:"SSH 私钥"},{pattern:/^\.?id_ed25519$/i,level:"high",description:"SSH Ed25519 私钥"},{pattern:/^\.?id_ecdsa$/i,level:"high",description:"SSH ECDSA 私钥"},{pattern:/\.pem$/i,level:"high",description:"PEM 格式私钥"},{pattern:/\.key$/i,level:"high",description:"密钥文件"},{pattern:/\.p12$/i,level:"high",description:"PKCS#12 证书"},{pattern:/\.pfx$/i,level:"high",description:"PFX 证书"},{pattern:/^\.?keystore$/i,level:"high",description:"Java Keystore"},{pattern:/^\.?pgpass$/i,level:"high",description:"PostgreSQL 密码文件"},{pattern:/^\.?my\.cnf$/i,level:"high",description:"MySQL 配置文件(可能含密码)"},{pattern:/credentials\.json$/i,level:"high",description:"Google Cloud 凭证"},{pattern:/^\.?aws[\\/]credentials$/i,level:"high",description:"AWS 凭证"},{pattern:/^\.?gcp[\\/]credentials$/i,level:"high",description:"GCP 凭证"},{pattern:/^\.?azure[\\/]credentials$/i,level:"high",description:"Azure 凭证"},{pattern:/^service-account.*\.json$/i,level:"high",description:"服务账号密钥"},{pattern:/^\.env$/i,level:"medium",description:"环境变量文件"},{pattern:/^\.env\./i,level:"medium",description:"环境变量文件(带环境后缀)"},{pattern:/^\.?npmrc$/i,level:"medium",description:"npm 配置文件(可能含 token)"},{pattern:/^\.?pypirc$/i,level:"medium",description:"PyPI 配置文件(可能含密码)"},{pattern:/^\.?dockercfg$/i,level:"medium",description:"Docker 配置文件"},{pattern:/^\.?docker[\\/]config\.json$/i,level:"medium",description:"Docker 配置文件"},{pattern:/^\.?netrc$/i,level:"medium",description:"FTP/HTTP 认证文件"},{pattern:/^\.?git-credentials$/i,level:"medium",description:"Git 凭证文件"},{pattern:/^config\.toml$/i,level:"medium",description:"配置文件(可能含敏感信息)"},{pattern:/^secrets\./i,level:"medium",description:"密钥配置文件"},{pattern:/\.sqlite$/i,level:"low",description:"SQLite 数据库"},{pattern:/\.db$/i,level:"low",description:"数据库文件"},{pattern:/\.sql$/i,level:"low",description:"SQL 文件(可能含敏感数据)"}];static SENSITIVE_PATHS=[{path:/\.ssh[\\/]/i,level:"high",description:"SSH 配置目录"},{path:/\.aws[\\/]/i,level:"high",description:"AWS 配置目录"},{path:/\.config[\\/]gcloud[\\/]/i,level:"high",description:"Google Cloud 配置目录"},{path:/\.kube[\\/]/i,level:"high",description:"Kubernetes 配置目录"}];static check($){let b=A$.normalizePath($),w=Gw.basename(b);for(let V of A$.SENSITIVE_PATTERNS)if(A$.matchPattern(w,V.pattern))return{isSensitive:!0,level:V.level,matchedPattern:V.pattern instanceof RegExp?V.pattern.source:V.pattern,reason:V.description};for(let V of A$.SENSITIVE_PATHS)if(A$.matchPattern(b,V.path))return{isSensitive:!0,level:V.level,matchedPattern:V.path instanceof RegExp?V.path.source:V.path,reason:V.description};return{isSensitive:!1}}static checkMultiple($){let b=new Map;for(let w of $)b.set(w,A$.check(w));return b}static filterSensitive($,b="low"){let w={["high"]:3,["medium"]:2,["low"]:1},V=w[b];return $.map((W)=>({path:W,result:A$.check(W)})).filter(({result:W})=>W.isSensitive&&W.level&&w[W.level]>=V)}static normalizePath($){if($.startsWith("~/")||$==="~")return Gw.join(cV.homedir(),$.slice(1));return Gw.resolve($)}static matchPattern($,b){if(b instanceof RegExp)return b.test($);let w=b.replace(/\*/g,".*");return new RegExp(`^${w}$`,"i").test($)}static getSensitivePatterns(){return[...A$.SENSITIVE_PATTERNS]}static getSensitivePaths(){return[...A$.SENSITIVE_PATHS]}}class Ib{config;constructor($){this.config=$}static buildSignature($){if($.tool?.extractSignatureContent)return`${$.toolName}:${$.tool.extractSignatureContent($.params)}`;return $.toolName}static abstractPattern($){if($.tool?.abstractPermissionRule)return`${$.toolName}:${$.tool.abstractPermissionRule($.params)}`;return`${$.toolName}:*`}check($){let b=Ib.buildSignature($);if(this.config.deny?.some((w)=>this.matchRule(b,w)))return{result:"deny",matchedRule:"deny",reason:"Denied by permission rule"};if(this.config.allow?.some((w)=>this.matchRule(b,w)))return{result:"allow",matchedRule:"allow",reason:"Allowed by permission rule"};if(this.config.ask?.some((w)=>this.matchRule(b,w)))return{result:"ask",matchedRule:"ask",reason:"Requires user confirmation"};return{result:"ask",reason:"Default: requires user confirmation"}}replaceConfig($){this.config={...this.config,...$}}matchRule($,b){if(b==="*")return!0;if(b.endsWith("*"))return $.startsWith(b.slice(0,-1));return $===b}}var Z0=N("Execution");class Bw{registry;name="discovery";constructor($){this.registry=$}async process($){let b=this.registry.get($.toolName);if(!b){$.abort(`Tool "${$.toolName}" not found`);return}$._internal.tool=b}}class Kw{name="permission";permissionChecker;sessionApprovals;defaultPermissionMode;constructor($,b,w){this.permissionChecker=new Ib($),this.sessionApprovals=b,this.defaultPermissionMode=w}getPermissionChecker(){return this.permissionChecker}async process($){let b=$._internal.tool;if(!b){$.abort("Discovery stage failed; cannot perform permission check");return}try{let w=b.build($.params),V=w.getAffectedPaths(),W={toolName:b.name,params:$.params,affectedPaths:V,tool:b},Q=Ib.buildSignature(W);$._internal.permissionSignature=Q;let Z=this.permissionChecker.check(W),Y=$.context.permissionMode||this.defaultPermissionMode;switch(Z=this.applyModeOverrides(b.kind,Z,Y),Z.result){case"deny":$.abort(Z.reason||`Tool invocation "${b.name}" was denied by permission rules: ${Z.matchedRule}`);return;case"ask":if(this.sessionApprovals.has(Q))Z={result:"allow",matchedRule:"remembered:session",reason:"User already allowed this operation in this session"};else $._internal.needsConfirmation=!0,$._internal.confirmationReason=Z.reason||"User confirmation required";break;case"allow":break}if(V.length>0){let J=["/etc/","/sys/","/proc/","/dev/","/boot/","/root/","C:\\Windows\\System32","C:\\Program Files","C:\\ProgramData"],X=V.filter((G)=>{if(G.includes(".."))return!0;return J.some((B)=>G.includes(B))});if(X.length>0){$.abort(`Access to dangerous system paths denied: ${X.join(", ")}`);return}let O=A$.filterSensitive(V,"medium");if(O.length>0){let G=O.map(({path:q,result:U})=>`${q} (${U.level}: ${U.reason})`);if(O.filter(({result:q})=>q.level==="high").length>0&&Z.result!=="allow"){$.abort(`Access to highly sensitive files denied:
1661
+ ${Q.additionalContext}`}if(Q.modifiedOutput!==void 0){let Z=Q.modifiedOutput;if(m6(Z))Object.assign(w,Z)}if(Q.warning)console.warn(`[PostToolUseHook Warning] ${Q.warning}`)}catch(W){console.error("[PostToolUseHookStage] Error executing post-tool hooks:",W)}}}var Fw=E("Execution");class a${static instance=null;locks=new Map;constructor(){}static getInstance(){if(!a$.instance)a$.instance=new a$;return a$.instance}async acquireLock($,b){let w=this.locks.get($);if(w)try{await w}catch{}let W=this.executeWithLock($,b);return this.locks.set($,W.then(()=>{return})),W}async executeWithLock($,b){Fw.debug(`获取文件锁: ${$}`);try{let w=await b();return Fw.debug(`释放文件锁: ${$}`),w}catch(w){throw Fw.debug(`操作失败,释放文件锁: ${$}`),w}}isLocked($){return this.locks.has($)}clearLock($){this.locks.delete($)}clearAll(){this.locks.clear()}getLockedFiles(){return Array.from(this.locks.keys())}getLockedFileCount(){return this.locks.size}static resetInstance(){a$.instance=null}}import c6 from"node:os";import Cw from"node:path";class C${static SENSITIVE_PATTERNS=[{pattern:/^\.?id_rsa$/i,level:"high",description:"SSH 私钥"},{pattern:/^\.?id_ed25519$/i,level:"high",description:"SSH Ed25519 私钥"},{pattern:/^\.?id_ecdsa$/i,level:"high",description:"SSH ECDSA 私钥"},{pattern:/\.pem$/i,level:"high",description:"PEM 格式私钥"},{pattern:/\.key$/i,level:"high",description:"密钥文件"},{pattern:/\.p12$/i,level:"high",description:"PKCS#12 证书"},{pattern:/\.pfx$/i,level:"high",description:"PFX 证书"},{pattern:/^\.?keystore$/i,level:"high",description:"Java Keystore"},{pattern:/^\.?pgpass$/i,level:"high",description:"PostgreSQL 密码文件"},{pattern:/^\.?my\.cnf$/i,level:"high",description:"MySQL 配置文件(可能含密码)"},{pattern:/credentials\.json$/i,level:"high",description:"Google Cloud 凭证"},{pattern:/^\.?aws[\\/]credentials$/i,level:"high",description:"AWS 凭证"},{pattern:/^\.?gcp[\\/]credentials$/i,level:"high",description:"GCP 凭证"},{pattern:/^\.?azure[\\/]credentials$/i,level:"high",description:"Azure 凭证"},{pattern:/^service-account.*\.json$/i,level:"high",description:"服务账号密钥"},{pattern:/^\.env$/i,level:"medium",description:"环境变量文件"},{pattern:/^\.env\./i,level:"medium",description:"环境变量文件(带环境后缀)"},{pattern:/^\.?npmrc$/i,level:"medium",description:"npm 配置文件(可能含 token)"},{pattern:/^\.?pypirc$/i,level:"medium",description:"PyPI 配置文件(可能含密码)"},{pattern:/^\.?dockercfg$/i,level:"medium",description:"Docker 配置文件"},{pattern:/^\.?docker[\\/]config\.json$/i,level:"medium",description:"Docker 配置文件"},{pattern:/^\.?netrc$/i,level:"medium",description:"FTP/HTTP 认证文件"},{pattern:/^\.?git-credentials$/i,level:"medium",description:"Git 凭证文件"},{pattern:/^config\.toml$/i,level:"medium",description:"配置文件(可能含敏感信息)"},{pattern:/^secrets\./i,level:"medium",description:"密钥配置文件"},{pattern:/\.sqlite$/i,level:"low",description:"SQLite 数据库"},{pattern:/\.db$/i,level:"low",description:"数据库文件"},{pattern:/\.sql$/i,level:"low",description:"SQL 文件(可能含敏感数据)"}];static SENSITIVE_PATHS=[{path:/\.ssh[\\/]/i,level:"high",description:"SSH 配置目录"},{path:/\.aws[\\/]/i,level:"high",description:"AWS 配置目录"},{path:/\.config[\\/]gcloud[\\/]/i,level:"high",description:"Google Cloud 配置目录"},{path:/\.kube[\\/]/i,level:"high",description:"Kubernetes 配置目录"}];static check($){let b=C$.normalizePath($),w=Cw.basename(b);for(let W of C$.SENSITIVE_PATTERNS)if(C$.matchPattern(w,W.pattern))return{isSensitive:!0,level:W.level,matchedPattern:W.pattern instanceof RegExp?W.pattern.source:W.pattern,reason:W.description};for(let W of C$.SENSITIVE_PATHS)if(C$.matchPattern(b,W.path))return{isSensitive:!0,level:W.level,matchedPattern:W.path instanceof RegExp?W.path.source:W.path,reason:W.description};return{isSensitive:!1}}static checkMultiple($){let b=new Map;for(let w of $)b.set(w,C$.check(w));return b}static filterSensitive($,b="low"){let w={["high"]:3,["medium"]:2,["low"]:1},W=w[b];return $.map((V)=>({path:V,result:C$.check(V)})).filter(({result:V})=>V.isSensitive&&V.level&&w[V.level]>=W)}static normalizePath($){if($.startsWith("~/")||$==="~")return Cw.join(c6.homedir(),$.slice(1));return Cw.resolve($)}static matchPattern($,b){if(b instanceof RegExp)return b.test($);let w=b.replace(/\*/g,".*");return new RegExp(`^${w}$`,"i").test($)}static getSensitivePatterns(){return[...C$.SENSITIVE_PATTERNS]}static getSensitivePaths(){return[...C$.SENSITIVE_PATHS]}}function Wb($,b,w=""){let W=$[b];return typeof W==="string"?W:w}class pb{config;constructor($){this.config=$}static buildSignature($){if($.tool?.extractSignatureContent)return`${$.toolName}:${$.tool.extractSignatureContent($.params)}`;return $.toolName}static abstractPattern($){if($.tool?.abstractPermissionRule)return`${$.toolName}:${$.tool.abstractPermissionRule($.params)}`;return`${$.toolName}:*`}check($){let b=pb.buildSignature($);if(this.config.deny?.some((w)=>this.matchRule(b,w)))return{result:"deny",matchedRule:"deny",reason:"Denied by permission rule"};if(this.config.allow?.some((w)=>this.matchRule(b,w)))return{result:"allow",matchedRule:"allow",reason:"Allowed by permission rule"};if(this.config.ask?.some((w)=>this.matchRule(b,w)))return{result:"ask",matchedRule:"ask",reason:"Requires user confirmation"};return{result:"ask",reason:"Default: requires user confirmation"}}replaceConfig($){this.config={...this.config,...$}}matchRule($,b){if(b==="*")return!0;if(b.endsWith("*"))return $.startsWith(b.slice(0,-1));return $===b}}var G0=E("Execution");class Uw{registry;name="discovery";constructor($){this.registry=$}async process($){let b=this.registry.get($.toolName);if(!b){$.abort(`Tool "${$.toolName}" not found`);return}$._internal.tool=b}}class Rw{name="permission";permissionChecker;sessionApprovals;defaultPermissionMode;constructor($,b,w){this.permissionChecker=new pb($),this.sessionApprovals=b,this.defaultPermissionMode=w}getPermissionChecker(){return this.permissionChecker}async process($){let b=$._internal.tool;if(!b){$.abort("Discovery stage failed; cannot perform permission check");return}try{let w=b.build($.params),W=w.getAffectedPaths(),V={toolName:b.name,params:$.params,affectedPaths:W,tool:b},Q=pb.buildSignature(V);$._internal.permissionSignature=Q;let Z=this.permissionChecker.check(V),J=$.context.permissionMode||this.defaultPermissionMode;switch(Z=this.applyModeOverrides(b.kind,Z,J),Z.result){case"deny":$.abort(Z.reason||`Tool invocation "${b.name}" was denied by permission rules: ${Z.matchedRule}`);return;case"ask":if(this.sessionApprovals.has(Q))Z={result:"allow",matchedRule:"remembered:session",reason:"User already allowed this operation in this session"};else $._internal.needsConfirmation=!0,$._internal.confirmationReason=Z.reason||"User confirmation required";break;case"allow":break}if(W.length>0){let Y=["/etc/","/sys/","/proc/","/dev/","/boot/","/root/","C:\\Windows\\System32","C:\\Program Files","C:\\ProgramData"],X=W.filter((G)=>{if(G.includes(".."))return!0;return Y.some((B)=>G.includes(B))});if(X.length>0){$.abort(`Access to dangerous system paths denied: ${X.join(", ")}`);return}let O=C$.filterSensitive(W,"medium");if(O.length>0){let G=O.map(({path:K,result:C})=>`${K} (${C.level}: ${C.reason})`);if(O.filter(({result:K})=>K.level==="high").length>0&&Z.result!=="allow"){$.abort(`Access to highly sensitive files denied:
1757
1662
  ${G.join(`
1758
1663
  `)}
1759
1664
 
@@ -1761,115 +1666,200 @@ If access is required, add an explicit allow rule in permissions.`);return}if(Z.
1761
1666
  ${G.join(`
1762
1667
  `)}
1763
1668
 
1764
- Confirm to proceed?`,$._internal.needsConfirmation=!0}}$._internal.invocation=w,$._internal.permissionCheckResult=Z}catch(w){$.abort(`Permission check failed: ${w.message}`)}}applyModeOverrides($,b,w){if(w===v.YOLO)return{result:"allow",matchedRule:"mode:yolo",reason:"YOLO mode: automatically approve all tool invocations"};if(w===v.PLAN){if(!B0($))return{result:"deny",matchedRule:"mode:plan",reason:"Plan mode: modification tools are blocked; only read-only tools are allowed (Read/Glob/Grep/WebFetch/WebSearch/Task)"}}if(b.result==="deny")return b;if(b.result==="allow")return b;if(B0($))return{result:"allow",matchedRule:`mode:${w}:readonly`,reason:"Read-only tools do not require confirmation"};if(w===v.AUTO_EDIT&&$==="write")return{result:"allow",matchedRule:"mode:autoEdit:write",reason:"AUTO_EDIT mode: automatically approve write tools"};return b}}class qw{sessionApprovals;permissionChecker;canUseTool;name="confirmation";constructor($,b,w){this.sessionApprovals=$;this.permissionChecker=b;this.canUseTool=w}async process($){let{tool:b,invocation:w,needsConfirmation:V}=$._internal;if(!b||!w){$.abort("Pre-confirmation stage failed; cannot request user approval");return}let W=w.getAffectedPaths()||[];if(this.canUseTool){let Q=await this.canUseTool(b.name,$.params,{signal:$.context.signal||new AbortController().signal,toolKind:b.kind,affectedPaths:W});await this.handleCanUseToolResult(Q,$);return}if(!V)return;await this.handleLegacyConfirmation($,b,w,W)}async handleCanUseToolResult($,b){let{tool:w,invocation:V}=b._internal;switch($.behavior){case"allow":if($.updatedInput){if(Object.assign(b.params,$.updatedInput),w&&V)b._internal.invocation=w.build(b.params)}if($.updatedPermissions)this.applyPermissionUpdates($.updatedPermissions);Z0.debug(`canUseTool allowed: ${b.toolName}`);break;case"deny":b.abort($.message,{shouldExitLoop:$.interrupt});break;case"ask":if(b._internal.needsConfirmation=!0,w&&V)await this.handleLegacyConfirmation(b,w,V,V.getAffectedPaths()||[]);break}}applyPermissionUpdates($){for(let b of $)switch(b.type){case"addRules":for(let w of b.rules){let V=w.ruleContent?`${w.toolName}:${w.ruleContent}`:w.toolName;if(b.behavior==="allow")this.sessionApprovals.add(V);Z0.debug(`Permission rule added: ${V} -> ${b.behavior}`)}break;case"removeRules":for(let w of b.rules){let V=w.ruleContent?`${w.toolName}:${w.ruleContent}`:w.toolName;this.sessionApprovals.delete(V),Z0.debug(`Permission rule removed: ${V}`)}break}}async handleLegacyConfirmation($,b,w,V){let{confirmationReason:W,permissionCheckResult:Q}=$._internal;try{let Y={title:`权限确认: ${b.extractSignatureContent?b.extractSignatureContent($.params):b.name}`,message:W||"此操作需要用户确认",kind:b.kind,details:this.generatePreviewForTool(b.name,$.params),risks:this.extractRisksFromPermissionCheck(b,$.params,Q),affectedFiles:V};Z0.warn(`工具 "${b.name}" 需要用户确认: ${Y.title}`);let J=$.context.confirmationHandler;if(J){Z0.info(`[ConfirmationStage] Requesting confirmation for ${b.name}`);let X=await J.requestConfirmation(Y);if(Z0.info(`[ConfirmationStage] Confirmation response: approved=${X.approved}`),!X.approved){$.abort(`User rejected execution: ${X.reason||"No reason provided"}`,{shouldExitLoop:!0});return}if((X.scope||"once")==="session"&&$._internal.permissionSignature)this.sessionApprovals.add($._internal.permissionSignature)}else Z0.warn("⚠️ No ConfirmationHandler; auto-approving tool execution")}catch(Z){$.abort(`User confirmation failed: ${Z.message}`)}}generatePreviewForTool($,b){switch($){case"Edit":{let{old_string:w,new_string:V}=b;if(!w&&!V)return;let W=20,Q=(Z)=>{let Y=Z.split(`
1765
- `);if(Y.length<=W)return Z;return`${Y.slice(0,W).join(`
1669
+ Confirm to proceed?`,$._internal.needsConfirmation=!0}}$._internal.invocation=w,$._internal.permissionCheckResult=Z}catch(w){$.abort(`Permission check failed: ${_(w)}`)}}applyModeOverrides($,b,w){if(w===z.YOLO)return{result:"allow",matchedRule:"mode:yolo",reason:"YOLO mode: automatically approve all tool invocations"};if(w===z.PLAN){if(!F0($))return{result:"deny",matchedRule:"mode:plan",reason:"Plan mode: modification tools are blocked; only read-only tools are allowed (Read/Glob/Grep/WebFetch/WebSearch/Task)"}}if(b.result==="deny")return b;if(b.result==="allow")return b;if(F0($))return{result:"allow",matchedRule:`mode:${w}:readonly`,reason:"Read-only tools do not require confirmation"};if(w===z.AUTO_EDIT&&$==="write")return{result:"allow",matchedRule:"mode:autoEdit:write",reason:"AUTO_EDIT mode: automatically approve write tools"};return b}}class Hw{sessionApprovals;permissionChecker;canUseTool;name="confirmation";constructor($,b,w){this.sessionApprovals=$;this.permissionChecker=b;this.canUseTool=w}async process($){let{tool:b,invocation:w,needsConfirmation:W}=$._internal;if(!b||!w){$.abort("Pre-confirmation stage failed; cannot request user approval");return}let V=w.getAffectedPaths()||[];if(this.canUseTool){let Q=await this.canUseTool(b.name,$.params,{signal:$.context.signal||new AbortController().signal,toolKind:b.kind,affectedPaths:V});await this.handleCanUseToolResult(Q,$);return}if(!W)return;await this.handleLegacyConfirmation($,b,w,V)}async handleCanUseToolResult($,b){let{tool:w,invocation:W}=b._internal;switch($.behavior){case"allow":if($.updatedInput){if(Object.assign(b.params,$.updatedInput),w&&W)b._internal.invocation=w.build(b.params)}if($.updatedPermissions)this.applyPermissionUpdates($.updatedPermissions);G0.debug(`canUseTool allowed: ${b.toolName}`);break;case"deny":b.abort($.message,{shouldExitLoop:$.interrupt});break;case"ask":if(b._internal.needsConfirmation=!0,w&&W)await this.handleLegacyConfirmation(b,w,W,W.getAffectedPaths()||[]);break}}applyPermissionUpdates($){for(let b of $)switch(b.type){case"addRules":for(let w of b.rules){let W=w.ruleContent?`${w.toolName}:${w.ruleContent}`:w.toolName;if(b.behavior==="allow")this.sessionApprovals.add(W);G0.debug(`Permission rule added: ${W} -> ${b.behavior}`)}break;case"removeRules":for(let w of b.rules){let W=w.ruleContent?`${w.toolName}:${w.ruleContent}`:w.toolName;this.sessionApprovals.delete(W),G0.debug(`Permission rule removed: ${W}`)}break}}async handleLegacyConfirmation($,b,w,W){let{confirmationReason:V,permissionCheckResult:Q}=$._internal;try{let J={title:`权限确认: ${b.extractSignatureContent?b.extractSignatureContent($.params):b.name}`,message:V||"此操作需要用户确认",kind:b.kind,details:this.generatePreviewForTool(b.name,$.params),risks:this.extractRisksFromPermissionCheck(b,$.params,Q),affectedFiles:W};G0.warn(`工具 "${b.name}" 需要用户确认: ${J.title}`);let Y=$.context.confirmationHandler;if(Y){G0.info(`[ConfirmationStage] Requesting confirmation for ${b.name}`);let X=await Y.requestConfirmation(J);if(G0.info(`[ConfirmationStage] Confirmation response: approved=${X.approved}`),!X.approved){$.abort(`User rejected execution: ${X.reason||"No reason provided"}`,{shouldExitLoop:!0});return}if((X.scope||"once")==="session"&&$._internal.permissionSignature)this.sessionApprovals.add($._internal.permissionSignature)}else G0.warn("⚠️ No ConfirmationHandler; auto-approving tool execution")}catch(Z){$.abort(`User confirmation failed: ${_(Z)}`)}}generatePreviewForTool($,b){switch($){case"Edit":{let w=Wb(b,"old_string"),W=Wb(b,"new_string");if(!w&&!W)return;let V=20,Q=(Z)=>{let J=Z.split(`
1670
+ `);if(J.length<=V)return Z;return`${J.slice(0,V).join(`
1766
1671
  `)}
1767
- ... (还有 ${Y.length-W} 行)`};return`**变更前:**
1672
+ ... (还有 ${J.length-V} 行)`};return`**变更前:**
1768
1673
  \`\`\`
1769
1674
  ${Q(w||"(空)")}
1770
1675
  \`\`\`
1771
1676
 
1772
1677
  **变更后:**
1773
1678
  \`\`\`
1774
- ${Q(V||"(删除)")}
1775
- \`\`\``}case"Write":{let w=b.content,V=b.encoding||"utf8";if(V!=="utf8"||!w)return`将写入 ${V==="base64"?"Base64 编码":V==="binary"?"二进制":""} 内容`;let W=30,Q=w.split(`
1776
- `);if(Q.length<=W)return`**文件内容预览:**
1679
+ ${Q(W||"(删除)")}
1680
+ \`\`\``}case"Write":{let w=Wb(b,"content"),W=Wb(b,"encoding","utf8");if(W!=="utf8"||!w)return`将写入 ${W==="base64"?"Base64 编码":W==="binary"?"二进制":""} 内容`;let V=30,Q=w.split(`
1681
+ `);if(Q.length<=V)return`**文件内容预览:**
1777
1682
  \`\`\`
1778
1683
  ${w}
1779
- \`\`\``;let Z=Q.slice(0,W).join(`
1780
- `);return`**文件内容预览 (前 ${W} 行):**
1684
+ \`\`\``;let Z=Q.slice(0,V).join(`
1685
+ `);return`**文件内容预览 (前 ${V} 行):**
1781
1686
  \`\`\`
1782
1687
  ${Z}
1783
1688
  \`\`\`
1784
1689
 
1785
- ... (还有 ${Q.length-W} 行)`}default:return}}extractRisksFromPermissionCheck($,b,w){let V=[];if(w?.reason)V.push(w.reason);if($.name==="Bash"){let W=b.command||"",Q=W.trim().split(/\s+/)[0];if(["cat","head","tail"].includes(Q))V.push(`\uD83D\uDCA1 建议使用 Read 工具代替 ${Q} 命令`);else if(["grep","rg"].includes(Q))V.push("\uD83D\uDCA1 建议使用 Grep 工具代替 grep/rg 命令");else if(Q==="find")V.push("\uD83D\uDCA1 建议使用 Glob 工具代替 find 命令");else if(["sed","awk"].includes(Q))V.push(`\uD83D\uDCA1 建议使用 Edit 工具代替 ${Q} 命令`);if(W.includes("rm"))V.push("⚠️ 此命令可能删除文件");if(W.includes("sudo"))V.push("⚠️ 此命令需要管理员权限");if(W.includes("git push"))V.push("⚠️ 此命令将推送代码到远程仓库")}else if(["Write","Edit"].includes($.name))V.push("此操作将修改文件内容");else if($.name==="Delete")V.push("此操作将永久删除文件");return V}}class Aw{name="execution";async process($){let b=$._internal.invocation;if(!b){$.abort("Pre-execution stage failed; cannot run tool");return}try{let w=await b.execute($.context.signal??new AbortController().signal,$.context.onProgress,$.context);$.setResult(w)}catch(w){$.abort(`Tool execution failed: ${w.message}`)}}}class Uw{name="formatting";async process($){try{let b=$.getResult();if(!b.llmContent)b.llmContent="Execution completed";if(!b.displayContent)b.displayContent=b.success?"执行成功":"执行失败";if(!b.metadata)b.metadata={};b.metadata.executionId=$.context.sessionId,b.metadata.toolName=$.toolName,b.metadata.timestamp=Date.now(),$.setResult(b)}catch(b){$.abort(`Result formatting failed: ${b.message}`)}}}class Pb extends iV{registry;stages;executionHistory=[];maxHistorySize;sessionApprovals=new Set;constructor($,b={}){super();this.registry=$;this.maxHistorySize=b.maxHistorySize||1000;let w=b.permissionConfig||{allow:[],ask:[],deny:[]},V=b.permissionMode??v.DEFAULT,W=new Kw(w,this.sessionApprovals,V);this.stages=[new Bw(this.registry),W,new Jw,new qw(this.sessionApprovals,W.getPermissionChecker(),b.canUseTool),new Aw,new Xw,new Uw]}async execute($,b,w){let V=Date.now(),W=this.generateExecutionId(),Q=new K1($,b,{...w,sessionId:w.sessionId||W});this.emit("executionStarted",{executionId:W,toolName:$,params:b,context:w,timestamp:V});let Z=this.registry.get($),Y=Z&&!Z.isConcurrencySafe,J=Y&&b.file_path?String(b.file_path):null;if(Y&&J)return n$.getInstance().acquireLock(J,()=>this.executeWithPipeline(Q,W,V));return this.executeWithPipeline(Q,W,V)}async executeWithPipeline($,b,w){try{for(let Q of this.stages){if($.context.signal?.aborted){$.abort("任务已被用户中止");break}if(this.emit("stageStarted",{executionId:b,stageName:Q.name,timestamp:Date.now()}),await Q.process($),this.emit("stageCompleted",{executionId:b,stageName:Q.name,timestamp:Date.now()}),$.shouldAbort())break}let V=$.getResult(),W=Date.now();return this.addToHistory({executionId:b,toolName:$.toolName,params:$.params,result:V,startTime:w,endTime:W,context:$.context}),this.emit("executionCompleted",{executionId:b,toolName:$.toolName,result:V,duration:W-w,timestamp:W}),V}catch(V){let W=Date.now(),Q=V.message?.includes("timeout")||V.name==="TimeoutError",Z={success:!1,llmContent:`Tool execution failed: ${V.message}`,displayContent:`错误: ${V.message}`,error:{type:"execution_error",message:V.message}};try{let J=await m.getInstance().executePostToolUseFailureHooks($.toolName,`tool_use_${b}`,$.params,V.message,{projectDir:process.cwd(),sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode||v.DEFAULT,isInterrupt:!1,isTimeout:Q,abortSignal:$.context.signal});if(J.additionalContext)Z={...Z,llmContent:`${Z.llmContent}
1690
+ ... (还有 ${Q.length-V} 行)`}default:return}}extractRisksFromPermissionCheck($,b,w){let W=[];if(w?.reason)W.push(w.reason);if($.name==="Bash"){let V=Wb(b,"command"),Q=V.trim().split(/\s+/)[0];if(["cat","head","tail"].includes(Q))W.push(`\uD83D\uDCA1 建议使用 Read 工具代替 ${Q} 命令`);else if(["grep","rg"].includes(Q))W.push("\uD83D\uDCA1 建议使用 Grep 工具代替 grep/rg 命令");else if(Q==="find")W.push("\uD83D\uDCA1 建议使用 Glob 工具代替 find 命令");else if(["sed","awk"].includes(Q))W.push(`\uD83D\uDCA1 建议使用 Edit 工具代替 ${Q} 命令`);if(V.includes("rm"))W.push("⚠️ 此命令可能删除文件");if(V.includes("sudo"))W.push("⚠️ 此命令需要管理员权限");if(V.includes("git push"))W.push("⚠️ 此命令将推送代码到远程仓库")}else if(["Write","Edit"].includes($.name))W.push("此操作将修改文件内容");else if($.name==="Delete")W.push("此操作将永久删除文件");return W}}class _w{name="execution";async process($){let b=$._internal.invocation;if(!b){$.abort("Pre-execution stage failed; cannot run tool");return}try{let w=await b.execute($.context.signal??new AbortController().signal,$.context.onProgress,$.context);$.setResult(w)}catch(w){$.abort(`Tool execution failed: ${_(w)}`)}}}class Dw{name="formatting";async process($){try{let b=$.getResult();if(!b.llmContent)b.llmContent="Execution completed";if(!b.displayContent)b.displayContent=b.success?"执行成功":"执行失败";if(!b.metadata)b.metadata={};b.metadata.executionId=$.context.sessionId,b.metadata.toolName=$.toolName,b.metadata.timestamp=Date.now(),$.setResult(b)}catch(b){$.abort(`Result formatting failed: ${_(b)}`)}}}class db extends i6{registry;stages;executionHistory=[];maxHistorySize;sessionApprovals=new Set;constructor($,b={}){super();this.registry=$;this.maxHistorySize=b.maxHistorySize||1000;let w=b.permissionConfig||{allow:[],ask:[],deny:[]},W=b.permissionMode??z.DEFAULT,V=new Rw(w,this.sessionApprovals,W);this.stages=[new Uw(this.registry),V,new qw,new Hw(this.sessionApprovals,V.getPermissionChecker(),b.canUseTool),new _w,new Aw,new Dw]}async execute($,b,w){let W=Date.now(),V=this.generateExecutionId(),Q=new Z1($,b,{...w,sessionId:w.sessionId||V});this.emit("executionStarted",{executionId:V,toolName:$,params:b,context:w,timestamp:W});let Z=this.registry.get($),J=Z&&!Z.isConcurrencySafe,Y=J&&b.file_path?String(b.file_path):null;if(J&&Y)return a$.getInstance().acquireLock(Y,()=>this.executeWithPipeline(Q,V,W));return this.executeWithPipeline(Q,V,W)}async executeWithPipeline($,b,w){try{for(let Q of this.stages){if($.context.signal?.aborted){$.abort("任务已被用户中止");break}if(this.emit("stageStarted",{executionId:b,stageName:Q.name,timestamp:Date.now()}),await Q.process($),this.emit("stageCompleted",{executionId:b,stageName:Q.name,timestamp:Date.now()}),$.shouldAbort())break}let W=$.getResult(),V=Date.now();return this.addToHistory({executionId:b,toolName:$.toolName,params:$.params,result:W,startTime:w,endTime:V,context:$.context}),this.emit("executionCompleted",{executionId:b,toolName:$.toolName,result:W,duration:V-w,timestamp:V}),W}catch(W){let V=Date.now(),Q=_(W),Z=Q.includes("timeout")||d(W)==="TimeoutError",J={success:!1,llmContent:`Tool execution failed: ${Q}`,displayContent:`错误: ${Q}`,error:{type:"execution_error",message:Q}};try{let X=await c.getInstance().executePostToolUseFailureHooks($.toolName,`tool_use_${b}`,$.params,Q,{projectDir:process.cwd(),sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode??z.DEFAULT,isInterrupt:!1,isTimeout:Z,abortSignal:$.context.signal});if(X.additionalContext)J={...J,llmContent:`${J.llmContent}
1786
1691
 
1787
- ${J.additionalContext}`};if(J.warning)console.warn(`[ExecutionPipeline] PostToolUseFailure hook warning: ${J.warning}`)}catch(Y){console.warn("[ExecutionPipeline] PostToolUseFailure hook execution failed:",Y)}return this.addToHistory({executionId:b,toolName:$.toolName,params:$.params,result:Z,startTime:w,endTime:W,context:$.context}),this.emit("executionFailed",{executionId:b,toolName:$.toolName,error:V,duration:W-w,timestamp:W}),Z}}async executeAll($){let b=$.map((w)=>this.execute(w.toolName,w.params,w.context));return Promise.all(b)}async executeParallel($,b=5){let w=[],V=[];for(let W=0;W<$.length;W++){let Q=$[W],Z=this.execute(Q.toolName,Q.params,Q.context);if(V.push(Z),V.length>=b||W===$.length-1){let Y=await Promise.all(V);w.push(...Y),V.length=0}}return w}getExecutionHistory($){let b=[...this.executionHistory];return $?b.slice(-$):b}clearHistory(){this.executionHistory=[],this.emit("historyClear",{timestamp:Date.now()})}getStats(){let $={totalExecutions:this.executionHistory.length,successfulExecutions:0,failedExecutions:0,averageDuration:0,toolUsage:new Map,recentExecutions:this.executionHistory.slice(-10)},b=0;for(let w of this.executionHistory){if(w.result.success)$.successfulExecutions++;else $.failedExecutions++;let V=w.endTime-w.startTime;b+=V;let W=$.toolUsage.get(w.toolName)||0;$.toolUsage.set(w.toolName,W+1)}return $.averageDuration=$.totalExecutions>0?b/$.totalExecutions:0,$}addStage($,b=-1){if(b===-1){let w=this.stages.findIndex((V)=>V.name==="execution");this.stages.splice(w,0,$)}else this.stages.splice(b,0,$);this.emit("stageAdded",{stageName:$.name,position:b,timestamp:Date.now()})}removeStage($){let b=this.stages.findIndex((w)=>w.name===$);if(b===-1)return!1;return this.stages.splice(b,1),this.emit("stageRemoved",{stageName:$,timestamp:Date.now()}),!0}getStages(){return[...this.stages]}getRegistry(){return this.registry}generateExecutionId(){return`exec_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}addToHistory($){if(this.executionHistory.push($),this.executionHistory.length>this.maxHistorySize)this.executionHistory=this.executionHistory.slice(-this.maxHistorySize)}}import{EventEmitter as lV}from"events";class $b extends lV{tools=new Map;mcpTools=new Map;categories=new Map;tags=new Map;constructor(){super()}register($){if(this.tools.has($.name))throw Error(`工具 '${$.name}' 已注册`);this.tools.set($.name,$),this.updateIndexes($),this.emit("toolRegistered",{type:"builtin",tool:$,timestamp:Date.now()})}registerAll($){let b=[];for(let w of $)try{this.register(w)}catch(V){b.push(`${w.name}: ${V.message}`)}if(b.length>0)throw Error(`批量注册失败: ${b.join(", ")}`)}unregister($){let b=this.tools.get($);if(!b)return!1;return this.tools.delete($),this.removeFromIndexes(b),this.emit("toolUnregistered",{type:"builtin",toolName:$,timestamp:Date.now()}),!0}get($){return this.tools.get($)||this.mcpTools.get($)}has($){return this.tools.has($)||this.mcpTools.has($)}getAll(){return[...Array.from(this.tools.values()),...Array.from(this.mcpTools.values())]}getBuiltinTools(){return Array.from(this.tools.values())}getMcpTools(){return Array.from(this.mcpTools.values())}getByCategory($){let b=this.categories.get($);if(!b)return[];return Array.from(b).map((w)=>this.get(w)).filter((w)=>w!==void 0)}getByTag($){let b=this.tags.get($);if(!b)return[];return Array.from(b).map((w)=>this.get(w)).filter((w)=>w!==void 0)}search($){let b=$.toLowerCase();return this.getAll().filter((w)=>{let V=typeof w.description==="string"?w.description:w.description.short;return w.name.toLowerCase().includes(b)||V.toLowerCase().includes(b)||w.displayName.toLowerCase().includes(b)||w.category&&w.category.toLowerCase().includes(b)||w.tags.some((W)=>W.toLowerCase().includes(b))})}getFunctionDeclarations(){return this.getAll().map(($)=>$.getFunctionDeclaration())}getReadOnlyFunctionDeclarations(){return this.getAll().filter(($)=>$.isReadOnly).map(($)=>$.getFunctionDeclaration())}getFunctionDeclarationsByMode($){if($===v.PLAN)return this.getReadOnlyFunctionDeclarations();if($===v.SPEC)return this.getSpecModeFunctionDeclarations();return this.getFunctionDeclarations()}static SPEC_TOOLS=["EnterSpecMode","UpdateSpec","GetSpecContext","TransitionSpecPhase","AddTask","UpdateTaskStatus","ValidateSpec","ExitSpecMode"];getSpecModeFunctionDeclarations(){return this.getFunctionDeclarations()}isSpecTool($){return $b.SPEC_TOOLS.includes($)}getReadOnlyTools(){return this.getAll().filter(($)=>$.isReadOnly)}getCategories(){return Array.from(this.categories.keys())}getTags(){return Array.from(this.tags.keys())}getStats(){return{totalTools:this.tools.size+this.mcpTools.size,builtinTools:this.tools.size,mcpTools:this.mcpTools.size,categories:this.categories.size,tags:this.tags.size,toolsByCategory:Object.fromEntries(Array.from(this.categories.entries()).map(([$,b])=>[$,b.size]))}}registerMcpTool($){if(this.mcpTools.has($.name))this.mcpTools.delete($.name);this.mcpTools.set($.name,$),this.updateIndexes($),this.emit("toolRegistered",{type:"mcp",tool:$,timestamp:Date.now()})}removeMcpTools($){let b=0,w=`mcp__${$}__`;for(let[V,W]of this.mcpTools.entries())if(V.startsWith(w))this.mcpTools.delete(V),this.removeFromIndexes(W),b++,this.emit("toolUnregistered",{type:"mcp",toolName:V,serverName:$,timestamp:Date.now()});return b}updateIndexes($){if($.category){if(!this.categories.has($.category))this.categories.set($.category,new Set);this.categories.get($.category).add($.name)}for(let b of $.tags){if(!this.tags.has(b))this.tags.set(b,new Set);this.tags.get(b).add($.name)}}removeFromIndexes($){if($.category){let b=this.categories.get($.category);if(b){if(b.delete($.name),b.size===0)this.categories.delete($.category)}}for(let b of $.tags){let w=this.tags.get(b);if(w){if(w.delete($.name),w.size===0)this.tags.delete(b)}}}}var nV=[/deepseek.*r1/i,/deepseek.*reasoner/i,/o1-preview/i,/o1-mini/i,/o1/i,/qwen.*qwq/i,/qwen.*think/i,/kimi.*k1/i,/moonshot.*think/i,/k1-32k/i,/doubao.*think/i,/doubao.*pro.*think/i,/claude.*opus.*4/i,/glm-4\.7/i];function L2($){return nV.some((b)=>b.test($))}function j2($){if($.supportsThinking!==void 0)return{supportsThinking:$.supportsThinking,thinkingBudget:$.thinkingBudget};return{supportsThinking:L2($.model),thinkingBudget:void 0}}function Cw($){return j2($).supportsThinking}import S2 from"fast-glob";import*as j0 from"fs/promises";import*as M2 from"path";import*as hb from"fs/promises";import*as a from"path";var N2=[".git",".claude","node_modules",".env",".env.local",".env.production",".env.development",".env.test"];class Y0 extends Error{code;constructor($,b){super($);this.code=b;this.name="PathSecurityError"}}class J0{static normalize($,b){let w=a.isAbsolute($)?$:a.resolve(b,$),V=a.normalize(w),W=a.normalize(b);if(!V.startsWith(W))throw new Y0(`Path outside workspace: ${$} (resolved to ${V}, workspace: ${W})`,"PATH_OUTSIDE_WORKSPACE");return V}static checkRestricted($){let b=$.split(a.sep);for(let w of N2)if(b.includes(w))throw new Y0(`Access denied: "${w}" is a protected directory`,"RESTRICTED_PATH")}static checkTraversal($){if($.includes(".."))throw new Y0(`Path traversal not allowed: ${$}`,"PATH_TRAVERSAL")}static async validatePath($,b){J0.checkTraversal($);let w=J0.normalize($,b);J0.checkRestricted(w);try{await hb.access(w)}catch(V){throw new Y0(`Path not found: ${$}`,"PATH_NOT_FOUND")}return w}static async resolveSymlink($,b){try{let w=await hb.realpath($),V=a.normalize(b);if(!w.startsWith(V))throw new Y0(`Symlink points outside workspace: ${$} -> ${w}`,"SYMLINK_OUTSIDE_WORKSPACE");return w}catch(w){if(w instanceof Y0)throw w;return $}}static getRelativePath($,b){return a.relative(b,$)}static isWithinWorkspace($,b){let w=a.normalize($),V=a.normalize(b);return w.startsWith(V)}static isRestricted($){let b=$.split(a.sep);return N2.some((w)=>b.includes(w))}}class U${static PATTERN=/@"([^"]+)"|@([^\s]+)/g;static LINE_RANGE_PATTERN=/#L(\d+)(?:-(\d+))?$/;static GLOB_PATTERN=/[*?[\]]/;static extract($){let b=[],w;U$.PATTERN.lastIndex=0;while((w=U$.PATTERN.exec($))!==null){let V=w[0],W=w[1]||w[2],Q=U$.parseLineRange(W);if(Q)W=W.replace(U$.LINE_RANGE_PATTERN,"");let Z=U$.GLOB_PATTERN.test(W);b.push({raw:V,path:W.trim(),lineRange:Q,startIndex:w.index,endIndex:w.index+V.length,isGlob:Z})}return b}static parseLineRange($){let b=$.match(U$.LINE_RANGE_PATTERN);if(!b)return;let w=parseInt(b[1],10),V=b[2]?parseInt(b[2],10):void 0;return{start:w,end:V}}static hasAtMentions($){return $.includes("@")}static isValidPath($){if(!$||$.trim().length===0)return!1;let b=["<",">","|","\x00"];for(let w of b)if($.includes(w))return!1;return!0}static removeAtMentions($){return U$.PATTERN.lastIndex=0,$.replace(U$.PATTERN,"")}}var D$=N("Prompts");function xb($){return $ instanceof Map}class Fw{fileCache=new Map;options;constructor($){this.options={maxFileSize:1048576,maxLines:2000,maxTokens:32000,...$},D$.debug("AttachmentCollector initialized",{maxFileSize:this.options.maxFileSize,maxLines:this.options.maxLines})}async collect($){if(!U$.hasAtMentions($))return[];let b=U$.extract($);if(b.length===0)return[];D$.debug(`Found ${b.length} @ mentions`);let w=b.map((W)=>this.processOne(W));return(await Promise.allSettled(w)).map((W,Q)=>{if(W.status==="fulfilled")return W.value;else{let Z=b[Q],Y=W.reason instanceof Error?W.reason.message:String(W.reason);return D$.warn(`Failed to process @${Z.path}:`,Y),{type:"error",path:Z.path,content:"",error:Y}}})}async processOne($){if($.isGlob)return D$.debug(`Processing glob pattern: ${$.path}`),await this.processGlob($.path);let b=await J0.validatePath($.path,this.options.cwd),w=await J0.resolveSymlink(b,this.options.cwd);if((await j0.stat(w)).isDirectory())return D$.debug(`Processing directory: ${$.path}`),await this.renderDirectoryTree(w,$.path);return D$.debug(`Processing file: ${$.path}`,{lineRange:$.lineRange}),await this.readFile(w,$.path,$.lineRange)}async readFile($,b,w){let V=this.fileCache.get($);if(V&&Date.now()-V.timestamp<60000)return D$.debug(`Cache hit: ${b}`),this.formatFileAttachment(b,V.content,w);let W=await j0.stat($);if(W.size>this.options.maxFileSize)throw Error(`File too large: ${Math.round(W.size/1024/1024)}MB (max ${Math.round(this.options.maxFileSize/1024/1024)}MB)`);let Q;try{Q=await j0.readFile($,"utf-8")}catch(Z){throw Error(`Cannot read file as text: ${b}. It may be a binary file.`)}return this.fileCache.set($,{content:Q,timestamp:Date.now()}),this.formatFileAttachment(b,Q,w)}formatFileAttachment($,b,w){let V=b.split(`
1788
- `),W=b,Q=!1,Z=w;if(w){let Y=Math.max(0,w.start-1),J=w.end?w.end:w.start;if(Y>=V.length)throw Error(`Line range start (${w.start}) exceeds file length (${V.length} lines)`);let X=Math.min(J,V.length);W=V.slice(Y,X).join(`
1789
- `);let O=Array.from({length:X-Y},(B,q)=>Y+q+1);W=W.split(`
1790
- `).map((B,q)=>`${O[q]}: ${B}`).join(`
1791
- `),Z={start:w.start,end:X}}else if(V.length>this.options.maxLines)W=V.slice(0,this.options.maxLines).join(`
1792
- `),W+=`
1692
+ ${X.additionalContext}`};if(X.warning)console.warn(`[ExecutionPipeline] PostToolUseFailure hook warning: ${X.warning}`)}catch(Y){console.warn("[ExecutionPipeline] PostToolUseFailure hook execution failed:",Y)}return this.addToHistory({executionId:b,toolName:$.toolName,params:$.params,result:J,startTime:w,endTime:V,context:$.context}),this.emit("executionFailed",{executionId:b,toolName:$.toolName,error:W,duration:V-w,timestamp:V}),J}}async executeAll($){let b=$.map((w)=>this.execute(w.toolName,w.params,w.context));return Promise.all(b)}async executeParallel($,b=5){let w=[],W=[];for(let V=0;V<$.length;V++){let Q=$[V],Z=this.execute(Q.toolName,Q.params,Q.context);if(W.push(Z),W.length>=b||V===$.length-1){let J=await Promise.all(W);w.push(...J),W.length=0}}return w}getExecutionHistory($){let b=[...this.executionHistory];return $?b.slice(-$):b}clearHistory(){this.executionHistory=[],this.emit("historyClear",{timestamp:Date.now()})}getStats(){let $={totalExecutions:this.executionHistory.length,successfulExecutions:0,failedExecutions:0,averageDuration:0,toolUsage:new Map,recentExecutions:this.executionHistory.slice(-10)},b=0;for(let w of this.executionHistory){if(w.result.success)$.successfulExecutions++;else $.failedExecutions++;let W=w.endTime-w.startTime;b+=W;let V=$.toolUsage.get(w.toolName)||0;$.toolUsage.set(w.toolName,V+1)}return $.averageDuration=$.totalExecutions>0?b/$.totalExecutions:0,$}addStage($,b=-1){if(b===-1){let w=this.stages.findIndex((W)=>W.name==="execution");this.stages.splice(w,0,$)}else this.stages.splice(b,0,$);this.emit("stageAdded",{stageName:$.name,position:b,timestamp:Date.now()})}removeStage($){let b=this.stages.findIndex((w)=>w.name===$);if(b===-1)return!1;return this.stages.splice(b,1),this.emit("stageRemoved",{stageName:$,timestamp:Date.now()}),!0}getStages(){return[...this.stages]}getRegistry(){return this.registry}generateExecutionId(){return`exec_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}addToHistory($){if(this.executionHistory.push($),this.executionHistory.length>this.maxHistorySize)this.executionHistory=this.executionHistory.slice(-this.maxHistorySize)}}import{EventEmitter as l6}from"events";class Vb extends l6{tools=new Map;mcpTools=new Map;categories=new Map;tags=new Map;constructor(){super()}register($){if(this.tools.has($.name))throw Error(`工具 '${$.name}' 已注册`);this.tools.set($.name,$),this.updateIndexes($),this.emit("toolRegistered",{type:"builtin",tool:$,timestamp:Date.now()})}registerAll($){let b=[];for(let w of $)try{this.register(w)}catch(W){b.push(`${w.name}: ${_(W)}`)}if(b.length>0)throw Error(`批量注册失败: ${b.join(", ")}`)}unregister($){let b=this.tools.get($);if(!b)return!1;return this.tools.delete($),this.removeFromIndexes(b),this.emit("toolUnregistered",{type:"builtin",toolName:$,timestamp:Date.now()}),!0}get($){return this.tools.get($)||this.mcpTools.get($)}has($){return this.tools.has($)||this.mcpTools.has($)}getAll(){return[...Array.from(this.tools.values()),...Array.from(this.mcpTools.values())]}getBuiltinTools(){return Array.from(this.tools.values())}getMcpTools(){return Array.from(this.mcpTools.values())}getByCategory($){let b=this.categories.get($);if(!b)return[];return Array.from(b).map((w)=>this.get(w)).filter((w)=>w!==void 0)}getByTag($){let b=this.tags.get($);if(!b)return[];return Array.from(b).map((w)=>this.get(w)).filter((w)=>w!==void 0)}search($){let b=$.toLowerCase();return this.getAll().filter((w)=>{let W=typeof w.description==="string"?w.description:w.description.short;return w.name.toLowerCase().includes(b)||W.toLowerCase().includes(b)||w.displayName.toLowerCase().includes(b)||w.category&&w.category.toLowerCase().includes(b)||w.tags.some((V)=>V.toLowerCase().includes(b))})}getFunctionDeclarations(){return this.getAll().map(($)=>$.getFunctionDeclaration())}getReadOnlyFunctionDeclarations(){return this.getAll().filter(($)=>$.isReadOnly).map(($)=>$.getFunctionDeclaration())}getFunctionDeclarationsByMode($){if($===z.PLAN)return this.getReadOnlyFunctionDeclarations();if($===z.SPEC)return this.getSpecModeFunctionDeclarations();return this.getFunctionDeclarations()}static SPEC_TOOLS=["EnterSpecMode","UpdateSpec","GetSpecContext","TransitionSpecPhase","AddTask","UpdateTaskStatus","ValidateSpec","ExitSpecMode"];getSpecModeFunctionDeclarations(){return this.getFunctionDeclarations()}isSpecTool($){return Vb.SPEC_TOOLS.includes($)}getReadOnlyTools(){return this.getAll().filter(($)=>$.isReadOnly)}getCategories(){return Array.from(this.categories.keys())}getTags(){return Array.from(this.tags.keys())}getStats(){return{totalTools:this.tools.size+this.mcpTools.size,builtinTools:this.tools.size,mcpTools:this.mcpTools.size,categories:this.categories.size,tags:this.tags.size,toolsByCategory:Object.fromEntries(Array.from(this.categories.entries()).map(([$,b])=>[$,b.size]))}}registerMcpTool($){if(this.mcpTools.has($.name))this.mcpTools.delete($.name);this.mcpTools.set($.name,$),this.updateIndexes($),this.emit("toolRegistered",{type:"mcp",tool:$,timestamp:Date.now()})}removeMcpTools($){let b=0,w=`mcp__${$}__`;for(let[W,V]of this.mcpTools.entries())if(W.startsWith(w))this.mcpTools.delete(W),this.removeFromIndexes(V),b++,this.emit("toolUnregistered",{type:"mcp",toolName:W,serverName:$,timestamp:Date.now()});return b}updateIndexes($){if($.category){if(!this.categories.has($.category))this.categories.set($.category,new Set);this.categories.get($.category).add($.name)}for(let b of $.tags){if(!this.tags.has(b))this.tags.set(b,new Set);this.tags.get(b).add($.name)}}removeFromIndexes($){if($.category){let b=this.categories.get($.category);if(b){if(b.delete($.name),b.size===0)this.categories.delete($.category)}}for(let b of $.tags){let w=this.tags.get(b);if(w){if(w.delete($.name),w.size===0)this.tags.delete(b)}}}}import v2 from"fast-glob";import*as y0 from"fs/promises";import*as T2 from"path";import*as ub from"fs/promises";import*as o from"path";var z2=[".git",".claude","node_modules",".env",".env.local",".env.production",".env.development",".env.test"];class B0 extends Error{code;constructor($,b){super($);this.code=b;this.name="PathSecurityError"}}class K0{static normalize($,b){let w=o.isAbsolute($)?$:o.resolve(b,$),W=o.normalize(w),V=o.normalize(b);if(!W.startsWith(V))throw new B0(`Path outside workspace: ${$} (resolved to ${W}, workspace: ${V})`,"PATH_OUTSIDE_WORKSPACE");return W}static checkRestricted($){let b=$.split(o.sep);for(let w of z2)if(b.includes(w))throw new B0(`Access denied: "${w}" is a protected directory`,"RESTRICTED_PATH")}static checkTraversal($){if($.includes(".."))throw new B0(`Path traversal not allowed: ${$}`,"PATH_TRAVERSAL")}static async validatePath($,b){K0.checkTraversal($);let w=K0.normalize($,b);K0.checkRestricted(w);try{await ub.access(w)}catch(W){throw new B0(`Path not found: ${$}`,"PATH_NOT_FOUND")}return w}static async resolveSymlink($,b){try{let w=await ub.realpath($),W=o.normalize(b);if(!w.startsWith(W))throw new B0(`Symlink points outside workspace: ${$} -> ${w}`,"SYMLINK_OUTSIDE_WORKSPACE");return w}catch(w){if(w instanceof B0)throw w;return $}}static getRelativePath($,b){return o.relative(b,$)}static isWithinWorkspace($,b){let w=o.normalize($),W=o.normalize(b);return w.startsWith(W)}static isRestricted($){let b=$.split(o.sep);return z2.some((w)=>b.includes(w))}}class U${static PATTERN=/@"([^"]+)"|@([^\s]+)/g;static LINE_RANGE_PATTERN=/#L(\d+)(?:-(\d+))?$/;static GLOB_PATTERN=/[*?[\]]/;static extract($){let b=[],w;U$.PATTERN.lastIndex=0;while((w=U$.PATTERN.exec($))!==null){let W=w[0],V=w[1]||w[2],Q=U$.parseLineRange(V);if(Q)V=V.replace(U$.LINE_RANGE_PATTERN,"");let Z=U$.GLOB_PATTERN.test(V);b.push({raw:W,path:V.trim(),lineRange:Q,startIndex:w.index,endIndex:w.index+W.length,isGlob:Z})}return b}static parseLineRange($){let b=$.match(U$.LINE_RANGE_PATTERN);if(!b)return;let w=parseInt(b[1],10),W=b[2]?parseInt(b[2],10):void 0;return{start:w,end:W}}static hasAtMentions($){return $.includes("@")}static isValidPath($){if(!$||$.trim().length===0)return!1;let b=["<",">","|","\x00"];for(let w of b)if($.includes(w))return!1;return!0}static removeAtMentions($){return U$.PATTERN.lastIndex=0,$.replace(U$.PATTERN,"")}}var E$=E("Prompts");function gb($){return $ instanceof Map}class Lw{fileCache=new Map;options;constructor($){this.options={maxFileSize:1048576,maxLines:2000,maxTokens:32000,...$},E$.debug("AttachmentCollector initialized",{maxFileSize:this.options.maxFileSize,maxLines:this.options.maxLines})}async collect($){if(!U$.hasAtMentions($))return[];let b=U$.extract($);if(b.length===0)return[];E$.debug(`Found ${b.length} @ mentions`);let w=b.map((V)=>this.processOne(V));return(await Promise.allSettled(w)).map((V,Q)=>{if(V.status==="fulfilled")return V.value;else{let Z=b[Q],J=V.reason instanceof Error?V.reason.message:String(V.reason);return E$.warn(`Failed to process @${Z.path}:`,J),{type:"error",path:Z.path,content:"",error:J}}})}async processOne($){if($.isGlob)return E$.debug(`Processing glob pattern: ${$.path}`),await this.processGlob($.path);let b=await K0.validatePath($.path,this.options.cwd),w=await K0.resolveSymlink(b,this.options.cwd);if((await y0.stat(w)).isDirectory())return E$.debug(`Processing directory: ${$.path}`),await this.renderDirectoryTree(w,$.path);return E$.debug(`Processing file: ${$.path}`,{lineRange:$.lineRange}),await this.readFile(w,$.path,$.lineRange)}async readFile($,b,w){let W=this.fileCache.get($);if(W&&Date.now()-W.timestamp<60000)return E$.debug(`Cache hit: ${b}`),this.formatFileAttachment(b,W.content,w);let V=await y0.stat($);if(V.size>this.options.maxFileSize)throw Error(`File too large: ${Math.round(V.size/1024/1024)}MB (max ${Math.round(this.options.maxFileSize/1024/1024)}MB)`);let Q;try{Q=await y0.readFile($,"utf-8")}catch(Z){throw Error(`Cannot read file as text: ${b}. It may be a binary file.`)}return this.fileCache.set($,{content:Q,timestamp:Date.now()}),this.formatFileAttachment(b,Q,w)}formatFileAttachment($,b,w){let W=b.split(`
1693
+ `),V=b,Q=!1,Z=w;if(w){let J=Math.max(0,w.start-1),Y=w.end?w.end:w.start;if(J>=W.length)throw Error(`Line range start (${w.start}) exceeds file length (${W.length} lines)`);let X=Math.min(Y,W.length);V=W.slice(J,X).join(`
1694
+ `);let O=Array.from({length:X-J},(B,K)=>J+K+1);V=V.split(`
1695
+ `).map((B,K)=>`${O[K]}: ${B}`).join(`
1696
+ `),Z={start:w.start,end:X}}else if(W.length>this.options.maxLines)V=W.slice(0,this.options.maxLines).join(`
1697
+ `),V+=`
1793
1698
 
1794
- [... truncated ${V.length-this.options.maxLines} lines ...]`,Q=!0;return{type:"file",path:$,content:W,metadata:{size:b.length,lines:V.length,truncated:Q,lineRange:Z}}}async renderDirectoryTree($,b){let w=await S2("**/*",{cwd:$,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(w.length===0)return{type:"directory",path:b,content:"(empty directory)"};D$.debug(`Found ${w.length} files in directory: ${b}`);let V=this.buildFileTree(w),W=this.printTree(V,b),Q=500,Z=w.length>Q?`
1699
+ [... truncated ${W.length-this.options.maxLines} lines ...]`,Q=!0;return{type:"file",path:$,content:V,metadata:{size:b.length,lines:W.length,truncated:Q,lineRange:Z}}}async renderDirectoryTree($,b){let w=await v2("**/*",{cwd:$,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(w.length===0)return{type:"directory",path:b,content:"(empty directory)"};E$.debug(`Found ${w.length} files in directory: ${b}`);let W=this.buildFileTree(w),V=this.printTree(W,b),Q=500,Z=w.length>Q?`
1795
1700
 
1796
- [... and ${w.length-Q} more files]`:"";return{type:"directory",path:b,content:W+Z,metadata:{lines:w.length,truncated:w.length>Q}}}buildFileTree($){let b=new Map;for(let w of $){let V=i0(w),W=b;for(let Q=0;Q<V.length;Q++){let Z=V[Q],Y=Q===V.length-1;if(!W.has(Z))W.set(Z,Y?null:new Map);if(!Y){let J=W.get(Z);if(J&&xb(J))W=J}}}return b}printTree($,b,w="",V=!0){let W=[];if(w==="")W.push(`${b}/`);let Q=Array.from($.entries()).sort((Z,Y)=>{let J=xb(Z[1]),X=xb(Y[1]);if(J!==X)return X?1:-1;return Z[0].localeCompare(Y[0])});return Q.forEach(([Z,Y],J)=>{let X=J===Q.length-1,O=X?"└── ":"├── ",G=xb(Y);if(W.push(`${w}${O}${Z}${G?"/":""}`),G&&Y.size>0){let B=w+(X?" ":"│ ");W.push(this.printTree(Y,"",B,X))}}),W.filter((Z)=>Z).join(`
1797
- `)}async processGlob($){let b=await S2($,{cwd:this.options.cwd,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(b.length===0)return{type:"error",path:$,content:"",error:`No files matched pattern: ${$}`};D$.debug(`Glob pattern "${$}" matched ${b.length} files`);let w=30,V=b.slice(0,w),Q=(await Promise.allSettled(V.map(async(X)=>{let O=M2.join(this.options.cwd,X);try{let G=await j0.readFile(O,"utf-8"),B=G.split(`
1798
- `),q=200,U=G,K=!1;if(B.length>200)U=B.slice(0,200).join(`
1799
- `),U+=`
1701
+ [... and ${w.length-Q} more files]`:"";return{type:"directory",path:b,content:V+Z,metadata:{lines:w.length,truncated:w.length>Q}}}buildFileTree($){let b=new Map;for(let w of $){let W=r0(w),V=b;for(let Q=0;Q<W.length;Q++){let Z=W[Q],J=Q===W.length-1;if(!V.has(Z))V.set(Z,J?null:new Map);if(!J){let Y=V.get(Z);if(Y&&gb(Y))V=Y}}}return b}printTree($,b,w="",W=!0){let V=[];if(w==="")V.push(`${b}/`);let Q=Array.from($.entries()).sort((Z,J)=>{let Y=gb(Z[1]),X=gb(J[1]);if(Y!==X)return X?1:-1;return Z[0].localeCompare(J[0])});return Q.forEach(([Z,J],Y)=>{let X=Y===Q.length-1,O=X?"└── ":"├── ",G=gb(J);if(V.push(`${w}${O}${Z}${G?"/":""}`),G&&J.size>0){let B=w+(X?" ":"│ ");V.push(this.printTree(J,"",B,X))}}),V.filter((Z)=>Z).join(`
1702
+ `)}async processGlob($){let b=await v2($,{cwd:this.options.cwd,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(b.length===0)return{type:"error",path:$,content:"",error:`No files matched pattern: ${$}`};E$.debug(`Glob pattern "${$}" matched ${b.length} files`);let w=30,W=b.slice(0,w),Q=(await Promise.allSettled(W.map(async(X)=>{let O=T2.join(this.options.cwd,X);try{let G=await y0.readFile(O,"utf-8"),B=G.split(`
1703
+ `),K=200,C=G,q=!1;if(B.length>200)C=B.slice(0,200).join(`
1704
+ `),C+=`
1800
1705
 
1801
- [... truncated ${B.length-200} lines ...]`,K=!0;return{path:X,content:U,lines:B.length,truncated:K}}catch(G){return{path:X,content:`[Error: ${G instanceof Error?G.message:"unknown error"}]`,lines:0,truncated:!1}}}))).map((X)=>X.status==="fulfilled"?X.value:null).filter((X)=>X!==null),Y=Q.map((X)=>`--- ${X.path} (${X.lines} lines${X.truncated?", truncated":""}) ---
1706
+ [... truncated ${B.length-200} lines ...]`,q=!0;return{path:X,content:C,lines:B.length,truncated:q}}catch(G){return{path:X,content:`[Error: ${G instanceof Error?G.message:"unknown error"}]`,lines:0,truncated:!1}}}))).map((X)=>X.status==="fulfilled"?X.value:null).filter((X)=>X!==null),J=Q.map((X)=>`--- ${X.path} (${X.lines} lines${X.truncated?", truncated":""}) ---
1802
1707
  ${X.content}`).join(`
1803
1708
 
1804
- `),J=b.length>w?`
1709
+ `),Y=b.length>w?`
1805
1710
 
1806
- [... and ${b.length-w} more files matched]`:"";return{type:"file",path:$,content:Y+J,metadata:{lines:Q.reduce((X,O)=>X+O.lines,0),truncated:b.length>w||Q.some((X)=>X.truncated)}}}clearExpiredCache(){let $=Date.now(),b=0;for(let[w,V]of this.fileCache.entries())if($-V.timestamp>60000)this.fileCache.delete(w),b++;if(b>0)D$.debug(`Cleared ${b} expired cache entries`)}clearCache(){this.fileCache.clear(),D$.debug("Cleared all cache")}getCacheStats(){return{size:this.fileCache.size,keys:Array.from(this.fileCache.keys())}}}var pb=N("Agent");class Hw{attachmentCollector;constructor($){this.attachmentCollector=new Fw({cwd:$,maxFileSize:1048576,maxLines:2000,maxTokens:32000})}async processAtMentionsForContent($){if(typeof $==="string")return this.processAtMentions($);let b=[];for(let V of $)if(V.type==="text")b.push(V.text);if(b.length===0)return $;let w=b.join(`
1807
- `);try{let V=await this.attachmentCollector.collect(w);if(V.length===0)return $;pb.debug(`✅ Processed ${V.length} @ file mentions in multimodal message`);let W=this.buildAttachmentText(V);if(!W)return $;return[...$,{type:"text",text:W}]}catch(V){return pb.error("Failed to process @ mentions in multimodal message:",V),$}}buildAttachmentText($){let b=[],w=[];for(let W of $)if(W.type==="file"){let Q=W.metadata?.lineRange?` (lines ${W.metadata.lineRange.start}${W.metadata.lineRange.end?`-${W.metadata.lineRange.end}`:""})`:"";b.push(`<file path="${W.path}"${Q?` range="${Q}"`:""}>`,W.content,"</file>")}else if(W.type==="directory")b.push(`<directory path="${W.path}">`,W.content,"</directory>");else if(W.type==="error")w.push(`- @${W.path}: ${W.error}`);let V="";if(b.length>0)V+=`
1711
+ [... and ${b.length-w} more files matched]`:"";return{type:"file",path:$,content:J+Y,metadata:{lines:Q.reduce((X,O)=>X+O.lines,0),truncated:b.length>w||Q.some((X)=>X.truncated)}}}clearExpiredCache(){let $=Date.now(),b=0;for(let[w,W]of this.fileCache.entries())if($-W.timestamp>60000)this.fileCache.delete(w),b++;if(b>0)E$.debug(`Cleared ${b} expired cache entries`)}clearCache(){this.fileCache.clear(),E$.debug("Cleared all cache")}getCacheStats(){return{size:this.fileCache.size,keys:Array.from(this.fileCache.keys())}}}var mb=E("Agent");class Ew{attachmentCollector;constructor($){this.attachmentCollector=new Lw({cwd:$,maxFileSize:1048576,maxLines:2000,maxTokens:32000})}async processAtMentionsForContent($){if(typeof $==="string")return this.processAtMentions($);let b=[];for(let W of $)if(W.type==="text")b.push(W.text);if(b.length===0)return $;let w=b.join(`
1712
+ `);try{let W=await this.attachmentCollector.collect(w);if(W.length===0)return $;mb.debug(`✅ Processed ${W.length} @ file mentions in multimodal message`);let V=this.buildAttachmentText(W);if(!V)return $;return[...$,{type:"text",text:V}]}catch(W){return mb.error("Failed to process @ mentions in multimodal message:",W),$}}buildAttachmentText($){let b=[],w=[];for(let V of $)if(V.type==="file"){let Q=V.metadata?.lineRange?` (lines ${V.metadata.lineRange.start}${V.metadata.lineRange.end?`-${V.metadata.lineRange.end}`:""})`:"";b.push(`<file path="${V.path}"${Q?` range="${Q}"`:""}>`,V.content,"</file>")}else if(V.type==="directory")b.push(`<directory path="${V.path}">`,V.content,"</directory>");else if(V.type==="error")w.push(`- @${V.path}: ${V.error}`);let W="";if(b.length>0)W+=`
1808
1713
 
1809
1714
  <system-reminder>
1810
- `,V+=`The following files were mentioned with @ syntax:
1715
+ `,W+=`The following files were mentioned with @ syntax:
1811
1716
 
1812
- `,V+=b.join(`
1813
- `),V+=`
1814
- </system-reminder>`;if(w.length>0)V+=`
1717
+ `,W+=b.join(`
1718
+ `),W+=`
1719
+ </system-reminder>`;if(w.length>0)W+=`
1815
1720
 
1816
1721
  ⚠️ Some files could not be loaded:
1817
- `,V+=w.join(`
1818
- `);return V}async processAtMentions($){try{let b=await this.attachmentCollector.collect($);if(b.length===0)return $;return pb.debug(`✅ Processed ${b.length} @ file mentions`),this.appendAttachments($,b)}catch(b){return pb.error("Failed to process @ mentions:",b),$}}appendAttachments($,b){let w=[],V=[];for(let Q of b)if(Q.type==="file"){let Z=Q.metadata?.lineRange?` (lines ${Q.metadata.lineRange.start}${Q.metadata.lineRange.end?`-${Q.metadata.lineRange.end}`:""})`:"";w.push(`<file path="${Q.path}"${Z?` range="${Z}"`:""}>`,Q.content,"</file>")}else if(Q.type==="directory")w.push(`<directory path="${Q.path}">`,Q.content,"</directory>");else if(Q.type==="error")V.push(`- @${Q.path}: ${Q.error}`);let W=$;if(w.length>0)W+=`
1722
+ `,W+=w.join(`
1723
+ `);return W}async processAtMentions($){try{let b=await this.attachmentCollector.collect($);if(b.length===0)return $;return mb.debug(`✅ Processed ${b.length} @ file mentions`),this.appendAttachments($,b)}catch(b){return mb.error("Failed to process @ mentions:",b),$}}appendAttachments($,b){let w=[],W=[];for(let Q of b)if(Q.type==="file"){let Z=Q.metadata?.lineRange?` (lines ${Q.metadata.lineRange.start}${Q.metadata.lineRange.end?`-${Q.metadata.lineRange.end}`:""})`:"";w.push(`<file path="${Q.path}"${Z?` range="${Z}"`:""}>`,Q.content,"</file>")}else if(Q.type==="directory")w.push(`<directory path="${Q.path}">`,Q.content,"</directory>");else if(Q.type==="error")W.push(`- @${Q.path}: ${Q.error}`);let V=$;if(w.length>0)V+=`
1819
1724
 
1820
1725
  <system-reminder>
1821
- `,W+=`The following files were mentioned with @ syntax:
1726
+ `,V+=`The following files were mentioned with @ syntax:
1822
1727
 
1823
- `,W+=w.join(`
1824
- `),W+=`
1825
- </system-reminder>`;if(V.length>0)W+=`
1728
+ `,V+=w.join(`
1729
+ `),V+=`
1730
+ </system-reminder>`;if(W.length>0)V+=`
1826
1731
 
1827
1732
  ⚠️ Some files could not be loaded:
1828
- `,W+=V.join(`
1829
- `);return W}}var C$=N("Agent");class _w{getChatService;getContextManager;constructor($,b){this.getChatService=$;this.getContextManager=b}async*checkAndCompactInLoop($,b,w){if(w===void 0)return C$.debug(`[Agent] [轮次 ${b}] 压缩检查: 跳过(无历史 usage 数据)`),!1;let W=this.getChatService().getConfig(),Q=W.model,Z=W.maxContextTokens??128000,Y=W.maxOutputTokens??8192,J=Z-Y,X=Math.floor(J*0.8);if(C$.debug(`[Agent] [轮次 ${b}] 压缩检查:`,{promptTokens:w,maxContextTokens:Z,maxOutputTokens:Y,availableForInput:J,threshold:X,shouldCompact:w>=X}),w<X)return!1;let O=b===0?"[Agent] 触发自动压缩":`[Agent] [轮次 ${b}] 触发循环内自动压缩`;C$.debug(O),yield{type:"compacting",isCompacting:!0};try{let G=await r.compact($.messages,{trigger:"auto",modelName:Q,maxContextTokens:Z,apiKey:W.apiKey,baseURL:W.baseUrl,actualPreTokens:w});if(G.success)$.messages=G.compactedMessages,C$.debug(`[Agent] [轮次 ${b}] 压缩完成: ${G.preTokens} → ${G.postTokens} tokens (-${((1-G.postTokens/G.preTokens)*100).toFixed(1)}%)`);else $.messages=G.compactedMessages,C$.warn(`[Agent] [轮次 ${b}] 压缩使用降级策略: ${G.preTokens} → ${G.postTokens} tokens`);try{let B=this.getContextManager();if(B&&$.sessionId)await B.saveCompaction($.sessionId,G.summary,{trigger:"auto",preTokens:G.preTokens,postTokens:G.postTokens,filesIncluded:G.filesIncluded},null),C$.debug(`[Agent] [轮次 ${b}] 压缩数据已保存到 JSONL`)}catch(B){C$.warn(`[Agent] [轮次 ${b}] 保存压缩数据失败:`,B)}return yield{type:"compacting",isCompacting:!1},!0}catch(G){return yield{type:"compacting",isCompacting:!1},C$.error(`[Agent] [轮次 ${b}] 压缩失败,继续执行`,G),!1}}async compactOnTurnLimit($,b,w){try{let W=this.getChatService().getConfig(),Q=await r.compact($.messages,{trigger:"auto",modelName:W.model,maxContextTokens:W.maxContextTokens??128000,apiKey:W.apiKey,baseURL:W.baseUrl,actualPreTokens:w});$.messages=Q.compactedMessages;let Z=b.find((X)=>X.role==="system"),Y=[];if(Z)Y.push(Z);Y.push(...$.messages);let J={role:"user",content:`This session is being continued from a previous conversation. The conversation is summarized above.
1733
+ `,V+=W.join(`
1734
+ `);return V}}import{nanoid as M0}from"nanoid";import{ProxyAgent as n6,fetch as s6}from"undici";function r6(){return process.env.HTTPS_PROXY||process.env.HTTP_PROXY||process.env.https_proxy||process.env.http_proxy}function a6(){let $=r6();if($)try{return new n6($)}catch(b){console.warn(`[proxyFetch] Invalid proxy URL: ${$}`)}return}async function k2($,b={}){let{timeout:w=30000,signal:W,...V}=b;if(W?.aborted)throw new DOMException("The operation was aborted.","AbortError");let Q=a6(),Z=new AbortController,J=!1,Y=setTimeout(()=>{J=!0,Z.abort()},w),X=()=>Z.abort();W?.addEventListener("abort",X);try{let O={method:V.method,headers:V.headers,body:V.body,signal:Z.signal,dispatcher:Q};return await s6($.toString(),O)}catch(O){if(O instanceof Error&&O.name==="AbortError"){if(J)throw Error(`Request timeout after ${w}ms`);throw O}throw O}finally{clearTimeout(Y),W?.removeEventListener("abort",X)}}var Qb=E("Service"),o6="https://blade-api-proxy.137844255.workers.dev/v1/get-zhipu-key",f2="blade-free-tier",cb=null;async function I2($){if($!==f2)return $;if(cb)return Qb.debug("使用缓存的内置 API Key"),cb;try{Qb.info("\uD83D\uDD11 正在从代理服务获取内置 API Key...");let b=await k2(o6,{method:"GET",headers:{Authorization:`Bearer ${f2}`,"Content-Type":"application/json"},timeout:1e4});if(!b.ok){let W=await b.text();throw Error(`获取 API Key 失败: ${b.status} - ${W}`)}let w=await b.json();if(!w.apiKey)throw Error("代理服务返回的数据中没有 apiKey");if(cb=w.apiKey,Qb.info("✅ 成功获取内置 API Key"),w.message)Qb.debug(`提示: ${w.message}`);return cb}catch(b){throw Qb.error(" 获取内置 API Key 失败:",b),Error(`无法获取内置模型的 API Key: ${b instanceof Error?b.message:"未知错误"}
1735
+ `+"请检查网络连接或使用自己的 API Key (/config)")}}import{createOpenAICompatible as jw}from"@ai-sdk/openai-compatible";import{generateText as t6,jsonSchema as P2,Output as e6,streamText as $V}from"ai";var j$=E("Chat");function h2($){let b=new Set;for(let w of $)if(w.role==="assistant"&&w.tool_calls)for(let W of w.tool_calls)b.add(W.id);return $.filter((w)=>{if(w.role==="tool"){if(!w.tool_call_id)return!1;return b.has(w.tool_call_id)}return!0})}function ib($){if(typeof $==="string")return $;return $.filter((b)=>b.type==="text").map((b)=>b.text).join(`
1736
+ `)}function bV($,b={}){try{return JSON.parse($)}catch{return j$.warn("⚠️ [VercelAIChatService] Failed to parse JSON, using fallback",{str:$}),b}}class Nw{model;config;initialized;constructor($){this.config=$,this.initialized=this.initModel($)}async initModel($){this.model=await this.createModel($),j$.debug("\uD83D\uDE80 [VercelAIChatService] Initialized",{provider:$.provider,model:$.model,providerId:$.providerId})}async createModel($){let{provider:b,apiKey:w,baseUrl:W,model:V,customHeaders:Q,providerId:Z,apiVersion:J}=$;switch(b){case"anthropic":{let{createAnthropic:Y}=await import("@ai-sdk/anthropic");return Y({apiKey:w,baseURL:W||void 0,headers:Q})(V)}case"gemini":{if(W&&!this.isGeminiOfficialUrl(W))return jw({name:"gemini",apiKey:w,baseURL:W,headers:Q})(V);let{createGoogleGenerativeAI:Y}=await import("@ai-sdk/google");return Y({apiKey:w,baseURL:W||void 0})(V)}case"azure-openai":{let Y=this.extractAzureResourceName(W);if(Y){let{createAzure:G}=await import("@ai-sdk/azure");return G({apiKey:w,resourceName:Y,apiVersion:J||"2024-08-01-preview"})(V)}let X=this.buildAzureBaseUrl(W,V);return jw({name:"azure-openai",apiKey:w,baseURL:X,headers:{...Q,"api-key":w},queryParams:{"api-version":J||"2024-08-01-preview"}})(V)}default:{if(Z==="deepseek"){let{createDeepSeek:X}=await import("@ai-sdk/deepseek");return X({apiKey:w,baseURL:W||void 0,headers:Q})(V)}return jw({name:Z||"custom",apiKey:w,baseURL:W,headers:Q})(V)}}}extractAzureResourceName($){if(!$)return;let b=$.match(/https:\/\/([^.]+)\.openai\.azure(?:\.com|\.us|\.cn|\.de)/);return b?b[1]:void 0}buildAzureBaseUrl($,b){if(!$)return"";let w=$.replace(/\/$/,"").replace(/\?.*$/,"");if(w.includes("/openai/deployments/"))return w;return`${w}/openai/deployments/${b}`}isGeminiOfficialUrl($){return $.includes("generativelanguage.googleapis.com")||$.includes("aiplatform.googleapis.com")}convertMessages($){let b=[];for(let w of $)if(w.role==="system")if(Array.isArray(w.content)){let W=w.content.find((Q)=>Q.type==="text"),V={role:"system",content:ib(w.content)};if(W?.providerOptions)V.providerOptions=W.providerOptions;b.push(V)}else b.push({role:"system",content:w.content});else if(w.role==="user")if(Array.isArray(w.content)){let W=w.content.map((V)=>{if(V.type==="text"){let Q={type:"text",text:V.text};if(V.providerOptions)Q.providerOptions=V.providerOptions;return Q}return{type:"image",image:V.image_url.url}});b.push({role:"user",content:W})}else b.push({role:"user",content:w.content});else if(w.role==="assistant")if(w.tool_calls&&w.tool_calls.length>0){let W=w.tool_calls.map((Q)=>{let Z=Q.function;return{type:"tool-call",toolCallId:Q.id,toolName:Z?.name||"",input:bV(Z?.arguments||"{}",{})}}),V=ib(w.content);if(V)b.push({role:"assistant",content:[{type:"text",text:V},...W]});else b.push({role:"assistant",content:W})}else b.push({role:"assistant",content:ib(w.content)});else if(w.role==="tool")b.push({role:"tool",content:[{type:"tool-result",toolCallId:w.tool_call_id,toolName:w.name||"unknown",output:{type:"text",value:ib(w.content)}}]});return b}convertTools($){if(!$||$.length===0)return;let b={};for(let w of $)b[w.name]={description:w.description,inputSchema:P2(w.parameters)};return b}convertToolCalls($){return $.map((b)=>({id:b.toolCallId,type:"function",function:{name:b.toolName,arguments:JSON.stringify(b.args??b.input??{})}}))}convertOutputFormat($){if(!$||$.type!=="json_schema")return;let{json_schema:b}=$;return e6.object({schema:P2(b.schema)})}convertUsage($,b){if(!$)return;let w=$.promptTokens??0,W=$.completionTokens??0,V={promptTokens:w,completionTokens:W,totalTokens:$.totalTokens??w+W};if(b?.anthropic){if(b.anthropic.cacheCreationInputTokens!==void 0)V.cacheCreationInputTokens=b.anthropic.cacheCreationInputTokens;if(b.anthropic.cacheReadInputTokens!==void 0)V.cacheReadInputTokens=b.anthropic.cacheReadInputTokens}return V}async chat($,b,w){await this.initialized;let W=Date.now();j$.debug("\uD83D\uDE80 [VercelAIChatService] Starting chat request");let V=h2($),Q=this.convertMessages(V),Z=this.convertTools(b),J=this.convertOutputFormat(this.config.outputFormat);try{let Y=await t6({model:this.model,messages:Q,tools:Z,maxOutputTokens:this.config.maxOutputTokens,temperature:this.config.temperature??0,abortSignal:w,experimental_output:J}),X=Date.now()-W;j$.debug("\uD83D\uDCE5 [VercelAIChatService] Response received in",X,"ms");let O=Y.toolCalls&&Y.toolCalls.length>0?this.convertToolCalls(Y.toolCalls):void 0,G=Array.isArray(Y.reasoning)?Y.reasoning.map((B)=>B.text).join(""):void 0;return{content:Y.text,reasoningContent:G,toolCalls:O,usage:this.convertUsage(Y.usage,Y.providerMetadata)}}catch(Y){let X=Date.now()-W;throw j$.error("❌ [VercelAIChatService] Chat failed after",X,"ms"),Y}}async*streamChat($,b,w){await this.initialized;let W=Date.now();j$.debug("\uD83D\uDE80 [VercelAIChatService] Starting stream request");let V=h2($),Q=this.convertMessages(V),Z=this.convertTools(b),J=this.convertOutputFormat(this.config.outputFormat);try{let Y=$V({model:this.model,messages:Q,tools:Z,maxOutputTokens:this.config.maxOutputTokens,temperature:this.config.temperature??0,abortSignal:w,experimental_output:J});j$.debug("\uD83D\uDCE5 [VercelAIChatService] Stream started");let X=0;for await(let G of Y.fullStream)switch(G.type){case"text-delta":yield{content:G.text??G.textDelta};break;case"reasoning-delta":yield{reasoningContent:G.textDelta};break;case"tool-call":yield{toolCalls:[{index:X++,id:G.toolCallId,type:"function",function:{name:G.toolName,arguments:JSON.stringify(G.args??G.input??{})}}]};break;case"finish":yield{finishReason:G.finishReason,usage:this.convertUsage(G.totalUsage,G.providerMetadata)};break}let O=Date.now()-W;j$.debug("✅ [VercelAIChatService] Stream completed in",O,"ms")}catch(Y){let X=Date.now()-W;throw j$.error("❌ [VercelAIChatService] Stream failed after",X,"ms"),Y}}getConfig(){return{...this.config}}updateConfig($){j$.debug("\uD83D\uDD04 [VercelAIChatService] Updating configuration"),this.config={...this.config,...$},this.initialized=this.initModel(this.config),j$.debug("✅ [VercelAIChatService] Configuration updated")}}var x2=E("Service"),wV="blade-free-tier";function WV($){return $===wV}function VV($){return{}}async function lb($){let b=$;if(WV($.apiKey)){x2.info("\uD83D\uDD11 检测到内置 API Key,正在获取...");let w=await I2($.apiKey);b={...$,apiKey:w}}if(b.providerId){let w=VV(b.providerId);if(Object.keys(w).length>0)b={...b,customHeaders:{...w,...b.customHeaders}},x2.debug(`\uD83D\uDD27 注入 ${b.providerId} 特定 headers:`,Object.keys(w))}return QV(b)}function QV($){return new Nw($)}import{readFile as ZV}from"node:fs/promises";import{basename as JV}from"node:path";class r{static MAX_FILES=5;static MAX_LINES_PER_FILE=1000;static analyzeFiles($){let b=new Map;return $.forEach((W,V)=>{let Q=typeof W.content==="string"?W.content:(W.content||[]).filter((J)=>J.type==="text").map((J)=>J.text).join(`
1737
+ `);if(r.extractFilePathsFromContent(Q).forEach((J)=>{r.updateFileReference(b,J,V,!1)}),W.tool_calls&&Array.isArray(W.tool_calls))W.tool_calls.forEach((J)=>{let Y=r.extractFilePathsFromToolCall(J),X=J.type==="function"&&"function"in J?J.function?.name:"",O=["Write","Edit"].includes(X||"");Y.forEach((G)=>{r.updateFileReference(b,G,V,O)})})}),Array.from(b.values()).sort((W,V)=>{if(W.wasModified!==V.wasModified)return W.wasModified?-1:1;if(W.mentions!==V.mentions)return V.mentions-W.mentions;return V.lastMentioned-W.lastMentioned}).slice(0,r.MAX_FILES)}static async readFilesContent($){let b=[];for(let w of $)try{let W=await ZV(w,"utf-8"),V=W.split(`
1738
+ `),Q=V.length,Z=W,J=!1,Y=Q;if(Q>r.MAX_LINES_PER_FILE)Z=V.slice(0,r.MAX_LINES_PER_FILE).join(`
1739
+ `),Z+=`
1830
1740
 
1831
- Please continue the conversation from where we left it off without asking the user any further questions. Continue with the last task that you were asked to work on.`};Y.push(J),$.messages.push(J);try{let X=this.getContextManager();if(X&&$.sessionId)await X.saveCompaction($.sessionId,Q.summary,{trigger:"auto",preTokens:Q.preTokens,postTokens:Q.postTokens,filesIncluded:Q.filesIncluded},null)}catch(X){C$.warn("[Agent] 保存压缩数据失败:",X)}return C$.info(`✅ 上下文已压缩 (${Q.preTokens} → ${Q.postTokens} tokens),重置轮次计数`),{success:!0,messages:Y}}catch(V){C$.error("[Agent] 压缩失败,使用降级策略:",V);let W=b.find((Y)=>Y.role==="system"),Q=b.slice(-80),Z=[];if(W&&!Q.some((Y)=>Y.role==="system"))Z.push(W);return Z.push(...Q),$.messages=Z.filter((Y)=>Y.role!=="system"),C$.warn(`⚠️ 降级压缩完成,保留 ${Z.length} 条消息`),{success:!1,messages:Z}}}}import*as v2 from"crypto";import{nanoid as z2}from"nanoid";class Rw{maxSummaryLength;keyPointsLimit;recentMessagesLimit;constructor($=500,b=10,w=20){this.maxSummaryLength=$,this.keyPointsLimit=b,this.recentMessagesLimit=w}async compress($){let b=$.layers.conversation.messages,w=$.layers.tool.recentCalls,V=b.filter((G)=>G.role==="system"),W=b.filter((G)=>G.role!=="system"),Q=this.getRecentMessages(W),Z=W.slice(0,-this.recentMessagesLimit),Y=await this.generateSummary(Z),J=this.extractKeyPoints(Z,w),X=this.generateToolSummary(w),O=this.estimateTokenCount(Y,J,Q,X);return{summary:Y,keyPoints:J,recentMessages:[...V,...Q],toolSummary:X,tokenCount:O}}getRecentMessages($){return $.slice(-this.recentMessagesLimit)}async generateSummary($){if($.length===0)return"";let b=new Set,w=new Set,V=new Set;for(let Q of $){let Z=Q.content.toLowerCase();["关于","讨论","问题","项目","功能","需求"].forEach((O)=>{if(Z.includes(O)){let G=this.extractContext(Z,O,50);if(G)b.add(G)}}),["创建","删除","修改","更新","实现","开发"].forEach((O)=>{if(Z.includes(O)){let G=this.extractContext(Z,O,30);if(G)w.add(G)}}),["决定","选择","确定","采用","使用"].forEach((O)=>{if(Z.includes(O)){let G=this.extractContext(Z,O,40);if(G)V.add(G)}})}let W=`对话涉及 ${$.length} 条消息。`;if(b.size>0)W+=` 主要讨论:${Array.from(b).slice(0,3).join("、")}。`;if(w.size>0)W+=` 执行操作:${Array.from(w).slice(0,3).join("、")}。`;if(V.size>0)W+=` 关键决策:${Array.from(V).slice(0,2).join("、")}。`;return W.length>this.maxSummaryLength?W.substring(0,this.maxSummaryLength)+"...":W}extractKeyPoints($,b){let w=new Set;for(let W of $)if(W.role==="user")this.extractQuestions(W.content).forEach((Y)=>w.add(`用户问题:${Y}`)),this.extractRequests(W.content).forEach((Y)=>w.add(`用户请求:${Y}`));else if(W.role==="assistant")this.extractSolutions(W.content).forEach((Z)=>w.add(`解决方案:${Z}`));return this.summarizeToolUsage(b).forEach((W)=>w.add(`工具使用:${W}`)),Array.from(w).slice(0,this.keyPointsLimit)}generateToolSummary($){if($.length===0)return"";let b=new Map,w=Date.now()-600000;for(let W of $){let Q=b.get(W.name)||{count:0,success:0,recent:0};if(Q.count++,W.status==="success")Q.success++;if(W.timestamp>w)Q.recent++;b.set(W.name,Q)}let V=[];for(let[W,Q]of Array.from(b.entries())){let Z=Math.round(Q.success/Q.count*100);V.push(`${W}(${Q.count}次,成功率${Z}%)`)}return`工具调用:${V.join("、")}`}estimateTokenCount($,b,w,V){let W=$.length+b.join(" ").length;if(V)W+=V.length;for(let Q of w)W+=Q.content.length;return Math.ceil(W/4)}extractContext($,b,w){let V=$.indexOf(b);if(V===-1)return null;let W=Math.max(0,V-w/2),Q=Math.min($.length,V+w/2);return $.substring(W,Q).trim()}extractQuestions($){let b=[],w=["?","?","如何","怎么","什么","为什么"],V=$.split(/[。!.!]/);for(let W of V)if(w.some((Q)=>W.includes(Q))){let Q=W.trim();if(Q.length>5&&Q.length<100)b.push(Q)}return b.slice(0,3)}extractRequests($){let b=[],w=["请","帮我","需要","想要","希望","能否"],V=$.split(/[。!.!]/);for(let W of V)if(w.some((Q)=>W.includes(Q))){let Q=W.trim();if(Q.length>5&&Q.length<100)b.push(Q)}return b.slice(0,3)}extractSolutions($){let b=[],w=["可以","建议","推荐","应该","最好","解决方案"],V=$.split(/[。!.!]/);for(let W of V)if(w.some((Q)=>W.includes(Q))){let Q=W.trim();if(Q.length>10&&Q.length<150)b.push(Q)}return b.slice(0,3)}summarizeToolUsage($){let b=[],w=$.filter((V)=>Date.now()-V.timestamp<1800000);if(w.length>0){let V=new Map;w.forEach((W)=>{let Q=V.get(W.name)||[];Q.push(W),V.set(W.name,Q)});for(let[W,Q]of Array.from(V.entries())){let Z=Q.filter((Y)=>Y.status==="success").length;b.push(`${W}(${Q.length}次,${Z}成功)`)}}return b.slice(0,5)}shouldCompress($,b){return this.estimateCurrentTokens($)>b*0.8}estimateCurrentTokens($){let w=$.layers.conversation.messages.reduce((V,W)=>V+W.content.length,0);return Math.ceil(w/4)}}class X0{defaultOptions;constructor($){this.defaultOptions={maxTokens:32000,maxMessages:50,timeWindow:86400000,priority:1,includeTools:!0,includeWorkspace:!0,...$}}filter($,b){let w={...this.defaultOptions,...b},V={layers:{system:$.layers.system,session:$.layers.session,conversation:this.filterConversation($.layers.conversation,w),tool:w.includeTools?this.filterTools($.layers.tool,w):{recentCalls:[],toolStates:{},dependencies:{}},workspace:w.includeWorkspace?$.layers.workspace:{currentFiles:[],recentFiles:[],environment:{}}},metadata:{...$.metadata,lastUpdated:Date.now()}};return V.metadata.totalTokens=this.estimateTokens(V),V}filterConversation($,b){let w=[...$.messages];if(b.timeWindow>0){let V=Date.now()-b.timeWindow;w=w.filter((W)=>W.timestamp>=V||W.role==="system")}if(b.priority>1)w=this.filterByPriority(w,b.priority);if(b.maxMessages>0)w=this.limitMessages(w,b.maxMessages);if(b.maxTokens>0)w=this.limitByTokens(w,b.maxTokens);return{messages:w,summary:$.summary,topics:this.updateTopics(w,$.topics),lastActivity:$.lastActivity}}filterTools($,b){let w=[...$.recentCalls];if(b.timeWindow>0){let J=Date.now()-b.timeWindow;w=w.filter((X)=>X.timestamp>=J)}let V=w.filter((J)=>J.status==="success"),W=w.filter((J)=>J.status==="error"),Q=Math.min(20,V.length),Z=Math.min(10,W.length);return{recentCalls:[...V.slice(-Q),...W.slice(-Z)].sort((J,X)=>J.timestamp-X.timestamp),toolStates:$.toolStates,dependencies:$.dependencies}}filterByPriority($,b){return $.filter((w)=>{if(w.role==="system")return!0;return this.calculateMessagePriority(w)>=b})}calculateMessagePriority($){let b=1;if($.role==="system")b+=3;else if($.role==="assistant")b+=1;let w=$.content.toLowerCase();if(["错误","警告","重要","关键","问题","解决"].some((Q)=>w.includes(Q)))b+=2;if(w.includes("```")||w.includes("function")||w.includes("class"))b+=1;let W=(Date.now()-$.timestamp)/3600000;if(W<1)b+=2;else if(W<6)b+=1;return b}limitMessages($,b){if($.length<=b)return $;let w=$.filter((Z)=>Z.role==="system"),V=$.filter((Z)=>Z.role!=="system"),W=b-w.length,Q=W>0?V.slice(-W):[];return[...w,...Q].sort((Z,Y)=>Z.timestamp-Y.timestamp)}limitByTokens($,b){if(b<=0)return $;let w=0,V=[];for(let W=$.length-1;W>=0;W--){let Q=$[W],Z=this.estimateMessageTokens(Q);if(Q.role==="system")if(w+Z<=b)V.unshift(Q),w+=Z;else{let Y=this.compressMessage(Q,b-w);V.unshift(Y),w+=this.estimateMessageTokens(Y)}else if(w+Z<=b)V.unshift(Q),w+=Z;else break}return V.sort((W,Q)=>W.timestamp-Q.timestamp)}estimateMessageTokens($){return Math.ceil($.content.length/4)}compressMessage($,b){let w=b*4;if($.content.length<=w)return $;let V=$.content.substring(0,w-3)+"...";return{...$,content:V,metadata:{...$.metadata,compressed:!0,originalLength:$.content.length}}}updateTopics($,b){let w=new Set(b);for(let V of $)this.extractTopicsFromMessage(V).forEach((Q)=>w.add(Q));return Array.from(w).slice(0,10)}extractTopicsFromMessage($){let b=$.content.toLowerCase(),w=[];return["项目","功能","模块","组件","服务","接口","数据库","前端","后端","算法","架构","设计"].forEach((W)=>{if(b.includes(W))w.push(W)}),w}estimateTokens($){let b=0;for(let V of $.layers.conversation.messages)b+=this.estimateMessageTokens(V);let w=JSON.stringify($.layers.system);if(b+=Math.ceil(w.length/4),$.layers.tool.recentCalls.length>0){let V=JSON.stringify($.layers.tool);b+=Math.ceil(V.length/8)}return b}static createPresets(){return{lightweight:new X0({maxTokens:1000,maxMessages:10,timeWindow:7200000,includeTools:!1,includeWorkspace:!1}),standard:new X0({maxTokens:4000,maxMessages:30,timeWindow:43200000,includeTools:!0,includeWorkspace:!0}),comprehensive:new X0({maxTokens:8000,maxMessages:100,timeWindow:86400000,includeTools:!0,includeWorkspace:!0}),debug:new X0({maxTokens:2000,maxMessages:20,timeWindow:21600000,priority:2,includeTools:!0,includeWorkspace:!1})}}}class Ew{cache=new Map;maxSize;defaultTTL;constructor($=100,b=300000){this.maxSize=$,this.defaultTTL=b}set($,b,w){let V=Date.now(),W={data:b,timestamp:V,accessCount:0,lastAccess:V,ttl:w||this.defaultTTL};if(this.cache.size>=this.maxSize&&!this.cache.has($))this.evictLeastUsed();this.cache.set($,W)}get($){let b=this.cache.get($);if(!b)return null;let w=Date.now();if(w-b.timestamp>b.ttl)return this.cache.delete($),null;return b.accessCount++,b.lastAccess=w,b.data}has($){let b=this.cache.get($);if(!b)return!1;if(Date.now()-b.timestamp>b.ttl)return this.cache.delete($),!1;return!0}delete($){return this.cache.delete($)}clear(){this.cache.clear()}size(){return this.cleanExpired(),this.cache.size}cacheMessageSummary($,b,w){let V=`summary:${$}:${b.length}`;this.set(V,{summary:w,messageCount:b.length,lastMessage:b[b.length-1]?.timestamp||0},600000)}getMessageSummary($,b){let w=`summary:${$}:${b}`;return this.get(w)}cacheToolResult($,b,w){let V=this.hashInput(b),W=`tool:${$}:${V}`;this.set(W,w,1800000)}getToolResult($,b){let w=this.hashInput(b),V=`tool:${$}:${w}`;return this.get(V)}cacheCompressedContext($,b){let w=`compressed:${$}`;this.set(w,b,900000)}getCompressedContext($){let b=`compressed:${$}`;return this.get(b)}getStats(){this.cleanExpired();let $=0,b=0,w=[];for(let[V,W]of Array.from(this.cache.entries()))$+=W.accessCount,b+=this.estimateItemSize(W),w.push({key:V,accessCount:W.accessCount,lastAccess:W.lastAccess});return w.sort((V,W)=>W.accessCount-V.accessCount),{size:this.cache.size,maxSize:this.maxSize,hitRate:$>0?$/($+this.cache.size):0,memoryUsage:b,topKeys:w.slice(0,10)}}cleanExpired(){let $=Date.now(),b=[];for(let[w,V]of Array.from(this.cache.entries()))if($-V.timestamp>V.ttl)b.push(w);b.forEach((w)=>this.cache.delete(w))}evictLeastUsed(){let $=null,b=1/0,w=Date.now();for(let[V,W]of Array.from(this.cache.entries())){let Q=1/(w-W.lastAccess+1),Z=W.accessCount,Y=Q*Z;if(Y<b)b=Y,$=V}if($)this.cache.delete($)}hashInput($){let b=JSON.stringify($),w=0;for(let V=0;V<b.length;V++){let W=b.charCodeAt(V);w=(w<<5)-w+W,w=w&w}return Math.abs(w).toString(36)}estimateItemSize($){try{return JSON.stringify($).length*2}catch{return 1000}}setTTL($,b){let w=this.cache.get($);if(w)return w.ttl=b,w.timestamp=Date.now(),!0;return!1}getRemainingTTL($){let b=this.cache.get($);if(!b)return-1;let w=b.ttl-(Date.now()-b.timestamp);return Math.max(0,w)}warmup($){$.forEach(({key:b,value:w,ttl:V})=>{this.set(b,w,V)})}}class Dw{contextData=null;maxSize;accessLog=new Map;constructor($=1000){this.maxSize=$}setContext($){this.contextData={...$},this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("context")}getContext(){if(this.contextData)this.recordAccess("context");return this.contextData}addMessage($){if(!this.contextData)throw Error("上下文数据未初始化");this.contextData.layers.conversation.messages.push($),this.contextData.layers.conversation.lastActivity=Date.now(),this.contextData.metadata.lastUpdated=Date.now(),this.enforceMemoryLimit(),this.recordAccess("messages")}getRecentMessages($=10){if(!this.contextData)return[];let b=this.contextData.layers.conversation.messages;return this.recordAccess("messages"),b.slice(-$)}addToolCall($){if(!this.contextData)throw Error("上下文数据未初始化");if(this.contextData.layers.tool.recentCalls.push($),this.contextData.metadata.lastUpdated=Date.now(),this.contextData.layers.tool.recentCalls.length>50)this.contextData.layers.tool.recentCalls=this.contextData.layers.tool.recentCalls.slice(-25);this.recordAccess("tools")}updateToolState($,b){if(!this.contextData)throw Error("上下文数据未初始化");this.contextData.layers.tool.toolStates[$]=b,this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("tools")}getToolState($){if(!this.contextData)return null;return this.recordAccess("tools"),this.contextData.layers.tool.toolStates[$]}updateWorkspace($){if(!this.contextData)throw Error("上下文数据未初始化");Object.assign(this.contextData.layers.workspace,$),this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("workspace")}clear(){this.contextData=null,this.accessLog.clear()}getMemoryInfo(){if(!this.contextData)return{hasData:!1,messageCount:0,toolCallCount:0,lastUpdated:null};return{hasData:!0,messageCount:this.contextData.layers.conversation.messages.length,toolCallCount:this.contextData.layers.tool.recentCalls.length,lastUpdated:this.contextData.metadata.lastUpdated}}recordAccess($){this.accessLog.set($,Date.now())}enforceMemoryLimit(){if(!this.contextData)return;let $=this.contextData.layers.conversation.messages;if($.length>this.maxSize){let b=Math.floor(this.maxSize*0.8);this.contextData.layers.conversation.messages=$.slice(-b)}}getMemoryUsage(){if(!this.contextData)return 0;return JSON.stringify(this.contextData).length}}import{nanoid as v$}from"nanoid";import*as x$ from"node:fs/promises";import*as y2 from"node:path";import*as db from"node:fs";import{createReadStream as sV}from"node:fs";import*as o from"node:fs/promises";import*as Lw from"node:path";import{createInterface as rV}from"node:readline";class W${filePath;constructor($){this.filePath=$}async append($){try{await o.mkdir(Lw.dirname(this.filePath),{recursive:!0,mode:493});let b=JSON.stringify($)+`
1832
- `;await o.appendFile(this.filePath,b,"utf-8")}catch(b){throw console.error(`[JSONLStore] 追加写入失败: ${this.filePath}`,b),b}}async appendBatch($){try{await o.mkdir(Lw.dirname(this.filePath),{recursive:!0,mode:493});let b=$.map((w)=>JSON.stringify(w)).join(`
1833
- `)+`
1834
- `;await o.appendFile(this.filePath,b,"utf-8")}catch(b){throw console.error(`[JSONLStore] 批量追加写入失败: ${this.filePath}`,b),b}}async readAll(){try{if(!db.existsSync(this.filePath))return[];let b=(await o.readFile(this.filePath,"utf-8")).split(`
1835
- `).filter((V)=>V.trim().length>0),w=[];for(let V of b)try{w.push(JSON.parse(V))}catch(W){console.warn(`[JSONLStore] 解析 JSON 行失败: ${V}`,W)}return w}catch($){return console.error(`[JSONLStore] 读取文件失败: ${this.filePath}`,$),[]}}async readStream($){return new Promise((b,w)=>{if(!db.existsSync(this.filePath)){b();return}let V=sV(this.filePath,"utf-8"),W=rV({input:V,crlfDelay:Number.POSITIVE_INFINITY});W.on("line",async(Q)=>{let Z=Q.trim();if(Z.length===0)return;try{let Y=JSON.parse(Z);await $(Y)}catch(Y){console.warn(`[JSONLStore] 解析 JSON 行失败: ${Z}`,Y)}}),W.on("close",()=>b()),W.on("error",w),V.on("error",w)})}async filter($){let b=[];return await this.readStream((w)=>{if($(w))b.push(w)}),b}async readLast($){return(await this.readAll()).slice(-$)}async getStats(){try{if(!db.existsSync(this.filePath))return{exists:!1,size:0,lineCount:0};let $=await o.stat(this.filePath),w=(await o.readFile(this.filePath,"utf-8")).split(`
1836
- `).filter((V)=>V.trim().length>0).length;return{exists:!0,size:$.size,lineCount:w}}catch($){return console.error(`[JSONLStore] 获取统计信息失败: ${this.filePath}`,$),{exists:!1,size:0,lineCount:0}}}async exists(){try{return await o.access(this.filePath),!0}catch{return!1}}async delete(){try{if(await this.exists())await o.unlink(this.filePath)}catch($){throw console.error(`[JSONLStore] 删除文件失败: ${this.filePath}`,$),$}}getFilePath(){return this.filePath}}class jw{projectPath;maxSessions;version;constructor($=process.cwd(),b=100,w="0.0.10"){this.projectPath=$,this.maxSessions=b,this.version=w}createEvent($,b,w){return{id:v$(),sessionId:b,timestamp:new Date().toISOString(),type:$,cwd:this.projectPath,gitBranch:R4(this.projectPath),version:this.version,data:w}}async ensureSessionCreated($,b){let w=X$(this.projectPath,$),V=new W$(w);if((await V.getStats()).lineCount>0)return;let Q=new Date().toISOString(),Z={sessionId:$,rootId:b?.parentSessionId??$,parentId:b?.parentSessionId,relationType:b?"subagent":void 0,title:void 0,status:"running",agentType:b?.subagentType,model:void 0,permission:void 0,createdAt:Q,updatedAt:Q},Y=this.createEvent("session_created",$,Z);await V.append(Y)}buildCompactionMetadata($){let b={trigger:$.trigger,preTokens:$.preTokens};if($.postTokens!==void 0)b.postTokens=$.postTokens;if($.filesIncluded)b.filesIncluded=$.filesIncluded;return b}async initialize(){try{let $=g0(this.projectPath);await x$.mkdir($,{recursive:!0,mode:493}),console.log(`[PersistentStore] 初始化存储目录: ${$}`)}catch($){console.warn("[PersistentStore] 无法创建持久化存储目录:",$)}}async saveMessage($,b,w,V=null,W,Q){try{let Z=X$(this.projectPath,$),Y=new W$(Z);await this.ensureSessionCreated($,Q);let J=new Date().toISOString(),X=v$(),O={messageId:X,role:b,parentMessageId:V??void 0,createdAt:J,model:W?.model,usage:W?.usage},G=this.createEvent("message_created",$,O),B={partId:v$(),messageId:X,partType:"text",payload:{text:w},createdAt:J},q=this.createEvent("part_created",$,B);return await Y.appendBatch([G,q]),X}catch(Z){throw console.error(`[PersistentStore] 保存消息失败 (session: ${$}):`,Z),Z}}async saveToolUse($,b,w,V=null,W){try{let Q=X$(this.projectPath,$),Z=new W$(Q);await this.ensureSessionCreated($,W);let Y=new Date().toISOString(),J=V??v$(),X=[];if(!V){let B={messageId:J,role:"assistant",parentMessageId:void 0,createdAt:Y};X.push(this.createEvent("message_created",$,B))}let O=v$(),G={partId:O,messageId:J,partType:"tool_call",payload:{toolCallId:O,toolName:b,input:w},createdAt:Y};if(X.push(this.createEvent("part_created",$,G)),b==="Task"&&w&&typeof w==="object"){let B=w,q=typeof B.subagent_session_id==="string"?B.subagent_session_id:void 0,U=typeof B.subagent_type==="string"?B.subagent_type:void 0;if(q&&U){let K={partId:v$(),messageId:J,partType:"subtask_ref",payload:{childSessionId:q,agentType:U,status:"running",summary:typeof B.description==="string"?B.description:"",startedAt:Y},createdAt:Y};X.push(this.createEvent("part_created",$,K))}}return await Z.appendBatch(X),O}catch(Q){throw console.error(`[PersistentStore] 保存工具调用失败 (session: ${$}):`,Q),Q}}async saveToolResult($,b,w,V,W=null,Q,Z,Y){try{let J=X$(this.projectPath,$),X=new W$(J);await this.ensureSessionCreated($,Z);let O=new Date().toISOString(),G=W??v$(),B=[];if(!W){let U={messageId:G,role:"assistant",parentMessageId:void 0,createdAt:O};B.push(this.createEvent("message_created",$,U))}let q={partId:b,messageId:G,partType:"tool_result",payload:{toolCallId:b,toolName:w,output:V,error:Q??null},createdAt:O};if(B.push(this.createEvent("part_created",$,q)),Y){let U=Y.subagentStatus==="running"?null:O,K={partId:v$(),messageId:G,partType:"subtask_ref",payload:{childSessionId:Y.subagentSessionId,agentType:Y.subagentType,status:Y.subagentStatus,summary:Y.subagentSummary??"",startedAt:O,finishedAt:U},createdAt:O};B.push(this.createEvent("part_created",$,K))}return await X.appendBatch(B),b}catch(J){throw console.error(`[PersistentStore] 保存工具结果失败 (session: ${$}):`,J),J}}async saveCompaction($,b,w,V=null){try{let W=X$(this.projectPath,$),Q=new W$(W);await this.ensureSessionCreated($);let Z=new Date().toISOString(),Y=v$(),J={messageId:Y,role:"system",parentMessageId:V??void 0,createdAt:Z},X=this.buildCompactionMetadata(w),O={partId:v$(),messageId:Y,partType:"summary",payload:{text:b,metadata:X},createdAt:Z},G=[this.createEvent("message_created",$,J),this.createEvent("part_created",$,O)];return await Q.appendBatch(G),Y}catch(W){throw console.error(`[PersistentStore] 保存压缩失败 (session: ${$}):`,W),W}}async saveContext($,b){try{let{conversation:w}=b.layers;for(let V of w.messages)await this.saveMessage($,V.role,V.content,null)}catch(w){console.warn(`[PersistentStore] 保存上下文失败 (session: ${$}):`,w)}}async saveSession($,b){console.warn("[PersistentStore] saveSession 方法已废弃,请使用 saveMessage")}async saveConversation($,b){console.warn("[PersistentStore] saveConversation 方法已废弃,请使用 saveMessage")}async loadSession($){try{let b=X$(this.projectPath,$),V=await new W$(b).readAll();if(V.length===0)return null;let W=V.find((Q)=>Q.type==="session_created");return{sessionId:$,userId:void 0,preferences:{},configuration:{},startTime:new Date(W?.timestamp??V[0].timestamp).getTime()}}catch{return null}}async loadConversation($){try{let b=X$(this.projectPath,$),V=await new W$(b).readAll();if(V.length===0)return null;let W=new Map;for(let J of V){if(J.type==="message_created")W.set(J.data.messageId,{id:J.data.messageId,role:J.data.role,content:"",timestamp:new Date(J.timestamp).getTime()});if(J.type==="part_created"&&J.data.partType==="text"){let X=W.get(J.data.messageId);if(X){let O=J.data.payload;X.content=O.text??""}}}let Q=Array.from(W.values()),Z=V[V.length-1],Y=new Date(Z.timestamp).getTime();return{messages:Q,topics:[],lastActivity:Y}}catch{return null}}async listSessions(){try{let $=g0(this.projectPath);return(await x$.readdir($)).filter((w)=>w.endsWith(".jsonl")).map((w)=>w.replace(".jsonl","")).sort()}catch{return[]}}async getSessionSummary($){try{let b=X$(this.projectPath,$),w=new W$(b);if(!(await w.getStats()).exists)return null;let W=await w.readAll();if(W.length===0)return null;let Q=W[W.length-1],Z=W.filter((Y)=>Y.type==="message_created"&&["user","assistant"].includes(Y.data.role)).length;return{sessionId:$,lastActivity:new Date(Q.timestamp).getTime(),messageCount:Z,topics:[]}}catch{return null}}async deleteSession($){try{let b=X$(this.projectPath,$);await new W$(b).delete()}catch(b){console.warn(`[PersistentStore] 删除会话失败 (session: ${$}):`,b)}}async cleanupOldSessions(){try{let $=await this.listSessions();if($.length<=this.maxSessions)return;let V=(await Promise.all($.map((W)=>this.getSessionSummary(W)))).filter((W)=>W!==null).sort((W,Q)=>Q.lastActivity-W.lastActivity).slice(this.maxSessions).map((W)=>W.sessionId);await Promise.all(V.map((W)=>this.deleteSession(W))),console.log(`[PersistentStore] 已清理 ${V.length} 个旧会话`)}catch($){console.error("[PersistentStore] 清理旧会话失败:",$)}}async getStorageStats(){try{let $=await this.listSessions(),b=0;for(let w of $){let V=X$(this.projectPath,w),Q=await new W$(V).getStats();b+=Q.size}return{totalSessions:$.length,totalSize:b,projectPath:this.projectPath}}catch{return{totalSessions:0,totalSize:0,projectPath:this.projectPath}}}async checkStorageHealth(){try{let $=g0(this.projectPath);await x$.mkdir($,{recursive:!0,mode:493});let b=y2.join($,".health-check");return await x$.writeFile(b,"test","utf-8"),await x$.unlink(b),{isAvailable:!0,canWrite:!0}}catch($){return{isAvailable:!1,canWrite:!1,error:$ instanceof Error?$.message:String($)}}}static async listAllProjects(){return E4()}}class ub{memory;persistent;cache;compressor;filter;options;currentSessionId=null;initialized=!1;constructor($={}){let b=$.storage?.persistentPath||m0();this.options={storage:{maxMemorySize:1000,persistentPath:b,cacheSize:100,compressionEnabled:!0,...$.storage},defaultFilter:{maxTokens:32000,maxMessages:50,timeWindow:86400000,...$.defaultFilter},compressionThreshold:$.compressionThreshold||6000,enableVectorSearch:$.enableVectorSearch||!1},this.memory=new Dw(this.options.storage.maxMemorySize),this.persistent=new jw(process.cwd(),100),this.cache=new Ew(this.options.storage.cacheSize,300000),this.compressor=new Rw,this.filter=new X0(this.options.defaultFilter)}async initialize(){if(this.initialized)return;try{if(await this.persistent.initialize(),!(await this.persistent.checkStorageHealth()).isAvailable)console.warn("警告:持久化存储不可用,将仅使用内存存储");this.initialized=!0,console.log("上下文管理器初始化完成")}catch($){throw console.error("上下文管理器初始化失败:",$),$}}async createSession($,b={},w={}){let V=w.sessionId||this.generateSessionId(),W=Date.now(),Q={layers:{system:await this.createSystemContext(),session:{sessionId:V,userId:$,preferences:b,configuration:w,startTime:W},conversation:{messages:[],topics:[],lastActivity:W},tool:{recentCalls:[],toolStates:{},dependencies:{}},workspace:await this.createWorkspaceContext()},metadata:{totalTokens:0,priority:1,lastUpdated:W}};return this.memory.setContext(Q),await this.persistent.saveContext(V,Q),this.currentSessionId=V,console.log(`新会话已创建: ${V}`),V}async loadSession($){try{let b=this.memory.getContext();if(!b||b.layers.session.sessionId!==$){let[w,V]=await Promise.all([this.persistent.loadSession($),this.persistent.loadConversation($)]);if(!w||!V)return!1;b={layers:{system:await this.createSystemContext(),session:w,conversation:V,tool:{recentCalls:[],toolStates:{},dependencies:{}},workspace:await this.createWorkspaceContext()},metadata:{totalTokens:0,priority:1,lastUpdated:Date.now()}},this.memory.setContext(b)}return this.currentSessionId=$,console.log(`会话已加载: ${$}`),!0}catch(b){return console.error("加载会话失败:",b),!1}}async addMessage($,b,w){if(!this.currentSessionId)throw Error("没有活动会话");let V={id:this.generateMessageId(),role:$,content:b,timestamp:Date.now(),metadata:w};this.memory.addMessage(V);let W=this.memory.getContext();if(W&&this.shouldCompress(W))await this.compressCurrentContext();this.saveCurrentSessionAsync()}async addToolCall($){if(!this.currentSessionId)throw Error("没有活动会话");if(this.memory.addToolCall($),$.status==="success"&&$.output)this.cache.cacheToolResult($.name,$.input,$.output);this.saveCurrentSessionAsync()}async saveMessage($,b,w,V=null,W,Q){return this.persistent.saveMessage($,b,w,V,W,Q)}async saveToolUse($,b,w,V=null,W){return this.persistent.saveToolUse($,b,w,V,W)}async saveToolResult($,b,w,V,W=null,Q,Z,Y){return this.persistent.saveToolResult($,b,w,V,W,Q,Z,Y)}async saveCompaction($,b,w,V=null){return this.persistent.saveCompaction($,b,w,V)}updateToolState($,b){if(!this.currentSessionId)throw Error("没有活动会话");this.memory.updateToolState($,b)}updateWorkspace($){if(!this.currentSessionId)throw Error("没有活动会话");this.memory.updateWorkspace($)}async getFormattedContext($){let b=this.memory.getContext();if(!b)throw Error("没有可用的上下文数据");let w=this.filter.filter(b,$),V=this.shouldCompress(w),W;if(V){let Q=this.hashContext(w);if(W=this.cache.getCompressedContext(Q)??void 0,!W)W=await this.compressor.compress(w),this.cache.cacheCompressedContext(Q,W)}return{context:w,compressed:W,tokenCount:W?W.tokenCount:w.metadata.totalTokens}}async searchSessions($,b=10){let w=await this.persistent.listSessions(),V=[];for(let W of w){let Q=await this.persistent.getSessionSummary(W);if(Q){let Z=this.calculateRelevance($,Q.topics);if(Z>0)V.push({sessionId:W,summary:`${Q.messageCount}条消息,主题:${Q.topics.join("、")}`,lastActivity:Q.lastActivity,relevanceScore:Z})}}return V.sort((W,Q)=>Q.relevanceScore-W.relevanceScore).slice(0,b)}getCachedToolResult($,b){return this.cache.getToolResult($,b)}async getStats(){let[$,b,w]=await Promise.all([Promise.resolve(this.memory.getMemoryInfo()),Promise.resolve(this.cache.getStats()),this.persistent.getStorageStats()]);return{currentSession:this.currentSessionId,memory:$,cache:b,storage:w}}async cleanup(){if(this.currentSessionId)await this.saveCurrentSession();this.memory.clear(),this.cache.clear(),await this.persistent.cleanupOldSessions(),this.currentSessionId=null,console.log("上下文管理器资源清理完成")}generateSessionId(){return z2()}generateMessageId(){return z2()}async createSystemContext(){return{role:"AI助手",capabilities:["对话","工具调用","代码生成","文档分析"],tools:["文件操作","Git操作","代码分析"],version:"1.0.0"}}async createWorkspaceContext(){try{let $=process.cwd();return{projectPath:$,currentFiles:[],recentFiles:[],environment:{nodeVersion:process.version,platform:process.platform,cwd:$}}}catch($){return{currentFiles:[],recentFiles:[],environment:{}}}}shouldCompress($){return $.metadata.totalTokens>this.options.compressionThreshold}async compressCurrentContext(){let $=this.memory.getContext();if(!$)return;let b=await this.compressor.compress($);$.layers.conversation.summary=b.summary,this.memory.setContext($)}async saveCurrentSession(){if(!this.currentSessionId)return;let $=this.memory.getContext();if($)await this.persistent.saveContext(this.currentSessionId,$)}saveCurrentSessionAsync(){this.saveCurrentSession().catch(($)=>{console.warn("异步保存会话失败:",$)})}hashContext($){let b=JSON.stringify({messageCount:$.layers.conversation.messages.length,lastMessage:$.layers.conversation.messages[$.layers.conversation.messages.length-1]?.id,toolCallCount:$.layers.tool.recentCalls.length});return v2.createHash("md5").update(b).digest("hex")}calculateRelevance($,b){let w=$.toLowerCase(),V=0;for(let W of b)if(w.includes(W.toLowerCase())||W.toLowerCase().includes(w))V+=1;return V}}class Nw{chatService;contextManager;memoryAdapter;constructor($,b){this.chatService=$,this.contextManager=b||new ub,this.memoryAdapter=this.createMemoryAdapter()}createMemoryAdapter(){let $=[];return{getMessages:()=>[...$],addMessage:(b)=>{$.push(b)},clearContext:()=>{$.length=0},getContextSize:()=>$.length}}getContextManager(){return this.contextManager}getMemoryAdapter(){return this.memoryAdapter}async executeTask($){let b=[{role:"user",content:$.prompt}],w=await this.chatService.chat(b);return{taskId:$.id,content:w.content,metadata:{taskType:$.type}}}}import{appendFileSync as aV,mkdirSync as oV,writeFileSync as tV}from"node:fs";import eV from"node:os";import k2 from"node:path";var Sw=k2.join(eV.homedir(),".blade","logs","stream-debug.log"),T2=!1;function $W(){if(T2)return;let $=k2.dirname(Sw);oV($,{recursive:!0,mode:493}),tV(Sw,`=== Stream Debug Log Started: ${new Date().toISOString()} ===
1837
- `),T2=!0}function f2($,b,w){$W();let V=new Date().toISOString(),W=w?` | ${JSON.stringify(w)}`:"",Q=`[${V}] [${$}] ${b}${W}
1838
- `;aV(Sw,Q)}var I2=N("Agent");class Mw{getChatService;constructor($){this.getChatService=$}async*streamResponse($,b,w){let V=this.getChatService(),W="",Q="",Z,Y=new Map;try{let J=V.streamChat($,b,w),X=0;for await(let O of J){if(X++,w?.aborted)break;if(O.content)W+=O.content,yield{type:"content_delta",delta:O.content};if(O.reasoningContent)Q+=O.reasoningContent,yield{type:"thinking_delta",delta:O.reasoningContent};if(O.usage)Z=O.usage;if(O.toolCalls)for(let G of O.toolCalls)this.accumulateToolCall(Y,G);if(O.finishReason){f2("processStreamResponse","finishReason received",{finishReason:O.finishReason,fullContentLen:W.length,fullReasoningContentLen:Q.length,toolCallAccumulatorSize:Y.size});break}}if(X===0&&!w?.aborted&&W.length===0&&Y.size===0)return I2.warn("[Agent] 流式响应返回0个chunk,回退到非流式模式"),V.chat($,b,w);return{content:W,reasoningContent:Q||void 0,toolCalls:this.buildFinalToolCalls(Y),usage:Z}}catch(J){if(this.isStreamingNotSupportedError(J))return I2.warn("[Agent] 流式请求失败,降级到非流式模式"),V.chat($,b,w);throw J}}accumulateToolCall($,b){let w=b,V=w.index??0;if(!$.has(V))$.set(V,{id:w.id||"",name:w.function?.name||"",arguments:""});let W=$.get(V);if(w.id&&!W.id)W.id=w.id;if(w.function?.name&&!W.name)W.name=w.function.name;if(w.function?.arguments)W.arguments+=w.function.arguments}buildFinalToolCalls($){if($.size===0)return;return Array.from($.values()).filter((b)=>b.id&&b.name).map((b)=>({id:b.id,type:"function",function:{name:b.name,arguments:b.arguments}}))}isStreamingNotSupportedError($){if(!($ instanceof Error))return!1;return["stream not supported","streaming is not available","sse not supported","does not support streaming"].some((w)=>$.message.toLowerCase().includes(w.toLowerCase()))}}function bW($){if(typeof $==="string")return $;try{return JSON.parse(JSON.stringify($))}catch{return String($)}}var S=N("Agent");class P${config;runtimeOptions;isInitialized=!1;activeTask;executionPipeline;chatService;executionEngine;attachmentHandler;streamHandler;compactionHandler;activeSkillContext;currentModelMaxContextTokens;currentModelId;constructor($,b={},w){this.config=$,this.runtimeOptions=b,this.executionPipeline=w||this.createDefaultPipeline()}createDefaultPipeline(){let $=new $b,b={...this.config.permissions,...this.runtimeOptions.permissions},w=this.runtimeOptions.permissionMode??v.DEFAULT;return new Pb($,{permissionConfig:b,permissionMode:w,maxHistorySize:1000,canUseTool:this.runtimeOptions.canUseTool})}resolveModelConfig($){let b=$&&$!=="inherit"?$:void 0,w=this.config.models||[],V=this.config.currentModelId,W=b?w.find((Q)=>Q.id===b):w.find((Q)=>Q.id===V)||w[0];if(!W)throw Error(`❌ 模型配置未找到: ${b??"current"}`);return W}async applyModelConfig($,b){this.log(`${b} ${$.name} (${$.model})`);let w=Cw($),V=$.thinkingEnabled??!1,W=w&&V;if(w&&!V)this.log("\uD83E\uDDE0 模型支持 Thinking,但用户未开启(按 Tab 开启)");else if(W)this.log("\uD83E\uDDE0 Thinking 模式已启用,启用 reasoning_content 支持");let Q=$.maxContextTokens??128000;this.currentModelMaxContextTokens=Q,this.chatService=await Yb({provider:$.provider,apiKey:$.apiKey||"",model:$.model,baseUrl:$.baseUrl||"",temperature:$.temperature??this.config.temperature,maxContextTokens:this.currentModelMaxContextTokens,supportsThinking:W,outputFormat:this.runtimeOptions.outputFormat});let Z=this.executionEngine?.getContextManager();this.executionEngine=new Nw(this.chatService,Z),this.currentModelId=$.id}async switchModelIfNeeded($){if(!$||$===this.currentModelId)return;let w=(this.config.models||[]).find((V)=>V.id===$);if(!w){this.log(`⚠️ 模型配置未找到: ${$}`);return}await this.applyModelConfig(w,"\uD83D\uDD01 切换模型")}static async create($,b={}){if(($.models||[]).length===0)throw Error(`❌ 没有可用的模型配置
1741
+ ... (truncated ${Q-r.MAX_LINES_PER_FILE} lines)`,J=!0,Y=r.MAX_LINES_PER_FILE;b.push({path:w,content:Z,truncated:J,lines:Q,includedLines:Y})}catch(W){console.warn(`[FileAnalyzer] 无法读取文件: ${w}`,W)}return b}static extractFilePathsFromContent($){let b=new Set,w=/```(?:\w+)?\s*\n?([\s\S]*?)```/g,W=Array.from($.matchAll(w));for(let Q of W){let Z=Q[1];r.extractPathsFromText(Z).forEach((Y)=>b.add(Y))}return r.extractPathsFromText($).forEach((Q)=>b.add(Q)),Array.from(b)}static extractPathsFromText($){let b=[],w=[/(?:src|tests?|docs?|lib|config|scripts?|bin|utils?|components?|services?|hooks?)\/[\w\-/.]+\.[\w]+/g,/(?:package|tsconfig|vite\.config|webpack\.config|next\.config|babel\.config)\.[\w]+/g,/(?:\.\.?\/|\/)[a-zA-Z0-9\-_/.]+\.[\w]+/g];for(let W of w){let V=Array.from($.matchAll(W));for(let Q of V){let Z=Q[0];if(Z=Z.replace(/[,。;:!?""''()【】《》]$/g,""),Z=Z.replace(/[,.;:!?"'()[\]<>]$/g,""),r.isValidFilePath(Z))b.push(Z)}}return b}static extractFilePathsFromToolCall($){let b=[];if($.type!=="function"||!$.function)return b;try{let w=$.function.name,W=JSON.parse($.function.arguments||"{}");if(["Read","Write","Edit","Glob","Grep","NotebookEdit","mcp__github__get_file_contents","mcp__github__create_or_update_file"].includes(w)){let Q=["file_path","path","notebook_path","filePath"];for(let Z of Q)if(W[Z]&&typeof W[Z]==="string")b.push(W[Z])}}catch{}return b}static updateFileReference($,b,w,W){let V=$.get(b);if(V)V.mentions++,V.lastMentioned=w,V.wasModified=V.wasModified||W;else $.set(b,{path:b,mentions:1,lastMentioned:w,wasModified:W})}static isValidFilePath($){if(!$.includes("/"))return!1;let b=JV($);if(!b.includes("."))return!1;let w=["ts","tsx","js","jsx","json","md","py","java","go","rs","c","cpp","h","css","scss","html","xml","yaml","yml","toml","sh","bash","sql","graphql","vue","svelte"],W=b.split(".").pop()?.toLowerCase();if(!W||!w.includes(W))return!1;return!0}}import{encodingForModel as p2}from"js-tiktoken";class Q${static encodingCache=new Map;static countTokens($,b){let w=Q$.getEncoding(b),W=0;for(let V of $){if(W+=4,V.role)W+=w.encode(V.role).length;if(V.content)if(typeof V.content==="string")W+=w.encode(V.content).length;else W+=w.encode(JSON.stringify(V.content)).length;if(V.tool_calls&&Array.isArray(V.tool_calls))W+=Q$.countToolCallTokens(V.tool_calls,w);if(V.name)W+=w.encode(V.name).length}return W}static getTokenLimit($){return $}static shouldCompact($,b,w,W=0.8){let V=Q$.countTokens($,b),Q=Math.floor(w*W);return V>=Q}static getEncoding($){if(!Q$.encodingCache.has($))try{let b=p2($);Q$.encodingCache.set($,b)}catch{try{let b=p2("gpt-4");Q$.encodingCache.set($,b)}catch{console.warn(`[TokenCounter] 无法为模型 ${$} 获取 encoding,使用粗略估算`),Q$.encodingCache.set($,{encode:(b)=>{return Array(Math.ceil(b.length/4))}})}}return Q$.encodingCache.get($)}static countToolCallTokens($,b){let w=0;for(let W of $){if(w+=4,W.type==="function"&&W.function?.name)w+=b.encode(W.function.name).length;if(W.type==="function"&&W.function?.arguments)w+=b.encode(W.function.arguments).length;if(W.id)w+=b.encode(W.id).length}return w}static clearCache(){Q$.encodingCache.clear()}static estimateTokens($){let b=($.match(/[\u4e00-\u9fa5]/g)||[]).length,w=$.length-b;return Math.ceil(b/1.5+w/4)}}class a{static THRESHOLD_PERCENT=0.8;static RETAIN_PERCENT=0.2;static FALLBACK_RETAIN_PERCENT=0.3;static async compact($,b){let w=b.actualPreTokens??Q$.countTokens($,b.modelName),W=b.actualPreTokens?"actual (from LLM usage)":"estimated";console.log(`[CompactionService] preTokens source: ${W}`);try{let Q=await c.getInstance().executeCompactionHooks(b.trigger,{projectDir:process.cwd(),sessionId:b.sessionId||"unknown",permissionMode:b.permissionMode||z.DEFAULT,messagesBefore:$.length,tokensBefore:w});if(Q.blockCompaction)return console.log(`[CompactionService] Compaction hook 阻止压缩: ${Q.blockReason||"(无原因)"}`),{success:!1,summary:"",preTokens:w,postTokens:w,filesIncluded:[],compactedMessages:$,boundaryMessage:{role:"system",content:""},summaryMessage:{role:"user",content:""},error:Q.blockReason||"Compaction blocked by hook"};if(Q.warning)console.warn(`[CompactionService] Compaction hook warning: ${Q.warning}`)}catch(V){console.warn("[CompactionService] Compaction hook execution failed:",V)}try{console.log("[CompactionService] 开始压缩,消息数:",$.length),console.log("[CompactionService] 压缩前 tokens:",w);let Q=r.analyzeFiles($).map((H)=>H.path);console.log("[CompactionService] 提取重点文件:",Q);let Z=await r.readFilesContent(Q);console.log("[CompactionService] 成功读取文件:",Z.length);let J=await a.generateSummary($,Z,b);console.log("[CompactionService] 生成总结,长度:",J.length);let Y=Math.ceil($.length*a.RETAIN_PERCENT),X=$.slice(-Y),O=new Set;for(let H of X)if(H.role==="assistant"&&H.tool_calls)for(let R of H.tool_calls)O.add(R.id);let G=X.filter((H)=>{if(H.role==="tool"&&H.tool_call_id)return O.has(H.tool_call_id);return!0});console.log("[CompactionService] 保留消息数:",Y),console.log("[CompactionService] 过滤后保留消息数:",G.length);let B=M0(),K=a.createBoundaryMessage(B,b.trigger,w),C=M0(),q=a.createSummaryMessage(C,J),F=[q,...G],U=Q$.countTokens(F,b.modelName);return console.log("[CompactionService] 压缩完成!"),console.log("[CompactionService] Token 变化:",w,"→",U,`(-${((1-U/w)*100).toFixed(1)}%)`),{success:!0,summary:J,preTokens:w,postTokens:U,filesIncluded:Q,compactedMessages:F,boundaryMessage:K,summaryMessage:q}}catch(V){return console.error("[CompactionService] 压缩失败,使用降级策略",V),a.fallbackCompact($,b,w,V)}}static async generateSummary($,b,w){let W=a.buildCompactionPrompt($,b);console.log("[CompactionService] 使用压缩模型:",w.modelName);let Z=(await(await lb({apiKey:w.apiKey||process.env.BLADE_API_KEY||"",baseUrl:w.baseURL||process.env.BLADE_BASE_URL||"https://api.openai.com/v1",model:w.modelName,temperature:0.3,maxOutputTokens:8000,timeout:60000,provider:"openai-compatible"})).chat([{role:"user",content:W}])).content||"",J=Z.match(/<summary>([\s\S]*?)<\/summary>/);if(!J)return console.warn("[CompactionService] 总结格式不正确,使用完整响应"),Z;return J[1].trim()}static buildCompactionPrompt($,b){let w=$.map((Q,Z)=>{let J=Q.role||"unknown",Y=typeof Q.content==="string"?Q.content:JSON.stringify(Q.content),X=5000,O=Y.length>5000?Y.substring(0,5000)+"...":Y;return`[${Z+1}] ${J}: ${O}`}).join(`
1839
1742
 
1840
- `+`请先使用以下命令添加模型:
1841
- `+` /model add
1743
+ `),W=b.map((Q)=>{return`### ${Q.path}
1744
+ \`\`\`
1745
+ ${Q.content}
1746
+ \`\`\``}).join(`
1842
1747
 
1843
- `+`或运行初始化向导:
1844
- `+" /init");let V=new P$($,b);if(await V.initialize(),b.toolWhitelist&&b.toolWhitelist.length>0)V.applyToolWhitelist(b.toolWhitelist);return V}async initialize(){if(this.isInitialized)return;try{this.log("初始化Agent..."),await this.initializeSystemPrompt(),await this.registerBuiltinTools(),await this.loadSubagents(),await this.discoverSkills();let $=this.resolveModelConfig(this.runtimeOptions.modelId);await this.applyModelConfig($,"\uD83D\uDE80 使用模型:"),this.attachmentHandler=new Hw(process.cwd()),this.streamHandler=new Mw(()=>this.chatService),this.compactionHandler=new _w(()=>this.chatService,()=>this.executionEngine?.getContextManager()),this.isInitialized=!0,this.log(`Agent初始化完成,已加载 ${this.executionPipeline.getRegistry().getAll().length} 个工具`)}catch($){throw this.error("Agent初始化失败",$),$}}async executeTask($){if(!this.isInitialized)throw Error("Agent未初始化");this.activeTask=$;try{this.log(`开始执行任务: ${$.id}`);let b=await this.executionEngine.executeTask($);return this.activeTask=void 0,this.log(`任务执行完成: ${$.id}`),b}catch(b){throw this.activeTask=void 0,this.error(`任务执行失败: ${$.id}`,b),b}}async chat($,b,w){if(!this.isInitialized)throw Error("Agent未初始化");let V=this.attachmentHandler?await this.attachmentHandler.processAtMentionsForContent($):$;if(b){let Y={signal:b.signal,...w},J;if(b.permissionMode==="plan")J=await this.runPlanLoop(V,b,Y);else J=await this.runLoop(V,b,Y);if(!J.success){if(J.error?.type==="aborted"||J.metadata?.shouldExitLoop)return"";throw Error(J.error?.message||"执行失败")}if(J.metadata?.targetMode&&b.permissionMode==="plan"){let X=J.metadata.targetMode,O=J.metadata.planContent;S.debug(`\uD83D\uDD04 Plan 模式已批准,切换到 ${X} 模式并重新执行`);let G={...b,permissionMode:X},B=V;if(O){let q=`
1748
+ `),V=`Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
1749
+ This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.
1845
1750
 
1846
- <approved-plan>
1847
- ${O}
1848
- </approved-plan>
1751
+ Before providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:
1849
1752
 
1850
- IMPORTANT: Execute according to the approved plan above. Follow the steps exactly as specified.`;if(typeof V==="string")B=V+q;else B=[...V,{type:"text",text:q}];S.debug(`\uD83D\uDCCB 已将 plan 内容注入到消息中 (${O.length} 字符)`)}return this.runLoop(B,G,Y).then((q)=>{if(!q.success)throw Error(q.error?.message||"执行失败");return q.finalMessage||""})}return J.finalMessage||""}let W=typeof V==="string"?V:V.filter((Y)=>Y.type==="text").map((Y)=>Y.text).join(`
1851
- `),Q={id:this.generateTaskId(),type:"simple",prompt:W};return(await this.executeTask(Q)).content}streamChat($,b,w){if(!this.isInitialized)throw Error("Agent未初始化");let W=(async()=>{let Z=this.attachmentHandler?await this.attachmentHandler.processAtMentionsForContent($):$;if(!b)throw Error("Context is required for streaming");let Y={signal:b.signal,...w};if(b.permissionMode==="plan"){let J=this.runPlanLoopStream(Z,b,Y),X,O=[];while(!0){let{value:G,done:B}=await J.next();if(B){X=G;break}O.push(G)}if(X?.metadata?.targetMode){let G=X.metadata.targetMode,B=X.metadata.planContent,q={...b,permissionMode:G},U=Z;if(B){let K=`
1753
+ 1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:
1754
+ - The user's explicit requests and intents
1755
+ - Your approach to addressing the user's requests
1756
+ - Key decisions, technical concepts and code patterns
1757
+ - Specific details like:
1758
+ - file names
1759
+ - full code snippets
1760
+ - function signatures
1761
+ - file edits
1762
+ - Errors that you ran into and how you fixed them
1763
+ - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
1764
+ 2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.
1852
1765
 
1853
- <approved-plan>
1854
- ${B}
1855
- </approved-plan>
1766
+ Your summary should include the following sections:
1856
1767
 
1857
- IMPORTANT: Execute according to the approved plan above. Follow the steps exactly as specified.`;if(typeof Z==="string")U=Z+K;else U=[...Z,{type:"text",text:K}]}return{events:O,continuation:this.runLoopStream(U,q,Y)}}return{events:O,result:X}}return{continuation:this.runLoopStream(Z,b,Y)}})();return async function*(){let Z=await W;if("events"in Z&&Z.events)for(let Y of Z.events)yield Y;if("continuation"in Z&&Z.continuation)return yield*Z.continuation;return Z.result}()}async runPlanLoop($,b,w){S.debug("\uD83D\uDD35 Processing Plan mode message...");let{prompt:V}=await U0({projectPath:process.cwd(),mode:v.PLAN,includeEnvironment:!0,language:this.config.language}),W;if(typeof $==="string")W=u$($);else{let Q=$.filter((Z)=>Z.type==="text");if(Q.length>0){let Z=Q[0];W=$.map((Y)=>Y===Z?{type:"text",text:u$(Z.text)}:Y)}else W=[{type:"text",text:u$("")},...$]}return this.executeLoop(W,b,w,V)}async*runPlanLoopStream($,b,w){let{prompt:V}=await U0({projectPath:process.cwd(),mode:v.PLAN,includeEnvironment:!0,language:this.config.language}),W;if(typeof $==="string")W=u$($);else{let Q=$.filter((Z)=>Z.type==="text");if(Q.length>0){let Z=Q[0];W=$.map((Y)=>Y===Z?{type:"text",text:u$(Z.text)}:Y)}else W=[{type:"text",text:u$("")},...$]}return yield*this.executeWithAgentLoop(W,b,w,V)}async runLoop($,b,w){S.debug("\uD83D\uDCAC Processing enhanced chat message...");let V=b.systemPrompt??await this.buildSystemPromptOnDemand(),W=d0(),Q=V?`${W}
1768
+ 1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail
1769
+ 2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.
1770
+ 3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
1771
+ 4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
1772
+ 5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
1773
+ 6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.
1774
+ 7. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
1775
+ 8. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
1776
+ 9. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request.`;return`Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
1777
+ This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.
1858
1778
 
1859
- ---
1779
+ Before providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:
1780
+
1781
+ 1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:
1782
+ - The user's explicit requests and intents
1783
+ - Your approach to addressing the user's requests
1784
+ - Key decisions, technical concepts and code patterns
1785
+ - Specific details like:
1786
+ - file names
1787
+ - full code snippets
1788
+ - function signatures
1789
+ - file edits
1790
+ - Errors that you ran into and how you fixed them
1791
+ - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
1792
+ 2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.
1793
+
1794
+ Your summary should include the following sections:
1795
+
1796
+ 1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail
1797
+ 2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.
1798
+ 3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
1799
+ 4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
1800
+ 5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
1801
+ 6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.
1802
+ 7. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
1803
+ 8. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
1804
+ 9. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request.
1805
+
1806
+ ## Conversation History
1807
+
1808
+ ${w}
1809
+
1810
+ ${b.length>0?`## Important Files
1860
1811
 
1861
- ${V}`:W;return this.executeLoop($,b,w,Q)}async*runLoopStream($,b,w){let V=b.systemPrompt??await this.buildSystemPromptOnDemand(),W=d0(),Q=V?`${W}
1812
+ ${W}`:""}
1813
+
1814
+ Please provide your summary following the structure specified above, with both <analysis> and <summary> sections.`}static createBoundaryMessage($,b,w){return{id:M0(),role:"system",content:"Conversation compacted",metadata:{type:"system",subtype:"compact_boundary",parentId:$,compactMetadata:{trigger:b,preTokens:w}}}}static createSummaryMessage($,b){return{id:M0(),role:"user",content:b,metadata:{parentId:$,isCompactSummary:!0}}}static fallbackCompact($,b,w,W){let V=Math.ceil($.length*a.FALLBACK_RETAIN_PERCENT),Q=$.slice(-V),Z=new Set;for(let q of Q)if(q.role==="assistant"&&q.tool_calls)for(let F of q.tool_calls)Z.add(F.id);let J=Q.filter((q)=>{if(q.role==="tool"&&q.tool_call_id)return Z.has(q.tool_call_id);return!0}),Y=M0(),X=a.createBoundaryMessage(Y,b.trigger,w),O=W instanceof Error?W.message:String(W),G=M0(),B=a.createSummaryMessage(G,`[Automatic compaction failed; using fallback]
1815
+
1816
+ An error occurred during compaction. Retained the latest ${V} messages (~30%).
1817
+
1818
+ Error: ${O}
1819
+
1820
+ The conversation can continue, but consider retrying compaction later with /compact.`),K=[B,...J],C=Q$.countTokens(K,b.modelName);return{success:!1,summary:typeof B.content==="string"?B.content:B.content.filter((q)=>q.type==="text").map((q)=>q.text).join(`
1821
+ `),preTokens:w,postTokens:C,filesIncluded:[],compactedMessages:K,boundaryMessage:X,summaryMessage:B,error:O}}}var R$=E("Agent");class Sw{getChatService;getContextManager;constructor($,b){this.getChatService=$;this.getContextManager=b}async*checkAndCompactInLoop($,b,w){if(w===void 0)return R$.debug(`[Agent] [轮次 ${b}] 压缩检查: 跳过(无历史 usage 数据)`),!1;let V=this.getChatService().getConfig(),Q=V.model,Z=V.maxContextTokens??128000,J=V.maxOutputTokens??8192,Y=Z-J,X=Math.floor(Y*0.8);if(R$.debug(`[Agent] [轮次 ${b}] 压缩检查:`,{promptTokens:w,maxContextTokens:Z,maxOutputTokens:J,availableForInput:Y,threshold:X,shouldCompact:w>=X}),w<X)return!1;let O=b===0?"[Agent] 触发自动压缩":`[Agent] [轮次 ${b}] 触发循环内自动压缩`;R$.debug(O),yield{type:"compacting",isCompacting:!0};try{let G=await a.compact($.messages,{trigger:"auto",modelName:Q,maxContextTokens:Z,apiKey:V.apiKey,baseURL:V.baseUrl,actualPreTokens:w});if(G.success)$.messages=G.compactedMessages,R$.debug(`[Agent] [轮次 ${b}] 压缩完成: ${G.preTokens} → ${G.postTokens} tokens (-${((1-G.postTokens/G.preTokens)*100).toFixed(1)}%)`);else $.messages=G.compactedMessages,R$.warn(`[Agent] [轮次 ${b}] 压缩使用降级策略: ${G.preTokens} → ${G.postTokens} tokens`);try{let B=this.getContextManager();if(B&&$.sessionId)await B.saveCompaction($.sessionId,G.summary,{trigger:"auto",preTokens:G.preTokens,postTokens:G.postTokens,filesIncluded:G.filesIncluded},null),R$.debug(`[Agent] [轮次 ${b}] 压缩数据已保存到 JSONL`)}catch(B){R$.warn(`[Agent] [轮次 ${b}] 保存压缩数据失败:`,B)}return yield{type:"compacting",isCompacting:!1},!0}catch(G){return yield{type:"compacting",isCompacting:!1},R$.error(`[Agent] [轮次 ${b}] 压缩失败,继续执行`,G),!1}}async compactOnTurnLimit($,b,w){try{let V=this.getChatService().getConfig(),Q=await a.compact($.messages,{trigger:"auto",modelName:V.model,maxContextTokens:V.maxContextTokens??128000,apiKey:V.apiKey,baseURL:V.baseUrl,actualPreTokens:w});$.messages=Q.compactedMessages;let Z=b.find((X)=>X.role==="system"),J=[];if(Z)J.push(Z);J.push(...$.messages);let Y={role:"user",content:`This session is being continued from a previous conversation. The conversation is summarized above.
1822
+
1823
+ Please continue the conversation from where we left it off without asking the user any further questions. Continue with the last task that you were asked to work on.`};J.push(Y),$.messages.push(Y);try{let X=this.getContextManager();if(X&&$.sessionId)await X.saveCompaction($.sessionId,Q.summary,{trigger:"auto",preTokens:Q.preTokens,postTokens:Q.postTokens,filesIncluded:Q.filesIncluded},null)}catch(X){R$.warn("[Agent] 保存压缩数据失败:",X)}return R$.info(`✅ 上下文已压缩 (${Q.preTokens} → ${Q.postTokens} tokens),重置轮次计数`),{success:!0,messages:J}}catch(W){R$.error("[Agent] 压缩失败,使用降级策略:",W);let V=b.find((J)=>J.role==="system"),Q=b.slice(-80),Z=[];if(V&&!Q.some((J)=>J.role==="system"))Z.push(V);return Z.push(...Q),$.messages=Z.filter((J)=>J.role!=="system"),R$.warn(`⚠️ 降级压缩完成,保留 ${Z.length} 条消息`),{success:!1,messages:Z}}}}var YV=E("Agent"),XV=[/:\s*$/,/:\s*$/,/\.\.\.\s*$/,/让我(先|来|开始|查看|检查|修复)/,/Let me (first|start|check|look|fix)/i],d2="请执行你提到的操作,不要只是描述。";function OV($){return XV.some((b)=>b.test($))}function GV($){return $.slice(-10).filter((b)=>b.role==="user"&&b.content===d2).length}async function*yw($){let{chatService:b,streamHandler:w,executionPipeline:W,tools:V,messages:Q,maxTurns:Z,isYoloMode:J,signal:Y,permissionMode:X,maxContextTokens:O,executionContext:G}=$,B=100,K=J?100:Z,C=Date.now(),q=0,F=[],U=0,H;yield{type:"agent_start"};while(!0){if(Y?.aborted)return yield{type:"agent_end"},Zb(q,F.length,C);if($.onBeforeTurn){let D=$.onBeforeTurn({turn:q,messages:Q,lastPromptTokens:H});while(!0){let{value:S,done:l}=await D.next();if(l)break;yield S}}if(q++,yield{type:"turn_start",turn:q,maxTurns:K},Y?.aborted)return yield{type:"agent_end"},Zb(q-1,F.length,C);let R;if(w){let D=w.streamResponse(Q,V,Y);while(!0){let{value:S,done:l}=await D.next();if(l){R=S;break}if(S.type==="content_delta")yield{type:"content_delta",delta:S.delta};else yield{type:"thinking_delta",delta:S.delta}}}else R=await b.chat(Q,V,Y);if(R.usage){if(R.usage.totalTokens)U+=R.usage.totalTokens;H=R.usage.promptTokens,yield{type:"token_usage",usage:{inputTokens:R.usage.promptTokens??0,outputTokens:R.usage.completionTokens??0,totalTokens:U,maxContextTokens:O}}}if(Y?.aborted)return yield{type:"agent_end"},Zb(q-1,F.length,C);if(R.reasoningContent&&!Y?.aborted)yield{type:"thinking",content:R.reasoningContent};if(R.content?.trim()&&!Y?.aborted)yield{type:"stream_end"};if(!R.toolCalls||R.toolCalls.length===0){let D=R.content||"";if(OV(D)&&GV(Q)<2){Q.push({role:"user",content:d2}),yield{type:"turn_end",turn:q,hasToolCalls:!1};continue}if($.onStopCheck){let S=await $.onStopCheck({content:D,turn:q});if(!S.shouldStop){let l=S.continueReason?`
1824
+
1825
+ <system-reminder>
1826
+ ${S.continueReason}
1827
+ </system-reminder>`:`
1828
+
1829
+ <system-reminder>
1830
+ Please continue the conversation from where we left it off without asking the user any further questions. Continue with the last task that you were asked to work on.
1831
+ </system-reminder>`;Q.push({role:"user",content:l}),yield{type:"turn_end",turn:q,hasToolCalls:!1};continue}}return await $.onComplete?.({content:D,turn:q}),yield{type:"turn_end",turn:q,hasToolCalls:!1},yield{type:"agent_end"},{success:!0,finalMessage:R.content,metadata:{turnsCount:q,toolCallsCount:F.length,duration:Date.now()-C,tokensUsed:U}}}Q.push({role:"assistant",content:R.content||"",reasoningContent:R.reasoningContent,tool_calls:R.toolCalls}),await $.onAssistantMessage?.({content:R.content||"",reasoningContent:R.reasoningContent,toolCalls:R.toolCalls,turn:q});let T=R.toolCalls.filter((D)=>D.type==="function");for(let D of T){let l=W.getRegistry().get(D.function.name)?.kind;yield{type:"tool_start",toolCall:D,toolKind:l}}if(Y?.aborted)return yield{type:"agent_end"},Zb(q,F.length,C);let N=await Promise.all(T.map((D)=>BV(D,W,G,$,Y)));for(let{toolCall:D,result:S,toolUseUuid:l}of N){if(F.push(S),S.metadata?.shouldExitLoop){let q$=typeof S.llmContent==="string"?S.llmContent:"循环已退出";return yield{type:"tool_result",toolCall:D,result:S},yield{type:"turn_end",turn:q,hasToolCalls:!0},yield{type:"agent_end"},{success:S.success,finalMessage:q$,metadata:{turnsCount:q,toolCallsCount:F.length,duration:Date.now()-C,shouldExitLoop:!0,targetMode:S.metadata?.targetMode}}}yield{type:"tool_result",toolCall:D,result:S},await $.onAfterToolExec?.({toolCall:D,result:S,toolUseUuid:l});let y=S.success?S.llmContent||S.displayContent||"":S.error?.message||"执行失败";if(typeof y==="object"&&y!==null)y=JSON.stringify(y,null,2);Q.push({role:"tool",tool_call_id:D.id,name:D.function.name,content:typeof y==="string"?y:JSON.stringify(y)})}if(yield{type:"turn_end",turn:q,hasToolCalls:!0},Y?.aborted)return yield{type:"agent_end"},Zb(q,F.length,C);if(q>=K&&!J){let D=await KV($,Q,q,F.length,C,U,H);if(D.action==="stop")return yield{type:"agent_end"},D.result;q=0;continue}}}function Zb($,b,w){return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:$,toolCallsCount:b,duration:Date.now()-w}}}async function BV($,b,w,W,V){try{let Q=JSON.parse($.function.arguments);if($.function.name==="Task"&&(typeof Q.subagent_session_id!=="string"||Q.subagent_session_id.length===0)){let{nanoid:Y}=await import("nanoid");Q.subagent_session_id=typeof Q.resume==="string"&&Q.resume.length>0?Q.resume:Y()}if(Q.todos&&typeof Q.todos==="string")try{Q.todos=JSON.parse(Q.todos)}catch{}let Z=await W.onBeforeToolExec?.({toolCall:$,params:Q})??null,J=await b.execute($.function.name,Q,{sessionId:w.sessionId,userId:w.userId,workspaceRoot:w.workspaceRoot,signal:V,confirmationHandler:w.confirmationHandler,permissionMode:W.permissionMode});return{toolCall:$,result:J,toolUseUuid:Z}}catch(Q){return YV.error(`Tool execution failed for ${$.function.name}:`,Q),{toolCall:$,result:{success:!1,llmContent:"",displayContent:"",error:{type:"execution_error",message:Q instanceof Error?Q.message:"Unknown error"}},toolUseUuid:null}}}async function KV($,b,w,W,V,Q,Z){if($.onTurnLimitReached){if((await $.onTurnLimitReached({turnsCount:w}))?.continue){if($.onTurnLimitCompact){let Y=await $.onTurnLimitCompact({messages:b,contextMessages:b.filter((X)=>X.role!=="system")});if(Y.success&&Y.compactedMessages){let X=b.find((O)=>O.role==="system");if(b.length=0,X)b.push(X);if(b.push(...Y.compactedMessages),Y.continueMessage)b.push(Y.continueMessage)}}return{action:"continue",result:{success:!0,metadata:{turnsCount:w,toolCallsCount:W,duration:Date.now()-V}}}}return{action:"stop",result:{success:!0,metadata:{turnsCount:w,toolCallsCount:W,duration:Date.now()-V,tokensUsed:Q,configuredMaxTurns:$.maxTurns,actualMaxTurns:$.maxTurns}}}}return{action:"stop",result:{success:!1,error:{type:"max_turns_exceeded",message:`达到最大轮次限制 (${$.maxTurns})`},metadata:{turnsCount:w,toolCallsCount:W,duration:Date.now()-V,tokensUsed:Q}}}}function qV($){if(typeof $==="string")return $;try{return JSON.parse(JSON.stringify($))}catch{return String($)}}var H$=E("Agent");class Mw{config;runtimeOptions;modelManager;executionPipeline;streamHandler;compactionHandler;activeSkillContext;constructor($,b,w,W,V,Q){this.config=$;this.runtimeOptions=b;this.modelManager=w;this.executionPipeline=W;this.streamHandler=V;this.compactionHandler=Q}async runLoop($,b,w){H$.debug("\uD83D\uDCAC Processing enhanced chat message...");let W=await this.buildNormalSystemPrompt(b);return this.executeLoop($,b,w,W)}async*runLoopStream($,b,w){let W=await this.buildNormalSystemPrompt(b);return yield*this.executeWithAgentLoop($,b,w,W)}async executeLoop($,b,w,W){let V=this.executeWithAgentLoop($,b,w,W),Q;while(!0){let{value:Z,done:J}=await V.next();if(J){Q=Z;break}}return Q}async*executeWithAgentLoop($,b,w,W){let V=this.executionPipeline.getRegistry(),Q=b.permissionMode,Z=V.getFunctionDeclarationsByMode(Q);Z=Hb(Z);let J=this.applySkillToolRestrictions(Z),Y=b.messages.length===0||!b.messages.some((F)=>F.role==="system"),X=[];if(Y&&W)X.push({role:"system",content:[{type:"text",text:W,providerOptions:{anthropic:{cacheControl:{type:"ephemeral"}}}}]});X.push(...b.messages,{role:"user",content:$});let O=null;try{let F=this.modelManager.getExecutionEngine()?.getContextManager(),U=typeof $==="string"?$:$.filter((H)=>H.type==="text").map((H)=>H.text).join(`
1832
+ `);if(F&&b.sessionId&&U.trim()!=="")O=await F.saveMessage(b.sessionId,"user",U,null,void 0,b.subagentInfo)}catch(F){H$.warn("[LoopRunner] 保存用户消息失败:",F)}let G=100,B=b.permissionMode===z.YOLO,K=this.runtimeOptions.maxTurns??w?.maxTurns??this.config.maxTurns??-1;if(K===0)return{success:!1,error:{type:"chat_disabled",message:"对话功能已被禁用 (maxTurns=0)"},metadata:{turnsCount:0,toolCallsCount:0,duration:0}};let C=K===-1?G:Math.min(K,G),q=this.buildLoopConfig(b,w,X,J,C,B,Q,()=>O,(F)=>{O=F});try{let F=yw(q),U;while(!0){let{value:H,done:R}=await F.next();if(R){U=H;break}yield H}if(!U)throw Error("AgentLoop ended without result");return b.messages=X.filter((H)=>H.role!=="system"),U}catch(F){if(F instanceof Error&&(F.name==="AbortError"||F.message.includes("aborted")))return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:0,toolCallsCount:0,duration:0}};return H$.error("[LoopRunner] AgentLoop error:",F),{success:!1,error:{type:"api_error",message:`处理消息时发生错误: ${F instanceof Error?F.message:"未知错误"}`,details:F},metadata:{turnsCount:0,toolCallsCount:0,duration:0}}}}async buildNormalSystemPrompt($){let b=$.systemPrompt??await this.buildSystemPromptOnDemand(),w=_b();return b?`${w}
1862
1833
 
1863
1834
  ---
1864
1835
 
1865
- ${V}`:W;return yield*this.executeWithAgentLoop($,b,w,Q)}async buildSystemPromptOnDemand(){let $=this.runtimeOptions.systemPrompt,b=this.runtimeOptions.appendSystemPrompt;return(await U0({projectPath:process.cwd(),replaceDefault:$,append:b,includeEnvironment:!1,language:this.config.language})).prompt}async executeLoop($,b,w,V){let W=this.executeWithAgentLoop($,b,w,V),Q;while(!0){let{value:Z,done:Y}=await W.next();if(Y){Q=Z;break}}return Q}async*executeWithAgentLoop($,b,w,V){if(!this.isInitialized)throw Error("Agent未初始化");let W=this.executionPipeline.getRegistry(),Q=b.permissionMode,Z=W.getFunctionDeclarationsByMode(Q);Z=Cb(Z);let Y=this.applySkillToolRestrictions(Z),J=b.messages.length===0||!b.messages.some((C)=>C.role==="system"),X=[];if(J&&V)X.push({role:"system",content:[{type:"text",text:V,providerOptions:{anthropic:{cacheControl:{type:"ephemeral"}}}}]});X.push(...b.messages,{role:"user",content:$});let O=null;try{let C=this.executionEngine?.getContextManager(),H=typeof $==="string"?$:$.filter((F)=>F.type==="text").map((F)=>F.text).join(`
1866
- `);if(C&&b.sessionId&&H.trim()!=="")O=await C.saveMessage(b.sessionId,"user",H,null,void 0,b.subagentInfo)}catch(C){S.warn("[Agent] 保存用户消息失败:",C)}let G=100,B=b.permissionMode===v.YOLO,q=this.runtimeOptions.maxTurns??w?.maxTurns??this.config.maxTurns??-1;if(q===0)return{success:!1,error:{type:"chat_disabled",message:"对话功能已被禁用 (maxTurns=0)"},metadata:{turnsCount:0,toolCallsCount:0,duration:0}};let U=q===-1?G:Math.min(q,G),K=this,_={chatService:this.chatService,streamHandler:this.streamHandler,executionPipeline:this.executionPipeline,tools:Y,messages:X,maxTurns:U,isYoloMode:B,signal:w?.signal,permissionMode:Q,maxContextTokens:this.currentModelMaxContextTokens,executionContext:{sessionId:b.sessionId,userId:b.userId||"default",workspaceRoot:b.workspaceRoot||process.cwd(),confirmationHandler:b.confirmationHandler},async*onBeforeTurn(C){if(!K.compactionHandler)return!1;let H=K.compactionHandler.checkAndCompactInLoop(b,C.turn,C.lastPromptTokens),F=!1;while(!0){let{value:M,done:L}=await H.next();if(L){F=M;break}yield M}return F},async onAssistantMessage(C){try{let H=K.executionEngine?.getContextManager();if(H&&b.sessionId&&C.content.trim()!=="")O=await H.saveMessage(b.sessionId,"assistant",C.content,O,void 0,b.subagentInfo)}catch(H){S.warn("[Agent] 保存助手消息失败:",H)}},async onBeforeToolExec(C){try{let H=K.executionEngine?.getContextManager();if(H&&b.sessionId)return await H.saveToolUse(b.sessionId,C.toolCall.function.name,C.params,O,b.subagentInfo)}catch(H){S.warn("[Agent] 保存工具调用失败:",H)}return null},async onAfterToolExec(C){let{toolCall:H,result:F,toolUseUuid:M}=C;try{let R=K.executionEngine?.getContextManager();if(R&&b.sessionId){let D=F.metadata&&typeof F.metadata==="object"?F.metadata:void 0,y=((F$)=>F$==="running"||F$==="completed"||F$==="failed"||F$==="cancelled")(D?.subagentStatus)?D.subagentStatus:"completed",l=D&&typeof D.subagentSessionId==="string"?{subagentSessionId:D.subagentSessionId,subagentType:typeof D.subagentType==="string"?D.subagentType:H.function.name,subagentStatus:y,subagentSummary:typeof D.subagentSummary==="string"?D.subagentSummary:void 0}:void 0;O=await R.saveToolResult(b.sessionId,H.id,H.function.name,F.success?bW(F.llmContent):null,M,F.success?void 0:F.error?.message,b.subagentInfo,l)}}catch(R){S.warn("[Agent] 保存工具结果失败:",R)}if(H.function.name==="Skill"&&F.success&&F.metadata){let R=F.metadata;if(R.skillName)K.activeSkillContext={skillName:R.skillName,allowedTools:R.allowedTools,basePath:R.basePath||""}}let L=F.metadata?.modelId?.trim()||F.metadata?.model?.trim()||void 0;if(L)await K.switchModelIfNeeded(L)},async onComplete(C){try{let H=K.executionEngine?.getContextManager();if(H&&b.sessionId&&C.content.trim()!=="")O=await H.saveMessage(b.sessionId,"assistant",C.content,O,void 0,b.subagentInfo)}catch(H){S.warn("[Agent] 保存助手消息失败:",H)}},async onStopCheck(C){try{let F=await m.getInstance().executeStopHooks({projectDir:process.cwd(),sessionId:b.sessionId,permissionMode:b.permissionMode,reason:C.content,abortSignal:w?.signal});return{shouldStop:F.shouldStop,continueReason:F.continueReason,warning:F.warning}}catch{return{shouldStop:!0}}},onTurnLimitReached:w?.onTurnLimitReached,async onTurnLimitCompact(C){try{let H=K.chatService.getConfig(),F=await r.compact(b.messages,{trigger:"auto",modelName:H.model,maxContextTokens:H.maxContextTokens??128000,apiKey:H.apiKey,baseURL:H.baseUrl});b.messages=F.compactedMessages;let M={role:"user",content:`This session is being continued from a previous conversation. The conversation is summarized above.
1836
+ ${b}`:w}async buildSystemPromptOnDemand(){let $=this.runtimeOptions.systemPrompt,b=this.runtimeOptions.appendSystemPrompt;return(await $0({projectPath:process.cwd(),replaceDefault:$,append:b,includeEnvironment:!1,language:this.config.language})).prompt}get skillContext(){return this.activeSkillContext}setSkillContext($){this.activeSkillContext=$}clearSkillContext(){if(this.activeSkillContext)H$.debug(`\uD83C\uDFAF Skill "${this.activeSkillContext.skillName}" deactivated`),this.activeSkillContext=void 0}applySkillToolRestrictions($){if(!this.activeSkillContext?.allowedTools)return $;let b=this.activeSkillContext.allowedTools;H$.debug(`\uD83D\uDD12 Applying Skill tool restrictions: ${b.join(", ")}`);let w=$.filter((W)=>{return b.some((V)=>{if(V===W.name)return!0;let Q=V.match(/^(\w+)\(.*\)$/);if(Q&&Q[1]===W.name)return!0;return!1})});return H$.debug(`\uD83D\uDD12 Filtered tools: ${w.map((W)=>W.name).join(", ")} (${w.length}/${$.length})`),w}buildLoopConfig($,b,w,W,V,Q,Z,J,Y){let X=this,O=this.modelManager.getChatService();return{chatService:O,streamHandler:this.streamHandler,executionPipeline:this.executionPipeline,tools:W,messages:w,maxTurns:V,isYoloMode:Q,signal:b?.signal,permissionMode:Z,maxContextTokens:this.modelManager.getMaxContextTokens(),executionContext:{sessionId:$.sessionId,userId:$.userId||"default",workspaceRoot:$.workspaceRoot||process.cwd(),confirmationHandler:$.confirmationHandler},async*onBeforeTurn(G){if(!X.compactionHandler)return!1;let B=X.compactionHandler.checkAndCompactInLoop($,G.turn,G.lastPromptTokens),K=!1;while(!0){let{value:C,done:q}=await B.next();if(q){K=C;break}yield C}return K},async onAssistantMessage(G){try{let B=X.modelManager.getExecutionEngine()?.getContextManager();if(B&&$.sessionId&&G.content.trim()!==""){let K=await B.saveMessage($.sessionId,"assistant",G.content,J(),void 0,$.subagentInfo);Y(K)}}catch(B){H$.warn("[LoopRunner] 保存助手消息失败:",B)}},async onBeforeToolExec(G){try{let B=X.modelManager.getExecutionEngine()?.getContextManager();if(B&&$.sessionId)return await B.saveToolUse($.sessionId,G.toolCall.function.name,G.params,J(),$.subagentInfo)}catch(B){H$.warn("[LoopRunner] 保存工具调用失败:",B)}return null},async onAfterToolExec(G){let{toolCall:B,result:K,toolUseUuid:C}=G;try{let F=X.modelManager.getExecutionEngine()?.getContextManager();if(F&&$.sessionId){let U=K.metadata,R=((D)=>D==="running"||D==="completed"||D==="failed"||D==="cancelled")(U?.subagentStatus)?U.subagentStatus:"completed",T=U&&typeof U.subagentSessionId==="string"?{subagentSessionId:U.subagentSessionId,subagentType:typeof U.subagentType==="string"?U.subagentType:B.function.name,subagentStatus:R,subagentSummary:typeof U.subagentSummary==="string"?U.subagentSummary:void 0}:void 0,N=await F.saveToolResult($.sessionId,B.id,B.function.name,K.success?qV(K.llmContent):null,C,K.success?void 0:K.error?.message,$.subagentInfo,T);Y(N)}}catch(F){H$.warn("[LoopRunner] 保存工具结果失败:",F)}if(B.function.name==="Skill"&&K.success&&K.metadata){let F=K.metadata;if(F.skillName&&typeof F.skillName==="string")X.activeSkillContext={skillName:F.skillName,allowedTools:Array.isArray(F.allowedTools)?F.allowedTools:void 0,basePath:typeof F.basePath==="string"?F.basePath:""}}let q=K.metadata?.modelId?.trim()||K.metadata?.model?.trim()||void 0;if(q)await X.modelManager.switchModelIfNeeded(q)},async onComplete(G){try{let B=X.modelManager.getExecutionEngine()?.getContextManager();if(B&&$.sessionId&&G.content.trim()!==""){let K=await B.saveMessage($.sessionId,"assistant",G.content,J(),void 0,$.subagentInfo);Y(K)}}catch(B){H$.warn("[LoopRunner] 保存助手消息失败:",B)}},async onStopCheck(G){try{let K=await c.getInstance().executeStopHooks({projectDir:process.cwd(),sessionId:$.sessionId,permissionMode:$.permissionMode??z.DEFAULT,reason:G.content,abortSignal:b?.signal});return{shouldStop:K.shouldStop,continueReason:K.continueReason,warning:K.warning}}catch{return{shouldStop:!0}}},onTurnLimitReached:b?.onTurnLimitReached,async onTurnLimitCompact(G){try{let B=O.getConfig(),K=await a.compact($.messages,{trigger:"auto",modelName:B.model,maxContextTokens:B.maxContextTokens??128000,apiKey:B.apiKey,baseURL:B.baseUrl});$.messages=K.compactedMessages;let C={role:"user",content:`This session is being continued from a previous conversation. The conversation is summarized above.
1837
+
1838
+ Please continue the conversation from where we left it off without asking the user any further questions. Continue with the last task that you were asked to work on.`};$.messages.push(C);try{let q=X.modelManager.getExecutionEngine()?.getContextManager();if(q&&$.sessionId)await q.saveCompaction($.sessionId,K.summary,{trigger:"auto",preTokens:K.preTokens,postTokens:K.postTokens,filesIncluded:K.filesIncluded},null)}catch(q){H$.warn("[LoopRunner] 保存压缩数据失败:",q)}return{success:!0,compactedMessages:K.compactedMessages,continueMessage:C}}catch(B){H$.error("[LoopRunner] 压缩失败,使用降级策略:",B);let K=$.messages.slice(-80);return $.messages=K,{success:!0,compactedMessages:K}}}}}}var AV=[/deepseek.*r1/i,/deepseek.*reasoner/i,/o1-preview/i,/o1-mini/i,/o1/i,/qwen.*qwq/i,/qwen.*think/i,/kimi.*k1/i,/moonshot.*think/i,/k1-32k/i,/doubao.*think/i,/doubao.*pro.*think/i,/claude.*opus.*4/i,/glm-4\.7/i];function u2($){return AV.some((b)=>b.test($))}function g2($){if($.supportsThinking!==void 0)return{supportsThinking:$.supportsThinking,thinkingBudget:$.thinkingBudget};return{supportsThinking:u2($.model),thinkingBudget:void 0}}function zw($){return g2($).supportsThinking}import*as l2 from"crypto";import{nanoid as i2}from"nanoid";class vw{maxSummaryLength;keyPointsLimit;recentMessagesLimit;constructor($=500,b=10,w=20){this.maxSummaryLength=$,this.keyPointsLimit=b,this.recentMessagesLimit=w}async compress($){let b=$.layers.conversation.messages,w=$.layers.tool.recentCalls,W=b.filter((G)=>G.role==="system"),V=b.filter((G)=>G.role!=="system"),Q=this.getRecentMessages(V),Z=V.slice(0,-this.recentMessagesLimit),J=await this.generateSummary(Z),Y=this.extractKeyPoints(Z,w),X=this.generateToolSummary(w),O=this.estimateTokenCount(J,Y,Q,X);return{summary:J,keyPoints:Y,recentMessages:[...W,...Q],toolSummary:X,tokenCount:O}}getRecentMessages($){return $.slice(-this.recentMessagesLimit)}async generateSummary($){if($.length===0)return"";let b=new Set,w=new Set,W=new Set;for(let Q of $){let Z=Q.content.toLowerCase();["关于","讨论","问题","项目","功能","需求"].forEach((O)=>{if(Z.includes(O)){let G=this.extractContext(Z,O,50);if(G)b.add(G)}}),["创建","删除","修改","更新","实现","开发"].forEach((O)=>{if(Z.includes(O)){let G=this.extractContext(Z,O,30);if(G)w.add(G)}}),["决定","选择","确定","采用","使用"].forEach((O)=>{if(Z.includes(O)){let G=this.extractContext(Z,O,40);if(G)W.add(G)}})}let V=`对话涉及 ${$.length} 条消息。`;if(b.size>0)V+=` 主要讨论:${Array.from(b).slice(0,3).join("、")}。`;if(w.size>0)V+=` 执行操作:${Array.from(w).slice(0,3).join("、")}。`;if(W.size>0)V+=` 关键决策:${Array.from(W).slice(0,2).join("、")}。`;return V.length>this.maxSummaryLength?V.substring(0,this.maxSummaryLength)+"...":V}extractKeyPoints($,b){let w=new Set;for(let V of $)if(V.role==="user")this.extractQuestions(V.content).forEach((J)=>w.add(`用户问题:${J}`)),this.extractRequests(V.content).forEach((J)=>w.add(`用户请求:${J}`));else if(V.role==="assistant")this.extractSolutions(V.content).forEach((Z)=>w.add(`解决方案:${Z}`));return this.summarizeToolUsage(b).forEach((V)=>w.add(`工具使用:${V}`)),Array.from(w).slice(0,this.keyPointsLimit)}generateToolSummary($){if($.length===0)return"";let b=new Map,w=Date.now()-600000;for(let V of $){let Q=b.get(V.name)||{count:0,success:0,recent:0};if(Q.count++,V.status==="success")Q.success++;if(V.timestamp>w)Q.recent++;b.set(V.name,Q)}let W=[];for(let[V,Q]of Array.from(b.entries())){let Z=Math.round(Q.success/Q.count*100);W.push(`${V}(${Q.count}次,成功率${Z}%)`)}return`工具调用:${W.join("、")}`}estimateTokenCount($,b,w,W){let V=$.length+b.join(" ").length;if(W)V+=W.length;for(let Q of w)V+=Q.content.length;return Math.ceil(V/4)}extractContext($,b,w){let W=$.indexOf(b);if(W===-1)return null;let V=Math.max(0,W-w/2),Q=Math.min($.length,W+w/2);return $.substring(V,Q).trim()}extractQuestions($){let b=[],w=["?","?","如何","怎么","什么","为什么"],W=$.split(/[。!.!]/);for(let V of W)if(w.some((Q)=>V.includes(Q))){let Q=V.trim();if(Q.length>5&&Q.length<100)b.push(Q)}return b.slice(0,3)}extractRequests($){let b=[],w=["请","帮我","需要","想要","希望","能否"],W=$.split(/[。!.!]/);for(let V of W)if(w.some((Q)=>V.includes(Q))){let Q=V.trim();if(Q.length>5&&Q.length<100)b.push(Q)}return b.slice(0,3)}extractSolutions($){let b=[],w=["可以","建议","推荐","应该","最好","解决方案"],W=$.split(/[。!.!]/);for(let V of W)if(w.some((Q)=>V.includes(Q))){let Q=V.trim();if(Q.length>10&&Q.length<150)b.push(Q)}return b.slice(0,3)}summarizeToolUsage($){let b=[],w=$.filter((W)=>Date.now()-W.timestamp<1800000);if(w.length>0){let W=new Map;w.forEach((V)=>{let Q=W.get(V.name)||[];Q.push(V),W.set(V.name,Q)});for(let[V,Q]of Array.from(W.entries())){let Z=Q.filter((J)=>J.status==="success").length;b.push(`${V}(${Q.length}次,${Z}成功)`)}}return b.slice(0,5)}shouldCompress($,b){return this.estimateCurrentTokens($)>b*0.8}estimateCurrentTokens($){let w=$.layers.conversation.messages.reduce((W,V)=>W+V.content.length,0);return Math.ceil(w/4)}}class q0{defaultOptions;constructor($){this.defaultOptions={maxTokens:32000,maxMessages:50,timeWindow:86400000,priority:1,includeTools:!0,includeWorkspace:!0,...$}}filter($,b){let w={...this.defaultOptions,...b},W={layers:{system:$.layers.system,session:$.layers.session,conversation:this.filterConversation($.layers.conversation,w),tool:w.includeTools?this.filterTools($.layers.tool,w):{recentCalls:[],toolStates:{},dependencies:{}},workspace:w.includeWorkspace?$.layers.workspace:{currentFiles:[],recentFiles:[],environment:{}}},metadata:{...$.metadata,lastUpdated:Date.now()}};return W.metadata.totalTokens=this.estimateTokens(W),W}filterConversation($,b){let w=[...$.messages];if(b.timeWindow>0){let W=Date.now()-b.timeWindow;w=w.filter((V)=>V.timestamp>=W||V.role==="system")}if(b.priority>1)w=this.filterByPriority(w,b.priority);if(b.maxMessages>0)w=this.limitMessages(w,b.maxMessages);if(b.maxTokens>0)w=this.limitByTokens(w,b.maxTokens);return{messages:w,summary:$.summary,topics:this.updateTopics(w,$.topics),lastActivity:$.lastActivity}}filterTools($,b){let w=[...$.recentCalls];if(b.timeWindow>0){let Y=Date.now()-b.timeWindow;w=w.filter((X)=>X.timestamp>=Y)}let W=w.filter((Y)=>Y.status==="success"),V=w.filter((Y)=>Y.status==="error"),Q=Math.min(20,W.length),Z=Math.min(10,V.length);return{recentCalls:[...W.slice(-Q),...V.slice(-Z)].sort((Y,X)=>Y.timestamp-X.timestamp),toolStates:$.toolStates,dependencies:$.dependencies}}filterByPriority($,b){return $.filter((w)=>{if(w.role==="system")return!0;return this.calculateMessagePriority(w)>=b})}calculateMessagePriority($){let b=1;if($.role==="system")b+=3;else if($.role==="assistant")b+=1;let w=$.content.toLowerCase();if(["错误","警告","重要","关键","问题","解决"].some((Q)=>w.includes(Q)))b+=2;if(w.includes("```")||w.includes("function")||w.includes("class"))b+=1;let V=(Date.now()-$.timestamp)/3600000;if(V<1)b+=2;else if(V<6)b+=1;return b}limitMessages($,b){if($.length<=b)return $;let w=$.filter((Z)=>Z.role==="system"),W=$.filter((Z)=>Z.role!=="system"),V=b-w.length,Q=V>0?W.slice(-V):[];return[...w,...Q].sort((Z,J)=>Z.timestamp-J.timestamp)}limitByTokens($,b){if(b<=0)return $;let w=0,W=[];for(let V=$.length-1;V>=0;V--){let Q=$[V],Z=this.estimateMessageTokens(Q);if(Q.role==="system")if(w+Z<=b)W.unshift(Q),w+=Z;else{let J=this.compressMessage(Q,b-w);W.unshift(J),w+=this.estimateMessageTokens(J)}else if(w+Z<=b)W.unshift(Q),w+=Z;else break}return W.sort((V,Q)=>V.timestamp-Q.timestamp)}estimateMessageTokens($){return Math.ceil($.content.length/4)}compressMessage($,b){let w=b*4;if($.content.length<=w)return $;let W=$.content.substring(0,w-3)+"...";return{...$,content:W,metadata:{...$.metadata,compressed:!0,originalLength:$.content.length}}}updateTopics($,b){let w=new Set(b);for(let W of $)this.extractTopicsFromMessage(W).forEach((Q)=>w.add(Q));return Array.from(w).slice(0,10)}extractTopicsFromMessage($){let b=$.content.toLowerCase(),w=[];return["项目","功能","模块","组件","服务","接口","数据库","前端","后端","算法","架构","设计"].forEach((V)=>{if(b.includes(V))w.push(V)}),w}estimateTokens($){let b=0;for(let W of $.layers.conversation.messages)b+=this.estimateMessageTokens(W);let w=JSON.stringify($.layers.system);if(b+=Math.ceil(w.length/4),$.layers.tool.recentCalls.length>0){let W=JSON.stringify($.layers.tool);b+=Math.ceil(W.length/8)}return b}static createPresets(){return{lightweight:new q0({maxTokens:1000,maxMessages:10,timeWindow:7200000,includeTools:!1,includeWorkspace:!1}),standard:new q0({maxTokens:4000,maxMessages:30,timeWindow:43200000,includeTools:!0,includeWorkspace:!0}),comprehensive:new q0({maxTokens:8000,maxMessages:100,timeWindow:86400000,includeTools:!0,includeWorkspace:!0}),debug:new q0({maxTokens:2000,maxMessages:20,timeWindow:21600000,priority:2,includeTools:!0,includeWorkspace:!1})}}}class Tw{cache=new Map;maxSize;defaultTTL;constructor($=100,b=300000){this.maxSize=$,this.defaultTTL=b}set($,b,w){let W=Date.now(),V={data:b,timestamp:W,accessCount:0,lastAccess:W,ttl:w||this.defaultTTL};if(this.cache.size>=this.maxSize&&!this.cache.has($))this.evictLeastUsed();this.cache.set($,V)}get($){let b=this.cache.get($);if(!b)return null;let w=Date.now();if(w-b.timestamp>b.ttl)return this.cache.delete($),null;return b.accessCount++,b.lastAccess=w,b.data}has($){let b=this.cache.get($);if(!b)return!1;if(Date.now()-b.timestamp>b.ttl)return this.cache.delete($),!1;return!0}delete($){return this.cache.delete($)}clear(){this.cache.clear()}size(){return this.cleanExpired(),this.cache.size}cacheMessageSummary($,b,w){let W=`summary:${$}:${b.length}`;this.set(W,{summary:w,messageCount:b.length,lastMessage:b[b.length-1]?.timestamp||0},600000)}getMessageSummary($,b){let w=`summary:${$}:${b}`;return this.get(w)}cacheToolResult($,b,w){let W=this.hashInput(b),V=`tool:${$}:${W}`;this.set(V,w,1800000)}getToolResult($,b){let w=this.hashInput(b),W=`tool:${$}:${w}`;return this.get(W)}cacheCompressedContext($,b){let w=`compressed:${$}`;this.set(w,b,900000)}getCompressedContext($){let b=`compressed:${$}`;return this.get(b)}getStats(){this.cleanExpired();let $=0,b=0,w=[];for(let[W,V]of Array.from(this.cache.entries()))$+=V.accessCount,b+=this.estimateItemSize(V),w.push({key:W,accessCount:V.accessCount,lastAccess:V.lastAccess});return w.sort((W,V)=>V.accessCount-W.accessCount),{size:this.cache.size,maxSize:this.maxSize,hitRate:$>0?$/($+this.cache.size):0,memoryUsage:b,topKeys:w.slice(0,10)}}cleanExpired(){let $=Date.now(),b=[];for(let[w,W]of Array.from(this.cache.entries()))if($-W.timestamp>W.ttl)b.push(w);for(let w of b)this.cache.delete(w)}evictLeastUsed(){let $=null,b=1/0,w=Date.now();for(let[W,V]of Array.from(this.cache.entries())){let Q=1/(w-V.lastAccess+1),Z=V.accessCount,J=Q*Z;if(J<b)b=J,$=W}if($)this.cache.delete($)}hashInput($){let b=JSON.stringify($),w=0;for(let W=0;W<b.length;W++){let V=b.charCodeAt(W);w=(w<<5)-w+V,w=w&w}return Math.abs(w).toString(36)}estimateItemSize($){try{return JSON.stringify($).length*2}catch{return 1000}}setTTL($,b){let w=this.cache.get($);if(w)return w.ttl=b,w.timestamp=Date.now(),!0;return!1}getRemainingTTL($){let b=this.cache.get($);if(!b)return-1;let w=b.ttl-(Date.now()-b.timestamp);return Math.max(0,w)}warmup($){$.forEach(({key:b,value:w,ttl:W})=>{this.set(b,w,W)})}}class kw{contextData=null;maxSize;accessLog=new Map;constructor($=1000){this.maxSize=$}setContext($){this.contextData={...$},this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("context")}getContext(){if(this.contextData)this.recordAccess("context");return this.contextData}addMessage($){if(!this.contextData)throw Error("上下文数据未初始化");this.contextData.layers.conversation.messages.push($),this.contextData.layers.conversation.lastActivity=Date.now(),this.contextData.metadata.lastUpdated=Date.now(),this.enforceMemoryLimit(),this.recordAccess("messages")}getRecentMessages($=10){if(!this.contextData)return[];let b=this.contextData.layers.conversation.messages;return this.recordAccess("messages"),b.slice(-$)}addToolCall($){if(!this.contextData)throw Error("上下文数据未初始化");if(this.contextData.layers.tool.recentCalls.push($),this.contextData.metadata.lastUpdated=Date.now(),this.contextData.layers.tool.recentCalls.length>50)this.contextData.layers.tool.recentCalls=this.contextData.layers.tool.recentCalls.slice(-25);this.recordAccess("tools")}updateToolState($,b){if(!this.contextData)throw Error("上下文数据未初始化");this.contextData.layers.tool.toolStates[$]=b,this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("tools")}getToolState($){if(!this.contextData)return null;return this.recordAccess("tools"),this.contextData.layers.tool.toolStates[$]}updateWorkspace($){if(!this.contextData)throw Error("上下文数据未初始化");Object.assign(this.contextData.layers.workspace,$),this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("workspace")}clear(){this.contextData=null,this.accessLog.clear()}getMemoryInfo(){if(!this.contextData)return{hasData:!1,messageCount:0,toolCallCount:0,lastUpdated:null};return{hasData:!0,messageCount:this.contextData.layers.conversation.messages.length,toolCallCount:this.contextData.layers.tool.recentCalls.length,lastUpdated:this.contextData.metadata.lastUpdated}}recordAccess($){this.accessLog.set($,Date.now())}enforceMemoryLimit(){if(!this.contextData)return;let $=this.contextData.layers.conversation.messages;if($.length>this.maxSize){let b=Math.floor(this.maxSize*0.8);this.contextData.layers.conversation.messages=$.slice(-b)}}getMemoryUsage(){if(!this.contextData)return 0;return JSON.stringify(this.contextData).length}}import{nanoid as f$}from"nanoid";import*as g$ from"node:fs/promises";import*as c2 from"node:path";import*as nb from"node:fs";import{createReadStream as FV}from"node:fs";import*as t from"node:fs/promises";import*as fw from"node:path";import{createInterface as CV}from"node:readline";function m2($){if(!$||typeof $!=="object")return!1;let b=$;return typeof b.id==="string"&&typeof b.type==="string"&&typeof b.timestamp==="string"}class Z${filePath;constructor($){this.filePath=$}async append($){try{await t.mkdir(fw.dirname(this.filePath),{recursive:!0,mode:493});let b=JSON.stringify($)+`
1839
+ `;await t.appendFile(this.filePath,b,"utf-8")}catch(b){throw console.error(`[JSONLStore] 追加写入失败: ${this.filePath}`,b),b}}async appendBatch($){try{await t.mkdir(fw.dirname(this.filePath),{recursive:!0,mode:493});let b=$.map((w)=>JSON.stringify(w)).join(`
1840
+ `)+`
1841
+ `;await t.appendFile(this.filePath,b,"utf-8")}catch(b){throw console.error(`[JSONLStore] 批量追加写入失败: ${this.filePath}`,b),b}}async readAll(){try{if(!nb.existsSync(this.filePath))return[];let b=(await t.readFile(this.filePath,"utf-8")).split(`
1842
+ `).filter((W)=>W.trim().length>0),w=[];for(let W of b)try{let V=JSON.parse(W);if(m2(V))w.push(V);else console.warn(`[JSONLStore] 无效的 SessionEvent 格式: ${W}`)}catch(V){console.warn(`[JSONLStore] 解析 JSON 行失败: ${W}`,V)}return w}catch($){return console.error(`[JSONLStore] 读取文件失败: ${this.filePath}`,$),[]}}async readStream($){return new Promise((b,w)=>{if(!nb.existsSync(this.filePath)){b();return}let W=FV(this.filePath,"utf-8"),V=CV({input:W,crlfDelay:Number.POSITIVE_INFINITY});V.on("line",async(Q)=>{let Z=Q.trim();if(Z.length===0)return;try{let J=JSON.parse(Z);if(m2(J))await $(J)}catch(J){console.warn(`[JSONLStore] 解析 JSON 行失败: ${Z}`,J)}}),V.on("close",()=>b()),V.on("error",w),W.on("error",w)})}async filter($){let b=[];return await this.readStream((w)=>{if($(w))b.push(w)}),b}async readLast($){return(await this.readAll()).slice(-$)}async getStats(){try{if(!nb.existsSync(this.filePath))return{exists:!1,size:0,lineCount:0};let $=await t.stat(this.filePath),w=(await t.readFile(this.filePath,"utf-8")).split(`
1843
+ `).filter((W)=>W.trim().length>0).length;return{exists:!0,size:$.size,lineCount:w}}catch($){return console.error(`[JSONLStore] 获取统计信息失败: ${this.filePath}`,$),{exists:!1,size:0,lineCount:0}}}async exists(){try{return await t.access(this.filePath),!0}catch{return!1}}async delete(){try{if(await this.exists())await t.unlink(this.filePath)}catch($){throw console.error(`[JSONLStore] 删除文件失败: ${this.filePath}`,$),$}}getFilePath(){return this.filePath}}class Iw{projectPath;maxSessions;version;constructor($=process.cwd(),b=100,w="0.0.10"){this.projectPath=$,this.maxSessions=b,this.version=w}createEvent($,b,w){return{id:f$(),sessionId:b,timestamp:new Date().toISOString(),type:$,cwd:this.projectPath,gitBranch:j4(this.projectPath),version:this.version,data:w}}async ensureSessionCreated($,b){let w=Y$(this.projectPath,$),W=new Z$(w);if((await W.getStats()).lineCount>0)return;let Q=new Date().toISOString(),Z={sessionId:$,rootId:b?.parentSessionId??$,parentId:b?.parentSessionId,relationType:b?"subagent":void 0,title:void 0,status:"running",agentType:b?.subagentType,model:void 0,permission:void 0,createdAt:Q,updatedAt:Q},J=this.createEvent("session_created",$,Z);await W.append(J)}buildCompactionMetadata($){let b={trigger:$.trigger,preTokens:$.preTokens};if($.postTokens!==void 0)b.postTokens=$.postTokens;if($.filesIncluded)b.filesIncluded=$.filesIncluded;return b}async initialize(){try{let $=l0(this.projectPath);await g$.mkdir($,{recursive:!0,mode:493}),console.log(`[PersistentStore] 初始化存储目录: ${$}`)}catch($){console.warn("[PersistentStore] 无法创建持久化存储目录:",$)}}async saveMessage($,b,w,W=null,V,Q){try{let Z=Y$(this.projectPath,$),J=new Z$(Z);await this.ensureSessionCreated($,Q);let Y=new Date().toISOString(),X=f$(),O={messageId:X,role:b,parentMessageId:W??void 0,createdAt:Y,model:V?.model,usage:V?.usage},G=this.createEvent("message_created",$,O),B={partId:f$(),messageId:X,partType:"text",payload:{text:w},createdAt:Y},K=this.createEvent("part_created",$,B);return await J.appendBatch([G,K]),X}catch(Z){throw console.error(`[PersistentStore] 保存消息失败 (session: ${$}):`,Z),Z}}async saveToolUse($,b,w,W=null,V){try{let Q=Y$(this.projectPath,$),Z=new Z$(Q);await this.ensureSessionCreated($,V);let J=new Date().toISOString(),Y=W??f$(),X=[];if(!W){let B={messageId:Y,role:"assistant",parentMessageId:void 0,createdAt:J};X.push(this.createEvent("message_created",$,B))}let O=f$(),G={partId:O,messageId:Y,partType:"tool_call",payload:{toolCallId:O,toolName:b,input:w},createdAt:J};if(X.push(this.createEvent("part_created",$,G)),b==="Task"&&w&&typeof w==="object"){let B=w,K=typeof B.subagent_session_id==="string"?B.subagent_session_id:void 0,C=typeof B.subagent_type==="string"?B.subagent_type:void 0;if(K&&C){let q={partId:f$(),messageId:Y,partType:"subtask_ref",payload:{childSessionId:K,agentType:C,status:"running",summary:typeof B.description==="string"?B.description:"",startedAt:J},createdAt:J};X.push(this.createEvent("part_created",$,q))}}return await Z.appendBatch(X),O}catch(Q){throw console.error(`[PersistentStore] 保存工具调用失败 (session: ${$}):`,Q),Q}}async saveToolResult($,b,w,W,V=null,Q,Z,J){try{let Y=Y$(this.projectPath,$),X=new Z$(Y);await this.ensureSessionCreated($,Z);let O=new Date().toISOString(),G=V??f$(),B=[];if(!V){let C={messageId:G,role:"assistant",parentMessageId:void 0,createdAt:O};B.push(this.createEvent("message_created",$,C))}let K={partId:b,messageId:G,partType:"tool_result",payload:{toolCallId:b,toolName:w,output:W,error:Q??null},createdAt:O};if(B.push(this.createEvent("part_created",$,K)),J){let C=J.subagentStatus==="running"?null:O,q={partId:f$(),messageId:G,partType:"subtask_ref",payload:{childSessionId:J.subagentSessionId,agentType:J.subagentType,status:J.subagentStatus,summary:J.subagentSummary??"",startedAt:O,finishedAt:C},createdAt:O};B.push(this.createEvent("part_created",$,q))}return await X.appendBatch(B),b}catch(Y){throw console.error(`[PersistentStore] 保存工具结果失败 (session: ${$}):`,Y),Y}}async saveCompaction($,b,w,W=null){try{let V=Y$(this.projectPath,$),Q=new Z$(V);await this.ensureSessionCreated($);let Z=new Date().toISOString(),J=f$(),Y={messageId:J,role:"system",parentMessageId:W??void 0,createdAt:Z},X=this.buildCompactionMetadata(w),O={partId:f$(),messageId:J,partType:"summary",payload:{text:b,metadata:X},createdAt:Z},G=[this.createEvent("message_created",$,Y),this.createEvent("part_created",$,O)];return await Q.appendBatch(G),J}catch(V){throw console.error(`[PersistentStore] 保存压缩失败 (session: ${$}):`,V),V}}async saveContext($,b){try{let{conversation:w}=b.layers;for(let W of w.messages)await this.saveMessage($,W.role,W.content,null)}catch(w){console.warn(`[PersistentStore] 保存上下文失败 (session: ${$}):`,w)}}async saveSession($,b){console.warn("[PersistentStore] saveSession 方法已废弃,请使用 saveMessage")}async saveConversation($,b){console.warn("[PersistentStore] saveConversation 方法已废弃,请使用 saveMessage")}async loadSession($){try{let b=Y$(this.projectPath,$),W=await new Z$(b).readAll();if(W.length===0)return null;let V=W.find((Q)=>Q.type==="session_created");return{sessionId:$,userId:void 0,preferences:{},configuration:{},startTime:new Date(V?.timestamp??W[0].timestamp).getTime()}}catch{return null}}async loadConversation($){try{let b=Y$(this.projectPath,$),W=await new Z$(b).readAll();if(W.length===0)return null;let V=new Map;for(let Y of W){if(Y.type==="message_created")V.set(Y.data.messageId,{id:Y.data.messageId,role:Y.data.role,content:"",timestamp:new Date(Y.timestamp).getTime()});if(Y.type==="part_created"&&Y.data.partType==="text"){let X=V.get(Y.data.messageId);if(X){let O=Y.data.payload;X.content=O.text??""}}}let Q=Array.from(V.values()),Z=W[W.length-1],J=new Date(Z.timestamp).getTime();return{messages:Q,topics:[],lastActivity:J}}catch{return null}}async listSessions(){try{let $=l0(this.projectPath);return(await g$.readdir($)).filter((w)=>w.endsWith(".jsonl")).map((w)=>w.replace(".jsonl","")).sort()}catch{return[]}}async getSessionSummary($){try{let b=Y$(this.projectPath,$),w=new Z$(b);if(!(await w.getStats()).exists)return null;let V=await w.readAll();if(V.length===0)return null;let Q=V[V.length-1],Z=V.filter((J)=>J.type==="message_created"&&["user","assistant"].includes(J.data.role)).length;return{sessionId:$,lastActivity:new Date(Q.timestamp).getTime(),messageCount:Z,topics:[]}}catch{return null}}async deleteSession($){try{let b=Y$(this.projectPath,$);await new Z$(b).delete()}catch(b){console.warn(`[PersistentStore] 删除会话失败 (session: ${$}):`,b)}}async cleanupOldSessions(){try{let $=await this.listSessions();if($.length<=this.maxSessions)return;let W=(await Promise.all($.map((V)=>this.getSessionSummary(V)))).filter((V)=>V!==null).sort((V,Q)=>Q.lastActivity-V.lastActivity).slice(this.maxSessions).map((V)=>V.sessionId);await Promise.all(W.map((V)=>this.deleteSession(V))),console.log(`[PersistentStore] 已清理 ${W.length} 个旧会话`)}catch($){console.error("[PersistentStore] 清理旧会话失败:",$)}}async getStorageStats(){try{let $=await this.listSessions(),b=0;for(let w of $){let W=Y$(this.projectPath,w),Q=await new Z$(W).getStats();b+=Q.size}return{totalSessions:$.length,totalSize:b,projectPath:this.projectPath}}catch{return{totalSessions:0,totalSize:0,projectPath:this.projectPath}}}async checkStorageHealth(){try{let $=l0(this.projectPath);await g$.mkdir($,{recursive:!0,mode:493});let b=c2.join($,".health-check");return await g$.writeFile(b,"test","utf-8"),await g$.unlink(b),{isAvailable:!0,canWrite:!0}}catch($){return{isAvailable:!1,canWrite:!1,error:$ instanceof Error?$.message:String($)}}}static async listAllProjects(){return N4()}}class sb{memory;persistent;cache;compressor;filter;options;currentSessionId=null;initialized=!1;constructor($={}){let b=$.storage?.persistentPath||n0();this.options={storage:{maxMemorySize:1000,persistentPath:b,cacheSize:100,compressionEnabled:!0,...$.storage},defaultFilter:{maxTokens:32000,maxMessages:50,timeWindow:86400000,...$.defaultFilter},compressionThreshold:$.compressionThreshold||6000,enableVectorSearch:$.enableVectorSearch||!1},this.memory=new kw(this.options.storage.maxMemorySize),this.persistent=new Iw(process.cwd(),100),this.cache=new Tw(this.options.storage.cacheSize,300000),this.compressor=new vw,this.filter=new q0(this.options.defaultFilter)}async initialize(){if(this.initialized)return;try{if(await this.persistent.initialize(),!(await this.persistent.checkStorageHealth()).isAvailable)console.warn("警告:持久化存储不可用,将仅使用内存存储");this.initialized=!0,console.log("上下文管理器初始化完成")}catch($){throw console.error("上下文管理器初始化失败:",$),$}}async createSession($,b={},w={}){let W=w.sessionId||this.generateSessionId(),V=Date.now(),Q={layers:{system:await this.createSystemContext(),session:{sessionId:W,userId:$,preferences:b,configuration:w,startTime:V},conversation:{messages:[],topics:[],lastActivity:V},tool:{recentCalls:[],toolStates:{},dependencies:{}},workspace:await this.createWorkspaceContext()},metadata:{totalTokens:0,priority:1,lastUpdated:V}};return this.memory.setContext(Q),await this.persistent.saveContext(W,Q),this.currentSessionId=W,console.log(`新会话已创建: ${W}`),W}async loadSession($){try{let b=this.memory.getContext();if(!b||b.layers.session.sessionId!==$){let[w,W]=await Promise.all([this.persistent.loadSession($),this.persistent.loadConversation($)]);if(!w||!W)return!1;b={layers:{system:await this.createSystemContext(),session:w,conversation:W,tool:{recentCalls:[],toolStates:{},dependencies:{}},workspace:await this.createWorkspaceContext()},metadata:{totalTokens:0,priority:1,lastUpdated:Date.now()}},this.memory.setContext(b)}return this.currentSessionId=$,console.log(`会话已加载: ${$}`),!0}catch(b){return console.error("加载会话失败:",b),!1}}async addMessage($,b,w){if(!this.currentSessionId)throw Error("没有活动会话");let W={id:this.generateMessageId(),role:$,content:b,timestamp:Date.now(),metadata:w};this.memory.addMessage(W);let V=this.memory.getContext();if(V&&this.shouldCompress(V))await this.compressCurrentContext();this.saveCurrentSessionAsync()}async addToolCall($){if(!this.currentSessionId)throw Error("没有活动会话");if(this.memory.addToolCall($),$.status==="success"&&$.output)this.cache.cacheToolResult($.name,$.input,$.output);this.saveCurrentSessionAsync()}async saveMessage($,b,w,W=null,V,Q){return this.persistent.saveMessage($,b,w,W,V,Q)}async saveToolUse($,b,w,W=null,V){return this.persistent.saveToolUse($,b,w,W,V)}async saveToolResult($,b,w,W,V=null,Q,Z,J){return this.persistent.saveToolResult($,b,w,W,V,Q,Z,J)}async saveCompaction($,b,w,W=null){return this.persistent.saveCompaction($,b,w,W)}updateToolState($,b){if(!this.currentSessionId)throw Error("没有活动会话");this.memory.updateToolState($,b)}updateWorkspace($){if(!this.currentSessionId)throw Error("没有活动会话");this.memory.updateWorkspace($)}async getFormattedContext($){let b=this.memory.getContext();if(!b)throw Error("没有可用的上下文数据");let w=this.filter.filter(b,$),W=this.shouldCompress(w),V;if(W){let Q=this.hashContext(w);if(V=this.cache.getCompressedContext(Q)??void 0,!V)V=await this.compressor.compress(w),this.cache.cacheCompressedContext(Q,V)}return{context:w,compressed:V,tokenCount:V?V.tokenCount:w.metadata.totalTokens}}async searchSessions($,b=10){let w=await this.persistent.listSessions(),W=[];for(let V of w){let Q=await this.persistent.getSessionSummary(V);if(Q){let Z=this.calculateRelevance($,Q.topics);if(Z>0)W.push({sessionId:V,summary:`${Q.messageCount}条消息,主题:${Q.topics.join("、")}`,lastActivity:Q.lastActivity,relevanceScore:Z})}}return W.sort((V,Q)=>Q.relevanceScore-V.relevanceScore).slice(0,b)}getCachedToolResult($,b){return this.cache.getToolResult($,b)}async getStats(){let[$,b,w]=await Promise.all([Promise.resolve(this.memory.getMemoryInfo()),Promise.resolve(this.cache.getStats()),this.persistent.getStorageStats()]);return{currentSession:this.currentSessionId,memory:$,cache:b,storage:w}}async cleanup(){if(this.currentSessionId)await this.saveCurrentSession();this.memory.clear(),this.cache.clear(),await this.persistent.cleanupOldSessions(),this.currentSessionId=null,console.log("上下文管理器资源清理完成")}generateSessionId(){return i2()}generateMessageId(){return i2()}async createSystemContext(){return{role:"AI助手",capabilities:["对话","工具调用","代码生成","文档分析"],tools:["文件操作","Git操作","代码分析"],version:"1.0.0"}}async createWorkspaceContext(){try{let $=process.cwd();return{projectPath:$,currentFiles:[],recentFiles:[],environment:{nodeVersion:process.version,platform:process.platform,cwd:$}}}catch($){return{currentFiles:[],recentFiles:[],environment:{}}}}shouldCompress($){return $.metadata.totalTokens>this.options.compressionThreshold}async compressCurrentContext(){let $=this.memory.getContext();if(!$)return;let b=await this.compressor.compress($);$.layers.conversation.summary=b.summary,this.memory.setContext($)}async saveCurrentSession(){if(!this.currentSessionId)return;let $=this.memory.getContext();if($)await this.persistent.saveContext(this.currentSessionId,$)}saveCurrentSessionAsync(){this.saveCurrentSession().catch(($)=>{console.warn("异步保存会话失败:",$)})}hashContext($){let b=JSON.stringify({messageCount:$.layers.conversation.messages.length,lastMessage:$.layers.conversation.messages[$.layers.conversation.messages.length-1]?.id,toolCallCount:$.layers.tool.recentCalls.length});return l2.createHash("md5").update(b).digest("hex")}calculateRelevance($,b){let w=$.toLowerCase(),W=0;for(let V of b)if(w.includes(V.toLowerCase())||V.toLowerCase().includes(w))W+=1;return W}}class Pw{chatService;contextManager;memoryAdapter;constructor($,b){this.chatService=$,this.contextManager=b||new sb,this.memoryAdapter=this.createMemoryAdapter()}createMemoryAdapter(){let $=[];return{getMessages:()=>[...$],addMessage:(b)=>{$.push(b)},clearContext:()=>{$.length=0},getContextSize:()=>$.length}}getContextManager(){return this.contextManager}getMemoryAdapter(){return this.memoryAdapter}async executeTask($){let b=[{role:"user",content:$.prompt}],w=await this.chatService.chat(b);return{taskId:$.id,content:w.content,metadata:{taskType:$.type}}}}var rb=E("Agent");class hw{config;outputFormat;chatService;executionEngine;currentModelId;currentModelMaxContextTokens;constructor($,b){this.config=$;this.outputFormat=b}getChatService(){return this.chatService}getExecutionEngine(){return this.executionEngine}getCurrentModelId(){return this.currentModelId}getMaxContextTokens(){return this.currentModelMaxContextTokens}resolveModelConfig($){let b=$&&$!=="inherit"?$:void 0,w=this.config.models||[],W=this.config.currentModelId,V=b?w.find((Q)=>Q.id===b):w.find((Q)=>Q.id===W)||w[0];if(!V)throw Error(`❌ 模型配置未找到: ${b??"current"}`);return V}async applyModelConfig($,b){rb.debug(`[ModelManager] ${b} ${$.name} (${$.model})`);let w=zw($),W=$.thinkingEnabled??!1,V=w&&W;if(w&&!W)rb.debug("[ModelManager] \uD83E\uDDE0 模型支持 Thinking,但用户未开启(按 Tab 开启)");else if(V)rb.debug("[ModelManager] \uD83E\uDDE0 Thinking 模式已启用,启用 reasoning_content 支持");let Q=$.maxContextTokens??128000;this.currentModelMaxContextTokens=Q,this.chatService=await lb({provider:$.provider,apiKey:$.apiKey||"",model:$.model,baseUrl:$.baseUrl||"",temperature:$.temperature??this.config.temperature,maxContextTokens:this.currentModelMaxContextTokens,supportsThinking:V,outputFormat:this.outputFormat});let Z=this.executionEngine?.getContextManager();this.executionEngine=new Pw(this.chatService,Z),this.currentModelId=$.id}async switchModelIfNeeded($){if(!$||$===this.currentModelId)return;let w=(this.config.models||[]).find((W)=>W.id===$);if(!w){rb.warn(`[ModelManager] ⚠️ 模型配置未找到: ${$}`);return}await this.applyModelConfig(w,"\uD83D\uDD01 切换模型")}}var UV=E("Agent");class xw{language;constructor($){this.language=$}injectPlanReminder($){if(typeof $==="string")return c0($);let b=$.filter((w)=>w.type==="text");if(b.length>0){let w=b[0];return $.map((W)=>W===w?{type:"text",text:c0(w.text)}:W)}return[{type:"text",text:c0("")},...$]}async buildPlanSystemPrompt(){let{prompt:$}=await $0({projectPath:process.cwd(),mode:z.PLAN,includeEnvironment:!0,language:this.language});return $}async runPlanLoop($,b,w,W){UV.debug("\uD83D\uDD35 Processing Plan mode message...");let V=await this.buildPlanSystemPrompt(),Q=this.injectPlanReminder($);return W(Q,b,w,V)}async*runPlanLoopStream($,b,w,W){let V=await this.buildPlanSystemPrompt(),Q=this.injectPlanReminder($);return yield*W(Q,b,w,V)}}import{appendFileSync as RV,mkdirSync as HV,writeFileSync as _V}from"node:fs";import DV from"node:os";import s2 from"node:path";var pw=s2.join(DV.homedir(),".blade","logs","stream-debug.log"),n2=!1;function LV(){if(n2)return;let $=s2.dirname(pw);HV($,{recursive:!0,mode:493}),_V(pw,`=== Stream Debug Log Started: ${new Date().toISOString()} ===
1844
+ `),n2=!0}function r2($,b,w){LV();let W=new Date().toISOString(),V=w?` | ${JSON.stringify(w)}`:"",Q=`[${W}] [${$}] ${b}${V}
1845
+ `;RV(pw,Q)}var a2=E("Agent");class dw{getChatService;constructor($){this.getChatService=$}async*streamResponse($,b,w){let W=this.getChatService(),V="",Q="",Z,J=new Map;try{let Y=W.streamChat($,b,w),X=0;for await(let O of Y){if(X++,w?.aborted)break;if(O.content)V+=O.content,yield{type:"content_delta",delta:O.content};if(O.reasoningContent)Q+=O.reasoningContent,yield{type:"thinking_delta",delta:O.reasoningContent};if(O.usage)Z=O.usage;if(O.toolCalls)for(let G of O.toolCalls)this.accumulateToolCall(J,G);if(O.finishReason){r2("processStreamResponse","finishReason received",{finishReason:O.finishReason,fullContentLen:V.length,fullReasoningContentLen:Q.length,toolCallAccumulatorSize:J.size});break}}if(X===0&&!w?.aborted&&V.length===0&&J.size===0)return a2.warn("[Agent] 流式响应返回0个chunk,回退到非流式模式"),W.chat($,b,w);return{content:V,reasoningContent:Q||void 0,toolCalls:this.buildFinalToolCalls(J),usage:Z}}catch(Y){if(this.isStreamingNotSupportedError(Y))return a2.warn("[Agent] 流式请求失败,降级到非流式模式"),W.chat($,b,w);throw Y}}accumulateToolCall($,b){let w=b,W=w.index??0;if(!$.has(W))$.set(W,{id:w.id||"",name:w.function?.name||"",arguments:""});let V=$.get(W);if(w.id&&!V.id)V.id=w.id;if(w.function?.name&&!V.name)V.name=w.function.name;if(w.function?.arguments)V.arguments+=w.function.arguments}buildFinalToolCalls($){if($.size===0)return;return Array.from($.values()).filter((b)=>b.id&&b.name).map((b)=>({id:b.id,type:"function",function:{name:b.name,arguments:b.arguments}}))}isStreamingNotSupportedError($){if(!($ instanceof Error))return!1;return["stream not supported","streaming is not available","sse not supported","does not support streaming"].some((w)=>$.message.toLowerCase().includes(w.toLowerCase()))}}var h=E("Agent");class d${config;runtimeOptions;isInitialized=!1;activeTask;executionPipeline;modelManager;planExecutor;loopRunner;attachmentHandler;mcpRegistry;constructor($,b={},w){this.config=$,this.runtimeOptions=b,this.executionPipeline=w||this.createDefaultPipeline(),this.modelManager=new hw($,b.outputFormat),this.planExecutor=new xw($.language),this.mcpRegistry=new e$}static async create($,b={}){if(($.models||[]).length===0)throw Error(`❌ 没有可用的模型配置
1846
+
1847
+ `+`请先使用以下命令添加模型:
1848
+ `+` /model add
1849
+
1850
+ `+`或运行初始化向导:
1851
+ `+" /init");let W=new d$($,b);if(await W.initialize(),b.toolWhitelist&&b.toolWhitelist.length>0)W.applyToolWhitelist(b.toolWhitelist);return W}async initialize(){if(this.isInitialized)return;try{this.log("初始化Agent..."),await this.initializeSystemPrompt(),await this.registerBuiltinTools(),await this.loadSubagents(),await this.discoverSkills();let $=this.modelManager.resolveModelConfig(this.runtimeOptions.modelId);await this.modelManager.applyModelConfig($,"\uD83D\uDE80 使用模型:"),this.attachmentHandler=new Ew(process.cwd());let b=new dw(()=>this.modelManager.getChatService()),w=new Sw(()=>this.modelManager.getChatService(),()=>this.modelManager.getExecutionEngine()?.getContextManager());this.loopRunner=new Mw(this.config,this.runtimeOptions,this.modelManager,this.executionPipeline,b,w),this.isInitialized=!0,this.log(`Agent初始化完成,已加载 ${this.executionPipeline.getRegistry().getAll().length} 个工具`)}catch($){throw this.error("Agent初始化失败",$),$}}async chat($,b,w){if(!this.isInitialized)throw Error("Agent未初始化");let W=this.attachmentHandler?await this.attachmentHandler.processAtMentionsForContent($):$;if(b){let J={signal:b.signal,...w},Y;if(b.permissionMode==="plan")Y=await this.planExecutor.runPlanLoop(W,b,J,(X,O,G,B)=>this.loopRunner.executeLoop(X,O,G,B));else Y=await this.loopRunner.runLoop(W,b,J);if(!Y.success){if(Y.error?.type==="aborted"||Y.metadata?.shouldExitLoop)return"";throw Error(Y.error?.message||"执行失败")}if(Y.metadata?.targetMode&&b.permissionMode==="plan")return this.executePlanApproval(W,b,J,Y);return Y.finalMessage||""}let V=typeof W==="string"?W:W.filter((J)=>J.type==="text").map((J)=>J.text).join(`
1852
+ `),Q={id:this.generateTaskId(),type:"simple",prompt:V};return(await this.executeTask(Q)).content}streamChat($,b,w){if(!this.isInitialized)throw Error("Agent未初始化");let W=this,Q=(async()=>{let J=W.attachmentHandler?await W.attachmentHandler.processAtMentionsForContent($):$;if(!b)throw Error("Context is required for streaming");let Y={signal:b.signal,...w};if(b.permissionMode==="plan"){let X=W.planExecutor.runPlanLoopStream(J,b,Y,(B,K,C,q)=>W.loopRunner.executeWithAgentLoop(B,K,C,q)),O,G=[];while(!0){let{value:B,done:K}=await X.next();if(K){O=B;break}G.push(B)}if(O?.metadata?.targetMode){let B=O.metadata.targetMode,K=O.metadata.planContent,C={...b,permissionMode:B},q=W.injectPlanContent(J,K);return{events:G,continuation:W.loopRunner.runLoopStream(q,C,Y)}}return{events:G,result:O}}return{continuation:W.loopRunner.runLoopStream(J,b,Y)}})();return async function*(){let J=await Q;if("events"in J&&J.events)for(let Y of J.events)yield Y;if("continuation"in J&&J.continuation)return yield*J.continuation;return J.result}()}async runAgenticLoop($,b,w){if(!this.isInitialized)throw Error("Agent未初始化");let W={messages:b.messages,userId:b.userId||"subagent",sessionId:b.sessionId||`subagent_${Date.now()}`,workspaceRoot:b.workspaceRoot||process.cwd(),signal:b.signal,confirmationHandler:b.confirmationHandler,permissionMode:b.permissionMode,systemPrompt:b.systemPrompt,subagentInfo:b.subagentInfo};return await this.loopRunner.runLoop($,W,w)}async chatWithSystem($,b){if(!this.isInitialized)throw Error("Agent未初始化");let w=[{role:"system",content:$},{role:"user",content:b}];return(await this.modelManager.getChatService().chat(w)).content}async executeTask($){if(!this.isInitialized)throw Error("Agent未初始化");this.activeTask=$;try{this.log(`开始执行任务: ${$.id}`);let b=await this.modelManager.getExecutionEngine().executeTask($);return this.activeTask=void 0,this.log(`任务执行完成: ${$.id}`),b}catch(b){throw this.activeTask=void 0,this.error(`任务执行失败: ${$.id}`,b),b}}getActiveTask(){return this.activeTask}getChatService(){return this.modelManager.getChatService()}getContextManager(){return this.modelManager.getExecutionEngine()?.getContextManager()}getAvailableTools(){return this.executionPipeline?this.executionPipeline.getRegistry().getAll():[]}getToolRegistry(){return this.executionPipeline.getRegistry()}getStats(){return{initialized:this.isInitialized,activeTask:this.activeTask?.id,components:{chatService:this.modelManager.getChatService()?"ready":"not_loaded",executionEngine:this.modelManager.getExecutionEngine()?"ready":"not_loaded"}}}getToolStats(){let $=this.getAvailableTools(),b=new Map;return $.forEach((w)=>{let W=b.get(w.kind)||0;b.set(w.kind,W+1)}),{totalTools:$.length,toolsByKind:Object.fromEntries(b),toolNames:$.map((w)=>w.name)}}applyToolWhitelist($){let b=this.executionPipeline.getRegistry(),W=b.getAll().filter((V)=>!$.includes(V.name));for(let V of W)b.unregister(V.name);h.debug(`\uD83D\uDD12 Applied tool whitelist: ${$.join(", ")} (removed ${W.length} tools)`)}clearSkillContext(){this.loopRunner.clearSkillContext()}async getSystemPrompt(){return this.loopRunner.buildSystemPromptOnDemand()}async destroy(){this.log("销毁Agent..."),this.isInitialized=!1,this.log("Agent已销毁")}createDefaultPipeline(){let $=new Vb,b={...this.config.permissions,...this.runtimeOptions.permissions},w=this.runtimeOptions.permissionMode??z.DEFAULT;return new db($,{permissionConfig:b,permissionMode:w,maxHistorySize:1000,canUseTool:this.runtimeOptions.canUseTool})}async executePlanApproval($,b,w,W){let V=W.metadata.targetMode,Q=W.metadata.planContent;h.debug(`\uD83D\uDD04 Plan 模式已批准,切换到 ${V} 模式并重新执行`);let Z={...b,permissionMode:V},J=this.injectPlanContent($,Q),Y=await this.loopRunner.runLoop(J,Z,w);if(!Y.success)throw Error(Y.error?.message||"执行失败");return Y.finalMessage||""}injectPlanContent($,b){if(!b)return $;let w=`
1853
+
1854
+ <approved-plan>
1855
+ ${b}
1856
+ </approved-plan>
1867
1857
 
1868
- Please continue the conversation from where we left it off without asking the user any further questions. Continue with the last task that you were asked to work on.`};b.messages.push(M);try{let L=K.executionEngine?.getContextManager();if(L&&b.sessionId)await L.saveCompaction(b.sessionId,F.summary,{trigger:"auto",preTokens:F.preTokens,postTokens:F.postTokens,filesIncluded:F.filesIncluded},null)}catch(L){S.warn("[Agent] 保存压缩数据失败:",L)}return{success:!0,compactedMessages:F.compactedMessages,continueMessage:M}}catch(H){S.error("[Agent] 压缩失败,使用降级策略:",H);let F=b.messages.slice(-80);return b.messages=F,{success:!0,compactedMessages:F}}}};try{let C=Yw(_),H;while(!0){let{value:F,done:M}=await C.next();if(M){H=F;break}yield F}if(!H)throw Error("AgentLoop ended without result");return b.messages=X.filter((F)=>F.role!=="system"),H}catch(C){if(C instanceof Error&&(C.name==="AbortError"||C.message.includes("aborted")))return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:0,toolCallsCount:0,duration:Date.now()-Date.now()}};return S.error("AgentLoop error:",C),{success:!1,error:{type:"api_error",message:`处理消息时发生错误: ${C instanceof Error?C.message:"未知错误"}`,details:C},metadata:{turnsCount:0,toolCallsCount:0,duration:0}}}}async runAgenticLoop($,b,w){if(!this.isInitialized)throw Error("Agent未初始化");let V={messages:b.messages,userId:b.userId||"subagent",sessionId:b.sessionId||`subagent_${Date.now()}`,workspaceRoot:b.workspaceRoot||process.cwd(),signal:b.signal,confirmationHandler:b.confirmationHandler,permissionMode:b.permissionMode,systemPrompt:b.systemPrompt,subagentInfo:b.subagentInfo};return await this.runLoop($,V,w)}async chatWithSystem($,b){if(!this.isInitialized)throw Error("Agent未初始化");let w=[{role:"system",content:$},{role:"user",content:b}];return(await this.chatService.chat(w)).content}getActiveTask(){return this.activeTask}getChatService(){return this.chatService}getContextManager(){return this.executionEngine?.getContextManager()}getStats(){return{initialized:this.isInitialized,activeTask:this.activeTask?.id,components:{chatService:this.chatService?"ready":"not_loaded",executionEngine:this.executionEngine?"ready":"not_loaded"}}}getAvailableTools(){return this.executionPipeline?this.executionPipeline.getRegistry().getAll():[]}getToolRegistry(){return this.executionPipeline.getRegistry()}applyToolWhitelist($){let b=this.executionPipeline.getRegistry(),V=b.getAll().filter((W)=>!$.includes(W.name));for(let W of V)b.unregister(W.name);S.debug(`\uD83D\uDD12 Applied tool whitelist: ${$.join(", ")} (removed ${V.length} tools)`)}getToolStats(){let $=this.getAvailableTools(),b=new Map;return $.forEach((w)=>{let V=b.get(w.kind)||0;b.set(w.kind,V+1)}),{totalTools:$.length,toolsByKind:Object.fromEntries(b),toolNames:$.map((w)=>w.name)}}async destroy(){this.log("销毁Agent...");try{this.isInitialized=!1,this.log("Agent已销毁")}catch($){throw this.error("Agent销毁失败",$),$}}generateTaskId(){return`task_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}log($,b){S.debug(`[MainAgent] ${$}`,b||"")}error($,b){S.error(`[MainAgent] ${$}`,b||"")}async initializeSystemPrompt(){try{let $=this.runtimeOptions.systemPrompt,b=this.runtimeOptions.appendSystemPrompt,w=await U0({projectPath:process.cwd(),replaceDefault:$,append:b,includeEnvironment:!1,language:this.config.language});if(w.prompt)this.log("系统提示配置验证成功"),S.debug(`[SystemPrompt] 可用来源: ${w.sources.filter((V)=>V.loaded).map((V)=>V.name).join(", ")}`)}catch($){this.error("系统提示配置验证失败",$)}}async getSystemPrompt(){return this.buildSystemPromptOnDemand()}async registerBuiltinTools(){try{let $=await Zw({sessionId:"default",configDir:h2.join(P2.homedir(),".blade")});S.debug(`\uD83D\uDCE6 Registering ${$.length} builtin tools...`),this.executionPipeline.getRegistry().registerAll($);let b=this.executionPipeline.getRegistry().getAll().length;S.debug(`✅ Builtin tools registered: ${b} tools`),S.debug(`[Tools] ${this.executionPipeline.getRegistry().getAll().map((w)=>w.name).join(", ")}`),await this.registerMcpTools()}catch($){throw S.error("Failed to register builtin tools:",$),$}}async registerMcpTools(){try{let $=this.config.mcpServers||{},b=new Set(Object.keys($));for(let W of this.config.inProcessMcpServerNames||[])b.add(W);if(b.size===0){S.debug("\uD83D\uDCE6 No MCP servers configured");return}let w=h.getInstance();for(let[W,Q]of Object.entries($)){if(Q.disabled){S.debug(`⏭️ MCP server "${W}" is disabled, skipping`);continue}try{S.debug(`\uD83D\uDD0C Connecting to MCP server: ${W}`),await w.registerServer(W,Q),S.debug(`✅ MCP server "${W}" connected`)}catch(Z){S.warn(`⚠️ MCP server "${W}" connection failed:`,Z)}}let V=await w.getAvailableToolsByServerNames(Array.from(b));if(V.length>0)this.executionPipeline.getRegistry().registerAll(V),S.debug(`✅ Registered ${V.length} MCP tools`),S.debug(`[MCP Tools] ${V.map((W)=>W.name).join(", ")}`);else S.debug("\uD83D\uDCE6 No MCP tools available")}catch($){S.warn("Failed to register MCP tools:",$)}}async loadSubagents(){if(w$.getAllNames().length>0){S.debug(`\uD83D\uDCE6 Subagents already loaded: ${w$.getAllNames().join(", ")}`);return}try{let $=w$.loadFromStandardLocations();if($>0)S.debug(`✅ Loaded ${$} subagents: ${w$.getAllNames().join(", ")}`);else S.debug("\uD83D\uDCE6 No subagents configured")}catch($){S.warn("Failed to load subagents:",$)}}async discoverSkills(){try{let $=await Ub({cwd:process.cwd()});if($.skills.length>0)S.debug(`✅ Discovered ${$.skills.length} skills: ${$.skills.map((b)=>b.name).join(", ")}`);else S.debug("\uD83D\uDCE6 No skills configured");for(let b of $.errors)S.warn(`⚠️ Skill loading error at ${b.path}: ${b.error}`)}catch($){S.warn("Failed to discover skills:",$)}}applySkillToolRestrictions($){if(!this.activeSkillContext?.allowedTools)return $;let b=this.activeSkillContext.allowedTools;S.debug(`\uD83D\uDD12 Applying Skill tool restrictions: ${b.join(", ")}`);let w=$.filter((V)=>{return b.some((W)=>{if(W===V.name)return!0;let Q=W.match(/^(\w+)\(.*\)$/);if(Q&&Q[1]===V.name)return!0;return!1})});return S.debug(`\uD83D\uDD12 Filtered tools: ${w.map((V)=>V.name).join(", ")} (${w.length}/${$.length})`),w}clearSkillContext(){if(this.activeSkillContext)S.debug(`\uD83C\uDFAF Skill "${this.activeSkillContext.skillName}" deactivated`),this.activeSkillContext=void 0}}import{execSync as wW}from"node:child_process";import x2 from"node:fs";import p2 from"node:path";class bb{async execute($,b){let w=$.content;if(b.signal?.aborted)throw Error("Command execution aborted");return w=this.interpolateArgs(w,b.args),w=await this.executeBashEmbeds(w,b),w=await this.resolveFileReferences(w,b.workspaceRoot),w}interpolateArgs($,b){$=$.replace(/\$ARGUMENTS/g,b.join(" "));for(let w=9;w>=1;w--){let V=`$${w}`,W=b[w-1]??"";$=$.split(V).join(W)}return $}async executeBashEmbeds($,b){let w=/!`([^`]+)`/g,V=[];for(let Q of $.matchAll(w))V.push({match:Q[0],command:Q[1]});let W=$;for(let{match:Q,command:Z}of V){if(b.signal?.aborted){W=W.replace(Q,"[Execution aborted]");continue}try{let Y=wW(Z,{cwd:b.workspaceRoot,encoding:"utf-8",timeout:30000,maxBuffer:1048576,stdio:["pipe","pipe","pipe"]}).trim();W=W.replace(Q,Y)}catch(Y){let J=Y instanceof Error?Y.message:String(Y);W=W.replace(Q,`[Error executing '${Z}': ${J}]`)}}return W}async resolveFileReferences($,b){let w=/@([\w./-]+(?:\/[\w./-]+|\.[\w]+))/g,V=[];for(let Q of $.matchAll(w))V.push({match:Q[0],relativePath:Q[1]});let W=$;for(let{match:Q,relativePath:Z}of V){let Y=p2.resolve(b,Z);try{if(x2.statSync(Y).isFile()){let X=x2.readFileSync(Y,"utf-8"),G=`\`\`\`${p2.extname(Z).slice(1)||"text"}
1858
+ IMPORTANT: Execute according to the approved plan above. Follow the steps exactly as specified.`;if(typeof $==="string")return $+w;return[...$,{type:"text",text:w}]}async initializeSystemPrompt(){try{let $=await $0({projectPath:process.cwd(),replaceDefault:this.runtimeOptions.systemPrompt,append:this.runtimeOptions.appendSystemPrompt,includeEnvironment:!1,language:this.config.language});if($.prompt)this.log("系统提示配置验证成功"),h.debug(`[SystemPrompt] 可用来源: ${$.sources.filter((b)=>b.loaded).map((b)=>b.name).join(", ")}`)}catch($){this.error("系统提示配置验证失败",$)}}async registerBuiltinTools(){try{let $=await Kw({sessionId:"default",configDir:t2.join(o2.homedir(),".blade"),mcpRegistry:this.mcpRegistry});h.debug(`\uD83D\uDCE6 Registering ${$.length} builtin tools...`),this.executionPipeline.getRegistry().registerAll($);let b=this.executionPipeline.getRegistry().getAll().length;h.debug(`✅ Builtin tools registered: ${b} tools`),h.debug(`[Tools] ${this.executionPipeline.getRegistry().getAll().map((w)=>w.name).join(", ")}`),await this.registerMcpTools()}catch($){throw h.error("Failed to register builtin tools:",$),$}}async registerMcpTools(){try{let $=this.config.mcpServers||{},b=new Set(Object.keys($));for(let V of this.config.inProcessMcpServerNames||[])b.add(V);if(b.size===0){h.debug("\uD83D\uDCE6 No MCP servers configured");return}let w=this.mcpRegistry;for(let[V,Q]of Object.entries($)){if(Q.disabled){h.debug(`⏭️ MCP server "${V}" is disabled, skipping`);continue}try{h.debug(`\uD83D\uDD0C Connecting to MCP server: ${V}`),await w.registerServer(V,Q),h.debug(`✅ MCP server "${V}" connected`)}catch(Z){h.warn(`⚠️ MCP server "${V}" connection failed:`,Z)}}let W=await w.getAvailableToolsByServerNames(Array.from(b));if(W.length>0)this.executionPipeline.getRegistry().registerAll(W),h.debug(`✅ Registered ${W.length} MCP tools`);else h.debug("\uD83D\uDCE6 No MCP tools available")}catch($){h.warn("Failed to register MCP tools:",$)}}async loadSubagents(){if(W$.getAllNames().length>0){h.debug(`\uD83D\uDCE6 Subagents already loaded: ${W$.getAllNames().join(", ")}`);return}try{let $=W$.loadFromStandardLocations();if($>0)h.debug(`✅ Loaded ${$} subagents: ${W$.getAllNames().join(", ")}`);else h.debug("\uD83D\uDCE6 No subagents configured")}catch($){h.warn("Failed to load subagents:",$)}}async discoverSkills(){try{let $=await Rb({cwd:process.cwd()});if($.skills.length>0)h.debug(`✅ Discovered ${$.skills.length} skills: ${$.skills.map((b)=>b.name).join(", ")}`);else h.debug("\uD83D\uDCE6 No skills configured");for(let b of $.errors)h.warn(`⚠️ Skill loading error at ${b.path}: ${b.error}`)}catch($){h.warn("Failed to discover skills:",$)}}generateTaskId(){return`task_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}log($,b){h.debug(`[MainAgent] ${$}`,b||"")}error($,b){h.error(`[MainAgent] ${$}`,b||"")}}import{execSync as EV}from"node:child_process";import e2 from"node:fs";import $8 from"node:path";class Jb{async execute($,b){let w=$.content;if(b.signal?.aborted)throw Error("Command execution aborted");return w=this.interpolateArgs(w,b.args),w=await this.executeBashEmbeds(w,b),w=await this.resolveFileReferences(w,b.workspaceRoot),w}interpolateArgs($,b){$=$.replace(/\$ARGUMENTS/g,b.join(" "));for(let w=9;w>=1;w--){let W=`$${w}`,V=b[w-1]??"";$=$.split(W).join(V)}return $}async executeBashEmbeds($,b){let w=/!`([^`]+)`/g,W=[];for(let Q of $.matchAll(w))W.push({match:Q[0],command:Q[1]});let V=$;for(let{match:Q,command:Z}of W){if(b.signal?.aborted){V=V.replace(Q,"[Execution aborted]");continue}try{let J=EV(Z,{cwd:b.workspaceRoot,encoding:"utf-8",timeout:30000,maxBuffer:1048576,stdio:["pipe","pipe","pipe"]}).trim();V=V.replace(Q,J)}catch(J){let Y=J instanceof Error?J.message:String(J);V=V.replace(Q,`[Error executing '${Z}': ${Y}]`)}}return V}async resolveFileReferences($,b){let w=/@([\w./-]+(?:\/[\w./-]+|\.[\w]+))/g,W=[];for(let Q of $.matchAll(w))W.push({match:Q[0],relativePath:Q[1]});let V=$;for(let{match:Q,relativePath:Z}of W){let J=$8.resolve(b,Z);try{if(e2.statSync(J).isFile()){let X=e2.readFileSync(J,"utf-8"),G=`\`\`\`${$8.extname(Z).slice(1)||"text"}
1869
1859
  ${X}
1870
- \`\`\``;W=W.replace(Q,G)}}catch{}}return W}hasDynamicContent($){return{hasArgs:/\$ARGUMENTS|\$\d/.test($),hasBashEmbeds:/!`[^`]+`/.test($),hasFileRefs:/@[\w./-]+(?:\/[\w./-]+|\.[\w]+)/.test($)}}}import yw from"node:fs";import u2 from"node:os";import p$ from"node:path";import VW from"node:fs";import d2 from"node:path";import WW from"gray-matter";class wb{parse($,b,w,V){try{let W=VW.readFileSync($,"utf-8"),{data:Q,content:Z}=WW(W),{name:Y,namespace:J}=this.extractNameAndNamespace($,b);if(!Y)return null;return{name:Y,namespace:J,config:this.normalizeConfig(Q),content:Z.trim(),path:$,source:w,sourceDir:V}}catch{return null}}normalizeConfig($){return{description:this.asString($.description),allowedTools:this.parseAllowedTools($["allowed-tools"]),argumentHint:this.asString($["argument-hint"]),model:this.asString($.model),disableModelInvocation:$["disable-model-invocation"]===!0}}asString($){if(typeof $==="string"&&$.trim())return $.trim();return}parseAllowedTools($){if(!$)return;if(Array.isArray($))return $.map((b)=>String(b).trim()).filter(Boolean);if(typeof $==="string")return $.split(",").map((b)=>b.trim()).filter(Boolean);return}extractNameAndNamespace($,b){let V=d2.relative(b,$).split(d2.sep),W=V.pop();if(!W)return{name:""};let Q=W.replace(/\.md$/i,""),Z=V.length>0?V.join("/"):void 0;return{name:Q,namespace:Z}}validateConfig($){let b=[];if($.model&&!this.isValidModelId($.model))b.push(`Invalid model ID: ${$.model}`);return b}isValidModelId($){return $.length>0&&$.length<200}}class Vb{parser=new wb;async discover($){let b=[],w=[],V=[],W=this.getSearchDirs($);for(let Q of W){if(!yw.existsSync(Q.path))continue;w.push(Q.path);try{let Z=await this.scanDirectory(Q.path);for(let Y of Z)try{let J=this.parser.parse(Y,Q.path,Q.source,Q.sourceDir);if(J)b.push(J)}catch(J){V.push({path:Y,error:J instanceof Error?J.message:String(J)})}}catch(Z){V.push({path:Q.path,error:Z instanceof Error?Z.message:String(Z)})}}return{commands:b,scannedDirs:w,errors:V}}getSearchDirs($){let b=u2.homedir();return[{path:p$.join(b,".blade","commands"),source:"user",sourceDir:"blade"},{path:p$.join(b,".claude","commands"),source:"user",sourceDir:"claude"},{path:p$.join($,".blade","commands"),source:"project",sourceDir:"blade"},{path:p$.join($,".claude","commands"),source:"project",sourceDir:"claude"}]}async scanDirectory($){let b=[],w=async(V)=>{let W=await yw.promises.readdir(V,{withFileTypes:!0});for(let Q of W){let Z=p$.join(V,Q.name);if(Q.isDirectory())await w(Z);else if(Q.isFile()&&Q.name.endsWith(".md"))b.push(Z)}};return await w($),b}async hasCommands($){let b=this.getSearchDirs($);for(let w of b){if(!yw.existsSync(w.path))continue;if((await this.scanDirectory(w.path)).length>0)return!0}return!1}getCommandDirs($){let b=u2.homedir();return{projectBlade:p$.join($,".blade","commands"),projectClaude:p$.join($,".claude","commands"),userBlade:p$.join(b,".blade","commands"),userClaude:p$.join(b,".claude","commands")}}}class L${static instance;commands=new Map;loader=new Vb;executor=new bb;initialized=!1;workspaceRoot="";lastDiscoveryResult=null;static getInstance(){if(!L$.instance)L$.instance=new L$;return L$.instance}static resetInstance(){L$.instance=new L$}constructor(){}async initialize($){this.workspaceRoot=$;let b=await this.loader.discover($);this.lastDiscoveryResult=b,this.commands.clear();for(let w of b.commands)this.commands.set(w.name,w);return this.initialized=!0,b}async refresh(){if(!this.workspaceRoot)throw Error("Registry not initialized. Call initialize() first.");return this.initialize(this.workspaceRoot)}isInitialized(){return this.initialized}getCommand($){return this.commands.get($)}hasCommand($){return this.commands.has($)}getAllCommands(){return Array.from(this.commands.values())}getCommandCount(){return this.commands.size}getModelInvocableCommands(){return this.getAllCommands().filter(($)=>$.config.description&&!$.config.disableModelInvocation)}async executeCommand($,b){let w=this.getCommand($);if(!w)return null;return this.executor.execute(w,b)}getCommandLabel($){let b=$.source==="project"?"project":"user";if($.namespace)return`(${b}:${$.namespace})`;return`(${b})`}getCommandDisplayName($){let b=[`/${$.name}`];if($.config.argumentHint)b.push($.config.argumentHint);if($.config.description)b.push("-",$.config.description);return b.push(this.getCommandLabel($)),b.join(" ")}getCommandsBySource(){let $=[],b=[];for(let w of this.commands.values())if(w.source==="project")$.push(w);else b.push(w);return{project:$,user:b}}getLastDiscoveryResult(){return this.lastDiscoveryResult}getCommandDirs(){if(!this.workspaceRoot)return null;return this.loader.getCommandDirs(this.workspaceRoot)}generateCommandListDescription($=15000){let b=this.getModelInvocableCommands(),w=b.length;if(w===0)return{text:"No custom commands available.",includedCount:0,totalCount:0};let V=`Available custom commands:
1860
+ \`\`\``;V=V.replace(Q,G)}}catch{}}return V}hasDynamicContent($){return{hasArgs:/\$ARGUMENTS|\$\d/.test($),hasBashEmbeds:/!`[^`]+`/.test($),hasFileRefs:/@[\w./-]+(?:\/[\w./-]+|\.[\w]+)/.test($)}}}import uw from"node:fs";import w8 from"node:os";import m$ from"node:path";import jV from"node:fs";import b8 from"node:path";import NV from"gray-matter";class Yb{parse($,b,w,W){try{let V=jV.readFileSync($,"utf-8"),{data:Q,content:Z}=NV(V),{name:J,namespace:Y}=this.extractNameAndNamespace($,b);if(!J)return null;return{name:J,namespace:Y,config:this.normalizeConfig(Q),content:Z.trim(),path:$,source:w,sourceDir:W}}catch{return null}}normalizeConfig($){return{description:this.asString($.description),allowedTools:this.parseAllowedTools($["allowed-tools"]),argumentHint:this.asString($["argument-hint"]),model:this.asString($.model),disableModelInvocation:$["disable-model-invocation"]===!0}}asString($){if(typeof $==="string"&&$.trim())return $.trim();return}parseAllowedTools($){if(!$)return;if(Array.isArray($))return $.map((b)=>String(b).trim()).filter(Boolean);if(typeof $==="string")return $.split(",").map((b)=>b.trim()).filter(Boolean);return}extractNameAndNamespace($,b){let W=b8.relative(b,$).split(b8.sep),V=W.pop();if(!V)return{name:""};let Q=V.replace(/\.md$/i,""),Z=W.length>0?W.join("/"):void 0;return{name:Q,namespace:Z}}validateConfig($){let b=[];if($.model&&!this.isValidModelId($.model))b.push(`Invalid model ID: ${$.model}`);return b}isValidModelId($){return $.length>0&&$.length<200}}class Xb{parser=new Yb;async discover($){let b=[],w=[],W=[],V=this.getSearchDirs($);for(let Q of V){if(!uw.existsSync(Q.path))continue;w.push(Q.path);try{let Z=await this.scanDirectory(Q.path);for(let J of Z)try{let Y=this.parser.parse(J,Q.path,Q.source,Q.sourceDir);if(Y)b.push(Y)}catch(Y){W.push({path:J,error:Y instanceof Error?Y.message:String(Y)})}}catch(Z){W.push({path:Q.path,error:Z instanceof Error?Z.message:String(Z)})}}return{commands:b,scannedDirs:w,errors:W}}getSearchDirs($){let b=w8.homedir();return[{path:m$.join(b,".blade","commands"),source:"user",sourceDir:"blade"},{path:m$.join(b,".claude","commands"),source:"user",sourceDir:"claude"},{path:m$.join($,".blade","commands"),source:"project",sourceDir:"blade"},{path:m$.join($,".claude","commands"),source:"project",sourceDir:"claude"}]}async scanDirectory($){let b=[],w=async(W)=>{let V=await uw.promises.readdir(W,{withFileTypes:!0});for(let Q of V){let Z=m$.join(W,Q.name);if(Q.isDirectory())await w(Z);else if(Q.isFile()&&Q.name.endsWith(".md"))b.push(Z)}};return await w($),b}async hasCommands($){let b=this.getSearchDirs($);for(let w of b){if(!uw.existsSync(w.path))continue;if((await this.scanDirectory(w.path)).length>0)return!0}return!1}getCommandDirs($){let b=w8.homedir();return{projectBlade:m$.join($,".blade","commands"),projectClaude:m$.join($,".claude","commands"),userBlade:m$.join(b,".blade","commands"),userClaude:m$.join(b,".claude","commands")}}}class N${static instance;commands=new Map;loader=new Xb;executor=new Jb;initialized=!1;workspaceRoot="";lastDiscoveryResult=null;static getInstance(){if(!N$.instance)N$.instance=new N$;return N$.instance}static resetInstance(){N$.instance=new N$}constructor(){}async initialize($){this.workspaceRoot=$;let b=await this.loader.discover($);this.lastDiscoveryResult=b,this.commands.clear();for(let w of b.commands)this.commands.set(w.name,w);return this.initialized=!0,b}async refresh(){if(!this.workspaceRoot)throw Error("Registry not initialized. Call initialize() first.");return this.initialize(this.workspaceRoot)}isInitialized(){return this.initialized}getCommand($){return this.commands.get($)}hasCommand($){return this.commands.has($)}getAllCommands(){return Array.from(this.commands.values())}getCommandCount(){return this.commands.size}getModelInvocableCommands(){return this.getAllCommands().filter(($)=>$.config.description&&!$.config.disableModelInvocation)}async executeCommand($,b){let w=this.getCommand($);if(!w)return null;return this.executor.execute(w,b)}getCommandLabel($){let b=$.source==="project"?"project":"user";if($.namespace)return`(${b}:${$.namespace})`;return`(${b})`}getCommandDisplayName($){let b=[`/${$.name}`];if($.config.argumentHint)b.push($.config.argumentHint);if($.config.description)b.push("-",$.config.description);return b.push(this.getCommandLabel($)),b.join(" ")}getCommandsBySource(){let $=[],b=[];for(let w of this.commands.values())if(w.source==="project")$.push(w);else b.push(w);return{project:$,user:b}}getLastDiscoveryResult(){return this.lastDiscoveryResult}getCommandDirs(){if(!this.workspaceRoot)return null;return this.loader.getCommandDirs(this.workspaceRoot)}generateCommandListDescription($=15000){let b=this.getModelInvocableCommands(),w=b.length;if(w===0)return{text:"No custom commands available.",includedCount:0,totalCount:0};let W=`Available custom commands:
1871
1861
 
1872
- `,W=V.length,Q=0;for(let Z of b){let Y=this.getCommandLabel(Z),J=Z.config.argumentHint?` ${Z.config.argumentHint}`:"",X=`- /${Z.name}${J}: ${Z.config.description} ${Y}
1873
- `;if(W+X.length>$)break;V+=X,W+=X.length,Q++}if(Q<w)V+=`
1874
- (${Q} of ${w} commands shown due to character budget)`;return{text:V,includedCount:Q,totalCount:w}}}import{InMemoryTransport as QW}from"@modelcontextprotocol/sdk/inMemory.js";import{McpServer as ZW}from"@modelcontextprotocol/sdk/server/mcp.js";function g2($,b,w,V){return{name:$,description:b,schema:w,handler:V}}async function m2($){let b=new ZW({name:$.name,version:$.version});for(let V of $.tools)b.tool(V.name,V.description,V.schema,async(W)=>{return V.handler(W)});let w=async()=>{let[V,W]=QW.createLinkedPair();return await b.connect(W),V};return{name:$.name,version:$.version,createClientTransport:w,server:b}}import{execSync as s2}from"node:child_process";import*as t from"node:fs/promises";import{homedir as BW}from"node:os";import*as N0 from"node:path";import*as gb from"node:fs/promises";import*as n2 from"node:path";import{z as j}from"zod";var YW=j.string().min(2,"Plugin name must be at least 2 characters").max(64,"Plugin name must be at most 64 characters").regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]{1,2}$/,{message:"Plugin name must be lowercase letters, numbers, and hyphens only, starting and ending with alphanumeric"}),JW=j.string().regex(/^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/,{message:"Version must be a valid semantic version (e.g., 1.0.0)"}),XW=j.object({name:j.string().min(1,"Author name is required"),email:j.string().email().optional(),url:j.string().url().optional()}),i2=j.object({name:YW,description:j.string().min(1,"Description is required").max(500,"Description must be at most 500 characters"),version:JW,author:XW.optional(),license:j.string().optional(),repository:j.string().url().optional(),homepage:j.string().url().optional(),keywords:j.array(j.string()).optional(),dependencies:j.record(j.string()).optional(),bladeVersion:j.string().optional()}),c2=j.object({type:j.enum(["stdio","sse","http"]),command:j.string().optional(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional(),url:j.string().url().optional(),headers:j.record(j.string()).optional(),timeout:j.number().positive().optional(),oauth:j.object({enabled:j.boolean().optional(),clientId:j.string().optional(),clientSecret:j.string().optional(),authorizationUrl:j.string().url().optional(),tokenUrl:j.string().url().optional(),scopes:j.array(j.string()).optional(),redirectUri:j.string().url().optional()}).optional(),healthCheck:j.object({enabled:j.boolean().optional(),interval:j.number().positive().optional(),timeout:j.number().positive().optional(),failureThreshold:j.number().positive().optional()}).optional()}),OW=j.union([j.object({mcpServers:j.record(c2)}),j.record(c2)]);function l2($){return OW.safeParse($)}var GW=[{dir:".blade-plugin",source:"blade"},{dir:".claude-plugin",source:"claude"}];async function s$($){for(let{dir:b,source:w}of GW){let V=n2.join($,b,"plugin.json");try{await gb.access(V)}catch{continue}try{let W=await gb.readFile(V,"utf-8"),Q=JSON.parse(W),Z=i2.safeParse(Q);if(!Z.success){let Y=Z.error.issues.map((J)=>`${J.path.join(".")}: ${J.message}`).join("; ");throw Error(`Invalid plugin.json: ${Y}`)}return I.debug(`Parsed plugin manifest from ${V}`),{manifest:Z.data,source:w,manifestPath:V}}catch(W){if(W instanceof SyntaxError)throw Error(`Invalid JSON in ${V}: ${W.message}`);throw W}}return null}async function mb($){try{return await s$($)!==null}catch{return!1}}class cb{userPluginsDir;constructor($){this.userPluginsDir=$||N0.join(BW(),".blade","plugins")}async install($){try{let b=this.parseGitUrl($);if(!b)return{success:!1,error:`Invalid source URL: ${$}`};let w=this.extractPluginName(b);if(!w)return{success:!1,error:`Could not extract plugin name from URL: ${b}`};await t.mkdir(this.userPluginsDir,{recursive:!0,mode:493});let V=N0.join(this.userPluginsDir,w);try{return await t.access(V),{success:!1,pluginName:w,pluginPath:V,error:`Plugin "${w}" already exists at ${V}. Use /plugins uninstall first.`}}catch{}I.info(`Cloning ${b} to ${V}...`);try{s2(`git clone --depth 1 "${b}" "${V}"`,{stdio:"pipe",timeout:60000})}catch(Q){return{success:!1,pluginName:w,error:`Failed to clone repository: ${Q instanceof Error?Q.message:String(Q)}`}}if(!await mb(V))return await t.rm(V,{recursive:!0,force:!0}),{success:!1,pluginName:w,error:"Invalid plugin: No .blade-plugin/plugin.json or .claude-plugin/plugin.json found"};let W;try{W=await s$(V)}catch(Q){return await t.rm(V,{recursive:!0,force:!0}),{success:!1,pluginName:w,error:`Invalid plugin manifest: ${Q instanceof Error?Q.message:String(Q)}`}}if(!W)return await t.rm(V,{recursive:!0,force:!0}),{success:!1,pluginName:w,error:"Invalid plugin manifest: No manifest found"};return I.info(`Successfully installed plugin: ${W.manifest.name}`),{success:!0,pluginName:W.manifest.name,pluginPath:V,manifest:W.manifest}}catch(b){return{success:!1,error:`Installation failed: ${b instanceof Error?b.message:String(b)}`}}}async uninstall($){try{let b=N0.join(this.userPluginsDir,$);try{await t.access(b)}catch{return{success:!1,pluginName:$,error:`Plugin "${$}" not found at ${b}`}}return await t.rm(b,{recursive:!0,force:!0}),I.info(`Successfully uninstalled plugin: ${$}`),{success:!0,pluginName:$,pluginPath:b}}catch(b){return{success:!1,pluginName:$,error:`Uninstallation failed: ${b instanceof Error?b.message:String(b)}`}}}async listInstalled(){try{return await t.access(this.userPluginsDir),(await t.readdir(this.userPluginsDir,{withFileTypes:!0})).filter((b)=>b.isDirectory()).map((b)=>b.name)}catch{return[]}}async update($){try{let b=N0.join(this.userPluginsDir,$);try{await t.access(b)}catch{return{success:!1,pluginName:$,error:`Plugin "${$}" not found at ${b}`}}let w=N0.join(b,".git");try{await t.access(w)}catch{return{success:!1,pluginName:$,error:`Plugin "${$}" is not a git repository`}}I.info(`Updating plugin: ${$}...`);try{s2(`git -C "${b}" pull --ff-only`,{stdio:"pipe",timeout:60000})}catch(W){return{success:!1,pluginName:$,error:`Failed to update: ${W instanceof Error?W.message:String(W)}`}}let V;try{V=await s$(b)}catch(W){return{success:!1,pluginName:$,error:`Plugin manifest invalid after update: ${W instanceof Error?W.message:String(W)}`}}if(!V)return{success:!1,pluginName:$,error:"Plugin manifest not found after update"};return I.info(`Successfully updated plugin: ${V.manifest.name}`),{success:!0,pluginName:V.manifest.name,pluginPath:b,manifest:V.manifest}}catch(b){return{success:!1,pluginName:$,error:`Update failed: ${b instanceof Error?b.message:String(b)}`}}}parseGitUrl($){if($.startsWith("https://")||$.startsWith("git@"))return $;if(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+$/.test($))return`https://github.com/${$}.git`;return null}extractPluginName($){let b=$.match(/\/([a-zA-Z0-9_.-]+?)(?:\.git)?$/);if(b)return b[1];let w=$.match(/:([a-zA-Z0-9_-]+\/)?([a-zA-Z0-9_.-]+?)(?:\.git)?$/);if(w)return w[2];return null}}var zw=null;function r2($){if(!zw)zw=new cb($);return zw}import*as G$ from"node:fs/promises";import{homedir as KW}from"node:os";import*as g from"node:path";import a2 from"gray-matter";function S0($,b){return`${$}:${b}`}function ib($,b){return`${$}__${b}`}class M0{async loadPlugin($,b,w={}){let V=await s$($);if(!V)throw Error(`Not a valid plugin directory: ${$}`);let{manifest:W,source:Q}=V,Z=W.name;I.debug(`Loading plugin "${Z}" from ${$}`);let Y=w.skipCommands?[]:await this.loadCommands($,Z),J=w.skipAgents?[]:await this.loadAgents($,Z),X=w.skipSkills?[]:await this.loadSkills($,Z),O=w.skipHooks?void 0:await this.loadHooks($),G=w.skipMcp?void 0:await this.loadMcpConfig($,Z);return I.debug(`Plugin "${Z}" loaded: ${Y.length} commands, ${J.length} agents, ${X.length} skills`),{manifest:W,basePath:$,source:b,manifestSource:Q,commands:Y,agents:J,skills:X,hooks:O,mcpServers:G,status:"active",loadedAt:new Date}}async loadCommands($,b){let w=g.join($,"commands"),V=[];if(!await this.dirExists(w))return V;let W=await this.scanMarkdownFiles(w);for(let Q of W)try{let Z=await this.parseCommandFile(Q,w,b);if(Z)V.push(Z)}catch(Z){I.warn(`Failed to load command from ${Q}: ${Z instanceof Error?Z.message:String(Z)}`)}return V}async parseCommandFile($,b,w){let V=await G$.readFile($,"utf-8"),{data:W,content:Q}=a2(V),Y=g.relative(b,$).split(g.sep),J=Y.pop();if(!J)return null;let X=J.replace(/\.md$/i,""),O=X;if(Y.length>0)O=[...Y,X].join("/");let G=S0(w,O),B=this.normalizeCommandConfig(W);return{originalName:O,namespacedName:G,pluginName:w,config:B,content:Q.trim(),path:$}}normalizeCommandConfig($){return{description:this.asString($.description),allowedTools:this.parseStringArray($["allowed-tools"]),argumentHint:this.asString($["argument-hint"]),model:this.asString($.model),disableModelInvocation:$["disable-model-invocation"]===!0}}async loadAgents($,b){let w=g.join($,"agents"),V=[];if(!await this.dirExists(w))return V;let W=await this.scanMarkdownFiles(w);for(let Q of W)try{let Z=await this.parseAgentFile(Q,w,b);if(Z)V.push(Z)}catch(Z){I.warn(`Failed to load agent from ${Q}: ${Z instanceof Error?Z.message:String(Z)}`)}return V}async parseAgentFile($,b,w){let V=await G$.readFile($,"utf-8"),{data:W,content:Q}=a2(V),Z=g.relative(b,$),Y=g.basename(Z,".md"),J=W.name||Y,X=S0(w,J),O={name:X,description:this.asString(W.description)||"",tools:this.parseStringArray(W.tools),color:this.asString(W.color),model:this.asString(W.model),permissionMode:this.asString(W.permissionMode),skills:this.parseStringArray(W.skills),systemPrompt:Q.trim(),source:`plugin:${w}`};return{originalName:J,namespacedName:X,pluginName:w,config:O,path:$}}async loadSkills($,b){let w=g.join($,"skills"),V=[];if(!await this.dirExists(w))return V;let W=await G$.readdir(w,{withFileTypes:!0});for(let Q of W){if(!Q.isDirectory())continue;let Z=g.join(w,Q.name),Y=g.join(Z,"SKILL.md");try{let J=await Kb(Y,"project");if(J.success&&J.content){let X=J.content.metadata.name,O=S0(b,X);V.push({originalName:X,namespacedName:O,pluginName:b,metadata:{...J.content.metadata,name:O},path:Z})}}catch(J){I.warn(`Failed to load skill from ${Y}: ${J instanceof Error?J.message:String(J)}`)}}return V}async loadHooks($){let b=g.join($,"hooks","hooks.json");try{let w=await G$.readFile(b,"utf-8"),V=JSON.parse(w);return V.hooks||V}catch{return}}async loadMcpConfig($,b){let w=g.join($,".mcp.json");try{let V=await G$.readFile(w,"utf-8"),W=JSON.parse(V),Q=l2(W);if(!Q.success){I.warn(`Invalid .mcp.json in ${$}: ${Q.error}`);return}let Z="mcpServers"in W?W.mcpServers:W,Y={};for(let[J,X]of Object.entries(Z)){let O=ib(b,J);Y[O]=X}return Y}catch{return}}async scanMarkdownFiles($){let b=[],w=async(V)=>{let W=await G$.readdir(V,{withFileTypes:!0});for(let Q of W){let Z=g.join(V,Q.name);if(Q.isDirectory())await w(Z);else if(Q.name.endsWith(".md"))b.push(Z)}};return await w($),b}async dirExists($){try{return(await G$.stat($)).isDirectory()}catch{return!1}}asString($){if(typeof $==="string"&&$.trim())return $.trim();return}parseStringArray($){if(!$)return;if(Array.isArray($))return $.map((b)=>String(b).trim()).filter(Boolean);if(typeof $==="string")return $.split(",").map((b)=>b.trim()).filter(Boolean);return}static getPluginDirs($){let b=KW();return[{path:g.join(b,".claude","plugins"),source:"user",type:"claude"},{path:g.join(b,".blade","plugins"),source:"user",type:"blade"},{path:g.join($,".claude","plugins"),source:"project",type:"claude"},{path:g.join($,".blade","plugins"),source:"project",type:"blade"}]}async discoverPluginsInDir($,b){let w=[],V=[];try{await G$.access($)}catch{return{plugins:w,errors:V}}let W=await G$.readdir($,{withFileTypes:!0});for(let Q of W){if(!Q.isDirectory())continue;let Z=g.join($,Q.name);try{let Y=await this.loadPlugin(Z,b);w.push(Y)}catch(Y){V.push({path:Z,error:Y instanceof Error?Y.message:String(Y)})}}return{plugins:w,errors:V}}}class d${static instance=null;plugins=new Map;loader=new M0;initialized=!1;workspaceRoot="";cliPluginDirs=[];constructor(){}static getInstance(){if(!d$.instance)d$.instance=new d$;return d$.instance}static resetInstance(){d$.instance=null}async initialize($,b=[]){this.workspaceRoot=$,this.cliPluginDirs=b;let w=[],V=[];for(let Q of b)try{let Z=await this.loader.loadPlugin(Q,"cli");this.plugins.set(Z.manifest.name,Z),w.push(Z),I.info(`Loaded CLI plugin: ${Z.manifest.name} from ${Q}`)}catch(Z){V.push({path:Q,error:Z instanceof Error?Z.message:String(Z)}),I.warn(`Failed to load CLI plugin from ${Q}: ${Z}`)}let W=M0.getPluginDirs($);for(let{path:Q,source:Z}of W){let Y=await this.loader.discoverPluginsInDir(Q,Z);for(let J of Y.plugins){let X=this.plugins.get(J.manifest.name);if(!X||X.source!=="cli")this.plugins.set(J.manifest.name,J),w.push(J)}V.push(...Y.errors)}return this.initialized=!0,I.info(`Plugin system initialized: ${this.plugins.size} plugins loaded`+(V.length>0?`, ${V.length} errors`:"")),{plugins:Array.from(this.plugins.values()),errors:V}}isInitialized(){return this.initialized}getAll(){return Array.from(this.plugins.values())}getActive(){return Array.from(this.plugins.values()).filter(($)=>$.status==="active")}get($){return this.plugins.get($)}has($){return this.plugins.has($)}getBySource(){let $={cli:[],project:[],user:[]};for(let b of this.plugins.values())$[b.source].push(b);return $}getAllCommands(){let $=[];for(let b of this.plugins.values())if(b.status==="active")$.push(...b.commands);return $}getAllSkills(){let $=[];for(let b of this.plugins.values())if(b.status==="active")$.push(...b.skills);return $}getAllAgents(){let $=[];for(let b of this.plugins.values())if(b.status==="active")$.push(...b.agents);return $}findCommand($){for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let V of w.commands)if(V.namespacedName===$)return V}let b=[];for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let V of w.commands)if(V.originalName===$)b.push(V)}if(b.length===1)return b[0];return}findSkill($){for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let V of w.skills)if(V.namespacedName===$)return V}let b=[];for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let V of w.skills)if(V.originalName===$)b.push(V)}if(b.length===1)return b[0];return}findAgent($){for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let V of w.agents)if(V.namespacedName===$)return V}let b=[];for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let V of w.agents)if(V.originalName===$)b.push(V)}if(b.length===1)return b[0];return}hasCommandConflict($){let b=0;for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let V of w.commands)if(V.originalName===$){if(b++,b>1)return!0}}return!1}getCommandProviders($){let b=[];for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let V of w.commands)if(V.originalName===$){b.push(w.manifest.name);break}}return b}disable($){let b=this.plugins.get($);if(b&&b.status==="active")return b.status="inactive",I.info(`Plugin "${$}" disabled`),!0;return!1}enable($){let b=this.plugins.get($);if(b&&b.status==="inactive")return b.status="active",I.info(`Plugin "${$}" enabled`),!0;return!1}async refresh(){return I.info("Refreshing plugin list..."),this.plugins.clear(),this.initialized=!1,this.initialize(this.workspaceRoot,this.cliPluginDirs)}getStats(){let $=0,b=0,w=0,V=0,W=0;for(let Q of this.plugins.values())if(Q.status==="active")$++,w+=Q.commands.length,V+=Q.skills.length,W+=Q.agents.length;else b++;return{total:this.plugins.size,active:$,inactive:b,commands:w,skills:V,agents:W}}formatPluginList(){if(this.getAll().length===0)return"没有已加载的插件。";let b=[],w=this.getBySource();if(w.cli.length>0){b.push("## CLI 指定的插件");for(let V of w.cli){let W=V.status==="inactive"?" (禁用)":"";b.push(`- **${V.manifest.name}** v${V.manifest.version}${W}`),b.push(` ${V.manifest.description}`)}b.push("")}if(w.project.length>0){b.push("## 项目级插件");for(let V of w.project){let W=V.status==="inactive"?" (禁用)":"";b.push(`- **${V.manifest.name}** v${V.manifest.version}${W}`),b.push(` ${V.manifest.description}`)}b.push("")}if(w.user.length>0){b.push("## 用户级插件");for(let V of w.user){let W=V.status==="inactive"?" (禁用)":"";b.push(`- **${V.manifest.name}** v${V.manifest.version}${W}`),b.push(` ${V.manifest.description}`)}}return b.join(`
1875
- `)}}function lb(){return d$.getInstance()}class Wb{hookManager;mcpRegistry;constructor(){this.hookManager=m.getInstance(),this.mcpRegistry=h.getInstance()}clearAllPluginResources(){_$().clearPluginSkills(),w$.clearPluginAgents(),I.debug("Cleared all plugin resources from subsystems")}async integrateAll(){let b=lb().getActive(),w=[],V=[],W=0,Q=0,Z=0,Y=0;for(let J of b){let X=await this.integratePlugin(J);w.push(X),W+=X.commandsRegistered,Q+=X.skillsRegistered,Z+=X.agentsRegistered,Y+=X.mcpServersRegistered,V.push(...X.errors)}if(W+Q+Z>0)I.info(`Plugin integration complete: ${W} commands, ${Q} skills, ${Z} agents, ${Y} MCP servers`);return{plugins:w,totalCommands:W,totalSkills:Q,totalAgents:Z,totalMcpServers:Y,errors:V}}async integratePlugin($){let b={pluginName:$.manifest.name,commandsRegistered:0,skillsRegistered:0,agentsRegistered:0,hooksRegistered:!1,mcpServersRegistered:0,errors:[]};try{b.commandsRegistered=this.integrateCommands($)}catch(w){b.errors.push(`Failed to integrate commands: ${w instanceof Error?w.message:String(w)}`)}try{b.skillsRegistered=this.integrateSkills($)}catch(w){b.errors.push(`Failed to integrate skills: ${w instanceof Error?w.message:String(w)}`)}try{b.agentsRegistered=this.integrateAgents($)}catch(w){b.errors.push(`Failed to integrate agents: ${w instanceof Error?w.message:String(w)}`)}try{b.hooksRegistered=this.integrateHooks($)}catch(w){b.errors.push(`Failed to integrate hooks: ${w instanceof Error?w.message:String(w)}`)}try{b.mcpServersRegistered=await this.integrateMcp($)}catch(w){b.errors.push(`Failed to integrate MCP servers: ${w instanceof Error?w.message:String(w)}`)}return I.debug(`Integrated plugin "${$.manifest.name}": ${b.commandsRegistered} commands, ${b.skillsRegistered} skills, ${b.agentsRegistered} agents`),b}integrateCommands($){return $.commands.length}integrateSkills($){let b=_$(),w=0;for(let V of $.skills)b.registerPluginSkill(V),w++;return w}integrateAgents($){let b=0;for(let w of $.agents)w$.register({...w.config,name:w.namespacedName}),b++;return b}integrateHooks($){if(!$.hooks)return!1;let b=this.hookManager.getConfig();return this.hookManager.loadConfig({...b,...$.hooks}),!0}async integrateMcp($){if(!$.mcpServers)return 0;let b=0;for(let[w,V]of Object.entries($.mcpServers))try{await this.mcpRegistry.registerServer(w,V),b++}catch(W){I.warn(`Failed to register MCP server "${w}" from plugin "${$.manifest.name}": ${W instanceof Error?W.message:String(W)}`)}return b}}async function o2(){return new Wb().integrateAll()}function t2(){new Wb().clearAllPluginResources()}import{nanoid as qW}from"nanoid";var e=N("Agent");function vw($){return"createClientTransport"in $&&"server"in $}class y0{sessionId;agent=null;abortController=null;_messages=[];options;maxTurns;permissionMode;initialized=!1;pendingMessage=null;pendingSendOptions=null;constructor($,b){this.sessionId=b||qW(),this.options=$,this.maxTurns=$.maxTurns??200,this.permissionMode=$.permissionMode??v.DEFAULT}get messages(){return[...this._messages]}async initialize(){if(this.initialized)return;let $=this.buildBladeConfig();if(this.options.sandbox)_0().configure(this.options.sandbox);if(this.options.enableFileCheckpointing)S$().configure({enabled:!0});await this.registerInProcessMcpServers(),this.agent=await P$.create($,{permissionMode:this.permissionMode,systemPrompt:this.options.systemPrompt,maxTurns:this.maxTurns,canUseTool:this.options.canUseTool,outputFormat:this.options.outputFormat,sandbox:this.options.sandbox}),this.initialized=!0,e.debug(`[Session] Initialized session ${this.sessionId}`)}async registerInProcessMcpServers(){if(!this.options.mcpServers)return;let $=h.getInstance();for(let[b,w]of Object.entries(this.options.mcpServers))if(vw(w))await $.registerInProcessServer(b,w),e.debug(`[Session] Registered in-process MCP server: ${b}`)}async loadHistory(){let $=this.options.cwd||process.cwd(),b=X$($,this.sessionId),w=new W$(b);try{let V=await w.readAll();if(V.length===0){e.debug(`[Session] No history found for session ${this.sessionId}`);return}let W=new Map,Q=new Map;for(let Z of V){if(Z.type==="message_created"){let Y=Z.data;W.set(Y.messageId,{role:Y.role,content:"",toolCalls:[]})}if(Z.type==="part_created"){let Y=Z.data,J=W.get(Y.messageId);if(!J)J={role:Y.partType==="tool_result"?"tool":"assistant",content:"",toolCalls:[]},W.set(Y.messageId,J);switch(Y.partType){case"text":{let X=Y.payload;J.content=X.text??"";break}case"tool_call":{let X=Y.payload,O={id:X.toolCallId,type:"function",function:{name:X.toolName,arguments:typeof X.input==="string"?X.input:JSON.stringify(X.input)}};J.toolCalls.push(O),Q.set(X.toolCallId,{messageId:Y.messageId,toolCallId:X.toolCallId});break}case"tool_result":{let X=Y.payload;if(J.role="tool",J.toolCallId=X.toolCallId,J.name=X.toolName,X.error)J.content=`Error: ${X.error}`;else if(X.output===null||X.output===void 0)J.content="";else if(typeof X.output==="string")J.content=X.output;else J.content=JSON.stringify(X.output);break}case"summary":{let X=Y.payload;J.content=X.text??"";break}}}}this._messages=Array.from(W.values()).map((Z)=>{let Y={role:Z.role,content:Z.content};if(Z.toolCalls.length>0)Y.tool_calls=Z.toolCalls;if(Z.toolCallId)Y.tool_call_id=Z.toolCallId;if(Z.name)Y.name=Z.name;return Y}),e.debug(`[Session] Loaded ${this._messages.length} messages from history`)}catch(V){e.warn(`[Session] Failed to load history for session ${this.sessionId}:`,V)}}buildBladeConfig(){let $=this.buildModelConfig(),b,w;if(this.options.mcpServers){let V={},W=[];for(let[Q,Z]of Object.entries(this.options.mcpServers))if(vw(Z))W.push(Q);else V[Q]=Z;b=Object.keys(V).length>0?V:void 0,w=W.length>0?W:void 0}return{models:[$],currentModelId:$.id,temperature:0.7,mcpServers:b,inProcessMcpServerNames:w,permissions:{allow:[],deny:[]}}}buildModelConfig(){let $=this.options.provider;return{id:"default",name:this.options.model,provider:this.mapProviderType($.type),model:this.options.model,apiKey:$.apiKey||"",baseUrl:$.baseUrl||this.getDefaultBaseUrl($.type),maxContextTokens:128000}}mapProviderType($){return{"openai-compatible":"openai-compatible",anthropic:"anthropic",gemini:"gemini","azure-openai":"azure-openai"}[$]||"openai-compatible"}getDefaultBaseUrl($){return{"openai-compatible":"https://api.openai.com/v1",anthropic:"https://api.anthropic.com",gemini:"https://generativelanguage.googleapis.com","azure-openai":""}[$]||""}async send($,b){if(await this.ensureInitialized(),this.pendingMessage!==null)throw Error("Cannot send a new message while a previous message is pending. Call stream() first.");this.pendingMessage=$,this.pendingSendOptions=b||null}async*stream($){if(this.pendingMessage===null)throw Error("No pending message. Call send() before stream().");let b=this.pendingMessage,w=this.pendingSendOptions;this.pendingMessage=null,this.pendingSendOptions=null;let V=[],W={inputTokens:0,outputTokens:0,totalTokens:0,maxContextTokens:0};this.abortController=new AbortController;let Q=w?.signal?this.combineSignals(w.signal,this.abortController.signal):this.abortController.signal,Z={messages:this._messages,userId:"sdk-user",sessionId:this.sessionId,workspaceRoot:this.options.cwd||process.cwd(),signal:Q,permissionMode:this.permissionMode},Y=this.agent.streamChat(b,Z,{maxTurns:w?.maxTurns??this.maxTurns,signal:Q});try{let J;while(!0){let{value:G,done:B}=await Y.next();if(B){J=G;break}switch(G.type){case"turn_start":yield{type:"turn_start",turn:G.turn,sessionId:this.sessionId};break;case"content_delta":yield{type:"content",delta:G.delta,sessionId:this.sessionId};break;case"thinking_delta":if($?.includeThinking)yield{type:"thinking",delta:G.delta,sessionId:this.sessionId};break;case"content":yield{type:"content",delta:G.content,sessionId:this.sessionId};break;case"thinking":if($?.includeThinking)yield{type:"thinking",delta:G.content,sessionId:this.sessionId};break;case"tool_start":{if(G.toolCall.type!=="function")break;let q=this.safeParseJson(G.toolCall.function.arguments);V.push({id:G.toolCall.id,name:G.toolCall.function.name,input:q,output:null,duration:0}),yield{type:"tool_use",id:G.toolCall.id,name:G.toolCall.function.name,input:q,sessionId:this.sessionId};break}case"tool_result":{if(G.toolCall.type!=="function")break;let q=V.find((U)=>U.id===G.toolCall.id);if(q)q.output=G.result.llmContent,q.isError=!G.result.success;yield{type:"tool_result",id:G.toolCall.id,name:G.toolCall.function.name,output:G.result.llmContent,isError:!G.result.success,sessionId:this.sessionId};break}case"token_usage":W={inputTokens:G.usage.inputTokens,outputTokens:G.usage.outputTokens,totalTokens:G.usage.totalTokens,maxContextTokens:G.usage.maxContextTokens};break;default:break}}if(!J)throw Error("Stream ended without result");let X=J.error?.type==="aborted",O=J.metadata?.shouldExitLoop;if(!J.success&&!X&&!O){yield{type:"error",message:J.error?.message||"Unknown error",sessionId:this.sessionId};return}yield{type:"usage",usage:W,sessionId:this.sessionId},this._messages=Z.messages,yield{type:"result",subtype:"success",content:J.finalMessage||"",sessionId:this.sessionId}}catch(J){yield{type:"error",message:J instanceof Error?J.message:String(J),sessionId:this.sessionId}}finally{this.abortController=null}}close(){this.abort(),this.agent=null,this.initialized=!1,this.pendingMessage=null,this.pendingSendOptions=null,e.debug(`[Session] Closed session ${this.sessionId}`)}abort(){if(this.abortController)this.abortController.abort(),this.abortController=null}setPermissionMode($){this.permissionMode=$}async setModel($){e.warn("[Session] setModel is not yet implemented")}setMaxTurns($){this.maxTurns=$}async supportedCommands(){let $=L$.getInstance();if(!$.isInitialized())await $.initialize(this.options.cwd||process.cwd());return $.getAllCommands().map((b)=>({name:b.name,description:b.config.description||"",usage:b.config.argumentHint}))}async supportedModels(){return[{id:"default",name:this.options.model,provider:this.options.provider.type}]}async mcpServerStatus(){let b=h.getInstance().getAllServers(),w=[];for(let[V,W]of b){let Q={connected:"connected",disconnected:"disconnected",connecting:"connecting",error:"error"};w.push({name:V,status:Q[W.status],toolCount:W.tools.length,tools:W.tools.map((Z)=>Z.name),connectedAt:W.connectedAt,error:W.lastError?.message})}return w}async mcpConnect($){await this.ensureInitialized();let b=h.getInstance();if(!b.getServerStatus($)){let V=this.options.mcpServers?.[$];if(!V)throw Error(`MCP server "${$}" not found in configuration`);if(vw(V))await b.registerInProcessServer($,V);else await b.registerServer($,V)}else await b.connectServer($);e.debug(`[Session] Connected to MCP server: ${$}`)}async mcpDisconnect($){await h.getInstance().disconnectServer($),e.debug(`[Session] Disconnected from MCP server: ${$}`)}async mcpReconnect($){await h.getInstance().reconnectServer($),e.debug(`[Session] Reconnected to MCP server: ${$}`)}async mcpListTools(){let b=h.getInstance().getAllServers(),w=[];for(let[V,W]of b)if(W.status==="connected")for(let Q of W.tools)w.push({name:Q.name,description:Q.description,serverName:V});return w}async[Symbol.asyncDispose](){this.close()}async ensureInitialized(){if(!this.initialized)await this.initialize()}combineSignals($,b){let w=new AbortController,V=()=>w.abort();if($.aborted||b.aborted)w.abort();else $.addEventListener("abort",V),b.addEventListener("abort",V);return w.signal}safeParseJson($){try{return JSON.parse($)}catch{return $}}async rewindFiles($){if(!this.options.enableFileCheckpointing)return{success:!1,restoredFiles:[],deletedFiles:[],errors:[{filePath:"",error:"File checkpointing is not enabled"}]};return S$().rewindFiles($)}getCheckpointStatistics(){if(!this.options.enableFileCheckpointing)return null;return S$().getStatistics()}async fork($){await this.ensureInitialized();let b=$?.messageId,w=[...this._messages];if(b){let W=this.findMessageIndexByUuid(b);if(W===-1)throw Error(`Message with ID "${b}" not found in session history`);w=this._messages.slice(0,W+1)}let V=new y0(this.options);if(await V.initialize(),V._messages=w.map((W)=>({...W})),$?.copyCheckpoints&&this.options.enableFileCheckpointing)e.debug("[Session] Checkpoint copying is not yet implemented for forked sessions");return e.debug(`[Session] Forked session ${this.sessionId} -> ${V.sessionId} with ${w.length} messages`),V}findMessageIndexByUuid($){for(let b=0;b<this._messages.length;b++)if(this._messages[b].uuid===$)return b;return this._messages.length>0?this._messages.length-1:-1}}async function e2($){let b=new y0($);return await b.initialize(),e.debug(`[Session] Created new session: ${b.sessionId}`),b}async function $8($){let{sessionId:b,...w}=$,V=new y0(w,b);return await V.initialize(),await V.loadHistory(),e.debug(`[Session] Resumed session: ${b} with ${V.messages.length} messages`),V}async function b8($){let{sessionId:b,messageId:w,copyCheckpoints:V,...W}=$,Q=new y0(W,b);await Q.initialize(),await Q.loadHistory();let Z=await Q.fork({messageId:w,copyCheckpoints:V});return Q.close(),e.debug(`[Session] Forked session ${b} -> ${Z.sessionId} with ${Z.messages.length} messages`),Z}async function w8($,b){let w=Date.now(),V=new y0(b);await V.initialize();let W=[],Q={inputTokens:0,outputTokens:0,totalTokens:0,maxContextTokens:0},Z=0,Y="",J=null;try{await V.send($);for await(let X of V.stream())if(X.type==="turn_start")Z=X.turn;else if(X.type==="tool_use")W.push({id:X.id,name:X.name,input:X.input,output:null,duration:0});else if(X.type==="tool_result"){let O=W.find((G)=>G.id===X.id);if(O)O.output=X.output,O.isError=X.isError}else if(X.type==="usage")Q=X.usage;else if(X.type==="result"&&X.subtype==="success")Y=X.content||"";else if(X.type==="error")J=X.message;else if(X.type==="result"&&X.subtype==="error")J=X.error||"Unknown error";if(J)throw Error(J);return{result:Y,toolCalls:W,usage:Q,duration:Date.now()-w,turnsCount:Z}}finally{V.close()}}export{S5 as toolFromDefinition,g2 as tool,tW as shutdownLogger,oW as setLoggerSessionId,$8 as resumeSession,kb as readMcpResourceTool,w8 as prompt,s$ as parsePluginManifest,Rb as notebookEditTool,I as logger,Tb as listMcpResourcesTool,mb as isValidPluginDir,Cw as isThinkingModel,B0 as isReadOnlyKind,y9 as isGlobMetadata,z9 as isEditMetadata,o2 as integrateAllPlugins,Cb as injectSkillsMetadata,j2 as getThinkingConfig,_0 as getSandboxService,H0 as getSandboxExecutor,lb as getPluginRegistry,r2 as getPluginInstaller,S0 as getNamespacedName,ib as getMcpNamespacedName,S$ as getCheckpointService,Zw as getBuiltinTools,b8 as forkSession,Ub as discoverSkills,L2 as detectThinkingSupport,M5 as defineTool,E as createTool,e2 as createSession,m2 as createSdkMcpServer,N as createLogger,Yb as createChatServiceAsync,t2 as clearAllPluginResources,yb as askUserQuestionTool,Yw as agentLoop,$b as ToolRegistry,O8 as ToolKind,K1 as ToolExecution,U8 as ToolErrorType,X8 as StreamMessageType,x as SpecManager,I$ as SandboxService,f$ as SandboxExecutor,b0 as STEERING_FILES,p4 as SPEC_FILE_NAMES,$0 as SPEC_DIRS,d$ as PluginRegistry,M0 as PluginLoader,Wb as PluginIntegrator,cb as PluginInstaller,rb as PermissionMode,K8 as PermissionDecision,G8 as PermissionBehavior,s0 as PHASE_TRANSITIONS,d4 as PHASE_PRIMARY_FILE,lY as PHASE_ORDER,q$ as PHASE_DISPLAY_NAMES,fw as MessageRole,h as McpRegistry,R1 as McpErrorType,r$ as McpConnectionStatus,K0 as McpClient,T$ as Logger,O1 as LogLevel,p as LogCategory,q8 as HookType,m as HookManager,A8 as HookExitCode,v0 as HookEvent,_1 as HealthStatus,x0 as HealthMonitor,Pb as ExecutionPipeline,B8 as DecisionBehavior,ub as ContextManager,r as CompactionService,L$ as CommandRegistry,wb as CommandParser,Vb as CommandLoader,bb as CommandExecutor,k$ as CheckpointService,P$ as Agent};
1862
+ `,V=W.length,Q=0;for(let Z of b){let J=this.getCommandLabel(Z),Y=Z.config.argumentHint?` ${Z.config.argumentHint}`:"",X=`- /${Z.name}${Y}: ${Z.config.description} ${J}
1863
+ `;if(V+X.length>$)break;W+=X,V+=X.length,Q++}if(Q<w)W+=`
1864
+ (${Q} of ${w} commands shown due to character budget)`;return{text:W,includedCount:Q,totalCount:w}}}import{InMemoryTransport as SV}from"@modelcontextprotocol/sdk/inMemory.js";import{McpServer as yV}from"@modelcontextprotocol/sdk/server/mcp.js";function W8($,b,w,W){return{name:$,description:b,schema:w,handler:W}}async function V8($){let b=new yV({name:$.name,version:$.version});for(let W of $.tools)b.tool(W.name,W.description,W.schema,async(V)=>{return W.handler(V)});let w=async()=>{let[W,V]=SV.createLinkedPair();return await b.connect(V),W};return{name:$.name,version:$.version,createClientTransport:w,server:b}}import{execSync as X8}from"node:child_process";import*as e from"node:fs/promises";import{homedir as fV}from"node:os";import*as z0 from"node:path";import*as ab from"node:fs/promises";import*as Y8 from"node:path";import{z as j}from"zod";var MV=j.string().min(2,"Plugin name must be at least 2 characters").max(64,"Plugin name must be at most 64 characters").regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]{1,2}$/,{message:"Plugin name must be lowercase letters, numbers, and hyphens only, starting and ending with alphanumeric"}),zV=j.string().regex(/^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/,{message:"Version must be a valid semantic version (e.g., 1.0.0)"}),vV=j.object({name:j.string().min(1,"Author name is required"),email:j.string().email().optional(),url:j.string().url().optional()}),Z8=j.object({name:MV,description:j.string().min(1,"Description is required").max(500,"Description must be at most 500 characters"),version:zV,author:vV.optional(),license:j.string().optional(),repository:j.string().url().optional(),homepage:j.string().url().optional(),keywords:j.array(j.string()).optional(),dependencies:j.record(j.string()).optional(),bladeVersion:j.string().optional()}),Q8=j.object({type:j.enum(["stdio","sse","http"]),command:j.string().optional(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional(),url:j.string().url().optional(),headers:j.record(j.string()).optional(),timeout:j.number().positive().optional(),oauth:j.object({enabled:j.boolean().optional(),clientId:j.string().optional(),clientSecret:j.string().optional(),authorizationUrl:j.string().url().optional(),tokenUrl:j.string().url().optional(),scopes:j.array(j.string()).optional(),redirectUri:j.string().url().optional()}).optional(),healthCheck:j.object({enabled:j.boolean().optional(),interval:j.number().positive().optional(),timeout:j.number().positive().optional(),failureThreshold:j.number().positive().optional()}).optional()}),TV=j.union([j.object({mcpServers:j.record(Q8)}),j.record(Q8)]);function J8($){return TV.safeParse($)}var kV=[{dir:".blade-plugin",source:"blade"},{dir:".claude-plugin",source:"claude"}];async function o$($){for(let{dir:b,source:w}of kV){let W=Y8.join($,b,"plugin.json");try{await ab.access(W)}catch{continue}try{let V=await ab.readFile(W,"utf-8"),Q=JSON.parse(V),Z=Z8.safeParse(Q);if(!Z.success){let J=Z.error.issues.map((Y)=>`${Y.path.join(".")}: ${Y.message}`).join("; ");throw Error(`Invalid plugin.json: ${J}`)}return I.debug(`Parsed plugin manifest from ${W}`),{manifest:Z.data,source:w,manifestPath:W}}catch(V){if(V instanceof SyntaxError)throw Error(`Invalid JSON in ${W}: ${V.message}`);throw V}}return null}async function ob($){try{return await o$($)!==null}catch{return!1}}class tb{userPluginsDir;constructor($){this.userPluginsDir=$||z0.join(fV(),".blade","plugins")}async install($){try{let b=this.parseGitUrl($);if(!b)return{success:!1,error:`Invalid source URL: ${$}`};let w=this.extractPluginName(b);if(!w)return{success:!1,error:`Could not extract plugin name from URL: ${b}`};await e.mkdir(this.userPluginsDir,{recursive:!0,mode:493});let W=z0.join(this.userPluginsDir,w);try{return await e.access(W),{success:!1,pluginName:w,pluginPath:W,error:`Plugin "${w}" already exists at ${W}. Use /plugins uninstall first.`}}catch{}I.info(`Cloning ${b} to ${W}...`);try{X8(`git clone --depth 1 "${b}" "${W}"`,{stdio:"pipe",timeout:60000})}catch(Q){return{success:!1,pluginName:w,error:`Failed to clone repository: ${Q instanceof Error?Q.message:String(Q)}`}}if(!await ob(W))return await e.rm(W,{recursive:!0,force:!0}),{success:!1,pluginName:w,error:"Invalid plugin: No .blade-plugin/plugin.json or .claude-plugin/plugin.json found"};let V;try{V=await o$(W)}catch(Q){return await e.rm(W,{recursive:!0,force:!0}),{success:!1,pluginName:w,error:`Invalid plugin manifest: ${Q instanceof Error?Q.message:String(Q)}`}}if(!V)return await e.rm(W,{recursive:!0,force:!0}),{success:!1,pluginName:w,error:"Invalid plugin manifest: No manifest found"};return I.info(`Successfully installed plugin: ${V.manifest.name}`),{success:!0,pluginName:V.manifest.name,pluginPath:W,manifest:V.manifest}}catch(b){return{success:!1,error:`Installation failed: ${b instanceof Error?b.message:String(b)}`}}}async uninstall($){try{let b=z0.join(this.userPluginsDir,$);try{await e.access(b)}catch{return{success:!1,pluginName:$,error:`Plugin "${$}" not found at ${b}`}}return await e.rm(b,{recursive:!0,force:!0}),I.info(`Successfully uninstalled plugin: ${$}`),{success:!0,pluginName:$,pluginPath:b}}catch(b){return{success:!1,pluginName:$,error:`Uninstallation failed: ${b instanceof Error?b.message:String(b)}`}}}async listInstalled(){try{return await e.access(this.userPluginsDir),(await e.readdir(this.userPluginsDir,{withFileTypes:!0})).filter((b)=>b.isDirectory()).map((b)=>b.name)}catch{return[]}}async update($){try{let b=z0.join(this.userPluginsDir,$);try{await e.access(b)}catch{return{success:!1,pluginName:$,error:`Plugin "${$}" not found at ${b}`}}let w=z0.join(b,".git");try{await e.access(w)}catch{return{success:!1,pluginName:$,error:`Plugin "${$}" is not a git repository`}}I.info(`Updating plugin: ${$}...`);try{X8(`git -C "${b}" pull --ff-only`,{stdio:"pipe",timeout:60000})}catch(V){return{success:!1,pluginName:$,error:`Failed to update: ${V instanceof Error?V.message:String(V)}`}}let W;try{W=await o$(b)}catch(V){return{success:!1,pluginName:$,error:`Plugin manifest invalid after update: ${V instanceof Error?V.message:String(V)}`}}if(!W)return{success:!1,pluginName:$,error:"Plugin manifest not found after update"};return I.info(`Successfully updated plugin: ${W.manifest.name}`),{success:!0,pluginName:W.manifest.name,pluginPath:b,manifest:W.manifest}}catch(b){return{success:!1,pluginName:$,error:`Update failed: ${b instanceof Error?b.message:String(b)}`}}}parseGitUrl($){if($.startsWith("https://")||$.startsWith("git@"))return $;if(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+$/.test($))return`https://github.com/${$}.git`;return null}extractPluginName($){let b=$.match(/\/([a-zA-Z0-9_.-]+?)(?:\.git)?$/);if(b)return b[1];let w=$.match(/:([a-zA-Z0-9_-]+\/)?([a-zA-Z0-9_.-]+?)(?:\.git)?$/);if(w)return w[2];return null}}var gw=null;function O8($){if(!gw)gw=new tb($);return gw}import*as K$ from"node:fs/promises";import{homedir as IV}from"node:os";import*as m from"node:path";import G8 from"gray-matter";function v0($,b){return`${$}:${b}`}function eb($,b){return`${$}__${b}`}class T0{async loadPlugin($,b,w={}){let W=await o$($);if(!W)throw Error(`Not a valid plugin directory: ${$}`);let{manifest:V,source:Q}=W,Z=V.name;I.debug(`Loading plugin "${Z}" from ${$}`);let J=w.skipCommands?[]:await this.loadCommands($,Z),Y=w.skipAgents?[]:await this.loadAgents($,Z),X=w.skipSkills?[]:await this.loadSkills($,Z),O=w.skipHooks?void 0:await this.loadHooks($),G=w.skipMcp?void 0:await this.loadMcpConfig($,Z);return I.debug(`Plugin "${Z}" loaded: ${J.length} commands, ${Y.length} agents, ${X.length} skills`),{manifest:V,basePath:$,source:b,manifestSource:Q,commands:J,agents:Y,skills:X,hooks:O,mcpServers:G,status:"active",loadedAt:new Date}}async loadCommands($,b){let w=m.join($,"commands"),W=[];if(!await this.dirExists(w))return W;let V=await this.scanMarkdownFiles(w);for(let Q of V)try{let Z=await this.parseCommandFile(Q,w,b);if(Z)W.push(Z)}catch(Z){I.warn(`Failed to load command from ${Q}: ${Z instanceof Error?Z.message:String(Z)}`)}return W}async parseCommandFile($,b,w){let W=await K$.readFile($,"utf-8"),{data:V,content:Q}=G8(W),J=m.relative(b,$).split(m.sep),Y=J.pop();if(!Y)return null;let X=Y.replace(/\.md$/i,""),O=X;if(J.length>0)O=[...J,X].join("/");let G=v0(w,O),B=this.normalizeCommandConfig(V);return{originalName:O,namespacedName:G,pluginName:w,config:B,content:Q.trim(),path:$}}normalizeCommandConfig($){return{description:this.asString($.description),allowedTools:this.parseStringArray($["allowed-tools"]),argumentHint:this.asString($["argument-hint"]),model:this.asString($.model),disableModelInvocation:$["disable-model-invocation"]===!0}}async loadAgents($,b){let w=m.join($,"agents"),W=[];if(!await this.dirExists(w))return W;let V=await this.scanMarkdownFiles(w);for(let Q of V)try{let Z=await this.parseAgentFile(Q,w,b);if(Z)W.push(Z)}catch(Z){I.warn(`Failed to load agent from ${Q}: ${Z instanceof Error?Z.message:String(Z)}`)}return W}async parseAgentFile($,b,w){let W=await K$.readFile($,"utf-8"),{data:V,content:Q}=G8(W),Z=m.relative(b,$),J=m.basename(Z,".md"),Y=V.name||J,X=v0(w,Y),O={name:X,description:this.asString(V.description)||"",tools:this.parseStringArray(V.tools),color:this.asString(V.color),model:this.asString(V.model),permissionMode:this.asString(V.permissionMode),skills:this.parseStringArray(V.skills),systemPrompt:Q.trim(),source:`plugin:${w}`};return{originalName:Y,namespacedName:X,pluginName:w,config:O,path:$}}async loadSkills($,b){let w=m.join($,"skills"),W=[];if(!await this.dirExists(w))return W;let V=await K$.readdir(w,{withFileTypes:!0});for(let Q of V){if(!Q.isDirectory())continue;let Z=m.join(w,Q.name),J=m.join(Z,"SKILL.md");try{let Y=await Fb(J,"project");if(Y.success&&Y.content){let X=Y.content.metadata.name,O=v0(b,X);W.push({originalName:X,namespacedName:O,pluginName:b,metadata:{...Y.content.metadata,name:O},path:Z})}}catch(Y){I.warn(`Failed to load skill from ${J}: ${Y instanceof Error?Y.message:String(Y)}`)}}return W}async loadHooks($){let b=m.join($,"hooks","hooks.json");try{let w=await K$.readFile(b,"utf-8"),W=JSON.parse(w);return W.hooks||W}catch{return}}async loadMcpConfig($,b){let w=m.join($,".mcp.json");try{let W=await K$.readFile(w,"utf-8"),V=JSON.parse(W),Q=J8(V);if(!Q.success){I.warn(`Invalid .mcp.json in ${$}: ${Q.error}`);return}let Z="mcpServers"in V?V.mcpServers:V,J={};for(let[Y,X]of Object.entries(Z)){let O=eb(b,Y);J[O]=X}return J}catch{return}}async scanMarkdownFiles($){let b=[],w=async(W)=>{let V=await K$.readdir(W,{withFileTypes:!0});for(let Q of V){let Z=m.join(W,Q.name);if(Q.isDirectory())await w(Z);else if(Q.name.endsWith(".md"))b.push(Z)}};return await w($),b}async dirExists($){try{return(await K$.stat($)).isDirectory()}catch{return!1}}asString($){if(typeof $==="string"&&$.trim())return $.trim();return}parseStringArray($){if(!$)return;if(Array.isArray($))return $.map((b)=>String(b).trim()).filter(Boolean);if(typeof $==="string")return $.split(",").map((b)=>b.trim()).filter(Boolean);return}static getPluginDirs($){let b=IV(),w="user",W="project";return[{path:m.join(b,".claude","plugins"),source:"user",type:"claude"},{path:m.join(b,".blade","plugins"),source:"user",type:"blade"},{path:m.join($,".claude","plugins"),source:"project",type:"claude"},{path:m.join($,".blade","plugins"),source:"project",type:"blade"}]}async discoverPluginsInDir($,b){let w=[],W=[];try{await K$.access($)}catch{return{plugins:w,errors:W}}let V=await K$.readdir($,{withFileTypes:!0});for(let Q of V){if(!Q.isDirectory())continue;let Z=m.join($,Q.name);try{let J=await this.loadPlugin(Z,b);w.push(J)}catch(J){W.push({path:Z,error:J instanceof Error?J.message:String(J)})}}return{plugins:w,errors:W}}}class c${static instance=null;plugins=new Map;loader=new T0;initialized=!1;workspaceRoot="";cliPluginDirs=[];constructor(){}static getInstance(){if(!c$.instance)c$.instance=new c$;return c$.instance}static resetInstance(){c$.instance=null}async initialize($,b=[]){this.workspaceRoot=$,this.cliPluginDirs=b;let w=[],W=[];for(let Q of b)try{let Z=await this.loader.loadPlugin(Q,"cli");this.plugins.set(Z.manifest.name,Z),w.push(Z),I.info(`Loaded CLI plugin: ${Z.manifest.name} from ${Q}`)}catch(Z){W.push({path:Q,error:Z instanceof Error?Z.message:String(Z)}),I.warn(`Failed to load CLI plugin from ${Q}: ${Z}`)}let V=T0.getPluginDirs($);for(let{path:Q,source:Z}of V){let J=await this.loader.discoverPluginsInDir(Q,Z);for(let Y of J.plugins){let X=this.plugins.get(Y.manifest.name);if(!X||X.source!=="cli")this.plugins.set(Y.manifest.name,Y),w.push(Y)}W.push(...J.errors)}return this.initialized=!0,I.info(`Plugin system initialized: ${this.plugins.size} plugins loaded`+(W.length>0?`, ${W.length} errors`:"")),{plugins:Array.from(this.plugins.values()),errors:W}}isInitialized(){return this.initialized}getAll(){return Array.from(this.plugins.values())}getActive(){return Array.from(this.plugins.values()).filter(($)=>$.status==="active")}get($){return this.plugins.get($)}has($){return this.plugins.has($)}getBySource(){let $={cli:[],project:[],user:[]};for(let b of this.plugins.values())$[b.source].push(b);return $}getAllCommands(){let $=[];for(let b of this.plugins.values())if(b.status==="active")$.push(...b.commands);return $}getAllSkills(){let $=[];for(let b of this.plugins.values())if(b.status==="active")$.push(...b.skills);return $}getAllAgents(){let $=[];for(let b of this.plugins.values())if(b.status==="active")$.push(...b.agents);return $}findCommand($){for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let W of w.commands)if(W.namespacedName===$)return W}let b=[];for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let W of w.commands)if(W.originalName===$)b.push(W)}if(b.length===1)return b[0];return}findSkill($){for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let W of w.skills)if(W.namespacedName===$)return W}let b=[];for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let W of w.skills)if(W.originalName===$)b.push(W)}if(b.length===1)return b[0];return}findAgent($){for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let W of w.agents)if(W.namespacedName===$)return W}let b=[];for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let W of w.agents)if(W.originalName===$)b.push(W)}if(b.length===1)return b[0];return}hasCommandConflict($){let b=0;for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let W of w.commands)if(W.originalName===$){if(b++,b>1)return!0}}return!1}getCommandProviders($){let b=[];for(let w of this.plugins.values()){if(w.status!=="active")continue;for(let W of w.commands)if(W.originalName===$){b.push(w.manifest.name);break}}return b}disable($){let b=this.plugins.get($);if(b&&b.status==="active")return b.status="inactive",I.info(`Plugin "${$}" disabled`),!0;return!1}enable($){let b=this.plugins.get($);if(b&&b.status==="inactive")return b.status="active",I.info(`Plugin "${$}" enabled`),!0;return!1}async refresh(){return I.info("Refreshing plugin list..."),this.plugins.clear(),this.initialized=!1,this.initialize(this.workspaceRoot,this.cliPluginDirs)}getStats(){let $=0,b=0,w=0,W=0,V=0;for(let Q of this.plugins.values())if(Q.status==="active")$++,w+=Q.commands.length,W+=Q.skills.length,V+=Q.agents.length;else b++;return{total:this.plugins.size,active:$,inactive:b,commands:w,skills:W,agents:V}}formatPluginList(){if(this.getAll().length===0)return"没有已加载的插件。";let b=[],w=this.getBySource();if(w.cli.length>0){b.push("## CLI 指定的插件");for(let W of w.cli){let V=W.status==="inactive"?" (禁用)":"";b.push(`- **${W.manifest.name}** v${W.manifest.version}${V}`),b.push(` ${W.manifest.description}`)}b.push("")}if(w.project.length>0){b.push("## 项目级插件");for(let W of w.project){let V=W.status==="inactive"?" (禁用)":"";b.push(`- **${W.manifest.name}** v${W.manifest.version}${V}`),b.push(` ${W.manifest.description}`)}b.push("")}if(w.user.length>0){b.push("## 用户级插件");for(let W of w.user){let V=W.status==="inactive"?" (禁用)":"";b.push(`- **${W.manifest.name}** v${W.manifest.version}${V}`),b.push(` ${W.manifest.description}`)}}return b.join(`
1865
+ `)}}function $1(){return c$.getInstance()}class Ob{hookManager;mcpRegistry;constructor($){this.hookManager=c.getInstance(),this.mcpRegistry=$}clearAllPluginResources(){_$().clearPluginSkills(),W$.clearPluginAgents(),I.debug("Cleared all plugin resources from subsystems")}async integrateAll(){let b=$1().getActive(),w=[],W=[],V=0,Q=0,Z=0,J=0;for(let Y of b){let X=await this.integratePlugin(Y);w.push(X),V+=X.commandsRegistered,Q+=X.skillsRegistered,Z+=X.agentsRegistered,J+=X.mcpServersRegistered,W.push(...X.errors)}if(V+Q+Z>0)I.info(`Plugin integration complete: ${V} commands, ${Q} skills, ${Z} agents, ${J} MCP servers`);return{plugins:w,totalCommands:V,totalSkills:Q,totalAgents:Z,totalMcpServers:J,errors:W}}async integratePlugin($){let b={pluginName:$.manifest.name,commandsRegistered:0,skillsRegistered:0,agentsRegistered:0,hooksRegistered:!1,mcpServersRegistered:0,errors:[]};try{b.commandsRegistered=this.integrateCommands($)}catch(w){b.errors.push(`Failed to integrate commands: ${w instanceof Error?w.message:String(w)}`)}try{b.skillsRegistered=this.integrateSkills($)}catch(w){b.errors.push(`Failed to integrate skills: ${w instanceof Error?w.message:String(w)}`)}try{b.agentsRegistered=this.integrateAgents($)}catch(w){b.errors.push(`Failed to integrate agents: ${w instanceof Error?w.message:String(w)}`)}try{b.hooksRegistered=this.integrateHooks($)}catch(w){b.errors.push(`Failed to integrate hooks: ${w instanceof Error?w.message:String(w)}`)}try{b.mcpServersRegistered=await this.integrateMcp($)}catch(w){b.errors.push(`Failed to integrate MCP servers: ${w instanceof Error?w.message:String(w)}`)}return I.debug(`Integrated plugin "${$.manifest.name}": ${b.commandsRegistered} commands, ${b.skillsRegistered} skills, ${b.agentsRegistered} agents`),b}integrateCommands($){return $.commands.length}integrateSkills($){let b=_$(),w=0;for(let W of $.skills)b.registerPluginSkill(W),w++;return w}integrateAgents($){let b=0;for(let w of $.agents)W$.register({...w.config,name:w.namespacedName}),b++;return b}integrateHooks($){if(!$.hooks)return!1;let b=this.hookManager.getConfig();return this.hookManager.loadConfig({...b,...$.hooks}),!0}async integrateMcp($){if(!$.mcpServers)return 0;let b=0;for(let[w,W]of Object.entries($.mcpServers))try{await this.mcpRegistry.registerServer(w,W),b++}catch(V){I.warn(`Failed to register MCP server "${w}" from plugin "${$.manifest.name}": ${V instanceof Error?V.message:String(V)}`)}return b}}async function B8($){return new Ob($).integrateAll()}function K8($){new Ob($).clearAllPluginResources()}import{nanoid as PV}from"nanoid";var $$=E("Agent");function mw($){return"createClientTransport"in $&&"server"in $}class k0{sessionId;agent=null;abortController=null;_messages=[];options;maxTurns;permissionMode;initialized=!1;mcpRegistry;pendingMessage=null;pendingSendOptions=null;constructor($,b){this.sessionId=b||PV(),this.options=$,this.maxTurns=$.maxTurns??200,this.permissionMode=$.permissionMode??z.DEFAULT,this.mcpRegistry=new e$}get messages(){return[...this._messages]}async initialize(){if(this.initialized)return;let $=this.buildBladeConfig();if(this.options.sandbox)L0().configure(this.options.sandbox);if(this.options.enableFileCheckpointing)z$().configure({enabled:!0});await this.registerInProcessMcpServers(),this.agent=await d$.create($,{permissionMode:this.permissionMode,systemPrompt:this.options.systemPrompt,maxTurns:this.maxTurns,canUseTool:this.options.canUseTool,outputFormat:this.options.outputFormat,sandbox:this.options.sandbox}),this.initialized=!0,$$.debug(`[Session] Initialized session ${this.sessionId}`)}async registerInProcessMcpServers(){if(!this.options.mcpServers)return;let $=this.mcpRegistry;for(let[b,w]of Object.entries(this.options.mcpServers))if(mw(w))await $.registerInProcessServer(b,w),$$.debug(`[Session] Registered in-process MCP server: ${b}`)}async loadHistory(){let $=this.options.cwd||process.cwd(),b=Y$($,this.sessionId),w=new Z$(b);try{let W=await w.readAll();if(W.length===0){$$.debug(`[Session] No history found for session ${this.sessionId}`);return}let V=new Map,Q=new Map;for(let Z of W){if(Z.type==="message_created"){let J=Z.data;V.set(J.messageId,{role:J.role,content:"",toolCalls:[]})}if(Z.type==="part_created"){let J=Z.data,Y=V.get(J.messageId);if(!Y)Y={role:J.partType==="tool_result"?"tool":"assistant",content:"",toolCalls:[]},V.set(J.messageId,Y);switch(J.partType){case"text":{let X=J.payload;Y.content=X.text??"";break}case"tool_call":{let X=J.payload,O={id:X.toolCallId,type:"function",function:{name:X.toolName,arguments:typeof X.input==="string"?X.input:JSON.stringify(X.input)}};Y.toolCalls.push(O),Q.set(X.toolCallId,{messageId:J.messageId,toolCallId:X.toolCallId});break}case"tool_result":{let X=J.payload;if(Y.role="tool",Y.toolCallId=X.toolCallId,Y.name=X.toolName,X.error)Y.content=`Error: ${X.error}`;else if(X.output===null||X.output===void 0)Y.content="";else if(typeof X.output==="string")Y.content=X.output;else Y.content=JSON.stringify(X.output);break}case"summary":{let X=J.payload;Y.content=X.text??"";break}}}}this._messages=Array.from(V.values()).map((Z)=>{let J={role:Z.role,content:Z.content};if(Z.toolCalls.length>0)J.tool_calls=Z.toolCalls;if(Z.toolCallId)J.tool_call_id=Z.toolCallId;if(Z.name)J.name=Z.name;return J}),$$.debug(`[Session] Loaded ${this._messages.length} messages from history`)}catch(W){$$.warn(`[Session] Failed to load history for session ${this.sessionId}:`,W)}}buildBladeConfig(){let $=this.buildModelConfig(),b,w;if(this.options.mcpServers){let W={},V=[];for(let[Q,Z]of Object.entries(this.options.mcpServers))if(mw(Z))V.push(Q);else W[Q]=Z;b=Object.keys(W).length>0?W:void 0,w=V.length>0?V:void 0}return{models:[$],currentModelId:$.id,temperature:0.7,mcpServers:b,inProcessMcpServerNames:w,permissions:{allow:[],deny:[]}}}buildModelConfig(){let $=this.options.provider;return{id:"default",name:this.options.model,provider:this.mapProviderType($.type),model:this.options.model,apiKey:$.apiKey||"",baseUrl:$.baseUrl||this.getDefaultBaseUrl($.type),maxContextTokens:128000}}mapProviderType($){return{"openai-compatible":"openai-compatible",anthropic:"anthropic",gemini:"gemini","azure-openai":"azure-openai"}[$]||"openai-compatible"}getDefaultBaseUrl($){return{"openai-compatible":"https://api.openai.com/v1",anthropic:"https://api.anthropic.com",gemini:"https://generativelanguage.googleapis.com","azure-openai":""}[$]||""}async send($,b){if(await this.ensureInitialized(),this.pendingMessage!==null)throw Error("Cannot send a new message while a previous message is pending. Call stream() first.");this.pendingMessage=$,this.pendingSendOptions=b||null}async*stream($){if(this.pendingMessage===null)throw Error("No pending message. Call send() before stream().");let b=this.pendingMessage,w=this.pendingSendOptions;this.pendingMessage=null,this.pendingSendOptions=null;let W=[],V={inputTokens:0,outputTokens:0,totalTokens:0,maxContextTokens:0};this.abortController=new AbortController;let Q=w?.signal?this.combineSignals(w.signal,this.abortController.signal):this.abortController.signal,Z={messages:this._messages,userId:"sdk-user",sessionId:this.sessionId,workspaceRoot:this.options.cwd||process.cwd(),signal:Q,permissionMode:this.permissionMode},J=this.agent.streamChat(b,Z,{maxTurns:w?.maxTurns??this.maxTurns,signal:Q});try{let Y;while(!0){let{value:G,done:B}=await J.next();if(B){Y=G;break}switch(G.type){case"turn_start":yield{type:"turn_start",turn:G.turn,sessionId:this.sessionId};break;case"content_delta":yield{type:"content",delta:G.delta,sessionId:this.sessionId};break;case"thinking_delta":if($?.includeThinking)yield{type:"thinking",delta:G.delta,sessionId:this.sessionId};break;case"content":yield{type:"content",delta:G.content,sessionId:this.sessionId};break;case"thinking":if($?.includeThinking)yield{type:"thinking",delta:G.content,sessionId:this.sessionId};break;case"tool_start":{if(G.toolCall.type!=="function")break;let K=this.safeParseJson(G.toolCall.function.arguments);W.push({id:G.toolCall.id,name:G.toolCall.function.name,input:K,output:null,duration:0}),yield{type:"tool_use",id:G.toolCall.id,name:G.toolCall.function.name,input:K,sessionId:this.sessionId};break}case"tool_result":{if(G.toolCall.type!=="function")break;let K=W.find((C)=>C.id===G.toolCall.id);if(K)K.output=G.result.llmContent,K.isError=!G.result.success;yield{type:"tool_result",id:G.toolCall.id,name:G.toolCall.function.name,output:G.result.llmContent,isError:!G.result.success,sessionId:this.sessionId};break}case"token_usage":V={inputTokens:G.usage.inputTokens,outputTokens:G.usage.outputTokens,totalTokens:G.usage.totalTokens,maxContextTokens:G.usage.maxContextTokens};break;default:break}}if(!Y)throw Error("Stream ended without result");let X=Y.error?.type==="aborted",O=Y.metadata?.shouldExitLoop;if(!Y.success&&!X&&!O){yield{type:"error",message:Y.error?.message||"Unknown error",sessionId:this.sessionId};return}yield{type:"usage",usage:V,sessionId:this.sessionId},this._messages=Z.messages,yield{type:"result",subtype:"success",content:Y.finalMessage||"",sessionId:this.sessionId}}catch(Y){yield{type:"error",message:Y instanceof Error?Y.message:String(Y),sessionId:this.sessionId}}finally{this.abortController=null}}close(){this.abort(),this.agent=null,this.initialized=!1,this.pendingMessage=null,this.pendingSendOptions=null,$$.debug(`[Session] Closed session ${this.sessionId}`)}abort(){if(this.abortController)this.abortController.abort(),this.abortController=null}setPermissionMode($){this.permissionMode=$}async setModel($){$$.warn("[Session] setModel is not yet implemented")}setMaxTurns($){this.maxTurns=$}async supportedCommands(){let $=N$.getInstance();if(!$.isInitialized())await $.initialize(this.options.cwd||process.cwd());return $.getAllCommands().map((b)=>({name:b.name,description:b.config.description||"",usage:b.config.argumentHint}))}async supportedModels(){return[{id:"default",name:this.options.model,provider:this.options.provider.type}]}async mcpServerStatus(){let b=this.mcpRegistry.getAllServers(),w=[];for(let[W,V]of b){let Q={connected:"connected",disconnected:"disconnected",connecting:"connecting",error:"error"};w.push({name:W,status:Q[V.status],toolCount:V.tools.length,tools:V.tools.map((Z)=>Z.name),connectedAt:V.connectedAt,error:V.lastError?.message})}return w}async mcpConnect($){await this.ensureInitialized();let b=this.mcpRegistry;if(!b.getServerStatus($)){let W=this.options.mcpServers?.[$];if(!W)throw Error(`MCP server "${$}" not found in configuration`);if(mw(W))await b.registerInProcessServer($,W);else await b.registerServer($,W)}else await b.connectServer($);$$.debug(`[Session] Connected to MCP server: ${$}`)}async mcpDisconnect($){await this.mcpRegistry.disconnectServer($),$$.debug(`[Session] Disconnected from MCP server: ${$}`)}async mcpReconnect($){await this.mcpRegistry.reconnectServer($),$$.debug(`[Session] Reconnected to MCP server: ${$}`)}async mcpListTools(){let b=this.mcpRegistry.getAllServers(),w=[];for(let[W,V]of b)if(V.status==="connected")for(let Q of V.tools)w.push({name:Q.name,description:Q.description,serverName:W});return w}async[Symbol.asyncDispose](){this.close()}async ensureInitialized(){if(!this.initialized)await this.initialize()}combineSignals($,b){let w=new AbortController,W=()=>w.abort();if($.aborted||b.aborted)w.abort();else $.addEventListener("abort",W),b.addEventListener("abort",W);return w.signal}safeParseJson($){try{return JSON.parse($)}catch{return $}}async rewindFiles($){if(!this.options.enableFileCheckpointing)return{success:!1,restoredFiles:[],deletedFiles:[],errors:[{filePath:"",error:"File checkpointing is not enabled"}]};return z$().rewindFiles($)}getCheckpointStatistics(){if(!this.options.enableFileCheckpointing)return null;return z$().getStatistics()}async fork($){await this.ensureInitialized();let b=$?.messageId,w=[...this._messages];if(b){let V=this.findMessageIndexByUuid(b);if(V===-1)throw Error(`Message with ID "${b}" not found in session history`);w=this._messages.slice(0,V+1)}let W=new k0(this.options);if(await W.initialize(),W._messages=w.map((V)=>({...V})),$?.copyCheckpoints&&this.options.enableFileCheckpointing)$$.debug("[Session] Checkpoint copying is not yet implemented for forked sessions");return $$.debug(`[Session] Forked session ${this.sessionId} -> ${W.sessionId} with ${w.length} messages`),W}findMessageIndexByUuid($){for(let b=0;b<this._messages.length;b++)if(this._messages[b].id===$)return b;return this._messages.length>0?this._messages.length-1:-1}}async function q8($){let b=new k0($);return await b.initialize(),$$.debug(`[Session] Created new session: ${b.sessionId}`),b}async function A8($){let{sessionId:b,...w}=$,W=new k0(w,b);return await W.initialize(),await W.loadHistory(),$$.debug(`[Session] Resumed session: ${b} with ${W.messages.length} messages`),W}async function F8($){let{sessionId:b,messageId:w,copyCheckpoints:W,...V}=$,Q=new k0(V,b);await Q.initialize(),await Q.loadHistory();let Z=await Q.fork({messageId:w,copyCheckpoints:W});return Q.close(),$$.debug(`[Session] Forked session ${b} -> ${Z.sessionId} with ${Z.messages.length} messages`),Z}async function C8($,b){let w=Date.now(),W=new k0(b);await W.initialize();let V=[],Q={inputTokens:0,outputTokens:0,totalTokens:0,maxContextTokens:0},Z=0,J="",Y=null;try{await W.send($);for await(let X of W.stream())if(X.type==="turn_start")Z=X.turn;else if(X.type==="tool_use")V.push({id:X.id,name:X.name,input:X.input,output:null,duration:0});else if(X.type==="tool_result"){let O=V.find((G)=>G.id===X.id);if(O)O.output=X.output,O.isError=X.isError}else if(X.type==="usage")Q=X.usage;else if(X.type==="result"&&X.subtype==="success")J=X.content||"";else if(X.type==="error")Y=X.message;else if(X.type==="result"&&X.subtype==="error")Y=X.error||"Unknown error";if(Y)throw Error(Y);return{result:J,toolCalls:V,usage:Q,duration:Date.now()-w,turnsCount:Z}}finally{W.close()}}export{c8 as toolFromDefinition,W8 as tool,cV as shutdownLogger,mV as setLoggerSessionId,A8 as resumeSession,C8 as prompt,o$ as parsePluginManifest,jb as notebookEditTool,I as logger,ob as isValidPluginDir,zw as isThinkingModel,F0 as isReadOnlyKind,nV as isGlobMetadata,sV as isEditMetadata,B8 as integrateAllPlugins,Hb as injectSkillsMetadata,g2 as getThinkingConfig,L0 as getSandboxService,D0 as getSandboxExecutor,$1 as getPluginRegistry,O8 as getPluginInstaller,v0 as getNamespacedName,eb as getMcpNamespacedName,z$ as getCheckpointService,Kw as getBuiltinTools,F8 as forkSession,Rb as discoverSkills,u2 as detectThinkingSupport,i8 as defineTool,L as createTool,q8 as createSession,V8 as createSdkMcpServer,hb as createReadMcpResourceTool,E as createLogger,Pb as createListMcpResourcesTool,lb as createChatServiceAsync,K8 as clearAllPluginResources,kb as askUserQuestionTool,yw as agentLoop,Vb as ToolRegistry,wW as ToolKind,Z1 as ToolExecution,YW as ToolErrorType,c4 as TASK_STATUSES,i4 as TASK_COMPLEXITIES,bW as StreamMessageType,p as SpecManager,p$ as SandboxService,x$ as SandboxExecutor,Z0 as STEERING_FILES,m4 as SPEC_PHASES,l4 as SPEC_FILE_NAMES,Q0 as SPEC_DIRS,c$ as PluginRegistry,T0 as PluginLoader,Ob as PluginIntegrator,tb as PluginInstaller,A1 as PermissionMode,QW as PermissionDecision,WW as PermissionBehavior,t0 as PHASE_TRANSITIONS,n4 as PHASE_PRIMARY_FILE,zJ as PHASE_ORDER,F$ as PHASE_DISPLAY_NAMES,V4 as MessageRole,e$ as McpRegistry,q1 as McpErrorType,t$ as McpConnectionStatus,C0 as McpClient,P$ as Logger,Q1 as LogLevel,x as LogCategory,ZW as HookType,c as HookManager,JW as HookExitCode,g0 as HookEvent,K1 as HealthStatus,u0 as HealthMonitor,db as ExecutionPipeline,VW as DecisionBehavior,sb as ContextManager,a as CompactionService,N$ as CommandRegistry,Yb as CommandParser,Xb as CommandLoader,Jb as CommandExecutor,h$ as CheckpointService,d$ as Agent};