blade-code 0.10.1 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blade.js +2 -2
- package/dist/{chunk-859m18ra.js → chunk-0h9m2fqd.js} +1 -1
- package/dist/chunk-1wyfb6s7.js +1 -0
- package/dist/{chunk-j457sh1b.js → chunk-2km4w0ky.js} +1 -1
- package/dist/{chunk-p6yed31x.js → chunk-3vyjshqp.js} +1 -1
- package/dist/{chunk-km7m66vw.js → chunk-5tfzehcg.js} +1 -1
- package/dist/{chunk-hefv4415.js → chunk-6sc78810.js} +1 -1
- package/dist/{chunk-a8y9xbxw.js → chunk-8mepk4tc.js} +1 -1
- package/dist/{chunk-3nx2579c.js → chunk-bpzv054r.js} +1 -1
- package/dist/{chunk-f19yx9an.js → chunk-bqk3wqts.js} +1 -1
- package/dist/{chunk-793k86j6.js → chunk-cjdnfyy0.js} +3 -3
- package/dist/{chunk-49sytjma.js → chunk-ct32ngah.js} +1 -1
- package/dist/{chunk-rppak8ep.js → chunk-d8zj7c0t.js} +1 -1
- package/dist/{chunk-pms05z02.js → chunk-e2ccyhgz.js} +1 -1
- package/dist/{chunk-t7ej11xd.js → chunk-gr5mzxdf.js} +1 -1
- package/dist/{chunk-h7kj4gvj.js → chunk-k89phc5j.js} +1 -1
- package/dist/{chunk-29r7z43j.js → chunk-k9a1vb8a.js} +1 -1
- package/dist/{chunk-mz1jrcgc.js → chunk-m5tjrr5c.js} +1 -1
- package/dist/{chunk-k6qwdjyy.js → chunk-m9zpxzg2.js} +1 -1
- package/dist/{chunk-gv8gfnz8.js → chunk-nqq4sbmv.js} +1 -1
- package/dist/{chunk-mrpvdvn4.js → chunk-p7ppnewt.js} +1 -1
- package/dist/{chunk-dnhb7k9g.js → chunk-qhf0knnx.js} +1 -1
- package/dist/{chunk-5pvxw7sd.js → chunk-rkzds6k8.js} +2 -2
- package/dist/{chunk-tkd04sjm.js → chunk-tckfyfsx.js} +1 -1
- package/dist/{chunk-j51fwecz.js → chunk-tm2ckreq.js} +1 -1
- package/dist/{chunk-51wa5fct.js → chunk-ws3gc024.js} +1 -1
- package/dist/{chunk-w1wp1t52.js → chunk-xhpezpjq.js} +1 -1
- package/dist/{chunk-11qty4fd.js → chunk-y0hwzmdn.js} +1 -1
- package/dist/{chunk-jzrqjzjm.js → chunk-y5vq7gek.js} +1 -1
- package/dist/{chunk-g2972yzq.js → chunk-ydqeg4p8.js} +1 -1
- package/dist/{chunk-tkr4d9ej.js → chunk-yknrffcs.js} +1 -1
- package/dist/{chunk-qk0akpsg.js → chunk-ymmtbq2b.js} +1 -1
- package/dist/{chunk-m3g8hz67.js → chunk-z2yzyr9h.js} +1 -1
- package/package.json +1 -1
- package/dist/chunk-g0jb7v73.js +0 -1
package/dist/blade.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Hb as W}from"./chunk-
|
|
2
|
+
import{Hb as W}from"./chunk-5tfzehcg.js";import{Kb as F,Lb as M}from"./chunk-kq5my0yy.js";import"./chunk-m9zpxzg2.js";import"./chunk-gafbzeyk.js";import"./chunk-0h81hxkw.js";import"./chunk-6sc78810.js";import"./chunk-beqaxytd.js";import{cd as T}from"./chunk-jxv6r0c7.js";import"./chunk-bpzv054r.js";import"./chunk-4vaywb2r.js";import"./chunk-qev36qrb.js";import{ge as N,he as B}from"./chunk-vjpd3nee.js";import"./chunk-a7nbn5kf.js";import"./chunk-2beq0syt.js";import"./chunk-k89phc5j.js";import"./chunk-6hj2dk75.js";import"./chunk-6n5xdf2r.js";import"./chunk-8nm1hqr1.js";import{Le as K}from"./chunk-mjp61rqd.js";import C from"node:path";var E=process.argv.slice(2),I=p(E),v=I!==null;if(I!==null)T.setGlobalDebug(I);function p(Q){for(let Y=0;Y<Q.length;Y+=1){let U=Q[Y];if(U==="--debug"||U==="-d"){let X=Q[Y+1];return X&&!X.startsWith("-")?X:!0}if(U.startsWith("--debug="))return U.slice(8)||!0}return null}function u(Q){return Q.length===1&&(Q[0]==="--version"||Q[0]==="-V")}function q(Q,...Y){return Q.some((U)=>Y.some((X)=>U===X||U.startsWith(`${X}=`)))}function c(Q,...Y){let U=[];for(let X=0;X<Q.length;X+=1){let G=Q[X],z=Y.find(($)=>G.startsWith(`${$}=`));if(z){let $=G.slice(z.length+1);if($)U.push($);continue}if(Y.includes(G)){let $=Q[X+1];if($&&!$.startsWith("-"))U.push($),X+=1}}return U}async function m(){if(u(E)){let{getVersion:J}=await import("./chunk-bqk3wqts.js");console.log(J());return}let Q=process.cwd(),Y=F(Q);M(Y),N(B());let U=c(E,"--plugin-dir","--pluginDir");if(U.length>0){let{configureInvocationPluginDirs:J}=await import("./chunk-yknrffcs.js");J(U.map((Z)=>C.resolve(Q,Z)))}if(q(E,"--trust-workspace","--trustWorkspace")){let{WorkspaceTrustService:J}=await import("./chunk-6g21dh3n.js");await J.getInstance().trust(B())}if(process.getuid&&process.getuid()===0){let J=!!process.env.SUDO_USER,Z=!!process.env.BLADE_ALLOW_ROOT;if(J&&!Z)console.error(""),console.error("Error: 请不要使用 sudo 运行 blade"),console.error(""),console.error("原因:"),console.error(" 使用 sudo 会创建属于 root 的配置文件,"),console.error(" 导致普通用户无法访问。"),console.error(""),console.error("正确用法:"),console.error(" blade # 直接运行,不要加 sudo"),console.error(""),console.error("如果遇到权限错误,请运行:"),console.error(" sudo chown -R $USER:$USER ~/.blade/"),console.error(""),console.error("如果你确实需要以 root 运行(容器/CI),设置环境变量:"),console.error(" BLADE_ALLOW_ROOT=1 blade"),console.error(""),process.exit(1)}if(q(E,"--headless")){let{handleHeadlessMode:J}=await import("./chunk-d8zj7c0t.js");if(await J())return}if(W(),q(E,"--print","-p")){let{handlePrintMode:J}=await import("./chunk-gr5mzxdf.js");if(await J())return}if(E.includes("--acp")){let{runAcpIntegration:J}=await import("./chunk-ct32ngah.js");await J();return}let[{default:X},{hideBin:G},{cliConfig:z,globalOptions:$},{loadConfiguration:_,validateOutput:D,validatePermissions:R},{doctorCommands:S},{installCommands:k},{mcpCommands:O},{projectsCommands:y},{serveCommand:b},{updateCommands:V},{webCommand:P}]=await Promise.all([import("yargs"),import("yargs/helpers"),import("./chunk-1wyfb6s7.js"),import("./chunk-3vyjshqp.js"),import("./chunk-rkzds6k8.js"),import("./chunk-d3236505.js"),import("./chunk-y0hwzmdn.js"),import("./chunk-vvy506b3.js"),import("./chunk-ydqeg4p8.js"),import("./chunk-zkbf8n6y.js"),import("./chunk-xhpezpjq.js")]),x=X(G(process.argv)).scriptName(z.scriptName).usage(z.usage).version(z.version).locale(z.locale).showHelpOnFail(z.showHelpOnFail).demandCommand(0,"").recommendCommands().strict(z.strict).parserConfiguration({"populate--":!0}).options($).middleware([_,R,D]).command(O).command(y).command(S).command(V).command(k).command(P).command(b).completion("completion",!1).help("help","Show help").alias("help","h").alias("version","V").fail((J,Z,L)=>{if(Z){if(console.error("An error occurred:"),console.error(Z.message),v&&Z.stack)console.error(`
|
|
3
3
|
Stack trace:`),console.error(Z.stack);else console.error(`
|
|
4
4
|
Run with --debug to show the stack trace.`);process.exit(1)}if(J)console.error("Error: Invalid arguments:"),console.error(J),console.error(`
|
|
5
|
-
Hint: Did you mean:`),L.showHelp(),process.exit(1)}).command("$0",!1,()=>{},async(J)=>{let Z=J._.slice(1),L=Z.length>0?Z.join(" "):void 0,h=import("./chunk-m78ceafk.js").then(({checkVersionOnStartup:j})=>j()),[{render:A},{createElement:w},{AppWrapper:f}]=await Promise.all([import("ink"),import("react"),import("./chunk-
|
|
5
|
+
Hint: Did you mean:`),L.showHelp(),process.exit(1)}).command("$0",!1,()=>{},async(J)=>{let Z=J._.slice(1),L=Z.length>0?Z.join(" "):void 0,h=import("./chunk-m78ceafk.js").then(({checkVersionOnStartup:j})=>j()),[{render:A},{createElement:w},{AppWrapper:f}]=await Promise.all([import("ink"),import("react"),import("./chunk-0h9m2fqd.js")]),H={...J,initialMessage:L,debug:J.debug,print:Boolean(J.print),versionCheckPromise:h};delete H._,delete H.$0,delete H.message,A(w(f,H),{patchConsole:!0,exitOnCtrlC:!1,alternateBuffer:!1})});try{await x.parse()}catch(J){console.error("Error: Parse error:",J),process.exit(1)}}if(K.main==K.module)m().catch(console.error);export{m as main};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{e as l9,f as d9}from"./chunk-wvj9h7mb.js";import{i as DJ,j as VJ,k as jJ}from"./chunk-th7sxjtk.js";import{$ as $6,E as O$,F as w4,G as b4,J as t$,K as UJ,L as GJ,O as KJ,P as qJ,U as O6,V as z6,W as oJ,X as v4,Z as k4,r as e4,u as o2,v as u2,w as l4,x as aJ}from"./chunk-
|
|
1
|
+
import{e as l9,f as d9}from"./chunk-wvj9h7mb.js";import{i as DJ,j as VJ,k as jJ}from"./chunk-th7sxjtk.js";import{$ as $6,E as O$,F as w4,G as b4,J as t$,K as UJ,L as GJ,O as KJ,P as qJ,U as O6,V as z6,W as oJ,X as v4,Z as k4,r as e4,u as o2,v as u2,w as l4,x as aJ}from"./chunk-cjdnfyy0.js";import{da as B9,ea as w9,fa as b9,ia as rJ}from"./chunk-ws3gc024.js";import{qa as j4}from"./chunk-y5vq7gek.js";import{La as $8}from"./chunk-88vy9hh0.js";import{$a as y4,Za as R4,_a as m2,db as n$,gb as E0}from"./chunk-8mepk4tc.js";import"./chunk-44wkjs2j.js";import{Eb as SJ}from"./chunk-nah0cbnp.js";import{Fb as Q8,Gb as g8,Ib as I1}from"./chunk-5tfzehcg.js";import"./chunk-kq5my0yy.js";import{$b as L2,Mb as R$,Nb as d0,Ob as n1,Pb as bQ,Qb as T$,Rb as f8,Sb as p6,Tb as mQ,Ub as E9,Vb as c6,Wb as I$,Xb as Y1,Yb as lJ,Zb as r0,_b as kJ,ac as s$,dc as C4,kc as u0}from"./chunk-m9zpxzg2.js";import"./chunk-gafbzeyk.js";import"./chunk-0h81hxkw.js";import"./chunk-af49jmns.js";import{uc as pQ}from"./chunk-px5ck9pf.js";import"./chunk-fjw32ex5.js";import"./chunk-k9a1vb8a.js";import{Ac as G6,Dc as bJ,Jc as XJ,Pc as dJ}from"./chunk-tm2ckreq.js";import"./chunk-d9ddpapp.js";import"./chunk-sndbq5xt.js";import{Yc as RQ,_c as F1}from"./chunk-6sc78810.js";import"./chunk-beqaxytd.js";import{ad as cJ,dd as o1}from"./chunk-jxv6r0c7.js";import{Hd as xJ,Sd as uJ}from"./chunk-bpzv054r.js";import"./chunk-4vaywb2r.js";import{be as v$,ce as D8,de as yQ}from"./chunk-qev36qrb.js";import{he as A0}from"./chunk-vjpd3nee.js";import{ie as c9,je as x9,me as f1}from"./chunk-a7nbn5kf.js";import"./chunk-2beq0syt.js";import{ye as v9}from"./chunk-k89phc5j.js";import{ze as aQ}from"./chunk-6hj2dk75.js";import"./chunk-6n5xdf2r.js";import"./chunk-8nm1hqr1.js";import{Le as PQ}from"./chunk-mjp61rqd.js";import{useMemoizedFn as C2}from"ahooks";import{useEffect as yX,useState as T2}from"react";import{useMemoizedFn as t0}from"ahooks";import{Box as U$}from"ink";import{useEffect as G$,useMemo as LX,useRef as y2}from"react";import{useShallow as nJ}from"zustand/react/shallow";import{useStore as iJ}from"zustand";function $0($){return iJ(I$,$)}var tJ=[],b8=()=>$0(($)=>$.session.sessionId),M1=()=>$0(($)=>$.session.workspaceRoot),oQ=()=>$0(($)=>$.session.messages),iQ=()=>$0(($)=>$.session.clearCount),nQ=()=>$0(($)=>$.session.isCompacting),tQ=()=>$0(($)=>$.session.tokenUsage.estimatedCostUsd),d1=()=>$0(($)=>$.session.actions),sQ=()=>$0(($)=>{let{inputTokens:Q,maxContextTokens:Y}=$.session.tokenUsage;if(Y<=0)return 100;let J=Math.max(0,100-Q/Y*100);return Math.round(J)}),eQ=()=>$0(($)=>$.app.initializationStatus),$4=()=>$0(($)=>$.app.initializationError),A8=()=>$0(($)=>$.app.activeModal),Q4=()=>$0(($)=>$.app.tasks),J4=()=>$0(($)=>$.app.modelEditorTarget),Y4=()=>$0(($)=>$.app.sessionSelectorData),Z4=()=>$0(($)=>$.app.awaitingSecondCtrlC),r1=()=>$0(($)=>$.app.actions),P8=()=>$0(($)=>$.app.initializationStatus==="ready"),X4=()=>$0(($)=>$.app.tasks.length>0),C$=()=>$0(($)=>$.config.config?.permissionMode||"default"),U4=()=>$0(($)=>$.config.config?.models??tJ),R8=()=>$0(($)=>{let Q=$.config.config;if(!Q)return;let Y=Q.currentModelId;return Q.models.find((Z)=>Z.id===Y)??Q.models[0]}),y8=()=>$0(($)=>$.config.config?.currentModelId),b0=()=>$0(($)=>{return d0.getTheme()}),G4=()=>$0(($)=>$.config.config?.theme??"default"),s0=()=>$0(($)=>$.focus.currentFocus),K4=()=>$0(($)=>$.focus.actions),a1=()=>$0(($)=>$.command.isProcessing),q4=()=>$0(($)=>$.command.actions),M8=()=>$0(($)=>$.command.pendingCommands),O4=()=>$0(($)=>$.command.recoveredSteeringCount),I8=()=>$0(($)=>$.app.thinkingModeEnabled),C8=()=>$0(($)=>$.app.reasoningEffort),T8=()=>$0(($)=>$.app.serviceTier),v8=()=>$0(($)=>$.app.responseVerbosity),k8=()=>$0(($)=>$.app.communicationStyle),z4=()=>$0(($)=>$.session.currentThinkingContent),_4=()=>$0(($)=>$.session.thinkingExpanded),N4=()=>$0(($)=>$.session.currentStreamingMessageId),F4=()=>$0(nJ(($)=>({lines:$.session.currentStreamingLines,tail:$.session.currentStreamingTail,lineCount:$.session.currentStreamingLineCount,version:$.session.currentStreamingVersion}))),H4=()=>$0(($)=>$.session.finalizingStreamingMessageId),W4=()=>$0(($)=>$.session.historyExpanded),L4=()=>$0(($)=>$.session.expandedMessageCount);import{useMemoizedFn as S$}from"ahooks";import{useEffect as h2,useRef as V4}from"react";function sJ($){if(!($ instanceof Error))return"未知错误";let J=$.lastError??$;if(J.responseBody)try{let U=JSON.parse(J.responseBody)?.error?.message;if(U){let G=J.statusCode?` (HTTP ${J.statusCode})`:"";return`${U}${G}`}}catch{}let Z=$.message.match(/Last error:\s*(.+)$/);if(Z)return Z[1];return $.message}function eJ($){if(!($ instanceof Error))return!1;return $.name==="AbortError"||$.message.includes("aborted")}function $Y($){if(!($ instanceof Error))return!1;let Q=$.message;return Q.includes("can only concatenate str")||Q.includes("image_url")||Q.includes("multimodal")||Q.includes("vision")||Q.includes("does not support images")}function S8($){let Q=eJ($),Y=$Y($),J;if(Y)J="当前模型不支持图片理解功能。请切换到支持视觉能力的模型(如 Claude 4.5、GPT-5.2、Gemini 3 Pro、Qwen3-VL-Plus 等)后重试。";else J=sJ($);return{displayMessage:J,isAbort:Q,isVisionNotSupported:Y}}import{appendFileSync as QY,mkdirSync as JY,writeFileSync as YY}from"node:fs";import ZY from"node:os";import f2 from"node:path";var B4=null;function XY(){let $=process.env.BLADE_STORAGE_ROOT||f2.join(ZY.homedir(),".blade");return f2.join($,"logs","stream-debug.log")}function UY($){if(B4===$)return;let Q=f2.dirname($);JY(Q,{recursive:!0,mode:493}),YY($,`=== Stream Debug Log Started: ${new Date().toISOString()} ===
|
|
2
2
|
`),B4=$}function D2($,Q,Y){try{let J=XY();UY(J);let Z=new Date().toISOString(),X=Y?` | ${JSON.stringify(Y)}`:"",U=`[${Z}] [${$}] ${Q}${X}
|
|
3
3
|
`;QY(J,U)}catch{}}var i$=o1("UI");function A4($,Q){let Y=!1;return(J)=>{switch(J.kind){case"content_delta":if(Y||$.signal.aborted)break;Q.contentDeltaCount++,Q.contentDeltaTotalLen+=J.delta.length,D2("loopEventHandler","onContentDelta",{callCount:Q.contentDeltaCount,deltaLen:J.delta.length,totalLen:Q.contentDeltaTotalLen}),$.streamingBuffer.batchAppendContent(J.delta);break;case"thinking_delta":if(Y||$.signal.aborted)break;if($.thinkingModeEnabled)$.streamingBuffer.batchAppendThinking(J.delta);break;case"stream_end":{if(i$.debug("[loopEventHandler] stream_end",{contentDeltaCount:Q.contentDeltaCount,contentDeltaTotalLen:Q.contentDeltaTotalLen,streamFinalized:Y,signalAborted:$.signal.aborted}),D2("loopEventHandler","onStreamEnd",{contentDeltaCallCount:Q.contentDeltaCount,contentDeltaTotalLen:Q.contentDeltaTotalLen,streamFinalized:Y,signalAborted:$.signal.aborted}),Y||$.signal.aborted){Y=!0;break}let{extraContent:Z,extraThinking:X}=$.streamingBuffer.drainPendingBuffers(),U=$.getStreamingMessageId();if(U){if(Z)T$(U,Z);f8(U)}$.sessionActions.finalizeStreamingMessage(Z,X),Y=!0;break}case"model_fallback":Y=!0,$.streamingBuffer.resetStreamingBuffers(),$.sessionActions.discardStreamingMessage(),$.sessionActions.setCurrentThinkingContent(null);break;case"tool_start":{let Z=J.toolCall;if(!("function"in Z))break;if(i$.debug("[loopEventHandler] tool_start",{toolName:Z.function.name,toolKind:J.toolKind}),["TaskCreate","TaskUpdate","TaskList"].includes(Z.function.name))break;try{let X=JSON.parse(Z.function.arguments),U=w4(Z.function.name,X);$.sessionActions.addToolMessage(U,{toolCallId:Z.id,toolName:Z.function.name,phase:"start",summary:U,params:X})}catch(X){i$.error("[loopEventHandler] onToolStart error:",X)}break}case"tool_progress":{let Z=J.toolCall;if(!("function"in Z))break;let X=J.update.total!==void 0?` ${Math.max(0,Math.min(100,Math.round((J.update.progress??0)/J.update.total*100)))}%`:"",U=`${Z.function.name}${X}: ${J.update.message}`;$.sessionActions.addToolMessage(U,{toolCallId:Z.id,toolName:Z.function.name,phase:"progress",summary:U});break}case"tool_result":{let Z=J.toolCall;if(!("function"in Z))break;i$.debug("[loopEventHandler] tool_result",{toolName:Z.function.name,success:J.result.success});let X=b4(Z.function.name,J.result);$.sessionActions.addToolMessage(X.summary,{toolCallId:Z.id,toolName:Z.function.name,phase:"complete",summary:X.summary,detail:X.detail});break}case"token_usage":$.sessionActions.updateTokenUsage(J.usage);break;case"compaction":if($.sessionActions.setCompacting(J.phase==="start"),J.phase==="end")$.sessionActions.resetContextUsage();break;case"turn_start":i$.debug("[loopEventHandler] turn_start",{turn:J.turn,maxTurns:J.maxTurns}),$.sessionActions.updateTokenUsage({turnCount:J.turn}),Y=!1;break;case"task_update":$.appActions.setTasks(J.tasks);break;case"mcp_catalog_changed":{let Z=`MCP catalog r${J.revision}: +${J.added.length} -${J.removed.length} ~${J.updated.length}`;$.sessionActions.addToolMessage(Z,{toolName:"MCP Catalog",phase:"complete",summary:Z,detail:[J.added.length>0?`Added: ${J.added.join(", ")}`:"",J.removed.length>0?`Removed: ${J.removed.join(", ")}`:"",J.updated.length>0?`Updated: ${J.updated.join(", ")}`:""].filter(Boolean).join(`
|
|
4
4
|
`)});break}case"mcp_content_changed":{let Z=`MCP ${J.contentKind} r${J.revision}: +${J.added.length} -${J.removed.length} ~${J.updated.length}`;$.sessionActions.addToolMessage(Z,{toolName:"MCP Content",phase:"complete",summary:Z,detail:[J.added.length>0?`Added: ${J.added.join(", ")}`:"",J.removed.length>0?`Removed: ${J.removed.join(", ")}`:"",J.updated.length>0?`Updated: ${J.updated.join(", ")}`:""].filter(Boolean).join(`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Ab as b,zb as a}from"./chunk-2km4w0ky.js";import"./chunk-k89phc5j.js";import"./chunk-mjp61rqd.js";export{a as globalOptions,b as cliConfig};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ue as d,we as h}from"./chunk-
|
|
1
|
+
import{ue as d,we as h}from"./chunk-k89phc5j.js";var q={debug:{alias:"d",type:"string",describe:'Enable debug mode with optional category filtering (e.g., "agent,ui" or "!chat,!loop")',group:"Debug Options:"},model:{type:"string",describe:"Override the current run model using a model config ID (TUI / print / headless)",group:"AI Options:"},print:{alias:"p",type:"boolean",describe:"Print response and exit (useful for pipes)",group:"Output Options:"},headless:{type:"boolean",describe:"Run full agent loop without Ink UI and print all events to the terminal",group:"Output Options:"},"output-format":{alias:["outputFormat"],type:"string",choices:["text","json","stream-json","jsonl"],default:"text",describe:"Output format: --print supports text|json|stream-json; --headless supports text|jsonl",group:"Output Options:"},"include-partial-messages":{alias:["includePartialMessages"],type:"boolean",describe:"Include partial message chunks as they arrive",group:"Output Options:"},"input-format":{alias:["inputFormat"],type:"string",choices:["text","stream-json"],default:"text",describe:"Input format",group:"Input Options:"},"replay-user-messages":{alias:["replayUserMessages"],type:"boolean",describe:"Re-emit user messages from stdin",group:"Input Options:"},"allowed-tools":{alias:["allowedTools"],type:"array",string:!0,describe:"Comma or space-separated list of tool names to allow",group:"Security Options:"},"disallowed-tools":{alias:["disallowedTools"],type:"array",string:!0,describe:"Comma or space-separated list of tool names to deny",group:"Security Options:"},"mcp-config":{alias:["mcpConfig"],type:"array",string:!0,describe:"Load MCP servers from JSON files or strings",group:"MCP Options:"},"system-prompt":{alias:["systemPrompt"],type:"string",describe:"System prompt to use for the session (replaces default)",group:"AI Options:"},"append-system-prompt":{alias:["appendSystemPrompt"],type:"string",describe:"Append a system prompt to the default system prompt",group:"AI Options:"},"max-turns":{alias:["maxTurns"],type:"number",describe:"Maximum conversation turns (-1: unlimited, 0: disable chat, N>0: limit to N turns)",group:"AI Options:",default:void 0},"max-concurrent-tasks":{alias:["maxConcurrentTasks"],type:"number",describe:"Maximum top-level tasks running concurrently in this process",group:"AI Options:",default:void 0},"max-queued-tasks":{alias:["maxQueuedTasks"],type:"number",describe:"Maximum top-level tasks waiting for an admission slot",group:"AI Options:",default:void 0},"permission-mode":{alias:["permissionMode"],type:"string",choices:["default","autoEdit","yolo","plan"],describe:"Permission mode (default: ask for non-read tools, autoEdit: auto-approve edits, yolo: auto-approve all, plan: reserved)",group:"Security Options:"},yolo:{type:"boolean",describe:"Auto-approve all tools (shortcut for --permission-mode=yolo)",group:"Security Options:"},"trust-workspace":{alias:["trustWorkspace"],type:"boolean",describe:"Trust the current workspace before loading project models, MCP, LSP, permissions, or plugins",group:"Security Options:"},continue:{alias:"c",type:"boolean",describe:"Continue the most recent conversation",group:"Session Options:"},resume:{alias:"r",describe:"Resume a conversation - provide a session ID or interactively select a conversation to resume",group:"Session Options:",coerce:(b)=>{if(b===void 0||b===!0||b==="")return"true";return String(b)}},"fork-session":{alias:["forkSession"],type:"boolean",describe:"Create a new session ID when resuming",group:"Session Options:"},settings:{type:"string",describe:"Path to a settings JSON file or JSON string",group:"Configuration:"},"add-dir":{alias:["addDir"],type:"array",string:!0,describe:"Additional directories to allow tool access to",group:"Security Options:"},ide:{type:"boolean",describe:"Automatically connect to IDE on startup",group:"Integration:"},acp:{type:"boolean",describe:"Run in ACP (Agent Client Protocol) mode for IDE integration",group:"Integration:"},"strict-mcp-config":{alias:["strictMcpConfig"],type:"boolean",describe:"Only use MCP servers from --mcp-config",group:"MCP Options:"},"session-id":{alias:["sessionId"],type:"string",describe:"Use a specific session ID for the conversation",group:"Session Options:"},agents:{type:"string",describe:"JSON object defining custom agents",group:"AI Options:"},"setting-sources":{alias:["settingSources"],type:"string",describe:"Comma-separated list of setting sources to load",group:"Configuration:"},"plugin-dir":{alias:["pluginDir"],type:"array",string:!0,describe:"Load plugins from specified directories",group:"Plugin Options:"}},w={scriptName:"blade",usage:"$0 [command] [options]",description:h(),version:d(),locale:"en",showHelpOnFail:!0,demandCommand:!1,recommendCommands:!0,strict:!1};
|
|
2
2
|
export{q as zb,w as Ab};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Bb as a,Cb as b,Db as c}from"./chunk-
|
|
1
|
+
import{Bb as a,Cb as b,Db as c}from"./chunk-m5tjrr5c.js";import"./chunk-nah0cbnp.js";import"./chunk-m9zpxzg2.js";import"./chunk-gafbzeyk.js";import"./chunk-0h81hxkw.js";import"./chunk-sndbq5xt.js";import"./chunk-jxv6r0c7.js";import"./chunk-bpzv054r.js";import"./chunk-4vaywb2r.js";import"./chunk-qev36qrb.js";import"./chunk-vjpd3nee.js";import"./chunk-a7nbn5kf.js";import"./chunk-2beq0syt.js";import"./chunk-k89phc5j.js";import"./chunk-6hj2dk75.js";import"./chunk-6n5xdf2r.js";import"./chunk-8nm1hqr1.js";import"./chunk-mjp61rqd.js";export{a as validatePermissions,c as validateOutput,b as loadConfiguration};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{Xb as Q}from"./chunk-
|
|
1
|
+
import{Xb as Q}from"./chunk-m9zpxzg2.js";import{_c as U}from"./chunk-6sc78810.js";import{bd as K,dd as N}from"./chunk-jxv6r0c7.js";import{he as O}from"./chunk-vjpd3nee.js";function Y(){if(process.stdin.isTTY&&typeof process.stdin.setRawMode==="function")try{process.stdin.setRawMode(!1)}catch{}process.stdout.write("\x1B[<u"),process.stdout.write("\x1B[>4;0m"),process.stdout.write("\x1B[?2004l"),process.stdout.write("\x1B[?1004l"),process.stdout.write("\x1B[?1l\x1B>"),process.stdout.write("\x1B[?25h"),process.stdout.write("\x1B[0m")}var A=N("Service");function Z(b){switch(b){case"SIGINT":return"ctrl_c";case"esc":return"esc";case"uncaughtException":case"unhandledRejection":return"error";case"SIGTERM":case"normal":default:return"user_exit"}}class D{static instance=null;cleanupHandlers=[];isShuttingDown=!1;initialized=!1;lastSigintTime=0;SIGINT_DOUBLE_CLICK_WINDOW=3000;constructor(){}static getInstance(){if(!D.instance)D.instance=new D;return D.instance}initialize(){if(this.initialized){A.debug("[GracefulShutdown] 已初始化,跳过重复初始化");return}process.on("uncaughtException",(b)=>{this.handleFatalError("uncaughtException",b)}),process.on("unhandledRejection",(b)=>{let q=b instanceof Error?b:Error(String(b));this.handleFatalError("unhandledRejection",q)}),process.on("SIGTERM",()=>{A.info("[GracefulShutdown] 收到 SIGTERM 信号"),this.shutdown("SIGTERM",0)}),process.on("SIGINT",()=>{let b=Date.now();if(b-this.lastSigintTime<this.SIGINT_DOUBLE_CLICK_WINDOW)A.info("[GracefulShutdown] 收到第二次 SIGINT 信号,执行退出"),this.shutdown("SIGINT",0);else A.info("[GracefulShutdown] 收到第一次 SIGINT 信号,再按一次退出"),this.lastSigintTime=b,console.log(`
|
|
2
2
|
再按一次 Ctrl+C 退出
|
|
3
3
|
`)}),this.initialized=!0,A.debug("[GracefulShutdown] 全局错误处理器已初始化")}registerCleanup(b){return this.cleanupHandlers.push(b),A.debug(`[GracefulShutdown] 注册清理函数,当前共 ${this.cleanupHandlers.length} 个`),()=>{let q=this.cleanupHandlers.indexOf(b);if(q!==-1)this.cleanupHandlers.splice(q,1),A.debug(`[GracefulShutdown] 取消注册清理函数,剩余 ${this.cleanupHandlers.length} 个`)}}handleFatalError(b,q){if(this.isShuttingDown){console.error(`[GracefulShutdown] 退出过程中发生额外错误 (${b}):`,q);return}if(console.error(""),console.error("═".repeat(60)),console.error(`Uncaught error (${b})`),console.error("═".repeat(60)),console.error(""),console.error("错误信息:",q.message),console.error(""),q.stack)console.error("堆栈跟踪:"),console.error(q.stack);console.error(""),console.error("═".repeat(60)),console.error(""),this.shutdown(b,1)}async shutdown(b,q=0){if(this.isShuttingDown){A.debug("[GracefulShutdown] 已在退出过程中,跳过重复退出");return}this.isShuttingDown=!0,A.info(`[GracefulShutdown] 开始优雅退出 (原因: ${b})`);try{await K()}catch(z){}try{let z=U.getInstance();if(z.isEnabled()){let F=Q(),W=F.session?.sessionId||"unknown",X=F.config?.config?.permissionMode||"default";await z.executeSessionEndHooks(Z(b),{projectDir:O(),sessionId:W,permissionMode:X})}}catch(z){console.error("[GracefulShutdown] SessionEnd hooks 执行失败:",z)}let B=5000,V=new Promise((z,F)=>{setTimeout(()=>{F(Error(`清理超时 (${B}ms)`))},B)});try{let z=this.runCleanupHandlers();await Promise.race([z,V])}catch(z){console.error("[GracefulShutdown] 清理过程中发生错误:",z)}finally{Y(),setTimeout(()=>{process.exit(q)},100)}}async runCleanupHandlers(){let b=[...this.cleanupHandlers].reverse();for(let q of b)try{let B=q();if(B instanceof Promise)await B}catch(B){console.error("[GracefulShutdown] 清理函数执行失败:",B)}}isExiting(){return this.isShuttingDown}reset(){this.isShuttingDown=!1,this.cleanupHandlers=[],this.initialized=!1}}var J=()=>{return D.getInstance()},H=(b)=>{return J().registerCleanup(b)},P=()=>{J().initialize()},L=(b=0)=>{J().shutdown("normal",b)};
|
|
4
4
|
export{J as Fb,H as Gb,P as Hb,L as Ib};
|
|
@@ -25,7 +25,7 @@ import{$c as YO}from"./chunk-beqaxytd.js";import{dd as XO}from"./chunk-jxv6r0c7.
|
|
|
25
25
|
`):void 0}}async executeNotificationHooks(O,q,Q){let Z="message"in q?q.message:"";if(O.length===0)return{suppress:!1,message:Z};let Y=[],$=!1,X=Z;for(let J of O)try{let W=await this.executeHook(J,q,Q);if(!W.success){if(W.warning)Y.push(W.warning);continue}if(W.output?.suppressOutput){$=!0;break}if(W.stdout&&W.stdout.trim())X=W.stdout.trim()}catch(W){let G=W instanceof Error?W.message:String(W);Y.push(`Hook failed: ${G}`)}return{suppress:$,message:X,warning:Y.length>0?Y.join(`
|
|
26
26
|
`):void 0}}async executeCompactionHooks(O,q,Q){if(O.length===0)return{blockCompaction:!1};let Z=[];for(let Y of O)try{let $=await this.executeHook(Y,q,Q);if(!$.success){if($.warning)Z.push($.warning);continue}let X=$.output?.hookSpecificOutput;if(X&&"blockCompaction"in X&&X.blockCompaction)return{blockCompaction:!0,blockReason:X.blockReason,warning:Z.length>0?Z.join(`
|
|
27
27
|
`):void 0}}catch($){let X=$ instanceof Error?$.message:String($);Z.push(`Hook failed: ${X}`)}return{blockCompaction:!1,warning:Z.length>0?Z.join(`
|
|
28
|
-
`):void 0}}async executeHook(O,q,Q){if(O.type!=="function"){let Y=await K.getInstance().getStatus(Q.projectDir,Q.config);if(Y.state!=="trusted"){let $=`${Y.trustRoot}:${Y.currentDigest}:${Y.state}`;if(!this.trustWarnings.has($)){if(this.trustWarnings.size>=512)this.trustWarnings.clear();this.trustWarnings.add($),$O.warn(`[HookTrust] Skipping configured hooks for ${Y.trustRoot}: ${Y.state}`)}return{success:!0,hook:O,warning:`Hook skipped: project hook trust is ${Y.state}`}}}let Z=this.withHookEnvironment(Q,O);if(O.type==="command")return this.executeCommandHook(O,q,Z);if(O.type==="prompt")return this.executePromptHook(O,q,Z);if(O.type==="function")return this.executeFunctionHook(O,q,Z);if(O.type==="http")return this.executeHttpHook(O,q,Z);throw Error(`Hook type ${O.type} not supported`)}async executeCommandHook(O,q,Q){let Z=(O.timeout??Q.config.defaultTimeout??60)*1000;try{let Y=await this.processExecutor.execute(O.command,q,Q,Z);return this.outputParser.parse(Y,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}catch(Y){return{success:!1,blocking:!1,error:Y instanceof Error?Y.message:String(Y),hook:O}}}async executePromptHook(O,q,Q){let Z=(O.timeout??Q.config.defaultTimeout??60)*1000;try{let Y=await this.getOrCreateChatService(O.model,Q),$="hook_event_name"in q?String(q.hook_event_name):"Unknown",X=this.buildPromptHookSystemMessage(O,$),J=JSON.stringify(q,null,2),W=new AbortController,G=setTimeout(()=>W.abort(),Z),L;try{L=(await Y.chat([{role:"system",content:X},{role:"user",content:J}],void 0,W.signal)).content}catch(F){if(W.signal.aborted||F instanceof Error&&F.name==="AbortError")return this.outputParser.parse({stdout:"",stderr:"",exitCode:0,timedOut:!0},O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior});throw F}finally{clearTimeout(G)}let R=this.extractJsonFromLLMResponse(L);return this.outputParser.parse({stdout:R,stderr:"",exitCode:0,timedOut:!1},O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}catch(Y){return $O.warn(`[PromptHook] 执行失败: ${Y instanceof Error?Y.message:String(Y)}`),{success:!1,blocking:!1,error:Y instanceof Error?Y.message:String(Y),hook:O}}}async executeFunctionHook(O,q,Q){let Z=(O.timeout??10)*1000;try{let Y=await this.runFunctionWithTimeout(O.handler,q,Q,Z);if(Y===void 0||Y===null)return{success:!0,hook:O};let $={stdout:JSON.stringify(Y),stderr:"",exitCode:0,timedOut:!1};return this.outputParser.parse($,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}catch(Y){if(Y.isTimeout){let $={stdout:"",stderr:`Function hook timeout after ${Z}ms`,exitCode:124,timedOut:!0};return this.outputParser.parse($,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}return{success:!1,blocking:!1,error:Y instanceof Error?Y.message:String(Y),hook:O}}}runFunctionWithTimeout(O,q,Q,Z){return new Promise((Y,$)=>{let X=!1,J=setTimeout(()=>{if(X)return;X=!0;let G=Object.assign(Error(`Function hook timed out after ${Z}ms`),{isTimeout:!0});$(G)},Z),W=()=>{if(X)return;X=!0,clearTimeout(J),$(Error("Function hook aborted"))};Q.abortSignal?.addEventListener("abort",W,{once:!0}),Promise.resolve().then(()=>O(q,Q)).then((G)=>{if(X)return;X=!0,clearTimeout(J),Q.abortSignal?.removeEventListener("abort",W),Y(G)},(G)=>{if(X)return;X=!0,clearTimeout(J),Q.abortSignal?.removeEventListener("abort",W),$(G)})})}async executeHttpHook(O,q,Q){let Z=(O.timeout??10)*1000,Y=O.maxResponseBytes??262144,$=Math.max(1,(O.retries??0)+1);try{e(O.url,Q.config.httpPolicy)}catch(G){return{success:!1,blocking:!0,error:G instanceof Error?G.message:String(G),hook:O}}let X={"Content-Type":"application/json",...OO(O.headers)},J=JSON.stringify(q),W;for(let G=0;G<$;G++){if(G>0){let V=Math.min(2**G*200,5000);await new Promise((B)=>setTimeout(B,V))}let L=new AbortController,R=setTimeout(()=>L.abort(),Z),F=()=>L.abort();Q.abortSignal?.addEventListener("abort",F,{once:!0});try{let V=await fetch(O.url,{method:"POST",headers:X,body:J,redirect:"manual",signal:L.signal});if(V.status>=300&&V.status<400){W=Error(`HTTP hook received redirect (${V.status}); redirects are disabled`);continue}if(!V.ok){if(W=Error(`HTTP hook returned ${V.status} ${V.statusText}`),V.status>=400&&V.status<500)break;continue}let P={stdout:await yO(V,Y),stderr:"",exitCode:0,timedOut:!1};return this.outputParser.parse(P,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}catch(V){let B=V.name==="AbortError"||V.code==="ABORT_ERR";if(B&&Q.abortSignal?.aborted){W=Error("HTTP hook aborted by caller");break}if(B){let P={stdout:"",stderr:`HTTP hook timeout after ${Z}ms`,exitCode:124,timedOut:!0};if(G===$-1)return this.outputParser.parse(P,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior});W=Error(`HTTP hook timeout attempt ${G+1}`);continue}W=V}finally{clearTimeout(R),Q.abortSignal?.removeEventListener("abort",F)}}return{success:!1,blocking:!1,error:W?.message??"HTTP hook failed",hook:O}}async getOrCreateChatService(O,q){let Q=this.sessionResourceKey(q.sessionId,q.projectDir),Z=`${Q}\x00${O||"__default__"}`,Y=this.chatServiceCache.get(Z);if(Y)return Y;let{ensureStoreInitialized:$,getConfig:X}=await import("./chunk-
|
|
28
|
+
`):void 0}}async executeHook(O,q,Q){if(O.type!=="function"){let Y=await K.getInstance().getStatus(Q.projectDir,Q.config);if(Y.state!=="trusted"){let $=`${Y.trustRoot}:${Y.currentDigest}:${Y.state}`;if(!this.trustWarnings.has($)){if(this.trustWarnings.size>=512)this.trustWarnings.clear();this.trustWarnings.add($),$O.warn(`[HookTrust] Skipping configured hooks for ${Y.trustRoot}: ${Y.state}`)}return{success:!0,hook:O,warning:`Hook skipped: project hook trust is ${Y.state}`}}}let Z=this.withHookEnvironment(Q,O);if(O.type==="command")return this.executeCommandHook(O,q,Z);if(O.type==="prompt")return this.executePromptHook(O,q,Z);if(O.type==="function")return this.executeFunctionHook(O,q,Z);if(O.type==="http")return this.executeHttpHook(O,q,Z);throw Error(`Hook type ${O.type} not supported`)}async executeCommandHook(O,q,Q){let Z=(O.timeout??Q.config.defaultTimeout??60)*1000;try{let Y=await this.processExecutor.execute(O.command,q,Q,Z);return this.outputParser.parse(Y,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}catch(Y){return{success:!1,blocking:!1,error:Y instanceof Error?Y.message:String(Y),hook:O}}}async executePromptHook(O,q,Q){let Z=(O.timeout??Q.config.defaultTimeout??60)*1000;try{let Y=await this.getOrCreateChatService(O.model,Q),$="hook_event_name"in q?String(q.hook_event_name):"Unknown",X=this.buildPromptHookSystemMessage(O,$),J=JSON.stringify(q,null,2),W=new AbortController,G=setTimeout(()=>W.abort(),Z),L;try{L=(await Y.chat([{role:"system",content:X},{role:"user",content:J}],void 0,W.signal)).content}catch(F){if(W.signal.aborted||F instanceof Error&&F.name==="AbortError")return this.outputParser.parse({stdout:"",stderr:"",exitCode:0,timedOut:!0},O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior});throw F}finally{clearTimeout(G)}let R=this.extractJsonFromLLMResponse(L);return this.outputParser.parse({stdout:R,stderr:"",exitCode:0,timedOut:!1},O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}catch(Y){return $O.warn(`[PromptHook] 执行失败: ${Y instanceof Error?Y.message:String(Y)}`),{success:!1,blocking:!1,error:Y instanceof Error?Y.message:String(Y),hook:O}}}async executeFunctionHook(O,q,Q){let Z=(O.timeout??10)*1000;try{let Y=await this.runFunctionWithTimeout(O.handler,q,Q,Z);if(Y===void 0||Y===null)return{success:!0,hook:O};let $={stdout:JSON.stringify(Y),stderr:"",exitCode:0,timedOut:!1};return this.outputParser.parse($,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}catch(Y){if(Y.isTimeout){let $={stdout:"",stderr:`Function hook timeout after ${Z}ms`,exitCode:124,timedOut:!0};return this.outputParser.parse($,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}return{success:!1,blocking:!1,error:Y instanceof Error?Y.message:String(Y),hook:O}}}runFunctionWithTimeout(O,q,Q,Z){return new Promise((Y,$)=>{let X=!1,J=setTimeout(()=>{if(X)return;X=!0;let G=Object.assign(Error(`Function hook timed out after ${Z}ms`),{isTimeout:!0});$(G)},Z),W=()=>{if(X)return;X=!0,clearTimeout(J),$(Error("Function hook aborted"))};Q.abortSignal?.addEventListener("abort",W,{once:!0}),Promise.resolve().then(()=>O(q,Q)).then((G)=>{if(X)return;X=!0,clearTimeout(J),Q.abortSignal?.removeEventListener("abort",W),Y(G)},(G)=>{if(X)return;X=!0,clearTimeout(J),Q.abortSignal?.removeEventListener("abort",W),$(G)})})}async executeHttpHook(O,q,Q){let Z=(O.timeout??10)*1000,Y=O.maxResponseBytes??262144,$=Math.max(1,(O.retries??0)+1);try{e(O.url,Q.config.httpPolicy)}catch(G){return{success:!1,blocking:!0,error:G instanceof Error?G.message:String(G),hook:O}}let X={"Content-Type":"application/json",...OO(O.headers)},J=JSON.stringify(q),W;for(let G=0;G<$;G++){if(G>0){let V=Math.min(2**G*200,5000);await new Promise((B)=>setTimeout(B,V))}let L=new AbortController,R=setTimeout(()=>L.abort(),Z),F=()=>L.abort();Q.abortSignal?.addEventListener("abort",F,{once:!0});try{let V=await fetch(O.url,{method:"POST",headers:X,body:J,redirect:"manual",signal:L.signal});if(V.status>=300&&V.status<400){W=Error(`HTTP hook received redirect (${V.status}); redirects are disabled`);continue}if(!V.ok){if(W=Error(`HTTP hook returned ${V.status} ${V.statusText}`),V.status>=400&&V.status<500)break;continue}let P={stdout:await yO(V,Y),stderr:"",exitCode:0,timedOut:!1};return this.outputParser.parse(P,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior})}catch(V){let B=V.name==="AbortError"||V.code==="ABORT_ERR";if(B&&Q.abortSignal?.aborted){W=Error("HTTP hook aborted by caller");break}if(B){let P={stdout:"",stderr:`HTTP hook timeout after ${Z}ms`,exitCode:124,timedOut:!0};if(G===$-1)return this.outputParser.parse(P,O,{timeoutBehavior:Q.config.timeoutBehavior,failureBehavior:Q.config.failureBehavior});W=Error(`HTTP hook timeout attempt ${G+1}`);continue}W=V}finally{clearTimeout(R),Q.abortSignal?.removeEventListener("abort",F)}}return{success:!1,blocking:!1,error:W?.message??"HTTP hook failed",hook:O}}async getOrCreateChatService(O,q){let Q=this.sessionResourceKey(q.sessionId,q.projectDir),Z=`${Q}\x00${O||"__default__"}`,Y=this.chatServiceCache.get(Z);if(Y)return Y;let{ensureStoreInitialized:$,getConfig:X}=await import("./chunk-tckfyfsx.js"),{createChatServiceAsync:J}=await import("./chunk-asbp4cv4.js"),{resolveModelConfig:W}=await import("./chunk-m3tx1k0s.js"),{resolveWorkspaceModelResources:G}=await import("./chunk-ymmtbq2b.js");await $();let L=X();if(!L)throw Error("PromptHook: 配置未初始化");let R=this.sessionModelResources.get(Q)??await G(q.projectDir,L),F=O?R.config.models.find((B)=>B.id===O):R.config.models.find((B)=>B.id===R.config.currentModelId)??R.config.models[0];if(!F)throw Error("PromptHook: 无法获取模型配置。请确保至少配置了一个模型。");let V=await J(W(F,R.config,"off",R.catalog).chat);return this.chatServiceCache.set(Z,V),V}sessionResourceKey(O,q){return`${O}\x00${DO.resolve(q)}`}withSessionEnvironment(O){let q=this.sessionEnvironments.get(this.sessionResourceKey(O.sessionId,O.projectDir));return q?{...O,environment:q}:O}withHookEnvironment(O,q){let Q=this.withSessionEnvironment(O);if(!q.source)return Q;return{...Q,environment:{...Q.environment,BLADE_PLUGIN_ROOT:q.source.pluginRoot,CLAUDE_PLUGIN_ROOT:q.source.pluginRoot,BLADE_PLUGIN_NAME:q.source.pluginName}}}buildPromptHookSystemMessage(O,q){let Q=EO[q]||"{ ... 根据事件类型返回相应字段 }";return`你是一个代码质量评估器,作为 Hook 在 ${q} 事件中被触发。
|
|
29
29
|
|
|
30
30
|
`+`## 评估指令
|
|
31
31
|
${O.prompt}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{hb as y$,ib as v,jb as h0,kb as j$,lb as l0,mb as p0,nb as c0,ob as r,pb as S$,qb as n0,sb as z0,vb as i0,wb as m$}from"./chunk-44wkjs2j.js";import{vc as Q0}from"./chunk-fjw32ex5.js";import{Sc as H0}from"./chunk-d9ddpapp.js";import{$c as U$}from"./chunk-beqaxytd.js";import{dd as Y0}from"./chunk-jxv6r0c7.js";import{be as g$,ce as f$}from"./chunk-qev36qrb.js";import{he as Z$}from"./chunk-vjpd3nee.js";import{ne as J0,qe as Z0}from"./chunk-2beq0syt.js";import{ue as l}from"./chunk-
|
|
1
|
+
import{hb as y$,ib as v,jb as h0,kb as j$,lb as l0,mb as p0,nb as c0,ob as r,pb as S$,qb as n0,sb as z0,vb as i0,wb as m$}from"./chunk-44wkjs2j.js";import{vc as Q0}from"./chunk-fjw32ex5.js";import{Sc as H0}from"./chunk-d9ddpapp.js";import{$c as U$}from"./chunk-beqaxytd.js";import{dd as Y0}from"./chunk-jxv6r0c7.js";import{be as g$,ce as f$}from"./chunk-qev36qrb.js";import{he as Z$}from"./chunk-vjpd3nee.js";import{ne as J0,qe as Z0}from"./chunk-2beq0syt.js";import{ue as l}from"./chunk-k89phc5j.js";import{Be as k$,Ce as V0,Ee as D,Fe as S,He as u0,Ie as h,Je as T0}from"./chunk-8nm1hqr1.js";import{readdir as z$,readFile as t,rm as _0,stat as C1}from"node:fs/promises";import*as V from"node:path";import{nanoid as j}from"nanoid";import{createHash as p$,randomUUID as c$}from"node:crypto";import*as m from"node:fs/promises";import*as X0 from"node:path";var Q$=1;function n$($,q){let T=p$("sha256").update(q).digest("hex");return X0.join(V0($),".locks",`${T}.lock`)}function O0($,q){return $ instanceof Error&&"code"in $&&$.code===q}async function R0($){try{let q=JSON.parse(await m.readFile($,"utf8"));if(q.version!==Q$||typeof q.sessionId!=="string"||typeof q.ownerId!=="string"||!Number.isInteger(q.pid)||(q.pid??0)<=0||typeof q.acquiredAt!=="string")return;return q}catch{return}}async function G$($){let q=await R0($);if(q)return q;return await new Promise((T)=>setTimeout(T,10)),R0($)}function i$($){try{return process.kill($,0),!0}catch(q){return O0(q,"EPERM")}}async function J$($,q){let T;try{return T=await m.open($,"wx",384),await T.writeFile(`${JSON.stringify(q)}
|
|
2
2
|
`,"utf8"),!0}catch(G){if(O0(G,"EEXIST"))return!1;if(T)await m.unlink($).catch(()=>{return});throw G}finally{await T?.close().catch(()=>{return})}}class p extends Error{code="BLADE_SESSION_IN_USE";constructor($){super($?`Session is already active in another Blade process (PID ${$}). Stop that process or choose a different session.`:"Session is already active in another Blade process. Stop that process or choose a different session.");this.name="SessionInUseError"}}class c{filePath;record;released=!1;constructor($,q){this.filePath=$;this.record=q}static async acquire($,q=Z$()){let T=n$(q,$),G={version:Q$,sessionId:$,ownerId:c$(),pid:process.pid,acquiredAt:new Date().toISOString()};if(await m.mkdir(X0.dirname(T),{recursive:!0,mode:448}),await J$(T,G))return new c(T,G);let Z=await G$(T);if(Z&&i$(Z.pid))throw new p(Z.pid);if(await m.unlink(T).catch((J)=>{if(!O0(J,"ENOENT"))throw J}),await J$(T,G))return new c(T,G);throw new p((await G$(T))?.pid)}async release(){if(this.released)return;if(this.released=!0,(await R0(this.filePath))?.ownerId!==this.record.ownerId)return;await m.unlink(this.filePath).catch((q)=>{if(!O0(q,"ENOENT"))throw q})}}var A0={authentication:{message:"Provider authentication failed. Check model credentials.",retryable:!1},permission:{message:"Provider rejected this request. Check account and model permissions.",retryable:!1},rate_limit:{message:"Provider rate limit or quota exceeded.",retryable:!0},timeout:{message:"Provider request timed out.",retryable:!0},network:{message:"Provider connection failed.",retryable:!0},model_unavailable:{message:"The selected model is unavailable.",retryable:!0},context_limit:{message:"The request exceeded the model context limit.",retryable:!1},unsupported_input:{message:"The selected model does not support this input.",retryable:!1},runtime:{message:"Agent execution failed.",retryable:!0}};function d$($){try{if($ instanceof Error)return $.message;if($!==null&&typeof $==="object"&&"message"in $&&typeof $.message==="string")return $.message;return String($)}catch{return"Unknown error"}}function r$($){let q=$.toLowerCase();if(/\b(401|unauthorized|authentication|invalid (?:api[ _-]?)?key|api[ _-]?key|credential)\b/.test(q))return"authentication";if(/\b(403|forbidden|permission denied|not permitted)\b/.test(q))return"permission";if(/\b(429|rate limit|too many requests|quota)\b/.test(q))return"rate_limit";if(/\b(timeout|timed out|deadline exceeded|etimedout)\b/.test(q))return"timeout";if(/\b(econnreset|econnrefused|enotfound|network|socket|connection)\b/.test(q))return"network";if(/\b(model not found|model unavailable|unsupported model|no such model)\b/.test(q))return"model_unavailable";if(/\b(context (?:length|window)|maximum context|too many tokens|token limit)\b/.test(q))return"context_limit";if(/\b(image|vision|multimodal|unsupported input|does not support)\b/.test(q))return"unsupported_input";return"runtime"}function o$($){return{code:$,...A0[$]}}function H$($){return o$(r$(d$($)))}function E0($){if(!$||typeof $!=="object")return!1;let q=$;if(typeof q.code!=="string"||!(q.code in A0))return!1;let T=A0[q.code];return q.message===T.message&&q.retryable===T.retryable}import{promises as e,realpathSync as t$}from"node:fs";import K0 from"node:path";import*as i from"fs/promises";import*as W from"path";var L$=[".git",".claude","node_modules",".env",".env.local",".env.production",".env.development",".env.test"];class n extends Error{code;constructor($,q){super($);this.code=q;this.name="PathSecurityError"}}class b0{static normalize($,q){let T=W.isAbsolute($)?$:W.resolve(q,$),G=W.normalize(T),Z=W.normalize(q);if(!this.isWithinWorkspace(G,Z))throw new n(`Path outside workspace: ${$} (resolved to ${G}, workspace: ${Z})`,"PATH_OUTSIDE_WORKSPACE");return G}static checkRestricted($){let q=$.split(W.sep);for(let T of L$)if(q.includes(T))throw new n(`Access denied: "${T}" is a protected directory`,"RESTRICTED_PATH")}static checkTraversal($){if($.includes(".."))throw new n(`Path traversal not allowed: ${$}`,"PATH_TRAVERSAL")}static async validatePath($,q){this.checkTraversal($);let T=this.normalize($,q);this.checkRestricted(T);try{await i.access(T)}catch(G){throw new n(`Path not found: ${$}`,"PATH_NOT_FOUND")}return T}static async resolveSymlink($,q){try{let T=await i.realpath($),G=await i.realpath(q);if(!this.isWithinWorkspace(T,G))throw new n(`Symlink points outside workspace: ${$} -> ${T}`,"SYMLINK_OUTSIDE_WORKSPACE");return T}catch(T){if(T instanceof n)throw T;return $}}static getRelativePath($,q){return W.relative(q,$)}static isWithinWorkspace($,q){let T=W.resolve($),G=W.resolve(q),Z=W.relative(G,T);return Z===""||Z!==".."&&!Z.startsWith(`..${W.sep}`)&&!W.isAbsolute(Z)}static async isWithinWorkspaceResolved($,q){let T=W.resolve(q),G=W.isAbsolute($)?W.resolve($):W.resolve(T,$);if(!this.isWithinWorkspace(G,T))return!1;let Z;try{Z=await i.realpath(T)}catch{return!1}let J=G;while(!0){try{let Q=await i.realpath(J);return this.isWithinWorkspace(Q,Z)}catch(Q){let L=Q.code;if(L!=="ENOENT"&&L!=="ENOTDIR")return!1}let H=W.dirname(J);if(H===J)return!1;J=H}}static isRestricted($){let q=$.split(W.sep);return L$.some((T)=>q.includes(T))}}var $0=Y0("Tool");class u{static instance=null;accessedFiles=new Map;pathAliases=new Map;constructor(){}static getInstance(){if(!u.instance)u.instance=new u;return u.instance}async recordFileRead($,q){try{let T=await e.stat($),G={filePath:K0.resolve($),accessTime:Date.now(),mtime:T.mtimeMs,sessionId:q,lastOperation:"read"};this.setRecord(G),await this.recordAliases($,G.filePath),$0.debug(`记录文件读取: ${$}`)}catch(T){$0.warn(`记录文件读取失败: ${$}`,T)}}async recordFileEdit($,q,T="edit"){try{let G=await e.stat($),Z={filePath:K0.resolve($),accessTime:Date.now(),mtime:G.mtimeMs,sessionId:q,lastOperation:T};this.setRecord(Z),await this.recordAliases($,Z.filePath),$0.debug(`记录文件${T==="edit"?"编辑":"写入"}: ${$}`)}catch(G){$0.warn(`记录文件${T==="edit"?"编辑":"写入"}失败: ${$}`,G)}}hasFileBeenRead($,q){let T=this.accessedFiles.get(this.resolveTrackedPath($));if(!T)return!1;return q?T.has(q):T.size>0}async checkFileModification($,q){let T=this.getFileRecord($,q);if(!T)return{modified:!1,message:"文件未被跟踪"};try{let G=await e.stat($);if(Math.abs(G.mtimeMs-T.mtime)>1)return{modified:!0,message:`文件在访问后被修改(访问时间: ${new Date(T.accessTime).toISOString()}, 当前修改时间: ${G.mtime.toISOString()})`};return{modified:!1}}catch(G){let Z=G;if(Z.code==="ENOENT")return{modified:!0,message:"文件已被删除"};return{modified:!1,message:`无法检查文件状态: ${Z.message}`}}}async checkExternalModification($,q){let T=this.getFileRecord($,q);if(!T)return{isExternal:!1,message:"文件未被跟踪"};try{let G=await e.stat($);if(G.mtimeMs-T.mtime>2000)return{isExternal:!0,message:`文件在 ${new Date(T.accessTime).toISOString()} (${T.lastOperation}) 之后被外部程序修改(当前修改时间: ${G.mtime.toISOString()})`};return{isExternal:!1}}catch(G){let Z=G;if(Z.code==="ENOENT")return{isExternal:!0,message:"文件已被删除"};return $0.warn(`检查文件外部修改失败: ${$}`,G),{isExternal:!1,message:`无法检查文件状态: ${Z.message}`}}}getFileRecord($,q){let T=this.accessedFiles.get(this.resolveTrackedPath($));if(!T)return;if(q)return T.get(q);return[...T.values()].sort((G,Z)=>Z.accessTime-G.accessTime)[0]}getTrackedRecords(){return[...this.accessedFiles.values()].flatMap(($)=>[...$.values()])}clearFileRecord($,q){let T=this.resolveTrackedPath($);if(!q){this.accessedFiles.delete(T),this.removeAliases(T);return}let G=this.accessedFiles.get(T);if(G?.delete(q),G?.size===0)this.accessedFiles.delete(T),this.removeAliases(T)}clearAll(){this.accessedFiles.clear(),this.pathAliases.clear()}clearSession($,q){for(let[T,G]of this.accessedFiles.entries()){if(q&&!b0.isWithinWorkspace(T,q))continue;if(G.delete($),G.size===0)this.accessedFiles.delete(T),this.removeAliases(T)}}getTrackedFiles(){return Array.from(this.accessedFiles.keys())}getTrackedFileCount(){return this.accessedFiles.size}static resetInstance(){u.instance=null}setRecord($){let q=this.accessedFiles.get($.filePath);if(!q)q=new Map,this.accessedFiles.set($.filePath,q);q.set($.sessionId,$)}async recordAliases($,q){this.pathAliases.set(K0.resolve($),q);let T=await e.realpath($).catch(()=>{return});if(T)this.pathAliases.set(T,q)}resolveTrackedPath($){let q=K0.resolve($);if(this.accessedFiles.has(q))return q;let T=this.pathAliases.get(q);if(T)return T;try{let G=t$.native(q);return this.pathAliases.get(G)??G}catch{return q}}removeAliases($){for(let[q,T]of this.pathAliases)if(T===$)this.pathAliases.delete(q)}}import*as q0 from"node:crypto";import{promises as K}from"node:fs";import*as F from"node:path";import w0 from"write-file-atomic";var B$="missing";class U0{sessionId;workspaceRoot;enableCheckpoints;maxSnapshots;snapshotDir;manifestPath;trackedFileBackups=new Map;snapshots=[];constructor($){if(D($.sessionId),this.sessionId=$.sessionId,$.workspaceRoot&&!F.isAbsolute($.workspaceRoot))throw Error("Snapshot workspace root must be absolute");this.workspaceRoot=$.workspaceRoot?F.resolve($.workspaceRoot):void 0,this.enableCheckpoints=$.enableCheckpoints??!0,this.maxSnapshots=$.maxSnapshots??10;let q=T0();this.snapshotDir=F.join(q,"file-history",this.sessionId),this.manifestPath=F.join(this.snapshotDir,"manifest.json")}async initialize(){if(!this.enableCheckpoints)return;if(this.workspaceRoot)await this.selectWorkspaceSnapshotDir();await K.mkdir(this.snapshotDir,{recursive:!0,mode:493}),await this.loadManifest()}async selectWorkspaceSnapshotDir(){let $=T0(),q=await K.realpath(this.workspaceRoot).catch(()=>this.workspaceRoot),T=q0.createHash("sha256").update(q).digest("hex").slice(0,24),G=F.join($,"file-history",this.sessionId),Z=F.join($,"file-history","workspaces",T,this.sessionId),J=F.join(Z,"manifest.json");try{await K.access(J)}catch{await this.migrateLegacySnapshotDir(G,Z,q)}this.snapshotDir=Z,this.manifestPath=J}async migrateLegacySnapshotDir($,q,T){let G;try{G=JSON.parse(await K.readFile(F.join($,"manifest.json"),"utf8"))}catch{return}if(G.schemaVersion!==1||!Array.isArray(G.snapshots)||!G.snapshots.every((Z)=>this.isWithinWorkspace(Z.filePath,T)))return;await K.mkdir(F.dirname(q),{recursive:!0,mode:493});try{await K.rename($,q)}catch(Z){let J=Z.code;if(J!=="ENOENT"&&J!=="EEXIST"&&J!=="ENOTEMPTY")throw Z}}isWithinWorkspace($,q){if(!F.isAbsolute($))return!1;let T=F.relative(q,F.resolve($));return T===""||T!==".."&&!T.startsWith(`..${F.sep}`)&&!F.isAbsolute(T)}async createSnapshot($,q){if(!this.enableCheckpoints)return{backupFileName:"",version:0,backupTime:new Date};let T=await this.resolveFileIdentity($),G=!0;try{await K.access(T)}catch{G=!1}let Z=this.trackedFileBackups.get(T),J=Z?Z.version+1:1,H=this.generateFileHash(T,J),Q=this.getSnapshotPath(H,J),L=new Date;if(G){let B=await K.readFile(T);await K.writeFile(Q,B)}let O={backupFileName:H,version:J,backupTime:L};return this.trackedFileBackups.set(T,O),this.snapshots.push({messageId:q,backupFileName:H,timestamp:L,filePath:T,version:J,existedBefore:G}),await this.cleanupOldSnapshots(T),await this.persistManifest(),O}async recordPostEditState($,q){if(!this.enableCheckpoints||!q.backupFileName)return;let T=await this.resolveFileIdentity($),G=this.snapshots.find((Z)=>Z.filePath===T&&Z.backupFileName===q.backupFileName&&Z.version===q.version);if(!G)throw Error(`未找到待完成的快照: ${T}`);G.postEditHash=await this.hashFile(T),await this.persistManifest()}async discardSnapshot($,q){if(!this.enableCheckpoints||!q.backupFileName)return;let T=await this.resolveFileIdentity($),G=this.snapshots.find((Z)=>Z.filePath===T&&Z.backupFileName===q.backupFileName&&Z.version===q.version);if(!G)return;this.removeSnapshot(G),await K.rm(this.getSnapshotPath(G.backupFileName,G.version),{force:!0}),await this.persistManifest()}async rewindLatest($){let q=await this.resolveFileIdentity($),T=this.snapshots.slice().reverse().find((J)=>J.filePath===q&&J.postEditHash!==void 0);if(!T?.postEditHash)throw Error(`未找到可回退快照: ${q}`);if(await this.hashFile(q)!==T.postEditHash)throw Error(`文件在 Blade 编辑后已被修改,拒绝覆盖: ${q}`);let Z=this.getSnapshotPath(T.backupFileName,T.version);if(T.existedBefore){let J=await K.readFile(Z);await K.mkdir(F.dirname(q),{recursive:!0}),await K.writeFile(q,J)}else await K.rm(q,{force:!0});return this.removeSnapshot(T),await K.rm(Z,{force:!0}),await this.persistManifest(),T}async restoreSnapshot($,q){let T=await this.resolveFileIdentity($),G=this.snapshots.slice().reverse().find((J)=>J.messageId===q&&J.filePath===T);if(!G)throw Error(`未找到快照: messageId=${q}, filePath=${T}`);let Z=this.getSnapshotPath(G.backupFileName,G.version);if(G.existedBefore){let J=await K.readFile(Z);await K.mkdir(F.dirname(T),{recursive:!0}),await K.writeFile(T,J)}else await K.rm(T,{force:!0})}async listSnapshots($){let q=await this.resolveFileIdentity($);return this.snapshots.filter((T)=>T.filePath===q)}async listAllSnapshots(){return this.snapshots.filter(($)=>$.postEditHash!==void 0)}async previewRewind($){let q=this.buildRewindPlan($);return{files:q.map((T)=>T.filePath),snapshotCount:q.reduce((T,G)=>T+G.selected.length,0)}}async rewindSnapshots($){let q=this.buildRewindPlan($);if(q.length===0)return{files:[],snapshotCount:0};let T=new Map;for(let Z of q){let J,H=!0;try{J=await K.readFile(Z.filePath)}catch(L){if(L.code!=="ENOENT")throw L;H=!1}if((J?q0.createHash("sha256").update(J).digest("hex"):B$)!==Z.latest.postEditHash)throw Error(`文件在 Blade 编辑后已被修改,拒绝覆盖: ${Z.filePath}`);if(T.set(Z.filePath,{existed:H,content:J}),Z.target.existedBefore)await K.access(this.getSnapshotPath(Z.target.backupFileName,Z.target.version))}let G=[...this.snapshots];try{for(let J of q)if(J.target.existedBefore){let H=await K.readFile(this.getSnapshotPath(J.target.backupFileName,J.target.version));await K.mkdir(F.dirname(J.filePath),{recursive:!0}),await w0(J.filePath,H)}else await K.rm(J.filePath,{force:!0});let Z=new Set(q.flatMap((J)=>J.selected));this.snapshots=this.snapshots.filter((J)=>!Z.has(J)),this.rebuildTrackedFileBackups(),await this.persistManifest(),await Promise.all([...Z].map((J)=>K.rm(this.getSnapshotPath(J.backupFileName,J.version),{force:!0}).catch(()=>{return})))}catch(Z){this.snapshots=G,this.rebuildTrackedFileBackups();let J=[];for(let[H,Q]of T)try{if(Q.existed&&Q.content)await w0(H,Q.content);else await K.rm(H,{force:!0})}catch(L){J.push(L)}if(J.length>0)throw AggregateError([Z,...J],"快照回退失败且无法完整恢复回退前状态");throw Z}return{files:q.map((Z)=>Z.filePath),snapshotCount:q.reduce((Z,J)=>Z+J.selected.length,0)}}async commitSnapshots($){let q=this.buildRewindPlan($),T=new Set(q.flatMap((Z)=>Z.selected));if(T.size===0)return{files:[],snapshotCount:0};let G=[...this.snapshots];this.snapshots=this.snapshots.filter((Z)=>!T.has(Z)),this.rebuildTrackedFileBackups();try{await this.persistManifest()}catch(Z){throw this.snapshots=G,this.rebuildTrackedFileBackups(),Z}return await Promise.all([...T].map((Z)=>K.rm(this.getSnapshotPath(Z.backupFileName,Z.version),{force:!0}).catch(()=>{return}))),{files:q.map((Z)=>Z.filePath),snapshotCount:T.size}}buildRewindPlan($){let q=new Set($),T=this.snapshots.filter((J)=>J.postEditHash!==void 0),G=T.filter((J)=>q.has(J.messageId));return[...new Set(G.map((J)=>J.filePath))].sort().map((J)=>{let H=T.filter((B)=>B.filePath===J),Q=H.filter((B)=>q.has(B.messageId)),L=H.indexOf(Q[0]),O=H.slice(L);if(O.length!==Q.length||O.some((B)=>!q.has(B.messageId)))throw Error(`请求的快照不是文件历史的连续后缀: ${J}`);return{filePath:J,selected:Q,target:Q[0],latest:Q.at(-1)}})}async loadManifest(){try{let $=await K.readFile(this.manifestPath,"utf-8"),q=JSON.parse($);if(q.schemaVersion!==1||!Array.isArray(q.snapshots))throw Error("Unsupported snapshot manifest");this.snapshots=await Promise.all(q.snapshots.map(async(T)=>({...T,filePath:await this.resolveFileIdentity(T.filePath),timestamp:new Date(T.timestamp)}))),this.rebuildTrackedFileBackups()}catch($){if($.code!=="ENOENT")throw $;this.snapshots=[],this.trackedFileBackups.clear()}}async persistManifest(){if(this.snapshots.length===0){await K.rm(this.manifestPath,{force:!0});return}let $={schemaVersion:1,snapshots:this.snapshots.map((q)=>({...q,timestamp:q.timestamp.toISOString()}))};await w0(this.manifestPath,JSON.stringify($,null,2),{encoding:"utf-8",mode:384})}async cleanupOldSnapshots($){let T=this.snapshots.filter((G)=>G.filePath===$).slice(0,-this.maxSnapshots);for(let G of T)await K.rm(this.getSnapshotPath(G.backupFileName,G.version),{force:!0}),this.removeSnapshot(G)}async cleanup($=0){let q=this.snapshots.slice().sort((G,Z)=>Z.timestamp.getTime()-G.timestamp.getTime()),T=new Set(q.slice(0,$));for(let G of this.snapshots)if(!T.has(G))await K.rm(this.getSnapshotPath(G.backupFileName,G.version),{force:!0});this.snapshots=q.slice(0,$).reverse(),this.rebuildTrackedFileBackups(),await this.persistManifest()}getSnapshotPath($,q){return F.join(this.snapshotDir,`${$}@v${q}`)}async resolveFileIdentity($){let q=F.resolve($),T=[],G=q;while(!0){try{let J=await K.realpath(G);return F.join(J,...T.reverse())}catch(J){let H=J.code;if(H!=="ENOENT"&&H!=="ENOTDIR")throw J}let Z=F.dirname(G);if(Z===G)return q;T.push(F.basename(G)),G=Z}}async hashFile($){try{let q=await K.readFile($);return q0.createHash("sha256").update(q).digest("hex")}catch(q){if(q.code==="ENOENT")return B$;throw q}}removeSnapshot($){let q=this.snapshots.indexOf($);if(q>=0)this.snapshots.splice(q,1);this.rebuildTrackedFileBackups()}rebuildTrackedFileBackups(){this.trackedFileBackups.clear();for(let $ of this.snapshots){let q=this.trackedFileBackups.get($.filePath);if(!q||q.version<$.version)this.trackedFileBackups.set($.filePath,{backupFileName:$.backupFileName,version:$.version,backupTime:$.timestamp})}}generateFileHash($,q){let T=q0.createHash("md5");return T.update(`${$}:${q}`),T.digest("hex").substring(0,16)}getSnapshotDir(){return this.snapshotDir}getSessionId(){return this.sessionId}getTrackedFileCount(){return this.trackedFileBackups.size}getSnapshotCount(){return this.snapshots.length}}import{createHash as O1}from"node:crypto";import W$ from"node:path";import{StringDecoder as q1}from"node:string_decoder";function s$($,q){let T=q;while(T<$.length&&($[T]&192)===128)T+=1;return T}class k0{maxBytes;chunks=[];retainedBytes=0;omittedBytes=0;constructor($=1048576){this.maxBytes=$;if(!Number.isSafeInteger($)||$<=0)throw Error("maxBytes must be a positive safe integer")}append($){let q=Buffer.isBuffer($)?Buffer.from($):Buffer.from($);if(q.length===0)return;this.chunks.push(q),this.retainedBytes+=q.length,this.trimToLimit()}peek(){return{content:Buffer.concat(this.chunks,this.retainedBytes).toString("utf8"),omittedBytes:this.omittedBytes}}consume(){let $=this.peek();return this.chunks.length=0,this.retainedBytes=0,this.omittedBytes=0,$}trimToLimit(){while(this.retainedBytes>this.maxBytes){let $=this.chunks[0];if(!$)return;let q=this.retainedBytes-this.maxBytes;if($.length<=q){this.chunks.shift(),this.retainedBytes-=$.length,this.omittedBytes+=$.length;continue}let T=s$($,q);this.chunks[0]=$.subarray(T),this.retainedBytes-=T,this.omittedBytes+=T}}}var N0={maxLines:30,maxChars:3000,keepHead:10,keepTail:10,summarize:!0},d={maxLines:100,maxChars:1e4,keepHead:40,keepTail:40,summarize:!0},O$={maxLines:200,maxChars:20000,keepHead:80,keepTail:80,summarize:!1},e$={maxLines:150,maxChars:15000,keepHead:50,keepTail:50,summarize:!0},$1=[{pattern:/^git\s+(rm|add)\s+(-r|--cached|-rf|-f)?\s*/i,config:N0,summaryTemplate:($)=>`Successfully processed ${$} files`},{pattern:/^(npm|pnpm|yarn|bun)\s+(install|i|add|remove|uninstall)/i,config:N0,summaryTemplate:($)=>`Package operation completed (${$} lines of output)`},{pattern:/^(npm|pnpm|yarn|bun)\s+(run|exec)\s+(build|compile|bundle)/i,config:d,summaryTemplate:($)=>`Build completed (${$} lines of output)`},{pattern:/^(npm|pnpm|yarn|bun)\s+(run|exec)\s+(test|lint|check)/i,config:O$},{pattern:/^git\s+(status|branch|remote)/i,config:d},{pattern:/^git\s+(log|diff|show)/i,config:O$},{pattern:/^(ls|dir|tree)\s+/i,config:d,summaryTemplate:($)=>`Listed ${$} items`},{pattern:/^find\s+/i,config:d,summaryTemplate:($)=>`Found ${$} matches`},{pattern:/^(grep|rg|ag)\s+/i,config:d,summaryTemplate:($)=>`Found ${$} matching lines`},{pattern:/^(docker|podman)\s+(build|pull|push)/i,config:N0,summaryTemplate:($)=>`Docker operation completed (${$} lines)`},{pattern:/^(pip|pip3|poetry|pipenv)\s+(install|uninstall)/i,config:N0,summaryTemplate:($)=>`Python package operation completed (${$} lines)`},{pattern:/^(cargo|rustup)\s+(build|install|update)/i,config:d,summaryTemplate:($)=>`Rust operation completed (${$} lines)`},{pattern:/^(go)\s+(build|get|mod)/i,config:d,summaryTemplate:($)=>`Go operation completed (${$} lines)`}];class g0{static getConfigForCommand($){for(let{pattern:q,config:T,summaryTemplate:G}of $1)if(q.test($))return{config:T,summaryTemplate:G};return{config:e$}}static truncate($,q){let{config:T,summaryTemplate:G}=this.getConfigForCommand(q);return this.truncateWithConfig($,T,G)}static truncateWithConfig($,q,T){let G=$.length,Z=$.split(`
|
|
3
3
|
`),J=Z.length;if(J<=q.maxLines&&G<=q.maxChars)return{content:$,truncated:!1,originalLines:J,originalChars:G};let H=Z.slice(0,q.keepHead),Q=Z.slice(-q.keepTail),L=J-q.keepHead-q.keepTail,O=H.join(`
|
|
4
4
|
`);if(O+=`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{$d as Zn,Ud as rn,Vd as D,Wd as m,ae as Jn}from"./chunk-4vaywb2r.js";import{be as Nn,ce as pn}from"./chunk-qev36qrb.js";import{he as b}from"./chunk-vjpd3nee.js";import{je as Dn,me as H}from"./chunk-a7nbn5kf.js";import{ue as En,ve as fn}from"./chunk-
|
|
1
|
+
import{$d as Zn,Ud as rn,Vd as D,Wd as m,ae as Jn}from"./chunk-4vaywb2r.js";import{be as Nn,ce as pn}from"./chunk-qev36qrb.js";import{he as b}from"./chunk-vjpd3nee.js";import{je as Dn,me as H}from"./chunk-a7nbn5kf.js";import{ue as En,ve as fn}from"./chunk-k89phc5j.js";import{ze as P}from"./chunk-6hj2dk75.js";import{Je as un}from"./chunk-8nm1hqr1.js";var Qn=/^[\x21\x23-\x5b\x5d-\x7e]+$/;function Wn(n){return n==="127.0.0.1"||n==="[::1]"||n.toLowerCase()==="localhost"}function I(n,t="MCP OAuth URL"){let e=new URL(n);if(e.username||e.password)throw Error(`${t} must not contain credentials`);if(e.protocol!=="https:"&&!(e.protocol==="http:"&&Wn(e.hostname)))throw Error(`${t} requires HTTPS; HTTP is allowed only for loopback servers`);return e}var B=async(n,t)=>{I(n,"MCP OAuth request URL");let e=await fetch(n,{...t,redirect:"manual"});if(e.status>=300&&e.status<400)throw await e.body?.cancel(),Error("MCP OAuth network requests must not follow redirects");return e};function q(n){let t=n.oauth;if(!t)return;let e=t;for(let o of["clientSecret","authorizationUrl","tokenUrl","redirectUri"])if(e[o]!==void 0)throw Error(`MCP OAuth "${o}" is not supported; use standards-based discovery`);if(t.enabled!==!0)return{enabled:!1};if(n.type!=="http"&&n.type!=="sse")throw Error("MCP OAuth is supported only for HTTP and SSE transports");if(!n.url)throw Error("MCP OAuth requires an MCP server URL");if(I(n.url,"MCP OAuth server URL"),Object.keys(n.headers??{}).find((o)=>o.toLowerCase()==="authorization"))throw Error("MCP OAuth cannot be combined with a configured Authorization header");let u=t.clientId?.trim();if(u&&u.length>4096)throw Error("MCP OAuth clientId exceeds 4096 characters");let _=t.scopes?.map((o)=>o.trim());if(_){if(_.length>32)throw Error("MCP OAuth supports at most 32 scopes");if(_.some((o)=>!o||o.length>128||!Qn.test(o)))throw Error("MCP OAuth scopes contain an invalid value");if(new Set(_).size!==_.length)throw Error("MCP OAuth scopes must not contain duplicates")}let M=t.callbackPort;if(M!==void 0&&(!Number.isInteger(M)||M<1024||M>65535))throw Error("MCP OAuth callbackPort must be between 1024 and 65535");return{enabled:!0,...u?{clientId:u}:{},..._?.length?{scopes:_}:{},...M!==void 0?{callbackPort:M}:{}}}import{randomUUID as J}from"node:crypto";import it from"node:http";import{auth as on}from"@modelcontextprotocol/sdk/client/auth.js";import St from"open";import{createHash as jn,randomUUID as Fn}from"node:crypto";import{constants as O,promises as A}from"node:fs";import Y from"node:path";import{Mutex as vn}from"async-mutex";import nt from"write-file-atomic";var Mn=1,tt=1048576,et=5000,ut=50,rt=/^[a-f0-9]{64}$/,Mt=m.Object({client_id:m.String({minLength:1,maxLength:4096})},{additionalProperties:!0}),_t=m.Object({access_token:m.String({minLength:1,maxLength:65536}),token_type:m.String({minLength:1,maxLength:64}),expires_in:m.Optional(m.Number({minimum:0})),refresh_token:m.Optional(m.String({minLength:1,maxLength:65536})),scope:m.Optional(m.String({maxLength:16384})),id_token:m.Optional(m.String({minLength:1,maxLength:262144}))},{additionalProperties:!1}),ot=m.Unsafe({type:"object",properties:{authorizationServerUrl:m.String({format:"uri"}),resourceMetadataUrl:m.Optional(m.String({format:"uri"})),resourceMetadata:m.Optional(m.Unknown()),authorizationServerMetadata:m.Optional(m.Unknown())},required:["authorizationServerUrl"],additionalProperties:!1}),_n=m.Object({serverUrl:m.String({format:"uri"}),clientId:m.Optional(m.String({minLength:1,maxLength:4096})),clientInformation:m.Optional(Mt),tokens:m.Optional(_t),tokenExpiresAt:m.Optional(m.Number({minimum:0})),discoveryState:m.Optional(ot),updatedAt:m.String({format:"date-time"})},{additionalProperties:!1}),tn=m.Object({version:m.Literal(Mn),credentials:m.Record(m.String(),_n)},{additionalProperties:!1});function y(n,t){return n instanceof Error&&"code"in n&&n.code===t}function st(n){if(!Number.isInteger(n)||n<=0)return!1;try{return process.kill(n,0),!0}catch(t){return y(t,"EPERM")}}function V(n){return structuredClone(n)}function en(n){if(Object.keys(n.credentials).some((t)=>!rt.test(t)))throw Error("MCP OAuth credential store contains an invalid identity")}function K(n){let t=new URL(n);return t.hash="",t.toString()}function Z(n,t,e=[]){return jn("sha256").update(JSON.stringify({serverUrl:K(n),clientId:t?.trim()||null,scopes:[...e].sort()})).digest("hex")}class x{static mutexes=new Map;stateRoot;tokenFilePath;mutex;constructor(n=un()){this.stateRoot=Y.join(n,"mcp"),this.tokenFilePath=Y.join(this.stateRoot,"oauth-credentials.json");let t=x.mutexes.get(this.tokenFilePath);if(!t)t=new vn,x.mutexes.set(this.tokenFilePath,t);this.mutex=t}async getCredential(n){return this.mutex.runExclusive(async()=>{let e=(await this.readStore()).credentials[n];return e?V(e):null})}async updateCredential(n,t){return this.runMutation(async(e)=>{let r=e.credentials[n],u=await t(r?V(r):null);if(u)e.credentials[n]=D(_n,u);else delete e.credentials[n];return u?V(e.credentials[n]):null})}async deleteCredential(n){await this.updateCredential(n,()=>null)}async listCredentialIds(){return this.mutex.runExclusive(async()=>Object.keys((await this.readStore()).credentials).sort())}async runMutation(n){return this.mutex.runExclusive(async()=>{let t=await this.acquireStoreLock();try{let e=await this.readStore(),r=await n(e);return await this.writeStore(e),r}finally{await t()}})}async ensureStateRoot(){await A.mkdir(this.stateRoot,{recursive:!0,mode:448});let n=await A.lstat(this.stateRoot);if(!n.isDirectory()||n.isSymbolicLink())throw Error("MCP OAuth credential root must be a regular directory");if(process.getuid&&n.uid!==process.getuid())throw Error("MCP OAuth credential root must be owned by the current user");if((n.mode&63)!==0)throw Error("MCP OAuth credential root permissions must not allow group access")}async readStore(){try{let n=await A.lstat(this.tokenFilePath);if(!n.isFile()||n.isSymbolicLink())throw Error("MCP OAuth credential store must be a regular file");if(process.getuid&&n.uid!==process.getuid())throw Error("MCP OAuth credential store must be owned by the current user");if((n.mode&511)!==384)throw Error("MCP OAuth credential store permissions must be 0600");if(n.size>tt)throw Error("MCP OAuth credential store exceeds the 1 MiB limit");let t=JSON.parse(await A.readFile(this.tokenFilePath,"utf8")),e=rn(tn,t);if(!e.success)throw Error("MCP OAuth credential store has an invalid schema");return en(e.data),e.data}catch(n){if(y(n,"ENOENT"))return{version:Mn,credentials:{}};throw n}}async writeStore(n){await this.ensureStateRoot();let t=D(tn,n);en(t),await nt(this.tokenFilePath,`${JSON.stringify(t,null,2)}
|
|
2
2
|
`,{mode:384,encoding:"utf8"}),await A.chmod(this.tokenFilePath,384)}async acquireStoreLock(){await this.ensureStateRoot();let n=Y.join(this.stateRoot,".oauth-credentials.lock"),t=Fn(),e=Date.now()+et;while(Date.now()<e)try{let r=await A.open(n,O.O_CREAT|O.O_EXCL|O.O_WRONLY,384);return await r.writeFile(`${JSON.stringify({version:1,pid:process.pid,token:t,createdAt:new Date().toISOString()})}
|
|
3
3
|
`,"utf8"),await r.close(),async()=>{try{if(JSON.parse(await A.readFile(n,"utf8")).token===t)await A.unlink(n)}catch(u){if(!y(u,"ENOENT"))throw u}}}catch(r){if(!y(r,"EEXIST"))throw r;await this.removeDeadLock(n),await new Promise((u)=>setTimeout(u,ut))}throw Error("MCP OAuth credential store is busy; retry the operation")}async removeDeadLock(n){let t=await A.lstat(n);if(!t.isFile()||t.isSymbolicLink())throw Error("MCP OAuth credential lock must be a regular file");if(process.getuid&&t.uid!==process.getuid()||(t.mode&511)!==384)throw Error("MCP OAuth credential lock ownership or permissions are invalid");let e=JSON.parse(await A.readFile(n,"utf8"));if(typeof e.pid!=="number"||!Number.isInteger(e.pid)||e.pid<=0)throw Error("MCP OAuth credential lock owner is invalid");if(!st(e.pid))await A.unlink(n)}}var sn="127.0.0.1",Sn=7777,mn="/oauth/callback",mt=300000;class Q extends Error{constructor(n){super(`MCP server "${n}" requires OAuth authorization; run "blade mcp login ${n}" or use the Web MCP panel`);this.name="McpOAuthAuthorizationRequiredError"}}class an extends Error{constructor(n){super(`MCP OAuth credentials are unavailable in this runtime for server "${n}"`);this.name="McpOAuthUnavailableError"}}function Et(n){let t=n?"Authentication complete":"Authentication failed";return`<!doctype html>
|
|
4
4
|
<html lang="en">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{te as a,ue as b,ve as c,we as d,xe as e,ye as f}from"./chunk-
|
|
1
|
+
import{te as a,ue as b,ve as c,we as d,xe as e,ye as f}from"./chunk-k89phc5j.js";import"./chunk-mjp61rqd.js";export{b as getVersion,c as getPackageName,a as getPackageInfo,e as getFormattedVersion,d as getDescription,f as getCopyright};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{aa as T,ba as m0,ga as M7,ha as A8,ia as y0}from"./chunk-
|
|
1
|
+
import{aa as T,ba as m0,ga as M7,ha as A8,ia as y0}from"./chunk-ws3gc024.js";import{Aa as O7,Ha as d8,ja as O$,ma as L2,qa as d0,ta as J0,za as p2}from"./chunk-y5vq7gek.js";import{Ia as $9,Ja as Z9,Ka as q6}from"./chunk-88vy9hh0.js";import{Qa as z0,Ra as Q0,Sa as a0,Ta as e2,Ua as Z1,Va as t9,Wa as e9,Xa as h2,Ya as $7,Za as Z7,ab as b7,db as J7,eb as X7,gb as n}from"./chunk-8mepk4tc.js";import{hb as v2,ib as s0,ob as i$,sb as B3,yb as K3}from"./chunk-44wkjs2j.js";import{Jb as t4,Kb as o4}from"./chunk-kq5my0yy.js";import{$b as B0,Wb as A2,Xb as H0,Yb as C,ac as D2,bc as W1,cc as b$,dc as L6,ec as v$,fc as u8,kc as F$}from"./chunk-m9zpxzg2.js";import{lc as g$}from"./chunk-gafbzeyk.js";import{mc as H$}from"./chunk-0h81hxkw.js";import{qc as V7,rc as _2}from"./chunk-af49jmns.js";import{tc as b0,uc as R$}from"./chunk-px5ck9pf.js";import{vc as G7}from"./chunk-fjw32ex5.js";import{xc as n9,yc as r9,zc as a9}from"./chunk-k9a1vb8a.js";import{Ac as T$,Bc as W9,Dc as P0,Ec as N3,Fc as S0,Gc as p0,Hc as U5,Ic as u2,Jc as X$,Kc as a$,Lc as o$,Mc as s9,Nc as p6,Pc as e,Qc as N2,Rc as Y7}from"./chunk-tm2ckreq.js";import{Sc as x7,Uc as o9,Vc as x2,Wc as e4}from"./chunk-d9ddpapp.js";import{Yc as J4,_c as O0}from"./chunk-6sc78810.js";import{$c as i0}from"./chunk-beqaxytd.js";import{dd as u}from"./chunk-jxv6r0c7.js";import{Ad as K8,Bd as Q8,Id as T4,Jd as W7,Kd as l9,Ld as C8,Md as P8,Nd as k8,Od as S8,Pd as v8,Qd as I8,Rd as $0,gd as x4,ld as h4,nd as t6,sd as T7,wd as u4,yd as p9}from"./chunk-bpzv054r.js";import{Ud as i1,Vd as N4,Wd as q,Xd as z9,Yd as R,Zd as d}from"./chunk-4vaywb2r.js";import{ce as u9,de as d9}from"./chunk-qev36qrb.js";import{fe as s1,he as L}from"./chunk-vjpd3nee.js";import{le as c9,me as i9}from"./chunk-a7nbn5kf.js";import{ne as u7,qe as I7}from"./chunk-2beq0syt.js";import{ue as G2}from"./chunk-k89phc5j.js";import{ze as R0}from"./chunk-6hj2dk75.js";import{Ce as X1,Ee as u$,Fe as v0,Ge as U1,He as _4,Ie as T8,Je as M0,Ke as M8}from"./chunk-8nm1hqr1.js";import{Le as c0}from"./chunk-mjp61rqd.js";import{randomUUID as C3}from"crypto";import{mkdir as p1,realpath as t2}from"node:fs/promises";import P$ from"node:path";import{Mutex as L3}from"async-mutex";var A3=new L3,s$,s2;function T3(){return import("@anthropic-ai/sandbox-runtime")}async function O1(){if(s$)return s$;if(!s2)s2=T3();return s$=await s2,s$}var M3={isSupportedPlatform:async()=>(await O1()).SandboxManager.isSupportedPlatform(),checkDependencies:async()=>(await O1()).SandboxManager.checkDependencies(),getDefaultWritePaths:async()=>(await O1()).getDefaultWritePaths(),initialize:async($)=>(await O1()).SandboxManager.initialize($),wrapWithSandboxArgv:async($,Z,J,X,U)=>(await O1()).SandboxManager.wrapWithSandboxArgv($,Z,J,X,U),cleanupAfterCommand:()=>s$?.SandboxManager.cleanupAfterCommand(),reset:async()=>{await s$?.SandboxManager.reset()}};class k$ extends Error{constructor($){super($);this.name="WorkspaceSandboxUnavailableError"}}class t$ extends Error{constructor($){super($);this.name="WorkspaceSandboxBoundaryError"}}class B4{backend;constructor($){this.backend=$}async prepare($){let Z=P$.resolve($.workspaceRoot),J=P$.resolve($.cwd);if(!z0.isWithinWorkspace(J,Z))throw new t$(`Bash cwd is outside the workspace sandbox: ${$.cwd}`);let X,U;try{[X,U]=await Promise.all([t2(Z),t2(J)])}catch(Y){throw new t$(`Workspace sandbox path cannot be resolved: ${Y instanceof Error?Y.message:String(Y)}`)}if(!z0.isWithinWorkspace(U,X))throw new t$(`Bash cwd resolves outside the workspace sandbox: ${$.cwd}`);return this.backend.prepare({...$,cwd:U,workspaceRoot:X})}}class K4{runtime;tempRoot;defaultWritePaths;initialization;constructor($={}){this.runtime=$.runtime??M3,this.tempRoot=$.tempRoot??P$.join(M0(),"sandbox-tmp"),this.defaultWritePaths=$.defaultWritePaths}async prepare($){await this.ensureInitialized();let Z=await this.prepareTempRoot(),J=P$.join(Z,"tmp"),X=P$.join(Z,"cache"),U=P$.join(X,"npm"),Y=P$.join(X,"bun");await Promise.all([p1(J,{recursive:!0}),p1(U,{recursive:!0}),p1(Y,{recursive:!0})]);let z=(this.defaultWritePaths??await this.runtime.getDefaultWritePaths()).filter((K)=>!K.startsWith("/dev/")),H=process.platform==="win32"?"bash":"/bin/bash",V;try{V=await A3.runExclusive(async()=>{let K=process.env.CLAUDE_CODE_TMPDIR;process.env.CLAUDE_CODE_TMPDIR=J;try{return await this.runtime.wrapWithSandboxArgv($.command,H,{filesystem:{denyRead:[],allowRead:[],allowWrite:[$.workspaceRoot,Z],denyWrite:z},git:{safeDirectories:[$.workspaceRoot]}},$.signal,$.cwd)}finally{if(K===void 0)delete process.env.CLAUDE_CODE_TMPDIR;else process.env.CLAUDE_CODE_TMPDIR=K}})}catch(K){if(K instanceof Error&&K.name==="AbortError")throw K;throw new k$(`Workspace sandbox failed to prepare the command: ${K instanceof Error?K.message:String(K)}`)}let B=!1;return{executable:V.argv[0]??H,args:V.argv.slice(1),env:{...V.env,TMPDIR:J,TMP:J,TEMP:J,XDG_CACHE_HOME:X,npm_config_cache:U,BUN_INSTALL_CACHE_DIR:Y},sandboxed:!0,cleanup:()=>{if(B)return;B=!0,this.runtime.cleanupAfterCommand()}}}async dispose(){this.initialization=void 0,await this.runtime.reset()}async ensureInitialized(){if(!this.initialization)this.initialization=this.initializeRuntime().catch(($)=>{throw this.initialization=void 0,$});return this.initialization}async initializeRuntime(){if(!await this.runtime.isSupportedPlatform())throw new k$(`Workspace sandbox is unsupported on ${process.platform}`);let $=await this.runtime.checkDependencies();if($.errors.length>0)throw new k$(`Workspace sandbox dependencies are unavailable: ${$.errors.join("; ")}`);try{await this.runtime.initialize({network:{allowedDomains:["*"],deniedDomains:[],strictAllowlist:!0},filesystem:{denyRead:[],allowRead:[],allowWrite:[],denyWrite:[]},enableWeakerNestedSandbox:!0})}catch(Z){throw new k$(`Workspace sandbox failed to initialize: ${Z instanceof Error?Z.message:String(Z)}`)}}async prepareTempRoot(){return await p1(this.tempRoot,{recursive:!0}),t2(this.tempRoot)}}function c1($,Z){let J=Z.toLowerCase();return $===71&&J.includes("sandbox-exec")||J.includes("sandbox_apply: operation not permitted")||J.includes("bwrap: creating new namespace failed")||J.includes("failed to create new user namespace")||J.includes("srt-win sandbox failed")}var f3=new K4,R3={prepare:($)=>f3.prepare($)},Q4=new B4(R3);class t{static instance=null;processes=new Map;static getInstance(){if(!t.instance)t.instance=new t;return t.instance}startBackgroundProcess($){let Z=`bash_${C3()}`,J={};for(let[H,V]of Object.entries({...process.env,...$.env,...$.sandboxedCommand?.env,BLADE_CLI:"1"}))if(V!==void 0)J[H]=V;let X=$.sandboxedCommand?.executable??"bash",U=$.sandboxedCommand?.args??["-c",$.command],{child:Y,processTree:W}=i0(X,U,{cwd:$.cwd||L(),env:J,stdio:["pipe","pipe","pipe"]}),z={id:Z,command:$.command,sessionId:$.sessionId,cwd:$.cwd,env:$.env,process:Y,processTree:W,pid:Y.pid,status:"running",startTime:Date.now(),pendingStdout:new e2,pendingStderr:new e2,sandboxed:Boolean($.sandboxedCommand)};return Y.stdout?.setEncoding("utf8"),Y.stderr?.setEncoding("utf8"),Y.stdout?.on("data",(H)=>{z.pendingStdout.append(H)}),Y.stderr?.on("data",(H)=>{z.pendingStderr.append(H)}),Y.on("close",(H,V)=>{$.sandboxedCommand?.cleanup();let B=z.sandboxed&&c1(H,z.pendingStderr.peek().content);if(z.status=z.status==="killed"?"killed":B?"error":"exited",z.exitCode=H,z.signal=V,B)z.errorMessage="Workspace sandbox failed to start; command was not executed";z.endTime=Date.now(),z.process=void 0}),Y.on("error",(H)=>{$.sandboxedCommand?.cleanup(),z.status="error",z.errorMessage=H.message,z.endTime=Date.now(),z.process=void 0,z.pendingStderr.append(`
|
|
2
2
|
[error] ${H.message}`)}),this.processes.set(Z,z),z}consumeOutput($,Z){let J=this.getProcess($,Z);if(!J)return;let X=J.pendingStdout.consume(),U=J.pendingStderr.consume();return{id:J.id,command:J.command,status:J.status,stdout:X.content,stderr:U.content,stdoutOmittedBytes:X.omittedBytes,stderrOmittedBytes:U.omittedBytes,exitCode:J.exitCode,signal:J.signal,pid:J.pid,startedAt:J.startTime,endedAt:J.endTime,errorMessage:J.errorMessage,sandboxed:J.sandboxed}}getProcess($,Z){let J=this.processes.get($);return J?.sessionId===Z?J:void 0}listForSession($){return Array.from(this.processes.values()).filter((Z)=>Z.sessionId===$)}async writeInput($,Z,J,X=!1){let U=this.getProcess($,Z);if(!U)return;let Y=U.process?.stdin;if(U.status!=="running"||!Y||Y.destroyed||Y.writableEnded)return{success:!1,status:U.status,bytesWritten:0,stdinClosed:!Y||Y.destroyed||Y.writableEnded,errorMessage:"Shell stdin is not writable"};try{return await new Promise((W,z)=>{let H=(B)=>{Y.off("error",H),z(B)},V=(B)=>{if(Y.off("error",H),B)z(B);else W()};if(Y.once("error",H),X)Y.end(J,V);else Y.write(J,V)}),{success:!0,status:U.status,bytesWritten:Buffer.byteLength(J),stdinClosed:X}}catch(W){return{success:!1,status:U.status,bytesWritten:0,stdinClosed:Y.destroyed||Y.writableEnded,errorMessage:W instanceof Error?W.message:"Failed to write stdin"}}}async kill($,Z){let J=this.getProcess($,Z);if(!J)return;return this.terminateProcess(J)}async killSession($){let Z=this.listForSession($);await Promise.all(Z.map((J)=>this.terminateProcess(J)));for(let J of Z)this.processes.delete(J.id)}async terminateProcess($){if($.status!=="running"||!$.process)return{success:!1,alreadyExited:!0,status:$.status,pid:$.pid,exitCode:$.exitCode,signal:$.signal};$.status="killed",$.endTime=Date.now();let Z=await $.processTree?.terminate();if(!Z?.success)return $.status="error",$.errorMessage="Failed to terminate owned process tree",{success:!1,alreadyExited:Z?.alreadyExited??!1,status:$.status,pid:$.pid,exitCode:$.exitCode,signal:$.signal};return{success:!0,alreadyExited:Z.alreadyExited,status:$.status,pid:$.pid,exitCode:$.exitCode,signal:$.signal}}async killAll(){await Promise.all(Array.from(this.processes.values()).map(($)=>this.terminateProcess($))),this.processes.clear()}}import{stat as iW}from"node:fs/promises";import{Mutex as lW}from"async-mutex";import{nanoid as nW}from"nanoid";import*as U7 from"os";import*as Y0 from"path";import*as x0 from"fs/promises";class S${async readTextFile($){return x0.readFile($,"utf-8")}async writeTextFile($,Z){await x0.writeFile($,Z,"utf-8")}async exists($){try{return await x0.access($),!0}catch{return!1}}async readBinaryFile($){return x0.readFile($)}async stat($){try{let Z=await x0.stat($);return{size:Z.size,isDirectory:Z.isDirectory(),isFile:Z.isFile(),mtime:Z.mtime}}catch{return null}}async mkdir($,Z){await x0.mkdir($,{recursive:Z?.recursive??!1,mode:Z?.mode??493})}}var P3=new S$;function w$(){return P3}var _0=u("Agent");class F1{connection;sessionId;capabilities;fallback;constructor($,Z,J,X=new S$){this.connection=$;this.sessionId=Z;this.capabilities=J;this.fallback=X}async readTextFile($){if(!this.capabilities.readTextFile)return _0.debug(`[AcpFileSystem] readTextFile fallback: ${$}`),this.fallback.readTextFile($);try{return _0.debug(`[AcpFileSystem] readTextFile via ACP: ${$}`),(await this.connection.readTextFile({path:$,sessionId:this.sessionId})).content}catch(Z){throw _0.warn(`[AcpFileSystem] readTextFile ACP failed: ${Z}`),Z}}async writeTextFile($,Z){if(!this.capabilities.writeTextFile)return _0.debug(`[AcpFileSystem] writeTextFile fallback: ${$}`),this.fallback.writeTextFile($,Z);try{_0.debug(`[AcpFileSystem] writeTextFile via ACP: ${$}`),await this.connection.writeTextFile({path:$,content:Z,sessionId:this.sessionId})}catch(J){throw _0.warn(`[AcpFileSystem] writeTextFile ACP failed: ${J}`),J}}async exists($){if(!this.capabilities.readTextFile)return _0.debug(`[AcpFileSystem] exists fallback to local: ${$}`),this.fallback.exists($);try{return await this.connection.readTextFile({path:$,sessionId:this.sessionId}),_0.debug(`[AcpFileSystem] exists(${$}): true (ACP read success)`),!0}catch(Z){let J=String(Z).toLowerCase();if(["not found","no such file","enoent","does not exist","file not found","path not found"].some((W)=>J.includes(W)))return _0.debug(`[AcpFileSystem] exists(${$}): false (ACP: not found)`),!1;let Y=k3(J);return _0.warn(`[AcpFileSystem] exists(${$}): assuming exists due to ${Y} error`,{error:String(Z),errorType:Y,filePath:$}),!0}}async readBinaryFile($){return _0.debug(`[AcpFileSystem] readBinaryFile fallback: ${$}`),this.fallback.readBinaryFile($)}async stat($){return _0.debug(`[AcpFileSystem] stat fallback: ${$}`),this.fallback.stat($)}async mkdir($,Z){return _0.debug(`[AcpFileSystem] mkdir fallback: ${$}`),this.fallback.mkdir($,Z)}getCapabilities(){return this.capabilities}canReadTextFile(){return this.capabilities.readTextFile??!1}canWriteTextFile(){return this.capabilities.writeTextFile??!1}usesRemoteFiles(){return this.canReadTextFile()||this.canWriteTextFile()}}function k3($){if($.includes("permission")||$.includes("access denied"))return"permission";if($.includes("timeout")||$.includes("timed out"))return"timeout";if($.includes("binary")||$.includes("encoding"))return"binary";if($.includes("too large")||$.includes("size"))return"size";if($.includes("connection")||$.includes("network"))return"network";return"unknown"}var l0=u("Agent");class $5{async execute($,Z){return new Promise((J)=>{let X=process.platform==="win32"?"cmd.exe":"/bin/bash",U=process.platform==="win32"?["/c",$]:["-c",$],{child:Y,processTree:W}=i0(X,U,{cwd:Z?.cwd||L(),env:{...process.env,...Z?.env},stdio:["pipe","pipe","pipe"]}),z,H=()=>{return z??=W.terminate(),z},V="",B="",K=!1,Q=Z?.timeout?setTimeout(()=>{K=!0,H()},Z.timeout):null,w=null,E=()=>{if(Q)clearTimeout(Q);if(w&&Z?.signal)Z.signal.removeEventListener("abort",w),w=null};if(Z?.signal){if(w=()=>{K=!0,H()},Z.signal.addEventListener("abort",w),Z.signal.aborted)w()}Y.stdout?.on("data",(O)=>{let F=O.toString();V+=F,Z?.onOutput?.(F)}),Y.stderr?.on("data",(O)=>{let F=O.toString();B+=F,Z?.onOutput?.(F)}),Y.on("close",async(O)=>{if(E(),K)await H();J({success:O===0&&!K,stdout:V,stderr:B,exitCode:O,error:K?"Command was terminated":void 0})}),Y.on("error",(O)=>{E(),J({success:!1,stdout:V,stderr:B,exitCode:null,error:O.message})})})}isAvailable(){return!0}}class q4{connection;sessionId;fallback;constructor($,Z,J=new $5){this.connection=$;this.sessionId=Z;this.fallback=J}async execute($,Z){try{l0.debug(`[AcpTerminal] Executing command via ACP: ${$}`);let J=await this.connection.createTerminal({sessionId:this.sessionId,command:$,cwd:Z?.cwd,env:Z?.env?Object.entries(Z.env).map(([V,B])=>({name:V,value:B})):void 0}),X=0,U=null;if(Z?.onOutput)U=setInterval(async()=>{try{let B=(await J.currentOutput()).output||"";if(B.length>X){let K=B.slice(X);X=B.length,Z.onOutput?.(K)}}catch{}},100);let Y=(V=!1)=>{if(U)clearInterval(U),U=null;(V?J.kill().then(()=>l0.debug("[AcpTerminal] Killed remote command")).catch(()=>{}).then(()=>J.release()).catch(()=>{}):J.release().catch(()=>{})).catch(()=>{})},W=[];if(W.push(J.waitForExit().then((V)=>({type:"completed",exitCode:V.exitCode??null}))),Z?.timeout)W.push(new Promise((V)=>{setTimeout(()=>V({type:"timeout"}),Z.timeout)}));if(Z?.signal)W.push(new Promise((V)=>{if(Z.signal.aborted)V({type:"aborted"});else Z.signal.addEventListener("abort",()=>V({type:"aborted"}),{once:!0})}));let z=await Promise.race(W),H="";try{if(H=(await J.currentOutput()).output||"",Z?.onOutput&&H.length>X)Z.onOutput(H.slice(X))}catch{}switch(z.type){case"completed":return Y(!1),{success:z.exitCode===0,stdout:H,stderr:"",exitCode:z.exitCode};case"timeout":return l0.debug(`[AcpTerminal] Command timed out, killing: ${$}`),Y(!0),{success:!1,stdout:H,stderr:"",exitCode:null,error:"Command timed out"};case"aborted":return l0.debug(`[AcpTerminal] Command aborted, killing: ${$}`),Y(!0),{success:!1,stdout:H,stderr:"",exitCode:null,error:"Command was aborted"}}}catch(J){if(Z?.allowLocalFallback===!1)return{success:!1,stdout:"",stderr:"",exitCode:null,error:J instanceof Error?`ACP terminal unavailable: ${J.message}`:"ACP terminal unavailable"};return l0.warn("[AcpTerminal] ACP terminal failed, using fallback:",J),this.fallback.execute($,Z)}}isAvailable(){return!0}}class I{static sessions=new Map;static currentSessionId=null;constructor(){}static getInstance(){return new I}static initializeSession($,Z,J,X){let U=J?.fs?new F1($,Z,J.fs):new S$;if(J?.fs)l0.debug(`[AcpServiceContext:${Z}] Using ACP file system service`);let Y=new q4($,Z);l0.debug(`[AcpServiceContext:${Z}] Using ACP terminal service`),I.sessions.set(Z,{fileSystemService:U,terminalService:Y,connection:$,clientCapabilities:J||null,cwd:X}),I.currentSessionId=Z,l0.debug(`[AcpServiceContext:${Z}] Initialized with capabilities:`,{fs:!!J?.fs,readTextFile:J?.fs?.readTextFile,writeTextFile:J?.fs?.writeTextFile,cwd:X})}static destroySession($){if(I.sessions.delete($),I.currentSessionId===$){let Z=Array.from(I.sessions.keys());I.currentSessionId=Z[0]||null}l0.debug(`[AcpServiceContext:${$}] Session destroyed`)}static getSessionServices($){return I.sessions.get($)||null}static setCurrentSession($){if(I.sessions.has($))I.currentSessionId=$}static getCurrentSessionId(){return I.currentSessionId}initialize($,Z,J,X){I.initializeSession($,Z,J,X||L())}reset(){if(I.currentSessionId)I.destroySession(I.currentSessionId)}isAcpMode(){return I.currentSessionId!==null}getFileSystemService($){let Z=$??I.currentSessionId;if(Z){let J=I.sessions.get(Z);if(J)return J.fileSystemService}return new S$}getTerminalService($){let Z=$??I.currentSessionId;if(Z){let J=I.sessions.get(Z);if(J)return J.terminalService}return new $5}getConnection(){if(I.currentSessionId){let $=I.sessions.get(I.currentSessionId);if($)return $.connection}return null}getSessionId(){return I.currentSessionId}getClientCapabilities(){if(I.currentSessionId){let $=I.sessions.get(I.currentSessionId);if($)return $.clientCapabilities}return null}async sendToolUpdate($,Z,J,X,U){let Y=I.currentSessionId;if(!Y)return;let W=I.sessions.get(Y);if(!W)return;try{await W.connection.sessionUpdate({sessionId:Y,update:{sessionUpdate:"tool_call",toolCallId:$,status:Z,title:J,content:X||[],kind:U||"other"}})}catch(z){l0.warn("[AcpServiceContext] Failed to send tool update:",z)}}}function E$($){return I.getInstance().getFileSystemService($)}function w4($){return I.getInstance().getTerminalService($)}function r($){return $?I.getSessionServices($)!==null:I.getInstance().isAcpMode()}import*as n0 from"node:fs/promises";import*as b4 from"node:path";import{Mutex as S3}from"async-mutex";import{nanoid as v3}from"nanoid";import I3 from"write-file-atomic";var E4=["active","paused","blocked","usage_limited","budget_limited","complete"];var O4=1048576,Z5=1e5,F4=q.Object({version:q.Literal(1),sessionId:q.String({minLength:1}),goalId:q.String({minLength:1}),objective:q.String({minLength:1,maxLength:Z5}),status:d(E4),tokenBudget:q.Optional(q.Integer({minimum:1})),tokensUsed:q.Integer({minimum:0}),timeUsedSeconds:q.Integer({minimum:0}),continuationCount:q.Integer({minimum:0}),statusReason:q.Optional(q.String()),createdAt:q.String({format:"date-time"}),updatedAt:q.String({format:"date-time"})});function G4($,Z){return $ instanceof Error&&"code"in $&&$.code===Z}function D4($){let Z=$.trim();if(!Z)throw Error("Goal objective must not be empty");if(Z.length>Z5)throw Error(`Goal objective exceeds ${Z5} characters`);return Z}function y3($){if($===void 0)return;if(!Number.isInteger($)||$<=0)throw Error("Goal token budget must be a positive integer");return $}class f0{workspaceRoot;sessionId;static mutexes=new Map;static listeners=new Set;filePath;mutex;constructor($,Z){this.workspaceRoot=$;this.sessionId=Z;this.filePath=_4($,Z);let J=f0.mutexes.get(this.filePath);if(!J)J=new S3,f0.mutexes.set(this.filePath,J);this.mutex=J}static subscribe($){return this.listeners.add($),()=>this.listeners.delete($)}static async hasActiveGoal($,Z){return(await new f0($,Z).get())?.status==="active"}async get(){return this.mutex.runExclusive(()=>this.readUnlocked())}async create($){return this.mutex.runExclusive(async()=>{let Z=await this.readUnlocked();if(Z&&Z.status!=="complete")throw Error(`Session already has an unfinished goal (${Z.status}); clear or complete it first`);let J=new Date().toISOString(),X=y3($.tokenBudget),U={version:1,sessionId:this.sessionId,goalId:v3(12),objective:D4($.objective),status:"active",...X===void 0?{}:{tokenBudget:X},tokensUsed:0,timeUsedSeconds:0,continuationCount:0,createdAt:J,updatedAt:J};return await this.persistUnlocked(U),this.emit(U),U})}async edit($){return this.updateExisting((Z)=>{if(!["active","paused","blocked"].includes(Z.status))throw Error(`Cannot edit goal while status is ${Z.status}`);return{...Z,objective:D4($),updatedAt:new Date().toISOString()}})}async pause($="paused by user"){return this.updateExisting((Z)=>{if(Z.status!=="active"&&Z.status!=="blocked")throw Error(`Cannot pause goal while status is ${Z.status}`);return{...Z,status:"paused",statusReason:$,updatedAt:new Date().toISOString()}})}async pauseIfActive($){return this.mutex.runExclusive(async()=>{let Z=await this.readUnlocked();if(!Z||Z.status!=="active")return Z;let J={...Z,status:"paused",statusReason:$,updatedAt:new Date().toISOString()};return await this.persistUnlocked(J),this.emit(J),J})}async resume(){return this.updateExisting(($)=>{if($.status!=="paused"&&$.status!=="blocked")throw Error(`Cannot resume goal while status is ${$.status}`);return{...$,status:"active",statusReason:void 0,updatedAt:new Date().toISOString()}})}async complete(){return this.updateExisting(($)=>{if(!["active","paused","blocked"].includes($.status))throw Error(`Cannot complete goal while status is ${$.status}`);return{...$,status:"complete",statusReason:void 0,updatedAt:new Date().toISOString()}})}async block($){return this.updateExisting((Z)=>{if(Z.status!=="active")throw Error(`Cannot block goal while status is ${Z.status}`);let J=$.trim();if(!J)throw Error("Blocked goal requires a reason");return{...Z,status:"blocked",statusReason:J,updatedAt:new Date().toISOString()}})}async recordProgress($){return this.mutex.runExclusive(async()=>{let Z=await this.readUnlocked();if(!Z||Z.status!=="active")return Z;let J=Math.max(0,Math.round($.tokens)),X=Math.max(0,Math.round($.elapsedMs/1000)),U=Z.tokensUsed+J,Y=Z.tokenBudget!==void 0&&U>=Z.tokenBudget,W={...Z,tokensUsed:U,timeUsedSeconds:Z.timeUsedSeconds+X,status:Y?"budget_limited":Z.status,statusReason:Y?"token budget exhausted":Z.statusReason,updatedAt:new Date().toISOString()};return await this.persistUnlocked(W),this.emit(W),W})}async beginContinuation(){return this.updateExisting(($)=>{if($.status!=="active")throw Error(`Cannot continue goal while status is ${$.status}`);return{...$,continuationCount:$.continuationCount+1,updatedAt:new Date().toISOString()}})}async tryBeginContinuation(){return this.mutex.runExclusive(async()=>{let $=await this.readUnlocked();if(!$||$.status!=="active")return null;let Z={...$,continuationCount:$.continuationCount+1,updatedAt:new Date().toISOString()};return await this.persistUnlocked(Z),this.emit(Z),Z})}async clear(){return this.mutex.runExclusive(async()=>{try{await n0.unlink(this.filePath)}catch($){if(G4($,"ENOENT"))return!1;throw $}return this.emit(null),!0})}async updateExisting($){return this.mutex.runExclusive(async()=>{let Z=await this.readUnlocked();if(!Z)throw Error("Session has no goal");let J=N4(F4,$(Z));return await this.persistUnlocked(J),this.emit(J),J})}async readUnlocked(){try{if((await n0.stat(this.filePath)).size>O4)throw Error(`Goal state exceeds ${O4} bytes`);await n0.chmod(this.filePath,384);let Z=i1(F4,JSON.parse(await n0.readFile(this.filePath,"utf8")));if(!Z.success||Z.data.sessionId!==this.sessionId)throw Error(`Invalid goal state: ${this.filePath}`);return Z.data}catch($){if(G4($,"ENOENT"))return null;if($ instanceof SyntaxError)throw Error(`Invalid goal state JSON: ${this.filePath}`,{cause:$});throw $}}async persistUnlocked($){await n0.mkdir(b4.dirname(this.filePath),{recursive:!0,mode:448}),await I3(this.filePath,`${JSON.stringify($)}
|
|
3
3
|
`,{encoding:"utf8",mode:384,fsync:!0})}emit($){let Z={workspaceRoot:this.workspaceRoot,sessionId:this.sessionId,goal:$?{...$}:null};for(let J of f0.listeners)try{J(Z)}catch{}}}import{createHash as x3}from"node:crypto";import{promises as l1,realpathSync as h3}from"node:fs";import i from"node:path";import{fileURLToPath as u3,pathToFileURL as J$}from"node:url";var j4=u("Service"),L4=65536;class J5{name;onCrash;child;processTree;connection;closePromise;crashCleanup;capabilities;initialized=!1;stopping=!1;notificationHandlers=new Map;requestHandlers=new Map;constructor($,Z){this.name=$;this.onCrash=Z}get serverCapabilities(){return this.capabilities}get isInitialized(){return this.initialized}async start($){if(await this.crashCleanup,this.crashCleanup=void 0,this.connection)return;let Z=await import("vscode-jsonrpc/node.js"),{child:J,processTree:X}=i0($.command,[...$.args],{cwd:$.cwd,env:{...$.environment,PATH:$.environment.PATH??process.env.PATH??"",HOME:$.environment.HOME??process.env.HOME??"",USER:$.environment.USER??process.env.USER??"",SHELL:$.environment.SHELL??process.env.SHELL??"/bin/sh",BLADE_CLI:"1"},stdio:["pipe","pipe","pipe"]},{releaseOnExit:!1});this.child=J,this.processTree=X;try{if(await new Promise((W,z)=>{let H=()=>{J.removeListener("spawn",V),J.removeListener("error",B)},V=()=>{H(),W()},B=(K)=>{H(),z(K)};J.once("spawn",V),J.once("error",B)}),!J.stdout||!J.stdin)throw Error("LSP server stdio is unavailable");let U="";J.stderr?.setEncoding("utf8"),J.stderr?.on("data",(W)=>{if(U.length<L4)U+=W.slice(0,L4-U.length)}),J.stdin.on("error",(W)=>{if(!this.stopping)j4.debug(`[LSP ${this.name}] stdin closed: ${W.message}`)}),this.closePromise=new Promise((W)=>{J.once("close",(z,H)=>{this.initialized=!1;let V=!this.stopping;if(!this.stopping){let B=U.trim()?`: ${U.trim().slice(0,512)}`:H?` (${H})`:"";this.onCrash(Error(`LSP server "${this.name}" exited with code ${z}${B}`))}if(this.child===J){let B=this.processTree;try{this.connection?.dispose()}catch{}if(this.connection=void 0,this.child=void 0,this.closePromise=void 0,V&&B)this.crashCleanup=B.terminate().then(()=>{return}),this.processTree=void 0}W()})});let Y=Z.createMessageConnection(new Z.StreamMessageReader(J.stdout),new Z.StreamMessageWriter(J.stdin));this.connection=Y,Y.onError(([W])=>{if(!this.stopping)j4.warn(`[LSP ${this.name}] connection error: ${W.message}`)}),Y.onClose(()=>{this.initialized=!1});for(let[W,z]of this.notificationHandlers)for(let H of z)Y.onNotification(W,H);for(let[W,z]of this.requestHandlers)Y.onRequest(W,z);Y.listen()}catch(U){throw await this.disposeTransport(),U}}async initialize($,Z,J){let X=await this.request("initialize",$,Z,J,!1);return this.capabilities=X.capabilities,await this.notify("initialized",{}),this.initialized=!0,X}async request($,Z,J,X,U=!0){let Y=this.connection;if(!Y)throw Error(`LSP server "${this.name}" is not started`);if(U&&!this.initialized)throw Error(`LSP server "${this.name}" is not initialized`);let z=new(await import("vscode-jsonrpc/node.js")).CancellationTokenSource;return this.awaitRequest(Y.sendRequest($,Z,z.token),z,J,X,$)}async notify($,Z){if(!this.connection)throw Error(`LSP server "${this.name}" is not started`);await this.connection.sendNotification($,Z)}onNotification($,Z){let J=this.notificationHandlers.get($)??[];J.push(Z),this.notificationHandlers.set($,J),this.connection?.onNotification($,Z)}onRequest($,Z){this.requestHandlers.set($,Z),this.connection?.onRequest($,Z)}async stop($){if(!this.child&&!this.connection){await this.crashCleanup,this.crashCleanup=void 0;return}this.stopping=!0;let Z=this.connection;try{if(Z&&this.initialized){let X=new(await import("vscode-jsonrpc/node.js")).CancellationTokenSource;await this.awaitRequest(Z.sendRequest("shutdown",X.token),X,$,void 0,"shutdown").catch(()=>{return}),await Z.sendNotification("exit").catch(()=>{return})}await Promise.race([this.closePromise??Promise.resolve(),new Promise((J)=>setTimeout(J,Math.min($,500)))])}finally{await this.disposeTransport(),this.stopping=!1,this.initialized=!1,this.capabilities=void 0}}awaitRequest($,Z,J,X,U){return new Promise((Y,W)=>{let z=!1,H=(K)=>{if(z)return;z=!0,clearTimeout(B),X?.removeEventListener("abort",V),K()},V=()=>{Z.cancel(),H(()=>W(Error(`LSP request "${U}" was aborted`)))},B=setTimeout(()=>{Z.cancel(),H(()=>W(Error(`LSP request "${U}" timed out after ${J}ms`)))},J);if(X?.addEventListener("abort",V,{once:!0}),X?.aborted)V();$.then((K)=>H(()=>Y(K)),(K)=>H(()=>W(K)))})}async disposeTransport(){let $=this.connection,Z=this.processTree;this.connection=void 0,this.processTree=void 0,this.child=void 0,this.closePromise=void 0;try{$?.dispose()}catch{}await Z?.terminate(),await this.crashCleanup,this.crashCleanup=void 0}}var d3=u("Service"),m3=10485760,g3=10,A4=30,p3=-32801;class X5{options;workspaceRoot;servers=new Map;diagnostics=new Map;delivered=new Map;waiters=new Map;disposeController=new AbortController;diagnosticSequence=0;disposed=!1;constructor($){this.options=$;let Z=i.resolve($.workspaceRoot);try{this.workspaceRoot=h3.native(Z)}catch{this.workspaceRoot=Z}for(let[J,X]of Object.entries($.servers)){if(X.enabled===!1)continue;let U={name:J,config:structuredClone(X),state:"stopped",restartCount:0,openedFiles:new Map,client:new J5(J,(Y)=>{U.state="error",U.lastError=Y.message,U.openedFiles.clear()})};U.client.onNotification("textDocument/publishDiagnostics",(Y)=>{this.captureDiagnostics(J,Y)}),U.client.onRequest("workspace/configuration",(Y)=>this.resolveWorkspaceConfiguration(X.settings,Y)),U.client.onRequest("workspace/workspaceFolders",()=>[{uri:J$(this.workspaceRoot).href,name:i.basename(this.workspaceRoot)}]),U.client.onRequest("window/workDoneProgress/create",()=>null),this.servers.set(J,U)}}get available(){return this.servers.size>0&&!this.isRemoteSession()&&!this.disposed}get workspacePath(){return this.workspaceRoot}getStatus(){return[...this.servers.values()].map(($)=>({name:$.name,state:$.state,restartCount:$.restartCount,extensions:Object.keys($.config.extensionToLanguage).sort(),...$.lastError?{lastError:$.lastError}:{}})).sort(($,Z)=>$.name.localeCompare(Z.name))}async afterToolUse($,Z,J,X){if(!this.available||this.disposed)return;let U;if(J.success&&($==="Write"||$==="Edit")&&typeof Z.file_path==="string")U=await this.syncAfterWrite(Z.file_path,X.signal);else if(J.success&&$==="ApplyPatch"){let Y=Array.isArray(J.metadata?.changes)?J.metadata.changes:[];for(let W of Y){if(!W||typeof W!=="object"||!("path"in W)||typeof W.path!=="string")continue;if("newContent"in W&&W.newContent===null)await this.syncAfterDelete(W.path);else U=await this.syncAfterWrite(W.path,X.signal)??U}}this.attachPendingDiagnostics(J,U)}async query($,Z){if(!this.available)throw Error(this.isRemoteSession()?"LSP is unavailable for ACP-owned remote files":"No LSP servers are configured for this Session");let J=await this.resolveFile($.filePath);if($.operation==="diagnostics")return{operation:$.operation,filePath:J,result:this.getCurrentDiagnostics(J)};let X=await this.ensureFileOpen(J,void 0,Z);if(!X)throw Error(`No LSP server handles ${i.extname(J)||"this file"}`);let U={line:Math.max(0,($.line??1)-1),character:Math.max(0,($.character??1)-1)},Y={uri:J$(J).href},W={goToDefinition:{method:"textDocument/definition",params:{textDocument:Y,position:U}},findReferences:{method:"textDocument/references",params:{textDocument:Y,position:U,context:{includeDeclaration:!0}}},hover:{method:"textDocument/hover",params:{textDocument:Y,position:U}},documentSymbol:{method:"textDocument/documentSymbol",params:{textDocument:Y}},workspaceSymbol:{method:"workspace/symbol",params:{query:$.query??""}},goToImplementation:{method:"textDocument/implementation",params:{textDocument:Y,position:U}},prepareCallHierarchy:{method:"textDocument/prepareCallHierarchy",params:{textDocument:Y,position:U}}},z;if($.operation==="incomingCalls"||$.operation==="outgoingCalls"){let V=(await this.requestWithRetry(X,"textDocument/prepareCallHierarchy",{textDocument:Y,position:U},Z))?.[0];z=V?await this.requestWithRetry(X,$.operation==="incomingCalls"?"callHierarchy/incomingCalls":"callHierarchy/outgoingCalls",{item:V},Z):[]}else{let H=W[$.operation];z=await this.requestWithRetry(X,H.method,H.params,Z)}return{operation:$.operation,filePath:J,serverName:X.name,result:z}}async dispose(){if(this.disposed)return;this.disposed=!0,this.disposeController.abort();for(let $ of this.waiters.values())for(let Z of $)clearTimeout(Z.timer),Z.resolve();this.waiters.clear(),await Promise.allSettled([...this.servers.values()].map(async($)=>{$.state="stopping",await $.client.stop($.config.shutdownTimeout??2000),$.state="stopped",$.openedFiles.clear()})),this.diagnostics.clear(),this.delivered.clear()}isRemoteSession(){return this.options.isRemoteSession?.()??r(this.options.sessionId)}selectServer($){let Z=i.extname($).toLowerCase();return[...this.servers.values()].filter((J)=>(Z in J.config.extensionToLanguage)).sort((J,X)=>(X.config.priority??0)-(J.config.priority??0)||J.name.localeCompare(X.name))[0]}async ensureFileOpen($,Z,J){let X=this.selectServer($);if(!X)return;await this.ensureStarted(X,J);let U=J$($).href;if(X.openedFiles.has(U))return X;let Y=Z??await this.readBoundedFile($);return await X.client.notify("textDocument/didOpen",{textDocument:{uri:U,languageId:X.config.extensionToLanguage[i.extname($).toLowerCase()],version:1,text:Y}}),X.openedFiles.set(U,1),X}async syncAfterWrite($,Z){try{let J=await this.resolveFile($),X=await this.readBoundedFile(J),U=await this.ensureFileOpen(J,X,Z);if(!U)return;let Y=J$(J).href,W=this.diagnostics.get(Y)?.sequence??0;this.delivered.delete(Y);let z=U.openedFiles.get(Y)??0;if(z>0){let H=z+1;await U.client.notify("textDocument/didChange",{textDocument:{uri:Y,version:H},contentChanges:[{text:X}]}),U.openedFiles.set(Y,H)}return await U.client.notify("textDocument/didSave",{textDocument:{uri:Y},text:X}),await this.waitForDiagnostics(Y,W,U.config.diagnosticWaitTimeout??750,Z),J}catch(J){if(!Z?.aborted&&!this.disposeController.signal.aborted)d3.debug(`[LSP] post-edit sync skipped: ${J instanceof Error?J.message:String(J)}`);return}}async syncAfterDelete($){let Z=await this.resolveMissingFile($).catch(()=>{return});if(!Z)return;if(!this.isInsideWorkspace(Z))return;let J=J$(Z).href;for(let X of this.servers.values()){if(!X.openedFiles.has(J))continue;await X.client.notify("textDocument/didClose",{textDocument:{uri:J}}).catch(()=>{return}),X.openedFiles.delete(J)}this.diagnostics.delete(J),this.delivered.delete(J)}async ensureStarted($,Z){if($.state==="running")return;if($.startPromise)return $.startPromise;if($.state==="error"){if($.restartCount>=($.config.maxRestarts??3))throw Error(`LSP server "${$.name}" exceeded its restart limit`);$.restartCount++}let J=this.startServer($,Z).finally(()=>{$.startPromise=void 0});return $.startPromise=J,J}async startServer($,Z){$.state="starting";try{await $.client.start({command:$.config.command,args:$.config.args??[],cwd:this.workspaceRoot,environment:{...this.options.environment,...$.config.env,BLADE_SESSION_ID:this.options.sessionId}});let J=J$(this.workspaceRoot).href,X={processId:process.pid,rootPath:this.workspaceRoot,rootUri:J,workspaceFolders:[{uri:J,name:i.basename(this.workspaceRoot)}],initializationOptions:$.config.initializationOptions??{},capabilities:{workspace:{configuration:!0,workspaceFolders:!0,symbol:{dynamicRegistration:!1}},textDocument:{synchronization:{dynamicRegistration:!1,willSave:!1,willSaveWaitUntil:!1,didSave:!0},publishDiagnostics:{relatedInformation:!0,versionSupport:!1},hover:{dynamicRegistration:!1,contentFormat:["markdown","plaintext"]},definition:{dynamicRegistration:!1,linkSupport:!0},references:{dynamicRegistration:!1},implementation:{dynamicRegistration:!1,linkSupport:!0},documentSymbol:{dynamicRegistration:!1,hierarchicalDocumentSymbolSupport:!0},callHierarchy:{dynamicRegistration:!1}},general:{positionEncodings:["utf-16"]}}};if(await $.client.initialize(X,$.config.startupTimeout??1e4,Z),$.config.settings!==void 0)await $.client.notify("workspace/didChangeConfiguration",{settings:$.config.settings});$.state="running",$.lastError=void 0}catch(J){throw $.state="error",$.lastError=J instanceof Error?J.message:String(J),await $.client.stop($.config.shutdownTimeout??2000).catch(()=>{return}),J}}async requestWithRetry($,Z,J,X){let U;for(let Y=0;Y<4;Y++)try{return await $.client.request(Z,J,$.config.requestTimeout??1e4,X)}catch(W){if(U=W,W.code!==p3||Y===3)break;await new Promise((z)=>setTimeout(z,100*2**Y))}throw U}captureDiagnostics($,Z){if(this.disposed||!Z||typeof Z!=="object"||!("uri"in Z)||!("diagnostics"in Z))return;let J=Z;if(!Array.isArray(J.diagnostics))return;let X;try{X=J.uri.startsWith("file:")?u3(J.uri):i.resolve(J.uri)}catch{return}if(!this.isInsideWorkspace(X))return;let U=J$(i.resolve(X)).href,Y={sequence:++this.diagnosticSequence,serverName:$,filePath:i.resolve(X),diagnostics:J.diagnostics.filter((H)=>H&&typeof H.message==="string"&&H.range!==void 0).slice(0,100).map((H)=>structuredClone(H))};this.diagnostics.set(U,Y);let W=this.waiters.get(U)??[],z=[];for(let H of W)if(Y.sequence>H.afterSequence)clearTimeout(H.timer),H.resolve();else z.push(H);if(z.length>0)this.waiters.set(U,z);else this.waiters.delete(U)}waitForDiagnostics($,Z,J,X){if(J===0||(this.diagnostics.get($)?.sequence??0)>Z)return Promise.resolve();return new Promise((U)=>{let Y=!1,W,z=()=>{if(Y)return;Y=!0,clearTimeout(W.timer),X?.removeEventListener("abort",z);let B=(this.waiters.get($)??[]).filter((K)=>K!==W);if(B.length>0)this.waiters.set($,B);else this.waiters.delete($);U()},H=setTimeout(z,J);W={afterSequence:Z,resolve:z,timer:H};let V=this.waiters.get($)??[];if(V.push(W),this.waiters.set($,V),X?.addEventListener("abort",z,{once:!0}),X?.aborted)z()})}attachPendingDiagnostics($,Z){let J=[...this.diagnostics.values()].sort((z,H)=>{if(Z){if(z.filePath===Z&&H.filePath!==Z)return-1;if(H.filePath===Z&&z.filePath!==Z)return 1}return H.sequence-z.sequence}),X=[],U=[],Y=0;for(let z of J){let H=J$(z.filePath).href,V=this.delivered.get(H)??new Set,B=z.diagnostics.sort((Q,w)=>(Q.severity??4)-(w.severity??4)).filter((Q)=>!V.has(this.diagnosticKey(Q))).slice(0,Math.min(g3,A4-Y));if(B.length===0)continue;let K=i.relative(this.workspaceRoot,z.filePath);X.push(`${K}:`);for(let Q of B){let w=Q.range.start.line+1,E=Q.range.start.character+1,O=["Error","Warning","Info","Hint"][(Q.severity??1)-1],F=Q.message.replace(/\s+/g," ").slice(0,500);X.push(` ${O??"Error"} ${w}:${E} ${F}`+(Q.code!==void 0?` [${String(Q.code)}]`:"")),V.add(this.diagnosticKey(Q)),U.push({file:K,line:w,character:E,severity:O??"Error",message:F,server:z.serverName}),Y++}if(this.delivered.set(H,V),Y>=A4)break}if(X.length===0)return;let W=typeof $.llmContent==="string"?$.llmContent:JSON.stringify($.llmContent);$.llmContent=`${W}
|
|
4
4
|
|
|
@@ -653,7 +653,7 @@ ${k}
|
|
|
653
653
|
</approved-plan>
|
|
654
654
|
|
|
655
655
|
IMPORTANT: Execute according to the approved plan above. Follow the steps exactly as specified.`;if(typeof K==="string")m=K+p;else m=[...K,{type:"text",text:p}]}A=yield*this.runLoop(m,Q,{...j,inputMessageId:void 0})}if(!this.sessionRuntime||!b)return A;if(A.success&&!Q.signal?.aborted)await this.sessionRuntime.acknowledgeTurn(b);let P=await this.sessionRuntime.recordGoalProgress({tokens:A.metadata?.tokensUsed??0,elapsedMs:A.metadata?.duration??0});if(P)yield{kind:"goal_updated",goal:P};if(!A.success||Q.signal?.aborted){if(P=await this.sessionRuntime.pauseActiveGoal(Q.signal?.aborted?"goal paused after user cancellation":A.error?.message??"goal paused after turn failure"),P)yield{kind:"goal_updated",goal:P}}let M=A.success&&!Q.signal?.aborted&&D<20;if(G=await this.sessionRuntime.finishTurn(b,{continuePending:M}),G){D++,w=!0,E=!1,O=null,K="",F=void 0,yield{kind:"follow_up_started",queued:this.sessionRuntime.getPendingSteeringCount(),recovered:this.sessionRuntime.getRecoveredSteeringCount(),messages:N()};continue}if(!A.success||Q.signal?.aborted)return A;if(P=await this.sessionRuntime.getGoal(),!P||P.status!=="active")return A;if(O=await this.sessionRuntime.beginGoalContinuation(),!O)return A;G=this.sessionRuntime.beginTurn(),w=!1,E=!0,K=R5(O),F=void 0,yield{kind:"goal_continuation_started",goal:O,continuation:O.continuationCount},yield{kind:"goal_updated",goal:O}}}finally{if(this.sessionRuntime&&G)await this.sessionRuntime.finishTurn(G)}}let H=typeof W==="string"?W:W.filter((K)=>K.type==="text").map((K)=>K.text).join(`
|
|
656
|
-
`),V={id:this.generateTaskId(),type:"simple",prompt:H};return{success:!0,finalMessage:(await this.executeTask(V)).content,metadata:{turnsCount:1,toolCallsCount:0,duration:0}}}async chat($,Z,J){let{drainLoop:X}=await import("./chunk-
|
|
656
|
+
`),V={id:this.generateTaskId(),type:"simple",prompt:H};return{success:!0,finalMessage:(await this.executeTask(V)).content,metadata:{turnsCount:1,toolCallsCount:0,duration:0}}}async chat($,Z,J){let{drainLoop:X}=await import("./chunk-z2yzyr9h.js");return X(this.chatStream($,Z,J))}async*runPlanLoop($,Z,J){y.debug("Processing Plan mode message...");let{prompt:X}=await I$({projectPath:Z.workspaceRoot||L(),mode:"plan",includeEnvironment:!0,language:this.config.language,availableSkills:this.agentResources?.skills.generateAvailableSkillsList(),communicationStyle:this.sessionRuntime?.getCommunicationStyleConfiguration().selection,communicationStyleCatalog:this.sessionRuntime?.getCommunicationStyleCatalog(),projectRuleCatalog:this.sessionRuntime?.getProjectRuleCatalog(),projectInstructionSourcePath:this.sessionRuntime?.projectRoot}),U;if(typeof $==="string")U=_1($);else{let Y=$.filter((W)=>W.type==="text");if(Y.length>0){let W=Y[0];U=$.map((z)=>z===W?{type:"text",text:_1(W.text)}:z)}else U=[{type:"text",text:_1("")},...$]}return yield*this.executeLoop(U,Z,J,X)}async*runLoop($,Z,J){y.debug("Processing enhanced chat message...");let X=Z.systemPrompt??await this.buildSystemPromptOnDemand(Z.workspaceRoot||L());return yield*this.executeLoop($,Z,J,X)}async buildSystemPromptOnDemand($){let Z=this.runtimeOptions.systemPrompt,J=this.runtimeOptions.appendSystemPrompt;return(await I$({projectPath:$,replaceDefault:Z,append:J,includeEnvironment:!0,language:this.config.language,availableSkills:this.agentResources?.skills.generateAvailableSkillsList(),communicationStyle:this.sessionRuntime?.getCommunicationStyleConfiguration().selection,communicationStyleCatalog:this.sessionRuntime?.getCommunicationStyleCatalog(),projectRuleCatalog:this.sessionRuntime?.getProjectRuleCatalog(),projectInstructionSourcePath:this.sessionRuntime?.projectRoot})).prompt}executeLoop($,Z,J,X){if(!this.isInitialized)throw Error("Agent未初始化");let U=this.buildLoopDependencies();return d8(U,$,Z,J,X)}buildLoopDependencies(){return{chatService:this.chatService,toolExecutor:this.toolExecutor,executionEngine:this.executionEngine,config:this.config,runtimeOptions:this.runtimeOptions,currentModelMaxContextTokens:this.currentModelMaxContextTokens,activeSkillContext:this.activeSkillContext,onSkillActivated:($)=>{this.activeSkillContext=$,y.debug(`Skill "${$.skillName}" activated`+($.allowedTools?` with allowed tools: ${$.allowedTools.join(", ")}`:""))},onModelSwitch:($)=>this.switchModelIfNeeded($),applySkillToolRestrictions:($)=>this.applySkillToolRestrictions($),staticProjectRules:this.sessionRuntime?.getStaticProjectRules(),hydrateProjectRules:this.sessionRuntime?($)=>this.sessionRuntime.hydrateProjectRules($):void 0,resolveContextualProjectRules:this.sessionRuntime?($,Z,J,X)=>this.sessionRuntime.resolveContextualProjectRules($,Z,J,X):void 0}}async chatWithSystem($,Z){if(!this.isInitialized)throw Error("Agent未初始化");let J=[{role:"system",content:$},{role:"user",content:Z}];return(await this.chatService.chat(J)).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.toolExecutor?this.toolExecutor.getRegistry().getAll():[]}getToolRegistry(){return this.toolExecutor.getRegistry()}applyToolWhitelist($){let Z=this.toolExecutor.getRegistry(),X=Z.getAll().filter((U)=>!$.includes(U.name));for(let U of X)Z.unregister(U.name);y.debug(`Applied tool whitelist: ${$.join(", ")} (removed ${X.length} tools)`)}applyToolBlacklist($){let Z=this.toolExecutor.getRegistry(),J=new Set($);for(let X of Z.getAll())if(J.has(X.name))Z.unregister(X.name);y.debug(`Applied tool blacklist: ${$.join(", ")}`)}getToolStats(){let $=this.getAvailableTools(),Z=new Map;return $.forEach((J)=>{let X=Z.get(J.kind)||0;Z.set(J.kind,X+1)}),{totalTools:$.length,toolsByKind:Object.fromEntries(Z),toolNames:$.map((J)=>J.name)}}async destroy(){this.log("销毁Agent...");try{await this.legacyMcpRegistry?.disconnectAll(),this.legacyMcpRegistry=void 0,this.log("Agent已销毁")}catch($){throw this.error("Agent销毁失败",$),$}finally{this.toolExecutor.dispose(),this.isInitialized=!1}}syncRuntimeState(){if(!this.sessionRuntime)return;this.chatService=this.sessionRuntime.getChatService(),this.executionEngine=this.sessionRuntime.getExecutionEngine(),this.attachmentCollector=this.sessionRuntime.getAttachmentCollector(),this.currentModelId=this.sessionRuntime.getCurrentModelId(),this.currentModelMaxContextTokens=this.sessionRuntime.getCurrentModelMaxContextTokens()}generateTaskId(){return`task_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}log($,Z){y.debug(`[MainAgent] ${$}`,Z||"")}error($,Z){y.error(`[MainAgent] ${$}`,Z||"")}async initializeSystemPrompt(){try{let $=this.runtimeOptions.systemPrompt,Z=this.runtimeOptions.appendSystemPrompt,J=await I$({projectPath:this.sessionRuntime?.workspaceRoot??L(),replaceDefault:$,append:Z,includeEnvironment:!1,language:this.config.language,availableSkills:this.agentResources?.skills.generateAvailableSkillsList(),communicationStyle:this.sessionRuntime?.getCommunicationStyleConfiguration().selection,communicationStyleCatalog:this.sessionRuntime?.getCommunicationStyleCatalog(),projectRuleCatalog:this.sessionRuntime?.getProjectRuleCatalog(),projectInstructionSourcePath:this.sessionRuntime?.projectRoot});if(J.prompt)this.log("系统提示配置验证成功"),y.debug(`[SystemPrompt] 可用来源: ${J.sources.filter((X)=>X.loaded).map((X)=>X.name).join(", ")}`)}catch($){this.error("系统提示配置验证失败",$)}}async registerBuiltinTools(){try{let $=await b2({sessionId:"default",configDir:g8.join(m8.homedir(),".blade"),workspaceRoot:L(),resourceRoot:L(),agentResources:this.agentResources});y.debug(`Registering ${$.length} builtin tools...`),this.toolExecutor.getRegistry().registerAll($);let Z=this.toolExecutor.getRegistry().getAll().length;y.debug(`Builtin tools registered: ${Z} tools`),y.debug(`[Tools] ${this.toolExecutor.getRegistry().getAll().map((J)=>J.name).join(", ")}`),await this.registerMcpTools()}catch($){throw y.error("Failed to register builtin tools:",$),$}}async registerMcpTools(){try{let $=await t1({workspaceRoot:L(),storeServers:this.config.mcpServers??{},cliConfigs:this.runtimeOptions.mcpConfig,strictCliConfig:this.runtimeOptions.strictMcpConfig});if(Object.keys($).length===0){y.debug("No MCP servers configured");return}let Z=y0.createIsolated({artifactWriter:new D1(`legacy-${rU()}`)});this.legacyMcpRegistry=Z;for(let[Y,W]of Object.entries($))try{y.debug(`Connecting to MCP server: ${Y}`),await Z.registerServer(Y,W),y.debug(`MCP server "${Y}" connected`)}catch(z){y.warn(`Warning: MCP server "${Y}" connection failed:`,z)}let J=this.toolExecutor.getRegistry();J.setMcpCatalogBarrier(()=>Z.waitForCatalogIdle());let X=Z.getCatalogSnapshot();J.replaceMcpTools(X.tools),J.registerAll(A1(Z));let U=Z.getInstructionsSnapshot();if(J.queueMcpInstructionsChange({revision:U.revision,reason:"snapshot",replace:!0,instructions:U.instructions,removed:[]}),Z.on("catalogChanged",(Y)=>{J.replaceMcpTools(Y.tools,Y)}),Z.on("contentCatalogChanged",(Y)=>{J.queueMcpContentChange(Y)}),Z.on("resourceUpdated",(Y)=>{J.queueMcpResourceUpdated(Y)}),Z.on("connectionLifecycleChanged",(Y)=>{J.queueMcpConnectionChange(Y)}),Z.on("log",(Y)=>{J.queueMcpLog(Y)}),Z.on("instructionsChanged",(Y)=>{J.queueMcpInstructionsChange({revision:Y.revision,reason:Y.reason,replace:!1,instructions:Y.action==="added"&&Y.instruction?[{serverName:Y.serverName,...Y.instruction}]:[],removed:Y.action==="removed"?[Y.serverName]:[]})}),X.tools.length>0)y.debug(`Registered ${X.tools.length} MCP tools`),y.debug(`[MCP Tools] ${X.tools.map((Y)=>Y.name).join(", ")}`)}catch($){y.warn("Failed to register MCP tools:",$)}}async loadSubagents(){let $=await e(L());if(this.agentResources=N2($),this.subagentRegistry=this.agentResources.subagents,this.runtimeOptions.agents?.length)this.subagentRegistry.applyOverrides(this.runtimeOptions.agents);let Z=this.subagentRegistry.getAllNames().length;if(Z>0)y.debug(`Loaded ${Z} subagents: ${this.subagentRegistry.getAllNames().join(", ")}`);else y.debug("No subagents configured")}applySkillToolRestrictions($){if(!this.activeSkillContext?.allowedTools)return $;let Z=this.activeSkillContext.allowedTools;y.debug(`Applying Skill tool restrictions: ${Z.join(", ")}`);let J=$.filter((X)=>{return Z.some((U)=>{if(U===X.name)return!0;let Y=U.match(/^(\w+)\(.*\)$/);if(Y&&Y[1]===X.name)return!0;return!1})});return y.debug(`Filtered tools: ${J.map((X)=>X.name).join(", ")} (${J.length}/${$.length})`),J}clearSkillContext(){if(this.activeSkillContext)y.debug(`Skill "${this.activeSkillContext.skillName}" deactivated`),this.activeSkillContext=void 0}async processAtMentionsForContent($){if(!this.attachmentCollector)return $;if(typeof $==="string")return this.processAtMentions($);let Z=[];for(let X of $)if(X.type==="text")Z.push(X.text);if(Z.length===0)return $;let J=Z.join(`
|
|
657
657
|
`);try{let X=await this.attachmentCollector.collect(J);if(X.length===0)return $;y.debug(`Processed ${X.length} @ file mentions in multimodal message`);let U=this.buildAttachmentText(X);if(!U)return $;return[...$,{type:"text",text:U}]}catch(X){return y.error("Failed to process @ mentions in multimodal message:",X),$}}buildAttachmentText($){let Z=[],J=[];for(let U of $)if(U.type==="file"){let Y=U.metadata?.lineRange?` (lines ${U.metadata.lineRange.start}${U.metadata.lineRange.end?`-${U.metadata.lineRange.end}`:""})`:"";Z.push(`<file path="${U.path}"${Y?` range="${Y}"`:""}>`,U.content,"</file>")}else if(U.type==="directory")Z.push(`<directory path="${U.path}">`,U.content,"</directory>");else if(U.type==="error")J.push(`- @${U.path}: ${U.error}`);let X="";if(Z.length>0)X+=`
|
|
658
658
|
|
|
659
659
|
<system-reminder>
|
|
@@ -1447,7 +1447,7 @@ ${J}
|
|
|
1447
1447
|
`)),{success:!0,message:`Installed ${U.pluginName}`}}return C().addAssistantMessage(`安装失败: ${U.error}`),{success:!1,error:U.error}}async function cH($,Z){let J=r2(Z),X=J.positional[0];if(!X)return C().addAssistantMessage("请指定插件名称: `/plugins uninstall <name> --confirm`"),{success:!1,error:"Plugin name required"};if(!J.confirm){let Y=`卸载 ${X} 需要显式确认,请添加 \`--confirm\``;return C().addAssistantMessage(Y),{success:!1,error:"Plugin uninstall confirmation required"}}let{result:U}=await r6($.getWorkspaceRoot(),X,J.confirm);if(U.success)return C().addAssistantMessage(`[OK] 已卸载插件: ${U.pluginName}`),{success:!0,message:`Uninstalled ${U.pluginName}`};return C().addAssistantMessage(`卸载失败: ${U.error}`),{success:!1,error:U.error}}async function iH($,Z){let J=r2(Z),X=J.positional[0];if(!X)return C().addAssistantMessage("请指定插件名称: `/plugins update <name> --trust`"),{success:!1,error:"Plugin name required"};if(!J.trust){let Y=`更新会执行 ${X} 的新代码,确认来源后使用 \`--trust\` 重试`;return C().addAssistantMessage(Y),{success:!1,error:"Plugin source trust required"}}C().addAssistantMessage(`正在更新插件: ${X}...`);let{result:U}=await n6($.getWorkspaceRoot(),X,{trusted:J.trust});if(U.success){let Y=[U.changed?"[OK] 插件更新成功!":"[OK] 插件已是最新版本","",`**名称**: ${U.pluginName}`,`**提交**: \`${U.installation?.revision??"local"}\``];if(U.manifest)Y.push(`**版本**: ${U.manifest.version}`);if(U.updatedDependencies?.length)Y.push(`**依赖更新**: ${U.updatedDependencies.join(", ")}`);return C().addAssistantMessage(Y.join(`
|
|
1448
1448
|
`)),{success:!0,message:`Updated ${U.pluginName}`}}return C().addAssistantMessage(`更新失败: ${U.error}`),{success:!1,error:U.error}}function q1($,Z){let J=$.indexOf(Z);if(J>=0)return $[J+1];let X=`${Z}=`;return $.find((U)=>U.startsWith(X))?.slice(X.length)}function z3($,Z){if($===void 0)return;if($==="true"||$==="on"||$==="1")return!0;if($==="false"||$==="off"||$==="0")return!1;throw Error(`${Z} must be true or false`)}function W4($){if($===void 0)return;return[...new Set($.split(",").map((Z)=>Z.trim()).filter(Boolean))]}function H3($){return["## Plugin Source Policy","",`- Restrict sources: ${$.restrictToAllowedSources?"on":"off"}`,`- Require full Git SHA: ${$.requireGitCommitSha?"on":"off"}`,`- Git hosts: ${$.allowedGitHosts.join(", ")||"(none)"}`,`- Marketplaces: ${$.allowedMarketplaces.join(", ")||"(none)"}`,`- Local roots: ${$.allowedLocalRoots.join(", ")||"(none)"}`].join(`
|
|
1449
1449
|
`)}async function lH($,Z){let J=Z[0]?.toLowerCase()??"show";if(J==="show"||J==="status"){let X=H3($.getSourcePolicy());return C().addAssistantMessage(X),{success:!0,message:X}}if(J!=="set"){let X="Usage: /plugins policy set [--restrict true] [--require-sha true] [--hosts host,...] [--marketplaces name,...] [--local-roots /path,...] [--scope global|project|local]";return C().addAssistantMessage(X),{success:!1,error:X}}try{let X=$.getSourcePolicy(),U=z3(q1(Z,"--restrict"),"--restrict"),Y=z3(q1(Z,"--require-sha"),"--require-sha"),W=W4(q1(Z,"--hosts")),z=W4(q1(Z,"--marketplaces")),H=W4(q1(Z,"--local-roots"));if(U===void 0&&Y===void 0&&W===void 0&&z===void 0&&H===void 0)throw Error("No plugin policy fields were provided");let V=q1(Z,"--scope")??"global",B=z4([V]),K=await i6($.getWorkspaceRoot(),{...X,...U===void 0?{}:{restrictToAllowedSources:U},...Y===void 0?{}:{requireGitCommitSha:Y},...W===void 0?{}:{allowedGitHosts:W},...z===void 0?{}:{allowedMarketplaces:z},...H===void 0?{}:{allowedLocalRoots:H}},B),Q=H3(K);return C().addAssistantMessage(Q),{success:!0,message:Q}}catch(X){let U=X instanceof Error?X.message:String(X);return C().addAssistantMessage(`Plugin policy update failed: ${U}`),{success:!1,error:U}}}async function nH($,Z){let J=Z[0]?.toLowerCase()??"list",X=r2(Z.slice(1));try{if(J==="list"||J==="ls"){let U=await p0().listCatalogs(),Y=U.length===0?["没有已配置的 Plugin Marketplace。"]:["## Plugin Marketplaces","",...U.flatMap(({marketplace:W,manifest:z})=>[`- **${W.name}** · ${z.plugins.length} plugins`,` ${z.description??z.metadata?.description??""}`,` revision: \`${W.revision}\``])];return C().addAssistantMessage(Y.join(`
|
|
1450
|
-
`)),{success:!0,message:"Marketplaces listed"}}if(J==="add"){let U=X.positional[0];if(!U)throw Error("Usage: /plugins marketplace add <source> [--ref <ref>]");let Y=await a6($.getWorkspaceRoot(),U,X.ref);if(!Y.success)throw Error(Y.error);let W=`[OK] 已添加 Marketplace ${Y.marketplace?.name}(${Y.manifest?.plugins.length??0} 个插件)`;return C().addAssistantMessage(W),{success:!0,message:W}}if(J==="update"||J==="refresh"){let U=X.positional[0],Y=U?[U]:(await p0().listMarketplaces()).map((H)=>H.name);if(Y.length===0)return C().addAssistantMessage("没有可更新的 Marketplace"),{success:!0,message:"没有可更新的 Marketplace"};let W=[];for(let H of Y){let V=await o6($.getWorkspaceRoot(),H);if(!V.success)throw Error(V.error);W.push(`${H}${V.changed?"":" (unchanged)"}`)}let z=`[OK] Marketplace 已更新: ${W.join(", ")}`;return C().addAssistantMessage(z),{success:!0,message:z}}if(J==="remove"||J==="rm"){let U=X.positional[0];if(!U)throw Error("Usage: /plugins marketplace remove <name> --confirm");if(!X.confirm)throw Error(`移除 Marketplace ${U} 需要 --confirm`);let Y=await s6(U,!0);if(!Y.success)throw Error(Y.error);let W=`[OK] 已移除 Marketplace: ${U}`;return C().addAssistantMessage(W),{success:!0,message:W}}throw Error("Usage: /plugins marketplace <add|list|update|remove> [args]")}catch(U){let Y=U instanceof Error?U.message:String(U);return C().addAssistantMessage(`Marketplace 操作失败: ${Y}`),{success:!1,error:Y}}}var V3=vH;import*as w1 from"node:fs/promises";import*as E1 from"node:path";async function Q3($,Z={}){let{maxResults:J=20,caseSensitive:X=!1,projectPath:U,storagePath:Y}=Z,W=Y??X1(U??L());if(!Y){let Q=await rH($,U??L(),J,X);if(Q)return Q}let z;try{z=(await w1.readdir(W)).filter((w)=>w.endsWith(".jsonl")&&!w.startsWith("agent_")).map((w)=>E1.join(W,w))}catch{return[]}let V=(await Promise.all(z.map(async(Q)=>{try{let w=await w1.stat(Q);return{path:Q,mtime:w.mtimeMs}}catch{return null}}))).filter((Q)=>Q!==null).sort((Q,w)=>w.mtime-Q.mtime).map((Q)=>Q.path),B=[],K=X?$:$.toLowerCase();for(let Q of V){if(B.length>=J)break;let w=E1.basename(Q,".jsonl"),E=await aH(Q,K,X,w);if(B.push(...E),B.length>=J){B.length=J;break}}return B}async function rH($,Z,J,X){try{let{syncAll:U}=await import("./chunk-jv4nkkb5.js"),Y=await B3();if(!Y)return null;let{SessionService:W}=await import("./chunk-
|
|
1450
|
+
`)),{success:!0,message:"Marketplaces listed"}}if(J==="add"){let U=X.positional[0];if(!U)throw Error("Usage: /plugins marketplace add <source> [--ref <ref>]");let Y=await a6($.getWorkspaceRoot(),U,X.ref);if(!Y.success)throw Error(Y.error);let W=`[OK] 已添加 Marketplace ${Y.marketplace?.name}(${Y.manifest?.plugins.length??0} 个插件)`;return C().addAssistantMessage(W),{success:!0,message:W}}if(J==="update"||J==="refresh"){let U=X.positional[0],Y=U?[U]:(await p0().listMarketplaces()).map((H)=>H.name);if(Y.length===0)return C().addAssistantMessage("没有可更新的 Marketplace"),{success:!0,message:"没有可更新的 Marketplace"};let W=[];for(let H of Y){let V=await o6($.getWorkspaceRoot(),H);if(!V.success)throw Error(V.error);W.push(`${H}${V.changed?"":" (unchanged)"}`)}let z=`[OK] Marketplace 已更新: ${W.join(", ")}`;return C().addAssistantMessage(z),{success:!0,message:z}}if(J==="remove"||J==="rm"){let U=X.positional[0];if(!U)throw Error("Usage: /plugins marketplace remove <name> --confirm");if(!X.confirm)throw Error(`移除 Marketplace ${U} 需要 --confirm`);let Y=await s6(U,!0);if(!Y.success)throw Error(Y.error);let W=`[OK] 已移除 Marketplace: ${U}`;return C().addAssistantMessage(W),{success:!0,message:W}}throw Error("Usage: /plugins marketplace <add|list|update|remove> [args]")}catch(U){let Y=U instanceof Error?U.message:String(U);return C().addAssistantMessage(`Marketplace 操作失败: ${Y}`),{success:!1,error:Y}}}var V3=vH;import*as w1 from"node:fs/promises";import*as E1 from"node:path";async function Q3($,Z={}){let{maxResults:J=20,caseSensitive:X=!1,projectPath:U,storagePath:Y}=Z,W=Y??X1(U??L());if(!Y){let Q=await rH($,U??L(),J,X);if(Q)return Q}let z;try{z=(await w1.readdir(W)).filter((w)=>w.endsWith(".jsonl")&&!w.startsWith("agent_")).map((w)=>E1.join(W,w))}catch{return[]}let V=(await Promise.all(z.map(async(Q)=>{try{let w=await w1.stat(Q);return{path:Q,mtime:w.mtimeMs}}catch{return null}}))).filter((Q)=>Q!==null).sort((Q,w)=>w.mtime-Q.mtime).map((Q)=>Q.path),B=[],K=X?$:$.toLowerCase();for(let Q of V){if(B.length>=J)break;let w=E1.basename(Q,".jsonl"),E=await aH(Q,K,X,w);if(B.push(...E),B.length>=J){B.length=J;break}}return B}async function rH($,Z,J,X){try{let{syncAll:U}=await import("./chunk-jv4nkkb5.js"),Y=await B3();if(!Y)return null;let{SessionService:W}=await import("./chunk-nqq4sbmv.js");await U(Y,W.projectionDeriverForSearch());let z=E1.resolve(Z),H=K3(Y,$,z,J*4),V=X?$:$.toLowerCase(),B=[];for(let K of H){if(K.role!=="user"&&K.role!=="assistant")continue;let Q=H4(K.text,V,X,K.session_id,K.role,K.timestamp??void 0,0);if(Q)B.push(Q);if(B.length>=J)break}return B}catch{return null}}async function aH($,Z,J,X){try{let U=await w1.readFile($,"utf8"),W=U.split(`
|
|
1451
1451
|
`).flatMap((K,Q)=>{if(!K.trim())return[];try{return[{event:JSON.parse(K),index:Q}]}catch{return[]}});if(!W.some(({event:K})=>K.type==="session_created"))return oH(W,Z,J,X);let H=new Map(W.flatMap(({event:K,index:Q})=>typeof K.id==="string"?[[K.id,Q+1]]:[])),V=i$(v2(U,$)),B=new Map;for(let K of V){if(K.type==="message_created"&&(K.data.role==="user"||K.data.role==="assistant"))B.set(K.data.messageId,{role:K.data.role,content:[],timestamp:K.timestamp,lineNumber:H.get(K.id)??0});if(K.type==="part_created"&&K.data.partType==="text"){let Q=B.get(K.data.messageId),w=K.data.payload.text;if(Q&&typeof w==="string")Q.content.push(w)}}return[...B.values()].flatMap((K)=>{let Q=H4(K.content.join(" "),Z,J,X,K.role,K.timestamp,K.lineNumber);return Q?[Q]:[]})}catch{return[]}}function oH($,Z,J,X){return $.flatMap(({event:U,index:Y})=>{if(U.type!=="message")return[];let W=U.message;if(W?.role!=="user"&&W?.role!=="assistant"||!W.content)return[];let z=typeof W.content==="string"?W.content:Array.isArray(W.content)?W.content.filter((V)=>typeof V==="object"&&V!==null&&V.type==="text"&&typeof V.text==="string").map((V)=>V.text).join(" "):"",H=H4(z,Z,J,X,W.role,typeof U.timestamp==="string"?U.timestamp:void 0,Y+1);return H?[H]:[]})}function H4($,Z,J,X,U,Y,W){if(!$)return;let z=J?$:$.toLowerCase();if(!z.includes(Z))return;let H=z.indexOf(Z),V=Math.max(0,H-80),B=Math.min($.length,H+Z.length+80);return{sessionId:X,role:U,content:(V>0?"...":"")+$.slice(V,B).replace(/\n/g," ")+(B<$.length?"...":""),timestamp:Y,lineNumber:W}}function q3($){if($.length===0)return"没有找到匹配的历史记录";let Z=[`**找到 ${$.length} 条匹配:**
|
|
1452
1452
|
`];for(let J of $){let X=J.timestamp?new Date(J.timestamp).toLocaleString("zh-CN",{timeZone:"Asia/Shanghai"}):"?",U=J.role==="user"?"\uD83D\uDC64":"\uD83E\uDD16";Z.push(`${U} \`${J.sessionId.slice(0,8)}\` (${X})`),Z.push(` ${J.content}`),Z.push("")}return Z.join(`
|
|
1453
1453
|
`)}var sH={name:"search",description:"Search past session transcripts",fullDescription:"搜索历史会话记录,查找过去的对话内容",usage:"/search <keyword>",aliases:["find","history"],category:"Session",examples:['/search 断路器 - 搜索包含"断路器"的历史对话',"/search edit tool - 搜索 edit tool 相关讨论"],async handler($,Z){let J=v(Z);if($.length===0)return J.sendMessage("**用法:** `/search <关键词>`\n\n在历史会话中搜索包含指定关键词的对话"),{success:!0,message:"显示帮助"};let X=$.join(" ");J.sendMessage(`正在搜索: "${X}" ...`);try{let U=await Q3(X,{maxResults:15,projectPath:Z.cwd}),Y=q3(U);return J.sendMessage(Y),{success:!0,message:`found ${U.length} results`,data:{matches:U.length}}}catch(U){let Y=U instanceof Error?U.message:"未知错误";return J.sendMessage(`搜索失败: ${Y}`),{success:!1,error:Y}}}},w3=sH;var tH={name:"skills",description:"查看所有可用的 Skills",fullDescription:"显示所有已发现的 Skills 及其详细信息,包括名称、描述、来源和允许的工具。",usage:"/skills",category:"system",examples:["/skills"],handler:async($,Z)=>{try{return await P0({cwd:Z.workspaceRoot??Z.cwd}).refresh(),o$(Z.workspaceRoot??Z.cwd),await a$(Z.workspaceRoot??Z.cwd),{success:!0,message:"show_skills_manager",data:{action:"show_skills_manager"}}}catch(J){let X=`获取 Skills 失败: ${J instanceof Error?J.message:"未知错误"}`;return C().addAssistantMessage(X),{success:!1,error:X}}}},E3=tH;import eH from"node:path";function a2($){if($<1000)return`${$}ms`;let Z=Math.floor($/1000);if(Z<60)return`${Z}s`;let J=Math.floor(Z/60);if(J<60)return`${J}m ${Z%60}s`;return`${Math.floor(J/60)}h ${J%60}m`}function O3($){switch($){case"running":return"[RUNNING]";case"completed":case"exited":return"[OK]";case"failed":case"error":return"[FAIL]";case"killed":case"cancelled":return"[STOPPED]";default:return"[?]"}}function F3($,Z){if($.length<=Z)return $;return $.slice(0,Z-3)+"..."}async function $V($,Z){let J=v(Z),X=$[0],U=t.getInstance(),Y=s.getInstance(),W=Z.sessionId??"",z=Z.sessionId?{sessionId:Z.sessionId,projectPath:eH.resolve(Z.workspaceRoot??Z.cwd)}:void 0;if(X==="resume"){let w=$[1],E=$.slice(2).join(" ").trim();if(!w||!E)return{success:!1,error:"Usage: /tasks resume <agentId> <prompt>"};if(!Z.subagents)return{success:!1,error:"This surface does not own a subagent runtime"};let O=await Z.subagents.resume(w,E),F=`Resumed \`${w}\` as \`${O.session.id}\` (depth ${O.session.resumeDepth}).`;return J.sendMessage(F),{success:!0,message:F,data:{action:"subagent_resumed",sourceAgentId:w,subagent:O.session}}}if(X==="clean"){let w=Y.cleanupExpiredSessionsForParent(z??W,0);return J.sendMessage(`已清理 ${w} 个已完成的 Agent 会话`),{success:!0,message:`Cleaned ${w} agent sessions`}}let H=[`**后台任务列表**
|