blade-code 0.0.32 → 0.0.34

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 CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import{createRequire as FQ}from"node:module";var UQ=Object.create;var{getPrototypeOf:HQ,defineProperty:M$,getOwnPropertyNames:K7,getOwnPropertyDescriptor:OQ}=Object,G7=Object.prototype.hasOwnProperty;var E0=($,Y,Z)=>{Z=$!=null?UQ(HQ($)):{};let X=Y||!$||!$.__esModule?M$(Z,"default",{value:$,enumerable:!0}):Z;for(let Q of K7($))if(!G7.call(X,Q))M$(X,Q,{get:()=>$[Q],enumerable:!0});return X},q7=new WeakMap,zQ=($)=>{var Y=q7.get($),Z;if(Y)return Y;if(Y=M$({},"__esModule",{value:!0}),$&&typeof $==="object"||typeof $==="function")K7($).map((X)=>!G7.call(Y,X)&&M$(Y,X,{get:()=>$[X],enumerable:!(Z=OQ($,X))||Z.enumerable}));return q7.set($,Y),Y};var W7=($,Y)=>{for(var Z in Y)M$($,Z,{get:Y[Z],enumerable:!0,configurable:!0,set:(X)=>Y[Z]=()=>X})};var R=($,Y)=>()=>($&&(Y=$($=0)),Y);var S1=FQ(import.meta.url);var I$;var U7=R(()=>{I$={name:"blade-code",version:"0.0.32",private:!1,description:"🗡️ Blade Code - 智能代码助手命令行工具",type:"module",bin:{blade:"dist/blade.js"},files:["dist","bin","vendor/ripgrep/**","config.env.example","README.md","CHANGELOG.md"],scripts:{dev:"bun --watch src/blade.tsx",build:"rm -rf dist && bun run scripts/build.ts",start:"bun run dist/blade.js",test:"node scripts/test.js","test:all":"vitest run --config vitest.config.ts","test:unit":"node scripts/test.js unit","test:integration":"node scripts/test.js integration","test:cli":"node scripts/test.js cli","test:coverage":"node scripts/test.js all --coverage","test:unit:coverage":"node scripts/test.js unit --coverage","test:integration:coverage":"node scripts/test.js integration --coverage","test:cli:coverage":"node scripts/test.js cli --coverage","test:watch":"vitest --watch --config vitest.config.ts","test:unit:watch":"vitest --watch --config vitest.config.ts --project unit","test:integration:watch":"vitest --watch --config vitest.config.ts --project integration","test:cli:watch":"vitest --watch --config vitest.config.ts --project cli","test:debug":"node scripts/test.js all --debug","test:verbose":"node scripts/test.js all --verbose","test:ci":"vitest run --config vitest.config.ts --coverage --reporter=verbose","test:performance":'vitest --testNamePattern="performance" --verbose',lint:"biome lint src tests","lint:fix":"biome lint --write src tests",format:"biome format --write src tests","format:check":"biome format src tests",check:"biome check src tests","check:fix":"biome check --write src tests","type-check":"tsc --noEmit","check:full":"npm run type-check && npm run lint && npm run format:check && npm run test:ci","security:audit":"pnpm audit","security:test":"bash scripts/run-security-tests.sh","vendor:ripgrep":"node scripts/download-ripgrep.js","vendor:ripgrep:clean":"rm -rf vendor/ripgrep/darwin-* vendor/ripgrep/linux-* vendor/ripgrep/win32-*",release:"node scripts/release.js","release:dry":"node scripts/release.js --dry-run","release:major":"node scripts/release.js --major","release:minor":"node scripts/release.js --minor","release:patch":"node scripts/release.js --patch",clean:"rm -rf dist node_modules/.cache coverage",prepare:"bun run build",preflight:"npm run clean && pnpm install && npm run format && npm run lint && npm run build && npm run type-check && npm run test:ci"},keywords:["cli","blade","ai","assistant","agent","llm","tool","qwen","volcengine","smart-tools","code-review","documentation","git-tools"],author:"echoVic",license:"MIT",repository:{type:"git",url:"git+https://github.com/echoVic/blade-code.git"},homepage:"https://github.com/echoVic/blade-code",bugs:{url:"https://github.com/echoVic/blade-code/issues"},engines:{node:">=16.0.0"},devDependencies:{"@biomejs/biome":"^2.2.4","@testing-library/react":"^16.2.0","@testing-library/user-event":"^14.5.0","@types/bun":"^1.3.4","@types/diff":"^8.0.0","@types/inquirer":"^9.0.8","@types/json-schema":"^7.0.15","@types/lodash-es":"^4.17.12","@types/node":"^22.15.24","@types/picomatch":"^4.0.2","@types/react":"^19.1.12","@types/react-dom":"^19.1.9","@types/semver":"^7.7.1","@types/uuid":"^10.0.0","@types/write-file-atomic":"^4.0.3","@types/ws":"^8.5.12","@types/yargs":"^17.0.33","@vitest/coverage-v8":"^3.0.0",execa:"^9.6.0",jsdom:"^26.0.0","ts-node":"^10.9.2",typescript:"^5.9.2",vitest:"^3.0.0"},optionalDependencies:{"@vscode/ripgrep":"^1.17.0"},dependencies:{"@agentclientprotocol/sdk":"^0.12.0","@inkjs/ui":"^2.0.0","@modelcontextprotocol/sdk":"^1.17.4",ahooks:"^3.9.5","async-mutex":"^0.5.0",axios:"^1.12.2",chalk:"^5.4.1",diff:"^8.0.2","fast-glob":"^3.3.3","fuse.js":"^7.1.0",glob:"^11.0.3",ink:"^6.4.0","ink-big-text":"^2.0.0","ink-gradient":"^3.0.0","ink-progress-bar":"^3.0.0","ink-select-input":"^6.2.0","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0",inquirer:"^12.6.3","js-tiktoken":"^1.0.21","lodash-es":"^4.17.21",lowlight:"^3.3.0","lru-cache":"^11.2.4",nanoid:"^5.1.6",openai:"^6.2.0",picomatch:"^4.0.3",pino:"^10.1.0","pino-pretty":"^13.1.3",react:"^19.1.1","react-dom":"^19.1.1",semver:"^7.7.3","string-width":"^8.1.0",undici:"^7.16.0","write-file-atomic":"^7.0.0",ws:"^8.18.0",yaml:"^2.8.1",yargs:"^18.0.0",zod:"^3.24.2","zod-to-json-schema":"^3.24.6",zustand:"^5.0.9"}}});function f2(){return I$.version}function H7(){return I$.name}function O7(){return I$.description}function z7(){return`v${I$.version} © 2025 Blade Code`}var k$=R(()=>{U7()});var s1=()=>{};var h2;var k4=R(()=>{s1();h2={currentModelId:"",models:[],temperature:0,maxContextTokens:128000,maxOutputTokens:32768,stream:!0,topP:0.9,topK:50,timeout:180000,theme:"GitHub",language:"zh-CN",fontSize:14,debug:!1,mcpEnabled:!1,mcpServers:{},permissions:{allow:["Bash(pwd)","Bash(which *)","Bash(whoami)","Bash(hostname)","Bash(uname *)","Bash(date)","Bash(echo *)","Bash(ls *)","Bash(tree *)","Bash(git status)","Bash(git log *)","Bash(git diff *)","Bash(git branch *)","Bash(git show *)","Bash(git remote *)","Bash(npm list *)","Bash(npm view *)","Bash(npm outdated *)","Bash(pnpm list *)","Bash(yarn list *)","Bash(pip list *)","Bash(pip show *)"],ask:["Bash(curl *)","Bash(wget *)","Bash(aria2c *)","Bash(axel *)","Bash(rm -rf *)","Bash(rm -r *)","Bash(rm --recursive *)","Bash(nc *)","Bash(netcat *)","Bash(telnet *)","Bash(ncat *)"],deny:["Read(./.env)","Read(./.env.*)","Bash(rm -rf /)","Bash(rm -rf /*)","Bash(sudo *)","Bash(chmod 777 *)","Bash(bash *)","Bash(sh *)","Bash(zsh *)","Bash(fish *)","Bash(dash *)","Bash(eval *)","Bash(source *)","Bash(mkfs *)","Bash(fdisk *)","Bash(dd *)","Bash(format *)","Bash(parted *)","Bash(open http*)","Bash(open https*)","Bash(xdg-open http*)","Bash(xdg-open https*)"]},permissionMode:"default",hooks:{enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],Stop:[]},env:{},disableAllHooks:!1,maxTurns:-1}});import{promises as W6}from"fs";import{merge as _7}from"lodash-es";import B7 from"os";import x2 from"path";class m1{static instance=null;constructor(){}static getInstance(){if(!m1.instance)m1.instance=new m1;return m1.instance}static resetInstance(){m1.instance=null}async initialize(){try{let $=await this.loadConfigFiles(),Y=await this.loadSettingsFiles(),Z={...h2,...$,...Y};if(this.resolveEnvInterpolation(Z),await this.ensureGitIgnore(Z.debug),Z.debug)console.log("[ConfigManager] Configuration loaded successfully");return Z}catch($){return console.error("[ConfigManager] Failed to initialize:",$),h2}}async loadConfigFiles(){let $=x2.join(B7.homedir(),".blade","config.json"),Y=x2.join(process.cwd(),".blade","config.json"),Z={},X=await this.loadJsonFile($);if(X)Z={...Z,...X};let Q=await this.loadJsonFile(Y);if(Q){let J={...Z.mcpServers||{},...Q.mcpServers||{}};if(Z={...Z,...Q},Object.keys(J).length>0)Z.mcpServers=J}return Z}async loadSettingsFiles(){let $=x2.join(B7.homedir(),".blade","settings.json"),Y=x2.join(process.cwd(),".blade","settings.json"),Z=x2.join(process.cwd(),".blade","settings.local.json"),X={},Q=await this.loadJsonFile($);if(Q)X=this.mergeSettings(X,Q);let J=await this.loadJsonFile(Y);if(J)X=this.mergeSettings(X,J);let q=await this.loadJsonFile(Z);if(q)X=this.mergeSettings(X,q);return X}mergeSettings($,Y){let Z=JSON.parse(JSON.stringify($));if(Y.permissions){if(!Z.permissions)Z.permissions={allow:[],ask:[],deny:[]};if(Y.permissions.allow){let X=[...Z.permissions.allow||[],...Y.permissions.allow];Z.permissions.allow=Array.from(new Set(X))}if(Y.permissions.ask){let X=[...Z.permissions.ask||[],...Y.permissions.ask];Z.permissions.ask=Array.from(new Set(X))}if(Y.permissions.deny){let X=[...Z.permissions.deny||[],...Y.permissions.deny];Z.permissions.deny=Array.from(new Set(X))}}if(Y.hooks)Z.hooks=_7({},Z.hooks,Y.hooks);if(Y.env)Z.env=_7({},Z.env,Y.env);if(Y.mcpServers)Z.mcpServers={...Z.mcpServers||{},...Y.mcpServers};if(Y.disableAllHooks!==void 0)Z.disableAllHooks=Y.disableAllHooks;if(Y.permissionMode!==void 0)Z.permissionMode=Y.permissionMode;if(Y.maxTurns!==void 0)Z.maxTurns=Y.maxTurns;return Z}resolveEnvInterpolation($){let Y=/\$\{?([A-Z_][A-Z0-9_]*)(:-([^}]+))?\}?/g,Z=(X)=>{if(typeof X==="string")return X.replace(Y,(Q,J,q,K)=>{return process.env[J]||K||Q});return X};for(let[X,Q]of Object.entries($))if(typeof Q==="string")$[X]=Z(Q)}async ensureGitIgnore($){let Y=x2.join(process.cwd(),".gitignore"),Z=".blade/settings.local.json";try{let X="";if(await this.fileExists(Y))X=await W6.readFile(Y,"utf-8");if(!X.includes(".blade/settings.local.json")){let Q=X.trim()+`
2
+ import{createRequire as jQ}from"node:module";var DQ=Object.create;var{getPrototypeOf:IQ,defineProperty:E$,getOwnPropertyNames:B7,getOwnPropertyDescriptor:MQ}=Object,w7=Object.prototype.hasOwnProperty;var v0=($,Y,Z)=>{Z=$!=null?DQ(IQ($)):{};let X=Y||!$||!$.__esModule?E$(Z,"default",{value:$,enumerable:!0}):Z;for(let Q of B7($))if(!w7.call(X,Q))E$(X,Q,{get:()=>$[Q],enumerable:!0});return X},N7=new WeakMap,kQ=($)=>{var Y=N7.get($),Z;if(Y)return Y;if(Y=E$({},"__esModule",{value:!0}),$&&typeof $==="object"||typeof $==="function")B7($).map((X)=>!w7.call(Y,X)&&E$(Y,X,{get:()=>$[X],enumerable:!(Z=MQ($,X))||Z.enumerable}));return N7.set($,Y),Y};var L7=($,Y)=>{for(var Z in Y)E$($,Z,{get:Y[Z],enumerable:!0,configurable:!0,set:(X)=>Y[Z]=()=>X})};var D=($,Y)=>()=>($&&(Y=$($=0)),Y);var C1=jQ(import.meta.url);var v$;var A7=D(()=>{v$={name:"blade-code",version:"0.0.34",private:!1,description:"🗡️ Blade Code - 智能代码助手命令行工具",type:"module",bin:{blade:"dist/blade.js"},files:["dist","bin","vendor/ripgrep/**","config.env.example","README.md","CHANGELOG.md"],scripts:{dev:"bun --watch src/blade.tsx",build:"rm -rf dist && bun run scripts/build.ts",start:"bun run dist/blade.js",test:"node scripts/test.js","test:all":"vitest run --config vitest.config.ts","test:unit":"node scripts/test.js unit","test:integration":"node scripts/test.js integration","test:cli":"node scripts/test.js cli","test:coverage":"node scripts/test.js all --coverage","test:unit:coverage":"node scripts/test.js unit --coverage","test:integration:coverage":"node scripts/test.js integration --coverage","test:cli:coverage":"node scripts/test.js cli --coverage","test:watch":"vitest --watch --config vitest.config.ts","test:unit:watch":"vitest --watch --config vitest.config.ts --project unit","test:integration:watch":"vitest --watch --config vitest.config.ts --project integration","test:cli:watch":"vitest --watch --config vitest.config.ts --project cli","test:debug":"node scripts/test.js all --debug","test:verbose":"node scripts/test.js all --verbose","test:ci":"vitest run --config vitest.config.ts --coverage --reporter=verbose","test:performance":'vitest --testNamePattern="performance" --verbose',lint:"biome lint src tests","lint:fix":"biome lint --write src tests",format:"biome format --write src tests","format:check":"biome format src tests",check:"biome check src tests","check:fix":"biome check --write src tests","type-check":"tsc --noEmit","check:full":"npm run type-check && npm run lint && npm run format:check && npm run test:ci","security:audit":"pnpm audit","security:test":"bash scripts/run-security-tests.sh","vendor:ripgrep":"node scripts/download-ripgrep.js","vendor:ripgrep:clean":"rm -rf vendor/ripgrep/darwin-* vendor/ripgrep/linux-* vendor/ripgrep/win32-*",release:"node scripts/release.js","release:dry":"node scripts/release.js --dry-run","release:major":"node scripts/release.js --major","release:minor":"node scripts/release.js --minor","release:patch":"node scripts/release.js --patch",clean:"rm -rf dist node_modules/.cache coverage",prepare:"bun run build",preflight:"npm run clean && pnpm install && npm run format && npm run lint && npm run build && npm run type-check && npm run test:ci"},keywords:["cli","blade","ai","assistant","agent","llm","tool","qwen","volcengine","smart-tools","code-review","documentation","git-tools"],author:"echoVic",license:"MIT",repository:{type:"git",url:"git+https://github.com/echoVic/blade-code.git"},homepage:"https://github.com/echoVic/blade-code",bugs:{url:"https://github.com/echoVic/blade-doc/issues"},engines:{node:">=16.0.0"},devDependencies:{"@biomejs/biome":"^2.2.4","@testing-library/react":"^16.2.0","@testing-library/user-event":"^14.5.0","@types/bun":"^1.3.4","@types/diff":"^8.0.0","@types/inquirer":"^9.0.8","@types/json-schema":"^7.0.15","@types/lodash-es":"^4.17.12","@types/node":"^22.15.24","@types/picomatch":"^4.0.2","@types/react":"^19.1.12","@types/react-dom":"^19.1.9","@types/semver":"^7.7.1","@types/uuid":"^10.0.0","@types/write-file-atomic":"^4.0.3","@types/ws":"^8.5.12","@types/yargs":"^17.0.33","@vitest/coverage-v8":"^3.0.0",execa:"^9.6.0",jsdom:"^26.0.0","ts-node":"^10.9.2",typescript:"^5.9.2",vitest:"^3.0.0"},optionalDependencies:{"@vscode/ripgrep":"^1.17.0"},dependencies:{"@agentclientprotocol/sdk":"^0.12.0","@inkjs/ui":"^2.0.0","@modelcontextprotocol/sdk":"^1.17.4",ahooks:"^3.9.5","ansi-escapes":"^7.2.0","async-mutex":"^0.5.0",axios:"^1.12.2",chalk:"^5.4.1",diff:"^8.0.2","fast-glob":"^3.3.3","fullscreen-ink":"^0.1.0","fuse.js":"^7.1.0",glob:"^11.0.3",ink:"npm:@jrichman/ink@6.4.6","ink-big-text":"^2.0.0","ink-gradient":"^3.0.0","ink-progress-bar":"^3.0.0","ink-select-input":"^6.2.0","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0",inquirer:"^12.6.3","js-tiktoken":"^1.0.21","lodash-es":"^4.17.21",lowlight:"^3.3.0","lru-cache":"^11.2.4",nanoid:"^5.1.6",openai:"^6.2.0",picomatch:"^4.0.3",pino:"^10.1.0","pino-pretty":"^13.1.3",react:"^19.1.1","react-dom":"^19.1.1",semver:"^7.7.3","string-width":"^8.1.0",undici:"^7.16.0","write-file-atomic":"^7.0.0",ws:"^8.18.0",yaml:"^2.8.1",yargs:"^18.0.0",zod:"^3.24.2","zod-to-json-schema":"^3.24.6",zustand:"^5.0.9"}}});function x2(){return v$.version}function b7(){return v$.name}function R7(){return v$.description}function V7(){return`v${v$.version} © 2025 Blade Code`}var y$=D(()=>{A7()});var s1=()=>{};var p2;var S4=D(()=>{s1();p2={currentModelId:"",models:[],temperature:0,maxContextTokens:128000,maxOutputTokens:32768,stream:!0,topP:0.9,topK:50,timeout:180000,theme:"GitHub",language:"zh-CN",fontSize:14,debug:!1,mcpEnabled:!1,mcpServers:{},permissions:{allow:["Bash(pwd)","Bash(which *)","Bash(whoami)","Bash(hostname)","Bash(uname *)","Bash(date)","Bash(echo *)","Bash(ls *)","Bash(tree *)","Bash(git status)","Bash(git log *)","Bash(git diff *)","Bash(git branch *)","Bash(git show *)","Bash(git remote *)","Bash(npm list *)","Bash(npm view *)","Bash(npm outdated *)","Bash(pnpm list *)","Bash(yarn list *)","Bash(pip list *)","Bash(pip show *)"],ask:["Bash(curl *)","Bash(wget *)","Bash(aria2c *)","Bash(axel *)","Bash(rm -rf *)","Bash(rm -r *)","Bash(rm --recursive *)","Bash(nc *)","Bash(netcat *)","Bash(telnet *)","Bash(ncat *)"],deny:["Read(./.env)","Read(./.env.*)","Bash(rm -rf /)","Bash(rm -rf /*)","Bash(sudo *)","Bash(chmod 777 *)","Bash(bash *)","Bash(sh *)","Bash(zsh *)","Bash(fish *)","Bash(dash *)","Bash(eval *)","Bash(source *)","Bash(mkfs *)","Bash(fdisk *)","Bash(dd *)","Bash(format *)","Bash(parted *)","Bash(open http*)","Bash(open https*)","Bash(xdg-open http*)","Bash(xdg-open https*)"]},permissionMode:"default",hooks:{enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],Stop:[]},env:{},disableAllHooks:!1,maxTurns:-1}});import{promises as _6}from"fs";import{merge as I7}from"lodash-es";import M7 from"os";import g2 from"path";class u1{static instance=null;constructor(){}static getInstance(){if(!u1.instance)u1.instance=new u1;return u1.instance}static resetInstance(){u1.instance=null}async initialize(){try{let $=await this.loadConfigFiles(),Y=await this.loadSettingsFiles(),Z={...p2,...$,...Y};if(this.resolveEnvInterpolation(Z),await this.ensureGitIgnore(Z.debug),Z.debug)console.log("[ConfigManager] Configuration loaded successfully");return Z}catch($){return console.error("[ConfigManager] Failed to initialize:",$),p2}}async loadConfigFiles(){let $=g2.join(M7.homedir(),".blade","config.json"),Y=g2.join(process.cwd(),".blade","config.json"),Z={},X=await this.loadJsonFile($);if(X)Z={...Z,...X};let Q=await this.loadJsonFile(Y);if(Q){let J={...Z.mcpServers||{},...Q.mcpServers||{}};if(Z={...Z,...Q},Object.keys(J).length>0)Z.mcpServers=J}return Z}async loadSettingsFiles(){let $=g2.join(M7.homedir(),".blade","settings.json"),Y=g2.join(process.cwd(),".blade","settings.json"),Z=g2.join(process.cwd(),".blade","settings.local.json"),X={},Q=await this.loadJsonFile($);if(Q)X=this.mergeSettings(X,Q);let J=await this.loadJsonFile(Y);if(J)X=this.mergeSettings(X,J);let q=await this.loadJsonFile(Z);if(q)X=this.mergeSettings(X,q);return X}mergeSettings($,Y){let Z=JSON.parse(JSON.stringify($));if(Y.permissions){if(!Z.permissions)Z.permissions={allow:[],ask:[],deny:[]};if(Y.permissions.allow){let X=[...Z.permissions.allow||[],...Y.permissions.allow];Z.permissions.allow=Array.from(new Set(X))}if(Y.permissions.ask){let X=[...Z.permissions.ask||[],...Y.permissions.ask];Z.permissions.ask=Array.from(new Set(X))}if(Y.permissions.deny){let X=[...Z.permissions.deny||[],...Y.permissions.deny];Z.permissions.deny=Array.from(new Set(X))}}if(Y.hooks)Z.hooks=I7({},Z.hooks,Y.hooks);if(Y.env)Z.env=I7({},Z.env,Y.env);if(Y.mcpServers)Z.mcpServers={...Z.mcpServers||{},...Y.mcpServers};if(Y.disableAllHooks!==void 0)Z.disableAllHooks=Y.disableAllHooks;if(Y.permissionMode!==void 0)Z.permissionMode=Y.permissionMode;if(Y.maxTurns!==void 0)Z.maxTurns=Y.maxTurns;return Z}resolveEnvInterpolation($){let Y=/\$\{?([A-Z_][A-Z0-9_]*)(:-([^}]+))?\}?/g,Z=(X)=>{if(typeof X==="string")return X.replace(Y,(Q,J,q,G)=>{return process.env[J]||G||Q});return X};for(let[X,Q]of Object.entries($))if(typeof Q==="string")$[X]=Z(Q)}async ensureGitIgnore($){let Y=g2.join(process.cwd(),".gitignore"),Z=".blade/settings.local.json";try{let X="";if(await this.fileExists(Y))X=await _6.readFile(Y,"utf-8");if(!X.includes(".blade/settings.local.json")){let Q=X.trim()+`
3
3
 
4
4
  # Blade local settings
5
5
  .blade/settings.local.json
6
- `;if(await W6.writeFile(Y,Q,"utf-8"),$)console.log("[ConfigManager] Added .blade/settings.local.json to .gitignore")}}catch(X){}}async loadJsonFile($){try{if(await this.fileExists($)){let Y=await W6.readFile($,"utf-8");return JSON.parse(Y)}}catch(Y){console.warn(`[ConfigManager] Failed to load ${$}:`,Y)}return null}async fileExists($){try{return await W6.access($),!0}catch{return!1}}validateConfig($){let Y=[];if(!$.models||$.models.length===0)Y.push("没有可用的模型配置");if($.models&&$.models.length>0){if(!$.currentModelId)Y.push("未设置当前模型 ID");else if(!$.models.find((X)=>X.id===$.currentModelId))Y.push("当前模型 ID 无效")}if(Y.length>0)throw Error(`配置验证失败:
6
+ `;if(await _6.writeFile(Y,Q,"utf-8"),$)console.log("[ConfigManager] Added .blade/settings.local.json to .gitignore")}}catch(X){}}async loadJsonFile($){try{if(await this.fileExists($)){let Y=await _6.readFile($,"utf-8");return JSON.parse(Y)}}catch(Y){console.warn(`[ConfigManager] Failed to load ${$}:`,Y)}return null}async fileExists($){try{return await _6.access($),!0}catch{return!1}}validateConfig($){let Y=[];if(!$.models||$.models.length===0)Y.push("没有可用的模型配置");if($.models&&$.models.length>0){if(!$.currentModelId)Y.push("未设置当前模型 ID");else if(!$.models.find((X)=>X.id===$.currentModelId))Y.push("当前模型 ID 无效")}if(Y.length>0)throw Error(`配置验证失败:
7
7
  ${Y.map((Z)=>` - ${Z}`).join(`
8
8
  `)}
9
9
 
@@ -26,16 +26,16 @@ ${Y.map((Z)=>` - ${Z}`).join(`
26
26
  }
27
27
  ]
28
28
  }
29
- `)}}function j4($,Y={}){let Z={...$};if(Y.fallbackModel!==void 0)Z.fallbackModel=Y.fallbackModel;if(Y.debug!==void 0)Z.debug=Y.debug===""?!0:Y.debug;if(Y.yolo===!0)Z.permissionMode="yolo";else if(Y.permissionMode!==void 0)Z.permissionMode=Y.permissionMode;if(Y.maxTurns!==void 0)Z.maxTurns=Y.maxTurns;return Z.systemPrompt=Y.systemPrompt,Z.appendSystemPrompt=Y.appendSystemPrompt,Z.resumeSessionId=Y.sessionId,Z.forkSession=Y.forkSession,Z.allowedTools=Y.allowedTools,Z.disallowedTools=Y.disallowedTools,Z.mcpConfigPaths=Y.mcpConfig,Z.strictMcpConfig=Y.strictMcpConfig,Z.addDirs=Y.addDir,Z.outputFormat=Y.outputFormat,Z.inputFormat=Y.inputFormat,Z.print=Y.print,Z.includePartialMessages=Y.includePartialMessages,Z.replayUserMessages=Y.replayUserMessages,Z.agentsConfig=Y.agents,Z.settingSources=Y.settingSources,Z}var N7=R(()=>{k4();s1()});import{promises as BQ}from"node:fs";import NQ from"node:os";import w7 from"node:path";import wQ from"pino";async function AQ(){let $=w7.join(NQ.homedir(),".blade","logs");return await BQ.mkdir($,{recursive:!0}),w7.join($,"blade.log")}async function RQ(){if(j$)return j$;if(E$)return E$;return E$=(async()=>{let $=await AQ();return j$=wQ({level:"debug",transport:{target:"pino/file",options:{destination:$}}}),j$})(),E$}function L7(){j$=null,E$=null}class N0{static globalDebugConfig=null;enabled;minLevel;category;pinoLogger=null;constructor($={}){if($.enabled!==void 0)this.enabled=$.enabled;else if(N0.globalDebugConfig!==null)this.enabled=Boolean(N0.globalDebugConfig);else this.enabled=!1;this.minLevel=$.minLevel??0,this.category=$.category??"General",this.initPino()}async initPino(){try{let $=await RQ();this.pinoLogger=$.child({category:this.category})}catch($){console.error("[Logger] Failed to initialize pino:",$)}}static setGlobalDebug($){N0.globalDebugConfig=$,L7()}static clearGlobalDebug(){N0.globalDebugConfig=null,L7()}setEnabled($){this.enabled=$}parseDebugFilter($){if(!$)return{enabled:!1};if($===!0||$==="true"||$==="1")return{enabled:!0};let Y=String($).trim();if(!Y)return{enabled:!0};if(Y.startsWith("!"))return{enabled:!0,filter:{mode:"exclude",categories:Y.split(",").map((Q)=>Q.trim().replace(/^!/,"")).filter(Boolean)}};return{enabled:!0,filter:{mode:"include",categories:Y.split(",").map((X)=>X.trim()).filter(Boolean)}}}shouldLogCategory($){if(!$)return!0;let Y=this.category.toLowerCase();if($.mode==="include")return $.categories.some((Z)=>Y.includes(Z.toLowerCase()));return!$.categories.some((Z)=>Y.includes(Z.toLowerCase()))}shouldLogToConsole($){if(N0.globalDebugConfig!==null){let{enabled:Y,filter:Z}=this.parseDebugFilter(N0.globalDebugConfig);if(!Y)return!1;if($<this.minLevel)return!1;return this.shouldLogCategory(Z)}return this.enabled&&$>=this.minLevel}log($,...Y){let Z=Y.map((X)=>typeof X==="object"?JSON.stringify(X):String(X)).join(" ");if(this.pinoLogger){let X=LQ[$];this.pinoLogger[X](Z)}if(this.shouldLogToConsole($)){let X=A7[$],Q=`[${this.category}] [${X}]`;console.error(Q,...Y)}}debug(...$){this.log(0,...$)}info(...$){this.log(1,...$)}warn(...$){this.log(2,...$)}error(...$){this.log(3,...$)}}function u($,Y){return new N0({...Y,category:$})}var A7,LQ,j$=null,E$=null,KO;var N1=R(()=>{((Q)=>{Q[Q.DEBUG=0]="DEBUG";Q[Q.INFO=1]="INFO";Q[Q.WARN=2]="WARN";Q[Q.ERROR=3]="ERROR"})(A7||={});LQ={[0]:"debug",[1]:"info",[2]:"warn",[3]:"error"};KO=new N0({category:"General"})});import{Mutex as R7}from"async-mutex";import{merge as bQ}from"lodash-es";import{promises as U6}from"node:fs";import b7 from"node:os";import t0 from"node:path";import VQ from"write-file-atomic";class c0{static instance=null;pendingUpdates=new Map;timers=new Map;fileLocks=new Map;lastSaveError=null;debounceDelay=300;constructor(){}static getInstance(){if(!c0.instance)c0.instance=new c0;return c0.instance}static resetInstance(){if(c0.instance)for(let $ of c0.instance.timers.values())clearTimeout($);c0.instance=null}async save($,Y={}){this.validatePersistableFields($);let Z=this.groupUpdatesByTarget($,Y.scope);if(Y.immediate)await Promise.all(Array.from(Z.entries()).map(([X,Q])=>this.flushTarget(X,Q)));else for(let[X,Q]of Z)this.scheduleSave(X,Q)}async flush(){for(let Y of this.timers.values())clearTimeout(Y);this.timers.clear();let $=Array.from(this.pendingUpdates.entries()).map(([Y,Z])=>this.flushTarget(Y,Z));this.pendingUpdates.clear(),await Promise.all($)}getLastSaveError(){return this.lastSaveError}clearLastSaveError(){this.lastSaveError=null}async appendPermissionRule($,Y={}){let Z=Y.scope??"local",X=this.resolveFilePath("settings",Z);await this.flushTargetWithModifier(X,(Q)=>{let J=Q.permissions??{allow:[],ask:[],deny:[]},q={allow:this.dedupeArray([...J.allow||[],$]),ask:J.ask||[],deny:J.deny||[]};return{...Q,permissions:q}})}async appendLocalPermissionRule($,Y={}){await this.appendPermissionRule($,{...Y,scope:"local"})}validatePersistableFields($){for(let Y of Object.keys($)){let Z=e0[Y];if(!Z)throw Error(`Unknown config field: ${Y}`);if(!Z.persistable)throw Error(`Field "${Y}" is non-persistable and cannot be saved to config files. Non-persistable fields are runtime-only and only valid for the current session.`)}}groupUpdatesByTarget($,Y){let Z=new Map;for(let[X,Q]of Object.entries($)){let J=e0[X];if(!J)continue;let q=Y??J.defaultScope,K=this.resolveFilePath(J.target,q);if(!Z.has(K))Z.set(K,{});Z.get(K)[X]=Q}return Z}resolveFilePath($,Y){if($==="config")return Y==="global"?t0.join(b7.homedir(),".blade","config.json"):t0.join(process.cwd(),".blade","config.json");switch(Y){case"local":return t0.join(process.cwd(),".blade","settings.local.json");case"project":return t0.join(process.cwd(),".blade","settings.json");case"global":return t0.join(b7.homedir(),".blade","settings.json");default:return t0.join(process.cwd(),".blade","settings.local.json")}}scheduleSave($,Y){let Z=this.pendingUpdates.get($)??{},X=this.mergePendingUpdates(Z,Y);this.pendingUpdates.set($,X);let Q=this.timers.get($);if(Q)clearTimeout(Q);let J=setTimeout(async()=>{let q=this.pendingUpdates.get($);if(q){this.pendingUpdates.delete($),this.timers.delete($);try{await this.flushTarget($,q),this.lastSaveError=null}catch(K){let G=K instanceof Error?K:Error(String(K));this.lastSaveError=G,V7.error(`Failed to save config to ${$}:`,G.message),V7.error("Stack trace:",G.stack)}}},this.debounceDelay);this.timers.set($,J)}mergePendingUpdates($,Y){let Z={...$};for(let[X,Q]of Object.entries(Y)){let J=e0[X];if(!J){Z[X]=Q;continue}switch(J.mergeStrategy){case"replace":Z[X]=Q;break;case"append-dedupe":this.applyAppendDedupe(Z,X,Q);break;case"deep-merge":this.applyDeepMerge(Z,X,Q);break}}return Z}async flushTarget($,Y){let Z=this.fileLocks.get($);if(!Z)Z=new R7,this.fileLocks.set($,Z);await Z.runExclusive(async()=>{await this.performWrite($,Y)})}async flushTargetWithModifier($,Y){let Z=this.fileLocks.get($);if(!Z)Z=new R7,this.fileLocks.set($,Z);await Z.runExclusive(async()=>{await U6.mkdir(t0.dirname($),{recursive:!0});let X={};try{let J=await U6.readFile($,"utf-8");X=JSON.parse(J)}catch{X={}}let Q=Y(X);await this.atomicWrite($,Q)})}async performWrite($,Y){await U6.mkdir(t0.dirname($),{recursive:!0});let Z={};try{let Q=await U6.readFile($,"utf-8");Z=JSON.parse(Q)}catch{Z={}}let X={...Z};for(let[Q,J]of Object.entries(Y)){let q=e0[Q];if(!q){X[Q]=J;continue}switch(q.mergeStrategy){case"replace":X[Q]=J;break;case"append-dedupe":this.applyAppendDedupe(X,Q,J);break;case"deep-merge":this.applyDeepMerge(X,Q,J);break}}await this.atomicWrite($,X)}applyAppendDedupe($,Y,Z){if(Y==="permissions"&&typeof Z==="object"&&Z!==null){let X=$[Y]??{allow:[],ask:[],deny:[]},Q=Z;$[Y]={allow:this.dedupeArray([...X.allow||[],...Q.allow||[]]),ask:this.dedupeArray([...X.ask||[],...Q.ask||[]]),deny:this.dedupeArray([...X.deny||[],...Q.deny||[]])}}else if(Array.isArray(Z)){let X=Array.isArray($[Y])?$[Y]:[];$[Y]=this.dedupeArray([...X,...Z])}else $[Y]=Z}applyDeepMerge($,Y,Z){if(typeof Z==="object"&&Z!==null&&!Array.isArray(Z)){let X=typeof $[Y]==="object"&&$[Y]!==null?$[Y]:{};$[Y]=bQ({},X,Z)}else $[Y]=Z}dedupeArray($){return Array.from(new Set($))}async atomicWrite($,Y){await VQ($,JSON.stringify(Y,null,2),{mode:384,encoding:"utf-8"})}}function f1(){return c0.getInstance()}var V7,e0,BO,NO,wO,LO;var D7=R(()=>{N1();V7=u("Service"),e0={models:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},currentModelId:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},temperature:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},maxContextTokens:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},maxOutputTokens:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},timeout:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},theme:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},language:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},debug:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},permissionMode:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},permissions:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},hooks:{target:"settings",defaultScope:"local",mergeStrategy:"deep-merge",persistable:!0},env:{target:"settings",defaultScope:"local",mergeStrategy:"deep-merge",persistable:!0},disableAllHooks:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},maxTurns:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},mcpServers:{target:"config",defaultScope:"project",mergeStrategy:"replace",persistable:!0},stream:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},topP:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},topK:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},fontSize:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},mcpEnabled:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},systemPrompt:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},appendSystemPrompt:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},initialMessage:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},resumeSessionId:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},forkSession:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},allowedTools:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},disallowedTools:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},mcpConfigPaths:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},strictMcpConfig:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},fallbackModel:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},addDirs:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},outputFormat:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},inputFormat:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},print:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},includePartialMessages:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},replayUserMessages:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},agentsConfig:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},settingSources:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1}},BO=new Set(Object.entries(e0).filter(([$,Y])=>Y.persistable).map(([$])=>$)),NO=new Set(Object.entries(e0).filter(([$,Y])=>!Y.persistable).map(([$])=>$)),wO=new Set(Object.entries(e0).filter(([$,Y])=>Y.target==="config").map(([$])=>$)),LO=new Set(Object.entries(e0).filter(([$,Y])=>Y.target==="settings").map(([$])=>$))});import y$ from"picomatch";class A2{config;constructor($){this.config=$}check($){let Y=A2.buildSignature($),Z=this.matchRules(Y,this.config.deny);if(Z)return{result:"deny",matchedRule:Z.rule,matchType:Z.type,reason:`工具调用被拒绝规则阻止: ${Z.rule}`};let X=this.matchRules(Y,this.config.allow);if(X)return{result:"allow",matchedRule:X.rule,matchType:X.type,reason:`工具调用符合允许规则: ${X.rule}`};let Q=this.matchRules(Y,this.config.ask);if(Q)return{result:"ask",matchedRule:Q.rule,matchType:Q.type,reason:`工具调用需要用户确认: ${Q.rule}`};return{result:"ask",reason:"工具调用未匹配任何规则,默认需要确认"}}static buildSignature($){let{toolName:Y,params:Z,tool:X}=$;try{if(X?.extractSignatureContent){let Q=X.extractSignatureContent(Z);return Q?`${Y}(${Q})`:Y}return Y}catch(Q){return console.warn(`Failed to build signature for ${Y}:`,Q instanceof Error?Q.message:Q),Y}}static abstractPattern($){let{toolName:Y,params:Z,tool:X}=$;try{if(X?.abstractPermissionRule){let Q=X.abstractPermissionRule(Z);if(Q==="")return"";return Q?`${Y}(${Q})`:Y}return Y}catch(Q){return console.warn(`Failed to abstract pattern for ${Y}:`,Q instanceof Error?Q.message:Q),Y}}matchRules($,Y){for(let Z of Y){let X=this.matchRule($,Z);if(X)return{rule:Z,type:X}}return null}matchRule($,Y){if($===Y)return"exact";if(Y==="*"||Y==="**")return"wildcard";let Z=this.extractToolName($),X=this.extractToolName(Y);if(!Z||!X)return null;if(X.includes("*")){if(!y$.isMatch(Z,X,{dot:!0,bash:!0}))return null}else if(Z!==X)return null;if(Y===X)return"prefix";if(Y.includes("*")){let Q=this.extractParams($),J=this.extractParams(Y);if(J==="*"||J==="**")return"wildcard";if(this.matchParams(Q,J))return J.includes("**")?"glob":"wildcard";if(y$.isMatch($,Y,{dot:!0,bash:!0}))return Y.includes("**")?"glob":"wildcard"}return null}extractParams($){let Y=$.match(/\(([\s\S]*)\)$/);return Y?Y[1]:""}matchParams($,Y){if(!$||!Y)return!1;let Z=this.parseParamPairs($),X=this.parseParamPairs(Y),Q=Object.keys(X).length>0,J=Object.keys(Z).length>0;if(Q!==J)return!1;if(!Q&&!J){if(Y==="*"||Y==="**")return!0;if(Y.includes("*")||Y.includes("{")||Y.includes("?"))return y$.isMatch($,Y,{dot:!0,bash:!0});return $===Y}for(let[q,K]of Object.entries(X)){let G=Z[q];if(G===void 0)return!1;if(K.includes("*")||K.includes("{")||K.includes("?")){if(K==="*"||K==="**")continue;if(!y$.isMatch(G,K,{dot:!0,bash:!0}))return!1}else if(G!==K)return!1}return!0}parseParamPairs($){let Y={},Z=this.smartSplit($,",");for(let X of Z){let Q=this.findTopLevelDelimiter(X,":");if(Q>0){let J=X.slice(0,Q).trim(),q=X.slice(Q+1).trim();Y[J]=q}}return Y}smartSplit($,Y){let Z=[],X="",Q=0,J=0,q=0,K=!1,G="",W=!1;for(let U=0;U<$.length;U++){let H=$[U];if(W){X+=H,W=!1;continue}if(H==="\\"){X+=H,W=!0;continue}if(!K&&H==="{")Q++;else if(!K&&H==="}")Q--;else if(!K&&H==="(")J++;else if(!K&&H===")")J--;else if(!K&&H==="[")q++;else if(!K&&H==="]")q--;if((H==='"'||H==="'")&&!K){K=!0,G=H,X+=H;continue}else if(K&&H===G){K=!1,G="",X+=H;continue}if(H===Y&&Q===0&&J===0&&q===0&&!K)Z.push(X.trim()),X="";else X+=H}if(X)Z.push(X.trim());return Z}findTopLevelDelimiter($,Y){let Z=0,X=0,Q=0,J=!1,q="",K=!1;for(let G=0;G<$.length;G++){let W=$[G];if(K){K=!1;continue}if(W==="\\"){K=!0;continue}if(!J&&W==="{")Z++;else if(!J&&W==="}")Z--;else if(!J&&W==="(")X++;else if(!J&&W===")")X--;else if(!J&&W==="[")Q++;else if(!J&&W==="]")Q--;if((W==='"'||W==="'")&&!J){J=!0,q=W;continue}else if(J&&W===q){J=!1,q="";continue}if(W===Y&&Z===0&&X===0&&Q===0&&!J)return G}return-1}extractToolName($){let Y=$.match(/^([A-Za-z0-9_]+)(\(|$)/);return Y?Y[1]:null}isAllowed($){return this.check($).result==="allow"}isDenied($){return this.check($).result==="deny"}needsConfirmation($){return this.check($).result==="ask"}updateConfig($){if($.allow)this.config.allow=[...this.config.allow,...$.allow];if($.ask)this.config.ask=[...this.config.ask,...$.ask];if($.deny)this.config.deny=[...this.config.deny,...$.deny]}replaceConfig($){this.config={...$}}getConfig(){return{...this.config}}}var E4=()=>{};var p2=R(()=>{N7();D7();k4();E4();s1()});var MQ,y4=($)=>({...MQ,actions:{setInitializationStatus:(Y)=>{$((Z)=>({app:{...Z.app,initializationStatus:Y}}))},setInitializationError:(Y)=>{$((Z)=>({app:{...Z.app,initializationError:Y}}))},setActiveModal:(Y)=>{$((Z)=>({app:{...Z.app,activeModal:Y}}))},showSessionSelector:(Y)=>{$((Z)=>({app:{...Z.app,activeModal:"sessionSelector",sessionSelectorData:Y}}))},showModelEditWizard:(Y)=>{$((Z)=>({app:{...Z.app,activeModal:"modelEditWizard",modelEditorTarget:Y}}))},closeModal:()=>{$((Y)=>({app:{...Y.app,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null}}))},setTodos:(Y)=>{$((Z)=>({app:{...Z.app,todos:Y}}))},updateTodo:(Y)=>{$((Z)=>({app:{...Z.app,todos:Z.app.todos.map((X)=>X.id===Y.id?Y:X)}}))},setAwaitingSecondCtrlC:(Y)=>{$((Z)=>({app:{...Z.app,awaitingSecondCtrlC:Y}}))},setThinkingModeEnabled:(Y)=>{$((Z)=>({app:{...Z.app,thinkingModeEnabled:Y}}))},toggleThinkingMode:()=>{$((Y)=>({app:{...Y.app,thinkingModeEnabled:!Y.app.thinkingModeEnabled}}))}}});var M7=R(()=>{MQ={initializationStatus:"idle",initializationError:null,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null,todos:[],awaitingSecondCtrlC:!1,thinkingModeEnabled:!1}});var IQ,v4=($,Y)=>({...IQ,actions:{setProcessing:(Z)=>{$((X)=>({command:{...X.command,isProcessing:Z}}))},createAbortController:()=>{let Z=new AbortController;return $((X)=>({command:{...X.command,abortController:Z}})),Z},clearAbortController:()=>{$((Z)=>({command:{...Z.command,abortController:null}}))},abort:()=>{let{abortController:Z}=Y().command;if(Z&&!Z.signal.aborted)Z.abort();Y().session.actions.setThinking(!1),$((X)=>({command:{...X.command,isProcessing:!1,abortController:null,pendingCommands:[]}}))},enqueueCommand:(Z)=>{$((X)=>({command:{...X.command,pendingCommands:[...X.command.pendingCommands,Z]}}))},dequeueCommand:()=>{let{pendingCommands:Z}=Y().command;if(Z.length===0)return;let[X,...Q]=Z;return $((J)=>({command:{...J.command,pendingCommands:Q}})),X},clearQueue:()=>{$((Z)=>({command:{...Z.command,pendingCommands:[]}}))}}});var I7=R(()=>{IQ={isProcessing:!1,abortController:null,pendingCommands:[]}});var kQ,P4=($)=>({...kQ,actions:{setConfig:(Y)=>{$((Z)=>({config:{...Z.config,config:Y}}))},updateConfig:(Y)=>{$((Z)=>{if(!Z.config.config)throw Error(`[ConfigSlice] Config not initialized. Cannot update: ${JSON.stringify(Y)}`);return{config:{...Z.config,config:{...Z.config.config,...Y}}}})}}});var k7=R(()=>{kQ={config:null}});var jQ,T4=($)=>({...jQ,actions:{setFocus:(Y)=>{$((Z)=>({focus:{...Z.focus,currentFocus:Y,previousFocus:Z.focus.currentFocus}}))},restorePreviousFocus:()=>{$((Y)=>({focus:{...Y.focus,currentFocus:Y.focus.previousFocus||"main-input",previousFocus:null}}))}}});var j7=R(()=>{jQ={currentFocus:"main-input",previousFocus:null}});import{nanoid as EQ}from"nanoid";var y7,E7,S4=($,Y)=>({...E7,actions:{addMessage:(Z)=>{$((X)=>({session:{...X.session,messages:[...X.session.messages,Z],error:null}}))},addUserMessage:(Z)=>{let X={id:`user-${Date.now()}-${Math.random()}`,role:"user",content:Z,timestamp:Date.now()};Y().session.actions.addMessage(X)},addAssistantMessage:(Z,X)=>{let Q={id:`assistant-${Date.now()}-${Math.random()}`,role:"assistant",content:Z,timestamp:Date.now(),thinkingContent:X};Y().session.actions.addMessage(Q)},addToolMessage:(Z,X)=>{let Q={id:`tool-${Date.now()}-${Math.random()}`,role:"tool",content:Z,timestamp:Date.now(),metadata:X};Y().session.actions.addMessage(Q)},setThinking:(Z)=>{$((X)=>({session:{...X.session,isThinking:Z}}))},setCompacting:(Z)=>{$((X)=>({session:{...X.session,isCompacting:Z}}))},setCommand:(Z)=>{$((X)=>({session:{...X.session,currentCommand:Z}}))},setError:(Z)=>{$((X)=>({session:{...X.session,error:Z}}))},clearMessages:()=>{$((Z)=>({session:{...Z.session,messages:[],error:null,clearCount:Z.session.clearCount+1}}))},resetSession:()=>{$((Z)=>({session:{...Z.session,...E7,sessionId:Z.session.sessionId,isActive:!0}}))},restoreSession:(Z,X)=>{$((Q)=>({session:{...Q.session,sessionId:Z,messages:X,error:null,isActive:!0}}))},updateTokenUsage:(Z)=>{$((X)=>({session:{...X.session,tokenUsage:{...X.session.tokenUsage,...Z}}}))},resetTokenUsage:()=>{$((Z)=>({session:{...Z.session,tokenUsage:{...y7}}}))},setCurrentThinkingContent:(Z)=>{$((X)=>({session:{...X.session,currentThinkingContent:Z}}))},appendThinkingContent:(Z)=>{$((X)=>({session:{...X.session,currentThinkingContent:(X.session.currentThinkingContent||"")+Z}}))},setThinkingExpanded:(Z)=>{$((X)=>({session:{...X.session,thinkingExpanded:Z}}))},toggleThinkingExpanded:()=>{$((Z)=>({session:{...Z.session,thinkingExpanded:!Z.session.thinkingExpanded}}))}}});var v7=R(()=>{y7={inputTokens:0,outputTokens:0,totalTokens:0,maxContextTokens:200000},E7={sessionId:EQ(),messages:[],isThinking:!1,isCompacting:!1,currentCommand:null,error:null,isActive:!0,tokenUsage:{...y7},currentThinkingContent:null,thinkingExpanded:!1,clearCount:0}});var P7=R(()=>{M7();I7();k7();j7();v7()});import{nanoid as yQ}from"nanoid";import{devtools as vQ,subscribeWithSelector as PQ}from"zustand/middleware";import{createStore as TQ}from"zustand/vanilla";async function H6(){if(V1()!==null)return;if(g2)return g2;return g2=(async()=>{try{let Z=await m1.getInstance().initialize();n().config.actions.setConfig(Z)}catch(Y){throw g2=null,Error(`❌ Store 未初始化且无法自动初始化
29
+ `)}}function C4($,Y={}){let Z={...$};if(Y.fallbackModel!==void 0)Z.fallbackModel=Y.fallbackModel;if(Y.debug!==void 0)Z.debug=Y.debug===""?!0:Y.debug;if(Y.yolo===!0)Z.permissionMode="yolo";else if(Y.permissionMode!==void 0)Z.permissionMode=Y.permissionMode;if(Y.maxTurns!==void 0)Z.maxTurns=Y.maxTurns;return Z.systemPrompt=Y.systemPrompt,Z.appendSystemPrompt=Y.appendSystemPrompt,Z.resumeSessionId=Y.sessionId,Z.forkSession=Y.forkSession,Z.allowedTools=Y.allowedTools,Z.disallowedTools=Y.disallowedTools,Z.mcpConfigPaths=Y.mcpConfig,Z.strictMcpConfig=Y.strictMcpConfig,Z.addDirs=Y.addDir,Z.outputFormat=Y.outputFormat,Z.inputFormat=Y.inputFormat,Z.print=Y.print,Z.includePartialMessages=Y.includePartialMessages,Z.replayUserMessages=Y.replayUserMessages,Z.agentsConfig=Y.agents,Z.settingSources=Y.settingSources,Z}var k7=D(()=>{S4();s1()});import{promises as vQ}from"node:fs";import yQ from"node:os";import j7 from"node:path";import PQ from"pino";async function SQ(){let $=j7.join(yQ.homedir(),".blade","logs");return await vQ.mkdir($,{recursive:!0}),j7.join($,"blade.log")}async function CQ(){if(P$)return P$;if(T$)return T$;return T$=(async()=>{let $=await SQ();return P$=PQ({level:"debug",transport:{target:"pino/file",options:{destination:$}}}),P$})(),T$}function E7(){P$=null,T$=null}class B0{static globalDebugConfig=null;enabled;minLevel;category;pinoLogger=null;constructor($={}){if($.enabled!==void 0)this.enabled=$.enabled;else if(B0.globalDebugConfig!==null)this.enabled=Boolean(B0.globalDebugConfig);else this.enabled=!1;this.minLevel=$.minLevel??0,this.category=$.category??"General",this.initPino()}async initPino(){try{let $=await CQ();this.pinoLogger=$.child({category:this.category})}catch($){console.error("[Logger] Failed to initialize pino:",$)}}static setGlobalDebug($){B0.globalDebugConfig=$,E7()}static clearGlobalDebug(){B0.globalDebugConfig=null,E7()}setEnabled($){this.enabled=$}parseDebugFilter($){if(!$)return{enabled:!1};if($===!0||$==="true"||$==="1")return{enabled:!0};let Y=String($).trim();if(!Y)return{enabled:!0};if(Y.startsWith("!"))return{enabled:!0,filter:{mode:"exclude",categories:Y.split(",").map((Q)=>Q.trim().replace(/^!/,"")).filter(Boolean)}};return{enabled:!0,filter:{mode:"include",categories:Y.split(",").map((X)=>X.trim()).filter(Boolean)}}}shouldLogCategory($){if(!$)return!0;let Y=this.category.toLowerCase();if($.mode==="include")return $.categories.some((Z)=>Y.includes(Z.toLowerCase()));return!$.categories.some((Z)=>Y.includes(Z.toLowerCase()))}shouldLogToConsole($){if(B0.globalDebugConfig!==null){let{enabled:Y,filter:Z}=this.parseDebugFilter(B0.globalDebugConfig);if(!Y)return!1;if($<this.minLevel)return!1;return this.shouldLogCategory(Z)}return this.enabled&&$>=this.minLevel}log($,...Y){let Z=Y.map((X)=>typeof X==="object"?JSON.stringify(X):String(X)).join(" ");if(this.pinoLogger){let X=TQ[$];this.pinoLogger[X](Z)}if(this.shouldLogToConsole($)){let X=v7[$],Q=`[${this.category}] [${X}]`;console.error(Q,...Y)}}debug(...$){this.log(0,...$)}info(...$){this.log(1,...$)}warn(...$){this.log(2,...$)}error(...$){this.log(3,...$)}}function l($,Y){return new B0({...Y,category:$})}var v7,TQ,P$=null,T$=null,BO;var B1=D(()=>{((Q)=>{Q[Q.DEBUG=0]="DEBUG";Q[Q.INFO=1]="INFO";Q[Q.WARN=2]="WARN";Q[Q.ERROR=3]="ERROR"})(v7||={});TQ={[0]:"debug",[1]:"info",[2]:"warn",[3]:"error"};BO=new B0({category:"General"})});import{Mutex as y7}from"async-mutex";import{merge as fQ}from"lodash-es";import{promises as N6}from"node:fs";import P7 from"node:os";import Y2 from"node:path";import hQ from"write-file-atomic";class i0{static instance=null;pendingUpdates=new Map;timers=new Map;fileLocks=new Map;lastSaveError=null;debounceDelay=300;constructor(){}static getInstance(){if(!i0.instance)i0.instance=new i0;return i0.instance}static resetInstance(){if(i0.instance)for(let $ of i0.instance.timers.values())clearTimeout($);i0.instance=null}async save($,Y={}){this.validatePersistableFields($);let Z=this.groupUpdatesByTarget($,Y.scope);if(Y.immediate)await Promise.all(Array.from(Z.entries()).map(([X,Q])=>this.flushTarget(X,Q)));else for(let[X,Q]of Z)this.scheduleSave(X,Q)}async flush(){for(let Y of this.timers.values())clearTimeout(Y);this.timers.clear();let $=Array.from(this.pendingUpdates.entries()).map(([Y,Z])=>this.flushTarget(Y,Z));this.pendingUpdates.clear(),await Promise.all($)}getLastSaveError(){return this.lastSaveError}clearLastSaveError(){this.lastSaveError=null}async appendPermissionRule($,Y={}){let Z=Y.scope??"local",X=this.resolveFilePath("settings",Z);await this.flushTargetWithModifier(X,(Q)=>{let J=Q.permissions??{allow:[],ask:[],deny:[]},q={allow:this.dedupeArray([...J.allow||[],$]),ask:J.ask||[],deny:J.deny||[]};return{...Q,permissions:q}})}async appendLocalPermissionRule($,Y={}){await this.appendPermissionRule($,{...Y,scope:"local"})}validatePersistableFields($){for(let Y of Object.keys($)){let Z=Z2[Y];if(!Z)throw Error(`Unknown config field: ${Y}`);if(!Z.persistable)throw Error(`Field "${Y}" is non-persistable and cannot be saved to config files. Non-persistable fields are runtime-only and only valid for the current session.`)}}groupUpdatesByTarget($,Y){let Z=new Map;for(let[X,Q]of Object.entries($)){let J=Z2[X];if(!J)continue;let q=Y??J.defaultScope,G=this.resolveFilePath(J.target,q);if(!Z.has(G))Z.set(G,{});Z.get(G)[X]=Q}return Z}resolveFilePath($,Y){if($==="config")return Y==="global"?Y2.join(P7.homedir(),".blade","config.json"):Y2.join(process.cwd(),".blade","config.json");switch(Y){case"local":return Y2.join(process.cwd(),".blade","settings.local.json");case"project":return Y2.join(process.cwd(),".blade","settings.json");case"global":return Y2.join(P7.homedir(),".blade","settings.json");default:return Y2.join(process.cwd(),".blade","settings.local.json")}}scheduleSave($,Y){let Z=this.pendingUpdates.get($)??{},X=this.mergePendingUpdates(Z,Y);this.pendingUpdates.set($,X);let Q=this.timers.get($);if(Q)clearTimeout(Q);let J=setTimeout(async()=>{let q=this.pendingUpdates.get($);if(q){this.pendingUpdates.delete($),this.timers.delete($);try{await this.flushTarget($,q),this.lastSaveError=null}catch(G){let K=G instanceof Error?G:Error(String(G));this.lastSaveError=K,T7.error(`Failed to save config to ${$}:`,K.message),T7.error("Stack trace:",K.stack)}}},this.debounceDelay);this.timers.set($,J)}mergePendingUpdates($,Y){let Z={...$};for(let[X,Q]of Object.entries(Y)){let J=Z2[X];if(!J){Z[X]=Q;continue}switch(J.mergeStrategy){case"replace":Z[X]=Q;break;case"append-dedupe":this.applyAppendDedupe(Z,X,Q);break;case"deep-merge":this.applyDeepMerge(Z,X,Q);break}}return Z}async flushTarget($,Y){let Z=this.fileLocks.get($);if(!Z)Z=new y7,this.fileLocks.set($,Z);await Z.runExclusive(async()=>{await this.performWrite($,Y)})}async flushTargetWithModifier($,Y){let Z=this.fileLocks.get($);if(!Z)Z=new y7,this.fileLocks.set($,Z);await Z.runExclusive(async()=>{await N6.mkdir(Y2.dirname($),{recursive:!0});let X={};try{let J=await N6.readFile($,"utf-8");X=JSON.parse(J)}catch{X={}}let Q=Y(X);await this.atomicWrite($,Q)})}async performWrite($,Y){await N6.mkdir(Y2.dirname($),{recursive:!0});let Z={};try{let Q=await N6.readFile($,"utf-8");Z=JSON.parse(Q)}catch{Z={}}let X={...Z};for(let[Q,J]of Object.entries(Y)){let q=Z2[Q];if(!q){X[Q]=J;continue}switch(q.mergeStrategy){case"replace":X[Q]=J;break;case"append-dedupe":this.applyAppendDedupe(X,Q,J);break;case"deep-merge":this.applyDeepMerge(X,Q,J);break}}await this.atomicWrite($,X)}applyAppendDedupe($,Y,Z){if(Y==="permissions"&&typeof Z==="object"&&Z!==null){let X=$[Y]??{allow:[],ask:[],deny:[]},Q=Z;$[Y]={allow:this.dedupeArray([...X.allow||[],...Q.allow||[]]),ask:this.dedupeArray([...X.ask||[],...Q.ask||[]]),deny:this.dedupeArray([...X.deny||[],...Q.deny||[]])}}else if(Array.isArray(Z)){let X=Array.isArray($[Y])?$[Y]:[];$[Y]=this.dedupeArray([...X,...Z])}else $[Y]=Z}applyDeepMerge($,Y,Z){if(typeof Z==="object"&&Z!==null&&!Array.isArray(Z)){let X=typeof $[Y]==="object"&&$[Y]!==null?$[Y]:{};$[Y]=fQ({},X,Z)}else $[Y]=Z}dedupeArray($){return Array.from(new Set($))}async atomicWrite($,Y){await hQ($,JSON.stringify(Y,null,2),{mode:384,encoding:"utf-8"})}}function x1(){return i0.getInstance()}var T7,Z2,MO,kO,jO,EO;var S7=D(()=>{B1();T7=l("Service"),Z2={models:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},currentModelId:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},temperature:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},maxContextTokens:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},maxOutputTokens:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},timeout:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},theme:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},language:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},debug:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},permissionMode:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},permissions:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},hooks:{target:"settings",defaultScope:"local",mergeStrategy:"deep-merge",persistable:!0},env:{target:"settings",defaultScope:"local",mergeStrategy:"deep-merge",persistable:!0},disableAllHooks:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},maxTurns:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},mcpServers:{target:"config",defaultScope:"project",mergeStrategy:"replace",persistable:!0},stream:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},topP:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},topK:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},fontSize:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},mcpEnabled:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},systemPrompt:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},appendSystemPrompt:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},initialMessage:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},resumeSessionId:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},forkSession:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},allowedTools:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},disallowedTools:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},mcpConfigPaths:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},strictMcpConfig:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},fallbackModel:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},addDirs:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},outputFormat:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},inputFormat:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},print:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},includePartialMessages:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},replayUserMessages:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},agentsConfig:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},settingSources:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1}},MO=new Set(Object.entries(Z2).filter(([$,Y])=>Y.persistable).map(([$])=>$)),kO=new Set(Object.entries(Z2).filter(([$,Y])=>!Y.persistable).map(([$])=>$)),jO=new Set(Object.entries(Z2).filter(([$,Y])=>Y.target==="config").map(([$])=>$)),EO=new Set(Object.entries(Z2).filter(([$,Y])=>Y.target==="settings").map(([$])=>$))});import S$ from"picomatch";class A2{config;constructor($){this.config=$}check($){let Y=A2.buildSignature($),Z=this.matchRules(Y,this.config.deny);if(Z)return{result:"deny",matchedRule:Z.rule,matchType:Z.type,reason:`工具调用被拒绝规则阻止: ${Z.rule}`};let X=this.matchRules(Y,this.config.allow);if(X)return{result:"allow",matchedRule:X.rule,matchType:X.type,reason:`工具调用符合允许规则: ${X.rule}`};let Q=this.matchRules(Y,this.config.ask);if(Q)return{result:"ask",matchedRule:Q.rule,matchType:Q.type,reason:`工具调用需要用户确认: ${Q.rule}`};return{result:"ask",reason:"工具调用未匹配任何规则,默认需要确认"}}static buildSignature($){let{toolName:Y,params:Z,tool:X}=$;try{if(X?.extractSignatureContent){let Q=X.extractSignatureContent(Z);return Q?`${Y}(${Q})`:Y}return Y}catch(Q){return console.warn(`Failed to build signature for ${Y}:`,Q instanceof Error?Q.message:Q),Y}}static abstractPattern($){let{toolName:Y,params:Z,tool:X}=$;try{if(X?.abstractPermissionRule){let Q=X.abstractPermissionRule(Z);if(Q==="")return"";return Q?`${Y}(${Q})`:Y}return Y}catch(Q){return console.warn(`Failed to abstract pattern for ${Y}:`,Q instanceof Error?Q.message:Q),Y}}matchRules($,Y){for(let Z of Y){let X=this.matchRule($,Z);if(X)return{rule:Z,type:X}}return null}matchRule($,Y){if($===Y)return"exact";if(Y==="*"||Y==="**")return"wildcard";let Z=this.extractToolName($),X=this.extractToolName(Y);if(!Z||!X)return null;if(X.includes("*")){if(!S$.isMatch(Z,X,{dot:!0,bash:!0}))return null}else if(Z!==X)return null;if(Y===X)return"prefix";if(Y.includes("*")){let Q=this.extractParams($),J=this.extractParams(Y);if(J==="*"||J==="**")return"wildcard";if(this.matchParams(Q,J))return J.includes("**")?"glob":"wildcard";if(S$.isMatch($,Y,{dot:!0,bash:!0}))return Y.includes("**")?"glob":"wildcard"}return null}extractParams($){let Y=$.match(/\(([\s\S]*)\)$/);return Y?Y[1]:""}matchParams($,Y){if(!$||!Y)return!1;let Z=this.parseParamPairs($),X=this.parseParamPairs(Y),Q=Object.keys(X).length>0,J=Object.keys(Z).length>0;if(Q!==J)return!1;if(!Q&&!J){if(Y==="*"||Y==="**")return!0;if(Y.includes("*")||Y.includes("{")||Y.includes("?"))return S$.isMatch($,Y,{dot:!0,bash:!0});return $===Y}for(let[q,G]of Object.entries(X)){let K=Z[q];if(K===void 0)return!1;if(G.includes("*")||G.includes("{")||G.includes("?")){if(G==="*"||G==="**")continue;if(!S$.isMatch(K,G,{dot:!0,bash:!0}))return!1}else if(K!==G)return!1}return!0}parseParamPairs($){let Y={},Z=this.smartSplit($,",");for(let X of Z){let Q=this.findTopLevelDelimiter(X,":");if(Q>0){let J=X.slice(0,Q).trim(),q=X.slice(Q+1).trim();Y[J]=q}}return Y}smartSplit($,Y){let Z=[],X="",Q=0,J=0,q=0,G=!1,K="",W=!1;for(let U=0;U<$.length;U++){let H=$[U];if(W){X+=H,W=!1;continue}if(H==="\\"){X+=H,W=!0;continue}if(!G&&H==="{")Q++;else if(!G&&H==="}")Q--;else if(!G&&H==="(")J++;else if(!G&&H===")")J--;else if(!G&&H==="[")q++;else if(!G&&H==="]")q--;if((H==='"'||H==="'")&&!G){G=!0,K=H,X+=H;continue}else if(G&&H===K){G=!1,K="",X+=H;continue}if(H===Y&&Q===0&&J===0&&q===0&&!G)Z.push(X.trim()),X="";else X+=H}if(X)Z.push(X.trim());return Z}findTopLevelDelimiter($,Y){let Z=0,X=0,Q=0,J=!1,q="",G=!1;for(let K=0;K<$.length;K++){let W=$[K];if(G){G=!1;continue}if(W==="\\"){G=!0;continue}if(!J&&W==="{")Z++;else if(!J&&W==="}")Z--;else if(!J&&W==="(")X++;else if(!J&&W===")")X--;else if(!J&&W==="[")Q++;else if(!J&&W==="]")Q--;if((W==='"'||W==="'")&&!J){J=!0,q=W;continue}else if(J&&W===q){J=!1,q="";continue}if(W===Y&&Z===0&&X===0&&Q===0&&!J)return K}return-1}extractToolName($){let Y=$.match(/^([A-Za-z0-9_]+)(\(|$)/);return Y?Y[1]:null}isAllowed($){return this.check($).result==="allow"}isDenied($){return this.check($).result==="deny"}needsConfirmation($){return this.check($).result==="ask"}updateConfig($){if($.allow)this.config.allow=[...this.config.allow,...$.allow];if($.ask)this.config.ask=[...this.config.ask,...$.ask];if($.deny)this.config.deny=[...this.config.deny,...$.deny]}replaceConfig($){this.config={...$}}getConfig(){return{...this.config}}}var f4=()=>{};var m2=D(()=>{k7();S7();S4();f4();s1()});var pQ,h4=($)=>({...pQ,actions:{setInitializationStatus:(Y)=>{$((Z)=>({app:{...Z.app,initializationStatus:Y}}))},setInitializationError:(Y)=>{$((Z)=>({app:{...Z.app,initializationError:Y}}))},setActiveModal:(Y)=>{$((Z)=>({app:{...Z.app,activeModal:Y}}))},showSessionSelector:(Y)=>{$((Z)=>({app:{...Z.app,activeModal:"sessionSelector",sessionSelectorData:Y}}))},showModelEditWizard:(Y)=>{$((Z)=>({app:{...Z.app,activeModal:"modelEditWizard",modelEditorTarget:Y}}))},closeModal:()=>{$((Y)=>({app:{...Y.app,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null}}))},setTodos:(Y)=>{$((Z)=>({app:{...Z.app,todos:Y}}))},updateTodo:(Y)=>{$((Z)=>({app:{...Z.app,todos:Z.app.todos.map((X)=>X.id===Y.id?Y:X)}}))},setAwaitingSecondCtrlC:(Y)=>{$((Z)=>({app:{...Z.app,awaitingSecondCtrlC:Y}}))},setThinkingModeEnabled:(Y)=>{$((Z)=>({app:{...Z.app,thinkingModeEnabled:Y}}))},toggleThinkingMode:()=>{$((Y)=>({app:{...Y.app,thinkingModeEnabled:!Y.app.thinkingModeEnabled}}))}}});var C7=D(()=>{pQ={initializationStatus:"idle",initializationError:null,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null,todos:[],awaitingSecondCtrlC:!1,thinkingModeEnabled:!1}});var gQ,x4=($,Y)=>({...gQ,actions:{setProcessing:(Z)=>{$((X)=>({command:{...X.command,isProcessing:Z}}))},createAbortController:()=>{let Z=new AbortController;return $((X)=>({command:{...X.command,abortController:Z}})),Z},clearAbortController:()=>{$((Z)=>({command:{...Z.command,abortController:null}}))},abort:()=>{let{abortController:Z}=Y().command;if(Z&&!Z.signal.aborted)Z.abort();$((X)=>({command:{...X.command,isProcessing:!1,abortController:null,pendingCommands:[]}}))},enqueueCommand:(Z)=>{$((X)=>({command:{...X.command,pendingCommands:[...X.command.pendingCommands,Z]}}))},dequeueCommand:()=>{let{pendingCommands:Z}=Y().command;if(Z.length===0)return;let[X,...Q]=Z;return $((J)=>({command:{...J.command,pendingCommands:Q}})),X},clearQueue:()=>{$((Z)=>({command:{...Z.command,pendingCommands:[]}}))}}});var f7=D(()=>{gQ={isProcessing:!1,abortController:null,pendingCommands:[]}});var mQ,p4=($)=>({...mQ,actions:{setConfig:(Y)=>{$((Z)=>({config:{...Z.config,config:Y}}))},updateConfig:(Y)=>{$((Z)=>{if(!Z.config.config)throw Error(`[ConfigSlice] Config not initialized. Cannot update: ${JSON.stringify(Y)}`);return{config:{...Z.config,config:{...Z.config.config,...Y}}}})}}});var h7=D(()=>{mQ={config:null}});var dQ,g4=($)=>({...dQ,actions:{setFocus:(Y)=>{$((Z)=>({focus:{...Z.focus,currentFocus:Y,previousFocus:Z.focus.currentFocus}}))},restorePreviousFocus:()=>{$((Y)=>({focus:{...Y.focus,currentFocus:Y.focus.previousFocus||"main-input",previousFocus:null}}))}}});var x7=D(()=>{dQ={currentFocus:"main-input",previousFocus:null}});import{nanoid as uQ}from"nanoid";var g7,p7,m4=($,Y)=>({...p7,actions:{addMessage:(Z)=>{$((X)=>({session:{...X.session,messages:[...X.session.messages,Z],error:null}}))},addUserMessage:(Z)=>{let X={id:`user-${Date.now()}-${Math.random()}`,role:"user",content:Z,timestamp:Date.now()};Y().session.actions.addMessage(X)},addAssistantMessage:(Z,X)=>{let Q={id:`assistant-${Date.now()}-${Math.random()}`,role:"assistant",content:Z,timestamp:Date.now(),thinkingContent:X};Y().session.actions.addMessage(Q)},addToolMessage:(Z,X)=>{let Q={id:`tool-${Date.now()}-${Math.random()}`,role:"tool",content:Z,timestamp:Date.now(),metadata:X};Y().session.actions.addMessage(Q)},setCompacting:(Z)=>{$((X)=>({session:{...X.session,isCompacting:Z}}))},setCommand:(Z)=>{$((X)=>({session:{...X.session,currentCommand:Z}}))},setError:(Z)=>{$((X)=>({session:{...X.session,error:Z}}))},clearMessages:()=>{$((Z)=>({session:{...Z.session,messages:[],error:null,clearCount:Z.session.clearCount+1}}))},resetSession:()=>{$((Z)=>({session:{...Z.session,...p7,sessionId:Z.session.sessionId,isActive:!0}}))},restoreSession:(Z,X)=>{$((Q)=>({session:{...Q.session,sessionId:Z,messages:X,error:null,isActive:!0}}))},updateTokenUsage:(Z)=>{$((X)=>({session:{...X.session,tokenUsage:{...X.session.tokenUsage,...Z}}}))},resetTokenUsage:()=>{$((Z)=>({session:{...Z.session,tokenUsage:{...g7}}}))},setCurrentThinkingContent:(Z)=>{$((X)=>({session:{...X.session,currentThinkingContent:Z}}))},appendThinkingContent:(Z)=>{$((X)=>({session:{...X.session,currentThinkingContent:(X.session.currentThinkingContent||"")+Z}}))},setThinkingExpanded:(Z)=>{$((X)=>({session:{...X.session,thinkingExpanded:Z}}))},toggleThinkingExpanded:()=>{$((Z)=>({session:{...Z.session,thinkingExpanded:!Z.session.thinkingExpanded}}))},setHistoryExpanded:(Z)=>{$((X)=>({session:{...X.session,historyExpanded:Z}}))},toggleHistoryExpanded:()=>{$((Z)=>({session:{...Z.session,historyExpanded:!Z.session.historyExpanded}}))},setExpandedMessageCount:(Z)=>{$((X)=>({session:{...X.session,expandedMessageCount:Z}}))}}});var m7=D(()=>{g7={inputTokens:0,outputTokens:0,totalTokens:0,maxContextTokens:200000},p7={sessionId:uQ(),messages:[],isCompacting:!1,currentCommand:null,error:null,isActive:!0,tokenUsage:{...g7},currentThinkingContent:null,thinkingExpanded:!1,clearCount:0,historyExpanded:!1,expandedMessageCount:30}});var d7=D(()=>{C7();f7();h7();x7();m7()});import{nanoid as cQ}from"nanoid";import{devtools as lQ,subscribeWithSelector as iQ}from"zustand/middleware";import{createStore as rQ}from"zustand/vanilla";async function B6(){if(V1()!==null)return;if(d2)return d2;return d2=(async()=>{try{let Z=await u1.getInstance().initialize();s().config.actions.setConfig(Z)}catch(Y){throw d2=null,Error(`❌ Store 未初始化且无法自动初始化
30
30
 
31
31
  `+`原因: ${Y instanceof Error?Y.message:"未知错误"}
32
32
 
33
33
  `+`请确保:
34
34
  `+`1. 配置文件格式正确 (~/.blade/config.json)
35
35
  `+`2. 运行 blade 进行首次配置
36
- `+"3. 配置文件权限正确")}finally{g2=null}})(),g2}var v$,n=()=>v$.getState(),SQ,P$=()=>n().session.actions,w0=()=>n().app.actions,T7=()=>n().session.messages,V1=()=>n().config.config,g2=null,T$=()=>n().config.config?.models??[],m2=()=>{let $=V1();if(!$)return;let Y=$.currentModelId;return $.models.find((X)=>X.id===Y)??$.models[0]},X0=()=>n().config.config?.mcpServers??{},U1=()=>({setPermissionMode:async($)=>{n().config.actions.updateConfig({permissionMode:$})},setTheme:async($,Y={})=>{n().config.actions.updateConfig({theme:$}),await f1().save({theme:$},{scope:"global",...Y})},setLanguage:async($,Y={})=>{n().config.actions.updateConfig({language:$}),await f1().save({language:$},{scope:"global",...Y})},setDebug:async($,Y={})=>{n().config.actions.updateConfig({debug:$}),await f1().save({debug:$},{scope:"global",...Y})},setTemperature:async($,Y={})=>{n().config.actions.updateConfig({temperature:$}),await f1().save({temperature:$},{scope:"global",...Y})},updateConfig:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let X={...Z};n().config.actions.updateConfig($);try{await f1().save($,Y)}catch(Q){throw n().config.actions.setConfig(X),Q}},flush:async()=>{await f1().flush()},appendPermissionAllowRule:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let X=Z.permissions?.allow||[];if(!X.includes($)){let Q=[...X,$];n().config.actions.updateConfig({permissions:{...Z.permissions,allow:Q}})}await f1().appendPermissionRule($,Y)},appendLocalPermissionAllowRule:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let X=Z.permissions?.allow||[];if(!X.includes($)){let Q=[...X,$];n().config.actions.updateConfig({permissions:{...Z.permissions,allow:Q}})}await f1().appendLocalPermissionRule($,Y)},setCurrentModel:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");if(!Z.models.find((Q)=>Q.id===$))throw Error(`Model not found: ${$}`);n().config.actions.updateConfig({currentModelId:$}),await f1().save({currentModelId:$},{scope:"global",...Y})},addModel:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let X="id"in $?$:{id:yQ(),...$},J={models:[...Z.models,X]};if(Z.models.length===0)J.currentModelId=X.id;return n().config.actions.updateConfig(J),await f1().save(J,{scope:"global",...Y}),X},updateModel:async($,Y,Z={})=>{let X=V1();if(!X)throw Error("Config not initialized");let Q=X.models.findIndex((q)=>q.id===$);if(Q===-1)throw Error(`Model not found: ${$}`);let J=[...X.models];J[Q]={...J[Q],...Y},n().config.actions.updateConfig({models:J}),await f1().save({models:J},{scope:"global",...Z})},removeModel:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");if(Z.models.length===1)throw Error("Cannot remove the only model");let X=Z.models.filter((J)=>J.id!==$),Q={models:X};if(Z.currentModelId===$)Q.currentModelId=X[0].id;n().config.actions.updateConfig(Q),await f1().save(Q,{scope:"global",...Y})},addMcpServer:async($,Y,Z={})=>{let X=V1();if(!X)throw Error("Config not initialized");let J={...X.mcpServers??{},[$]:Y};n().config.actions.updateConfig({mcpServers:J}),await f1().save({mcpServers:J},{scope:"project",...Z})},removeMcpServer:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let Q={...Z.mcpServers??{}};delete Q[$],n().config.actions.updateConfig({mcpServers:Q}),await f1().save({mcpServers:Q},{scope:"project",...Y})}});var F1=R(()=>{p2();P7();v$=TQ()(vQ(PQ((...$)=>({session:S4(...$),app:y4(...$),config:P4(...$),focus:T4(...$),command:v4(...$)})),{name:"BladeStore",enabled:!0})),SQ=v$.subscribe});function S$($){return $==="readonly"}var y0=()=>{};class f4{toolName;params;context;aborted=!1;result;_internal={};constructor($,Y,Z){this.toolName=$;this.params=Y;this.context=Z}shouldAbort(){return this.aborted||(this.context.signal?.aborted??!1)}abort($,Y){this.aborted=!0,this.result={success:!1,llmContent:`Tool execution aborted: ${$||"Unknown reason"}`,displayContent:`执行已中止: ${$||"未知原因"}`,error:{type:"execution_error",message:$||"Execution aborted"},metadata:Y?.shouldExitLoop?{shouldExitLoop:!0}:void 0}}setResult($){this.result=$}getResult(){if(!this.result)throw Error("Tool execution result not set");return this.result}}var h4=R(()=>{y0()});var h1=R(()=>{h4();y0()});function CQ($){let{code:Y}=$,Z=$.received;switch(Y){case"invalid_type":return`类型错误:期望 ${$.expected},实际收到 ${Z}`;case"too_small":{let{minimum:X,inclusive:Q}=$;if($.type==="string")return`长度不能少于 ${X} 个字符`;if($.type==="number")return`不能小于${Q?"等于":""} ${X}`;if($.type==="array")return`数组长度不能少于 ${X}`;return"值太小"}case"too_big":{let{maximum:X,inclusive:Q}=$;if($.type==="string")return`长度不能超过 ${X} 个字符`;if($.type==="number")return`不能大于${Q?"等于":""} ${X}`;if($.type==="array")return`数组长度不能超过 ${X}`;return"值太大"}case"invalid_string":{let X=$.validation;if(X==="email")return"必须是有效的电子邮件地址";if(X==="url")return"必须是有效的 URL";if(X==="uuid")return"必须是有效的 UUID";if(typeof X==="object"&&X.includes)return`必须包含 "${X.includes}"`;if(typeof X==="object"&&X.startsWith)return`必须以 "${X.startsWith}" 开头`;if(typeof X==="object"&&X.endsWith)return`必须以 "${X.endsWith}" 结尾`;return"字符串格式不正确"}case"invalid_enum_value":return`必须是以下值之一:${$.options.join(", ")}`;case"invalid_literal":return`必须是字面量值:${$.expected}`;case"unrecognized_keys":return`包含未知的参数:${$.keys.join(", ")}`;case"invalid_union":return"不符合任何有效的类型定义";case"invalid_date":return"必须是有效的日期";case"custom":return $.message||"自定义验证失败";default:return $.message||"验证失败"}}function fQ($){let Y=$.issues.map((X)=>{let Q=X.path.join("."),J=CQ(X),q=X.received;return{field:Q||"root",message:J,value:q}}),Z=Y.length===1?`参数验证失败 [${Y[0].field}]: ${Y[0].message}`:`参数验证失败 (${Y.length} 个错误):
36
+ `+"3. 配置文件权限正确")}finally{d2=null}})(),d2}var C$,s=()=>C$.getState(),aQ,f$=()=>s().session.actions,w0=()=>s().app.actions,u7=()=>s().session.messages,V1=()=>s().config.config,d2=null,h$=()=>s().config.config?.models??[],u2=()=>{let $=V1();if(!$)return;let Y=$.currentModelId;return $.models.find((X)=>X.id===Y)??$.models[0]},Q0=()=>s().config.config?.mcpServers??{},H1=()=>({setPermissionMode:async($)=>{s().config.actions.updateConfig({permissionMode:$})},setTheme:async($,Y={})=>{s().config.actions.updateConfig({theme:$}),await x1().save({theme:$},{scope:"global",...Y})},setLanguage:async($,Y={})=>{s().config.actions.updateConfig({language:$}),await x1().save({language:$},{scope:"global",...Y})},setDebug:async($,Y={})=>{s().config.actions.updateConfig({debug:$}),await x1().save({debug:$},{scope:"global",...Y})},setTemperature:async($,Y={})=>{s().config.actions.updateConfig({temperature:$}),await x1().save({temperature:$},{scope:"global",...Y})},updateConfig:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let X={...Z};s().config.actions.updateConfig($);try{await x1().save($,Y)}catch(Q){throw s().config.actions.setConfig(X),Q}},flush:async()=>{await x1().flush()},appendPermissionAllowRule:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let X=Z.permissions?.allow||[];if(!X.includes($)){let Q=[...X,$];s().config.actions.updateConfig({permissions:{...Z.permissions,allow:Q}})}await x1().appendPermissionRule($,Y)},appendLocalPermissionAllowRule:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let X=Z.permissions?.allow||[];if(!X.includes($)){let Q=[...X,$];s().config.actions.updateConfig({permissions:{...Z.permissions,allow:Q}})}await x1().appendLocalPermissionRule($,Y)},setCurrentModel:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");if(!Z.models.find((Q)=>Q.id===$))throw Error(`Model not found: ${$}`);s().config.actions.updateConfig({currentModelId:$}),await x1().save({currentModelId:$},{scope:"global",...Y})},addModel:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let X="id"in $?$:{id:cQ(),...$},J={models:[...Z.models,X]};if(Z.models.length===0)J.currentModelId=X.id;return s().config.actions.updateConfig(J),await x1().save(J,{scope:"global",...Y}),X},updateModel:async($,Y,Z={})=>{let X=V1();if(!X)throw Error("Config not initialized");let Q=X.models.findIndex((q)=>q.id===$);if(Q===-1)throw Error(`Model not found: ${$}`);let J=[...X.models];J[Q]={...J[Q],...Y},s().config.actions.updateConfig({models:J}),await x1().save({models:J},{scope:"global",...Z})},removeModel:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");if(Z.models.length===1)throw Error("Cannot remove the only model");let X=Z.models.filter((J)=>J.id!==$),Q={models:X};if(Z.currentModelId===$)Q.currentModelId=X[0].id;s().config.actions.updateConfig(Q),await x1().save(Q,{scope:"global",...Y})},addMcpServer:async($,Y,Z={})=>{let X=V1();if(!X)throw Error("Config not initialized");let J={...X.mcpServers??{},[$]:Y};s().config.actions.updateConfig({mcpServers:J}),await x1().save({mcpServers:J},{scope:"project",...Z})},removeMcpServer:async($,Y={})=>{let Z=V1();if(!Z)throw Error("Config not initialized");let Q={...Z.mcpServers??{}};delete Q[$],s().config.actions.updateConfig({mcpServers:Q}),await x1().save({mcpServers:Q},{scope:"project",...Y})}});var z1=D(()=>{m2();d7();C$=rQ()(lQ(iQ((...$)=>({session:m4(...$),app:h4(...$),config:p4(...$),focus:g4(...$),command:x4(...$)})),{name:"BladeStore",enabled:!0})),aQ=C$.subscribe});function x$($){return $==="readonly"}var y0=()=>{};class u4{toolName;params;context;aborted=!1;result;_internal={};constructor($,Y,Z){this.toolName=$;this.params=Y;this.context=Z}shouldAbort(){return this.aborted||(this.context.signal?.aborted??!1)}abort($,Y){this.aborted=!0,this.result={success:!1,llmContent:`Tool execution aborted: ${$||"Unknown reason"}`,displayContent:`执行已中止: ${$||"未知原因"}`,error:{type:"execution_error",message:$||"Execution aborted"},metadata:Y?.shouldExitLoop?{shouldExitLoop:!0}:void 0}}setResult($){this.result=$}getResult(){if(!this.result)throw Error("Tool execution result not set");return this.result}}var c4=D(()=>{y0()});var p1=D(()=>{c4();y0()});function nQ($){let{code:Y}=$,Z=$.received;switch(Y){case"invalid_type":return`类型错误:期望 ${$.expected},实际收到 ${Z}`;case"too_small":{let{minimum:X,inclusive:Q}=$;if($.type==="string")return`长度不能少于 ${X} 个字符`;if($.type==="number")return`不能小于${Q?"等于":""} ${X}`;if($.type==="array")return`数组长度不能少于 ${X}`;return"值太小"}case"too_big":{let{maximum:X,inclusive:Q}=$;if($.type==="string")return`长度不能超过 ${X} 个字符`;if($.type==="number")return`不能大于${Q?"等于":""} ${X}`;if($.type==="array")return`数组长度不能超过 ${X}`;return"值太大"}case"invalid_string":{let X=$.validation;if(X==="email")return"必须是有效的电子邮件地址";if(X==="url")return"必须是有效的 URL";if(X==="uuid")return"必须是有效的 UUID";if(typeof X==="object"&&X.includes)return`必须包含 "${X.includes}"`;if(typeof X==="object"&&X.startsWith)return`必须以 "${X.startsWith}" 开头`;if(typeof X==="object"&&X.endsWith)return`必须以 "${X.endsWith}" 结尾`;return"字符串格式不正确"}case"invalid_enum_value":return`必须是以下值之一:${$.options.join(", ")}`;case"invalid_literal":return`必须是字面量值:${$.expected}`;case"unrecognized_keys":return`包含未知的参数:${$.keys.join(", ")}`;case"invalid_union":return"不符合任何有效的类型定义";case"invalid_date":return"必须是有效的日期";case"custom":return $.message||"自定义验证失败";default:return $.message||"验证失败"}}function oQ($){let Y=$.issues.map((X)=>{let Q=X.path.join("."),J=nQ(X),q=X.received;return{field:Q||"root",message:J,value:q}}),Z=Y.length===1?`参数验证失败 [${Y[0].field}]: ${Y[0].message}`:`参数验证失败 (${Y.length} 个错误):
37
37
  ${Y.map((X)=>` - ${X.field}: ${X.message}`).join(`
38
- `)}`;return new p7(Z,Y)}function g7($,Y){let Z=$.safeParse(Y);if(!Z.success)throw fQ(Z.error);return Z.data}var p7;var m7=R(()=>{h1();p7=class p7 extends Error{issues;type;constructor($,Y,Z="validation_error"){super($);this.issues=Y;this.type=Z;this.name="ToolValidationError"}}});import{zodToJsonSchema as hQ}from"zod-to-json-schema";function x4($){return hQ($,{target:"jsonSchema7",$refStrategy:"none"})}var d7=()=>{};class p4{toolName;params;executeFn;descriptionFn;affectedPathsFn;constructor($,Y,Z,X,Q){this.toolName=$;this.params=Y;this.executeFn=Z;this.descriptionFn=X;this.affectedPathsFn=Q}getDescription(){if(this.descriptionFn)return this.descriptionFn(this.params);return`执行工具: ${this.toolName}`}getAffectedPaths(){if(this.affectedPathsFn)return this.affectedPathsFn(this.params);return[]}async execute($,Y,Z){let X={signal:$,updateOutput:Y,...Z};return this.executeFn(this.params,X)}}function e($){return{name:$.name,displayName:$.displayName,kind:$.kind,isReadOnly:$.isReadOnly??S$($.kind),isConcurrencySafe:$.isConcurrencySafe??!0,strict:$.strict??!1,description:$.description,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],getFunctionDeclaration(){let Y=x4($.schema),Z=$.description.short;if($.description.long)Z+=`
38
+ `)}`;return new n7(Z,Y)}function o7($,Y){let Z=$.safeParse(Y);if(!Z.success)throw oQ(Z.error);return Z.data}var n7;var s7=D(()=>{p1();n7=class n7 extends Error{issues;type;constructor($,Y,Z="validation_error"){super($);this.issues=Y;this.type=Z;this.name="ToolValidationError"}}});import{zodToJsonSchema as sQ}from"zod-to-json-schema";function l4($){return sQ($,{target:"jsonSchema7",$refStrategy:"none"})}var t7=()=>{};class i4{toolName;params;executeFn;descriptionFn;affectedPathsFn;constructor($,Y,Z,X,Q){this.toolName=$;this.params=Y;this.executeFn=Z;this.descriptionFn=X;this.affectedPathsFn=Q}getDescription(){if(this.descriptionFn)return this.descriptionFn(this.params);return`执行工具: ${this.toolName}`}getAffectedPaths(){if(this.affectedPathsFn)return this.affectedPathsFn(this.params);return[]}async execute($,Y,Z){let X={signal:$,updateOutput:Y,...Z};return this.executeFn(this.params,X)}}function Y1($){return{name:$.name,displayName:$.displayName,kind:$.kind,isReadOnly:$.isReadOnly??x$($.kind),isConcurrencySafe:$.isConcurrencySafe??!0,strict:$.strict??!1,description:$.description,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],getFunctionDeclaration(){let Y=l4($.schema),Z=$.description.short;if($.description.long)Z+=`
39
39
 
40
40
  ${$.description.long}`;if($.description.usageNotes&&$.description.usageNotes.length>0)Z+=`
41
41
 
@@ -45,12 +45,12 @@ ${$.description.usageNotes.map((X)=>`- ${X}`).join(`
45
45
 
46
46
  Important:
47
47
  ${$.description.important.map((X)=>`⚠️ ${X}`).join(`
48
- `)}`;return{name:$.name,description:Z,parameters:Y}},getMetadata(){return{name:$.name,displayName:$.displayName,kind:$.kind,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],description:$.description,schema:x4($.schema)}},build(Y){let Z=g7($.schema,Y);return new p4($.name,Z,$.execute)},async execute(Y,Z){return this.build(Y).execute(Z||new AbortController().signal)},extractSignatureContent:$.extractSignatureContent?(Y)=>$.extractSignatureContent(Y):void 0,abstractPermissionRule:$.abstractPermissionRule?(Y)=>$.abstractPermissionRule(Y):void 0}}var k1=R(()=>{y0();m7();d7()});import{z as Q0}from"zod";function O6($,Y,Z,X){let Q;try{Q=C$(Z.inputSchema)}catch(q){console.warn(`[createMcpTool] Schema 转换失败,使用降级 schema: ${Z.name}`,q),Q=Q0.any()}let J=X||Z.name;return e({name:J,displayName:`${Y}: ${Z.name}`,kind:"execute",schema:Q,description:{short:Z.description||`MCP Tool: ${Z.name}`,important:[`From MCP server: ${Y}`,"Executes external tools; user confirmation required"]},category:"MCP tool",tags:["mcp","external",Y],async execute(q,K){try{let G=await $.callTool(Z.name,q),W="",U="";if(G.content&&Array.isArray(G.content)){for(let H of G.content)if(H.type==="text"&&H.text)W+=H.text,U+=H.text;else if(H.type==="image")U+=`[图片: ${H.mimeType||"unknown"}]
48
+ `)}`;return{name:$.name,description:Z,parameters:Y}},getMetadata(){return{name:$.name,displayName:$.displayName,kind:$.kind,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],description:$.description,schema:l4($.schema)}},build(Y){let Z=o7($.schema,Y);return new i4($.name,Z,$.execute)},async execute(Y,Z){return this.build(Y).execute(Z||new AbortController().signal)},extractSignatureContent:$.extractSignatureContent?(Y)=>$.extractSignatureContent(Y):void 0,abstractPermissionRule:$.abstractPermissionRule?(Y)=>$.abstractPermissionRule(Y):void 0}}var j1=D(()=>{y0();s7();t7()});import{z as J0}from"zod";function w6($,Y,Z,X){let Q;try{Q=p$(Z.inputSchema)}catch(q){console.warn(`[createMcpTool] Schema 转换失败,使用降级 schema: ${Z.name}`,q),Q=J0.any()}let J=X||Z.name;return Y1({name:J,displayName:`${Y}: ${Z.name}`,kind:"execute",schema:Q,description:{short:Z.description||`MCP Tool: ${Z.name}`,important:[`From MCP server: ${Y}`,"Executes external tools; user confirmation required"]},category:"MCP tool",tags:["mcp","external",Y],async execute(q,G){try{let K=await $.callTool(Z.name,q),W="",U="";if(K.content&&Array.isArray(K.content)){for(let H of K.content)if(H.type==="text"&&H.text)W+=H.text,U+=H.text;else if(H.type==="image")U+=`[图片: ${H.mimeType||"unknown"}]
49
49
  `,W+=`[image: ${H.mimeType||"unknown"}]
50
50
  `;else if(H.type==="resource")U+=`[资源: ${H.mimeType||"unknown"}]
51
51
  `,W+=`[resource: ${H.mimeType||"unknown"}]
52
- `}if(G.isError)return{success:!1,llmContent:W||"MCP tool execution failed",displayContent:`❌ ${U||"MCP工具执行失败"}`,error:{type:"execution_error",message:W||"MCP tool execution failed"}};return{success:!0,llmContent:W||"Execution succeeded",displayContent:`✅ MCP工具 ${Z.name} 执行成功
53
- ${U}`,metadata:{serverName:Y,toolName:Z.name,mcpResult:G}}}catch(G){return{success:!1,llmContent:`MCP tool execution failed: ${G.message}`,displayContent:`❌ ${G.message}`,error:{type:"execution_error",message:G.message}}}}})}function C$($){if($.type==="object"||$.properties){let Y={},Z=$.required||[];if($.properties){for(let[X,Q]of Object.entries($.properties))if(typeof Q==="object"&&Q!==null){let J=C$(Q);if(!Z.includes(X))J=J.optional();Y[X]=J}}return Q0.object(Y)}if($.type==="array"&&$.items){if(typeof $.items==="object"&&!Array.isArray($.items)&&$.items!==null)return Q0.array(C$($.items));return Q0.array(Q0.any())}if($.type==="string"){let Y=Q0.string();if($.minLength!==void 0)Y=Y.min($.minLength);if($.maxLength!==void 0)Y=Y.max($.maxLength);if($.pattern)Y=Y.regex(new RegExp($.pattern));if($.enum)return Q0.enum($.enum);return Y}if($.type==="number"||$.type==="integer"){let Y=Q0.number();if($.minimum!==void 0)Y=Y.min($.minimum);if($.maximum!==void 0)Y=Y.max($.maximum);return Y}if($.type==="boolean")return Q0.boolean();if($.oneOf&&$.oneOf.length>0){let Y=$.oneOf.filter((Z)=>typeof Z==="object"&&Z!==null).map((Z)=>C$(Z));if(Y.length>=2)return Q0.union(Y)}if($.anyOf&&$.anyOf.length>0){let Y=$.anyOf.filter((Z)=>typeof Z==="object"&&Z!==null).map((Z)=>C$(Z));if(Y.length>=2)return Q0.union(Y)}return Q0.any()}var u7=R(()=>{k1();h1()});import{promises as g4}from"fs";import xQ from"os";import m4 from"path";class z6{tokenFilePath;constructor(){let $=xQ.homedir(),Y=m4.join($,".blade");this.tokenFilePath=m4.join(Y,"mcp-oauth-tokens.json")}async ensureConfigDir(){let $=m4.dirname(this.tokenFilePath);try{await g4.mkdir($,{recursive:!0})}catch(Y){}}async loadAllCredentials(){let $=new Map;try{let Y=await g4.readFile(this.tokenFilePath,"utf-8"),Z=JSON.parse(Y);for(let X of Z)$.set(X.serverName,X)}catch(Y){if(Y.code!=="ENOENT")console.warn("[OAuthTokenStorage] 加载令牌失败:",Y)}return $}async saveAllCredentials($){await this.ensureConfigDir();let Y=Array.from($.values());await g4.writeFile(this.tokenFilePath,JSON.stringify(Y,null,2),{mode:384})}async saveToken($,Y,Z,X){let Q=await this.loadAllCredentials(),J={serverName:$,token:Y,clientId:Z,tokenUrl:X,updatedAt:Date.now()};Q.set($,J),await this.saveAllCredentials(Q)}async getCredentials($){return(await this.loadAllCredentials()).get($)||null}async deleteCredentials($){let Y=await this.loadAllCredentials();Y.delete($),await this.saveAllCredentials(Y)}async listServers(){let $=await this.loadAllCredentials();return Array.from($.keys())}isTokenExpired($){if(!$.expiresAt)return!1;let Y=300000;return Date.now()>=$.expiresAt-Y}}var d4=()=>{};import*as h$ from"crypto";import*as i7 from"http";import{spawn as pQ}from"child_process";import{URL as c7}from"url";class F6{tokenStorage;constructor($=new z6){this.tokenStorage=$}generatePKCEParams(){let $=h$.randomBytes(32).toString("base64url"),Y=h$.createHash("sha256").update($).digest("base64url"),Z=h$.randomBytes(16).toString("base64url");return{codeVerifier:$,codeChallenge:Y,state:Z}}buildAuthorizationUrl($,Y){let Z=$.redirectUri||`http://localhost:${f$}${u4}`,X=new URLSearchParams({client_id:$.clientId,response_type:"code",redirect_uri:Z,state:Y.state,code_challenge:Y.codeChallenge,code_challenge_method:"S256"});if($.scopes&&$.scopes.length>0)X.append("scope",$.scopes.join(" "));let Q=new c7($.authorizationUrl);return X.forEach((J,q)=>{Q.searchParams.append(q,J)}),Q.toString()}async startCallbackServer($){return new Promise((Y,Z)=>{let X=i7.createServer((Q,J)=>{try{let q=new c7(Q.url,`http://localhost:${f$}`);if(q.pathname!==u4){J.writeHead(404),J.end("Not found");return}let K=q.searchParams.get("code"),G=q.searchParams.get("state"),W=q.searchParams.get("error");if(W){J.writeHead(l7,{"Content-Type":"text/html"}),J.end(`
52
+ `}if(K.isError)return{success:!1,llmContent:W||"MCP tool execution failed",displayContent:`❌ ${U||"MCP工具执行失败"}`,error:{type:"execution_error",message:W||"MCP tool execution failed"}};return{success:!0,llmContent:W||"Execution succeeded",displayContent:`✅ MCP工具 ${Z.name} 执行成功
53
+ ${U}`,metadata:{serverName:Y,toolName:Z.name,mcpResult:K}}}catch(K){return{success:!1,llmContent:`MCP tool execution failed: ${K.message}`,displayContent:`❌ ${K.message}`,error:{type:"execution_error",message:K.message}}}}})}function p$($){if($.type==="object"||$.properties){let Y={},Z=$.required||[];if($.properties){for(let[X,Q]of Object.entries($.properties))if(typeof Q==="object"&&Q!==null){let J=p$(Q);if(!Z.includes(X))J=J.optional();Y[X]=J}}return J0.object(Y)}if($.type==="array"&&$.items){if(typeof $.items==="object"&&!Array.isArray($.items)&&$.items!==null)return J0.array(p$($.items));return J0.array(J0.any())}if($.type==="string"){let Y=J0.string();if($.minLength!==void 0)Y=Y.min($.minLength);if($.maxLength!==void 0)Y=Y.max($.maxLength);if($.pattern)Y=Y.regex(new RegExp($.pattern));if($.enum)return J0.enum($.enum);return Y}if($.type==="number"||$.type==="integer"){let Y=J0.number();if($.minimum!==void 0)Y=Y.min($.minimum);if($.maximum!==void 0)Y=Y.max($.maximum);return Y}if($.type==="boolean")return J0.boolean();if($.oneOf&&$.oneOf.length>0){let Y=$.oneOf.filter((Z)=>typeof Z==="object"&&Z!==null).map((Z)=>p$(Z));if(Y.length>=2)return J0.union(Y)}if($.anyOf&&$.anyOf.length>0){let Y=$.anyOf.filter((Z)=>typeof Z==="object"&&Z!==null).map((Z)=>p$(Z));if(Y.length>=2)return J0.union(Y)}return J0.any()}var e7=D(()=>{j1();p1()});import{promises as r4}from"fs";import tQ from"os";import a4 from"path";class L6{tokenFilePath;constructor(){let $=tQ.homedir(),Y=a4.join($,".blade");this.tokenFilePath=a4.join(Y,"mcp-oauth-tokens.json")}async ensureConfigDir(){let $=a4.dirname(this.tokenFilePath);try{await r4.mkdir($,{recursive:!0})}catch(Y){}}async loadAllCredentials(){let $=new Map;try{let Y=await r4.readFile(this.tokenFilePath,"utf-8"),Z=JSON.parse(Y);for(let X of Z)$.set(X.serverName,X)}catch(Y){if(Y.code!=="ENOENT")console.warn("[OAuthTokenStorage] 加载令牌失败:",Y)}return $}async saveAllCredentials($){await this.ensureConfigDir();let Y=Array.from($.values());await r4.writeFile(this.tokenFilePath,JSON.stringify(Y,null,2),{mode:384})}async saveToken($,Y,Z,X){let Q=await this.loadAllCredentials(),J={serverName:$,token:Y,clientId:Z,tokenUrl:X,updatedAt:Date.now()};Q.set($,J),await this.saveAllCredentials(Q)}async getCredentials($){return(await this.loadAllCredentials()).get($)||null}async deleteCredentials($){let Y=await this.loadAllCredentials();Y.delete($),await this.saveAllCredentials(Y)}async listServers(){let $=await this.loadAllCredentials();return Array.from($.keys())}isTokenExpired($){if(!$.expiresAt)return!1;let Y=300000;return Date.now()>=$.expiresAt-Y}}var n4=()=>{};import*as m$ from"crypto";import*as Z3 from"http";import{spawn as eQ}from"child_process";import{URL as $3}from"url";class A6{tokenStorage;constructor($=new L6){this.tokenStorage=$}generatePKCEParams(){let $=m$.randomBytes(32).toString("base64url"),Y=m$.createHash("sha256").update($).digest("base64url"),Z=m$.randomBytes(16).toString("base64url");return{codeVerifier:$,codeChallenge:Y,state:Z}}buildAuthorizationUrl($,Y){let Z=$.redirectUri||`http://localhost:${g$}${o4}`,X=new URLSearchParams({client_id:$.clientId,response_type:"code",redirect_uri:Z,state:Y.state,code_challenge:Y.codeChallenge,code_challenge_method:"S256"});if($.scopes&&$.scopes.length>0)X.append("scope",$.scopes.join(" "));let Q=new $3($.authorizationUrl);return X.forEach((J,q)=>{Q.searchParams.append(q,J)}),Q.toString()}async startCallbackServer($){return new Promise((Y,Z)=>{let X=Z3.createServer((Q,J)=>{try{let q=new $3(Q.url,`http://localhost:${g$}`);if(q.pathname!==o4){J.writeHead(404),J.end("Not found");return}let G=q.searchParams.get("code"),K=q.searchParams.get("state"),W=q.searchParams.get("error");if(W){J.writeHead(Y3,{"Content-Type":"text/html"}),J.end(`
54
54
  <html>
55
55
  <body>
56
56
  <h1>Authentication Failed</h1>
@@ -58,7 +58,7 @@ ${U}`,metadata:{serverName:Y,toolName:Z.name,mcpResult:G}}}catch(G){return{succe
58
58
  <p>You can close this window.</p>
59
59
  </body>
60
60
  </html>
61
- `),X.close(),Z(Error(`OAuth error: ${W}`));return}if(!K||!G){J.writeHead(400),J.end("Missing code or state parameter");return}if(G!==$){J.writeHead(400),J.end("Invalid state parameter"),X.close(),Z(Error("State mismatch - possible CSRF attack"));return}J.writeHead(l7,{"Content-Type":"text/html"}),J.end(`
61
+ `),X.close(),Z(Error(`OAuth error: ${W}`));return}if(!G||!K){J.writeHead(400),J.end("Missing code or state parameter");return}if(K!==$){J.writeHead(400),J.end("Invalid state parameter"),X.close(),Z(Error("State mismatch - possible CSRF attack"));return}J.writeHead(Y3,{"Content-Type":"text/html"}),J.end(`
62
62
  <html>
63
63
  <body>
64
64
  <h1>Authentication Successful!</h1>
@@ -66,18 +66,28 @@ ${U}`,metadata:{serverName:Y,toolName:Z.name,mcpResult:G}}}catch(G){return{succe
66
66
  <script>window.close();</script>
67
67
  </body>
68
68
  </html>
69
- `),X.close(),Y(K)}catch(q){X.close(),Z(q)}});X.on("error",Z),X.listen(f$,()=>{console.log(`[OAuth] Callback server listening on port ${f$}`)}),setTimeout(()=>{X.close(),Z(Error("OAuth callback timeout"))},300000)})}async exchangeCodeForToken($,Y,Z){let X=$.redirectUri||`http://localhost:${f$}${u4}`,Q=new URLSearchParams({grant_type:"authorization_code",code:Y,redirect_uri:X,code_verifier:Z,client_id:$.clientId});if($.clientSecret)Q.append("client_secret",$.clientSecret);let J=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Q.toString()});if(!J.ok){let q=await J.text();throw Error(`Token exchange failed: ${J.status} - ${q}`)}return await J.json()}async refreshAccessToken($,Y){let Z=new URLSearchParams({grant_type:"refresh_token",refresh_token:Y,client_id:$.clientId});if($.clientSecret)Z.append("client_secret",$.clientSecret);if($.scopes&&$.scopes.length>0)Z.append("scope",$.scopes.join(" "));let X=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Z.toString()});if(!X.ok){let Q=await X.text();throw Error(`Token refresh failed: ${X.status} - ${Q}`)}return await X.json()}async authenticate($,Y){if(!Y.clientId||!Y.authorizationUrl||!Y.tokenUrl)throw Error("Missing required OAuth configuration");let Z=this.generatePKCEParams(),X=this.buildAuthorizationUrl(Y,Z);console.log(`
69
+ `),X.close(),Y(G)}catch(q){X.close(),Z(q)}});X.on("error",Z),X.listen(g$,()=>{console.log(`[OAuth] Callback server listening on port ${g$}`)}),setTimeout(()=>{X.close(),Z(Error("OAuth callback timeout"))},300000)})}async exchangeCodeForToken($,Y,Z){let X=$.redirectUri||`http://localhost:${g$}${o4}`,Q=new URLSearchParams({grant_type:"authorization_code",code:Y,redirect_uri:X,code_verifier:Z,client_id:$.clientId});if($.clientSecret)Q.append("client_secret",$.clientSecret);let J=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Q.toString()});if(!J.ok){let q=await J.text();throw Error(`Token exchange failed: ${J.status} - ${q}`)}return await J.json()}async refreshAccessToken($,Y){let Z=new URLSearchParams({grant_type:"refresh_token",refresh_token:Y,client_id:$.clientId});if($.clientSecret)Z.append("client_secret",$.clientSecret);if($.scopes&&$.scopes.length>0)Z.append("scope",$.scopes.join(" "));let X=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Z.toString()});if(!X.ok){let Q=await X.text();throw Error(`Token refresh failed: ${X.status} - ${Q}`)}return await X.json()}async authenticate($,Y){if(!Y.clientId||!Y.authorizationUrl||!Y.tokenUrl)throw Error("Missing required OAuth configuration");let Z=this.generatePKCEParams(),X=this.buildAuthorizationUrl(Y,Z);console.log(`
70
70
  [OAuth] Opening browser for authentication...`),console.log(`
71
- If the browser does not open automatically, copy and paste this URL:`),console.log(X),console.log("");let Q=this.startCallbackServer(Z.state);try{await this.openAuthorizationUrl(X)}catch(G){console.warn("[OAuth] Failed to open browser automatically:",G)}let J=await Q;console.log("[OAuth] Authorization code received, exchanging for tokens...");let q=await this.exchangeCodeForToken(Y,J,Z.codeVerifier),K={accessToken:q.access_token,tokenType:q.token_type||"Bearer",refreshToken:q.refresh_token,scope:q.scope};if(q.expires_in)K.expiresAt=Date.now()+q.expires_in*1000;return await this.tokenStorage.saveToken($,K,Y.clientId,Y.tokenUrl),console.log("[OAuth] Authentication successful! Token saved."),K}async openAuthorizationUrl($){let{command:Y,args:Z}=this.getBrowserCommand($);await new Promise((X,Q)=>{let J=pQ(Y,Z,{stdio:"ignore"});J.once("error",Q),J.once("close",(q)=>{if(q===0||q===null)X();else Q(Error(`Failed to open browser (exit code ${q})`))})})}getBrowserCommand($){if(process.platform==="darwin")return{command:"open",args:[$]};if(process.platform==="win32")return{command:"cmd",args:["/c","start","",$]};return{command:"xdg-open",args:[$]}}async getValidToken($,Y){let Z=await this.tokenStorage.getCredentials($);if(!Z)return null;let{token:X}=Z;if(!this.tokenStorage.isTokenExpired(X))return X.accessToken;if(X.refreshToken&&Y.clientId&&Z.tokenUrl)try{console.log(`[OAuth] Refreshing expired token for server: ${$}`);let Q=await this.refreshAccessToken(Y,X.refreshToken),J={accessToken:Q.access_token,tokenType:Q.token_type,refreshToken:Q.refresh_token||X.refreshToken,scope:Q.scope||X.scope};if(Q.expires_in)J.expiresAt=Date.now()+Q.expires_in*1000;return await this.tokenStorage.saveToken($,J,Y.clientId,Z.tokenUrl),J.accessToken}catch(Q){console.error("[OAuth] Failed to refresh token:",Q),await this.tokenStorage.deleteCredentials($)}return null}}var f$=7777,u4="/oauth/callback",l7=200;var r7=R(()=>{d4()});var a7=R(()=>{r7();d4()});var d2=()=>{};import{EventEmitter as gQ}from"events";var c4;var n7=R(()=>{d2();c4=class c4 extends gQ{client;config;checkTimer=null;isChecking=!1;consecutiveFailures=0;lastCheckTime=0;currentStatus="healthy";constructor($,Y={}){super();this.client=$,this.config={interval:Y.interval??30000,timeout:Y.timeout??1e4,enabled:Y.enabled??!1,failureThreshold:Y.failureThreshold??3}}start(){if(this.checkTimer){console.warn("[HealthMonitor] 健康监控已在运行");return}if(!this.config.enabled){console.log("[HealthMonitor] 健康监控未启用");return}console.log(`[HealthMonitor] 启动健康监控(间隔: ${this.config.interval}ms)`),this.scheduleNextCheck()}stop(){if(this.checkTimer)clearTimeout(this.checkTimer),this.checkTimer=null,console.log("[HealthMonitor] 停止健康监控")}scheduleNextCheck(){this.checkTimer=setTimeout(async()=>{await this.performHealthCheck(),this.scheduleNextCheck()},this.config.interval)}async performHealthCheck(){if(this.isChecking)return console.warn("[HealthMonitor] 上一次检查仍在进行中"),this.getLastResult();this.isChecking=!0,this.lastCheckTime=Date.now(),this.setStatus("checking");try{let $=this.client.connectionStatus;if($==="connected"){await this.pingServer(),this.consecutiveFailures=0,this.setStatus("healthy");let Y={status:"healthy",timestamp:Date.now(),consecutiveFailures:0};return this.emit("healthCheck",Y),Y}else throw Error(`连接状态异常: ${$}`)}catch($){this.consecutiveFailures++;let Y=$;console.warn(`[HealthMonitor] 健康检查失败(${this.consecutiveFailures}/${this.config.failureThreshold}):`,Y.message);let Z;if(this.consecutiveFailures>=this.config.failureThreshold)Z="unhealthy",this.emit("unhealthy",this.consecutiveFailures,Y),console.log("[HealthMonitor] 达到失败阈值,触发重连..."),this.triggerReconnection().catch((Q)=>{console.error("[HealthMonitor] 重连失败:",Q)});else Z="degraded";this.setStatus(Z);let X={status:Z,timestamp:Date.now(),consecutiveFailures:this.consecutiveFailures,lastError:Y};return this.emit("healthCheck",X),X}finally{this.isChecking=!1}}async pingServer(){let $=new Promise((Z,X)=>{setTimeout(()=>X(Error("Health check timeout")),this.config.timeout)}),Y=(async()=>{if(this.client.availableTools.length===0){if(!this.client.server)throw Error("Server info not available")}})();await Promise.race([Y,$])}async triggerReconnection(){try{await this.client.disconnect(),await new Promise(($)=>setTimeout($,1000)),await this.client.connect(),console.log("[HealthMonitor] 重连成功"),this.consecutiveFailures=0,this.setStatus("healthy"),this.emit("reconnected")}catch($){throw console.error("[HealthMonitor] 重连失败:",$),$}}setStatus($){if(this.currentStatus!==$){let Y=this.currentStatus;this.currentStatus=$,this.emit("statusChanged",$,Y)}}getStatus(){return this.currentStatus}getLastResult(){return{status:this.currentStatus,timestamp:this.lastCheckTime,consecutiveFailures:this.consecutiveFailures}}getStatistics(){return{status:this.currentStatus,consecutiveFailures:this.consecutiveFailures,lastCheckTime:this.lastCheckTime,isChecking:this.isChecking,config:this.config}}async checkNow(){return this.performHealthCheck()}resetFailureCount(){if(this.consecutiveFailures=0,this.currentStatus!=="checking")this.setStatus("healthy")}}});import{Client as mQ}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as dQ}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as uQ}from"@modelcontextprotocol/sdk/client/stdio.js";import{EventEmitter as cQ}from"events";function o7($){if(!($ instanceof Error))return{type:"unknown",isRetryable:!1,originalError:Error(String($))};let Y=$.message.toLowerCase();if(["command not found","no such file","permission denied","invalid configuration","malformed","syntax error"].some((Q)=>Y.includes(Q)))return{type:"config_error",isRetryable:!1,originalError:$};if(Y.includes("unauthorized")||Y.includes("401")||Y.includes("authentication failed"))return{type:"auth_error",isRetryable:!1,originalError:$};if(["timeout","connection refused","network error","temporary","try again","rate limit","too many requests","service unavailable","socket hang up","econnreset","enotfound","econnrefused","etimedout","503","429"].some((Q)=>Y.includes(Q)))return{type:"network_temporary",isRetryable:!0,originalError:$};return{type:"unknown",isRetryable:!0,originalError:$}}var l4;var s7=R(()=>{k$();a7();n7();d2();l4=class l4 extends cQ{config;status="disconnected";sdkClient=null;tools=new Map;serverInfo=null;reconnectAttempts=0;MAX_RECONNECT_ATTEMPTS=5;reconnectTimer=null;isManualDisconnect=!1;oauthProvider=null;serverName;healthMonitor=null;constructor($,Y,Z){super();this.config=$;if(this.serverName=Y||"default",$.oauth?.enabled)this.oauthProvider=new F6;if(Z?.enabled)this.healthMonitor=new c4(this,Z),this.healthMonitor.on("unhealthy",(X,Q)=>{this.emit("unhealthy",X,Q)}),this.healthMonitor.on("reconnected",()=>{this.emit("healthMonitorReconnected")})}get connectionStatus(){return this.status}get availableTools(){return Array.from(this.tools.values())}get server(){return this.serverInfo}get healthCheck(){return this.healthMonitor}async connect(){return this.connectWithRetry(3,1000)}async connectWithRetry($=3,Y=1000){if(this.status!=="disconnected")throw Error("客户端已连接或正在连接中");let Z=null;for(let X=1;X<=$;X++)try{await this.doConnect(),this.reconnectAttempts=0;return}catch(Q){Z=Q;let J=o7(Q);if(!J.isRetryable)throw console.error("[McpClient] 检测到永久性错误,放弃重试:",J.type),Q;if(X<$){let q=Y*Math.pow(2,X-1);console.warn(`[McpClient] 连接失败(${X}/${$}),${q}ms 后重试...`),await new Promise((K)=>setTimeout(K,q))}}throw Z||Error("连接失败")}async doConnect(){try{this.setStatus("connecting"),this.sdkClient=new mQ({name:H7(),version:f2()},{capabilities:{roots:{listChanged:!0},sampling:{}}}),this.sdkClient.onclose=()=>{this.handleUnexpectedClose()};let $=await this.createTransport();await this.sdkClient.connect($);let Y=this.sdkClient.getServerVersion();if(this.serverInfo={name:Y?.name||"Unknown",version:Y?.version||"0.0.0"},await this.loadTools(),this.setStatus("connected"),this.emit("connected",this.serverInfo),this.healthMonitor)this.healthMonitor.start()}catch($){throw this.setStatus("error"),this.emit("error",$),$}}handleUnexpectedClose(){if(this.isManualDisconnect)return;if(this.status==="connected")console.warn("[McpClient] 检测到意外断连,准备重连..."),this.setStatus("error"),this.emit("error",Error("MCP服务器连接意外关闭")),this.scheduleReconnect()}scheduleReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.reconnectAttempts>=this.MAX_RECONNECT_ATTEMPTS){console.error("[McpClient] 达到最大重连次数,放弃重连"),this.emit("reconnectFailed");return}let $=Math.min(1000*Math.pow(2,this.reconnectAttempts),30000);this.reconnectAttempts++,console.log(`[McpClient] 将在 ${$}ms 后进行第 ${this.reconnectAttempts} 次重连...`),this.reconnectTimer=setTimeout(async()=>{try{if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected"),await this.doConnect(),console.log("[McpClient] 重连成功"),this.reconnectAttempts=0,this.emit("reconnected")}catch(Y){if(console.error("[McpClient] 重连失败:",Y),o7(Y).isRetryable)this.scheduleReconnect();else console.error("[McpClient] 检测到永久性错误,停止重连"),this.emit("reconnectFailed")}},$)}async disconnect(){if(this.isManualDisconnect=!0,this.healthMonitor)this.healthMonitor.stop();if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.sdkClient){try{await this.sdkClient.close()}catch($){console.warn("[McpClient] 断开连接时出错:",$)}this.sdkClient=null}this.tools.clear(),this.serverInfo=null,this.reconnectAttempts=0,this.setStatus("disconnected"),this.emit("disconnected"),this.isManualDisconnect=!1}async callTool($,Y={}){if(!this.sdkClient)throw Error("客户端未连接到服务器");if(!this.tools.has($))throw Error(`工具 "${$}" 不存在`);try{return await this.sdkClient.callTool({name:$,arguments:Y})}catch(Z){throw console.error(`[McpClient] 调用工具 "${$}" 失败:`,Z),Z}}async createTransport(){let{type:$,command:Y,args:Z,env:X,url:Q,headers:J,oauth:q}=this.config,K={...J};if(q?.enabled&&this.oauthProvider&&($==="sse"||$==="http"))try{let G=await this.oauthProvider.getValidToken(this.serverName,q);if(!G){console.log(`[McpClient] 服务器 "${this.serverName}" 需要 OAuth 认证`);let W=await this.oauthProvider.authenticate(this.serverName,q);K.Authorization=`Bearer ${W.accessToken}`}else K.Authorization=`Bearer ${G}`}catch(G){throw console.error("[McpClient] OAuth 认证失败:",G),Error(`OAuth 认证失败: ${G instanceof Error?G.message:String(G)}`)}if($==="stdio"){if(!Y)throw Error("stdio 传输需要 command 参数");let G={};for(let[W,U]of Object.entries(process.env))if(U!==void 0)G[W]=U;return new uQ({command:Y,args:Z||[],env:{...G,...X},stderr:"ignore"})}else if($==="sse"){if(!Q)throw Error("sse 传输需要 url 参数");return new dQ(new URL(Q),{requestInit:{headers:K}})}else if($==="http"){if(!Q)throw Error("http 传输需要 url 参数");let{StreamableHTTPClientTransport:G}=await import("@modelcontextprotocol/sdk/client/streamableHttp.js");return new G(new URL(Q),{requestInit:{headers:K}})}throw Error(`不支持的传输类型: ${$}`)}async loadTools(){if(!this.sdkClient)return;try{let $=await this.sdkClient.listTools();if(this.tools.clear(),$.tools)for(let Y of $.tools)this.tools.set(Y.name,Y);this.emit("toolsUpdated",this.availableTools)}catch($){throw console.error("[McpClient] 加载工具失败:",$),$}}setStatus($){let Y=this.status;this.status=$,this.emit("statusChanged",$,Y)}async initialize(){return this.connect()}async destroy(){return this.disconnect()}async connectToServer($){return this.connect()}async disconnectFromServer($){return this.disconnect()}async listResources($){if(!this.sdkClient)return[];try{return(await this.sdkClient.listResources()).resources||[]}catch{return[]}}async listTools($){return this.availableTools}async readResource($,Y){if(!this.sdkClient)throw Error("客户端未连接");return(await this.sdkClient.readResource({uri:$})).contents?.[0]||{uri:$,text:""}}}});import{EventEmitter as lQ}from"events";var C1;var u2=R(()=>{u7();s7();d2();C1=class C1 extends lQ{static instance=null;servers=new Map;isDiscovering=!1;constructor(){super()}static getInstance(){if(!C1.instance)C1.instance=new C1;return C1.instance}async registerServer($,Y){if(this.servers.has($))throw Error(`MCP服务器 "${$}" 已经注册`);let Z=new l4(Y,$,Y.healthCheck),X={config:Y,client:Z,status:"disconnected",tools:[]};this.setupClientEventHandlers(Z,X,$),this.servers.set($,X),this.emit("serverRegistered",$,X);try{await this.connectServer($)}catch(Q){console.warn(`MCP服务器 "${$}" 连接失败:`,Q)}}async unregisterServer($){let Y=this.servers.get($);if(!Y)return;try{await Y.client.disconnect()}catch(Z){console.warn(`断开MCP服务器 "${$}" 时出错:`,Z)}this.servers.delete($),this.emit("serverUnregistered",$)}async connectServer($){let Y=this.servers.get($);if(!Y)throw Error(`MCP服务器 "${$}" 未注册`);if(Y.status==="connected")return;try{Y.status="connecting",await Y.client.connect(),Y.connectedAt=new Date,Y.lastError=void 0,Y.tools=Y.client.availableTools}catch(Z){throw Y.lastError=Z,Y.status="error",Z}}async disconnectServer($){let Y=this.servers.get($);if(!Y)return;await Y.client.disconnect(),Y.connectedAt=void 0}async getAvailableTools(){let $=[],Y=new Map;for(let[Z,X]of this.servers)if(X.status==="connected")for(let Q of X.tools){let J=Y.get(Q.name)||0;Y.set(Q.name,J+1)}for(let[Z,X]of this.servers)if(X.status==="connected")for(let Q of X.tools){let q=(Y.get(Q.name)||0)>1?`${Z}__${Q.name}`:Q.name,K=O6(X.client,Z,Q,q);$.push(K)}return $}async findTool($){for(let[Y,Z]of this.servers)if(Z.status==="connected"){let X=Z.tools.find((Q)=>Q.name===$);if(X)return O6(Z.client,Y,X)}return null}getToolsByServer($){let Y=this.servers.get($);if(!Y||Y.status!=="connected")return[];return Y.tools.map((Z)=>O6(Y.client,$,Z))}getServerStatus($){return this.servers.get($)||null}getAllServers(){return new Map(this.servers)}async refreshAllTools(){let $=[];for(let[Y,Z]of this.servers)if(Z.status==="connected")$.push(this.refreshServerTools(Y));await Promise.allSettled($)}async refreshServerTools($){let Y=this.servers.get($);if(!Y||Y.status!=="connected")return;try{let Z=Y.client.availableTools,X=Y.tools.length;Y.tools=Z,this.emit("toolsUpdated",$,Z,X)}catch(Z){console.warn(`刷新服务器 "${$}" 工具列表失败:`,Z)}}setupClientEventHandlers($,Y,Z){$.on("connected",(X)=>{Y.status="connected",Y.connectedAt=new Date,Y.tools=$.availableTools,this.emit("serverConnected",Z,X)}),$.on("disconnected",()=>{Y.status="disconnected",Y.connectedAt=void 0,Y.tools=[],this.emit("serverDisconnected",Z)}),$.on("error",(X)=>{Y.status="error",Y.lastError=X,this.emit("serverError",Z,X)}),$.on("toolsUpdated",(X)=>{let Q=Y.tools.length;Y.tools=X,this.emit("toolsUpdated",Z,X,Q)}),$.on("statusChanged",(X,Q)=>{Y.status=X,this.emit("serverStatusChanged",Z,X,Q)})}async discoverServers(){if(this.isDiscovering)return Array.from(this.servers.values());this.isDiscovering=!0,this.emit("discoveryStarted");try{return Array.from(this.servers.values())}finally{this.isDiscovering=!1,this.emit("discoveryCompleted")}}async registerServers($){let Y=Object.entries($).map(([Z,X])=>this.registerServer(Z,X).catch((Q)=>{return console.warn(`注册MCP服务器 "${Z}" 失败:`,Q),Q}));await Promise.allSettled(Y)}getStatistics(){let $=0,Y=0,Z=0;for(let X of this.servers.values())if(X.status==="connected")$++,Y+=X.tools.length;else if(X.status==="error")Z++;return{totalServers:this.servers.size,connectedServers:$,errorServers:Z,totalTools:Y,isDiscovering:this.isDiscovering}}async disconnectAll(){let $=[];for(let[Y,Z]of this.servers)if(Z.status==="connected")$.push(Z.client.disconnect().catch((X)=>{console.warn(`断开 MCP 服务器 "${Y}" 时出错:`,X)}));await Promise.allSettled($),this.servers.clear()}}});import{randomUUID as $J}from"node:crypto";import YJ from"openai";function ZJ(){return $J().replace(/-/g,"")+"01"}function $3($){return $.toLowerCase().includes("gemini")}function N6($){if(!$||typeof $!=="object")return $;if(Array.isArray($))return $.map(N6);let Y={};for(let[Z,X]of Object.entries($)){if(Z==="$schema"||Z==="additionalProperties")continue;Y[Z]=N6(X)}return Y}function Y3($){let Y=new Map;for(let J=0;J<$.length;J++){let q=$[J];if(q.role==="assistant"&&q.tool_calls)for(let K of q.tool_calls)Y.set(K.id,J)}let Z=new Set;for(let J of $)if(J.role==="tool"&&J.tool_call_id)Z.add(J.tool_call_id);let X=[];for(let J of Y.keys())if(!Z.has(J))X.push(J);let Q=[];for(let J of $)if(J.role==="tool"){if(J.tool_call_id&&Y.has(J.tool_call_id))Q.push(J)}else if(Q.push(J),J.role==="assistant"&&J.tool_calls){for(let q of J.tool_calls)if(X.includes(q.id))Q.push({role:"tool",content:"[Result lost due to context compression]",tool_call_id:q.id})}if(X.length>0)$1.debug(`\uD83D\uDD27 [GptOpenaiPlatformChatService] Gemini 修复:补充 ${X.length} 个缺失的 tool results`);return Q}class i4{config;constructor($){if($1.debug("\uD83D\uDE80 [GptOpenaiPlatformChatService] Initializing"),$1.debug("⚙️ [GptOpenaiPlatformChatService] Config:",{model:$.model,baseUrl:$.baseUrl,apiVersion:$.apiVersion,temperature:$.temperature,maxContextTokens:$.maxContextTokens,timeout:$.timeout,hasApiKey:!!$.apiKey}),!$.baseUrl)throw $1.error("❌ [GptOpenaiPlatformChatService] baseUrl is required"),Error("baseUrl is required in ChatConfig");if(!$.apiKey)throw $1.error("❌ [GptOpenaiPlatformChatService] apiKey is required"),Error("apiKey is required in ChatConfig");if(!$.model)throw $1.error("❌ [GptOpenaiPlatformChatService] model is required"),Error("model is required in ChatConfig");this.config=$,$1.debug("✅ [GptOpenaiPlatformChatService] Initialized successfully")}createClient(){let $=ZJ();$1.debug("\uD83D\uDD11 [GptOpenaiPlatformChatService] Generated logid:",$);let Y={},Z={"api-key":this.config.apiKey,"x-tt-logid":$};if(this.config.apiVersion)Y["api-version"]=this.config.apiVersion;return new YJ({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,timeout:this.config.timeout??180000,maxRetries:3,defaultQuery:Y,defaultHeaders:Z})}async chat($,Y,Z){let X=Date.now();$1.debug("\uD83D\uDE80 [GptOpenaiPlatformChatService] Starting chat request"),$1.debug("\uD83D\uDCDD [GptOpenaiPlatformChatService] Messages count:",$.length);let Q=this.createClient(),J=$3(this.config.model),K=(J?Y3($):$).map((U)=>{if(U.role==="tool")return{role:"tool",content:U.content,tool_call_id:U.tool_call_id};if(U.role==="assistant"&&U.tool_calls)return{role:"assistant",content:U.content||null,tool_calls:U.tool_calls};return{role:U.role,content:U.content}}),G=Y?.map((U)=>({type:"function",function:{name:U.name,description:U.description,parameters:J?N6(U.parameters):U.parameters}}));$1.debug("\uD83D\uDD27 [GptOpenaiPlatformChatService] Tools count:",G?.length||0);let W={model:this.config.model,messages:K,tools:G,tool_choice:G&&G.length>0?"auto":void 0,max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0};$1.debug("\uD83D\uDCE4 [GptOpenaiPlatformChatService] Request params:",{model:W.model,messagesCount:W.messages.length,toolsCount:W.tools?.length||0,tool_choice:W.tool_choice,max_tokens:W.max_tokens,temperature:W.temperature});try{let U=await Q.chat.completions.create(W,{signal:Z}),H=Date.now()-X;if($1.debug("\uD83D\uDCE5 [GptOpenaiPlatformChatService] Response received in",H,"ms"),!U)throw $1.error("❌ [GptOpenaiPlatformChatService] API returned null/undefined response"),Error("API returned null/undefined response");if(!U.choices||!Array.isArray(U.choices))throw $1.error("❌ [GptOpenaiPlatformChatService] Invalid API response format - missing choices array"),Error(`Invalid API response: missing choices array. Response: ${JSON.stringify(U)}`);if(U.choices.length===0)throw $1.error("❌ [GptOpenaiPlatformChatService] API returned empty choices array"),Error("API returned empty choices array");let O=U.choices[0];if(!O)throw $1.error("❌ [GptOpenaiPlatformChatService] No completion choice returned"),Error("No completion choice returned");$1.debug("\uD83D\uDCDD [GptOpenaiPlatformChatService] Response choice:",{finishReason:O.finish_reason,contentLength:O.message.content?.length||0,hasToolCalls:!!O.message.tool_calls,toolCallsCount:O.message.tool_calls?.length||0});let z=O.message.tool_calls?.filter((B)=>B.type==="function"),F=O.message.reasoning_content||void 0,N=U.usage,w={content:O.message.content||"",reasoningContent:F,toolCalls:z,usage:{promptTokens:U.usage?.prompt_tokens||0,completionTokens:U.usage?.completion_tokens||0,totalTokens:U.usage?.total_tokens||0,reasoningTokens:N?.reasoning_tokens}};return $1.debug("✅ [GptOpenaiPlatformChatService] Chat completed successfully"),w}catch(U){let H=Date.now()-X;throw $1.error("❌ [GptOpenaiPlatformChatService] Chat request failed after",H,"ms"),$1.error("❌ [GptOpenaiPlatformChatService] Error details:",U),U}}async*streamChat($,Y,Z){let X=Date.now();$1.debug("\uD83D\uDE80 [GptOpenaiPlatformChatService] Starting stream request"),$1.debug("\uD83D\uDCDD [GptOpenaiPlatformChatService] Messages count:",$.length);let Q=this.createClient(),J=$3(this.config.model),K=(J?Y3($):$).map((U)=>{if(U.role==="tool")return{role:"tool",content:U.content,tool_call_id:U.tool_call_id};if(U.role==="assistant"&&U.tool_calls)return{role:"assistant",content:U.content||null,tool_calls:U.tool_calls};return{role:U.role,content:U.content}}),G=Y?.map((U)=>({type:"function",function:{name:U.name,description:U.description,parameters:J?N6(U.parameters):U.parameters}})),W={model:this.config.model,messages:K,tools:G,tool_choice:G&&G.length>0?"auto":"none",max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0,stream:!0};$1.debug("\uD83D\uDCE4 [GptOpenaiPlatformChatService] Stream request params:",{model:W.model,messagesCount:W.messages.length,toolsCount:W.tools?.length||0});try{let U=await Q.chat.completions.create(W,{signal:Z}),H=Date.now()-X;$1.debug("\uD83D\uDCE5 [GptOpenaiPlatformChatService] Stream started in",H,"ms");let O=0,z="",_="",F=!1;for await(let N of U){if(O++,!N||!N.choices||!Array.isArray(N.choices)){$1.warn("⚠️ [GptOpenaiPlatformChatService] Invalid chunk format in stream",O);continue}let w=N.choices[0]?.delta;if(!w)continue;let B=w;if(w.content)z+=w.content;if(B.reasoning_content)_+=B.reasoning_content;if(w.tool_calls&&!F)F=!0,$1.debug("\uD83D\uDD27 [GptOpenaiPlatformChatService] Tool calls detected in stream");let A=N.choices[0]?.finish_reason;if(A)$1.debug("\uD83C\uDFC1 [GptOpenaiPlatformChatService] Stream finished with reason:",A),$1.debug("\uD83D\uDCCA [GptOpenaiPlatformChatService] Stream summary:",{totalChunks:O,totalContentLength:z.length,totalReasoningContentLength:_.length,hadToolCalls:F,duration:Date.now()-X+"ms"});yield{content:w.content||void 0,reasoningContent:B.reasoning_content||void 0,toolCalls:w.tool_calls,finishReason:A||void 0}}$1.debug("✅ [GptOpenaiPlatformChatService] Stream completed successfully")}catch(U){let H=Date.now()-X;throw $1.error("❌ [GptOpenaiPlatformChatService] Stream request failed after",H,"ms"),$1.error("❌ [GptOpenaiPlatformChatService] Stream error details:",U),U}}getConfig(){return{...this.config}}updateConfig($){$1.debug("\uD83D\uDD04 [GptOpenaiPlatformChatService] Updating configuration"),this.config={...this.config,...$},$1.debug("✅ [GptOpenaiPlatformChatService] Configuration updated successfully")}}var $1;var Z3=R(()=>{N1();$1=u("Chat")});import X3 from"openai";function XJ($){for(let Y of J3){let Z=$[Y];if(Z)return{content:Z,fieldName:Y}}return}function Q3($){let Y=new Set;for(let Z of $)if(Z.role==="assistant"&&Z.tool_calls)for(let X of Z.tool_calls)Y.add(X.id);return $.filter((Z)=>{if(Z.role==="tool"){if(!Z.tool_call_id)return!1;return Y.has(Z.tool_call_id)}return!0})}class w6{config;client;detectedReasoningFieldName=null;convertToOpenAIMessages($){return $.map((Y)=>{if(Y.role==="tool")return{role:"tool",content:Y.content,tool_call_id:Y.tool_call_id};if(Y.role==="assistant"&&Y.tool_calls){let Z={role:"assistant",content:Y.content||null,tool_calls:Y.tool_calls};if(this.config.supportsThinking){let X="reasoningContent"in Y&&Y.reasoningContent?Y.reasoningContent:"";if(this.detectedReasoningFieldName)Z[this.detectedReasoningFieldName]=X;else for(let Q of J3)Z[Q]=X}return Z}return{role:Y.role,content:Y.content}})}convertToOpenAITools($){return $?.map((Y)=>({type:"function",function:{name:Y.name,description:Y.description,parameters:Y.parameters}}))}extractAndDetectReasoning($){let Y=XJ($);if(Y){if(!this.detectedReasoningFieldName)this.detectedReasoningFieldName=Y.fieldName,x.debug(`\uD83E\uDDE0 [ChatService] Detected reasoning field: ${Y.fieldName}`);return Y.content}return}constructor($){this.config=$;if(x.debug("\uD83D\uDE80 [ChatService] Initializing ChatService"),x.debug("⚙️ [ChatService] Config:",{model:$.model,baseUrl:$.baseUrl,temperature:$.temperature,maxContextTokens:$.maxContextTokens,timeout:$.timeout,hasApiKey:!!$.apiKey}),!$.baseUrl)throw x.error("❌ [ChatService] baseUrl is required in ChatConfig"),Error("baseUrl is required in ChatConfig");if(!$.apiKey)throw x.error("❌ [ChatService] apiKey is required in ChatConfig"),Error("apiKey is required in ChatConfig");if(!$.model)throw x.error("❌ [ChatService] model is required in ChatConfig"),Error("model is required in ChatConfig");this.client=new X3({apiKey:$.apiKey,baseURL:$.baseUrl,timeout:$.timeout??180000,maxRetries:3}),x.debug("✅ [ChatService] ChatService initialized successfully")}async chat($,Y,Z){let X=Date.now();x.debug("\uD83D\uDE80 [ChatService] Starting chat request"),x.debug("\uD83D\uDCDD [ChatService] Messages count:",$.length);let Q=Q3($);if(Q.length<$.length)x.debug(`\uD83D\uDD27 [ChatService] 过滤掉 ${$.length-Q.length} 条孤儿 tool 消息`);x.debug("\uD83D\uDCDD [ChatService] Messages preview:",Q.map((G)=>({role:G.role,contentLength:G.content.length})));let J=this.convertToOpenAIMessages(Q),q=this.convertToOpenAITools(Y);if(x.debug("\uD83D\uDD27 [ChatService] Tools count:",q?.length||0),q&&q.length>0)x.debug("\uD83D\uDD27 [ChatService] Available tools:",q.map((G)=>G.type==="function"?G.function.name:"unknown"));let K={model:this.config.model,messages:J,tools:q,tool_choice:q&&q.length>0?"auto":void 0,max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0};x.debug("\uD83D\uDCE4 [ChatService] Request params:",{model:K.model,messagesCount:K.messages.length,toolsCount:K.tools?.length||0,tool_choice:K.tool_choice,max_tokens:K.max_tokens,temperature:K.temperature});try{let G=await this.client.chat.completions.create(K,{signal:Z}),W=Date.now()-X;if(x.debug("\uD83D\uDCE5 [ChatService] Response received in",W,"ms"),!G)throw x.error("❌ [ChatService] API returned null/undefined response"),Error("API returned null/undefined response");if(!G.choices||!Array.isArray(G.choices))throw x.error("❌ [ChatService] Invalid API response format - missing choices array"),x.error("❌ [ChatService] Response object:",JSON.stringify(G,null,2)),Error(`Invalid API response: missing choices array. Response: ${JSON.stringify(G)}`);if(G.choices.length===0)throw x.error("❌ [ChatService] API returned empty choices array"),Error("API returned empty choices array");x.debug("\uD83D\uDCCA [ChatService] Response usage:",G.usage),x.debug("\uD83D\uDCCA [ChatService] Response choices count:",G.choices.length);let U=G.choices[0];if(!U)throw x.error("❌ [ChatService] No completion choice returned"),Error("No completion choice returned");if(x.debug("\uD83D\uDCDD [ChatService] Response choice:",{finishReason:U.finish_reason,contentLength:U.message.content?.length||0,hasToolCalls:!!U.message.tool_calls,toolCallsCount:U.message.tool_calls?.length||0}),U.message.tool_calls)x.debug("\uD83D\uDD27 [ChatService] Tool calls:",U.message.tool_calls.map((N)=>({id:N.id,type:N.type,functionName:N.type==="function"?N.function?.name:"unknown",functionArgsLength:N.type==="function"?N.function?.arguments?.length||0:0})));let H=U.message.tool_calls?.filter((N)=>N.type==="function"),O=U.message,z=this.extractAndDetectReasoning(O);if(this.config.supportsThinking)x.debug("\uD83E\uDDE0 [ChatService] Thinking model response:",{reasoningContentLength:z?.length||0,detectedFieldName:this.detectedReasoningFieldName,messageKeys:Object.keys(U.message)});let _=G.usage,F={content:U.message.content||"",reasoningContent:z,toolCalls:H,usage:{promptTokens:G.usage?.prompt_tokens||0,completionTokens:G.usage?.completion_tokens||0,totalTokens:G.usage?.total_tokens||0,reasoningTokens:_?.reasoning_tokens}};return x.debug("✅ [ChatService] Chat completed successfully"),x.debug("\uD83D\uDCCA [ChatService] Final response:",{contentLength:F.content.length,toolCallsCount:F.toolCalls?.length||0,usage:F.usage}),F}catch(G){let W=Date.now()-X;throw x.error("❌ [ChatService] Chat request failed after",W,"ms"),x.error("❌ [ChatService] Error details:",G),G}}async*streamChat($,Y,Z){let X=Date.now();x.debug("\uD83D\uDE80 [ChatService] Starting chat stream request"),x.debug("\uD83D\uDCDD [ChatService] Messages count:",$.length);let Q=Q3($);if(Q.length<$.length)x.debug(`\uD83D\uDD27 [ChatService] 过滤掉 ${$.length-Q.length} 条孤儿 tool 消息`);x.debug("\uD83D\uDCDD [ChatService] Messages preview:",Q.map((G)=>({role:G.role,contentLength:G.content.length})));let J=this.convertToOpenAIMessages(Q),q=this.convertToOpenAITools(Y);if(x.debug("\uD83D\uDD27 [ChatService] Stream tools count:",q?.length||0),q&&q.length>0)x.debug("\uD83D\uDD27 [ChatService] Stream available tools:",q.map((G)=>G.type==="function"?G.function.name:"unknown"));let K={model:this.config.model,messages:J,tools:q,tool_choice:q&&q.length>0?"auto":"none",max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0,stream:!0};x.debug("\uD83D\uDCE4 [ChatService] Stream request params:",{model:K.model,messagesCount:K.messages.length,toolsCount:K.tools?.length||0,tool_choice:K.tool_choice,max_tokens:K.max_tokens,temperature:K.temperature,stream:K.stream});try{let G=await this.client.chat.completions.create(K,{signal:Z}),W=Date.now()-X;x.debug("\uD83D\uDCE5 [ChatService] Stream started in",W,"ms");let U=0,H="",O="",z=!1;for await(let _ of G){if(U++,!_||!_.choices||!Array.isArray(_.choices)){x.warn("⚠️ [ChatService] Invalid chunk format in stream",U);continue}let F=_.choices[0]?.delta;if(!F){x.warn("⚠️ [ChatService] Empty delta in chunk",U);continue}let N=F,w=this.extractAndDetectReasoning(N);if(F.content)H+=F.content;if(w)O+=w;if(F.tool_calls&&!z)z=!0,x.debug("\uD83D\uDD27 [ChatService] Tool calls detected in stream");let B=_.choices[0]?.finish_reason;if(B)x.debug("\uD83C\uDFC1 [ChatService] Stream finished with reason:",B),x.debug("\uD83D\uDCCA [ChatService] Stream summary:",{totalChunks:U,totalContentLength:H.length,totalReasoningContentLength:O.length,hadToolCalls:z,duration:Date.now()-X+"ms"});yield{content:F.content||void 0,reasoningContent:w,toolCalls:F.tool_calls,finishReason:B||void 0}}x.debug("✅ [ChatService] Stream completed successfully")}catch(G){let W=Date.now()-X;throw x.error("❌ [ChatService] Stream request failed after",W,"ms"),x.error("❌ [ChatService] Stream error details:",G),G}}getConfig(){return{...this.config}}updateConfig($){x.debug("\uD83D\uDD04 [ChatService] Updating configuration"),x.debug("\uD83D\uDD04 [ChatService] New config:",{model:$.model,baseUrl:$.baseUrl,temperature:$.temperature,maxContextTokens:$.maxContextTokens,timeout:$.timeout,hasApiKey:!!$.apiKey});let Y={...this.config};if(this.config={...this.config,...$},Y.baseUrl!==this.config.baseUrl)this.detectedReasoningFieldName=null,x.debug("\uD83D\uDD04 [ChatService] Reset detectedReasoningFieldName due to baseUrl change");this.client=new X3({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,timeout:this.config.timeout??180000,maxRetries:2}),x.debug("✅ [ChatService] Configuration updated successfully"),x.debug("\uD83D\uDCCA [ChatService] Config changes:",{modelChanged:Y.model!==this.config.model,baseUrlChanged:Y.baseUrl!==this.config.baseUrl,temperatureChanged:Y.temperature!==this.config.temperature,maxContextTokensChanged:Y.maxContextTokens!==this.config.maxContextTokens,timeoutChanged:Y.timeout!==this.config.timeout,apiKeyChanged:Y.apiKey!==this.config.apiKey})}}var x,J3;var q3=R(()=>{N1();x=u("Chat"),J3=["reasoning_content","reasoning","reasoningContent","thinking_content"]});function L6($){switch($.provider){case"openai-compatible":return new w6($);case"gpt-openai-platform":return new i4($);case"anthropic":throw Error(`❌ Anthropic provider 暂未实现
71
+ If the browser does not open automatically, copy and paste this URL:`),console.log(X),console.log("");let Q=this.startCallbackServer(Z.state);try{await this.openAuthorizationUrl(X)}catch(K){console.warn("[OAuth] Failed to open browser automatically:",K)}let J=await Q;console.log("[OAuth] Authorization code received, exchanging for tokens...");let q=await this.exchangeCodeForToken(Y,J,Z.codeVerifier),G={accessToken:q.access_token,tokenType:q.token_type||"Bearer",refreshToken:q.refresh_token,scope:q.scope};if(q.expires_in)G.expiresAt=Date.now()+q.expires_in*1000;return await this.tokenStorage.saveToken($,G,Y.clientId,Y.tokenUrl),console.log("[OAuth] Authentication successful! Token saved."),G}async openAuthorizationUrl($){let{command:Y,args:Z}=this.getBrowserCommand($);await new Promise((X,Q)=>{let J=eQ(Y,Z,{stdio:"ignore"});J.once("error",Q),J.once("close",(q)=>{if(q===0||q===null)X();else Q(Error(`Failed to open browser (exit code ${q})`))})})}getBrowserCommand($){if(process.platform==="darwin")return{command:"open",args:[$]};if(process.platform==="win32")return{command:"cmd",args:["/c","start","",$]};return{command:"xdg-open",args:[$]}}async getValidToken($,Y){let Z=await this.tokenStorage.getCredentials($);if(!Z)return null;let{token:X}=Z;if(!this.tokenStorage.isTokenExpired(X))return X.accessToken;if(X.refreshToken&&Y.clientId&&Z.tokenUrl)try{console.log(`[OAuth] Refreshing expired token for server: ${$}`);let Q=await this.refreshAccessToken(Y,X.refreshToken),J={accessToken:Q.access_token,tokenType:Q.token_type,refreshToken:Q.refresh_token||X.refreshToken,scope:Q.scope||X.scope};if(Q.expires_in)J.expiresAt=Date.now()+Q.expires_in*1000;return await this.tokenStorage.saveToken($,J,Y.clientId,Z.tokenUrl),J.accessToken}catch(Q){console.error("[OAuth] Failed to refresh token:",Q),await this.tokenStorage.deleteCredentials($)}return null}}var g$=7777,o4="/oauth/callback",Y3=200;var X3=D(()=>{n4()});var Q3=D(()=>{X3();n4()});var c2=()=>{};import{EventEmitter as $J}from"events";var s4;var J3=D(()=>{c2();s4=class s4 extends $J{client;config;checkTimer=null;isChecking=!1;consecutiveFailures=0;lastCheckTime=0;currentStatus="healthy";constructor($,Y={}){super();this.client=$,this.config={interval:Y.interval??30000,timeout:Y.timeout??1e4,enabled:Y.enabled??!1,failureThreshold:Y.failureThreshold??3}}start(){if(this.checkTimer){console.warn("[HealthMonitor] 健康监控已在运行");return}if(!this.config.enabled){console.log("[HealthMonitor] 健康监控未启用");return}console.log(`[HealthMonitor] 启动健康监控(间隔: ${this.config.interval}ms)`),this.scheduleNextCheck()}stop(){if(this.checkTimer)clearTimeout(this.checkTimer),this.checkTimer=null,console.log("[HealthMonitor] 停止健康监控")}scheduleNextCheck(){this.checkTimer=setTimeout(async()=>{await this.performHealthCheck(),this.scheduleNextCheck()},this.config.interval)}async performHealthCheck(){if(this.isChecking)return console.warn("[HealthMonitor] 上一次检查仍在进行中"),this.getLastResult();this.isChecking=!0,this.lastCheckTime=Date.now(),this.setStatus("checking");try{let $=this.client.connectionStatus;if($==="connected"){await this.pingServer(),this.consecutiveFailures=0,this.setStatus("healthy");let Y={status:"healthy",timestamp:Date.now(),consecutiveFailures:0};return this.emit("healthCheck",Y),Y}else throw Error(`连接状态异常: ${$}`)}catch($){this.consecutiveFailures++;let Y=$;console.warn(`[HealthMonitor] 健康检查失败(${this.consecutiveFailures}/${this.config.failureThreshold}):`,Y.message);let Z;if(this.consecutiveFailures>=this.config.failureThreshold)Z="unhealthy",this.emit("unhealthy",this.consecutiveFailures,Y),console.log("[HealthMonitor] 达到失败阈值,触发重连..."),this.triggerReconnection().catch((Q)=>{console.error("[HealthMonitor] 重连失败:",Q)});else Z="degraded";this.setStatus(Z);let X={status:Z,timestamp:Date.now(),consecutiveFailures:this.consecutiveFailures,lastError:Y};return this.emit("healthCheck",X),X}finally{this.isChecking=!1}}async pingServer(){let $=new Promise((Z,X)=>{setTimeout(()=>X(Error("Health check timeout")),this.config.timeout)}),Y=(async()=>{if(this.client.availableTools.length===0){if(!this.client.server)throw Error("Server info not available")}})();await Promise.race([Y,$])}async triggerReconnection(){try{await this.client.disconnect(),await new Promise(($)=>setTimeout($,1000)),await this.client.connect(),console.log("[HealthMonitor] 重连成功"),this.consecutiveFailures=0,this.setStatus("healthy"),this.emit("reconnected")}catch($){throw console.error("[HealthMonitor] 重连失败:",$),$}}setStatus($){if(this.currentStatus!==$){let Y=this.currentStatus;this.currentStatus=$,this.emit("statusChanged",$,Y)}}getStatus(){return this.currentStatus}getLastResult(){return{status:this.currentStatus,timestamp:this.lastCheckTime,consecutiveFailures:this.consecutiveFailures}}getStatistics(){return{status:this.currentStatus,consecutiveFailures:this.consecutiveFailures,lastCheckTime:this.lastCheckTime,isChecking:this.isChecking,config:this.config}}async checkNow(){return this.performHealthCheck()}resetFailureCount(){if(this.consecutiveFailures=0,this.currentStatus!=="checking")this.setStatus("healthy")}}});import{Client as YJ}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as ZJ}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as XJ}from"@modelcontextprotocol/sdk/client/stdio.js";import{EventEmitter as QJ}from"events";function q3($){if(!($ instanceof Error))return{type:"unknown",isRetryable:!1,originalError:Error(String($))};let Y=$.message.toLowerCase();if(["command not found","no such file","permission denied","invalid configuration","malformed","syntax error"].some((Q)=>Y.includes(Q)))return{type:"config_error",isRetryable:!1,originalError:$};if(Y.includes("unauthorized")||Y.includes("401")||Y.includes("authentication failed"))return{type:"auth_error",isRetryable:!1,originalError:$};if(["timeout","connection refused","network error","temporary","try again","rate limit","too many requests","service unavailable","socket hang up","econnreset","enotfound","econnrefused","etimedout","503","429"].some((Q)=>Y.includes(Q)))return{type:"network_temporary",isRetryable:!0,originalError:$};return{type:"unknown",isRetryable:!0,originalError:$}}var t4;var G3=D(()=>{y$();Q3();J3();c2();t4=class t4 extends QJ{config;status="disconnected";sdkClient=null;tools=new Map;serverInfo=null;reconnectAttempts=0;MAX_RECONNECT_ATTEMPTS=5;reconnectTimer=null;isManualDisconnect=!1;oauthProvider=null;serverName;healthMonitor=null;constructor($,Y,Z){super();this.config=$;if(this.serverName=Y||"default",$.oauth?.enabled)this.oauthProvider=new A6;if(Z?.enabled)this.healthMonitor=new s4(this,Z),this.healthMonitor.on("unhealthy",(X,Q)=>{this.emit("unhealthy",X,Q)}),this.healthMonitor.on("reconnected",()=>{this.emit("healthMonitorReconnected")})}get connectionStatus(){return this.status}get availableTools(){return Array.from(this.tools.values())}get server(){return this.serverInfo}get healthCheck(){return this.healthMonitor}async connect(){return this.connectWithRetry(3,1000)}async connectWithRetry($=3,Y=1000){if(this.status!=="disconnected")throw Error("客户端已连接或正在连接中");let Z=null;for(let X=1;X<=$;X++)try{await this.doConnect(),this.reconnectAttempts=0;return}catch(Q){Z=Q;let J=q3(Q);if(!J.isRetryable)throw console.error("[McpClient] 检测到永久性错误,放弃重试:",J.type),Q;if(X<$){let q=Y*Math.pow(2,X-1);console.warn(`[McpClient] 连接失败(${X}/${$}),${q}ms 后重试...`),await new Promise((G)=>setTimeout(G,q))}}throw Z||Error("连接失败")}async doConnect(){try{this.setStatus("connecting"),this.sdkClient=new YJ({name:b7(),version:x2()},{capabilities:{roots:{listChanged:!0},sampling:{}}}),this.sdkClient.onclose=()=>{this.handleUnexpectedClose()};let $=await this.createTransport();await this.sdkClient.connect($);let Y=this.sdkClient.getServerVersion();if(this.serverInfo={name:Y?.name||"Unknown",version:Y?.version||"0.0.0"},await this.loadTools(),this.setStatus("connected"),this.emit("connected",this.serverInfo),this.healthMonitor)this.healthMonitor.start()}catch($){throw this.setStatus("error"),this.emit("error",$),$}}handleUnexpectedClose(){if(this.isManualDisconnect)return;if(this.status==="connected")console.warn("[McpClient] 检测到意外断连,准备重连..."),this.setStatus("error"),this.emit("error",Error("MCP服务器连接意外关闭")),this.scheduleReconnect()}scheduleReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.reconnectAttempts>=this.MAX_RECONNECT_ATTEMPTS){console.error("[McpClient] 达到最大重连次数,放弃重连"),this.emit("reconnectFailed");return}let $=Math.min(1000*Math.pow(2,this.reconnectAttempts),30000);this.reconnectAttempts++,console.log(`[McpClient] 将在 ${$}ms 后进行第 ${this.reconnectAttempts} 次重连...`),this.reconnectTimer=setTimeout(async()=>{try{if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected"),await this.doConnect(),console.log("[McpClient] 重连成功"),this.reconnectAttempts=0,this.emit("reconnected")}catch(Y){if(console.error("[McpClient] 重连失败:",Y),q3(Y).isRetryable)this.scheduleReconnect();else console.error("[McpClient] 检测到永久性错误,停止重连"),this.emit("reconnectFailed")}},$)}async disconnect(){if(this.isManualDisconnect=!0,this.healthMonitor)this.healthMonitor.stop();if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.sdkClient){try{await this.sdkClient.close()}catch($){console.warn("[McpClient] 断开连接时出错:",$)}this.sdkClient=null}this.tools.clear(),this.serverInfo=null,this.reconnectAttempts=0,this.setStatus("disconnected"),this.emit("disconnected"),this.isManualDisconnect=!1}async callTool($,Y={}){if(!this.sdkClient)throw Error("客户端未连接到服务器");if(!this.tools.has($))throw Error(`工具 "${$}" 不存在`);try{return await this.sdkClient.callTool({name:$,arguments:Y})}catch(Z){throw console.error(`[McpClient] 调用工具 "${$}" 失败:`,Z),Z}}async createTransport(){let{type:$,command:Y,args:Z,env:X,url:Q,headers:J,oauth:q}=this.config,G={...J};if(q?.enabled&&this.oauthProvider&&($==="sse"||$==="http"))try{let K=await this.oauthProvider.getValidToken(this.serverName,q);if(!K){console.log(`[McpClient] 服务器 "${this.serverName}" 需要 OAuth 认证`);let W=await this.oauthProvider.authenticate(this.serverName,q);G.Authorization=`Bearer ${W.accessToken}`}else G.Authorization=`Bearer ${K}`}catch(K){throw console.error("[McpClient] OAuth 认证失败:",K),Error(`OAuth 认证失败: ${K instanceof Error?K.message:String(K)}`)}if($==="stdio"){if(!Y)throw Error("stdio 传输需要 command 参数");let K={};for(let[W,U]of Object.entries(process.env))if(U!==void 0)K[W]=U;return new XJ({command:Y,args:Z||[],env:{...K,...X},stderr:"ignore"})}else if($==="sse"){if(!Q)throw Error("sse 传输需要 url 参数");return new ZJ(new URL(Q),{requestInit:{headers:G}})}else if($==="http"){if(!Q)throw Error("http 传输需要 url 参数");let{StreamableHTTPClientTransport:K}=await import("@modelcontextprotocol/sdk/client/streamableHttp.js");return new K(new URL(Q),{requestInit:{headers:G}})}throw Error(`不支持的传输类型: ${$}`)}async loadTools(){if(!this.sdkClient)return;try{let $=await this.sdkClient.listTools();if(this.tools.clear(),$.tools)for(let Y of $.tools)this.tools.set(Y.name,Y);this.emit("toolsUpdated",this.availableTools)}catch($){throw console.error("[McpClient] 加载工具失败:",$),$}}setStatus($){let Y=this.status;this.status=$,this.emit("statusChanged",$,Y)}async initialize(){return this.connect()}async destroy(){return this.disconnect()}async connectToServer($){return this.connect()}async disconnectFromServer($){return this.disconnect()}async listResources($){if(!this.sdkClient)return[];try{return(await this.sdkClient.listResources()).resources||[]}catch{return[]}}async listTools($){return this.availableTools}async readResource($,Y){if(!this.sdkClient)throw Error("客户端未连接");return(await this.sdkClient.readResource({uri:$})).contents?.[0]||{uri:$,text:""}}}});import{EventEmitter as JJ}from"events";var f1;var l2=D(()=>{e7();G3();c2();f1=class f1 extends JJ{static instance=null;servers=new Map;isDiscovering=!1;constructor(){super()}static getInstance(){if(!f1.instance)f1.instance=new f1;return f1.instance}async registerServer($,Y){if(this.servers.has($))throw Error(`MCP服务器 "${$}" 已经注册`);let Z=new t4(Y,$,Y.healthCheck),X={config:Y,client:Z,status:"disconnected",tools:[]};this.setupClientEventHandlers(Z,X,$),this.servers.set($,X),this.emit("serverRegistered",$,X);try{await this.connectServer($)}catch(Q){console.warn(`MCP服务器 "${$}" 连接失败:`,Q)}}async unregisterServer($){let Y=this.servers.get($);if(!Y)return;try{await Y.client.disconnect()}catch(Z){console.warn(`断开MCP服务器 "${$}" 时出错:`,Z)}this.servers.delete($),this.emit("serverUnregistered",$)}async connectServer($){let Y=this.servers.get($);if(!Y)throw Error(`MCP服务器 "${$}" 未注册`);if(Y.status==="connected")return;try{Y.status="connecting",await Y.client.connect(),Y.connectedAt=new Date,Y.lastError=void 0,Y.tools=Y.client.availableTools}catch(Z){throw Y.lastError=Z,Y.status="error",Z}}async disconnectServer($){let Y=this.servers.get($);if(!Y)return;await Y.client.disconnect(),Y.connectedAt=void 0}async getAvailableTools(){let $=[],Y=new Map;for(let[Z,X]of this.servers)if(X.status==="connected")for(let Q of X.tools){let J=Y.get(Q.name)||0;Y.set(Q.name,J+1)}for(let[Z,X]of this.servers)if(X.status==="connected")for(let Q of X.tools){let q=(Y.get(Q.name)||0)>1?`${Z}__${Q.name}`:Q.name,G=w6(X.client,Z,Q,q);$.push(G)}return $}async findTool($){for(let[Y,Z]of this.servers)if(Z.status==="connected"){let X=Z.tools.find((Q)=>Q.name===$);if(X)return w6(Z.client,Y,X)}return null}getToolsByServer($){let Y=this.servers.get($);if(!Y||Y.status!=="connected")return[];return Y.tools.map((Z)=>w6(Y.client,$,Z))}getServerStatus($){return this.servers.get($)||null}getAllServers(){return new Map(this.servers)}async refreshAllTools(){let $=[];for(let[Y,Z]of this.servers)if(Z.status==="connected")$.push(this.refreshServerTools(Y));await Promise.allSettled($)}async refreshServerTools($){let Y=this.servers.get($);if(!Y||Y.status!=="connected")return;try{let Z=Y.client.availableTools,X=Y.tools.length;Y.tools=Z,this.emit("toolsUpdated",$,Z,X)}catch(Z){console.warn(`刷新服务器 "${$}" 工具列表失败:`,Z)}}setupClientEventHandlers($,Y,Z){$.on("connected",(X)=>{Y.status="connected",Y.connectedAt=new Date,Y.tools=$.availableTools,this.emit("serverConnected",Z,X)}),$.on("disconnected",()=>{Y.status="disconnected",Y.connectedAt=void 0,Y.tools=[],this.emit("serverDisconnected",Z)}),$.on("error",(X)=>{Y.status="error",Y.lastError=X,this.emit("serverError",Z,X)}),$.on("toolsUpdated",(X)=>{let Q=Y.tools.length;Y.tools=X,this.emit("toolsUpdated",Z,X,Q)}),$.on("statusChanged",(X,Q)=>{Y.status=X,this.emit("serverStatusChanged",Z,X,Q)})}async discoverServers(){if(this.isDiscovering)return Array.from(this.servers.values());this.isDiscovering=!0,this.emit("discoveryStarted");try{return Array.from(this.servers.values())}finally{this.isDiscovering=!1,this.emit("discoveryCompleted")}}async registerServers($){let Y=Object.entries($).map(([Z,X])=>this.registerServer(Z,X).catch((Q)=>{return console.warn(`注册MCP服务器 "${Z}" 失败:`,Q),Q}));await Promise.allSettled(Y)}getStatistics(){let $=0,Y=0,Z=0;for(let X of this.servers.values())if(X.status==="connected")$++,Y+=X.tools.length;else if(X.status==="error")Z++;return{totalServers:this.servers.size,connectedServers:$,errorServers:Z,totalTools:Y,isDiscovering:this.isDiscovering}}async disconnectAll(){let $=[];for(let[Y,Z]of this.servers)if(Z.status==="connected")$.push(Z.client.disconnect().catch((X)=>{console.warn(`断开 MCP 服务器 "${Y}" 时出错:`,X)}));await Promise.allSettled($),this.servers.clear()}}});import{randomUUID as zJ}from"node:crypto";import _J from"openai";function NJ(){return zJ().replace(/-/g,"")+"01"}function U3($){return $.toLowerCase().includes("gemini")}function V6($){if(!$||typeof $!=="object")return $;if(Array.isArray($))return $.map(V6);let Y={};for(let[Z,X]of Object.entries($)){if(Z==="$schema"||Z==="additionalProperties")continue;Y[Z]=V6(X)}return Y}function H3($){let Y=new Map;for(let J=0;J<$.length;J++){let q=$[J];if(q.role==="assistant"&&q.tool_calls)for(let G of q.tool_calls)Y.set(G.id,J)}let Z=new Set;for(let J of $)if(J.role==="tool"&&J.tool_call_id)Z.add(J.tool_call_id);let X=[];for(let J of Y.keys())if(!Z.has(J))X.push(J);let Q=[];for(let J of $)if(J.role==="tool"){if(J.tool_call_id&&Y.has(J.tool_call_id))Q.push(J)}else if(Q.push(J),J.role==="assistant"&&J.tool_calls){for(let q of J.tool_calls)if(X.includes(q.id))Q.push({role:"tool",content:"[Result lost due to context compression]",tool_call_id:q.id})}if(X.length>0)X1.debug(`\uD83D\uDD27 [GptOpenaiPlatformChatService] Gemini 修复:补充 ${X.length} 个缺失的 tool results`);return Q}class e4{config;constructor($){if(X1.debug("\uD83D\uDE80 [GptOpenaiPlatformChatService] Initializing"),X1.debug("⚙️ [GptOpenaiPlatformChatService] Config:",{model:$.model,baseUrl:$.baseUrl,apiVersion:$.apiVersion,temperature:$.temperature,maxContextTokens:$.maxContextTokens,timeout:$.timeout,hasApiKey:!!$.apiKey}),!$.baseUrl)throw X1.error("❌ [GptOpenaiPlatformChatService] baseUrl is required"),Error("baseUrl is required in ChatConfig");if(!$.apiKey)throw X1.error("❌ [GptOpenaiPlatformChatService] apiKey is required"),Error("apiKey is required in ChatConfig");if(!$.model)throw X1.error("❌ [GptOpenaiPlatformChatService] model is required"),Error("model is required in ChatConfig");this.config=$,X1.debug("✅ [GptOpenaiPlatformChatService] Initialized successfully")}createClient(){let $=NJ();X1.debug("\uD83D\uDD11 [GptOpenaiPlatformChatService] Generated logid:",$);let Y={},Z={"api-key":this.config.apiKey,"x-tt-logid":$};if(this.config.apiVersion)Y["api-version"]=this.config.apiVersion;return new _J({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,timeout:this.config.timeout??180000,maxRetries:3,defaultQuery:Y,defaultHeaders:Z})}async chat($,Y,Z){let X=Date.now();X1.debug("\uD83D\uDE80 [GptOpenaiPlatformChatService] Starting chat request"),X1.debug("\uD83D\uDCDD [GptOpenaiPlatformChatService] Messages count:",$.length);let Q=this.createClient(),J=U3(this.config.model),G=(J?H3($):$).map((U)=>{if(U.role==="tool")return{role:"tool",content:typeof U.content==="string"?U.content:U.content.filter((O)=>O.type==="text").map((O)=>O.text).join(`
72
+ `),tool_call_id:U.tool_call_id};if(U.role==="assistant"&&U.tool_calls)return{role:"assistant",content:(typeof U.content==="string"?U.content:U.content?.filter((O)=>O.type==="text").map((O)=>O.text).join(`
73
+ `))||null,tool_calls:U.tool_calls};if(U.role==="user"&&Array.isArray(U.content))return{role:"user",content:U.content.map((H)=>{if(H.type==="text")return{type:"text",text:H.text};return{type:"image_url",image_url:{url:H.image_url.url}}})};return{role:U.role,content:typeof U.content==="string"?U.content:U.content.filter((H)=>H.type==="text").map((H)=>H.text).join(`
74
+ `)}}),K=Y?.map((U)=>({type:"function",function:{name:U.name,description:U.description,parameters:J?V6(U.parameters):U.parameters}}));X1.debug("\uD83D\uDD27 [GptOpenaiPlatformChatService] Tools count:",K?.length||0);let W={model:this.config.model,messages:G,tools:K,tool_choice:K&&K.length>0?"auto":void 0,max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0};X1.debug("\uD83D\uDCE4 [GptOpenaiPlatformChatService] Request params:",{model:W.model,messagesCount:W.messages.length,toolsCount:W.tools?.length||0,tool_choice:W.tool_choice,max_tokens:W.max_tokens,temperature:W.temperature});try{let U=await Q.chat.completions.create(W,{signal:Z}),H=Date.now()-X;if(X1.debug("\uD83D\uDCE5 [GptOpenaiPlatformChatService] Response received in",H,"ms"),!U)throw X1.error("❌ [GptOpenaiPlatformChatService] API returned null/undefined response"),Error("API returned null/undefined response");if(!U.choices||!Array.isArray(U.choices))throw X1.error("❌ [GptOpenaiPlatformChatService] Invalid API response format - missing choices array"),Error(`Invalid API response: missing choices array. Response: ${JSON.stringify(U)}`);if(U.choices.length===0)throw X1.error("❌ [GptOpenaiPlatformChatService] API returned empty choices array"),Error("API returned empty choices array");let O=U.choices[0];if(!O)throw X1.error("❌ [GptOpenaiPlatformChatService] No completion choice returned"),Error("No completion choice returned");X1.debug("\uD83D\uDCDD [GptOpenaiPlatformChatService] Response choice:",{finishReason:O.finish_reason,contentLength:O.message.content?.length||0,hasToolCalls:!!O.message.tool_calls,toolCallsCount:O.message.tool_calls?.length||0});let F=O.message.tool_calls?.filter((N)=>N.type==="function"),z=O.message.reasoning_content||void 0,w=U.usage,B={content:O.message.content||"",reasoningContent:z,toolCalls:F,usage:{promptTokens:U.usage?.prompt_tokens||0,completionTokens:U.usage?.completion_tokens||0,totalTokens:U.usage?.total_tokens||0,reasoningTokens:w?.reasoning_tokens}};return X1.debug("✅ [GptOpenaiPlatformChatService] Chat completed successfully"),B}catch(U){let H=Date.now()-X;throw X1.error("❌ [GptOpenaiPlatformChatService] Chat request failed after",H,"ms"),X1.error("❌ [GptOpenaiPlatformChatService] Error details:",U),U}}async*streamChat($,Y,Z){let X=Date.now();X1.debug("\uD83D\uDE80 [GptOpenaiPlatformChatService] Starting stream request"),X1.debug("\uD83D\uDCDD [GptOpenaiPlatformChatService] Messages count:",$.length);let Q=this.createClient(),J=U3(this.config.model),G=(J?H3($):$).map((U)=>{if(U.role==="tool")return{role:"tool",content:typeof U.content==="string"?U.content:U.content.filter((O)=>O.type==="text").map((O)=>O.text).join(`
75
+ `),tool_call_id:U.tool_call_id};if(U.role==="assistant"&&U.tool_calls)return{role:"assistant",content:(typeof U.content==="string"?U.content:U.content?.filter((O)=>O.type==="text").map((O)=>O.text).join(`
76
+ `))||null,tool_calls:U.tool_calls};if(U.role==="user"&&Array.isArray(U.content))return{role:"user",content:U.content.map((H)=>{if(H.type==="text")return{type:"text",text:H.text};return{type:"image_url",image_url:{url:H.image_url.url}}})};return{role:U.role,content:typeof U.content==="string"?U.content:U.content.filter((H)=>H.type==="text").map((H)=>H.text).join(`
77
+ `)}}),K=Y?.map((U)=>({type:"function",function:{name:U.name,description:U.description,parameters:J?V6(U.parameters):U.parameters}})),W={model:this.config.model,messages:G,tools:K,tool_choice:K&&K.length>0?"auto":"none",max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0,stream:!0};X1.debug("\uD83D\uDCE4 [GptOpenaiPlatformChatService] Stream request params:",{model:W.model,messagesCount:W.messages.length,toolsCount:W.tools?.length||0});try{let U=await Q.chat.completions.create(W,{signal:Z}),H=Date.now()-X;X1.debug("\uD83D\uDCE5 [GptOpenaiPlatformChatService] Stream started in",H,"ms");let O=0,F="",_="",z=!1;for await(let w of U){if(O++,!w||!w.choices||!Array.isArray(w.choices)){X1.warn("⚠️ [GptOpenaiPlatformChatService] Invalid chunk format in stream",O);continue}let B=w.choices[0]?.delta;if(!B)continue;let N=B;if(B.content)F+=B.content;if(N.reasoning_content)_+=N.reasoning_content;if(B.tool_calls&&!z)z=!0,X1.debug("\uD83D\uDD27 [GptOpenaiPlatformChatService] Tool calls detected in stream");let b=w.choices[0]?.finish_reason;if(b)X1.debug("\uD83C\uDFC1 [GptOpenaiPlatformChatService] Stream finished with reason:",b),X1.debug("\uD83D\uDCCA [GptOpenaiPlatformChatService] Stream summary:",{totalChunks:O,totalContentLength:F.length,totalReasoningContentLength:_.length,hadToolCalls:z,duration:Date.now()-X+"ms"});yield{content:B.content||void 0,reasoningContent:N.reasoning_content||void 0,toolCalls:B.tool_calls,finishReason:b||void 0}}X1.debug("✅ [GptOpenaiPlatformChatService] Stream completed successfully")}catch(U){let H=Date.now()-X;throw X1.error("❌ [GptOpenaiPlatformChatService] Stream request failed after",H,"ms"),X1.error("❌ [GptOpenaiPlatformChatService] Stream error details:",U),U}}getConfig(){return{...this.config}}updateConfig($){X1.debug("\uD83D\uDD04 [GptOpenaiPlatformChatService] Updating configuration"),this.config={...this.config,...$},X1.debug("✅ [GptOpenaiPlatformChatService] Configuration updated successfully")}}var X1;var O3=D(()=>{B1();X1=l("Chat")});import F3 from"openai";function BJ($){for(let Y of _3){let Z=$[Y];if(Z)return{content:Z,fieldName:Y}}return}function z3($){let Y=new Set;for(let Z of $)if(Z.role==="assistant"&&Z.tool_calls)for(let X of Z.tool_calls)Y.add(X.id);return $.filter((Z)=>{if(Z.role==="tool"){if(!Z.tool_call_id)return!1;return Y.has(Z.tool_call_id)}return!0})}class D6{config;client;detectedReasoningFieldName=null;convertToOpenAIMessages($){return $.map((Y)=>{if(Y.role==="tool")return{role:"tool",content:typeof Y.content==="string"?Y.content:Y.content.filter((X)=>X.type==="text").map((X)=>X.text).join(`
78
+ `),tool_call_id:Y.tool_call_id};if(Y.role==="assistant"&&Y.tool_calls){let X={role:"assistant",content:(typeof Y.content==="string"?Y.content:Y.content.filter((Q)=>Q.type==="text").map((Q)=>Q.text).join(`
79
+ `))||null,tool_calls:Y.tool_calls};if(this.config.supportsThinking){let Q="reasoningContent"in Y&&Y.reasoningContent?Y.reasoningContent:"";if(this.detectedReasoningFieldName)X[this.detectedReasoningFieldName]=Q;else for(let J of _3)X[J]=Q}return X}if(Y.role==="user"&&Array.isArray(Y.content))return{role:"user",content:Y.content.map((Z)=>{if(Z.type==="text")return{type:"text",text:Z.text};return{type:"image_url",image_url:{url:Z.image_url.url}}})};return{role:Y.role,content:typeof Y.content==="string"?Y.content:Y.content.filter((Z)=>Z.type==="text").map((Z)=>Z.text).join(`
80
+ `)}})}convertToOpenAITools($){return $?.map((Y)=>({type:"function",function:{name:Y.name,description:Y.description,parameters:Y.parameters}}))}extractAndDetectReasoning($){let Y=BJ($);if(Y){if(!this.detectedReasoningFieldName)this.detectedReasoningFieldName=Y.fieldName,m.debug(`\uD83E\uDDE0 [ChatService] Detected reasoning field: ${Y.fieldName}`);return Y.content}return}constructor($){this.config=$;if(m.debug("\uD83D\uDE80 [ChatService] Initializing ChatService"),m.debug("⚙️ [ChatService] Config:",{model:$.model,baseUrl:$.baseUrl,temperature:$.temperature,maxContextTokens:$.maxContextTokens,timeout:$.timeout,hasApiKey:!!$.apiKey}),!$.baseUrl)throw m.error("❌ [ChatService] baseUrl is required in ChatConfig"),Error("baseUrl is required in ChatConfig");if(!$.apiKey)throw m.error("❌ [ChatService] apiKey is required in ChatConfig"),Error("apiKey is required in ChatConfig");if(!$.model)throw m.error("❌ [ChatService] model is required in ChatConfig"),Error("model is required in ChatConfig");this.client=new F3({apiKey:$.apiKey,baseURL:$.baseUrl,timeout:$.timeout??180000,maxRetries:3}),m.debug("✅ [ChatService] ChatService initialized successfully")}async chat($,Y,Z){let X=Date.now();m.debug("\uD83D\uDE80 [ChatService] Starting chat request"),m.debug("\uD83D\uDCDD [ChatService] Messages count:",$.length);let Q=z3($);if(Q.length<$.length)m.debug(`\uD83D\uDD27 [ChatService] 过滤掉 ${$.length-Q.length} 条孤儿 tool 消息`);m.debug("\uD83D\uDCDD [ChatService] Messages preview:",Q.map((K)=>({role:K.role,contentLength:typeof K.content==="string"?K.content.length:K.content.length,isMultimodal:Array.isArray(K.content)})));let J=this.convertToOpenAIMessages(Q),q=this.convertToOpenAITools(Y);if(m.debug("\uD83D\uDD27 [ChatService] Tools count:",q?.length||0),q&&q.length>0)m.debug("\uD83D\uDD27 [ChatService] Available tools:",q.map((K)=>K.type==="function"?K.function.name:"unknown"));let G={model:this.config.model,messages:J,tools:q,tool_choice:q&&q.length>0?"auto":void 0,max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0};m.debug("\uD83D\uDCE4 [ChatService] Request params:",{model:G.model,messagesCount:G.messages.length,toolsCount:G.tools?.length||0,tool_choice:G.tool_choice,max_tokens:G.max_tokens,temperature:G.temperature});try{let K=await this.client.chat.completions.create(G,{signal:Z}),W=Date.now()-X;if(m.debug("\uD83D\uDCE5 [ChatService] Response received in",W,"ms"),!K)throw m.error("❌ [ChatService] API returned null/undefined response"),Error("API returned null/undefined response");if(!K.choices||!Array.isArray(K.choices))throw m.error("❌ [ChatService] Invalid API response format - missing choices array"),m.error("❌ [ChatService] Response object:",JSON.stringify(K,null,2)),Error(`Invalid API response: missing choices array. Response: ${JSON.stringify(K)}`);if(K.choices.length===0)throw m.error("❌ [ChatService] API returned empty choices array"),Error("API returned empty choices array");m.debug("\uD83D\uDCCA [ChatService] Response usage:",K.usage),m.debug("\uD83D\uDCCA [ChatService] Response choices count:",K.choices.length);let U=K.choices[0];if(!U)throw m.error("❌ [ChatService] No completion choice returned"),Error("No completion choice returned");if(m.debug("\uD83D\uDCDD [ChatService] Response choice:",{finishReason:U.finish_reason,contentLength:U.message.content?.length||0,hasToolCalls:!!U.message.tool_calls,toolCallsCount:U.message.tool_calls?.length||0}),U.message.tool_calls)m.debug("\uD83D\uDD27 [ChatService] Tool calls:",U.message.tool_calls.map((w)=>({id:w.id,type:w.type,functionName:w.type==="function"?w.function?.name:"unknown",functionArgsLength:w.type==="function"?w.function?.arguments?.length||0:0})));let H=U.message.tool_calls?.filter((w)=>w.type==="function"),O=U.message,F=this.extractAndDetectReasoning(O);if(this.config.supportsThinking)m.debug("\uD83E\uDDE0 [ChatService] Thinking model response:",{reasoningContentLength:F?.length||0,detectedFieldName:this.detectedReasoningFieldName,messageKeys:Object.keys(U.message)});let _=K.usage,z={content:U.message.content||"",reasoningContent:F,toolCalls:H,usage:{promptTokens:K.usage?.prompt_tokens||0,completionTokens:K.usage?.completion_tokens||0,totalTokens:K.usage?.total_tokens||0,reasoningTokens:_?.reasoning_tokens}};return m.debug("✅ [ChatService] Chat completed successfully"),m.debug("\uD83D\uDCCA [ChatService] Final response:",{contentLength:z.content.length,toolCallsCount:z.toolCalls?.length||0,usage:z.usage}),z}catch(K){let W=Date.now()-X;throw m.error("❌ [ChatService] Chat request failed after",W,"ms"),m.error("❌ [ChatService] Error details:",K),K}}async*streamChat($,Y,Z){let X=Date.now();m.debug("\uD83D\uDE80 [ChatService] Starting chat stream request"),m.debug("\uD83D\uDCDD [ChatService] Messages count:",$.length);let Q=z3($);if(Q.length<$.length)m.debug(`\uD83D\uDD27 [ChatService] 过滤掉 ${$.length-Q.length} 条孤儿 tool 消息`);m.debug("\uD83D\uDCDD [ChatService] Messages preview:",Q.map((K)=>({role:K.role,contentLength:typeof K.content==="string"?K.content.length:K.content.length,isMultimodal:Array.isArray(K.content)})));let J=this.convertToOpenAIMessages(Q),q=this.convertToOpenAITools(Y);if(m.debug("\uD83D\uDD27 [ChatService] Stream tools count:",q?.length||0),q&&q.length>0)m.debug("\uD83D\uDD27 [ChatService] Stream available tools:",q.map((K)=>K.type==="function"?K.function.name:"unknown"));let G={model:this.config.model,messages:J,tools:q,tool_choice:q&&q.length>0?"auto":"none",max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0,stream:!0};m.debug("\uD83D\uDCE4 [ChatService] Stream request params:",{model:G.model,messagesCount:G.messages.length,toolsCount:G.tools?.length||0,tool_choice:G.tool_choice,max_tokens:G.max_tokens,temperature:G.temperature,stream:G.stream});try{let K=await this.client.chat.completions.create(G,{signal:Z}),W=Date.now()-X;m.debug("\uD83D\uDCE5 [ChatService] Stream started in",W,"ms");let U=0,H="",O="",F=!1;for await(let _ of K){if(U++,!_||!_.choices||!Array.isArray(_.choices)){m.warn("⚠️ [ChatService] Invalid chunk format in stream",U);continue}let z=_.choices[0]?.delta;if(!z){m.warn("⚠️ [ChatService] Empty delta in chunk",U);continue}let w=z,B=this.extractAndDetectReasoning(w);if(z.content)H+=z.content;if(B)O+=B;if(z.tool_calls&&!F)F=!0,m.debug("\uD83D\uDD27 [ChatService] Tool calls detected in stream");let N=_.choices[0]?.finish_reason;if(N)m.debug("\uD83C\uDFC1 [ChatService] Stream finished with reason:",N),m.debug("\uD83D\uDCCA [ChatService] Stream summary:",{totalChunks:U,totalContentLength:H.length,totalReasoningContentLength:O.length,hadToolCalls:F,duration:Date.now()-X+"ms"});yield{content:z.content||void 0,reasoningContent:B,toolCalls:z.tool_calls,finishReason:N||void 0}}m.debug("✅ [ChatService] Stream completed successfully")}catch(K){let W=Date.now()-X;throw m.error("❌ [ChatService] Stream request failed after",W,"ms"),m.error("❌ [ChatService] Stream error details:",K),K}}getConfig(){return{...this.config}}updateConfig($){m.debug("\uD83D\uDD04 [ChatService] Updating configuration"),m.debug("\uD83D\uDD04 [ChatService] New config:",{model:$.model,baseUrl:$.baseUrl,temperature:$.temperature,maxContextTokens:$.maxContextTokens,timeout:$.timeout,hasApiKey:!!$.apiKey});let Y={...this.config};if(this.config={...this.config,...$},Y.baseUrl!==this.config.baseUrl)this.detectedReasoningFieldName=null,m.debug("\uD83D\uDD04 [ChatService] Reset detectedReasoningFieldName due to baseUrl change");this.client=new F3({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,timeout:this.config.timeout??180000,maxRetries:2}),m.debug("✅ [ChatService] Configuration updated successfully"),m.debug("\uD83D\uDCCA [ChatService] Config changes:",{modelChanged:Y.model!==this.config.model,baseUrlChanged:Y.baseUrl!==this.config.baseUrl,temperatureChanged:Y.temperature!==this.config.temperature,maxContextTokensChanged:Y.maxContextTokens!==this.config.maxContextTokens,timeoutChanged:Y.timeout!==this.config.timeout,apiKeyChanged:Y.apiKey!==this.config.apiKey})}}var m,_3;var N3=D(()=>{B1();m=l("Chat"),_3=["reasoning_content","reasoning","reasoningContent","thinking_content"]});function I6($){switch($.provider){case"openai-compatible":return new D6($);case"gpt-openai-platform":return new e4($);case"anthropic":throw Error(`❌ Anthropic provider 暂未实现
72
81
 
73
82
  `+`请使用 "openai-compatible" 提供商,或者:
74
83
  `+`1. 等待官方实现
75
84
  `+`2. 贡献代码实现此功能: https://github.com/echoVic/blade-code
76
- `);default:return QJ.warn(`⚠️ 未知的 provider: ${$.provider}, 回退到 openai-compatible`),new w6($)}}var QJ;var r4=R(()=>{N1();Z3();q3();QJ=u("Service")});import{readFile as JJ}from"node:fs/promises";class A6{static MAX_FILES=5;static MAX_LINES_PER_FILE=1000;static analyzeFiles($){let Y=new Map;return $.forEach((X,Q)=>{if(this.extractFilePathsFromContent(X.content||"").forEach((q)=>{this.updateFileReference(Y,q,Q,!1)}),X.tool_calls&&Array.isArray(X.tool_calls))X.tool_calls.forEach((q)=>{let K=this.extractFilePathsFromToolCall(q),G=q.type==="function"&&"function"in q?q.function?.name:"",W=["Write","Edit"].includes(G||"");K.forEach((U)=>{this.updateFileReference(Y,U,Q,W)})})}),Array.from(Y.values()).sort((X,Q)=>{if(X.wasModified!==Q.wasModified)return X.wasModified?-1:1;if(X.mentions!==Q.mentions)return Q.mentions-X.mentions;return Q.lastMentioned-X.lastMentioned}).slice(0,this.MAX_FILES)}static async readFilesContent($){let Y=[];for(let Z of $)try{let X=await JJ(Z,"utf-8"),Q=X.split(`
77
- `),J=Q.length,q=X,K=!1,G=J;if(J>this.MAX_LINES_PER_FILE)q=Q.slice(0,this.MAX_LINES_PER_FILE).join(`
85
+ `);default:return wJ.warn(`⚠️ 未知的 provider: ${$.provider}, 回退到 openai-compatible`),new D6($)}}var wJ;var $8=D(()=>{B1();O3();N3();wJ=l("Service")});import{readFile as LJ}from"node:fs/promises";class M6{static MAX_FILES=5;static MAX_LINES_PER_FILE=1000;static analyzeFiles($){let Y=new Map;return $.forEach((X,Q)=>{let J=typeof X.content==="string"?X.content:(X.content||[]).filter((G)=>G.type==="text").map((G)=>G.text).join(`
86
+ `);if(this.extractFilePathsFromContent(J).forEach((G)=>{this.updateFileReference(Y,G,Q,!1)}),X.tool_calls&&Array.isArray(X.tool_calls))X.tool_calls.forEach((G)=>{let K=this.extractFilePathsFromToolCall(G),W=G.type==="function"&&"function"in G?G.function?.name:"",U=["Write","Edit"].includes(W||"");K.forEach((H)=>{this.updateFileReference(Y,H,Q,U)})})}),Array.from(Y.values()).sort((X,Q)=>{if(X.wasModified!==Q.wasModified)return X.wasModified?-1:1;if(X.mentions!==Q.mentions)return Q.mentions-X.mentions;return Q.lastMentioned-X.lastMentioned}).slice(0,this.MAX_FILES)}static async readFilesContent($){let Y=[];for(let Z of $)try{let X=await LJ(Z,"utf-8"),Q=X.split(`
87
+ `),J=Q.length,q=X,G=!1,K=J;if(J>this.MAX_LINES_PER_FILE)q=Q.slice(0,this.MAX_LINES_PER_FILE).join(`
78
88
  `),q+=`
79
89
 
80
- ... (truncated ${J-this.MAX_LINES_PER_FILE} lines)`,K=!0,G=this.MAX_LINES_PER_FILE;Y.push({path:Z,content:q,truncated:K,lines:J,includedLines:G})}catch(X){console.warn(`[FileAnalyzer] 无法读取文件: ${Z}`,X)}return Y}static extractFilePathsFromContent($){let Y=new Set,Z=/```(?:\w+)?\s*\n?([\s\S]*?)```/g,X=Array.from($.matchAll(Z));for(let J of X){let q=J[1];this.extractPathsFromText(q).forEach((G)=>Y.add(G))}return this.extractPathsFromText($).forEach((J)=>Y.add(J)),Array.from(Y)}static extractPathsFromText($){let Y=[],Z=[/(?:src|tests?|docs?|lib|config|scripts?|bin|utils?|components?|services?|hooks?)\/[\w\-/.]+\.[\w]+/g,/(?:package|tsconfig|vite\.config|webpack\.config|next\.config|babel\.config)\.[\w]+/g,/(?:\.\.?\/|\/)[a-zA-Z0-9\-_/.]+\.[\w]+/g];for(let X of Z){let Q=Array.from($.matchAll(X));for(let J of Q){let q=J[0];if(q=q.replace(/[,。;:!?""''()【】《》]$/g,""),q=q.replace(/[,.;:!?"'()[\]<>]$/g,""),this.isValidFilePath(q))Y.push(q)}}return Y}static extractFilePathsFromToolCall($){let Y=[];try{let Z=$.function?.name,X=typeof $.function?.arguments==="string"?JSON.parse($.function.arguments):$.function?.arguments||{};if(["Read","Write","Edit","Glob","Grep","NotebookEdit","mcp__github__get_file_contents","mcp__github__create_or_update_file"].includes(Z)){let J=["file_path","path","notebook_path","filePath"];for(let q of J)if(X[q]&&typeof X[q]==="string")Y.push(X[q])}}catch(Z){}return Y}static updateFileReference($,Y,Z,X){let Q=$.get(Y);if(Q)Q.mentions++,Q.lastMentioned=Z,Q.wasModified=Q.wasModified||X;else $.set(Y,{path:Y,mentions:1,lastMentioned:Z,wasModified:X})}static isValidFilePath($){if(!$.includes("/"))return!1;let Y=$.split("/"),Z=Y[Y.length-1];if(!Z.includes("."))return!1;let X=["ts","tsx","js","jsx","json","md","py","java","go","rs","c","cpp","h","css","scss","html","xml","yaml","yml","toml","sh","bash","sql","graphql","vue","svelte"],Q=Z.split(".").pop()?.toLowerCase();if(!Q||!X.includes(Q))return!1;return!0}}var K3=()=>{};import{encodingForModel as G3}from"js-tiktoken";var l0;var R6=R(()=>{l0=class l0{static encodingCache=new Map;static countTokens($,Y){let Z=this.getEncoding(Y),X=0;for(let Q of $){if(X+=4,Q.role)X+=Z.encode(Q.role).length;if(Q.content)if(typeof Q.content==="string")X+=Z.encode(Q.content).length;else X+=Z.encode(JSON.stringify(Q.content)).length;if(Q.tool_calls&&Array.isArray(Q.tool_calls))X+=this.countToolCallTokens(Q.tool_calls,Z);if(Q.name)X+=Z.encode(Q.name).length}return X}static getTokenLimit($){return $}static shouldCompact($,Y,Z,X=0.8){let Q=this.countTokens($,Y),J=Math.floor(Z*X);return Q>=J}static getEncoding($){if(!this.encodingCache.has($))try{let Y=G3($);this.encodingCache.set($,Y)}catch{try{let Y=G3("gpt-4");this.encodingCache.set($,Y)}catch{console.warn(`[TokenCounter] 无法为模型 ${$} 获取 encoding,使用粗略估算`),this.encodingCache.set($,{encode:(Y)=>{return Array(Math.ceil(Y.length/4))}})}}return this.encodingCache.get($)}static countToolCallTokens($,Y){let Z=0;for(let X of $){if(Z+=4,X.function?.name)Z+=Y.encode(X.function.name).length;if(X.function?.arguments){let Q=typeof X.function.arguments==="string"?X.function.arguments:JSON.stringify(X.function.arguments);Z+=Y.encode(Q).length}if(X.id)Z+=Y.encode(X.id).length}return Z}static clearCache(){this.encodingCache.clear()}static estimateTokens($){let Y=($.match(/[\u4e00-\u9fa5]/g)||[]).length,Z=$.length-Y;return Math.ceil(Y/1.5+Z/4)}}});import{nanoid as c2}from"nanoid";class l2{static THRESHOLD_PERCENT=0.8;static RETAIN_PERCENT=0.2;static FALLBACK_RETAIN_PERCENT=0.3;static async compact($,Y){let Z=Y.actualPreTokens??l0.countTokens($,Y.modelName),X=Y.actualPreTokens?"actual (from LLM usage)":"estimated";console.log(`[CompactionService] preTokens source: ${X}`);try{console.log("[CompactionService] 开始压缩,消息数:",$.length),console.log("[CompactionService] 压缩前 tokens:",Z);let J=A6.analyzeFiles($).map((B)=>B.path);console.log("[CompactionService] 提取重点文件:",J);let q=await A6.readFilesContent(J);console.log("[CompactionService] 成功读取文件:",q.length);let K=await this.generateSummary($,q,Y);console.log("[CompactionService] 生成总结,长度:",K.length);let G=Math.ceil($.length*this.RETAIN_PERCENT),W=$.slice(-G),U=new Set;for(let B of W)if(B.role==="assistant"&&B.tool_calls)for(let A of B.tool_calls)U.add(A.id);let H=W.filter((B)=>{if(B.role==="tool"&&B.tool_call_id)return U.has(B.tool_call_id);return!0});console.log("[CompactionService] 保留消息数:",G),console.log("[CompactionService] 过滤后保留消息数:",H.length);let O=c2(),z=this.createBoundaryMessage(O,Y.trigger,Z),_=c2(),F=this.createSummaryMessage(_,K),N=[F,...H],w=l0.countTokens(N,Y.modelName);return console.log("[CompactionService] 压缩完成!"),console.log("[CompactionService] Token 变化:",Z,"→",w,`(-${((1-w/Z)*100).toFixed(1)}%)`),{success:!0,summary:K,preTokens:Z,postTokens:w,filesIncluded:J,compactedMessages:N,boundaryMessage:z,summaryMessage:F}}catch(Q){return console.error("[CompactionService] 压缩失败,使用降级策略",Q),this.fallbackCompact($,Y,Z,Q)}}static async generateSummary($,Y,Z){let X=this.buildCompactionPrompt($,Y);console.log("[CompactionService] 使用压缩模型:",Z.modelName);let q=(await L6({apiKey:Z.apiKey||process.env.BLADE_API_KEY||"",baseUrl:Z.baseURL||process.env.BLADE_BASE_URL||"https://api.openai.com/v1",model:Z.modelName,temperature:0.3,maxOutputTokens:8000,timeout:60000,provider:"openai-compatible"}).chat([{role:"user",content:X}])).content||"",K=q.match(/<summary>([\s\S]*?)<\/summary>/);if(!K)return console.warn("[CompactionService] 总结格式不正确,使用完整响应"),q;return K[1].trim()}static buildCompactionPrompt($,Y){let Z=$.map((J,q)=>{let K=J.role||"unknown",G=typeof J.content==="string"?J.content:JSON.stringify(J.content),W=5000,U=G.length>5000?G.substring(0,5000)+"...":G;return`[${q+1}] ${K}: ${U}`}).join(`
90
+ ... (truncated ${J-this.MAX_LINES_PER_FILE} lines)`,G=!0,K=this.MAX_LINES_PER_FILE;Y.push({path:Z,content:q,truncated:G,lines:J,includedLines:K})}catch(X){console.warn(`[FileAnalyzer] 无法读取文件: ${Z}`,X)}return Y}static extractFilePathsFromContent($){let Y=new Set,Z=/```(?:\w+)?\s*\n?([\s\S]*?)```/g,X=Array.from($.matchAll(Z));for(let J of X){let q=J[1];this.extractPathsFromText(q).forEach((K)=>Y.add(K))}return this.extractPathsFromText($).forEach((J)=>Y.add(J)),Array.from(Y)}static extractPathsFromText($){let Y=[],Z=[/(?:src|tests?|docs?|lib|config|scripts?|bin|utils?|components?|services?|hooks?)\/[\w\-/.]+\.[\w]+/g,/(?:package|tsconfig|vite\.config|webpack\.config|next\.config|babel\.config)\.[\w]+/g,/(?:\.\.?\/|\/)[a-zA-Z0-9\-_/.]+\.[\w]+/g];for(let X of Z){let Q=Array.from($.matchAll(X));for(let J of Q){let q=J[0];if(q=q.replace(/[,。;:!?""''()【】《》]$/g,""),q=q.replace(/[,.;:!?"'()[\]<>]$/g,""),this.isValidFilePath(q))Y.push(q)}}return Y}static extractFilePathsFromToolCall($){let Y=[];try{let Z=$.function?.name,X=typeof $.function?.arguments==="string"?JSON.parse($.function.arguments):$.function?.arguments||{};if(["Read","Write","Edit","Glob","Grep","NotebookEdit","mcp__github__get_file_contents","mcp__github__create_or_update_file"].includes(Z)){let J=["file_path","path","notebook_path","filePath"];for(let q of J)if(X[q]&&typeof X[q]==="string")Y.push(X[q])}}catch(Z){}return Y}static updateFileReference($,Y,Z,X){let Q=$.get(Y);if(Q)Q.mentions++,Q.lastMentioned=Z,Q.wasModified=Q.wasModified||X;else $.set(Y,{path:Y,mentions:1,lastMentioned:Z,wasModified:X})}static isValidFilePath($){if(!$.includes("/"))return!1;let Y=$.split("/"),Z=Y[Y.length-1];if(!Z.includes("."))return!1;let X=["ts","tsx","js","jsx","json","md","py","java","go","rs","c","cpp","h","css","scss","html","xml","yaml","yml","toml","sh","bash","sql","graphql","vue","svelte"],Q=Z.split(".").pop()?.toLowerCase();if(!Q||!X.includes(Q))return!1;return!0}}var B3=()=>{};import{encodingForModel as w3}from"js-tiktoken";var r0;var k6=D(()=>{r0=class r0{static encodingCache=new Map;static countTokens($,Y){let Z=this.getEncoding(Y),X=0;for(let Q of $){if(X+=4,Q.role)X+=Z.encode(Q.role).length;if(Q.content)if(typeof Q.content==="string")X+=Z.encode(Q.content).length;else X+=Z.encode(JSON.stringify(Q.content)).length;if(Q.tool_calls&&Array.isArray(Q.tool_calls))X+=this.countToolCallTokens(Q.tool_calls,Z);if(Q.name)X+=Z.encode(Q.name).length}return X}static getTokenLimit($){return $}static shouldCompact($,Y,Z,X=0.8){let Q=this.countTokens($,Y),J=Math.floor(Z*X);return Q>=J}static getEncoding($){if(!this.encodingCache.has($))try{let Y=w3($);this.encodingCache.set($,Y)}catch{try{let Y=w3("gpt-4");this.encodingCache.set($,Y)}catch{console.warn(`[TokenCounter] 无法为模型 ${$} 获取 encoding,使用粗略估算`),this.encodingCache.set($,{encode:(Y)=>{return Array(Math.ceil(Y.length/4))}})}}return this.encodingCache.get($)}static countToolCallTokens($,Y){let Z=0;for(let X of $){if(Z+=4,X.function?.name)Z+=Y.encode(X.function.name).length;if(X.function?.arguments){let Q=typeof X.function.arguments==="string"?X.function.arguments:JSON.stringify(X.function.arguments);Z+=Y.encode(Q).length}if(X.id)Z+=Y.encode(X.id).length}return Z}static clearCache(){this.encodingCache.clear()}static estimateTokens($){let Y=($.match(/[\u4e00-\u9fa5]/g)||[]).length,Z=$.length-Y;return Math.ceil(Y/1.5+Z/4)}}});import{nanoid as i2}from"nanoid";class r2{static THRESHOLD_PERCENT=0.8;static RETAIN_PERCENT=0.2;static FALLBACK_RETAIN_PERCENT=0.3;static async compact($,Y){let Z=Y.actualPreTokens??r0.countTokens($,Y.modelName),X=Y.actualPreTokens?"actual (from LLM usage)":"estimated";console.log(`[CompactionService] preTokens source: ${X}`);try{console.log("[CompactionService] 开始压缩,消息数:",$.length),console.log("[CompactionService] 压缩前 tokens:",Z);let J=M6.analyzeFiles($).map((N)=>N.path);console.log("[CompactionService] 提取重点文件:",J);let q=await M6.readFilesContent(J);console.log("[CompactionService] 成功读取文件:",q.length);let G=await this.generateSummary($,q,Y);console.log("[CompactionService] 生成总结,长度:",G.length);let K=Math.ceil($.length*this.RETAIN_PERCENT),W=$.slice(-K),U=new Set;for(let N of W)if(N.role==="assistant"&&N.tool_calls)for(let b of N.tool_calls)U.add(b.id);let H=W.filter((N)=>{if(N.role==="tool"&&N.tool_call_id)return U.has(N.tool_call_id);return!0});console.log("[CompactionService] 保留消息数:",K),console.log("[CompactionService] 过滤后保留消息数:",H.length);let O=i2(),F=this.createBoundaryMessage(O,Y.trigger,Z),_=i2(),z=this.createSummaryMessage(_,G),w=[z,...H],B=r0.countTokens(w,Y.modelName);return console.log("[CompactionService] 压缩完成!"),console.log("[CompactionService] Token 变化:",Z,"→",B,`(-${((1-B/Z)*100).toFixed(1)}%)`),{success:!0,summary:G,preTokens:Z,postTokens:B,filesIncluded:J,compactedMessages:w,boundaryMessage:F,summaryMessage:z}}catch(Q){return console.error("[CompactionService] 压缩失败,使用降级策略",Q),this.fallbackCompact($,Y,Z,Q)}}static async generateSummary($,Y,Z){let X=this.buildCompactionPrompt($,Y);console.log("[CompactionService] 使用压缩模型:",Z.modelName);let q=(await I6({apiKey:Z.apiKey||process.env.BLADE_API_KEY||"",baseUrl:Z.baseURL||process.env.BLADE_BASE_URL||"https://api.openai.com/v1",model:Z.modelName,temperature:0.3,maxOutputTokens:8000,timeout:60000,provider:"openai-compatible"}).chat([{role:"user",content:X}])).content||"",G=q.match(/<summary>([\s\S]*?)<\/summary>/);if(!G)return console.warn("[CompactionService] 总结格式不正确,使用完整响应"),q;return G[1].trim()}static buildCompactionPrompt($,Y){let Z=$.map((J,q)=>{let G=J.role||"unknown",K=typeof J.content==="string"?J.content:JSON.stringify(J.content),W=5000,U=K.length>5000?K.substring(0,5000)+"...":K;return`[${q+1}] ${G}: ${U}`}).join(`
81
91
 
82
92
  `),X=Y.map((J)=>{return`### ${J.path}
83
93
  \`\`\`
@@ -150,13 +160,14 @@ ${Y.length>0?`## Important Files
150
160
 
151
161
  ${X}`:""}
152
162
 
153
- Please provide your summary following the structure specified above, with both <analysis> and <summary> sections.`}static createBoundaryMessage($,Y,Z){return{id:c2(),role:"system",content:"Conversation compacted",metadata:{type:"system",subtype:"compact_boundary",parentId:$,compactMetadata:{trigger:Y,preTokens:Z}}}}static createSummaryMessage($,Y){return{id:c2(),role:"user",content:Y,metadata:{parentId:$,isCompactSummary:!0}}}static fallbackCompact($,Y,Z,X){let Q=Math.ceil($.length*this.FALLBACK_RETAIN_PERCENT),J=$.slice(-Q),q=new Set;for(let F of J)if(F.role==="assistant"&&F.tool_calls)for(let N of F.tool_calls)q.add(N.id);let K=J.filter((F)=>{if(F.role==="tool"&&F.tool_call_id)return q.has(F.tool_call_id);return!0}),G=c2(),W=this.createBoundaryMessage(G,Y.trigger,Z),U=X instanceof Error?X.message:String(X),H=c2(),O=this.createSummaryMessage(H,`[Automatic compaction failed; using fallback]
163
+ Please provide your summary following the structure specified above, with both <analysis> and <summary> sections.`}static createBoundaryMessage($,Y,Z){return{id:i2(),role:"system",content:"Conversation compacted",metadata:{type:"system",subtype:"compact_boundary",parentId:$,compactMetadata:{trigger:Y,preTokens:Z}}}}static createSummaryMessage($,Y){return{id:i2(),role:"user",content:Y,metadata:{parentId:$,isCompactSummary:!0}}}static fallbackCompact($,Y,Z,X){let Q=Math.ceil($.length*this.FALLBACK_RETAIN_PERCENT),J=$.slice(-Q),q=new Set;for(let z of J)if(z.role==="assistant"&&z.tool_calls)for(let w of z.tool_calls)q.add(w.id);let G=J.filter((z)=>{if(z.role==="tool"&&z.tool_call_id)return q.has(z.tool_call_id);return!0}),K=i2(),W=this.createBoundaryMessage(K,Y.trigger,Z),U=X instanceof Error?X.message:String(X),H=i2(),O=this.createSummaryMessage(H,`[Automatic compaction failed; using fallback]
154
164
 
155
165
  An error occurred during compaction. Retained the latest ${Q} messages (~30%).
156
166
 
157
167
  Error: ${U}
158
168
 
159
- The conversation can continue, but consider retrying compaction later with /compact.`),z=[O,...K],_=l0.countTokens(z,Y.modelName);return{success:!1,summary:O.content,preTokens:Z,postTokens:_,filesIncluded:[],compactedMessages:z,boundaryMessage:W,summaryMessage:O,error:U}}}var a4=R(()=>{r4();K3();R6()});import qJ from"fs/promises";import KJ from"path";async function U3($){for(let Y of $)try{let Z;if(Y.trim().startsWith("{")){let J=JSON.parse(Y);if(J.name&&J.type){let{name:q,...K}=J;Z={[q]:K}}else Z=J}else{let J=KJ.resolve(process.cwd(),Y),q=await qJ.readFile(J,"utf-8"),K=JSON.parse(q);Z=K.mcpServers||K}let Q={...X0(),...Z};n().config.actions.updateConfig({mcpServers:Q}),W3.debug(`✅ Loaded MCP config from CLI: ${Object.keys(Z).join(", ")}`)}catch(Z){W3.warn(`⚠️ Failed to load MCP config "${Y}":`,Z)}}var W3;var H3=R(()=>{N1();F1();W3=u("General")});import{execSync as GJ}from"child_process";import*as r2 from"os";import*as i2 from"path";function WJ(){let $=process.cwd(),Y=UJ($);return{workingDirectory:$,projectRoot:Y,platform:`${r2.platform()} (${r2.arch()})`,nodeVersion:process.version,currentDate:new Date().toISOString().split("T")[0],homeDirectory:r2.homedir()}}function b6(){let $=WJ();return`# Environment Context
169
+ The conversation can continue, but consider retrying compaction later with /compact.`),F=[O,...G],_=r0.countTokens(F,Y.modelName);return{success:!1,summary:typeof O.content==="string"?O.content:O.content.filter((z)=>z.type==="text").map((z)=>z.text).join(`
170
+ `),preTokens:Z,postTokens:_,filesIncluded:[],compactedMessages:F,boundaryMessage:W,summaryMessage:O,error:U}}}var Y8=D(()=>{$8();B3();k6()});import AJ from"fs/promises";import bJ from"path";async function A3($){for(let Y of $)try{let Z;if(Y.trim().startsWith("{")){let J=JSON.parse(Y);if(J.name&&J.type){let{name:q,...G}=J;Z={[q]:G}}else Z=J}else{let J=bJ.resolve(process.cwd(),Y),q=await AJ.readFile(J,"utf-8"),G=JSON.parse(q);Z=G.mcpServers||G}let Q={...Q0(),...Z};s().config.actions.updateConfig({mcpServers:Q}),L3.debug(`✅ Loaded MCP config from CLI: ${Object.keys(Z).join(", ")}`)}catch(Z){L3.warn(`⚠️ Failed to load MCP config "${Y}":`,Z)}}var L3;var b3=D(()=>{B1();z1();L3=l("General")});import{execSync as RJ}from"child_process";import*as n2 from"os";import*as a2 from"path";function VJ(){let $=process.cwd(),Y=DJ($);return{workingDirectory:$,projectRoot:Y,platform:`${n2.platform()} (${n2.arch()})`,nodeVersion:process.version,currentDate:new Date().toISOString().split("T")[0],homeDirectory:n2.homedir()}}function j6(){let $=VJ();return`# Environment Context
160
171
 
161
172
  ## Working Directory
162
173
  **Current**: \`${$.workingDirectory}\`
@@ -174,9 +185,9 @@ When using file tools (read, write, edit), provide **absolute paths**:
174
185
  - ❌ Incorrect: \`/package.json\` (root directory)
175
186
  - ❌ Incorrect: \`package.json\` (relative path without context)
176
187
 
177
- **Always use** \`${$.workingDirectory}/\` as the base for file paths.`}function UJ($){let Y=$;while(Y!==i2.dirname(Y)){if(O3(i2.join(Y,".git")))return Y;if(O3(i2.join(Y,"package.json")))return Y;Y=i2.dirname(Y)}return $}function O3($){try{return GJ(`test -e "${$}"`,{stdio:"ignore"}),!0}catch{return!1}}var n4=()=>{};function t4($){return`<system-reminder>Plan mode is active. You MUST NOT make any file changes or run non-readonly tools. Research only, then call ExitPlanMode with your plan.</system-reminder>
188
+ **Always use** \`${$.workingDirectory}/\` as the base for file paths.`}function DJ($){let Y=$;while(Y!==a2.dirname(Y)){if(R3(a2.join(Y,".git")))return Y;if(R3(a2.join(Y,"package.json")))return Y;Y=a2.dirname(Y)}return $}function R3($){try{return RJ(`test -e "${$}"`,{stdio:"ignore"}),!0}catch{return!1}}var Z8=()=>{};function d$($){return`<system-reminder>Plan mode is active. You MUST NOT make any file changes or run non-readonly tools. Research only, then call ExitPlanMode with your plan.</system-reminder>
178
189
 
179
- `+$}var o4=`You are Blade Code, an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
190
+ `+$}var X8=`You are Blade Code, an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
180
191
 
181
192
  IMPORTANT: Assist with authorized security testing, defensive security, CTF challenges, and educational contexts. Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes. Dual-use security tools (C2 frameworks, credential testing, exploit development) require clear authorization context: pentesting engagements, CTF competitions, security research, or defensive use cases.
182
193
  IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.
@@ -324,7 +335,7 @@ assistant: Clients are marked as failed in the \`connectToServer\` function in s
324
335
  </example>
325
336
 
326
337
  # Language Requirement
327
- IMPORTANT: Always respond in Chinese (Simplified Chinese). Translate all your responses to Chinese before sending them to the user.`,s4=`You are in **PLAN MODE** - a read-only research phase for designing implementation plans.
338
+ IMPORTANT: Always respond in Chinese (Simplified Chinese). Translate all your responses to Chinese before sending them to the user.`,Q8=`You are in **PLAN MODE** - a read-only research phase for designing implementation plans.
328
339
 
329
340
  ## Core Objective
330
341
 
@@ -364,57 +375,57 @@ Your plan should include:
364
375
  3. **Steps** - Detailed implementation steps with file paths
365
376
  4. **Testing** - How to verify changes
366
377
  5. **Risks** - Potential issues and mitigations
367
- `;var e4=()=>{};import{promises as z3}from"fs";import HJ from"path";async function V6($={}){let{projectPath:Y,replaceDefault:Z,append:X,mode:Q,includeEnvironment:J=!0}=$,q=[],K=[];if(J){let H=b6();if(H)q.push(H),K.push({name:"environment",loaded:!0,length:H.length})}let G=Q==="plan",W=G?s4:Z??o4;if(q.push(W),K.push({name:G?"plan_mode_prompt":Z?"replace_default":"default",loaded:!0,length:W.length}),Y){let H=await OJ(Y);if(H)q.push(H),K.push({name:"blade_md",loaded:!0,length:H.length});else K.push({name:"blade_md",loaded:!1})}if(X?.trim())q.push(X.trim()),K.push({name:"append",loaded:!0,length:X.trim().length});return{prompt:q.join(`
378
+ `;var J8=()=>{};import{promises as V3}from"fs";import IJ from"path";async function E6($={}){let{projectPath:Y,replaceDefault:Z,append:X,mode:Q,includeEnvironment:J=!0}=$,q=[],G=[];if(J){let H=j6();if(H)q.push(H),G.push({name:"environment",loaded:!0,length:H.length})}let K=Q==="plan",W=K?Q8:Z??X8;if(q.push(W),G.push({name:K?"plan_mode_prompt":Z?"replace_default":"default",loaded:!0,length:W.length}),Y){let H=await MJ(Y);if(H)q.push(H),G.push({name:"blade_md",loaded:!0,length:H.length});else G.push({name:"blade_md",loaded:!1})}if(X?.trim())q.push(X.trim()),G.push({name:"append",loaded:!0,length:X.trim().length});return{prompt:q.join(`
368
379
 
369
380
  ---
370
381
 
371
- `),sources:K}}async function OJ($){let Y=HJ.join($,"BLADE.md");try{return(await z3.readFile(Y,"utf-8")).trim()||null}catch{return null}}var F3=R(()=>{s1();n4();e4()});var _3=R(()=>{F3();e4()});import*as D6 from"fs/promises";import*as d1 from"path";class M6{static normalize($,Y){let Z=d1.isAbsolute($)?$:d1.resolve(Y,$),X=d1.normalize(Z),Q=d1.normalize(Y);if(!X.startsWith(Q))throw new R2(`Path outside workspace: ${$} (resolved to ${X}, workspace: ${Q})`,"PATH_OUTSIDE_WORKSPACE");return X}static checkRestricted($){let Y=$.split(d1.sep);for(let Z of B3)if(Y.includes(Z))throw new R2(`Access denied: "${Z}" is a protected directory`,"RESTRICTED_PATH")}static checkTraversal($){if($.includes(".."))throw new R2(`Path traversal not allowed: ${$}`,"PATH_TRAVERSAL")}static async validatePath($,Y){this.checkTraversal($);let Z=this.normalize($,Y);this.checkRestricted(Z);try{await D6.access(Z)}catch(X){throw new R2(`Path not found: ${$}`,"PATH_NOT_FOUND")}return Z}static async resolveSymlink($,Y){try{let Z=await D6.realpath($),X=d1.normalize(Y);if(!Z.startsWith(X))throw new R2(`Symlink points outside workspace: ${$} -> ${Z}`,"SYMLINK_OUTSIDE_WORKSPACE");return Z}catch(Z){if(Z instanceof R2)throw Z;return $}}static getRelativePath($,Y){return d1.relative(Y,$)}static isWithinWorkspace($,Y){let Z=d1.normalize($),X=d1.normalize(Y);return Z.startsWith(X)}static isRestricted($){let Y=$.split(d1.sep);return B3.some((Z)=>Y.includes(Z))}}var B3,R2;var N3=R(()=>{B3=[".git",".claude","node_modules",".env",".env.local",".env.production",".env.development",".env.test"];R2=class R2 extends Error{code;constructor($,Y){super($);this.code=Y;this.name="PathSecurityError"}}});var I6;var w3=R(()=>{I6=class I6{static PATTERN=/@"([^"]+)"|@([^\s]+)/g;static LINE_RANGE_PATTERN=/#L(\d+)(?:-(\d+))?$/;static GLOB_PATTERN=/[*?[\]]/;static extract($){let Y=[],Z;this.PATTERN.lastIndex=0;while((Z=this.PATTERN.exec($))!==null){let X=Z[0],Q=Z[1]||Z[2],J=this.parseLineRange(Q);if(J)Q=Q.replace(this.LINE_RANGE_PATTERN,"");let q=this.GLOB_PATTERN.test(Q);Y.push({raw:X,path:Q.trim(),lineRange:J,startIndex:Z.index,endIndex:Z.index+X.length,isGlob:q})}return Y}static parseLineRange($){let Y=$.match(this.LINE_RANGE_PATTERN);if(!Y)return;let Z=parseInt(Y[1],10),X=Y[2]?parseInt(Y[2],10):void 0;return{start:Z,end:X}}static hasAtMentions($){return $.includes("@")}static isValidPath($){if(!$||$.trim().length===0)return!1;let Y=["<",">","|","\x00"];for(let Z of Y)if($.includes(Z))return!1;return!0}static removeAtMentions($){return this.PATTERN.lastIndex=0,$.replace(this.PATTERN,"")}}});import L3 from"fast-glob";import*as a2 from"fs/promises";import*as A3 from"path";class $8{fileCache=new Map;options;constructor($){this.options={maxFileSize:1048576,maxLines:2000,maxTokens:32000,...$},L0.debug("AttachmentCollector initialized",{maxFileSize:this.options.maxFileSize,maxLines:this.options.maxLines})}async collect($){if(!I6.hasAtMentions($))return[];let Y=I6.extract($);if(Y.length===0)return[];L0.debug(`Found ${Y.length} @ mentions`);let Z=Y.map((Q)=>this.processOne(Q));return(await Promise.allSettled(Z)).map((Q,J)=>{if(Q.status==="fulfilled")return Q.value;else{let q=Y[J],K=Q.reason instanceof Error?Q.reason.message:String(Q.reason);return L0.warn(`Failed to process @${q.path}:`,K),{type:"error",path:q.path,content:"",error:K}}})}async processOne($){if($.isGlob)return L0.debug(`Processing glob pattern: ${$.path}`),await this.processGlob($.path);let Y=await M6.validatePath($.path,this.options.cwd),Z=await M6.resolveSymlink(Y,this.options.cwd);if((await a2.stat(Z)).isDirectory())return L0.debug(`Processing directory: ${$.path}`),await this.renderDirectoryTree(Z,$.path);return L0.debug(`Processing file: ${$.path}`,{lineRange:$.lineRange}),await this.readFile(Z,$.path,$.lineRange)}async readFile($,Y,Z){let X=this.fileCache.get($);if(X&&Date.now()-X.timestamp<60000)return L0.debug(`Cache hit: ${Y}`),this.formatFileAttachment(Y,X.content,Z);let Q=await a2.stat($);if(Q.size>this.options.maxFileSize)throw Error(`File too large: ${Math.round(Q.size/1024/1024)}MB (max ${Math.round(this.options.maxFileSize/1024/1024)}MB)`);let J;try{J=await a2.readFile($,"utf-8")}catch(q){throw Error(`Cannot read file as text: ${Y}. It may be a binary file.`)}return this.fileCache.set($,{content:J,timestamp:Date.now()}),this.formatFileAttachment(Y,J,Z)}formatFileAttachment($,Y,Z){let X=Y.split(`
372
- `),Q=Y,J=!1,q=Z;if(Z){let K=Math.max(0,Z.start-1),G=Z.end?Z.end:Z.start;if(K>=X.length)throw Error(`Line range start (${Z.start}) exceeds file length (${X.length} lines)`);let W=Math.min(G,X.length);Q=X.slice(K,W).join(`
373
- `);let U=Array.from({length:W-K},(O,z)=>K+z+1);Q=Q.split(`
374
- `).map((O,z)=>`${U[z]}: ${O}`).join(`
382
+ `),sources:G}}async function MJ($){let Y=IJ.join($,"BLADE.md");try{return(await V3.readFile(Y,"utf-8")).trim()||null}catch{return null}}var D3=D(()=>{s1();Z8();J8()});var I3=D(()=>{D3();J8()});import*as v6 from"fs/promises";import*as c1 from"path";class y6{static normalize($,Y){let Z=c1.isAbsolute($)?$:c1.resolve(Y,$),X=c1.normalize(Z),Q=c1.normalize(Y);if(!X.startsWith(Q))throw new b2(`Path outside workspace: ${$} (resolved to ${X}, workspace: ${Q})`,"PATH_OUTSIDE_WORKSPACE");return X}static checkRestricted($){let Y=$.split(c1.sep);for(let Z of M3)if(Y.includes(Z))throw new b2(`Access denied: "${Z}" is a protected directory`,"RESTRICTED_PATH")}static checkTraversal($){if($.includes(".."))throw new b2(`Path traversal not allowed: ${$}`,"PATH_TRAVERSAL")}static async validatePath($,Y){this.checkTraversal($);let Z=this.normalize($,Y);this.checkRestricted(Z);try{await v6.access(Z)}catch(X){throw new b2(`Path not found: ${$}`,"PATH_NOT_FOUND")}return Z}static async resolveSymlink($,Y){try{let Z=await v6.realpath($),X=c1.normalize(Y);if(!Z.startsWith(X))throw new b2(`Symlink points outside workspace: ${$} -> ${Z}`,"SYMLINK_OUTSIDE_WORKSPACE");return Z}catch(Z){if(Z instanceof b2)throw Z;return $}}static getRelativePath($,Y){return c1.relative(Y,$)}static isWithinWorkspace($,Y){let Z=c1.normalize($),X=c1.normalize(Y);return Z.startsWith(X)}static isRestricted($){let Y=$.split(c1.sep);return M3.some((Z)=>Y.includes(Z))}}var M3,b2;var k3=D(()=>{M3=[".git",".claude","node_modules",".env",".env.local",".env.production",".env.development",".env.test"];b2=class b2 extends Error{code;constructor($,Y){super($);this.code=Y;this.name="PathSecurityError"}}});var P6;var j3=D(()=>{P6=class P6{static PATTERN=/@"([^"]+)"|@([^\s]+)/g;static LINE_RANGE_PATTERN=/#L(\d+)(?:-(\d+))?$/;static GLOB_PATTERN=/[*?[\]]/;static extract($){let Y=[],Z;this.PATTERN.lastIndex=0;while((Z=this.PATTERN.exec($))!==null){let X=Z[0],Q=Z[1]||Z[2],J=this.parseLineRange(Q);if(J)Q=Q.replace(this.LINE_RANGE_PATTERN,"");let q=this.GLOB_PATTERN.test(Q);Y.push({raw:X,path:Q.trim(),lineRange:J,startIndex:Z.index,endIndex:Z.index+X.length,isGlob:q})}return Y}static parseLineRange($){let Y=$.match(this.LINE_RANGE_PATTERN);if(!Y)return;let Z=parseInt(Y[1],10),X=Y[2]?parseInt(Y[2],10):void 0;return{start:Z,end:X}}static hasAtMentions($){return $.includes("@")}static isValidPath($){if(!$||$.trim().length===0)return!1;let Y=["<",">","|","\x00"];for(let Z of Y)if($.includes(Z))return!1;return!0}static removeAtMentions($){return this.PATTERN.lastIndex=0,$.replace(this.PATTERN,"")}}});import E3 from"fast-glob";import*as o2 from"fs/promises";import*as v3 from"path";class q8{fileCache=new Map;options;constructor($){this.options={maxFileSize:1048576,maxLines:2000,maxTokens:32000,...$},L0.debug("AttachmentCollector initialized",{maxFileSize:this.options.maxFileSize,maxLines:this.options.maxLines})}async collect($){if(!P6.hasAtMentions($))return[];let Y=P6.extract($);if(Y.length===0)return[];L0.debug(`Found ${Y.length} @ mentions`);let Z=Y.map((Q)=>this.processOne(Q));return(await Promise.allSettled(Z)).map((Q,J)=>{if(Q.status==="fulfilled")return Q.value;else{let q=Y[J],G=Q.reason instanceof Error?Q.reason.message:String(Q.reason);return L0.warn(`Failed to process @${q.path}:`,G),{type:"error",path:q.path,content:"",error:G}}})}async processOne($){if($.isGlob)return L0.debug(`Processing glob pattern: ${$.path}`),await this.processGlob($.path);let Y=await y6.validatePath($.path,this.options.cwd),Z=await y6.resolveSymlink(Y,this.options.cwd);if((await o2.stat(Z)).isDirectory())return L0.debug(`Processing directory: ${$.path}`),await this.renderDirectoryTree(Z,$.path);return L0.debug(`Processing file: ${$.path}`,{lineRange:$.lineRange}),await this.readFile(Z,$.path,$.lineRange)}async readFile($,Y,Z){let X=this.fileCache.get($);if(X&&Date.now()-X.timestamp<60000)return L0.debug(`Cache hit: ${Y}`),this.formatFileAttachment(Y,X.content,Z);let Q=await o2.stat($);if(Q.size>this.options.maxFileSize)throw Error(`File too large: ${Math.round(Q.size/1024/1024)}MB (max ${Math.round(this.options.maxFileSize/1024/1024)}MB)`);let J;try{J=await o2.readFile($,"utf-8")}catch(q){throw Error(`Cannot read file as text: ${Y}. It may be a binary file.`)}return this.fileCache.set($,{content:J,timestamp:Date.now()}),this.formatFileAttachment(Y,J,Z)}formatFileAttachment($,Y,Z){let X=Y.split(`
383
+ `),Q=Y,J=!1,q=Z;if(Z){let G=Math.max(0,Z.start-1),K=Z.end?Z.end:Z.start;if(G>=X.length)throw Error(`Line range start (${Z.start}) exceeds file length (${X.length} lines)`);let W=Math.min(K,X.length);Q=X.slice(G,W).join(`
384
+ `);let U=Array.from({length:W-G},(O,F)=>G+F+1);Q=Q.split(`
385
+ `).map((O,F)=>`${U[F]}: ${O}`).join(`
375
386
  `),q={start:Z.start,end:W}}else if(X.length>this.options.maxLines)Q=X.slice(0,this.options.maxLines).join(`
376
387
  `),Q+=`
377
388
 
378
- [... truncated ${X.length-this.options.maxLines} lines ...]`,J=!0;return{type:"file",path:$,content:Q,metadata:{size:Y.length,lines:X.length,truncated:J,lineRange:q}}}async renderDirectoryTree($,Y){let Z=await L3("**/*",{cwd:$,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(Z.length===0)return{type:"directory",path:Y,content:"(empty directory)"};L0.debug(`Found ${Z.length} files in directory: ${Y}`);let X=this.buildFileTree(Z),Q=this.printTree(X,Y),J=500,q=Z.length>J?`
389
+ [... truncated ${X.length-this.options.maxLines} lines ...]`,J=!0;return{type:"file",path:$,content:Q,metadata:{size:Y.length,lines:X.length,truncated:J,lineRange:q}}}async renderDirectoryTree($,Y){let Z=await E3("**/*",{cwd:$,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(Z.length===0)return{type:"directory",path:Y,content:"(empty directory)"};L0.debug(`Found ${Z.length} files in directory: ${Y}`);let X=this.buildFileTree(Z),Q=this.printTree(X,Y),J=500,q=Z.length>J?`
379
390
 
380
- [... and ${Z.length-J} more files]`:"";return{type:"directory",path:Y,content:Q+q,metadata:{lines:Z.length,truncated:Z.length>J}}}buildFileTree($){let Y=new Map;for(let Z of $){let X=Z.split("/"),Q=Y;for(let J=0;J<X.length;J++){let q=X[J],K=J===X.length-1;if(!Q.has(q))Q.set(q,K?null:new Map);if(!K)Q=Q.get(q)}}return Y}printTree($,Y,Z="",X=!0){let Q=[];if(Z==="")Q.push(`${Y}/`);let J=Array.from($.entries()).sort((q,K)=>{let G=q[1]instanceof Map,W=K[1]instanceof Map;if(G!==W)return W?1:-1;return q[0].localeCompare(K[0])});return J.forEach(([q,K],G)=>{let W=G===J.length-1,U=W?"└── ":"├── ",H=K instanceof Map;if(Q.push(`${Z}${U}${q}${H?"/":""}`),H&&K.size>0){let O=Z+(W?" ":"│ ");Q.push(this.printTree(K,"",O,W))}}),Q.filter((q)=>q).join(`
381
- `)}async processGlob($){let Y=await L3($,{cwd:this.options.cwd,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(Y.length===0)return{type:"error",path:$,content:"",error:`No files matched pattern: ${$}`};L0.debug(`Glob pattern "${$}" matched ${Y.length} files`);let Z=30,X=Y.slice(0,Z),J=(await Promise.allSettled(X.map(async(W)=>{let U=A3.join(this.options.cwd,W);try{let H=await a2.readFile(U,"utf-8"),O=H.split(`
382
- `),z=200,_=H,F=!1;if(O.length>200)_=O.slice(0,200).join(`
391
+ [... and ${Z.length-J} more files]`:"";return{type:"directory",path:Y,content:Q+q,metadata:{lines:Z.length,truncated:Z.length>J}}}buildFileTree($){let Y=new Map;for(let Z of $){let X=Z.split("/"),Q=Y;for(let J=0;J<X.length;J++){let q=X[J],G=J===X.length-1;if(!Q.has(q))Q.set(q,G?null:new Map);if(!G)Q=Q.get(q)}}return Y}printTree($,Y,Z="",X=!0){let Q=[];if(Z==="")Q.push(`${Y}/`);let J=Array.from($.entries()).sort((q,G)=>{let K=q[1]instanceof Map,W=G[1]instanceof Map;if(K!==W)return W?1:-1;return q[0].localeCompare(G[0])});return J.forEach(([q,G],K)=>{let W=K===J.length-1,U=W?"└── ":"├── ",H=G instanceof Map;if(Q.push(`${Z}${U}${q}${H?"/":""}`),H&&G.size>0){let O=Z+(W?" ":"│ ");Q.push(this.printTree(G,"",O,W))}}),Q.filter((q)=>q).join(`
392
+ `)}async processGlob($){let Y=await E3($,{cwd:this.options.cwd,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(Y.length===0)return{type:"error",path:$,content:"",error:`No files matched pattern: ${$}`};L0.debug(`Glob pattern "${$}" matched ${Y.length} files`);let Z=30,X=Y.slice(0,Z),J=(await Promise.allSettled(X.map(async(W)=>{let U=v3.join(this.options.cwd,W);try{let H=await o2.readFile(U,"utf-8"),O=H.split(`
393
+ `),F=200,_=H,z=!1;if(O.length>200)_=O.slice(0,200).join(`
383
394
  `),_+=`
384
395
 
385
- [... truncated ${O.length-200} lines ...]`,F=!0;return{path:W,content:_,lines:O.length,truncated:F}}catch(H){return{path:W,content:`[Error: ${H instanceof Error?H.message:"unknown error"}]`,lines:0,truncated:!1}}}))).map((W)=>W.status==="fulfilled"?W.value:null).filter((W)=>W!==null),K=J.map((W)=>`--- ${W.path} (${W.lines} lines${W.truncated?", truncated":""}) ---
396
+ [... truncated ${O.length-200} lines ...]`,z=!0;return{path:W,content:_,lines:O.length,truncated:z}}catch(H){return{path:W,content:`[Error: ${H instanceof Error?H.message:"unknown error"}]`,lines:0,truncated:!1}}}))).map((W)=>W.status==="fulfilled"?W.value:null).filter((W)=>W!==null),G=J.map((W)=>`--- ${W.path} (${W.lines} lines${W.truncated?", truncated":""}) ---
386
397
  ${W.content}`).join(`
387
398
 
388
- `),G=Y.length>Z?`
399
+ `),K=Y.length>Z?`
389
400
 
390
- [... and ${Y.length-Z} more files matched]`:"";return{type:"file",path:$,content:K+G,metadata:{lines:J.reduce((W,U)=>W+U.lines,0),truncated:Y.length>Z||J.some((W)=>W.truncated)}}}clearExpiredCache(){let $=Date.now(),Y=0;for(let[Z,X]of this.fileCache.entries())if($-X.timestamp>60000)this.fileCache.delete(Z),Y++;if(Y>0)L0.debug(`Cleared ${Y} expired cache entries`)}clearCache(){this.fileCache.clear(),L0.debug("Cleared all cache")}getCacheStats(){return{size:this.fileCache.size,keys:Array.from(this.fileCache.keys())}}}var L0;var R3=R(()=>{N1();N3();w3();L0=u("Prompts")});import*as A0 from"fs/promises";class $2{async readTextFile($){return A0.readFile($,"utf-8")}async writeTextFile($,Y){await A0.writeFile($,Y,"utf-8")}async exists($){try{return await A0.access($),!0}catch{return!1}}async readBinaryFile($){return A0.readFile($)}async stat($){try{let Y=await A0.stat($);return{size:Y.size,isDirectory:Y.isDirectory(),isFile:Y.isFile(),mtime:Y.mtime}}catch{return null}}async mkdir($,Y){await A0.mkdir($,{recursive:Y?.recursive??!1})}}function n2(){return Y8}function k6($){Y8=$}function b3(){Y8=new $2}var Y8;var o2=R(()=>{Y8=new $2});class Z8{connection;sessionId;capabilities;fallback;constructor($,Y,Z,X=new $2){this.connection=$;this.sessionId=Y;this.capabilities=Z;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(Y){return $0.warn(`[AcpFileSystem] readTextFile ACP failed, fallback: ${Y}`),this.fallback.readTextFile($)}}async writeTextFile($,Y){if(!this.capabilities.writeTextFile)return $0.debug(`[AcpFileSystem] writeTextFile fallback: ${$}`),this.fallback.writeTextFile($,Y);try{$0.debug(`[AcpFileSystem] writeTextFile via ACP: ${$}`),await this.connection.writeTextFile({path:$,content:Y,sessionId:this.sessionId})}catch(Z){return $0.warn(`[AcpFileSystem] writeTextFile ACP failed, fallback: ${Z}`),this.fallback.writeTextFile($,Y)}}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(Y){let Z=String(Y).toLowerCase();if(["not found","no such file","enoent","does not exist","file not found","path not found"].some((q)=>Z.includes(q)))return $0.debug(`[AcpFileSystem] exists(${$}): false (ACP: not found)`),!1;let J=zJ(Z);return $0.warn(`[AcpFileSystem] exists(${$}): assuming exists due to ${J} error`,{error:String(Y),errorType:J,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($,Y){return $0.debug(`[AcpFileSystem] mkdir fallback: ${$}`),this.fallback.mkdir($,Y)}getCapabilities(){return this.capabilities}canReadTextFile(){return this.capabilities.readTextFile??!1}canWriteTextFile(){return this.capabilities.writeTextFile??!1}}function zJ($){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 $0;var V3=R(()=>{N1();o2();$0=u("Agent")});import{spawn as FJ}from"child_process";class X8{async execute($,Y){return new Promise((Z)=>{let X=process.platform==="win32"?"cmd.exe":"/bin/bash",Q=process.platform==="win32"?["/c",$]:["-c",$],J=FJ(X,Q,{cwd:Y?.cwd||process.cwd(),env:{...process.env,...Y?.env},stdio:["pipe","pipe","pipe"]}),q="",K="",G=!1,W=Y?.timeout?setTimeout(()=>{G=!0,J.kill("SIGTERM")},Y.timeout):null;if(Y?.signal)Y.signal.addEventListener("abort",()=>{G=!0,J.kill("SIGTERM")});J.stdout.on("data",(U)=>{let H=U.toString();q+=H,Y?.onOutput?.(H)}),J.stderr.on("data",(U)=>{let H=U.toString();K+=H,Y?.onOutput?.(H)}),J.on("close",(U)=>{if(W)clearTimeout(W);Z({success:U===0&&!G,stdout:q,stderr:K,exitCode:U,error:G?"Command was terminated":void 0})}),J.on("error",(U)=>{if(W)clearTimeout(W);Z({success:!1,stdout:q,stderr:K,exitCode:null,error:U.message})})})}isAvailable(){return!0}}class D3{connection;sessionId;fallback;constructor($,Y,Z=new X8){this.connection=$;this.sessionId=Y;this.fallback=Z}async execute($,Y){try{v0.debug(`[AcpTerminal] Executing command via ACP: ${$}`);let Z=await this.connection.createTerminal({sessionId:this.sessionId,command:$,cwd:Y?.cwd,env:Y?.env?Object.entries(Y.env).map(([W,U])=>({name:W,value:U})):void 0}),X=0,Q=null;if(Y?.onOutput)Q=setInterval(async()=>{try{let U=(await Z.currentOutput()).output||"";if(U.length>X){let H=U.slice(X);X=U.length,Y.onOutput?.(H)}}catch{}},100);let J=(W=!1)=>{if(Q)clearInterval(Q),Q=null;(W?Z.kill().then(()=>v0.debug("[AcpTerminal] Killed remote command")).catch(()=>{}).then(()=>Z.release()).catch(()=>{}):Z.release().catch(()=>{})).catch(()=>{})},q=[];if(q.push(Z.waitForExit().then((W)=>({type:"completed",exitCode:W.exitCode??null}))),Y?.timeout)q.push(new Promise((W)=>{setTimeout(()=>W({type:"timeout"}),Y.timeout)}));if(Y?.signal)q.push(new Promise((W)=>{if(Y.signal.aborted)W({type:"aborted"});else Y.signal.addEventListener("abort",()=>W({type:"aborted"}),{once:!0})}));let K=await Promise.race(q),G="";try{if(G=(await Z.currentOutput()).output||"",Y?.onOutput&&G.length>X)Y.onOutput(G.slice(X))}catch{}switch(K.type){case"completed":return J(!1),{success:K.exitCode===0,stdout:G,stderr:"",exitCode:K.exitCode};case"timeout":return v0.debug(`[AcpTerminal] Command timed out, killing: ${$}`),J(!0),{success:!1,stdout:G,stderr:"",exitCode:null,error:"Command timed out"};case"aborted":return v0.debug(`[AcpTerminal] Command aborted, killing: ${$}`),J(!0),{success:!1,stdout:G,stderr:"",exitCode:null,error:"Command was aborted"}}}catch(Z){return v0.warn("[AcpTerminal] ACP terminal failed, using fallback:",Z),this.fallback.execute($,Y)}}isAvailable(){return!0}}function M3(){return l.getInstance().getTerminalService()}function Y2(){return l.getInstance().isAcpMode()}var v0,l;var s2=R(()=>{N1();o2();V3();v0=u("Agent");l=class l{static sessions=new Map;static currentSessionId=null;constructor(){}static getInstance(){return new l}static initializeSession($,Y,Z,X){let Q=Z?.fs?new Z8($,Y,Z.fs):new $2;if(Z?.fs)v0.debug(`[AcpServiceContext:${Y}] Using ACP file system service`);let J=new D3($,Y);v0.debug(`[AcpServiceContext:${Y}] Using ACP terminal service`),l.sessions.set(Y,{fileSystemService:Q,terminalService:J,connection:$,clientCapabilities:Z||null,cwd:X}),l.currentSessionId=Y,k6(Q),v0.debug(`[AcpServiceContext:${Y}] Initialized with capabilities:`,{fs:!!Z?.fs,readTextFile:Z?.fs?.readTextFile,writeTextFile:Z?.fs?.writeTextFile,cwd:X})}static destroySession($){if(l.sessions.delete($),l.currentSessionId===$){let Y=Array.from(l.sessions.keys());if(l.currentSessionId=Y[0]||null,!l.currentSessionId)b3();else{let Z=l.sessions.get(l.currentSessionId);if(Z)k6(Z.fileSystemService)}}v0.debug(`[AcpServiceContext:${$}] Session destroyed`)}static getSessionServices($){return l.sessions.get($)||null}static setCurrentSession($){if(l.sessions.has($)){l.currentSessionId=$;let Y=l.sessions.get($);if(Y)k6(Y.fileSystemService)}}static getCurrentSessionId(){return l.currentSessionId}initialize($,Y,Z,X){l.initializeSession($,Y,Z,X||process.cwd())}reset(){if(l.currentSessionId)l.destroySession(l.currentSessionId)}isAcpMode(){return l.currentSessionId!==null}getFileSystemService(){if(l.currentSessionId){let $=l.sessions.get(l.currentSessionId);if($)return $.fileSystemService}return new $2}getTerminalService(){if(l.currentSessionId){let $=l.sessions.get(l.currentSessionId);if($)return $.terminalService}return new X8}getConnection(){if(l.currentSessionId){let $=l.sessions.get(l.currentSessionId);if($)return $.connection}return null}getSessionId(){return l.currentSessionId}getClientCapabilities(){if(l.currentSessionId){let $=l.sessions.get(l.currentSessionId);if($)return $.clientCapabilities}return null}async sendToolUpdate($,Y,Z,X,Q){let J=l.currentSessionId;if(!J)return;let q=l.sessions.get(J);if(!q)return;try{await q.connection.sessionUpdate({sessionId:J,update:{sessionUpdate:"tool_call",toolCallId:$,status:Y,title:Z,content:X||[],kind:Q||"other"}})}catch(K){v0.warn("[AcpServiceContext] Failed to send tool update:",K)}}}});import{isAbsolute as I3}from"path";import{z as j1}from"zod";var H1;var Z2=R(()=>{H1={filePath:($)=>j1.string().min(1,"File path is required").refine((Y)=>I3(Y),{message:"Path must be absolute"}).describe($?.description||"Absolute file path"),encoding:()=>j1.enum(["utf8","base64","binary"]).default("utf8").describe("File encoding"),timeout:($=1000,Y=300000,Z=30000)=>j1.number().int("Must be an integer").min($,`Cannot be less than ${$}ms`).max(Y,`Cannot exceed ${Y}ms`).default(Z).describe(`Timeout in milliseconds (default ${Z}ms)`),pattern:($)=>j1.string().min(1,"Pattern is required").describe($?.description||"Regex or glob pattern"),glob:($)=>j1.string().min(1,"Glob pattern is required").describe($?.description||'Glob pattern (e.g., "*.js", "**/*.ts")'),lineNumber:($)=>j1.number().int("Line number must be an integer").min($?.min??0,`Line number cannot be less than ${$?.min??0}`).describe($?.description||"Line number"),lineLimit:($)=>j1.number().int("Line count must be an integer").min($?.min??1,`Line count cannot be less than ${$?.min??1}`).max($?.max??1e4,`Line count cannot exceed ${$?.max??1e4}`).describe($?.description||"Limit on lines to read"),workingDirectory:()=>j1.string().min(1,"Working directory is required").refine(($)=>I3($),{message:"Path must be absolute"}).describe("Absolute working directory"),environment:()=>j1.record(j1.string(),j1.string()).describe("Environment variables (key-value)").optional(),outputMode:($,Y)=>{let Z=j1.enum($);return Y?Z.default(Y):Z},flag:($)=>j1.boolean().default($?.defaultValue??!1).describe($?.description||"Boolean flag"),url:($)=>j1.string().url("Must be a valid URL").describe($?.description||"URL"),port:()=>j1.number().int("Port must be an integer").min(1,"Port cannot be less than 1").max(65535,"Port cannot exceed 65535").describe("Port number"),command:($)=>j1.string().min(1,"Command is required").describe($?.description||"Command to execute"),sessionId:()=>j1.string().min(1,"Session ID is required").uuid("Must be a valid UUID").optional().describe("Session identifier (UUID)"),nonNegativeInt:($)=>j1.number().int("Must be an integer").min(0,"Cannot be negative").describe($?.description||"Non-negative integer"),positiveInt:($)=>j1.number().int("Must be an integer").min(1,"Must be greater than 0").describe($?.description||"Positive integer")}});import*as Q8 from"diff";function k3($,Y,Z=4){if($===Y)return null;let X=Q8.createPatch("file",$,Y,"","",{context:Z}),Q=X.split(`
391
- `),J=1;for(let q of Q){let K=q.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);if(K){J=parseInt(K[1],10);break}}return`
401
+ [... and ${Y.length-Z} more files matched]`:"";return{type:"file",path:$,content:G+K,metadata:{lines:J.reduce((W,U)=>W+U.lines,0),truncated:Y.length>Z||J.some((W)=>W.truncated)}}}clearExpiredCache(){let $=Date.now(),Y=0;for(let[Z,X]of this.fileCache.entries())if($-X.timestamp>60000)this.fileCache.delete(Z),Y++;if(Y>0)L0.debug(`Cleared ${Y} expired cache entries`)}clearCache(){this.fileCache.clear(),L0.debug("Cleared all cache")}getCacheStats(){return{size:this.fileCache.size,keys:Array.from(this.fileCache.keys())}}}var L0;var y3=D(()=>{B1();k3();j3();L0=l("Prompts")});import*as A0 from"fs/promises";class X2{async readTextFile($){return A0.readFile($,"utf-8")}async writeTextFile($,Y){await A0.writeFile($,Y,"utf-8")}async exists($){try{return await A0.access($),!0}catch{return!1}}async readBinaryFile($){return A0.readFile($)}async stat($){try{let Y=await A0.stat($);return{size:Y.size,isDirectory:Y.isDirectory(),isFile:Y.isFile(),mtime:Y.mtime}}catch{return null}}async mkdir($,Y){await A0.mkdir($,{recursive:Y?.recursive??!1})}}function s2(){return G8}function T6($){G8=$}function P3(){G8=new X2}var G8;var t2=D(()=>{G8=new X2});class K8{connection;sessionId;capabilities;fallback;constructor($,Y,Z,X=new X2){this.connection=$;this.sessionId=Y;this.capabilities=Z;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(Y){return $0.warn(`[AcpFileSystem] readTextFile ACP failed, fallback: ${Y}`),this.fallback.readTextFile($)}}async writeTextFile($,Y){if(!this.capabilities.writeTextFile)return $0.debug(`[AcpFileSystem] writeTextFile fallback: ${$}`),this.fallback.writeTextFile($,Y);try{$0.debug(`[AcpFileSystem] writeTextFile via ACP: ${$}`),await this.connection.writeTextFile({path:$,content:Y,sessionId:this.sessionId})}catch(Z){return $0.warn(`[AcpFileSystem] writeTextFile ACP failed, fallback: ${Z}`),this.fallback.writeTextFile($,Y)}}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(Y){let Z=String(Y).toLowerCase();if(["not found","no such file","enoent","does not exist","file not found","path not found"].some((q)=>Z.includes(q)))return $0.debug(`[AcpFileSystem] exists(${$}): false (ACP: not found)`),!1;let J=kJ(Z);return $0.warn(`[AcpFileSystem] exists(${$}): assuming exists due to ${J} error`,{error:String(Y),errorType:J,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($,Y){return $0.debug(`[AcpFileSystem] mkdir fallback: ${$}`),this.fallback.mkdir($,Y)}getCapabilities(){return this.capabilities}canReadTextFile(){return this.capabilities.readTextFile??!1}canWriteTextFile(){return this.capabilities.writeTextFile??!1}}function kJ($){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 $0;var T3=D(()=>{B1();t2();$0=l("Agent")});import{spawn as jJ}from"child_process";class W8{async execute($,Y){return new Promise((Z)=>{let X=process.platform==="win32"?"cmd.exe":"/bin/bash",Q=process.platform==="win32"?["/c",$]:["-c",$],J=jJ(X,Q,{cwd:Y?.cwd||process.cwd(),env:{...process.env,...Y?.env},stdio:["pipe","pipe","pipe"]}),q="",G="",K=!1,W=Y?.timeout?setTimeout(()=>{K=!0,J.kill("SIGTERM")},Y.timeout):null;if(Y?.signal)Y.signal.addEventListener("abort",()=>{K=!0,J.kill("SIGTERM")});J.stdout.on("data",(U)=>{let H=U.toString();q+=H,Y?.onOutput?.(H)}),J.stderr.on("data",(U)=>{let H=U.toString();G+=H,Y?.onOutput?.(H)}),J.on("close",(U)=>{if(W)clearTimeout(W);Z({success:U===0&&!K,stdout:q,stderr:G,exitCode:U,error:K?"Command was terminated":void 0})}),J.on("error",(U)=>{if(W)clearTimeout(W);Z({success:!1,stdout:q,stderr:G,exitCode:null,error:U.message})})})}isAvailable(){return!0}}class S3{connection;sessionId;fallback;constructor($,Y,Z=new W8){this.connection=$;this.sessionId=Y;this.fallback=Z}async execute($,Y){try{P0.debug(`[AcpTerminal] Executing command via ACP: ${$}`);let Z=await this.connection.createTerminal({sessionId:this.sessionId,command:$,cwd:Y?.cwd,env:Y?.env?Object.entries(Y.env).map(([W,U])=>({name:W,value:U})):void 0}),X=0,Q=null;if(Y?.onOutput)Q=setInterval(async()=>{try{let U=(await Z.currentOutput()).output||"";if(U.length>X){let H=U.slice(X);X=U.length,Y.onOutput?.(H)}}catch{}},100);let J=(W=!1)=>{if(Q)clearInterval(Q),Q=null;(W?Z.kill().then(()=>P0.debug("[AcpTerminal] Killed remote command")).catch(()=>{}).then(()=>Z.release()).catch(()=>{}):Z.release().catch(()=>{})).catch(()=>{})},q=[];if(q.push(Z.waitForExit().then((W)=>({type:"completed",exitCode:W.exitCode??null}))),Y?.timeout)q.push(new Promise((W)=>{setTimeout(()=>W({type:"timeout"}),Y.timeout)}));if(Y?.signal)q.push(new Promise((W)=>{if(Y.signal.aborted)W({type:"aborted"});else Y.signal.addEventListener("abort",()=>W({type:"aborted"}),{once:!0})}));let G=await Promise.race(q),K="";try{if(K=(await Z.currentOutput()).output||"",Y?.onOutput&&K.length>X)Y.onOutput(K.slice(X))}catch{}switch(G.type){case"completed":return J(!1),{success:G.exitCode===0,stdout:K,stderr:"",exitCode:G.exitCode};case"timeout":return P0.debug(`[AcpTerminal] Command timed out, killing: ${$}`),J(!0),{success:!1,stdout:K,stderr:"",exitCode:null,error:"Command timed out"};case"aborted":return P0.debug(`[AcpTerminal] Command aborted, killing: ${$}`),J(!0),{success:!1,stdout:K,stderr:"",exitCode:null,error:"Command was aborted"}}}catch(Z){return P0.warn("[AcpTerminal] ACP terminal failed, using fallback:",Z),this.fallback.execute($,Y)}}isAvailable(){return!0}}function C3(){return a.getInstance().getTerminalService()}function Q2(){return a.getInstance().isAcpMode()}var P0,a;var e2=D(()=>{B1();t2();T3();P0=l("Agent");a=class a{static sessions=new Map;static currentSessionId=null;constructor(){}static getInstance(){return new a}static initializeSession($,Y,Z,X){let Q=Z?.fs?new K8($,Y,Z.fs):new X2;if(Z?.fs)P0.debug(`[AcpServiceContext:${Y}] Using ACP file system service`);let J=new S3($,Y);P0.debug(`[AcpServiceContext:${Y}] Using ACP terminal service`),a.sessions.set(Y,{fileSystemService:Q,terminalService:J,connection:$,clientCapabilities:Z||null,cwd:X}),a.currentSessionId=Y,T6(Q),P0.debug(`[AcpServiceContext:${Y}] Initialized with capabilities:`,{fs:!!Z?.fs,readTextFile:Z?.fs?.readTextFile,writeTextFile:Z?.fs?.writeTextFile,cwd:X})}static destroySession($){if(a.sessions.delete($),a.currentSessionId===$){let Y=Array.from(a.sessions.keys());if(a.currentSessionId=Y[0]||null,!a.currentSessionId)P3();else{let Z=a.sessions.get(a.currentSessionId);if(Z)T6(Z.fileSystemService)}}P0.debug(`[AcpServiceContext:${$}] Session destroyed`)}static getSessionServices($){return a.sessions.get($)||null}static setCurrentSession($){if(a.sessions.has($)){a.currentSessionId=$;let Y=a.sessions.get($);if(Y)T6(Y.fileSystemService)}}static getCurrentSessionId(){return a.currentSessionId}initialize($,Y,Z,X){a.initializeSession($,Y,Z,X||process.cwd())}reset(){if(a.currentSessionId)a.destroySession(a.currentSessionId)}isAcpMode(){return a.currentSessionId!==null}getFileSystemService(){if(a.currentSessionId){let $=a.sessions.get(a.currentSessionId);if($)return $.fileSystemService}return new X2}getTerminalService(){if(a.currentSessionId){let $=a.sessions.get(a.currentSessionId);if($)return $.terminalService}return new W8}getConnection(){if(a.currentSessionId){let $=a.sessions.get(a.currentSessionId);if($)return $.connection}return null}getSessionId(){return a.currentSessionId}getClientCapabilities(){if(a.currentSessionId){let $=a.sessions.get(a.currentSessionId);if($)return $.clientCapabilities}return null}async sendToolUpdate($,Y,Z,X,Q){let J=a.currentSessionId;if(!J)return;let q=a.sessions.get(J);if(!q)return;try{await q.connection.sessionUpdate({sessionId:J,update:{sessionUpdate:"tool_call",toolCallId:$,status:Y,title:Z,content:X||[],kind:Q||"other"}})}catch(G){P0.warn("[AcpServiceContext] Failed to send tool update:",G)}}}});import{isAbsolute as f3}from"path";import{z as E1}from"zod";var O1;var J2=D(()=>{O1={filePath:($)=>E1.string().min(1,"File path is required").refine((Y)=>f3(Y),{message:"Path must be absolute"}).describe($?.description||"Absolute file path"),encoding:()=>E1.enum(["utf8","base64","binary"]).default("utf8").describe("File encoding"),timeout:($=1000,Y=300000,Z=30000)=>E1.number().int("Must be an integer").min($,`Cannot be less than ${$}ms`).max(Y,`Cannot exceed ${Y}ms`).default(Z).describe(`Timeout in milliseconds (default ${Z}ms)`),pattern:($)=>E1.string().min(1,"Pattern is required").describe($?.description||"Regex or glob pattern"),glob:($)=>E1.string().min(1,"Glob pattern is required").describe($?.description||'Glob pattern (e.g., "*.js", "**/*.ts")'),lineNumber:($)=>E1.number().int("Line number must be an integer").min($?.min??0,`Line number cannot be less than ${$?.min??0}`).describe($?.description||"Line number"),lineLimit:($)=>E1.number().int("Line count must be an integer").min($?.min??1,`Line count cannot be less than ${$?.min??1}`).max($?.max??1e4,`Line count cannot exceed ${$?.max??1e4}`).describe($?.description||"Limit on lines to read"),workingDirectory:()=>E1.string().min(1,"Working directory is required").refine(($)=>f3($),{message:"Path must be absolute"}).describe("Absolute working directory"),environment:()=>E1.record(E1.string(),E1.string()).describe("Environment variables (key-value)").optional(),outputMode:($,Y)=>{let Z=E1.enum($);return Y?Z.default(Y):Z},flag:($)=>E1.boolean().default($?.defaultValue??!1).describe($?.description||"Boolean flag"),url:($)=>E1.string().url("Must be a valid URL").describe($?.description||"URL"),port:()=>E1.number().int("Port must be an integer").min(1,"Port cannot be less than 1").max(65535,"Port cannot exceed 65535").describe("Port number"),command:($)=>E1.string().min(1,"Command is required").describe($?.description||"Command to execute"),sessionId:()=>E1.string().min(1,"Session ID is required").uuid("Must be a valid UUID").optional().describe("Session identifier (UUID)"),nonNegativeInt:($)=>E1.number().int("Must be an integer").min(0,"Cannot be negative").describe($?.description||"Non-negative integer"),positiveInt:($)=>E1.number().int("Must be an integer").min(1,"Must be greater than 0").describe($?.description||"Positive integer")}});import*as U8 from"diff";function h3($,Y,Z=4){if($===Y)return null;let X=U8.createPatch("file",$,Y,"","",{context:Z}),Q=X.split(`
402
+ `),J=1;for(let q of Q){let G=q.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);if(G){J=parseInt(G[1],10);break}}return`
392
403
  <<<DIFF>>>
393
404
  ${JSON.stringify({patch:X,startLine:Math.max(1,J-Z),matchLine:J})}
394
405
  <<</DIFF>>>
395
- `}function j3($,Y,Z,X,Q=4){let J=$.indexOf(Z);if(J===-1)return null;let K=$.substring(0,J).split(`
396
- `).length-1,G=$.split(`
406
+ `}function x3($,Y,Z,X,Q=4){let J=$.indexOf(Z);if(J===-1)return null;let G=$.substring(0,J).split(`
407
+ `).length-1,K=$.split(`
397
408
  `),W=Y.split(`
398
409
  `),U=Z.split(`
399
410
  `),H=X.split(`
400
- `),O=Math.max(0,K-Q),z=Math.min(G.length,K+U.length+Q),_=Math.min(W.length,K+H.length+Q),F=G.slice(O,z).join(`
401
- `),N=W.slice(O,_).join(`
402
- `),w=Q8.createPatch("file",F,N,"","",{context:Q});return`
411
+ `),O=Math.max(0,G-Q),F=Math.min(K.length,G+U.length+Q),_=Math.min(W.length,G+H.length+Q),z=K.slice(O,F).join(`
412
+ `),w=W.slice(O,_).join(`
413
+ `),B=U8.createPatch("file",z,w,"","",{context:Q});return`
403
414
  <<<DIFF>>>
404
- ${JSON.stringify({patch:w,startLine:O+1,matchLine:K+1})}
415
+ ${JSON.stringify({patch:B,startLine:O+1,matchLine:G+1})}
405
416
  <<</DIFF>>>
406
- `}var J8=()=>{};function E3($){return $.replace(/\\+(n|t|r|'|"|`|\\|\n)/g,(Y,Z)=>{switch(Z){case"n":return`
417
+ `}var H8=()=>{};function p3($){return $.replace(/\\+(n|t|r|'|"|`|\\|\n)/g,(Y,Z)=>{switch(Z){case"n":return`
407
418
  `;case"t":return"\t";case"r":return"\r";case"'":return"'";case'"':return'"';case"`":return"`";case"\\":return"\\";case`
408
419
  `:return`
409
- `;default:return Y}})}function y3($,Y){let Z=Y.split(`
410
- `);if(Z.length===1)return null;let Q=Z[0].match(/^(\s+)/);if(!Q)return null;let J=Q[1],K=Z.map((W)=>{if(W.startsWith(J))return W.slice(J.length);return W}).join(`
411
- `),G=$.split(`
412
- `);for(let W=0;W<=G.length-Z.length;W++){let U=G[W].match(/^(\s+)/),H=U?U[1]:"",O=G.slice(W,W+Z.length);if(O.map((F)=>{if(F.startsWith(H))return F.slice(H.length);return F}).join(`
413
- `)===K)return O.join(`
414
- `)}return null}var v3=()=>{};import{promises as j6}from"node:fs";class l1{static instance=null;accessedFiles=new Map;constructor(){}static getInstance(){if(!l1.instance)l1.instance=new l1;return l1.instance}async recordFileRead($,Y){try{let Z=await j6.stat($),X={filePath:$,accessTime:Date.now(),mtime:Z.mtimeMs,sessionId:Y,lastOperation:"read"};this.accessedFiles.set($,X),x$.debug(`记录文件读取: ${$}`)}catch(Z){x$.warn(`记录文件读取失败: ${$}`,Z)}}async recordFileEdit($,Y,Z="edit"){try{let X=await j6.stat($),Q={filePath:$,accessTime:Date.now(),mtime:X.mtimeMs,sessionId:Y,lastOperation:Z};this.accessedFiles.set($,Q),x$.debug(`记录文件${Z==="edit"?"编辑":"写入"}: ${$}`)}catch(X){x$.warn(`记录文件${Z==="edit"?"编辑":"写入"}失败: ${$}`,X)}}hasFileBeenRead($,Y){let Z=this.accessedFiles.get($);if(!Z)return!1;if(Y&&Z.sessionId!==Y)return!1;return!0}async checkFileModification($){let Y=this.accessedFiles.get($);if(!Y)return{modified:!1,message:"文件未被跟踪"};try{let Z=await j6.stat($);if(Math.abs(Z.mtimeMs-Y.mtime)>1)return{modified:!0,message:`文件在访问后被修改(访问时间: ${new Date(Y.accessTime).toISOString()}, 当前修改时间: ${Z.mtime.toISOString()})`};return{modified:!1}}catch(Z){if(Z.code==="ENOENT")return{modified:!0,message:"文件已被删除"};return{modified:!1,message:`无法检查文件状态: ${Z.message}`}}}async checkExternalModification($){let Y=this.accessedFiles.get($);if(!Y)return{isExternal:!1,message:"文件未被跟踪"};try{let Z=await j6.stat($);if(Z.mtimeMs-Y.mtime>2000)return{isExternal:!0,message:`文件在 ${new Date(Y.accessTime).toISOString()} (${Y.lastOperation}) 之后被外部程序修改(当前修改时间: ${Z.mtime.toISOString()})`};return{isExternal:!1}}catch(Z){if(Z.code==="ENOENT")return{isExternal:!0,message:"文件已被删除"};return x$.warn(`检查文件外部修改失败: ${$}`,Z),{isExternal:!1,message:`无法检查文件状态: ${Z.message}`}}}getFileRecord($){return this.accessedFiles.get($)}clearFileRecord($){this.accessedFiles.delete($)}clearAll(){this.accessedFiles.clear()}clearSession($){for(let[Y,Z]of this.accessedFiles.entries())if(Z.sessionId===$)this.accessedFiles.delete(Y)}getTrackedFiles(){return Array.from(this.accessedFiles.keys())}getTrackedFileCount(){return this.accessedFiles.size}static resetInstance(){l1.instance=null}}var x$;var E6=R(()=>{N1();x$=u("Tool")});var T3={};W7(T3,{unescapeProjectPath:()=>K8,listProjectDirectories:()=>G8,getSessionFilePath:()=>R0,getProjectStoragePath:()=>t2,getBladeStorageRoot:()=>X2,escapeProjectPath:()=>P3,detectGitBranch:()=>V2});import{execSync as _J}from"node:child_process";import*as q8 from"node:os";import*as b2 from"node:path";function P3($){return b2.resolve($).replace(/\//g,"-")}function K8($){if($.startsWith("-"))return"/"+$.slice(1).replace(/-/g,"/");return $.replace(/-/g,"/")}function t2($){let Y=q8.homedir(),Z=P3($);return b2.join(Y,".blade","projects",Z)}function R0($,Y){return b2.join(t2($),`${Y}.jsonl`)}function V2($){try{return _J("git rev-parse --abbrev-ref HEAD",{cwd:$,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{return}}function X2(){return b2.join(q8.homedir(),".blade")}async function G8(){let{readdir:$}=await import("node:fs/promises");try{let Y=b2.join(X2(),"projects");return(await $(Y,{withFileTypes:!0})).filter((X)=>X.isDirectory()).map((X)=>X.name)}catch{return[]}}var e2=()=>{};import*as S3 from"node:crypto";import{promises as P0}from"node:fs";import*as D2 from"node:path";class p${sessionId;enableCheckpoints;maxSnapshots;snapshotDir;trackedFileBackups=new Map;snapshots=[];constructor($){this.sessionId=$.sessionId,this.enableCheckpoints=$.enableCheckpoints??!0,this.maxSnapshots=$.maxSnapshots??10;let Y=X2();this.snapshotDir=D2.join(Y,"file-history",this.sessionId)}async initialize(){if(!this.enableCheckpoints)return;try{await P0.mkdir(this.snapshotDir,{recursive:!0}),console.log(`[SnapshotManager] 初始化快照目录: ${this.snapshotDir}`)}catch($){throw console.warn("[SnapshotManager] 创建快照目录失败:",$),$}}async createSnapshot($,Y){if(!this.enableCheckpoints)return console.log("[SnapshotManager] 检查点已禁用,跳过快照创建"),{backupFileName:"",version:0,backupTime:new Date};try{await P0.access($)}catch{return console.warn(`[SnapshotManager] 文件不存在,跳过快照: ${$}`),{backupFileName:"",version:0,backupTime:new Date}}let Z=this.trackedFileBackups.get($),X=Z?Z.version+1:1,Q=this.generateFileHash($,X),J=D2.join(this.snapshotDir,`${Q}@v${X}`);try{let q=await P0.readFile($,{encoding:"utf-8"});await P0.writeFile(J,q,{encoding:"utf-8"});let K={backupFileName:Q,version:X,backupTime:new Date};return this.trackedFileBackups.set($,K),this.snapshots.push({messageId:Y,backupFileName:Q,timestamp:new Date,filePath:$}),console.log(`[SnapshotManager] 创建快照: ${$} -> ${Q}@v${X}`),await this.cleanupOldSnapshots($),K}catch(q){throw console.error(`[SnapshotManager] 创建快照失败: ${$}`,q),q}}async restoreSnapshot($,Y){let Z=this.snapshots.slice().reverse().find((J)=>J.messageId===Y&&J.filePath===$);if(!Z)throw Error(`未找到快照: messageId=${Y}, filePath=${$}`);let X=this.trackedFileBackups.get($);if(!X)throw Error(`未找到文件追踪信息: ${$}`);let Q=D2.join(this.snapshotDir,`${Z.backupFileName}@v${X.version}`);try{let J=await P0.readFile(Q,{encoding:"utf-8"});await P0.writeFile($,J,{encoding:"utf-8"}),console.log(`[SnapshotManager] 恢复快照: ${$} <- ${Z.backupFileName}@v${X.version}`)}catch(J){throw console.error(`[SnapshotManager] 恢复快照失败: ${$}`,J),J}}async listSnapshots($){return this.snapshots.filter((Y)=>Y.filePath===$)}async cleanupOldSnapshots($){let Y=this.snapshots.filter((Q)=>Q.filePath===$);if(Y.length<=this.maxSnapshots)return;let X=Y.sort((Q,J)=>Q.timestamp.getTime()-J.timestamp.getTime()).slice(0,Y.length-this.maxSnapshots);for(let Q of X){let J=this.trackedFileBackups.get(Q.filePath);if(!J)continue;let q=D2.join(this.snapshotDir,`${Q.backupFileName}@v${J.version}`);try{await P0.unlink(q),console.log(`[SnapshotManager] 删除旧快照: ${q}`)}catch(G){console.warn(`[SnapshotManager] 删除快照失败: ${q}`,G)}let K=this.snapshots.indexOf(Q);if(K>-1)this.snapshots.splice(K,1)}}async cleanup($=0){try{let Y=await P0.readdir(this.snapshotDir);if(Y.length<=$)return;let Z=await Promise.all(Y.map(async(Q)=>{let J=D2.join(this.snapshotDir,Q),q=await P0.stat(J);return{file:Q,mtime:q.mtime.getTime()}}));Z.sort((Q,J)=>J.mtime-Q.mtime);let X=Z.slice($);for(let{file:Q}of X){let J=D2.join(this.snapshotDir,Q);await P0.unlink(J),console.log(`[SnapshotManager] 清理快照: ${J}`)}}catch(Y){console.warn("[SnapshotManager] 清理快照失败:",Y)}}generateFileHash($,Y){let Z=S3.createHash("md5");return Z.update(`${$}:${Y}`),Z.digest("hex").substring(0,16)}getSnapshotDir(){return this.snapshotDir}getSessionId(){return this.sessionId}getTrackedFileCount(){return this.trackedFileBackups.size}getSnapshotCount(){return this.snapshots.length}}var W8=R(()=>{e2()});import{extname as BJ}from"path";import{z as y6}from"zod";function C3($){return $.replaceAll("‘","'").replaceAll("’","'").replaceAll("“",'"').replaceAll("”",'"')}function NJ($,Y){if($.includes(Y))return{matched:Y,strategy:"exact"};let Z=C3(Y),Q=C3($).indexOf(Z);if(Q!==-1)return{matched:$.substring(Q,Q+Y.length),strategy:"normalize_quotes"};let J=E3(Y);if(J!==Y&&$.includes(J))return{matched:J,strategy:"unescape"};let q=y3($,Y);if(q)return{matched:q,strategy:"flexible"};return{matched:null,strategy:"failed"}}function wJ($,Y){if(Y.length===0)return[];let Z=[],X=$.indexOf(Y);while(X!==-1)Z.push(X),X=$.indexOf(Y,X+Y.length);return Z}function LJ($,Y){let{file_path:Z,matches_found:X,replacements_made:Q,replace_all:J,size_diff:q}=$,K=`✅ 成功编辑文件: ${Z}`;if(K+=`
415
- \uD83D\uDCDD 替换了 ${Q} 个匹配项`,!J&&X>1)K+=` (共找到 ${X} 个匹配项)`;if(q!==0){let G=q>0?`增加${q}`:`减少${Math.abs(q)}`;K+=`
416
- \uD83D\uDCCA 文件大小${G}个字符`}if(Y)K+=Y;return K}function AJ($,Y,Z){let X=$.split(`
417
- `),Q=X.length,J=RJ($,Y,3),q=0,K=Math.min(20,Q);if(J.length>0){let z=J[0];q=Math.max(0,z.lineNumber-10),K=Math.min(Q,z.lineNumber+10)}let W=X.slice(q,K).map((z,_)=>{return` ${(q+_+1).toString().padStart(4)}: ${z}`}).join(`
420
+ `;default:return Y}})}function g3($,Y){let Z=Y.split(`
421
+ `);if(Z.length===1)return null;let Q=Z[0].match(/^(\s+)/);if(!Q)return null;let J=Q[1],G=Z.map((W)=>{if(W.startsWith(J))return W.slice(J.length);return W}).join(`
422
+ `),K=$.split(`
423
+ `);for(let W=0;W<=K.length-Z.length;W++){let U=K[W].match(/^(\s+)/),H=U?U[1]:"",O=K.slice(W,W+Z.length);if(O.map((z)=>{if(z.startsWith(H))return z.slice(H.length);return z}).join(`
424
+ `)===G)return O.join(`
425
+ `)}return null}var m3=()=>{};import{promises as S6}from"node:fs";class i1{static instance=null;accessedFiles=new Map;constructor(){}static getInstance(){if(!i1.instance)i1.instance=new i1;return i1.instance}async recordFileRead($,Y){try{let Z=await S6.stat($),X={filePath:$,accessTime:Date.now(),mtime:Z.mtimeMs,sessionId:Y,lastOperation:"read"};this.accessedFiles.set($,X),u$.debug(`记录文件读取: ${$}`)}catch(Z){u$.warn(`记录文件读取失败: ${$}`,Z)}}async recordFileEdit($,Y,Z="edit"){try{let X=await S6.stat($),Q={filePath:$,accessTime:Date.now(),mtime:X.mtimeMs,sessionId:Y,lastOperation:Z};this.accessedFiles.set($,Q),u$.debug(`记录文件${Z==="edit"?"编辑":"写入"}: ${$}`)}catch(X){u$.warn(`记录文件${Z==="edit"?"编辑":"写入"}失败: ${$}`,X)}}hasFileBeenRead($,Y){let Z=this.accessedFiles.get($);if(!Z)return!1;if(Y&&Z.sessionId!==Y)return!1;return!0}async checkFileModification($){let Y=this.accessedFiles.get($);if(!Y)return{modified:!1,message:"文件未被跟踪"};try{let Z=await S6.stat($);if(Math.abs(Z.mtimeMs-Y.mtime)>1)return{modified:!0,message:`文件在访问后被修改(访问时间: ${new Date(Y.accessTime).toISOString()}, 当前修改时间: ${Z.mtime.toISOString()})`};return{modified:!1}}catch(Z){if(Z.code==="ENOENT")return{modified:!0,message:"文件已被删除"};return{modified:!1,message:`无法检查文件状态: ${Z.message}`}}}async checkExternalModification($){let Y=this.accessedFiles.get($);if(!Y)return{isExternal:!1,message:"文件未被跟踪"};try{let Z=await S6.stat($);if(Z.mtimeMs-Y.mtime>2000)return{isExternal:!0,message:`文件在 ${new Date(Y.accessTime).toISOString()} (${Y.lastOperation}) 之后被外部程序修改(当前修改时间: ${Z.mtime.toISOString()})`};return{isExternal:!1}}catch(Z){if(Z.code==="ENOENT")return{isExternal:!0,message:"文件已被删除"};return u$.warn(`检查文件外部修改失败: ${$}`,Z),{isExternal:!1,message:`无法检查文件状态: ${Z.message}`}}}getFileRecord($){return this.accessedFiles.get($)}clearFileRecord($){this.accessedFiles.delete($)}clearAll(){this.accessedFiles.clear()}clearSession($){for(let[Y,Z]of this.accessedFiles.entries())if(Z.sessionId===$)this.accessedFiles.delete(Y)}getTrackedFiles(){return Array.from(this.accessedFiles.keys())}getTrackedFileCount(){return this.accessedFiles.size}static resetInstance(){i1.instance=null}}var u$;var C6=D(()=>{B1();u$=l("Tool")});var u3={};L7(u3,{unescapeProjectPath:()=>F8,listProjectDirectories:()=>z8,getSessionFilePath:()=>b0,getProjectStoragePath:()=>$$,getBladeStorageRoot:()=>q2,escapeProjectPath:()=>d3,detectGitBranch:()=>V2});import{execSync as EJ}from"node:child_process";import*as O8 from"node:os";import*as R2 from"node:path";function d3($){return R2.resolve($).replace(/\//g,"-")}function F8($){if($.startsWith("-"))return"/"+$.slice(1).replace(/-/g,"/");return $.replace(/-/g,"/")}function $$($){let Y=O8.homedir(),Z=d3($);return R2.join(Y,".blade","projects",Z)}function b0($,Y){return R2.join($$($),`${Y}.jsonl`)}function V2($){try{return EJ("git rev-parse --abbrev-ref HEAD",{cwd:$,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{return}}function q2(){return R2.join(O8.homedir(),".blade")}async function z8(){let{readdir:$}=await import("node:fs/promises");try{let Y=R2.join(q2(),"projects");return(await $(Y,{withFileTypes:!0})).filter((X)=>X.isDirectory()).map((X)=>X.name)}catch{return[]}}var Y$=()=>{};import*as c3 from"node:crypto";import{promises as T0}from"node:fs";import*as D2 from"node:path";class c${sessionId;enableCheckpoints;maxSnapshots;snapshotDir;trackedFileBackups=new Map;snapshots=[];constructor($){this.sessionId=$.sessionId,this.enableCheckpoints=$.enableCheckpoints??!0,this.maxSnapshots=$.maxSnapshots??10;let Y=q2();this.snapshotDir=D2.join(Y,"file-history",this.sessionId)}async initialize(){if(!this.enableCheckpoints)return;try{await T0.mkdir(this.snapshotDir,{recursive:!0}),console.log(`[SnapshotManager] 初始化快照目录: ${this.snapshotDir}`)}catch($){throw console.warn("[SnapshotManager] 创建快照目录失败:",$),$}}async createSnapshot($,Y){if(!this.enableCheckpoints)return console.log("[SnapshotManager] 检查点已禁用,跳过快照创建"),{backupFileName:"",version:0,backupTime:new Date};try{await T0.access($)}catch{return console.warn(`[SnapshotManager] 文件不存在,跳过快照: ${$}`),{backupFileName:"",version:0,backupTime:new Date}}let Z=this.trackedFileBackups.get($),X=Z?Z.version+1:1,Q=this.generateFileHash($,X),J=D2.join(this.snapshotDir,`${Q}@v${X}`);try{let q=await T0.readFile($,{encoding:"utf-8"});await T0.writeFile(J,q,{encoding:"utf-8"});let G={backupFileName:Q,version:X,backupTime:new Date};return this.trackedFileBackups.set($,G),this.snapshots.push({messageId:Y,backupFileName:Q,timestamp:new Date,filePath:$}),console.log(`[SnapshotManager] 创建快照: ${$} -> ${Q}@v${X}`),await this.cleanupOldSnapshots($),G}catch(q){throw console.error(`[SnapshotManager] 创建快照失败: ${$}`,q),q}}async restoreSnapshot($,Y){let Z=this.snapshots.slice().reverse().find((J)=>J.messageId===Y&&J.filePath===$);if(!Z)throw Error(`未找到快照: messageId=${Y}, filePath=${$}`);let X=this.trackedFileBackups.get($);if(!X)throw Error(`未找到文件追踪信息: ${$}`);let Q=D2.join(this.snapshotDir,`${Z.backupFileName}@v${X.version}`);try{let J=await T0.readFile(Q,{encoding:"utf-8"});await T0.writeFile($,J,{encoding:"utf-8"}),console.log(`[SnapshotManager] 恢复快照: ${$} <- ${Z.backupFileName}@v${X.version}`)}catch(J){throw console.error(`[SnapshotManager] 恢复快照失败: ${$}`,J),J}}async listSnapshots($){return this.snapshots.filter((Y)=>Y.filePath===$)}async cleanupOldSnapshots($){let Y=this.snapshots.filter((Q)=>Q.filePath===$);if(Y.length<=this.maxSnapshots)return;let X=Y.sort((Q,J)=>Q.timestamp.getTime()-J.timestamp.getTime()).slice(0,Y.length-this.maxSnapshots);for(let Q of X){let J=this.trackedFileBackups.get(Q.filePath);if(!J)continue;let q=D2.join(this.snapshotDir,`${Q.backupFileName}@v${J.version}`);try{await T0.unlink(q),console.log(`[SnapshotManager] 删除旧快照: ${q}`)}catch(K){console.warn(`[SnapshotManager] 删除快照失败: ${q}`,K)}let G=this.snapshots.indexOf(Q);if(G>-1)this.snapshots.splice(G,1)}}async cleanup($=0){try{let Y=await T0.readdir(this.snapshotDir);if(Y.length<=$)return;let Z=await Promise.all(Y.map(async(Q)=>{let J=D2.join(this.snapshotDir,Q),q=await T0.stat(J);return{file:Q,mtime:q.mtime.getTime()}}));Z.sort((Q,J)=>J.mtime-Q.mtime);let X=Z.slice($);for(let{file:Q}of X){let J=D2.join(this.snapshotDir,Q);await T0.unlink(J),console.log(`[SnapshotManager] 清理快照: ${J}`)}}catch(Y){console.warn("[SnapshotManager] 清理快照失败:",Y)}}generateFileHash($,Y){let Z=c3.createHash("md5");return Z.update(`${$}:${Y}`),Z.digest("hex").substring(0,16)}getSnapshotDir(){return this.snapshotDir}getSessionId(){return this.sessionId}getTrackedFileCount(){return this.trackedFileBackups.size}getSnapshotCount(){return this.snapshots.length}}var _8=D(()=>{Y$()});import{extname as vJ}from"path";import{z as f6}from"zod";function l3($){return $.replaceAll("‘","'").replaceAll("’","'").replaceAll("“",'"').replaceAll("”",'"')}function yJ($,Y){if($.includes(Y))return{matched:Y,strategy:"exact"};let Z=l3(Y),Q=l3($).indexOf(Z);if(Q!==-1)return{matched:$.substring(Q,Q+Y.length),strategy:"normalize_quotes"};let J=p3(Y);if(J!==Y&&$.includes(J))return{matched:J,strategy:"unescape"};let q=g3($,Y);if(q)return{matched:q,strategy:"flexible"};return{matched:null,strategy:"failed"}}function PJ($,Y){if(Y.length===0)return[];let Z=[],X=$.indexOf(Y);while(X!==-1)Z.push(X),X=$.indexOf(Y,X+Y.length);return Z}function TJ($,Y){let{file_path:Z,matches_found:X,replacements_made:Q,replace_all:J,size_diff:q}=$,G=`✅ 成功编辑文件: ${Z}`;if(G+=`
426
+ \uD83D\uDCDD 替换了 ${Q} 个匹配项`,!J&&X>1)G+=` (共找到 ${X} 个匹配项)`;if(q!==0){let K=q>0?`增加${q}`:`减少${Math.abs(q)}`;G+=`
427
+ \uD83D\uDCCA 文件大小${K}个字符`}if(Y)G+=Y;return G}function SJ($,Y,Z){let X=$.split(`
428
+ `),Q=X.length,J=CJ($,Y,3),q=0,G=Math.min(20,Q);if(J.length>0){let F=J[0];q=Math.max(0,F.lineNumber-10),G=Math.min(Q,F.lineNumber+10)}let W=X.slice(q,G).map((F,_)=>{return` ${(q+_+1).toString().padStart(4)}: ${F}`}).join(`
418
429
  `),U=`String not found in file.
419
430
 
420
431
  File: ${Z}
@@ -424,15 +435,15 @@ Total lines: ${Q}
424
435
  ... (truncated)`:Y;if(U+=`You tried to match:
425
436
  ${H}
426
437
 
427
- `,J.length>0)U+=`File content around possible matches (lines ${q+1}-${K}):
438
+ `,J.length>0)U+=`File content around possible matches (lines ${q+1}-${G}):
428
439
  ${W}
429
440
 
430
- `;else U+=`File content preview (lines ${q+1}-${K}):
441
+ `;else U+=`File content preview (lines ${q+1}-${G}):
431
442
  ${W}
432
443
 
433
444
  `;if(J.length>0)U+=`Possible similar matches found:
434
- `,J.forEach((z,_)=>{let F=z.text.length>100?z.text.substring(0,100)+"...":z.text;U+=` ${_+1}. Line ${z.lineNumber} (similarity: ${Math.round(z.similarity*100)}%)
435
- ${F.replace(/\n/g,"\\n")}
445
+ `,J.forEach((F,_)=>{let z=F.text.length>100?F.text.substring(0,100)+"...":F.text;U+=` ${_+1}. Line ${F.lineNumber} (similarity: ${Math.round(F.similarity*100)}%)
446
+ ${z.replace(/\n/g,"\\n")}
436
447
  `}),U+=`
437
448
  `;U+=`Recovery suggestions:
438
449
  1. Use the Read tool to verify the current file content
@@ -450,67 +461,67 @@ Common issues:
450
461
  搜索字符串长度: ${Y.length} 字符
451
462
  `;if(J.length>0)O+=`
452
463
  \uD83D\uDCA1 找到 ${J.length} 个相似匹配项:
453
- `,J.forEach((z,_)=>{O+=` ${_+1}. 第 ${z.lineNumber} 行 (相似度: ${Math.round(z.similarity*100)}%)
464
+ `,J.forEach((F,_)=>{O+=` ${_+1}. 第 ${F.lineNumber} 行 (相似度: ${Math.round(F.similarity*100)}%)
454
465
  `});else O+=`
455
466
  ⚠️ 未找到相似的匹配项
456
467
  `;return O+=`
457
- \uD83D\uDCC4 文件内容摘录 (${q+1}-${K} 行):
468
+ \uD83D\uDCC4 文件内容摘录 (${q+1}-${G} 行):
458
469
  ${W}
459
470
  `,O+=`
460
471
  \uD83D\uDD27 建议:
461
472
  `,O+=` 1. 使用 Read 工具重新读取文件
462
473
  `,O+=` 2. 检查空格、换行符、引号是否完全匹配
463
- `,O+=" 3. 提供更多上下文代码确保唯一性",{llmContent:U,displayContent:O,metadata:{searchStringLength:Y.length,fuzzyMatches:J.map((z)=>({line:z.lineNumber,similarity:z.similarity,preview:z.text.substring(0,100)})),excerptRange:[q+1,K],totalLines:Q}}}function RJ($,Y,Z=3){let X=$.split(`
474
+ `,O+=" 3. 提供更多上下文代码确保唯一性",{llmContent:U,displayContent:O,metadata:{searchStringLength:Y.length,fuzzyMatches:J.map((F)=>({line:F.lineNumber,similarity:F.similarity,preview:F.text.substring(0,100)})),excerptRange:[q+1,G],totalLines:Q}}}function CJ($,Y,Z=3){let X=$.split(`
464
475
  `),Q=Y.split(`
465
- `);if(Q.length===1)return X.map((G,W)=>({text:G,lineNumber:W+1,similarity:f3(Y.trim(),G.trim())})).filter((G)=>G.similarity>0.5).sort((G,W)=>W.similarity-G.similarity).slice(0,Z);let J=Q.length,q=[];for(let K=0;K<=X.length-J;K++){let G=X.slice(K,K+J).join(`
466
- `),W=f3(Y,G);if(W>0.5)q.push({text:G,lineNumber:K+1,similarity:W})}return q.sort((K,G)=>G.similarity-K.similarity).slice(0,Z)}function f3($,Y){let Z=(O)=>O.trim().replace(/\s+/g," ").replace(/[\u201c\u201d"]/g,'"').replace(/[\u2018\u2019']/g,"'"),X=Z($),Q=Z(Y);if(X===Q)return 1;let J=X.length,q=Q.length;if(J===0)return q===0?1:0;if(q===0)return 0;let K=200,G=X.substring(0,K),W=Q.substring(0,K),U=bJ(G,W),H=Math.max(G.length,W.length);return 1-U/H}function bJ($,Y){let Z=$.length,X=Y.length,Q=Array(Z+1).fill(null).map(()=>Array(X+1).fill(0));for(let J=0;J<=Z;J++)Q[J][0]=J;for(let J=0;J<=X;J++)Q[0][J]=J;for(let J=1;J<=Z;J++)for(let q=1;q<=X;q++){let K=$[J-1]===Y[q-1]?0:1;Q[J][q]=Math.min(Q[J-1][q]+1,Q[J][q-1]+1,Q[J-1][q-1]+K)}return Q[Z][X]}var U8;var h3=R(()=>{s2();o2();k1();h1();Z2();J8();v3();E6();W8();U8=e({name:"Edit",displayName:"File Edit",kind:"write",strict:!0,isConcurrencySafe:!1,schema:y6.object({file_path:H1.filePath({description:"Absolute path of the file to edit"}),old_string:y6.string().min(1,"old_string cannot be empty").describe("String to replace"),new_string:y6.string().describe("Replacement string (can be empty)"),replace_all:y6.boolean().default(!1).describe("Replace all matches (default: first only)")}),description:{short:"Performs exact string replacements in files",long:"Performs exact string replacements in files.",usageNotes:["You must use your Read tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file.","When editing text from Read tool output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: spaces + line number + tab. Everything after that tab is the actual file content to match. Never include any part of the line number prefix in the old_string or new_string.","ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.","Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.","The edit will FAIL if old_string is not unique in the file. Either provide a larger string with more surrounding context to make it unique or use replace_all to change every instance of old_string.","Use replace_all for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance."]},async execute($,Y){let{file_path:Z,old_string:X,new_string:Q,replace_all:J}=$,{updateOutput:q,sessionId:K,messageId:G}=Y,W=Y.signal??new AbortController().signal;try{q?.("Starting to read file...");let U=n2(),H=Y2(),O;try{if(H)q?.("通过 IDE 读取文件...");O=await U.readTextFile(Z)}catch(V){if(V.code==="ENOENT"||V.message?.includes("not found"))return{success:!1,llmContent:`File not found: ${Z}`,displayContent:`❌ 文件不存在: ${Z}`,error:{type:"execution_error",message:"文件不存在"}};throw V}if(W.throwIfAborted(),K){let V=l1.getInstance();if(!V.hasFileBeenRead(Z,K))return{success:!1,llmContent:"You must use your Read tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file.",displayContent:`❌ 编辑失败:必须先使用 Read 工具读取文件
476
+ `);if(Q.length===1)return X.map((K,W)=>({text:K,lineNumber:W+1,similarity:i3(Y.trim(),K.trim())})).filter((K)=>K.similarity>0.5).sort((K,W)=>W.similarity-K.similarity).slice(0,Z);let J=Q.length,q=[];for(let G=0;G<=X.length-J;G++){let K=X.slice(G,G+J).join(`
477
+ `),W=i3(Y,K);if(W>0.5)q.push({text:K,lineNumber:G+1,similarity:W})}return q.sort((G,K)=>K.similarity-G.similarity).slice(0,Z)}function i3($,Y){let Z=(O)=>O.trim().replace(/\s+/g," ").replace(/[\u201c\u201d"]/g,'"').replace(/[\u2018\u2019']/g,"'"),X=Z($),Q=Z(Y);if(X===Q)return 1;let J=X.length,q=Q.length;if(J===0)return q===0?1:0;if(q===0)return 0;let G=200,K=X.substring(0,G),W=Q.substring(0,G),U=fJ(K,W),H=Math.max(K.length,W.length);return 1-U/H}function fJ($,Y){let Z=$.length,X=Y.length,Q=Array(Z+1).fill(null).map(()=>Array(X+1).fill(0));for(let J=0;J<=Z;J++)Q[J][0]=J;for(let J=0;J<=X;J++)Q[0][J]=J;for(let J=1;J<=Z;J++)for(let q=1;q<=X;q++){let G=$[J-1]===Y[q-1]?0:1;Q[J][q]=Math.min(Q[J-1][q]+1,Q[J][q-1]+1,Q[J-1][q-1]+G)}return Q[Z][X]}var N8;var r3=D(()=>{e2();t2();j1();p1();J2();H8();m3();C6();_8();N8=Y1({name:"Edit",displayName:"File Edit",kind:"write",strict:!0,isConcurrencySafe:!1,schema:f6.object({file_path:O1.filePath({description:"Absolute path of the file to edit"}),old_string:f6.string().min(1,"old_string cannot be empty").describe("String to replace"),new_string:f6.string().describe("Replacement string (can be empty)"),replace_all:f6.boolean().default(!1).describe("Replace all matches (default: first only)")}),description:{short:"Performs exact string replacements in files",long:"Performs exact string replacements in files.",usageNotes:["You must use your Read tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file.","When editing text from Read tool output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: spaces + line number + tab. Everything after that tab is the actual file content to match. Never include any part of the line number prefix in the old_string or new_string.","ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.","Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.","The edit will FAIL if old_string is not unique in the file. Either provide a larger string with more surrounding context to make it unique or use replace_all to change every instance of old_string.","Use replace_all for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance."]},async execute($,Y){let{file_path:Z,old_string:X,new_string:Q,replace_all:J}=$,{updateOutput:q,sessionId:G,messageId:K}=Y,W=Y.signal??new AbortController().signal;try{q?.("Starting to read file...");let U=s2(),H=Q2(),O;try{if(H)q?.("通过 IDE 读取文件...");O=await U.readTextFile(Z)}catch(k){if(k.code==="ENOENT"||k.message?.includes("not found"))return{success:!1,llmContent:`File not found: ${Z}`,displayContent:`❌ 文件不存在: ${Z}`,error:{type:"execution_error",message:"文件不存在"}};throw k}if(W.throwIfAborted(),G){let k=i1.getInstance();if(!k.hasFileBeenRead(Z,G))return{success:!1,llmContent:"You must use your Read tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file.",displayContent:`❌ 编辑失败:必须先使用 Read 工具读取文件
467
478
 
468
- 请先用 Read 工具查看文件内容,再进行编辑。`,error:{type:"validation_error",message:"File not read before edit"}};let j=await V.checkExternalModification(Z);if(j.isExternal)return{success:!1,llmContent:`The file has been modified by an external program since you last read it. You must use the Read tool again to see the current content before editing.
479
+ 请先用 Read 工具查看文件内容,再进行编辑。`,error:{type:"validation_error",message:"File not read before edit"}};let I=await k.checkExternalModification(Z);if(I.isExternal)return{success:!1,llmContent:`The file has been modified by an external program since you last read it. You must use the Read tool again to see the current content before editing.
469
480
 
470
- Details: ${j.message}`,displayContent:`❌ 编辑失败:文件已被外部程序修改
481
+ Details: ${I.message}`,displayContent:`❌ 编辑失败:文件已被外部程序修改
471
482
 
472
- ${j.message}
483
+ ${I.message}
473
484
 
474
- \uD83D\uDCA1 请重新使用 Read 工具读取最新内容后再编辑`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:j.message}}}}if(K&&G)try{let V=new p$({sessionId:K});await V.initialize(),await V.createSnapshot(Z,G)}catch(V){console.warn("[EditTool] 创建快照失败:",V)}if(X===Q)return{success:!1,llmContent:"New string is identical; no replacement needed",displayContent:"⚠️ 新字符串与旧字符串相同,无需进行替换",error:{type:"validation_error",message:"新旧字符串相同"}};let z=NJ(O,X);if(!z.matched){let V=AJ(O,X,Z);return{success:!1,llmContent:V.llmContent,displayContent:V.displayContent,error:{type:"execution_error",message:"未找到匹配内容",details:V.metadata}}}let _=z.matched;if(z.strategy!=="exact")console.log(`[SmartEdit] 使用策略: ${z.strategy}`);let F=wJ(O,_);if(F.length>1&&!J){let V=O.split(`
475
- `),j=0,m=[];for(let Z1=0;Z1<V.length;Z1++){let X1=V[Z1],n1=j,z1=j+X1.length;for(let d of F)if(d>=n1&&d<z1){let C2=Math.max(0,Z1-1),J1=Math.min(V.length-1,Z1+1),m0=V.slice(C2,J1+1).map((c)=>c.trim()).join(" ").slice(0,80);m.push({line:Z1+1,column:d-n1+1,context:m0})}j=z1+1}let P=[`⚠️ EDIT PAUSED: old_string matches ${F.length} locations (must be unique).`,"","**Matches found at:**",...m.map((Z1,X1)=>` ${X1+1}. Line ${Z1.line}`),"","**Action Required:** Add 3-5 lines of surrounding context to make old_string unique.","","**Tips for quick success:**","• Include the function/class name that wraps the target code","• Add 2-3 lines before and after the target","• Include unique comments or variable names nearby",`• Or use replace_all=true to change all ${F.length} occurrences`,"","\uD83E\uDD16 **Auto-retry expected** - This usually resolves in 1-2 attempts."].join(`
476
- `),v=["⚠️ 编辑暂停:需要更精确的定位","",`在文件中找到 ${F.length} 处相似代码:`,...m.map((Z1,X1)=>` • 第 ${Z1.line} 行 (匹配 ${X1+1}/${F.length})`),"","AI 正在自动调整,添加更多上下文以精确定位...","通常需要 1-2 次尝试即可成功","","\uD83D\uDCA1 如果多次失败,可能需要:"," • 包含函数/类名等独特标识符"," • 添加目标代码前后 3-5 行完整上下文",` • 或使用 replace_all=true 同时替换所有 ${F.length} 处匹配`].join(`
477
- `);return{success:!1,llmContent:P,displayContent:v,error:{type:"validation_error",message:"old_string is not unique",details:{matches:m.map((Z1)=>({line:Z1.line,column:Z1.column})),count:F.length}}}}else q?.(`找到 ${F.length} 个匹配项,开始替换...`);let N,w;if(J)N=O.split(_).join(Q),w=F.length;else{let V=O.indexOf(_);N=O.substring(0,V)+Q+O.substring(V+_.length),w=1}if(W.throwIfAborted(),H)q?.("通过 IDE 写入文件...");if(await U.writeTextFile(Z,N),K)await l1.getInstance().recordFileEdit(Z,K,"edit");let B=await U.stat(Z),A=j3(O,N,_,Q,4),D=Z.split("/").pop()||Z,I=w===1?`替换 1 处匹配到 ${D}`:`替换 ${w} 处匹配到 ${D}`,b={file_path:Z,matches_found:F.length,replacements_made:w,replace_all:J,old_string_length:X.length,new_string_length:Q.length,original_size:O.length,new_size:N.length,size_diff:N.length-O.length,last_modified:B?.mtime instanceof Date?B.mtime.toISOString():void 0,snapshot_created:!!(K&&G),session_id:K,message_id:G,diff_snippet:A,summary:I,kind:"edit",oldContent:O,newContent:N},L=LJ(b,A);return{success:!0,llmContent:{file_path:Z,replacements:w,total_matches:F.length},displayContent:L,metadata:b}}catch(U){if(U.name==="AbortError")return{success:!1,llmContent:"File edit aborted",displayContent:"⚠️ 文件编辑被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File edit failed: ${U.message}`,displayContent:`❌ 编辑文件失败: ${U.message}`,error:{type:"execution_error",message:U.message,details:U}}}},version:"2.0.0",category:"文件操作",tags:["file","edit","replace","modify"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=BJ($.file_path);return Y?`**/*${Y}`:"**/*"}})});import{extname as x3}from"path";import{z as VJ}from"zod";function DJ($){return[".txt",".md",".js",".ts",".jsx",".tsx",".json",".xml",".html",".htm",".css",".scss",".sass",".less",".yml",".yaml",".toml",".ini",".cfg",".py",".rb",".php",".java",".cpp",".c",".h",".hpp",".rs",".go",".sh",".bash",".zsh",".fish",".ps1",".bat",".cmd",".sql",".graphql",".vue",".svelte",".astro",".dockerfile",".gitignore",".env"].includes($)||$===""}function MJ($){return[".jpg",".jpeg",".png",".gif",".bmp",".svg",".ico",".webp",".mp3",".wav",".mp4",".avi",".mov",".wmv",".flv",".webm",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".zip",".tar",".gz",".rar",".7z",".exe",".dll",".so",".ttf",".otf",".woff",".woff2",".eot"].includes($)}function IJ($,Y){let Z=`✅ 成功读取文件: ${$}`;if(Y.file_size!==void 0)Z+=` (${kJ(Y.file_size)})`;if(Y.lines_read!==void 0)Z+=`
485
+ \uD83D\uDCA1 请重新使用 Read 工具读取最新内容后再编辑`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:I.message}}}}if(G&&K)try{let k=new c$({sessionId:G});await k.initialize(),await k.createSnapshot(Z,K)}catch(k){console.warn("[EditTool] 创建快照失败:",k)}if(X===Q)return{success:!1,llmContent:"New string is identical; no replacement needed",displayContent:"⚠️ 新字符串与旧字符串相同,无需进行替换",error:{type:"validation_error",message:"新旧字符串相同"}};let F=yJ(O,X);if(!F.matched){let k=SJ(O,X,Z);return{success:!1,llmContent:k.llmContent,displayContent:k.displayContent,error:{type:"execution_error",message:"未找到匹配内容",details:k.metadata}}}let _=F.matched;if(F.strategy!=="exact")console.log(`[SmartEdit] 使用策略: ${F.strategy}`);let z=PJ(O,_);if(z.length>1&&!J){let k=O.split(`
486
+ `),I=0,T=[];for(let g=0;g<k.length;g++){let u=k[g],D1=I,J1=I+u.length;for(let x of z)if(x>=D1&&x<J1){let j0=Math.max(0,g-1),Q1=Math.min(k.length-1,g+1),u0=k.slice(j0,Q1+1).map((i)=>i.trim()).join(" ").slice(0,80);T.push({line:g+1,column:x-D1+1,context:u0})}I=J1+1}let E=[`⚠️ EDIT PAUSED: old_string matches ${z.length} locations (must be unique).`,"","**Matches found at:**",...T.map((g,u)=>` ${u+1}. Line ${g.line}`),"","**Action Required:** Add 3-5 lines of surrounding context to make old_string unique.","","**Tips for quick success:**","• Include the function/class name that wraps the target code","• Add 2-3 lines before and after the target","• Include unique comments or variable names nearby",`• Or use replace_all=true to change all ${z.length} occurrences`,"","\uD83E\uDD16 **Auto-retry expected** - This usually resolves in 1-2 attempts."].join(`
487
+ `),v=["⚠️ 编辑暂停:需要更精确的定位","",`在文件中找到 ${z.length} 处相似代码:`,...T.map((g,u)=>` • 第 ${g.line} 行 (匹配 ${u+1}/${z.length})`),"","AI 正在自动调整,添加更多上下文以精确定位...","通常需要 1-2 次尝试即可成功","","\uD83D\uDCA1 如果多次失败,可能需要:"," • 包含函数/类名等独特标识符"," • 添加目标代码前后 3-5 行完整上下文",` • 或使用 replace_all=true 同时替换所有 ${z.length} 处匹配`].join(`
488
+ `);return{success:!1,llmContent:E,displayContent:v,error:{type:"validation_error",message:"old_string is not unique",details:{matches:T.map((g)=>({line:g.line,column:g.column})),count:z.length}}}}else q?.(`找到 ${z.length} 个匹配项,开始替换...`);let w,B;if(J)w=O.split(_).join(Q),B=z.length;else{let k=O.indexOf(_);w=O.substring(0,k)+Q+O.substring(k+_.length),B=1}if(W.throwIfAborted(),H)q?.("通过 IDE 写入文件...");if(await U.writeTextFile(Z,w),G)await i1.getInstance().recordFileEdit(Z,G,"edit");let N=await U.stat(Z),b=x3(O,w,_,Q,4),V=Z.split("/").pop()||Z,R=B===1?`替换 1 处匹配到 ${V}`:`替换 ${B} 处匹配到 ${V}`,L={file_path:Z,matches_found:z.length,replacements_made:B,replace_all:J,old_string_length:X.length,new_string_length:Q.length,original_size:O.length,new_size:w.length,size_diff:w.length-O.length,last_modified:N?.mtime instanceof Date?N.mtime.toISOString():void 0,snapshot_created:!!(G&&K),session_id:G,message_id:K,diff_snippet:b,summary:R,kind:"edit",oldContent:O,newContent:w},A=TJ(L,b);return{success:!0,llmContent:{file_path:Z,replacements:B,total_matches:z.length},displayContent:A,metadata:L}}catch(U){if(U.name==="AbortError")return{success:!1,llmContent:"File edit aborted",displayContent:"⚠️ 文件编辑被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File edit failed: ${U.message}`,displayContent:`❌ 编辑文件失败: ${U.message}`,error:{type:"execution_error",message:U.message,details:U}}}},version:"2.0.0",category:"文件操作",tags:["file","edit","replace","modify"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=vJ($.file_path);return Y?`**/*${Y}`:"**/*"}})});import{extname as a3}from"path";import{z as hJ}from"zod";function xJ($){return[".txt",".md",".js",".ts",".jsx",".tsx",".json",".xml",".html",".htm",".css",".scss",".sass",".less",".yml",".yaml",".toml",".ini",".cfg",".py",".rb",".php",".java",".cpp",".c",".h",".hpp",".rs",".go",".sh",".bash",".zsh",".fish",".ps1",".bat",".cmd",".sql",".graphql",".vue",".svelte",".astro",".dockerfile",".gitignore",".env"].includes($)||$===""}function pJ($){return[".jpg",".jpeg",".png",".gif",".bmp",".svg",".ico",".webp",".mp3",".wav",".mp4",".avi",".mov",".wmv",".flv",".webm",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".zip",".tar",".gz",".rar",".7z",".exe",".dll",".so",".ttf",".otf",".woff",".woff2",".eot"].includes($)}function gJ($,Y){let Z=`✅ 成功读取文件: ${$}`;if(Y.file_size!==void 0)Z+=` (${mJ(Y.file_size)})`;if(Y.lines_read!==void 0)Z+=`
478
489
  \uD83D\uDCC4 读取了 ${Y.lines_read} 行 (第${Y.start_line}-${Y.end_line}行,共${Y.total_lines}行)`;if(Y.is_binary)Z+=`
479
- \uD83D\uDD10 文件以 base64 编码显示`;return Z}function kJ($){let Y=["B","KB","MB","GB"],Z=$,X=0;while(Z>=1024&&X<Y.length-1)Z/=1024,X++;return`${Z.toFixed(1)}${Y[X]}`}var H8;var p3=R(()=>{s2();o2();k1();h1();Z2();E6();H8=e({name:"Read",displayName:"File Read",kind:"readonly",schema:VJ.object({file_path:H1.filePath({description:"File path to read (must be absolute)"}),offset:H1.lineNumber({description:"Starting line number (0-based, text files only)"}).optional(),limit:H1.lineLimit({description:"Number of lines to read (text files only)"}).optional(),encoding:H1.encoding()}),description:{short:"Read files from the local filesystem",long:"Reads a file from the local filesystem. You can access any file directly by using this tool. Assume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.",usageNotes:["The file_path parameter must be an absolute path, not a relative path","By default, it reads up to 2000 lines starting from the beginning of the file","You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters","Any lines longer than 2000 characters will be truncated","Results are returned using cat -n format, with line numbers starting at 1","This tool allows reading images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as this is a multimodal LLM.","This tool can read PDF files (.pdf). PDFs are processed page by page, extracting both text and visual content for analysis.","This tool can read Jupyter notebooks (.ipynb files) and returns all cells with their outputs, combining code, text, and visualizations.","This tool can only read files, not directories. To read a directory, use an ls command via the Bash tool.","You can call multiple tools in a single response. It is always better to speculatively read multiple potentially useful files in parallel.","You will regularly be asked to read screenshots. If the user provides a path to a screenshot, ALWAYS use this tool to view the file at the path. This tool will work with all temporary file paths.","If you read a file that exists but has empty contents you will receive a system reminder warning in place of file contents."],examples:[{description:"Read the entire file (recommended)",params:{file_path:"/path/to/file.ts"}},{description:"Read the first 100 lines",params:{file_path:"/path/to/file.txt",limit:100}},{description:"Read 100 lines starting at line 50 (large file)",params:{file_path:"/path/to/large-file.log",offset:50,limit:100}}],important:["file_path must be absolute","Prefer reading the entire file (omit offset and limit)","Use offset/limit only for very large files","Line numbers start at 1 (cat -n format)"]},async execute($,Y){let{file_path:Z,offset:X,limit:Q,encoding:J="utf8"}=$,{updateOutput:q,sessionId:K}=Y,G=Y.signal??new AbortController().signal;try{q?.("Starting file read...");let W=n2(),U=Y2();try{if(!await W.exists(Z))throw Error("File not found")}catch(I){return{success:!1,llmContent:`File not found: ${Z}`,displayContent:`❌ 文件不存在: ${Z}`,error:{type:"execution_error",message:`File not found: ${Z}`}}}if(G.throwIfAborted(),K)await l1.getInstance().recordFileRead(Z,K);let H=await W.stat(Z);if(H?.isDirectory)return{success:!1,llmContent:`Cannot read a directory: ${Z}`,displayContent:`❌ 无法读取目录: ${Z}`,error:{type:"execution_error",message:"Target is a directory, not a file"}};let O=x3(Z).toLowerCase(),z=DJ(O),_=MJ(O),F,N={file_path:Z,file_size:H?.size,file_type:O,last_modified:H?.mtime instanceof Date?H.mtime.toISOString():void 0,encoding:J,acp_mode:U};if(_&&J==="utf8"){if(U)q?.("⚠️ 二进制文件通过本地读取(ACP 不支持)..."),N.acp_fallback=!0;else q?.("检测到二进制文件,使用 base64 编码...");F=(await W.readBinaryFile(Z)).toString("base64"),N.encoding="base64",N.is_binary=!0}else if(z){if(U)q?.("通过 IDE 读取文件...");F=await W.readTextFile(Z)}else{if(U)N.acp_fallback=!0;let I=await W.readBinaryFile(Z);if(J==="base64")F=I.toString("base64");else if(J==="binary")F=I.toString("binary");else F=I.toString("utf8")}if(G.throwIfAborted(),(X!==void 0||Q!==void 0)&&J==="utf8"&&z){let I=F.split(`
480
- `),b=X||0,L=Q!==void 0?b+Q:I.length,V=I.slice(b,L);F=V.map((j,m)=>{let P=b+m+1,v=j.length>2000?`${j.substring(0,2000)}...`:j;return`${P.toString().padStart(6)}→${v}`}).join(`
481
- `),N.lines_read=V.length,N.total_lines=I.length,N.start_line=b+1,N.end_line=Math.min(L,I.length)}let w=Z.split("/").pop()||Z,B=N.lines_read||N.total_lines,A=B?`读取 ${B} 行从 ${w}`:`读取 ${w}`;N.summary=A;let D=IJ(Z,N);return{success:!0,llmContent:F,displayContent:D,metadata:N}}catch(W){if(W.name==="AbortError")return{success:!1,llmContent:"File read aborted",displayContent:"⚠️ 文件读取被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`File read failed: ${W.message}`,displayContent:`❌ 读取文件失败: ${W.message}`,error:{type:"execution_error",message:W.message,details:W}}}},version:"2.0.0",category:"文件操作",tags:["file","io","read"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=x3($.file_path);return Y?`**/*${Y}`:"**/*"}})});import{promises as jJ}from"fs";import{dirname as EJ,extname as g3}from"path";import{z as O8}from"zod";function yJ($,Y,Z,X){let Q=`✅ 成功写入文件: ${$}`;if(Y.file_size!==void 0)Q+=` (${m3(Y.file_size)})`;if(Y.snapshot_created)Q+=`
490
+ \uD83D\uDD10 文件以 base64 编码显示`;return Z}function mJ($){let Y=["B","KB","MB","GB"],Z=$,X=0;while(Z>=1024&&X<Y.length-1)Z/=1024,X++;return`${Z.toFixed(1)}${Y[X]}`}var B8;var n3=D(()=>{e2();t2();j1();p1();J2();C6();B8=Y1({name:"Read",displayName:"File Read",kind:"readonly",schema:hJ.object({file_path:O1.filePath({description:"File path to read (must be absolute)"}),offset:O1.lineNumber({description:"Starting line number (0-based, text files only)"}).optional(),limit:O1.lineLimit({description:"Number of lines to read (text files only)"}).optional(),encoding:O1.encoding()}),description:{short:"Read files from the local filesystem",long:"Reads a file from the local filesystem. You can access any file directly by using this tool. Assume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.",usageNotes:["The file_path parameter must be an absolute path, not a relative path","By default, it reads up to 2000 lines starting from the beginning of the file","You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters","Any lines longer than 2000 characters will be truncated","Results are returned using cat -n format, with line numbers starting at 1","This tool allows reading images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as this is a multimodal LLM.","This tool can read PDF files (.pdf). PDFs are processed page by page, extracting both text and visual content for analysis.","This tool can read Jupyter notebooks (.ipynb files) and returns all cells with their outputs, combining code, text, and visualizations.","This tool can only read files, not directories. To read a directory, use an ls command via the Bash tool.","You can call multiple tools in a single response. It is always better to speculatively read multiple potentially useful files in parallel.","You will regularly be asked to read screenshots. If the user provides a path to a screenshot, ALWAYS use this tool to view the file at the path. This tool will work with all temporary file paths.","If you read a file that exists but has empty contents you will receive a system reminder warning in place of file contents."],examples:[{description:"Read the entire file (recommended)",params:{file_path:"/path/to/file.ts"}},{description:"Read the first 100 lines",params:{file_path:"/path/to/file.txt",limit:100}},{description:"Read 100 lines starting at line 50 (large file)",params:{file_path:"/path/to/large-file.log",offset:50,limit:100}}],important:["file_path must be absolute","Prefer reading the entire file (omit offset and limit)","Use offset/limit only for very large files","Line numbers start at 1 (cat -n format)"]},async execute($,Y){let{file_path:Z,offset:X,limit:Q,encoding:J="utf8"}=$,{updateOutput:q,sessionId:G}=Y,K=Y.signal??new AbortController().signal;try{q?.("Starting file read...");let W=s2(),U=Q2();try{if(!await W.exists(Z))throw Error("File not found")}catch(R){return{success:!1,llmContent:`File not found: ${Z}`,displayContent:`❌ 文件不存在: ${Z}`,error:{type:"execution_error",message:`File not found: ${Z}`}}}if(K.throwIfAborted(),G)await i1.getInstance().recordFileRead(Z,G);let H=await W.stat(Z);if(H?.isDirectory)return{success:!1,llmContent:`Cannot read a directory: ${Z}`,displayContent:`❌ 无法读取目录: ${Z}`,error:{type:"execution_error",message:"Target is a directory, not a file"}};let O=a3(Z).toLowerCase(),F=xJ(O),_=pJ(O),z,w={file_path:Z,file_size:H?.size,file_type:O,last_modified:H?.mtime instanceof Date?H.mtime.toISOString():void 0,encoding:J,acp_mode:U};if(_&&J==="utf8"){if(U)q?.("⚠️ 二进制文件通过本地读取(ACP 不支持)..."),w.acp_fallback=!0;else q?.("检测到二进制文件,使用 base64 编码...");z=(await W.readBinaryFile(Z)).toString("base64"),w.encoding="base64",w.is_binary=!0}else if(F){if(U)q?.("通过 IDE 读取文件...");z=await W.readTextFile(Z)}else{if(U)w.acp_fallback=!0;let R=await W.readBinaryFile(Z);if(J==="base64")z=R.toString("base64");else if(J==="binary")z=R.toString("binary");else z=R.toString("utf8")}if(K.throwIfAborted(),(X!==void 0||Q!==void 0)&&J==="utf8"&&F){let R=z.split(`
491
+ `),L=X||0,A=Q!==void 0?L+Q:R.length,k=R.slice(L,A);z=k.map((I,T)=>{let E=L+T+1,v=I.length>2000?`${I.substring(0,2000)}...`:I;return`${E.toString().padStart(6)}→${v}`}).join(`
492
+ `),w.lines_read=k.length,w.total_lines=R.length,w.start_line=L+1,w.end_line=Math.min(A,R.length)}let B=Z.split("/").pop()||Z,N=w.lines_read||w.total_lines,b=N?`读取 ${N} 行从 ${B}`:`读取 ${B}`;w.summary=b;let V=gJ(Z,w);return{success:!0,llmContent:z,displayContent:V,metadata:w}}catch(W){if(W.name==="AbortError")return{success:!1,llmContent:"File read aborted",displayContent:"⚠️ 文件读取被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`File read failed: ${W.message}`,displayContent:`❌ 读取文件失败: ${W.message}`,error:{type:"execution_error",message:W.message,details:W}}}},version:"2.0.0",category:"文件操作",tags:["file","io","read"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=a3($.file_path);return Y?`**/*${Y}`:"**/*"}})});import{promises as dJ}from"fs";import{dirname as uJ,extname as o3}from"path";import{z as w8}from"zod";function cJ($,Y,Z,X){let Q=`✅ 成功写入文件: ${$}`;if(Y.file_size!==void 0)Q+=` (${s3(Y.file_size)})`;if(Y.snapshot_created)Q+=`
482
493
  \uD83D\uDCF8 已创建快照 (可回滚)`;if(Y.encoding!=="utf8")Q+=`
483
- \uD83D\uDD10 使用编码: ${Y.encoding}`;if(X)Q+=X;if(Z&&Y.encoding==="utf8"&&!X){let J=vJ($,Z);if(J)Q+=`
494
+ \uD83D\uDD10 使用编码: ${Y.encoding}`;if(X)Q+=X;if(Z&&Y.encoding==="utf8"&&!X){let J=lJ($,Z);if(J)Q+=`
484
495
 
485
- `+J}return Q}function vJ($,Y){let Z=g3($).toLowerCase(),Q={".ts":"typescript",".tsx":"tsx",".js":"javascript",".jsx":"jsx",".py":"python",".go":"go",".rs":"rust",".java":"java",".c":"c",".cpp":"cpp",".h":"c",".hpp":"cpp",".cs":"csharp",".rb":"ruby",".php":"php",".swift":"swift",".kt":"kotlin",".scala":"scala",".sh":"bash",".bash":"bash",".zsh":"zsh",".json":"json",".yaml":"yaml",".yml":"yaml",".toml":"toml",".xml":"xml",".html":"html",".css":"css",".scss":"scss",".sass":"sass",".less":"less",".md":"markdown",".sql":"sql",".graphql":"graphql",".proto":"protobuf"}[Z]||"",J=100,q=5000,K=Y,G=!1,W=Y.split(`
486
- `);if(W.length>100)K=W.slice(0,100).join(`
487
- `),G=!0;if(K.length>5000)K=K.substring(0,5000),G=!0;let U=`\uD83D\uDCC4 文件内容:
496
+ `+J}return Q}function lJ($,Y){let Z=o3($).toLowerCase(),Q={".ts":"typescript",".tsx":"tsx",".js":"javascript",".jsx":"jsx",".py":"python",".go":"go",".rs":"rust",".java":"java",".c":"c",".cpp":"cpp",".h":"c",".hpp":"cpp",".cs":"csharp",".rb":"ruby",".php":"php",".swift":"swift",".kt":"kotlin",".scala":"scala",".sh":"bash",".bash":"bash",".zsh":"zsh",".json":"json",".yaml":"yaml",".yml":"yaml",".toml":"toml",".xml":"xml",".html":"html",".css":"css",".scss":"scss",".sass":"sass",".less":"less",".md":"markdown",".sql":"sql",".graphql":"graphql",".proto":"protobuf"}[Z]||"",J=100,q=5000,G=Y,K=!1,W=Y.split(`
497
+ `);if(W.length>100)G=W.slice(0,100).join(`
498
+ `),K=!0;if(G.length>5000)G=G.substring(0,5000),K=!0;let U=`\uD83D\uDCC4 文件内容:
488
499
 
489
500
  `;if(U+="```"+Q+`
490
- `,U+=K,!K.endsWith(`
501
+ `,U+=G,!G.endsWith(`
491
502
  `))U+=`
492
- `;if(U+="```",G)U+=`
503
+ `;if(U+="```",K)U+=`
493
504
 
494
- ⚠️ 内容已截断(完整文件共 ${W.length} 行,${Y.length} 字符)`;return U}function m3($){let Y=["B","KB","MB","GB"],Z=$,X=0;while(Z>=1024&&X<Y.length-1)Z/=1024,X++;return`${Z.toFixed(1)}${Y[X]}`}var z8;var d3=R(()=>{s2();o2();k1();h1();Z2();J8();E6();W8();z8=e({name:"Write",displayName:"File Write",kind:"write",strict:!0,isConcurrencySafe:!1,schema:O8.object({file_path:H1.filePath({description:"Absolute file path to write"}),content:O8.string().describe("Content to write"),encoding:H1.encoding(),create_directories:O8.boolean().default(!0).describe("Automatically create missing parent directories")}),description:{short:"Writes a file to the local filesystem",long:"Writes a file to the local filesystem.",usageNotes:["This tool will overwrite the existing file if there is one at the provided path.","If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.","ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.","NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.","Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked."]},async execute($,Y){let{file_path:Z,content:X,encoding:Q,create_directories:J}=$,{updateOutput:q,sessionId:K,messageId:G}=Y,W=Y.signal??new AbortController().signal;try{q?.("开始写入文件...");let U=n2(),H=Y2();if(J){let I=EJ(Z);try{await U.mkdir(I,{recursive:!0})}catch(b){if(b.code!=="EEXIST")throw b}}W.throwIfAborted();let O=!1,z=null;try{if(O=await U.exists(Z),O&&Q==="utf8")try{z=await U.readTextFile(Z)}catch(I){console.warn("[WriteTool] 读取旧文件内容失败:",I)}}catch{}if(O&&K){let I=l1.getInstance();if(!I.hasFileBeenRead(Z,K))return{success:!1,llmContent:"If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.",displayContent:`❌ 写入失败:必须先使用 Read 工具读取文件
505
+ ⚠️ 内容已截断(完整文件共 ${W.length} 行,${Y.length} 字符)`;return U}function s3($){let Y=["B","KB","MB","GB"],Z=$,X=0;while(Z>=1024&&X<Y.length-1)Z/=1024,X++;return`${Z.toFixed(1)}${Y[X]}`}var L8;var t3=D(()=>{e2();t2();j1();p1();J2();H8();C6();_8();L8=Y1({name:"Write",displayName:"File Write",kind:"write",strict:!0,isConcurrencySafe:!1,schema:w8.object({file_path:O1.filePath({description:"Absolute file path to write"}),content:w8.string().describe("Content to write"),encoding:O1.encoding(),create_directories:w8.boolean().default(!0).describe("Automatically create missing parent directories")}),description:{short:"Writes a file to the local filesystem",long:"Writes a file to the local filesystem.",usageNotes:["This tool will overwrite the existing file if there is one at the provided path.","If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.","ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.","NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.","Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked."]},async execute($,Y){let{file_path:Z,content:X,encoding:Q,create_directories:J}=$,{updateOutput:q,sessionId:G,messageId:K}=Y,W=Y.signal??new AbortController().signal;try{q?.("开始写入文件...");let U=s2(),H=Q2();if(J){let R=uJ(Z);try{await U.mkdir(R,{recursive:!0})}catch(L){if(L.code!=="EEXIST")throw L}}W.throwIfAborted();let O=!1,F=null;try{if(O=await U.exists(Z),O&&Q==="utf8")try{F=await U.readTextFile(Z)}catch(R){console.warn("[WriteTool] 读取旧文件内容失败:",R)}}catch{}if(O&&G){let R=i1.getInstance();if(!R.hasFileBeenRead(Z,G))return{success:!1,llmContent:"If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.",displayContent:`❌ 写入失败:必须先使用 Read 工具读取文件
495
506
 
496
- 文件 ${Z} 已存在,请先用 Read 工具查看其内容。`,error:{type:"validation_error",message:"File not read before write"}};let b=await I.checkExternalModification(Z);if(b.isExternal)return{success:!1,llmContent:`The file has been modified by an external program since you last read it. You must use the Read tool again to see the current content before writing.
507
+ 文件 ${Z} 已存在,请先用 Read 工具查看其内容。`,error:{type:"validation_error",message:"File not read before write"}};let L=await R.checkExternalModification(Z);if(L.isExternal)return{success:!1,llmContent:`The file has been modified by an external program since you last read it. You must use the Read tool again to see the current content before writing.
497
508
 
498
- Details: ${b.message}`,displayContent:`❌ 写入失败:文件已被外部程序修改
509
+ Details: ${L.message}`,displayContent:`❌ 写入失败:文件已被外部程序修改
499
510
 
500
- ${b.message}
511
+ ${L.message}
501
512
 
502
- \uD83D\uDCA1 请重新使用 Read 工具读取最新内容后再写入`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:b.message}}}}let _=!1;if(O&&K&&G)try{let I=new p$({sessionId:K});await I.initialize(),await I.createSnapshot(Z,G),_=!0}catch(I){console.warn("[WriteTool] 创建快照失败:",I)}if(W.throwIfAborted(),Q==="utf8"){if(H)q?.("通过 IDE 写入文件...");await U.writeTextFile(Z,X)}else{if(H)return{success:!1,llmContent:"Binary file writes are not supported in ACP mode. The IDE only supports text file operations. Please use encoding='utf8' for text files, or ask the user to write the file manually.",displayContent:`❌ ACP 模式不支持二进制文件写入
513
+ \uD83D\uDCA1 请重新使用 Read 工具读取最新内容后再写入`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:L.message}}}}let _=!1;if(O&&G&&K)try{let R=new c$({sessionId:G});await R.initialize(),await R.createSnapshot(Z,K),_=!0}catch(R){console.warn("[WriteTool] 创建快照失败:",R)}if(W.throwIfAborted(),Q==="utf8"){if(H)q?.("通过 IDE 写入文件...");await U.writeTextFile(Z,X)}else{if(H)return{success:!1,llmContent:"Binary file writes are not supported in ACP mode. The IDE only supports text file operations. Please use encoding='utf8' for text files, or ask the user to write the file manually.",displayContent:`❌ ACP 模式不支持二进制文件写入
503
514
 
504
515
  当前通过 IDE 执行文件操作,但 IDE 仅支持文本文件。
505
516
 
506
517
  \uD83D\uDCA1 建议:
507
518
  • 如果是文本文件,使用 encoding='utf8'
508
- • 如果必须写入二进制文件,请在本地终端执行`,error:{type:"validation_error",message:"Binary writes not supported in ACP mode"}};let I;if(Q==="base64")I=Buffer.from(X,"base64");else if(Q==="binary")I=Buffer.from(X,"binary");else I=Buffer.from(X,"utf8");await jJ.writeFile(Z,I)}if(K)await l1.getInstance().recordFileEdit(Z,K,"write");W.throwIfAborted();let F=await U.stat(Z),N=Q==="utf8"?X.split(`
509
- `).length:0,w=Z.split("/").pop()||Z,B=null;if(z&&Q==="utf8"&&z!==X){if(z.length<1048576&&X.length<1048576)B=k3(z,X,4)}let A={file_path:Z,content_size:X.length,file_size:F?.size,encoding:Q,created_directories:J,snapshot_created:_,session_id:K,message_id:G,last_modified:F?.mtime instanceof Date?F.mtime.toISOString():void 0,has_diff:!!B,summary:Q==="utf8"?`写入 ${N} 行到 ${w}`:`写入 ${F?.size?m3(F.size):"unknown"} 到 ${w}`,kind:"edit",oldContent:z||"",newContent:Q==="utf8"?X:void 0},D=yJ(Z,A,X,B);return{success:!0,llmContent:{file_path:Z,size:F?.size,modified:F?.mtime instanceof Date?F.mtime.toISOString():void 0},displayContent:D,metadata:A}}catch(U){if(U.name==="AbortError")return{success:!1,llmContent:"File write aborted",displayContent:"⚠️ 文件写入被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File write failed: ${U.message}`,displayContent:`❌ 写入文件失败: ${U.message}`,error:{type:"execution_error",message:U.message,details:U}}}},version:"2.0.0",category:"文件操作",tags:["file","io","write","create"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=g3($.file_path);return Y?`**/*${Y}`:"**/*"}})});var u3=R(()=>{h3();p3();d3()});import*as v6 from"fs/promises";import{z as $$}from"zod";var F8;var c3=R(()=>{k1();y0();F8=e({name:"NotebookEdit",displayName:"Notebook Edit",kind:"write",schema:$$.object({notebook_path:$$.string().describe("The absolute path to the Jupyter notebook file to edit (must be absolute, not relative)"),cell_id:$$.string().optional().describe("The ID of the cell to edit. When inserting a new cell, the new cell will be inserted after the cell with this ID, or at the beginning if not specified."),new_source:$$.string().describe("The new source for the cell"),cell_type:$$.enum(["code","markdown"]).optional().describe("The type of the cell (code or markdown). If not specified, it defaults to the current cell type. If using edit_mode=insert, this is required."),edit_mode:$$.enum(["replace","insert","delete"]).optional().default("replace").describe("The type of edit to make (replace, insert, delete). Defaults to replace.")}),description:{short:"Completely replaces the contents of a specific cell in a Jupyter notebook",long:"Completely replaces the contents of a specific cell in a Jupyter notebook (.ipynb file) with new source. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path. The cell_number is 0-indexed. Use edit_mode=insert to add a new cell at the index specified by cell_number. Use edit_mode=delete to delete the cell at the index specified by cell_number."},async execute($,Y){let{notebook_path:Z,cell_id:X,new_source:Q,cell_type:J,edit_mode:q="replace"}=$;try{let K=await v6.readFile(Z,"utf-8"),G=JSON.parse(K);if(!G.cells||!Array.isArray(G.cells))return{success:!1,llmContent:"Invalid notebook format: no cells array found",displayContent:"Invalid notebook format",error:{type:"validation_error",message:"Invalid notebook format"}};let W=-1;if(X){if(W=G.cells.findIndex((H)=>H.id===X),W===-1&&q!=="insert")return{success:!1,llmContent:`Cell with ID "${X}" not found`,displayContent:"Cell not found",error:{type:"validation_error",message:`Cell ID "${X}" not found`}}}switch(q){case"replace":{if(W===-1)return{success:!1,llmContent:"Cell ID required for replace operation",displayContent:"Cell ID required",error:{type:"validation_error",message:"Cell ID required for replace"}};let H=G.cells[W];if(H.source=Q.split(`
510
- `).map((O,z,_)=>z<_.length-1?O+`
519
+ • 如果必须写入二进制文件,请在本地终端执行`,error:{type:"validation_error",message:"Binary writes not supported in ACP mode"}};let R;if(Q==="base64")R=Buffer.from(X,"base64");else if(Q==="binary")R=Buffer.from(X,"binary");else R=Buffer.from(X,"utf8");await dJ.writeFile(Z,R)}if(G)await i1.getInstance().recordFileEdit(Z,G,"write");W.throwIfAborted();let z=await U.stat(Z),w=Q==="utf8"?X.split(`
520
+ `).length:0,B=Z.split("/").pop()||Z,N=null;if(F&&Q==="utf8"&&F!==X){if(F.length<1048576&&X.length<1048576)N=h3(F,X,4)}let b={file_path:Z,content_size:X.length,file_size:z?.size,encoding:Q,created_directories:J,snapshot_created:_,session_id:G,message_id:K,last_modified:z?.mtime instanceof Date?z.mtime.toISOString():void 0,has_diff:!!N,summary:Q==="utf8"?`写入 ${w} 行到 ${B}`:`写入 ${z?.size?s3(z.size):"unknown"} 到 ${B}`,kind:"edit",oldContent:F||"",newContent:Q==="utf8"?X:void 0},V=cJ(Z,b,X,N);return{success:!0,llmContent:{file_path:Z,size:z?.size,modified:z?.mtime instanceof Date?z.mtime.toISOString():void 0},displayContent:V,metadata:b}}catch(U){if(U.name==="AbortError")return{success:!1,llmContent:"File write aborted",displayContent:"⚠️ 文件写入被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File write failed: ${U.message}`,displayContent:`❌ 写入文件失败: ${U.message}`,error:{type:"execution_error",message:U.message,details:U}}}},version:"2.0.0",category:"文件操作",tags:["file","io","write","create"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=o3($.file_path);return Y?`**/*${Y}`:"**/*"}})});var e3=D(()=>{r3();n3();t3()});import*as h6 from"fs/promises";import{z as Z$}from"zod";var A8;var $5=D(()=>{j1();y0();A8=Y1({name:"NotebookEdit",displayName:"Notebook Edit",kind:"write",schema:Z$.object({notebook_path:Z$.string().describe("The absolute path to the Jupyter notebook file to edit (must be absolute, not relative)"),cell_id:Z$.string().optional().describe("The ID of the cell to edit. When inserting a new cell, the new cell will be inserted after the cell with this ID, or at the beginning if not specified."),new_source:Z$.string().describe("The new source for the cell"),cell_type:Z$.enum(["code","markdown"]).optional().describe("The type of the cell (code or markdown). If not specified, it defaults to the current cell type. If using edit_mode=insert, this is required."),edit_mode:Z$.enum(["replace","insert","delete"]).optional().default("replace").describe("The type of edit to make (replace, insert, delete). Defaults to replace.")}),description:{short:"Completely replaces the contents of a specific cell in a Jupyter notebook",long:"Completely replaces the contents of a specific cell in a Jupyter notebook (.ipynb file) with new source. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path. The cell_number is 0-indexed. Use edit_mode=insert to add a new cell at the index specified by cell_number. Use edit_mode=delete to delete the cell at the index specified by cell_number."},async execute($,Y){let{notebook_path:Z,cell_id:X,new_source:Q,cell_type:J,edit_mode:q="replace"}=$;try{let G=await h6.readFile(Z,"utf-8"),K=JSON.parse(G);if(!K.cells||!Array.isArray(K.cells))return{success:!1,llmContent:"Invalid notebook format: no cells array found",displayContent:"Invalid notebook format",error:{type:"validation_error",message:"Invalid notebook format"}};let W=-1;if(X){if(W=K.cells.findIndex((H)=>H.id===X),W===-1&&q!=="insert")return{success:!1,llmContent:`Cell with ID "${X}" not found`,displayContent:"Cell not found",error:{type:"validation_error",message:`Cell ID "${X}" not found`}}}switch(q){case"replace":{if(W===-1)return{success:!1,llmContent:"Cell ID required for replace operation",displayContent:"Cell ID required",error:{type:"validation_error",message:"Cell ID required for replace"}};let H=K.cells[W];if(H.source=Q.split(`
521
+ `).map((O,F,_)=>F<_.length-1?O+`
511
522
  `:O),J)H.cell_type=J;break}case"insert":{if(!J)return{success:!1,llmContent:"cell_type is required for insert operation",displayContent:"cell_type required",error:{type:"validation_error",message:"cell_type required for insert"}};let H={cell_type:J,source:Q.split(`
512
- `).map((z,_,F)=>_<F.length-1?z+`
513
- `:z),metadata:{},...J==="code"?{execution_count:null,outputs:[]}:{}},O=W===-1?0:W+1;G.cells.splice(O,0,H);break}case"delete":{if(W===-1)return{success:!1,llmContent:"Cell ID required for delete operation",displayContent:"Cell ID required",error:{type:"validation_error",message:"Cell ID required for delete"}};G.cells.splice(W,1);break}}await v6.writeFile(Z,JSON.stringify(G,null,2));let U=q==="replace"?"replaced":q==="insert"?"inserted":"deleted";return{success:!0,llmContent:`Successfully ${U} cell in ${Z}`,displayContent:`Cell ${U} in notebook`,metadata:{notebook_path:Z,edit_mode:q,cell_id:X}}}catch(K){let G=K instanceof Error?K.message:"Unknown error";return{success:!1,llmContent:`Failed to edit notebook: ${G}`,displayContent:"Notebook edit failed",error:{type:"execution_error",message:G}}}}})});var l3=R(()=>{c3()});import{z as PJ}from"zod";var _8;var i3=R(()=>{k1();y0();_8=e({name:"EnterPlanMode",displayName:"Enter Plan Mode",kind:"readonly",schema:PJ.object({}),description:{short:"Use this tool to enter plan mode for complex tasks requiring careful planning",long:`Use this tool when you encounter a complex task that requires careful planning and exploration before implementation. This tool transitions you into plan mode where you can thoroughly explore the codebase and design an implementation approach.
523
+ `).map((F,_,z)=>_<z.length-1?F+`
524
+ `:F),metadata:{},...J==="code"?{execution_count:null,outputs:[]}:{}},O=W===-1?0:W+1;K.cells.splice(O,0,H);break}case"delete":{if(W===-1)return{success:!1,llmContent:"Cell ID required for delete operation",displayContent:"Cell ID required",error:{type:"validation_error",message:"Cell ID required for delete"}};K.cells.splice(W,1);break}}await h6.writeFile(Z,JSON.stringify(K,null,2));let U=q==="replace"?"replaced":q==="insert"?"inserted":"deleted";return{success:!0,llmContent:`Successfully ${U} cell in ${Z}`,displayContent:`Cell ${U} in notebook`,metadata:{notebook_path:Z,edit_mode:q,cell_id:X}}}catch(G){let K=G instanceof Error?G.message:"Unknown error";return{success:!1,llmContent:`Failed to edit notebook: ${K}`,displayContent:"Notebook edit failed",error:{type:"execution_error",message:K}}}}})});var Y5=D(()=>{$5()});import{z as iJ}from"zod";var b8;var Z5=D(()=>{j1();y0();b8=Y1({name:"EnterPlanMode",displayName:"Enter Plan Mode",kind:"readonly",schema:iJ.object({}),description:{short:"Use this tool to enter plan mode for complex tasks requiring careful planning",long:`Use this tool when you encounter a complex task that requires careful planning and exploration before implementation. This tool transitions you into plan mode where you can thoroughly explore the codebase and design an implementation approach.
514
525
 
515
526
  ## When to Use This Tool
516
527
 
@@ -602,7 +613,7 @@ Begin your research now.`,displayContent:"✅ Entering Plan mode",metadata:{appr
602
613
 
603
614
  `+"Proceed with the task directly without planning phase. You can still use search tools to understand the codebase as needed, but implement the solution directly.",displayContent:"⚠️ Plan mode declined, proceeding directly",metadata:{approved:!1,enterPlanMode:!1}}}catch(Z){return{success:!1,llmContent:`Confirmation flow error: ${Z instanceof Error?Z.message:"Unknown error"}`,displayContent:"❌ Failed to request confirmation",error:{type:"execution_error",message:"Confirmation flow error"}}}return{success:!0,llmContent:`Plan mode requested but no interactive confirmation available.
604
615
 
605
- Proceeding with research phase. Use read-only tools to explore the codebase, then call ExitPlanMode with your implementation plan when ready.`,displayContent:"Plan mode (non-interactive)",metadata:{approved:null,enterPlanMode:!0}}}})});import{z as r3}from"zod";import{promises as a3}from"node:fs";import*as B8 from"node:path";import{homedir as TJ}from"node:os";var N8;var n3=R(()=>{k1();y0();N8=e({name:"ExitPlanMode",displayName:"Exit Plan Mode",kind:"readonly",schema:r3.object({plan:r3.string().describe("The complete implementation plan in markdown format")}),description:{short:"Use this tool when you are in plan mode and have finished creating your plan and are ready for user approval",long:`Use this tool when you are in plan mode and have finished creating your implementation plan and are ready for user approval.
616
+ Proceeding with research phase. Use read-only tools to explore the codebase, then call ExitPlanMode with your implementation plan when ready.`,displayContent:"Plan mode (non-interactive)",metadata:{approved:null,enterPlanMode:!0}}}})});import{z as X5}from"zod";import{promises as Q5}from"node:fs";import*as R8 from"node:path";import{homedir as rJ}from"node:os";var V8;var J5=D(()=>{j1();y0();V8=Y1({name:"ExitPlanMode",displayName:"Exit Plan Mode",kind:"readonly",schema:X5.object({plan:X5.string().describe("The complete implementation plan in markdown format")}),description:{short:"Use this tool when you are in plan mode and have finished creating your plan and are ready for user approval",long:`Use this tool when you are in plan mode and have finished creating your implementation plan and are ready for user approval.
606
617
 
607
618
  ## \uD83D\uDEA8 PREREQUISITES (MUST be satisfied before calling)
608
619
 
@@ -637,7 +648,7 @@ Before using this tool, ensure your plan is clear and unambiguous. If there are
637
648
  1. Initial task: "Search for and understand the implementation of vim mode in the codebase" - Do not use the exit plan mode tool because you are not planning the implementation steps of a task.
638
649
  2. Initial task: "Help me implement yank mode for vim" - Use the exit plan mode tool after you have finished planning the implementation steps of the task.
639
650
  3. Initial task: "Add a new feature to handle user authentication" - If unsure about auth method (OAuth, JWT, etc.), use AskUserQuestion first, then use exit plan mode tool after clarifying the approach.
640
- `},async execute($,Y){let Z=$.plan||"";if(Z&&Y.sessionId)try{let X=B8.join(TJ(),".blade","plans");await a3.mkdir(X,{recursive:!0});let Q=B8.join(X,`plan_${Y.sessionId}.md`);await a3.writeFile(Q,Z,"utf-8")}catch(X){console.warn("Failed to save plan file:",X)}if(Y.confirmationHandler)try{let X=await Y.confirmationHandler.requestConfirmation({type:"exitPlanMode",message:`The assistant has finished planning and is ready for your review.
651
+ `},async execute($,Y){let Z=$.plan||"";if(Z&&Y.sessionId)try{let X=R8.join(rJ(),".blade","plans");await Q5.mkdir(X,{recursive:!0});let Q=R8.join(X,`plan_${Y.sessionId}.md`);await Q5.writeFile(Q,Z,"utf-8")}catch(X){console.warn("Failed to save plan file:",X)}if(Y.confirmationHandler)try{let X=await Y.confirmationHandler.requestConfirmation({type:"exitPlanMode",message:`The assistant has finished planning and is ready for your review.
641
652
 
642
653
  `+`⚠️ Before approving, please verify:
643
654
  `+`1. The assistant has written a detailed plan to the plan file
@@ -650,40 +661,40 @@ please reject and ask for a proper plan.`,details:"After approval, the assistant
650
661
  `+(X.feedback||"No specific feedback provided.")+`
651
662
 
652
663
  The agent has stopped and control is returned to the user. The user can now provide additional information or clarification.`,displayContent:"⚠️ 方案被拒绝,等待用户补充信息",metadata:{approved:!1,shouldExitLoop:!0,feedback:X.feedback,awaitingUserInput:!0}}}catch(X){return{success:!1,llmContent:`Confirmation flow error: ${X instanceof Error?X.message:"Unknown error"}`,displayContent:"❌ Confirmation failed",error:{type:"execution_error",message:"Confirmation flow error"}}}return{success:!0,llmContent:`✅ Plan mode exit requested. No interactive confirmation available.
653
- `+"Proceeding with implementation.",displayContent:"Plan mode exit (non-interactive)",metadata:{approved:null}}}})});var o3=R(()=>{i3();n3()});import SJ from"fast-glob";import{LRUCache as CJ}from"lru-cache";import{existsSync as fJ,readFileSync as hJ}from"node:fs";import{readFile as xJ}from"node:fs/promises";import{dirname as pJ,join as t3}from"node:path";import g$ from"picomatch";function gJ($){if(!fJ($))return{patterns:[],negatePatterns:[]};try{let Y=hJ($,"utf-8"),Z=[],X=[];for(let Q of Y.split(`
654
- `)){let J=Q.trim();if(!J||J.startsWith("#"))continue;if(J.startsWith("!"))X.push(J.slice(1));else Z.push(J)}return{patterns:Z,negatePatterns:X}}catch(Y){return console.warn(`Failed to read .gitignore: ${Y}`),{patterns:[],negatePatterns:[]}}}async function mJ($,Y){let Z=[...T0.map((G)=>`${G}/**`),...Y?.scanIgnore??[]],X=`${$}|${Z.join(",")}`,Q=s3.get(X);if(Q)return Q;let J=await SJ("**/.gitignore",{cwd:$,dot:!0,onlyFiles:!0,followSymbolicLinks:!1,unique:!0,ignore:Z});J.sort((G,W)=>G.split("/").length-W.split("/").length);let q=[];for(let G of J){let W=pJ(G).replace(/\\/g,"/"),U=W==="."?"":W,O=(await xJ(t3($,G),"utf-8")).split(`
655
- `);for(let z of O){let _=z.trim();if(!_||_.startsWith("#"))continue;let F=_.startsWith("!"),w=(F?_.slice(1):_).trim();if(!w)continue;let B="";if(w.startsWith("/")){let A=w.slice(1).replace(/\\/g,"/");if(B=(U?U+"/":"")+A,q.push({type:F?"negate":"ignore",pattern:B}),w.endsWith("/")){let D=B+"**";q.push({type:F?"negate":"ignore",pattern:D});let I=B.replace(/\/$/,"");if(I!==B)q.push({type:F?"negate":"ignore",pattern:I})}}else{let A=w.replace(/\\/g,"/");if(A.includes("/")){if(B=(U?U+"/":"")+A,q.push({type:F?"negate":"ignore",pattern:B}),A.endsWith("/")){let D=B+"**";q.push({type:F?"negate":"ignore",pattern:D});let I=B.replace(/\/$/,"");if(I!==B)q.push({type:F?"negate":"ignore",pattern:I})}}else B=(U?U+"/**/":"**/")+A,q.push({type:F?"negate":"ignore",pattern:B})}}}let K=Y?.cacheTTL??30000;return s3.set(X,q,{ttl:K}),q}class P6{orderedRules=[];ignorePatterns=[];negatePatterns=[];constructor($={}){this.initialize($)}static async create($={}){let Y=new P6({...$,useGitignore:!1}),{cwd:Z=process.cwd(),useGitignore:X=!0,gitignoreScanMode:Q="root",customScanIgnore:J=[],cacheTTL:q}=$;if(X&&Q==="recursive"){let K=await mJ(Z,{scanIgnore:J,cacheTTL:q});for(let G of K)if(Y.orderedRules.push({type:G.type,matcher:g$(G.pattern,{dot:!0})}),G.type==="ignore")Y.ignorePatterns.push(G.pattern);else Y.negatePatterns.push(G.pattern)}return Y}initialize($){let{cwd:Y=process.cwd(),useGitignore:Z=!0,useDefaults:X=!0,customPatterns:Q=[]}=$,J=[],q=[];if(X){let K=[...T0.map((G)=>`${G}/**`),...T0,...w8];J.push(...K);for(let G of K)this.orderedRules.push({type:"ignore",matcher:g$(G,{dot:!0})})}if(Z){let K=t3(Y,".gitignore"),{patterns:G,negatePatterns:W}=gJ(K);for(let U of G)this.orderedRules.push({type:"ignore",matcher:g$(U,{dot:!0})}),J.push(U);for(let U of W)this.orderedRules.push({type:"negate",matcher:g$(U,{dot:!0})}),q.push(U)}J.push(...Q);for(let K of Q)this.orderedRules.push({type:"ignore",matcher:g$(K,{dot:!0})});this.ignorePatterns=J,this.negatePatterns=q}shouldIgnore($){let Y=$.replace(/\\/g,"/"),Z=void 0;for(let X of this.orderedRules)if(X.matcher(Y))Z=X.type==="ignore";return Z===!0}shouldIgnoreDirectory($){let Y=$.replace(/\\/g,"/");return this.shouldIgnore(Y)||this.shouldIgnore(`${Y}/`)}filter($){return $.filter((Y)=>!this.shouldIgnore(Y))}getIgnorePatterns(){return this.ignorePatterns}getNegatePatterns(){return this.negatePatterns}}var T0,w8,s3;var T6=R(()=>{T0=["node_modules",".git","dist","build","out",".next",".nuxt",".cache",".parcel-cache","coverage",".nyc_output",".idea",".vscode",".vs","bower_components","jspm_packages"],w8=["*.log","npm-debug.log*","yarn-debug.log*","pnpm-debug.log*","*.lock","package-lock.json","yarn.lock","pnpm-lock.yaml","*.tmp","*.temp","*.swp","*.bak","*~",".DS_Store","Thumbs.db","*.pid","*.seed"];s3=new CJ({max:100,ttl:30000,updateAgeOnGet:!0})});import dJ from"fast-glob";import{stat as uJ}from"node:fs/promises";import{join as cJ,resolve as lJ}from"path";import{z as S6}from"zod";function L8($){let Y=Error($);return Y.name="AbortError",Y}async function iJ($,Y,Z,X){let Q=X.getIgnorePatterns(),J=[],q=!1;return await new Promise((K,G)=>{if(Z.signal.aborted){G(L8("文件搜索被用户中止"));return}let W=dJ.stream(Y,{cwd:$,dot:!0,followSymbolicLinks:!1,unique:!0,caseSensitiveMatch:Z.caseSensitive,objectMode:!0,stats:!0,onlyFiles:!Z.includeDirectories,ignore:Q}),U=!1,H=null,O=()=>{if(H){if(Z.signal.removeEventListener)Z.signal.removeEventListener("abort",H);else if("onabort"in Z.signal)Z.signal.onabort=null;H=null}},z=()=>{if(!U)U=!0,q=!0,W.destroy(),O(),K({matches:J,wasTruncated:q})},_=(F)=>{if(Z.signal.aborted){if(!U)U=!0,W.destroy(L8("文件搜索被用户中止"));return}if(J.length>=Z.maxResults){z();return}let N=F.path.replace(/\\/g,"/"),w=cJ($,N);if(X.shouldIgnore(N))return;let B=F.stats?F.stats.isDirectory():!1;if(B&&X.shouldIgnoreDirectory(N))return;let A=F.stats&&F.stats.isFile()?F.stats.size:void 0,D=F.stats?F.stats.mtime.toISOString():void 0;if(J.push({path:w,relative_path:N,is_directory:B,size:A,modified:D}),J.length>=Z.maxResults)z()};if(W.on("data",_),H=()=>{if(!U)U=!0,O(),W.destroy(L8("文件搜索被用户中止"))},Z.signal.addEventListener)Z.signal.addEventListener("abort",H);else if("onabort"in Z.signal)Z.signal.onabort=H;W.once("error",(F)=>{if(!U)U=!0,O(),G(F)}),W.once("end",()=>{if(!U)U=!0,O(),K({matches:J,wasTruncated:q})})})}function rJ($){return $.sort((Y,Z)=>{if(Y.is_directory!==Z.is_directory)return Y.is_directory?1:-1;if(Y.modified&&Z.modified)return new Date(Z.modified).getTime()-new Date(Y.modified).getTime();return Y.relative_path.localeCompare(Z.relative_path)})}function aJ($){let{search_path:Y,pattern:Z,total_matches:X,returned_matches:Q,truncated:J}=$,q;if(J)q=`✅ 在 ${Y} 中找到至少 ${X} 个匹配 "${Z}" 的文件(已截断)`,q+=`
656
- \uD83D\uDCCB 显示前 ${Q} 个结果`;else q=`✅ 在 ${Y} 中找到 ${X} 个匹配 "${Z}" 的文件`;return q}var A8;var e3=R(()=>{T6();k1();h1();Z2();A8=e({name:"Glob",displayName:"File Pattern Match",kind:"readonly",schema:S6.object({pattern:H1.glob({description:"Glob pattern string (supports *, ?, ** wildcards)"}),path:S6.string().optional().describe("Search path (optional, defaults to cwd)"),max_results:H1.positiveInt({description:"Maximum number of results"}).max(1000,"At most 1000 results can be returned").default(100),include_directories:S6.boolean().default(!1).describe("Include directories in results"),case_sensitive:S6.boolean().default(!1).describe("Case sensitive matching")}),description:{short:"Fast file pattern matching tool that works with any codebase size",long:'Fast file pattern matching tool that works with any codebase size. Supports glob patterns like "**/*.js" or "src/**/*.ts". Returns matching file paths sorted by modification time.',usageNotes:["Use this tool when you need to find files by name patterns","When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead","You can call multiple tools in a single response. It is always better to speculatively perform multiple searches in parallel if they are potentially useful."]},async execute($,Y){let{pattern:Z,path:X=process.cwd(),max_results:Q,include_directories:J,case_sensitive:q}=$,{updateOutput:K}=Y,G=Y.signal??new AbortController().signal;try{K?.(`Searching in ${X} for pattern "${Z}"...`);let W=lJ(X);try{if(!(await uJ(W)).isDirectory())return{success:!1,llmContent:`Search path must be a directory: ${W}`,displayContent:`❌ 搜索路径必须是目录: ${W}`,error:{type:"validation_error",message:"搜索路径必须是目录"}}}catch(w){if(w.code==="ENOENT")return{success:!1,llmContent:`Search path does not exist: ${W}`,displayContent:`❌ 搜索路径不存在: ${W}`,error:{type:"execution_error",message:"搜索路径不存在"}};throw w}G.throwIfAborted();let U=await P6.create({cwd:W,useGitignore:!0,useDefaults:!0,gitignoreScanMode:"recursive",customScanIgnore:[],cacheTTL:30000}),{matches:H,wasTruncated:O}=await iJ(W,Z,{maxResults:Q,includeDirectories:J,caseSensitive:q,signal:G},U),z=rJ(H),_={search_path:W,pattern:Z,total_matches:H.length,returned_matches:H.length,max_results:Q,include_directories:J,case_sensitive:q,truncated:O},F=aJ(_),N;if(z.length>0)N=`${O?`Found at least ${z.length} file(s) matching "${Z}" (truncated)`:`Found ${z.length} file(s) matching "${Z}"`}:
664
+ `+"Proceeding with implementation.",displayContent:"Plan mode exit (non-interactive)",metadata:{approved:null}}}})});var q5=D(()=>{Z5();J5()});import aJ from"fast-glob";import{LRUCache as nJ}from"lru-cache";import{existsSync as oJ,readFileSync as sJ}from"node:fs";import{readFile as tJ}from"node:fs/promises";import{dirname as eJ,join as K5}from"node:path";import l$ from"picomatch";function $q($){if(!oJ($))return{patterns:[],negatePatterns:[]};try{let Y=sJ($,"utf-8"),Z=[],X=[];for(let Q of Y.split(`
665
+ `)){let J=Q.trim();if(!J||J.startsWith("#"))continue;if(J.startsWith("!"))X.push(J.slice(1));else Z.push(J)}return{patterns:Z,negatePatterns:X}}catch(Y){return console.warn(`Failed to read .gitignore: ${Y}`),{patterns:[],negatePatterns:[]}}}async function Yq($,Y){let Z=[...S0.map((K)=>`${K}/**`),...Y?.scanIgnore??[]],X=`${$}|${Z.join(",")}`,Q=G5.get(X);if(Q)return Q;let J=await aJ("**/.gitignore",{cwd:$,dot:!0,onlyFiles:!0,followSymbolicLinks:!1,unique:!0,ignore:Z});J.sort((K,W)=>K.split("/").length-W.split("/").length);let q=[];for(let K of J){let W=eJ(K).replace(/\\/g,"/"),U=W==="."?"":W,O=(await tJ(K5($,K),"utf-8")).split(`
666
+ `);for(let F of O){let _=F.trim();if(!_||_.startsWith("#"))continue;let z=_.startsWith("!"),B=(z?_.slice(1):_).trim();if(!B)continue;let N="";if(B.startsWith("/")){let b=B.slice(1).replace(/\\/g,"/");if(N=(U?U+"/":"")+b,q.push({type:z?"negate":"ignore",pattern:N}),B.endsWith("/")){let V=N+"**";q.push({type:z?"negate":"ignore",pattern:V});let R=N.replace(/\/$/,"");if(R!==N)q.push({type:z?"negate":"ignore",pattern:R})}}else{let b=B.replace(/\\/g,"/");if(b.includes("/")){if(N=(U?U+"/":"")+b,q.push({type:z?"negate":"ignore",pattern:N}),b.endsWith("/")){let V=N+"**";q.push({type:z?"negate":"ignore",pattern:V});let R=N.replace(/\/$/,"");if(R!==N)q.push({type:z?"negate":"ignore",pattern:R})}}else N=(U?U+"/**/":"**/")+b,q.push({type:z?"negate":"ignore",pattern:N})}}}let G=Y?.cacheTTL??30000;return G5.set(X,q,{ttl:G}),q}class x6{orderedRules=[];ignorePatterns=[];negatePatterns=[];constructor($={}){this.initialize($)}static async create($={}){let Y=new x6({...$,useGitignore:!1}),{cwd:Z=process.cwd(),useGitignore:X=!0,gitignoreScanMode:Q="root",customScanIgnore:J=[],cacheTTL:q}=$;if(X&&Q==="recursive"){let G=await Yq(Z,{scanIgnore:J,cacheTTL:q});for(let K of G)if(Y.orderedRules.push({type:K.type,matcher:l$(K.pattern,{dot:!0})}),K.type==="ignore")Y.ignorePatterns.push(K.pattern);else Y.negatePatterns.push(K.pattern)}return Y}initialize($){let{cwd:Y=process.cwd(),useGitignore:Z=!0,useDefaults:X=!0,customPatterns:Q=[]}=$,J=[],q=[];if(X){let G=[...S0.map((K)=>`${K}/**`),...S0,...D8];J.push(...G);for(let K of G)this.orderedRules.push({type:"ignore",matcher:l$(K,{dot:!0})})}if(Z){let G=K5(Y,".gitignore"),{patterns:K,negatePatterns:W}=$q(G);for(let U of K)this.orderedRules.push({type:"ignore",matcher:l$(U,{dot:!0})}),J.push(U);for(let U of W)this.orderedRules.push({type:"negate",matcher:l$(U,{dot:!0})}),q.push(U)}J.push(...Q);for(let G of Q)this.orderedRules.push({type:"ignore",matcher:l$(G,{dot:!0})});this.ignorePatterns=J,this.negatePatterns=q}shouldIgnore($){let Y=$.replace(/\\/g,"/"),Z=void 0;for(let X of this.orderedRules)if(X.matcher(Y))Z=X.type==="ignore";return Z===!0}shouldIgnoreDirectory($){let Y=$.replace(/\\/g,"/");return this.shouldIgnore(Y)||this.shouldIgnore(`${Y}/`)}filter($){return $.filter((Y)=>!this.shouldIgnore(Y))}getIgnorePatterns(){return this.ignorePatterns}getNegatePatterns(){return this.negatePatterns}}var S0,D8,G5;var p6=D(()=>{S0=["node_modules",".git","dist","build","out",".next",".nuxt",".cache",".parcel-cache","coverage",".nyc_output",".idea",".vscode",".vs","bower_components","jspm_packages"],D8=["*.log","npm-debug.log*","yarn-debug.log*","pnpm-debug.log*","*.lock","package-lock.json","yarn.lock","pnpm-lock.yaml","*.tmp","*.temp","*.swp","*.bak","*~",".DS_Store","Thumbs.db","*.pid","*.seed"];G5=new nJ({max:100,ttl:30000,updateAgeOnGet:!0})});import Zq from"fast-glob";import{stat as Xq}from"node:fs/promises";import{join as Qq,resolve as Jq}from"path";import{z as g6}from"zod";function I8($){let Y=Error($);return Y.name="AbortError",Y}async function qq($,Y,Z,X){let Q=X.getIgnorePatterns(),J=[],q=!1;return await new Promise((G,K)=>{if(Z.signal.aborted){K(I8("文件搜索被用户中止"));return}let W=Zq.stream(Y,{cwd:$,dot:!0,followSymbolicLinks:!1,unique:!0,caseSensitiveMatch:Z.caseSensitive,objectMode:!0,stats:!0,onlyFiles:!Z.includeDirectories,ignore:Q}),U=!1,H=null,O=()=>{if(H){if(Z.signal.removeEventListener)Z.signal.removeEventListener("abort",H);else if("onabort"in Z.signal)Z.signal.onabort=null;H=null}},F=()=>{if(!U)U=!0,q=!0,W.destroy(),O(),G({matches:J,wasTruncated:q})},_=(z)=>{if(Z.signal.aborted){if(!U)U=!0,W.destroy(I8("文件搜索被用户中止"));return}if(J.length>=Z.maxResults){F();return}let w=z.path.replace(/\\/g,"/"),B=Qq($,w);if(X.shouldIgnore(w))return;let N=z.stats?z.stats.isDirectory():!1;if(N&&X.shouldIgnoreDirectory(w))return;let b=z.stats&&z.stats.isFile()?z.stats.size:void 0,V=z.stats?z.stats.mtime.toISOString():void 0;if(J.push({path:B,relative_path:w,is_directory:N,size:b,modified:V}),J.length>=Z.maxResults)F()};if(W.on("data",_),H=()=>{if(!U)U=!0,O(),W.destroy(I8("文件搜索被用户中止"))},Z.signal.addEventListener)Z.signal.addEventListener("abort",H);else if("onabort"in Z.signal)Z.signal.onabort=H;W.once("error",(z)=>{if(!U)U=!0,O(),K(z)}),W.once("end",()=>{if(!U)U=!0,O(),G({matches:J,wasTruncated:q})})})}function Gq($){return $.sort((Y,Z)=>{if(Y.is_directory!==Z.is_directory)return Y.is_directory?1:-1;if(Y.modified&&Z.modified)return new Date(Z.modified).getTime()-new Date(Y.modified).getTime();return Y.relative_path.localeCompare(Z.relative_path)})}function Kq($){let{search_path:Y,pattern:Z,total_matches:X,returned_matches:Q,truncated:J}=$,q;if(J)q=`✅ 在 ${Y} 中找到至少 ${X} 个匹配 "${Z}" 的文件(已截断)`,q+=`
667
+ \uD83D\uDCCB 显示前 ${Q} 个结果`;else q=`✅ 在 ${Y} 中找到 ${X} 个匹配 "${Z}" 的文件`;return q}var M8;var W5=D(()=>{p6();j1();p1();J2();M8=Y1({name:"Glob",displayName:"File Pattern Match",kind:"readonly",schema:g6.object({pattern:O1.glob({description:"Glob pattern string (supports *, ?, ** wildcards)"}),path:g6.string().optional().describe("Search path (optional, defaults to cwd)"),max_results:O1.positiveInt({description:"Maximum number of results"}).max(1000,"At most 1000 results can be returned").default(100),include_directories:g6.boolean().default(!1).describe("Include directories in results"),case_sensitive:g6.boolean().default(!1).describe("Case sensitive matching")}),description:{short:"Fast file pattern matching tool that works with any codebase size",long:'Fast file pattern matching tool that works with any codebase size. Supports glob patterns like "**/*.js" or "src/**/*.ts". Returns matching file paths sorted by modification time.',usageNotes:["Use this tool when you need to find files by name patterns","When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead","You can call multiple tools in a single response. It is always better to speculatively perform multiple searches in parallel if they are potentially useful."]},async execute($,Y){let{pattern:Z,path:X=process.cwd(),max_results:Q,include_directories:J,case_sensitive:q}=$,{updateOutput:G}=Y,K=Y.signal??new AbortController().signal;try{G?.(`Searching in ${X} for pattern "${Z}"...`);let W=Jq(X);try{if(!(await Xq(W)).isDirectory())return{success:!1,llmContent:`Search path must be a directory: ${W}`,displayContent:`❌ 搜索路径必须是目录: ${W}`,error:{type:"validation_error",message:"搜索路径必须是目录"}}}catch(B){if(B.code==="ENOENT")return{success:!1,llmContent:`Search path does not exist: ${W}`,displayContent:`❌ 搜索路径不存在: ${W}`,error:{type:"execution_error",message:"搜索路径不存在"}};throw B}K.throwIfAborted();let U=await x6.create({cwd:W,useGitignore:!0,useDefaults:!0,gitignoreScanMode:"recursive",customScanIgnore:[],cacheTTL:30000}),{matches:H,wasTruncated:O}=await qq(W,Z,{maxResults:Q,includeDirectories:J,caseSensitive:q,signal:K},U),F=Gq(H),_={search_path:W,pattern:Z,total_matches:H.length,returned_matches:H.length,max_results:Q,include_directories:J,case_sensitive:q,truncated:O},z=Kq(_),w;if(F.length>0)w=`${O?`Found at least ${F.length} file(s) matching "${Z}" (truncated)`:`Found ${F.length} file(s) matching "${Z}"`}:
657
668
 
658
- `+z.map((B)=>`- ${B.relative_path}`).join(`
669
+ `+F.map((N)=>`- ${N.relative_path}`).join(`
659
670
  `)+`
660
671
 
661
- Use the relative_path values above for Read/Edit operations.`;else N=`No files found matching "${Z}"`;return{success:!0,llmContent:N,displayContent:F,metadata:{..._,matches:z}}}catch(W){if(W.name==="AbortError")return{success:!1,llmContent:"File search aborted",displayContent:"⚠️ 文件搜索被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Search failed: ${W.message}`,displayContent:`❌ 搜索失败: ${W.message}`,error:{type:"execution_error",message:W.message,details:W}}}},version:"2.0.0",category:"搜索工具",tags:["file","search","glob","pattern","wildcard"],extractSignatureContent:($)=>$.pattern,abstractPermissionRule:()=>"*"})});import{execSync as R8,spawn as b8}from"child_process";import{existsSync as C6}from"fs";import{readdir as nJ,readFile as oJ}from"fs/promises";import{join as $5,relative as sJ}from"path";import tJ from"picomatch";import{z as Q2}from"zod";function eJ(){let{platform:$,arch:Y}=process,Z={"darwin-arm64":"darwin-arm64/rg","darwin-x64":"darwin-x64/rg","linux-arm64":"linux-arm64/rg","linux-x64":"linux-x64/rg","win32-x64":"win32-x64/rg.exe"},X=`${$}-${Y}`,Q=Z[X];if(!Q)return null;let J=$5(process.cwd(),"vendor","ripgrep",Q);if(C6(J))return J;try{let q=new URL("../../../../vendor/ripgrep/"+Q,import.meta.url).pathname;if(C6(q))return q}catch{}return null}function Y5(){try{let Y=process.platform==="win32"?"where rg":"command -v rg 2>/dev/null || which rg 2>/dev/null",Z=R8(Y,{encoding:"utf8",stdio:["pipe","pipe","ignore"]}).split(/\r?\n/)[0].trim();if(Z)return Z}catch{}let $=eJ();if($&&C6($))return $;try{let Y=S1("@vscode/ripgrep");if(Y?.rgPath&&C6(Y.rgPath))return Y.rgPath}catch{}return null}async function $q($){try{return R8("git rev-parse --git-dir",{cwd:$,stdio:"ignore"}),!0}catch{return!1}}function Yq(){try{return R8("grep --version",{stdio:"ignore"}),!0}catch{return!1}}async function Zq($,Y,Z,X){let Q=Y5();if(!Q)throw Error("ripgrep not available");return new Promise((J,q)=>{let K=b8(Q,$,{stdio:["pipe","pipe","pipe"]}),G="",W="";K.stdout.on("data",(H)=>{G+=H.toString()}),K.stderr.on("data",(H)=>{W+=H.toString()}),K.on("close",(H)=>{J({stdout:G,stderr:W,exitCode:H||0})}),K.on("error",(H)=>{q(H)});let U=()=>{K.kill("SIGTERM"),q(Error("搜索被用户中止"))};Z.addEventListener("abort",U),K.on("close",()=>{Z.removeEventListener("abort",U)})})}async function Xq($,Y,Z,X){let Q=["grep","-n"];if(Z.caseInsensitive)Q.push("-i");if(Z.contextLines!==void 0)Q.push(`-C${Z.contextLines}`);if(Q.push("-e",$),Z.glob)Q.push("--",Z.glob);return new Promise((J,q)=>{let K=b8("git",Q,{cwd:Y,stdio:["pipe","pipe","pipe"]}),G="",W="";K.stdout.on("data",(H)=>{G+=H.toString()}),K.stderr.on("data",(H)=>{W+=H.toString()}),K.on("close",(H)=>{J({stdout:G,stderr:W,exitCode:H||0})}),K.on("error",(H)=>{q(H)});let U=()=>{K.kill("SIGTERM"),q(Error("搜索被用户中止"))};X.addEventListener("abort",U),K.on("close",()=>{X.removeEventListener("abort",U)})})}async function Qq($,Y,Z,X){let Q=["-rn"];if(Z.caseInsensitive)Q.push("-i");if(Z.contextLines!==void 0)Q.push(`-C${Z.contextLines}`);for(let J of T0)Q.push("--exclude-dir="+J.replace(/^\./,""));return Q.push("-e",$,Y),new Promise((J,q)=>{let K=b8("grep",Q,{stdio:["pipe","pipe","pipe"]}),G="",W="";K.stdout.on("data",(H)=>{G+=H.toString()}),K.stderr.on("data",(H)=>{W+=H.toString()}),K.on("close",(H)=>{J({stdout:G,stderr:W,exitCode:H||0})}),K.on("error",(H)=>{q(H)});let U=()=>{K.kill("SIGTERM"),q(Error("搜索被用户中止"))};X.addEventListener("abort",U),K.on("close",()=>{X.removeEventListener("abort",U)})})}async function Jq($,Y,Z,X){let Q=[],J=new RegExp($,Z.caseInsensitive?"gi":"g"),q=await qq(Y,X),K=0;for(let G of q){if(X.throwIfAborted(),Z5(G))continue;if(Z.glob&&!Kq(G,Z.glob))continue;try{(await oJ(G,"utf-8")).split(`
662
- `).forEach((H,O)=>{if(J.test(H))Q.push({file_path:sJ(Y,G),line_number:O+1,content:H})}),K++}catch(W){continue}}return{matches:Q,totalFiles:K}}async function qq($,Y){let Z=[];async function X(Q){Y.throwIfAborted();try{let J=await nJ(Q,{withFileTypes:!0});for(let q of J){Y.throwIfAborted();let K=$5(Q,q.name);if(q.isDirectory()){if(!Z5(K))await X(K)}else if(q.isFile())Z.push(K)}}catch(J){}}return await X($),Z}function Z5($){for(let Y of T0)if($.includes(Y))return!0;return!1}function Kq($,Y){return tJ(Y)($)}function Gq($){let Y=[];if($.case_insensitive)Y.push("-i");if($.multiline)Y.push("-U","--multiline-dotall");switch($.output_mode){case"files_with_matches":Y.push("-l");break;case"count":Y.push("-c");break;case"content":if($.line_numbers)Y.push("-n");break}if($.context!==void 0&&$.output_mode==="content")Y.push("-C",$.context.toString());else{if($.context_before!==void 0&&$.output_mode==="content")Y.push("-B",$.context_before.toString());if($.context_after!==void 0&&$.output_mode==="content")Y.push("-A",$.context_after.toString())}if($.type)Y.push("--type",$.type);for(let Z of T0)Y.push("--glob",`!${Z}/**`);if($.glob)Y.push("--glob",$.glob);if($.head_limit!==void 0){let Z=($.offset??0)+$.head_limit;Y.push("-m",Z.toString())}return Y.push($.pattern),Y.push($.path),Y}function Wq($,Y){if(!$.trim())return[];let Z=$.trim().split(`
663
- `),X=[];switch(Y){case"files_with_matches":return Z.map((Q)=>({file_path:Q.trim()}));case"count":return Z.map((Q)=>{let[J,q]=Q.split(":");return{file_path:J,count:parseInt(q,10)}});case"content":for(let Q of Z){let J=Uq(Q);if(J)X.push(J)}return X;default:return[]}}function Uq($){let Y=$.indexOf(":");if(Y===-1)return null;let Z=$.substring(0,Y),X=$.substring(Y+1),Q=X.indexOf(":");if(Q!==-1&&/^\d+$/.test(X.substring(0,Q))){let J=parseInt(X.substring(0,Q),10),q=X.substring(Q+1);return{file_path:Z,line_number:J,content:q}}else return{file_path:Z,content:X}}function Hq($){let{search_pattern:Y,search_path:Z,output_mode:X,total_matches:Q,strategy:J}=$,q=`✅ 在 ${Z} 中搜索 "${Y}"`;if(J)q+=`
672
+ Use the relative_path values above for Read/Edit operations.`;else w=`No files found matching "${Z}"`;return{success:!0,llmContent:w,displayContent:z,metadata:{..._,matches:F}}}catch(W){if(W.name==="AbortError")return{success:!1,llmContent:"File search aborted",displayContent:"⚠️ 文件搜索被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Search failed: ${W.message}`,displayContent:`❌ 搜索失败: ${W.message}`,error:{type:"execution_error",message:W.message,details:W}}}},version:"2.0.0",category:"搜索工具",tags:["file","search","glob","pattern","wildcard"],extractSignatureContent:($)=>$.pattern,abstractPermissionRule:()=>"*"})});import{execSync as k8,spawn as j8}from"child_process";import{existsSync as m6}from"fs";import{readdir as Wq,readFile as Uq}from"fs/promises";import{join as U5,relative as Hq}from"path";import Oq from"picomatch";import{z as G2}from"zod";function Fq(){let{platform:$,arch:Y}=process,Z={"darwin-arm64":"darwin-arm64/rg","darwin-x64":"darwin-x64/rg","linux-arm64":"linux-arm64/rg","linux-x64":"linux-x64/rg","win32-x64":"win32-x64/rg.exe"},X=`${$}-${Y}`,Q=Z[X];if(!Q)return null;let J=U5(process.cwd(),"vendor","ripgrep",Q);if(m6(J))return J;try{let q=new URL("../../../../vendor/ripgrep/"+Q,import.meta.url).pathname;if(m6(q))return q}catch{}return null}function H5(){try{let Y=process.platform==="win32"?"where rg":"command -v rg 2>/dev/null || which rg 2>/dev/null",Z=k8(Y,{encoding:"utf8",stdio:["pipe","pipe","ignore"]}).split(/\r?\n/)[0].trim();if(Z)return Z}catch{}let $=Fq();if($&&m6($))return $;try{let Y=C1("@vscode/ripgrep");if(Y?.rgPath&&m6(Y.rgPath))return Y.rgPath}catch{}return null}async function zq($){try{return k8("git rev-parse --git-dir",{cwd:$,stdio:"ignore"}),!0}catch{return!1}}function _q(){try{return k8("grep --version",{stdio:"ignore"}),!0}catch{return!1}}async function Nq($,Y,Z,X){let Q=H5();if(!Q)throw Error("ripgrep not available");return new Promise((J,q)=>{let G=j8(Q,$,{stdio:["pipe","pipe","pipe"]}),K="",W="";G.stdout.on("data",(H)=>{K+=H.toString()}),G.stderr.on("data",(H)=>{W+=H.toString()}),G.on("close",(H)=>{J({stdout:K,stderr:W,exitCode:H||0})}),G.on("error",(H)=>{q(H)});let U=()=>{G.kill("SIGTERM"),q(Error("搜索被用户中止"))};Z.addEventListener("abort",U),G.on("close",()=>{Z.removeEventListener("abort",U)})})}async function Bq($,Y,Z,X){let Q=["grep","-n"];if(Z.caseInsensitive)Q.push("-i");if(Z.contextLines!==void 0)Q.push(`-C${Z.contextLines}`);if(Q.push("-e",$),Z.glob)Q.push("--",Z.glob);return new Promise((J,q)=>{let G=j8("git",Q,{cwd:Y,stdio:["pipe","pipe","pipe"]}),K="",W="";G.stdout.on("data",(H)=>{K+=H.toString()}),G.stderr.on("data",(H)=>{W+=H.toString()}),G.on("close",(H)=>{J({stdout:K,stderr:W,exitCode:H||0})}),G.on("error",(H)=>{q(H)});let U=()=>{G.kill("SIGTERM"),q(Error("搜索被用户中止"))};X.addEventListener("abort",U),G.on("close",()=>{X.removeEventListener("abort",U)})})}async function wq($,Y,Z,X){let Q=["-rn"];if(Z.caseInsensitive)Q.push("-i");if(Z.contextLines!==void 0)Q.push(`-C${Z.contextLines}`);for(let J of S0)Q.push("--exclude-dir="+J.replace(/^\./,""));return Q.push("-e",$,Y),new Promise((J,q)=>{let G=j8("grep",Q,{stdio:["pipe","pipe","pipe"]}),K="",W="";G.stdout.on("data",(H)=>{K+=H.toString()}),G.stderr.on("data",(H)=>{W+=H.toString()}),G.on("close",(H)=>{J({stdout:K,stderr:W,exitCode:H||0})}),G.on("error",(H)=>{q(H)});let U=()=>{G.kill("SIGTERM"),q(Error("搜索被用户中止"))};X.addEventListener("abort",U),G.on("close",()=>{X.removeEventListener("abort",U)})})}async function Lq($,Y,Z,X){let Q=[],J=new RegExp($,Z.caseInsensitive?"gi":"g"),q=await Aq(Y,X),G=0;for(let K of q){if(X.throwIfAborted(),O5(K))continue;if(Z.glob&&!bq(K,Z.glob))continue;try{(await Uq(K,"utf-8")).split(`
673
+ `).forEach((H,O)=>{if(J.test(H))Q.push({file_path:Hq(Y,K),line_number:O+1,content:H})}),G++}catch(W){continue}}return{matches:Q,totalFiles:G}}async function Aq($,Y){let Z=[];async function X(Q){Y.throwIfAborted();try{let J=await Wq(Q,{withFileTypes:!0});for(let q of J){Y.throwIfAborted();let G=U5(Q,q.name);if(q.isDirectory()){if(!O5(G))await X(G)}else if(q.isFile())Z.push(G)}}catch(J){}}return await X($),Z}function O5($){for(let Y of S0)if($.includes(Y))return!0;return!1}function bq($,Y){return Oq(Y)($)}function Rq($){let Y=[];if($.case_insensitive)Y.push("-i");if($.multiline)Y.push("-U","--multiline-dotall");switch($.output_mode){case"files_with_matches":Y.push("-l");break;case"count":Y.push("-c");break;case"content":if($.line_numbers)Y.push("-n");break}if($.context!==void 0&&$.output_mode==="content")Y.push("-C",$.context.toString());else{if($.context_before!==void 0&&$.output_mode==="content")Y.push("-B",$.context_before.toString());if($.context_after!==void 0&&$.output_mode==="content")Y.push("-A",$.context_after.toString())}if($.type)Y.push("--type",$.type);for(let Z of S0)Y.push("--glob",`!${Z}/**`);if($.glob)Y.push("--glob",$.glob);if($.head_limit!==void 0){let Z=($.offset??0)+$.head_limit;Y.push("-m",Z.toString())}return Y.push($.pattern),Y.push($.path),Y}function Vq($,Y){if(!$.trim())return[];let Z=$.trim().split(`
674
+ `),X=[];switch(Y){case"files_with_matches":return Z.map((Q)=>({file_path:Q.trim()}));case"count":return Z.map((Q)=>{let[J,q]=Q.split(":");return{file_path:J,count:parseInt(q,10)}});case"content":for(let Q of Z){let J=Dq(Q);if(J)X.push(J)}return X;default:return[]}}function Dq($){let Y=$.indexOf(":");if(Y===-1)return null;let Z=$.substring(0,Y),X=$.substring(Y+1),Q=X.indexOf(":");if(Q!==-1&&/^\d+$/.test(X.substring(0,Q))){let J=parseInt(X.substring(0,Q),10),q=X.substring(Q+1);return{file_path:Z,line_number:J,content:q}}else return{file_path:Z,content:X}}function Iq($){let{search_pattern:Y,search_path:Z,output_mode:X,total_matches:Q,strategy:J}=$,q=`✅ 在 ${Z} 中搜索 "${Y}"`;if(J)q+=`
664
675
  \uD83D\uDD27 使用策略: ${J}`;switch(X){case"files_with_matches":q+=`
665
676
  \uD83D\uDCC1 找到 ${Q} 个包含匹配内容的文件`;break;case"count":q+=`
666
677
  \uD83D\uDD22 统计了 ${Q} 个文件的匹配数量`;break;case"content":q+=`
667
- \uD83D\uDCDD 找到 ${Q} 个匹配行`;break}return q}var V8;var X5=R(()=>{T6();k1();h1();Z2();V8=e({name:"Grep",displayName:"内容搜索",kind:"readonly",schema:Q2.object({pattern:H1.pattern({description:"The regular expression pattern to search for in file contents"}),path:Q2.string().optional().describe("File or directory to search in (rg PATH). Defaults to current working directory"),glob:Q2.string().optional().describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}") - maps to rg --glob'),type:Q2.string().optional().describe("File type to search (rg --type). Common types: js, py, rust, go, java, etc. More efficient than include for standard file types"),output_mode:Q2.enum(["content","files_with_matches","count"]).default("files_with_matches").describe('Output mode: "content" shows matching lines (supports -A/-B/-C context, -n line numbers, head_limit), "files_with_matches" shows file paths (supports head_limit), "count" shows match counts (supports head_limit). Defaults to "files_with_matches"'),"-i":Q2.boolean().optional().describe("Case insensitive search (rg -i)"),"-n":Q2.boolean().default(!0).describe('Show line numbers in output (rg -n). Requires output_mode: "content", ignored otherwise. Defaults to true'),"-B":H1.nonNegativeInt().optional().describe('Number of lines to show before each match (rg -B). Requires output_mode: "content", ignored otherwise'),"-A":H1.nonNegativeInt().optional().describe('Number of lines to show after each match (rg -A). Requires output_mode: "content", ignored otherwise'),"-C":H1.nonNegativeInt().optional().describe('Number of lines to show before and after each match (rg -C). Requires output_mode: "content", ignored otherwise'),head_limit:H1.positiveInt().optional().describe('Limit output to first N lines/entries, equivalent to "| head -N". Works across all output modes: content (limits output lines), files_with_matches (limits file paths), count (limits count entries). Defaults based on "cap" experiment value: 0 (unlimited), 20, or 100'),offset:H1.nonNegativeInt().optional().describe('Skip first N lines/entries before applying head_limit, equivalent to "| tail -n +N | head -N". Works across all output modes. Defaults to 0'),multiline:Q2.boolean().default(!1).describe("Enable multiline mode where . matches newlines and patterns can span lines (rg -U --multiline-dotall). Default: false")}),description:{short:"A powerful search tool built on ripgrep",long:'A powerful search tool built on ripgrep\n\n Usage:\n - ALWAYS use Grep for search tasks. NEVER invoke `grep` or `rg` as a Bash command. The Grep tool has been optimized for correct permissions and access.\n - Supports full regex syntax (e.g., "log.*Error", "function\\s+\\w+")\n - Filter files with glob parameter (e.g., "*.js", "**/*.tsx") or type parameter (e.g., "js", "py", "rust")\n - Output modes: "content" shows matching lines, "files_with_matches" shows only file paths (default), "count" shows match counts\n - Use Task tool for open-ended searches requiring multiple rounds\n - Pattern syntax: Uses ripgrep (not grep) - literal braces need escaping (use `interface\\{\\}` to find `interface{}` in Go code)\n - Multiline matching: By default patterns match within single lines only. For cross-line patterns like `struct \\{[\\s\\S]*?field`, use `multiline: true`\n'},async execute($,Y){let{pattern:Z,path:X=process.cwd(),glob:Q,type:J,output_mode:q,"-i":K,"-n":G=!0,"-B":W,"-A":U,"-C":H,head_limit:O,offset:z,multiline:_}=$,{updateOutput:F}=Y,N=Y.signal??new AbortController().signal;try{F?.(`使用智能搜索策略查找模式 "${Z}"...`);let w=null,B="ripgrep",A=[],D=Y5();if(D)try{F?.(`\uD83D\uDE80 使用 ripgrep (${D})`);let V=Gq({pattern:Z,path:X,glob:Q,type:J,output_mode:q,case_insensitive:K??!1,line_numbers:G,context_before:W,context_after:U,context:H,head_limit:O,offset:z,multiline:_??!1});w=await Zq(V,q,N,F),B="ripgrep"}catch(V){F?.("⚠️ ripgrep 失败,尝试降级策略..."),w=null}if(!w&&await $q(X))try{F?.("\uD83D\uDCE6 使用 git grep"),w=await Xq(Z,X,{caseInsensitive:K??!1,glob:Q,contextLines:H},N),B="git-grep"}catch(V){F?.("⚠️ git grep 失败,继续尝试其他策略..."),w=null}if(!w&&Yq())try{F?.("\uD83D\uDD27 使用系统 grep"),w=await Qq(Z,X,{caseInsensitive:K??!1,contextLines:H},N),B="system-grep"}catch(V){F?.("⚠️ 系统 grep 失败,使用纯 JavaScript 实现..."),w=null}if(!w)F?.("\uD83D\uDCA1 使用纯 JavaScript 搜索实现"),A=(await Jq(Z,X,{caseInsensitive:K??!1,glob:Q,multiline:_??!1},N)).matches,B="fallback",w={stdout:"",stderr:"",exitCode:0};else A=Wq(w.stdout,q);let I=A.length;if(z!==void 0&&z>0)A=A.slice(z);if(O!==void 0&&A.length>O)A=A.slice(0,O);let b={search_pattern:Z,search_path:X,output_mode:q,case_insensitive:K??!1,total_matches:A.length,original_total:I,offset:z,head_limit:O,strategy:B,exit_code:w?.exitCode};if(w&&w.exitCode!==0&&w.stderr)return{success:!1,llmContent:`Search execution failed: ${w.stderr}`,displayContent:`❌ 搜索执行失败: ${w.stderr}`,error:{type:"execution_error",message:w.stderr}};let L=Hq(b);return{success:!0,llmContent:A,displayContent:L,metadata:b}}catch(w){if(w.name==="AbortError")return{success:!1,llmContent:"Search aborted",displayContent:"⚠️ 搜索被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Search failed: ${w.message}`,displayContent:`❌ 搜索失败: ${w.message}`,error:{type:"execution_error",message:w.message,details:w}}}},version:"3.0.0",category:"搜索工具",tags:["search","grep","ripgrep","regex","text","fallback"],extractSignatureContent:($)=>$.pattern,abstractPermissionRule:()=>"*"})});var Q5=R(()=>{e3();X5()});import{spawn as Oq}from"child_process";import{randomUUID as zq}from"crypto";class i1{static instance=null;processes=new Map;static getInstance(){if(!i1.instance)i1.instance=new i1;return i1.instance}startBackgroundProcess($){let Y=`bash_${zq()}`,Z={};for(let[J,q]of Object.entries({...process.env,...$.env,BLADE_CLI:"1"}))if(q!==void 0)Z[J]=q;let X=Oq("bash",["-c",$.command],{cwd:$.cwd||process.cwd(),env:Z,stdio:["ignore","pipe","pipe"]}),Q={id:Y,command:$.command,sessionId:$.sessionId,cwd:$.cwd,env:$.env,process:X,pid:X.pid,status:"running",startTime:Date.now(),pendingStdout:"",pendingStderr:""};return X.stdout?.setEncoding("utf8"),X.stderr?.setEncoding("utf8"),X.stdout?.on("data",(J)=>{Q.pendingStdout+=J.toString()}),X.stderr?.on("data",(J)=>{Q.pendingStderr+=J.toString()}),X.on("close",(J,q)=>{Q.status=Q.status==="killed"?"killed":"exited",Q.exitCode=J,Q.signal=q,Q.endTime=Date.now(),Q.process=void 0}),X.on("error",(J)=>{Q.status="error",Q.errorMessage=J.message,Q.endTime=Date.now(),Q.process=void 0,Q.pendingStderr+=`
668
- [error] ${J.message}`}),this.processes.set(Y,Q),Q}consumeOutput($){let Y=this.processes.get($);if(!Y)return;let Z={id:Y.id,command:Y.command,status:Y.status,stdout:Y.pendingStdout,stderr:Y.pendingStderr,exitCode:Y.exitCode,signal:Y.signal,pid:Y.pid,startedAt:Y.startTime,endedAt:Y.endTime,errorMessage:Y.errorMessage};return Y.pendingStdout="",Y.pendingStderr="",Z}getProcess($){return this.processes.get($)}kill($){let Y=this.processes.get($);if(!Y)return;if(Y.status!=="running"||!Y.process)return{success:!1,alreadyExited:!0,status:Y.status,pid:Y.pid,exitCode:Y.exitCode,signal:Y.signal};if(!Y.process.kill("SIGTERM"))return{success:!1,alreadyExited:!1,status:Y.status,pid:Y.pid,exitCode:Y.exitCode,signal:Y.signal};return Y.status="killed",Y.endTime=Date.now(),Y.process=void 0,{success:!0,alreadyExited:!1,status:Y.status,pid:Y.pid,exitCode:Y.exitCode,signal:Y.signal}}killAll(){for(let[$,Y]of this.processes)if(Y.status==="running"&&Y.process)try{Y.process.kill("SIGTERM"),Y.status="killed",Y.endTime=Date.now(),Y.process=void 0}catch{}this.processes.clear()}}var Y$=()=>{};import{spawn as Fq}from"child_process";import{randomUUID as _q}from"crypto";import{z as D8}from"zod";function Bq($,Y,Z){let Q=i1.getInstance().startBackgroundProcess({command:$,sessionId:_q(),cwd:Y||process.cwd(),env:Z}),q=`后台启动命令: ${$.length>30?`${$.substring(0,30)}...`:$}`,K={command:$,background:!0,pid:Q.pid,bash_id:Q.id,shell_id:Q.id,message:"命令已在后台启动",summary:q},G=`✅ 命令已在后台启动
678
+ \uD83D\uDCDD 找到 ${Q} 个匹配行`;break}return q}var E8;var F5=D(()=>{p6();j1();p1();J2();E8=Y1({name:"Grep",displayName:"内容搜索",kind:"readonly",schema:G2.object({pattern:O1.pattern({description:"The regular expression pattern to search for in file contents"}),path:G2.string().optional().describe("File or directory to search in (rg PATH). Defaults to current working directory"),glob:G2.string().optional().describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}") - maps to rg --glob'),type:G2.string().optional().describe("File type to search (rg --type). Common types: js, py, rust, go, java, etc. More efficient than include for standard file types"),output_mode:G2.enum(["content","files_with_matches","count"]).default("files_with_matches").describe('Output mode: "content" shows matching lines (supports -A/-B/-C context, -n line numbers, head_limit), "files_with_matches" shows file paths (supports head_limit), "count" shows match counts (supports head_limit). Defaults to "files_with_matches"'),"-i":G2.boolean().optional().describe("Case insensitive search (rg -i)"),"-n":G2.boolean().default(!0).describe('Show line numbers in output (rg -n). Requires output_mode: "content", ignored otherwise. Defaults to true'),"-B":O1.nonNegativeInt().optional().describe('Number of lines to show before each match (rg -B). Requires output_mode: "content", ignored otherwise'),"-A":O1.nonNegativeInt().optional().describe('Number of lines to show after each match (rg -A). Requires output_mode: "content", ignored otherwise'),"-C":O1.nonNegativeInt().optional().describe('Number of lines to show before and after each match (rg -C). Requires output_mode: "content", ignored otherwise'),head_limit:O1.positiveInt().optional().describe('Limit output to first N lines/entries, equivalent to "| head -N". Works across all output modes: content (limits output lines), files_with_matches (limits file paths), count (limits count entries). Defaults based on "cap" experiment value: 0 (unlimited), 20, or 100'),offset:O1.nonNegativeInt().optional().describe('Skip first N lines/entries before applying head_limit, equivalent to "| tail -n +N | head -N". Works across all output modes. Defaults to 0'),multiline:G2.boolean().default(!1).describe("Enable multiline mode where . matches newlines and patterns can span lines (rg -U --multiline-dotall). Default: false")}),description:{short:"A powerful search tool built on ripgrep",long:'A powerful search tool built on ripgrep\n\n Usage:\n - ALWAYS use Grep for search tasks. NEVER invoke `grep` or `rg` as a Bash command. The Grep tool has been optimized for correct permissions and access.\n - Supports full regex syntax (e.g., "log.*Error", "function\\s+\\w+")\n - Filter files with glob parameter (e.g., "*.js", "**/*.tsx") or type parameter (e.g., "js", "py", "rust")\n - Output modes: "content" shows matching lines, "files_with_matches" shows only file paths (default), "count" shows match counts\n - Use Task tool for open-ended searches requiring multiple rounds\n - Pattern syntax: Uses ripgrep (not grep) - literal braces need escaping (use `interface\\{\\}` to find `interface{}` in Go code)\n - Multiline matching: By default patterns match within single lines only. For cross-line patterns like `struct \\{[\\s\\S]*?field`, use `multiline: true`\n'},async execute($,Y){let{pattern:Z,path:X=process.cwd(),glob:Q,type:J,output_mode:q,"-i":G,"-n":K=!0,"-B":W,"-A":U,"-C":H,head_limit:O,offset:F,multiline:_}=$,{updateOutput:z}=Y,w=Y.signal??new AbortController().signal;try{z?.(`使用智能搜索策略查找模式 "${Z}"...`);let B=null,N="ripgrep",b=[],V=H5();if(V)try{z?.(`\uD83D\uDE80 使用 ripgrep (${V})`);let k=Rq({pattern:Z,path:X,glob:Q,type:J,output_mode:q,case_insensitive:G??!1,line_numbers:K,context_before:W,context_after:U,context:H,head_limit:O,offset:F,multiline:_??!1});B=await Nq(k,q,w,z),N="ripgrep"}catch(k){z?.("⚠️ ripgrep 失败,尝试降级策略..."),B=null}if(!B&&await zq(X))try{z?.("\uD83D\uDCE6 使用 git grep"),B=await Bq(Z,X,{caseInsensitive:G??!1,glob:Q,contextLines:H},w),N="git-grep"}catch(k){z?.("⚠️ git grep 失败,继续尝试其他策略..."),B=null}if(!B&&_q())try{z?.("\uD83D\uDD27 使用系统 grep"),B=await wq(Z,X,{caseInsensitive:G??!1,contextLines:H},w),N="system-grep"}catch(k){z?.("⚠️ 系统 grep 失败,使用纯 JavaScript 实现..."),B=null}if(!B)z?.("\uD83D\uDCA1 使用纯 JavaScript 搜索实现"),b=(await Lq(Z,X,{caseInsensitive:G??!1,glob:Q,multiline:_??!1},w)).matches,N="fallback",B={stdout:"",stderr:"",exitCode:0};else b=Vq(B.stdout,q);let R=b.length;if(F!==void 0&&F>0)b=b.slice(F);if(O!==void 0&&b.length>O)b=b.slice(0,O);let L={search_pattern:Z,search_path:X,output_mode:q,case_insensitive:G??!1,total_matches:b.length,original_total:R,offset:F,head_limit:O,strategy:N,exit_code:B?.exitCode};if(B&&B.exitCode!==0&&B.stderr)return{success:!1,llmContent:`Search execution failed: ${B.stderr}`,displayContent:`❌ 搜索执行失败: ${B.stderr}`,error:{type:"execution_error",message:B.stderr}};let A=Iq(L);return{success:!0,llmContent:b,displayContent:A,metadata:L}}catch(B){if(B.name==="AbortError")return{success:!1,llmContent:"Search aborted",displayContent:"⚠️ 搜索被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Search failed: ${B.message}`,displayContent:`❌ 搜索失败: ${B.message}`,error:{type:"execution_error",message:B.message,details:B}}}},version:"3.0.0",category:"搜索工具",tags:["search","grep","ripgrep","regex","text","fallback"],extractSignatureContent:($)=>$.pattern,abstractPermissionRule:()=>"*"})});var z5=D(()=>{W5();F5()});import{spawn as Mq}from"child_process";import{randomUUID as kq}from"crypto";class r1{static instance=null;processes=new Map;static getInstance(){if(!r1.instance)r1.instance=new r1;return r1.instance}startBackgroundProcess($){let Y=`bash_${kq()}`,Z={};for(let[J,q]of Object.entries({...process.env,...$.env,BLADE_CLI:"1"}))if(q!==void 0)Z[J]=q;let X=Mq("bash",["-c",$.command],{cwd:$.cwd||process.cwd(),env:Z,stdio:["ignore","pipe","pipe"]}),Q={id:Y,command:$.command,sessionId:$.sessionId,cwd:$.cwd,env:$.env,process:X,pid:X.pid,status:"running",startTime:Date.now(),pendingStdout:"",pendingStderr:""};return X.stdout?.setEncoding("utf8"),X.stderr?.setEncoding("utf8"),X.stdout?.on("data",(J)=>{Q.pendingStdout+=J.toString()}),X.stderr?.on("data",(J)=>{Q.pendingStderr+=J.toString()}),X.on("close",(J,q)=>{Q.status=Q.status==="killed"?"killed":"exited",Q.exitCode=J,Q.signal=q,Q.endTime=Date.now(),Q.process=void 0}),X.on("error",(J)=>{Q.status="error",Q.errorMessage=J.message,Q.endTime=Date.now(),Q.process=void 0,Q.pendingStderr+=`
679
+ [error] ${J.message}`}),this.processes.set(Y,Q),Q}consumeOutput($){let Y=this.processes.get($);if(!Y)return;let Z={id:Y.id,command:Y.command,status:Y.status,stdout:Y.pendingStdout,stderr:Y.pendingStderr,exitCode:Y.exitCode,signal:Y.signal,pid:Y.pid,startedAt:Y.startTime,endedAt:Y.endTime,errorMessage:Y.errorMessage};return Y.pendingStdout="",Y.pendingStderr="",Z}getProcess($){return this.processes.get($)}kill($){let Y=this.processes.get($);if(!Y)return;if(Y.status!=="running"||!Y.process)return{success:!1,alreadyExited:!0,status:Y.status,pid:Y.pid,exitCode:Y.exitCode,signal:Y.signal};if(!Y.process.kill("SIGTERM"))return{success:!1,alreadyExited:!1,status:Y.status,pid:Y.pid,exitCode:Y.exitCode,signal:Y.signal};return Y.status="killed",Y.endTime=Date.now(),Y.process=void 0,{success:!0,alreadyExited:!1,status:Y.status,pid:Y.pid,exitCode:Y.exitCode,signal:Y.signal}}killAll(){for(let[$,Y]of this.processes)if(Y.status==="running"&&Y.process)try{Y.process.kill("SIGTERM"),Y.status="killed",Y.endTime=Date.now(),Y.process=void 0}catch{}this.processes.clear()}}var X$=()=>{};import{spawn as jq}from"child_process";import{randomUUID as Eq}from"crypto";import{z as v8}from"zod";function vq($,Y,Z){let Q=r1.getInstance().startBackgroundProcess({command:$,sessionId:Eq(),cwd:Y||process.cwd(),env:Z}),q=`后台启动命令: ${$.length>30?`${$.substring(0,30)}...`:$}`,G={command:$,background:!0,pid:Q.pid,bash_id:Q.id,shell_id:Q.id,message:"命令已在后台启动",summary:q},K=`✅ 命令已在后台启动
669
680
  `+`\uD83C\uDD94 进程 ID: ${Q.pid}
670
681
  `+`\uD83D\uDCA1 Bash ID: ${Q.id}
671
- `+"⚠️ 使用 BashOutput/KillShell 管理后台进程";return{success:!0,llmContent:{command:$,background:!0,pid:Q.pid,bash_id:Q.id,shell_id:Q.id},displayContent:G,metadata:K}}async function Nq($,Y,Z,X,Q,J){let q=Date.now();try{let G=await M3().execute($,{cwd:Y||process.cwd(),env:Z,timeout:X,signal:Q,onOutput:(_)=>{J?.(_)}}),W=Date.now()-q;if(Q.aborted||G.error==="Command was aborted"||G.error==="Command was terminated")return{success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
672
- 输出: ${G.stdout}
673
- 错误: ${G.stderr}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:G.stdout,stderr:G.stderr,execution_time:W}};if(G.error==="Command timed out")return{success:!1,llmContent:`Command execution timed out (${X}ms)`,displayContent:`⏱️ 命令执行超时 (${X}ms)
674
- 输出: ${G.stdout}
675
- 错误: ${G.stderr}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:G.stdout,stderr:G.stderr,execution_time:W}};let U=$.length>30?`${$.substring(0,30)}...`:$,H=G.exitCode===0?`执行命令成功 (${W}ms): ${U}`:`执行命令完成 (退出码 ${G.exitCode}, ${W}ms): ${U}`,O={command:$,execution_time:W,exit_code:G.exitCode,stdout_length:G.stdout.length,stderr_length:G.stderr.length,has_stderr:G.stderr.length>0,acp_mode:!0,summary:H},z=J5({stdout:G.stdout,stderr:G.stderr,command:$,execution_time:W,exit_code:G.exitCode,signal:null});return{success:G.success,llmContent:{stdout:G.stdout.trim(),stderr:G.stderr.trim(),execution_time:W,exit_code:G.exitCode},displayContent:z,metadata:O}}catch(K){let G=Date.now()-q;return{success:!1,llmContent:`Command execution failed: ${K.message}`,displayContent:`❌ 命令执行失败: ${K.message}`,error:{type:"execution_error",message:K.message,details:K},metadata:{command:$,execution_time:G,error:K.message}}}}async function wq($,Y,Z,X,Q,J){return new Promise((q)=>{let K=Date.now(),G="",W="",U=!1,H=Fq("bash",["-c",$],{cwd:Y||process.cwd(),env:{...process.env,...Z,BLADE_CLI:"1"},stdio:["pipe","pipe","pipe"]});H.stdout.on("data",(_)=>{G+=_.toString()}),H.stderr.on("data",(_)=>{W+=_.toString()});let O=setTimeout(()=>{U=!0,H.kill("SIGTERM"),setTimeout(()=>{if(!H.killed)H.kill("SIGKILL")},1000)},X),z=()=>{H.kill("SIGTERM"),clearTimeout(O)};if(Q.addEventListener)Q.addEventListener("abort",z);else if("onabort"in Q)Q.onabort=z;H.on("close",(_,F)=>{if(clearTimeout(O),Q.removeEventListener)Q.removeEventListener("abort",z);else if("onabort"in Q)Q.onabort=null;let N=Date.now()-K;if(U){q({success:!1,llmContent:`Command execution timed out (${X}ms)`,displayContent:`⏱️ 命令执行超时 (${X}ms)
676
- 输出: ${G}
677
- 错误: ${W}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:G,stderr:W,execution_time:N}});return}if(Q.aborted){q({success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
678
- 输出: ${G}
679
- 错误: ${W}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:G,stderr:W,execution_time:N}});return}let w=$.length>30?`${$.substring(0,30)}...`:$,B=_===0?`执行命令成功 (${N}ms): ${w}`:`执行命令完成 (退出码 ${_}, ${N}ms): ${w}`,A={command:$,execution_time:N,exit_code:_,signal:F,stdout_length:G.length,stderr_length:W.length,has_stderr:W.length>0,summary:B},D=J5({stdout:G,stderr:W,command:$,execution_time:N,exit_code:_,signal:F});q({success:!0,llmContent:{stdout:G.trim(),stderr:W.trim(),execution_time:N,exit_code:_,signal:F},displayContent:D,metadata:A})}),H.on("error",(_)=>{if(clearTimeout(O),Q.removeEventListener)Q.removeEventListener("abort",z);else if("onabort"in Q)Q.onabort=null;q({success:!1,llmContent:`Command execution failed: ${_.message}`,displayContent:`❌ 命令执行失败: ${_.message}`,error:{type:"execution_error",message:_.message,details:_}})})})}function J5($){let{stdout:Y,stderr:Z,command:X,execution_time:Q,exit_code:J,signal:q}=$,K=`✅ Bash 命令执行完成: ${X}`;if(K+=`
680
- ⏱️ 执行时间: ${Q}ms`,K+=`
681
- \uD83D\uDCCA 退出码: ${J??"N/A"}`,q)K+=`
682
- ⚡ 信号: ${q}`;if(Y&&Y.trim())K+=`
682
+ `+"⚠️ 使用 BashOutput/KillShell 管理后台进程";return{success:!0,llmContent:{command:$,background:!0,pid:Q.pid,bash_id:Q.id,shell_id:Q.id},displayContent:K,metadata:G}}async function yq($,Y,Z,X,Q,J){let q=Date.now();try{let K=await C3().execute($,{cwd:Y||process.cwd(),env:Z,timeout:X,signal:Q,onOutput:(_)=>{J?.(_)}}),W=Date.now()-q;if(Q.aborted||K.error==="Command was aborted"||K.error==="Command was terminated")return{success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
683
+ 输出: ${K.stdout}
684
+ 错误: ${K.stderr}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:K.stdout,stderr:K.stderr,execution_time:W}};if(K.error==="Command timed out")return{success:!1,llmContent:`Command execution timed out (${X}ms)`,displayContent:`⏱️ 命令执行超时 (${X}ms)
685
+ 输出: ${K.stdout}
686
+ 错误: ${K.stderr}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:K.stdout,stderr:K.stderr,execution_time:W}};let U=$.length>30?`${$.substring(0,30)}...`:$,H=K.exitCode===0?`执行命令成功 (${W}ms): ${U}`:`执行命令完成 (退出码 ${K.exitCode}, ${W}ms): ${U}`,O={command:$,execution_time:W,exit_code:K.exitCode,stdout_length:K.stdout.length,stderr_length:K.stderr.length,has_stderr:K.stderr.length>0,acp_mode:!0,summary:H},F=_5({stdout:K.stdout,stderr:K.stderr,command:$,execution_time:W,exit_code:K.exitCode,signal:null});return{success:K.success,llmContent:{stdout:K.stdout.trim(),stderr:K.stderr.trim(),execution_time:W,exit_code:K.exitCode},displayContent:F,metadata:O}}catch(G){let K=Date.now()-q;return{success:!1,llmContent:`Command execution failed: ${G.message}`,displayContent:`❌ 命令执行失败: ${G.message}`,error:{type:"execution_error",message:G.message,details:G},metadata:{command:$,execution_time:K,error:G.message}}}}async function Pq($,Y,Z,X,Q,J){return new Promise((q)=>{let G=Date.now(),K="",W="",U=!1,H=jq("bash",["-c",$],{cwd:Y||process.cwd(),env:{...process.env,...Z,BLADE_CLI:"1"},stdio:["pipe","pipe","pipe"]});H.stdout.on("data",(_)=>{K+=_.toString()}),H.stderr.on("data",(_)=>{W+=_.toString()});let O=setTimeout(()=>{U=!0,H.kill("SIGTERM"),setTimeout(()=>{if(!H.killed)H.kill("SIGKILL")},1000)},X),F=()=>{H.kill("SIGTERM"),clearTimeout(O)};if(Q.addEventListener)Q.addEventListener("abort",F);else if("onabort"in Q)Q.onabort=F;H.on("close",(_,z)=>{if(clearTimeout(O),Q.removeEventListener)Q.removeEventListener("abort",F);else if("onabort"in Q)Q.onabort=null;let w=Date.now()-G;if(U){q({success:!1,llmContent:`Command execution timed out (${X}ms)`,displayContent:`⏱️ 命令执行超时 (${X}ms)
687
+ 输出: ${K}
688
+ 错误: ${W}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:K,stderr:W,execution_time:w}});return}if(Q.aborted){q({success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
689
+ 输出: ${K}
690
+ 错误: ${W}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:K,stderr:W,execution_time:w}});return}let B=$.length>30?`${$.substring(0,30)}...`:$,N=_===0?`执行命令成功 (${w}ms): ${B}`:`执行命令完成 (退出码 ${_}, ${w}ms): ${B}`,b={command:$,execution_time:w,exit_code:_,signal:z,stdout_length:K.length,stderr_length:W.length,has_stderr:W.length>0,summary:N},V=_5({stdout:K,stderr:W,command:$,execution_time:w,exit_code:_,signal:z});q({success:!0,llmContent:{stdout:K.trim(),stderr:W.trim(),execution_time:w,exit_code:_,signal:z},displayContent:V,metadata:b})}),H.on("error",(_)=>{if(clearTimeout(O),Q.removeEventListener)Q.removeEventListener("abort",F);else if("onabort"in Q)Q.onabort=null;q({success:!1,llmContent:`Command execution failed: ${_.message}`,displayContent:`❌ 命令执行失败: ${_.message}`,error:{type:"execution_error",message:_.message,details:_}})})})}function _5($){let{stdout:Y,stderr:Z,command:X,execution_time:Q,exit_code:J,signal:q}=$,G=`✅ Bash 命令执行完成: ${X}`;if(G+=`
691
+ ⏱️ 执行时间: ${Q}ms`,G+=`
692
+ \uD83D\uDCCA 退出码: ${J??"N/A"}`,q)G+=`
693
+ ⚡ 信号: ${q}`;if(Y&&Y.trim())G+=`
683
694
  \uD83D\uDCE4 输出:
684
- ${Y.trim()}`;if(Z&&Z.trim())K+=`
695
+ ${Y.trim()}`;if(Z&&Z.trim())G+=`
685
696
  ⚠️ 错误输出:
686
- ${Z.trim()}`;return K}var M8;var q5=R(()=>{s2();k1();h1();Z2();Y$();M8=e({name:"Bash",displayName:"Bash Command",kind:"execute",schema:D8.object({command:H1.command({description:"Bash command to execute"}),timeout:H1.timeout(1000,300000,30000),cwd:D8.string().optional().describe("Working directory (optional; applies only to this command). To persist, use cd"),env:H1.environment(),run_in_background:D8.boolean().default(!1).describe("Run in background (suitable for long-running commands)")}),description:{short:"Execute bash commands in a persistent shell session with optional timeout",long:`Executes bash commands with proper handling and security measures.
697
+ ${Z.trim()}`;return G}var y8;var N5=D(()=>{e2();j1();p1();J2();X$();y8=Y1({name:"Bash",displayName:"Bash Command",kind:"execute",schema:v8.object({command:O1.command({description:"Bash command to execute"}),timeout:O1.timeout(1000,300000,30000),cwd:v8.string().optional().describe("Working directory (optional; applies only to this command). To persist, use cd"),env:O1.environment(),run_in_background:v8.boolean().default(!1).describe("Run in background (suitable for long-running commands)")}),description:{short:"Execute bash commands in a persistent shell session with optional timeout",long:`Executes bash commands with proper handling and security measures.
687
698
 
688
699
  IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.
689
700
 
@@ -699,16 +710,16 @@ Before executing commands:
699
710
  * cd "/Users/name/My Documents" (correct)
700
711
  * cd /Users/name/My Documents (incorrect - will fail)
701
712
  * python "/path/with spaces/script.py" (correct)
702
- * python /path/with spaces/script.py (incorrect - will fail)`,usageNotes:["The command argument is required","You can specify an optional timeout in milliseconds (up to 600000ms / 10 minutes). If not specified, commands will timeout after 30000ms (30 seconds)","It is very helpful if you write a clear, concise description of what this command does in 5-10 words","If the output exceeds 30000 characters, output will be truncated before being returned to you",'You can use the run_in_background parameter to run the command in the background, which allows you to continue working while the command runs. You can monitor the output using the BashOutput tool. You do not need to use "&" at the end of the command when using this parameter',"Avoid using Bash with the find, grep, cat, head, tail, sed, awk, or echo commands, unless explicitly instructed or when these commands are truly necessary for the task. Instead, always prefer using the dedicated tools for these commands:"," - File search: Use Glob (NOT find or ls)"," - Content search: Use Grep (NOT grep or rg)"," - Read files: Use Read (NOT cat/head/tail)"," - Edit files: Use Edit (NOT sed/awk)"," - Write files: Use Write (NOT echo >/cat <<EOF)"," - Communication: Output text directly (NOT echo/printf)","When issuing multiple commands:",' - If the commands are independent and can run in parallel, make multiple Bash tool calls in a single message. For example, if you need to run "git status" and "git diff", send a single message with two Bash tool calls in parallel',' - If the commands depend on each other and must run sequentially, use a single Bash call with "&&" to chain them together (e.g., git add . && git commit -m "message" && git push). For instance, if one operation must complete before another starts (like mkdir before cp, Write before Bash for git operations, or git add before git commit), run these operations sequentially instead',` - Use ";" only when you need to run commands sequentially but don't care if earlier commands fail`," - DO NOT use newlines to separate commands (newlines are ok in quoted strings)","Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of cd. You may use cd if the User explicitly requests it"," Good example: pytest /foo/bar/tests"," Bad example: cd /foo/bar && pytest tests"],examples:[{description:"Run a simple command",params:{command:"ls -la",description:"List files in current directory"}},{description:"Temporarily change working directory (this command only)",params:{command:"npm install",cwd:"/path/to/project",description:"Install package dependencies"}},{description:"Persistently change working directory",params:{command:"cd /path/to/project && npm install",description:"Change directory and install dependencies"}},{description:"Run a long-running command in background",params:{command:"npm run dev",run_in_background:!0,description:"Start development server in background"}},{description:"Run multiple independent commands in parallel",params:{command:"git status",description:"Show working tree status"}}],important:["Committing changes with git:"," - Only create commits when requested by the user. If unclear, ask first"," - Git Safety Protocol:"," * NEVER update the git config"," * NEVER run destructive/irreversible git commands (like push --force, hard reset, etc) unless the user explicitly requests them"," * NEVER skip hooks (--no-verify, --no-gpg-sign, etc) unless the user explicitly requests it"," * NEVER run force push to main/master, warn the user if they request it"," * Avoid git commit --amend. ONLY use --amend when either (1) user explicitly requested amend OR (2) adding edits from pre-commit hook",' * Before amending: ALWAYS check authorship (git log -1 --format="%an %ae")'," * NEVER commit changes unless the user explicitly asks you to"," - When creating commits:"," 1. Run git status, git diff, and git log in parallel to understand changes",' 2. Analyze staged changes and draft a concise commit message (1-2 sentences) focusing on "why" rather than "what"'," 3. Add relevant untracked files, create the commit, and run git status to verify"," 4. Always pass commit message via HEREDOC format"," - DO NOT push to remote repository unless explicitly requested"," - NEVER use git commands with the -i flag (no interactive input supported)"," - If no changes to commit, do not create an empty commit","Creating pull requests:"," - Use the gh command for ALL GitHub-related tasks"," - When creating a PR:"," 1. Run git status, git diff, and git log in parallel to understand branch changes"," 2. Analyze all commits (not just the latest) and draft a PR summary"," 3. Create new branch if needed, push with -u flag, and create PR using gh pr create with HEREDOC body format"," - Return the PR URL when done","Other important notes:"," - Dangerous commands (rm -rf, sudo, etc.) require user confirmation"," - Background commands require manual termination using KillShell"," - NEVER use find, grep, cat, sed, etc. — use dedicated tools instead"]},async execute($,Y){let{command:Z,timeout:X=30000,cwd:Q,env:J,run_in_background:q=!1}=$,{updateOutput:K}=Y,G=Y.signal??new AbortController().signal;try{if(K?.(`Executing Bash command: ${Z}`),q)return Bq(Z,Q,J);if(Y2())return K?.("通过 IDE 终端执行命令..."),Nq(Z,Q,J,X,G,K);else return wq(Z,Q,J,X,G,K)}catch(W){let U=W;if(U.name==="AbortError")return{success:!1,llmContent:"Command execution aborted",displayContent:"⚠️ 命令执行被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`Command execution failed: ${U.message}`,displayContent:`❌ 命令执行失败: ${U.message}`,error:{type:"execution_error",message:U.message,details:U}}}},version:"2.0.0",category:"命令工具",tags:["bash","shell","non-interactive","event-driven"],extractSignatureContent:($)=>{return $.command.trim()},abstractPermissionRule:($)=>{let Z=$.command.trim().split(/\s+/);if(Z.length===1)return Z[0];if(["run","exec","test","start","build","dev"].includes(Z[1])){if(Z.length===2)return`${Z[0]} ${Z[1]}`;return`${Z[0]} ${Z[1]} *`}if(Z.length===2)return`${Z[0]} ${Z[1]}`;return`${Z[0]} ${Z[1]} *`}})});import{z as I8}from"zod";function Lq($,Y){let Z=K5($.stdout).filter((Q)=>{if(!Y)return!0;return Y.lastIndex=0,Y.test(Q)}),X=K5($.stderr).filter((Q)=>{if(!Y)return!0;return Y.lastIndex=0,Y.test(Q)});return{stdoutLines:Z,stderrLines:X}}function K5($){if(!$)return[];return $.replace(/\r\n/g,`
713
+ * python /path/with spaces/script.py (incorrect - will fail)`,usageNotes:["The command argument is required","You can specify an optional timeout in milliseconds (up to 600000ms / 10 minutes). If not specified, commands will timeout after 30000ms (30 seconds)","It is very helpful if you write a clear, concise description of what this command does in 5-10 words","If the output exceeds 30000 characters, output will be truncated before being returned to you",'You can use the run_in_background parameter to run the command in the background, which allows you to continue working while the command runs. You can monitor the output using the BashOutput tool. You do not need to use "&" at the end of the command when using this parameter',"Avoid using Bash with the find, grep, cat, head, tail, sed, awk, or echo commands, unless explicitly instructed or when these commands are truly necessary for the task. Instead, always prefer using the dedicated tools for these commands:"," - File search: Use Glob (NOT find or ls)"," - Content search: Use Grep (NOT grep or rg)"," - Read files: Use Read (NOT cat/head/tail)"," - Edit files: Use Edit (NOT sed/awk)"," - Write files: Use Write (NOT echo >/cat <<EOF)"," - Communication: Output text directly (NOT echo/printf)","When issuing multiple commands:",' - If the commands are independent and can run in parallel, make multiple Bash tool calls in a single message. For example, if you need to run "git status" and "git diff", send a single message with two Bash tool calls in parallel',' - If the commands depend on each other and must run sequentially, use a single Bash call with "&&" to chain them together (e.g., git add . && git commit -m "message" && git push). For instance, if one operation must complete before another starts (like mkdir before cp, Write before Bash for git operations, or git add before git commit), run these operations sequentially instead',` - Use ";" only when you need to run commands sequentially but don't care if earlier commands fail`," - DO NOT use newlines to separate commands (newlines are ok in quoted strings)","Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of cd. You may use cd if the User explicitly requests it"," Good example: pytest /foo/bar/tests"," Bad example: cd /foo/bar && pytest tests"],examples:[{description:"Run a simple command",params:{command:"ls -la",description:"List files in current directory"}},{description:"Temporarily change working directory (this command only)",params:{command:"npm install",cwd:"/path/to/project",description:"Install package dependencies"}},{description:"Persistently change working directory",params:{command:"cd /path/to/project && npm install",description:"Change directory and install dependencies"}},{description:"Run a long-running command in background",params:{command:"npm run dev",run_in_background:!0,description:"Start development server in background"}},{description:"Run multiple independent commands in parallel",params:{command:"git status",description:"Show working tree status"}}],important:["Committing changes with git:"," - Only create commits when requested by the user. If unclear, ask first"," - Git Safety Protocol:"," * NEVER update the git config"," * NEVER run destructive/irreversible git commands (like push --force, hard reset, etc) unless the user explicitly requests them"," * NEVER skip hooks (--no-verify, --no-gpg-sign, etc) unless the user explicitly requests it"," * NEVER run force push to main/master, warn the user if they request it"," * Avoid git commit --amend. ONLY use --amend when either (1) user explicitly requested amend OR (2) adding edits from pre-commit hook",' * Before amending: ALWAYS check authorship (git log -1 --format="%an %ae")'," * NEVER commit changes unless the user explicitly asks you to"," - When creating commits:"," 1. Run git status, git diff, and git log in parallel to understand changes",' 2. Analyze staged changes and draft a concise commit message (1-2 sentences) focusing on "why" rather than "what"'," 3. Add relevant untracked files, create the commit, and run git status to verify"," 4. Always pass commit message via HEREDOC format"," - DO NOT push to remote repository unless explicitly requested"," - NEVER use git commands with the -i flag (no interactive input supported)"," - If no changes to commit, do not create an empty commit","Creating pull requests:"," - Use the gh command for ALL GitHub-related tasks"," - When creating a PR:"," 1. Run git status, git diff, and git log in parallel to understand branch changes"," 2. Analyze all commits (not just the latest) and draft a PR summary"," 3. Create new branch if needed, push with -u flag, and create PR using gh pr create with HEREDOC body format"," - Return the PR URL when done","Other important notes:"," - Dangerous commands (rm -rf, sudo, etc.) require user confirmation"," - Background commands require manual termination using KillShell"," - NEVER use find, grep, cat, sed, etc. — use dedicated tools instead"]},async execute($,Y){let{command:Z,timeout:X=30000,cwd:Q,env:J,run_in_background:q=!1}=$,{updateOutput:G}=Y,K=Y.signal??new AbortController().signal;try{if(G?.(`Executing Bash command: ${Z}`),q)return vq(Z,Q,J);if(Q2())return G?.("通过 IDE 终端执行命令..."),yq(Z,Q,J,X,K,G);else return Pq(Z,Q,J,X,K,G)}catch(W){let U=W;if(U.name==="AbortError")return{success:!1,llmContent:"Command execution aborted",displayContent:"⚠️ 命令执行被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`Command execution failed: ${U.message}`,displayContent:`❌ 命令执行失败: ${U.message}`,error:{type:"execution_error",message:U.message,details:U}}}},version:"2.0.0",category:"命令工具",tags:["bash","shell","non-interactive","event-driven"],extractSignatureContent:($)=>{return $.command.trim()},abstractPermissionRule:($)=>{let Z=$.command.trim().split(/\s+/);if(Z.length===1)return Z[0];if(["run","exec","test","start","build","dev"].includes(Z[1])){if(Z.length===2)return`${Z[0]} ${Z[1]}`;return`${Z[0]} ${Z[1]} *`}if(Z.length===2)return`${Z[0]} ${Z[1]}`;return`${Z[0]} ${Z[1]} *`}})});import{z as P8}from"zod";function Tq($,Y){let Z=B5($.stdout).filter((Q)=>{if(!Y)return!0;return Y.lastIndex=0,Y.test(Q)}),X=B5($.stderr).filter((Q)=>{if(!Y)return!0;return Y.lastIndex=0,Y.test(Q)});return{stdoutLines:Z,stderrLines:X}}function B5($){if(!$)return[];return $.replace(/\r\n/g,`
703
714
  `).split(`
704
- `)}function Aq($,Y,Z){let Q=`${$.status==="running"?"⏳":$.status==="exited"?"✅":$.status==="killed"?"✂️":"⚠️"} BashOutput(${$.id}) - 状态: ${$.status}`;if(Q+=`
715
+ `)}function Sq($,Y,Z){let Q=`${$.status==="running"?"⏳":$.status==="exited"?"✅":$.status==="killed"?"✂️":"⚠️"} BashOutput(${$.id}) - 状态: ${$.status}`;if(Q+=`
705
716
  命令: ${$.command}`,$.pid)Q+=`
706
717
  PID: ${$.pid}`;if($.exitCode!==void 0&&$.exitCode!==null)Q+=`
707
718
  退出码: ${$.exitCode}`;if($.signal)Q+=`
708
719
  信号: ${$.signal}`;if(Y===0&&Z===0)Q+=`
709
720
  无新的输出`;else Q+=`
710
721
  stdout 行数: ${Y}`,Q+=`
711
- stderr 行数: ${Z}`;return Q}var k8;var G5=R(()=>{k1();h1();Y$();k8=e({name:"BashOutput",displayName:"后台命令输出",kind:"readonly",schema:I8.object({bash_id:I8.string().min(1).describe("Background bash session ID"),filter:I8.string().optional().describe("Optional regex filter: only return matching lines; non-matching lines are discarded")}),description:{short:"Retrieves output from a running or completed background bash shell",long:`
722
+ stderr 行数: ${Z}`;return Q}var T8;var w5=D(()=>{j1();p1();X$();T8=Y1({name:"BashOutput",displayName:"后台命令输出",kind:"readonly",schema:P8.object({bash_id:P8.string().min(1).describe("Background bash session ID"),filter:P8.string().optional().describe("Optional regex filter: only return matching lines; non-matching lines are discarded")}),description:{short:"Retrieves output from a running or completed background bash shell",long:`
712
723
  - Retrieves output from a running or completed background bash shell
713
724
  - Takes a shell_id parameter identifying the shell
714
725
  - Always returns only new output since the last check
@@ -716,17 +727,17 @@ stderr 行数: ${Z}`;return Q}var k8;var G5=R(()=>{k1();h1();Y$();k8=e({name:"Ba
716
727
  - Supports optional regex filtering to show only lines matching a pattern
717
728
  - Use this tool when you need to monitor or check the output of a long-running shell
718
729
  - Shell IDs can be found using the /tasks command
719
- `},async execute($,Y){let Z=i1.getInstance(),X;if($.filter)try{X=new RegExp($.filter)}catch(W){return{success:!1,llmContent:`Invalid regular expression: ${$.filter}
730
+ `},async execute($,Y){let Z=r1.getInstance(),X;if($.filter)try{X=new RegExp($.filter)}catch(W){return{success:!1,llmContent:`Invalid regular expression: ${$.filter}
720
731
 
721
732
  \uD83D\uDCA1 Output was not consumed; you can retry`,displayContent:`❌ 无效的正则表达式: ${$.filter}
722
733
 
723
- \uD83D\uDCA1 输出未被消费,可重新尝试`,error:{type:"validation_error",message:W.message}}}let Q=Z.consumeOutput($.bash_id);if(!Q)return{success:!1,llmContent:`Bash session not found: ${$.bash_id}`,displayContent:`❌ 未找到 Bash 会话: ${$.bash_id}`,error:{type:"execution_error",message:"Bash 会话不存在或已清理"}};let{stdoutLines:J,stderrLines:q}=Lq(Q,X),K={bash_id:Q.id,status:Q.status,command:Q.command,pid:Q.pid,exit_code:Q.exitCode,signal:Q.signal,started_at:new Date(Q.startedAt).toISOString(),finished_at:Q.endedAt?new Date(Q.endedAt).toISOString():void 0,stdout:J,stderr:q},G=Aq(Q,J.length,q.length);return{success:!0,llmContent:K,displayContent:G,metadata:K}},version:"1.0.0",category:"命令工具",tags:["bash","shell","monitor"],extractSignatureContent:($)=>$.bash_id,abstractPermissionRule:()=>"*"})});import{z as W5}from"zod";var j8;var U5=R(()=>{k1();h1();Y$();j8=e({name:"KillShell",displayName:"终止后台 Shell",kind:"execute",schema:W5.object({shell_id:W5.string().min(1).describe("Background Shell ID to terminate")}),description:{short:"Kills a running background bash shell by its ID",long:`
734
+ \uD83D\uDCA1 输出未被消费,可重新尝试`,error:{type:"validation_error",message:W.message}}}let Q=Z.consumeOutput($.bash_id);if(!Q)return{success:!1,llmContent:`Bash session not found: ${$.bash_id}`,displayContent:`❌ 未找到 Bash 会话: ${$.bash_id}`,error:{type:"execution_error",message:"Bash 会话不存在或已清理"}};let{stdoutLines:J,stderrLines:q}=Tq(Q,X),G={bash_id:Q.id,status:Q.status,command:Q.command,pid:Q.pid,exit_code:Q.exitCode,signal:Q.signal,started_at:new Date(Q.startedAt).toISOString(),finished_at:Q.endedAt?new Date(Q.endedAt).toISOString():void 0,stdout:J,stderr:q},K=Sq(Q,J.length,q.length);return{success:!0,llmContent:G,displayContent:K,metadata:G}},version:"1.0.0",category:"命令工具",tags:["bash","shell","monitor"],extractSignatureContent:($)=>$.bash_id,abstractPermissionRule:()=>"*"})});import{z as L5}from"zod";var S8;var A5=D(()=>{j1();p1();X$();S8=Y1({name:"KillShell",displayName:"终止后台 Shell",kind:"execute",schema:L5.object({shell_id:L5.string().min(1).describe("Background Shell ID to terminate")}),description:{short:"Kills a running background bash shell by its ID",long:`
724
735
  - Kills a running background bash shell by its ID
725
736
  - Takes a shell_id parameter identifying the shell to kill
726
737
  - Returns a success or failure status
727
738
  - Use this tool when you need to terminate a long-running shell
728
739
  - Shell IDs can be found using the /tasks command
729
- `},async execute($,Y){let X=i1.getInstance().kill($.shell_id);if(!X)return{success:!1,llmContent:`Shell not found: ${$.shell_id}`,displayContent:`❌ 未找到 Shell: ${$.shell_id}`,error:{type:"execution_error",message:"Shell ID 不存在或已清理"}};if(!X.success&&!X.alreadyExited)return{success:!1,llmContent:`Failed to terminate Shell: ${$.shell_id}`,displayContent:`❌ 无法终止 Shell (${$.shell_id})`,error:{type:"execution_error",message:"发送终止信号失败"},metadata:X};let Q=X.alreadyExited?`Shell ${$.shell_id} 已经处于 ${X.status} 状态`:`已向 Shell ${$.shell_id} 发送终止信号`;return{success:!0,llmContent:{shell_id:$.shell_id,status:X.status,already_exited:X.alreadyExited,pid:X.pid,exit_code:X.exitCode,signal:X.signal},displayContent:X.alreadyExited?`ℹ️ ${Q}`:`✂️ ${Q}`,metadata:X}},version:"1.0.0",category:"命令工具",tags:["bash","shell","terminate"],extractSignatureContent:($)=>$.shell_id,abstractPermissionRule:()=>"*"})});var H5=R(()=>{Y$();q5();G5();U5()});import{z as O5}from"zod";var E8;var z5=R(()=>{k1();y0();E8=e({name:"Skill",displayName:"Skill",kind:"execute",schema:O5.object({skill:O5.string().describe('The skill name (no arguments). E.g., "pdf" or "xlsx"')}),description:{short:"Execute a skill within the main conversation",long:`Execute a skill within the main conversation
740
+ `},async execute($,Y){let X=r1.getInstance().kill($.shell_id);if(!X)return{success:!1,llmContent:`Shell not found: ${$.shell_id}`,displayContent:`❌ 未找到 Shell: ${$.shell_id}`,error:{type:"execution_error",message:"Shell ID 不存在或已清理"}};if(!X.success&&!X.alreadyExited)return{success:!1,llmContent:`Failed to terminate Shell: ${$.shell_id}`,displayContent:`❌ 无法终止 Shell (${$.shell_id})`,error:{type:"execution_error",message:"发送终止信号失败"},metadata:X};let Q=X.alreadyExited?`Shell ${$.shell_id} 已经处于 ${X.status} 状态`:`已向 Shell ${$.shell_id} 发送终止信号`;return{success:!0,llmContent:{shell_id:$.shell_id,status:X.status,already_exited:X.alreadyExited,pid:X.pid,exit_code:X.exitCode,signal:X.signal},displayContent:X.alreadyExited?`ℹ️ ${Q}`:`✂️ ${Q}`,metadata:X}},version:"1.0.0",category:"命令工具",tags:["bash","shell","terminate"],extractSignatureContent:($)=>$.shell_id,abstractPermissionRule:()=>"*"})});var b5=D(()=>{X$();N5();w5();A5()});import{z as R5}from"zod";var C8;var V5=D(()=>{j1();y0();C8=Y1({name:"Skill",displayName:"Skill",kind:"execute",schema:R5.object({skill:R5.string().describe('The skill name (no arguments). E.g., "pdf" or "xlsx"')}),description:{short:"Execute a skill within the main conversation",long:`Execute a skill within the main conversation
730
741
 
731
742
  <skills_instructions>
732
743
  When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
@@ -749,7 +760,7 @@ Important:
749
760
  <available_skills>
750
761
 
751
762
  </available_skills>
752
- `},async execute($,Y){let{skill:Z}=$;return{success:!1,llmContent:`Skill system not yet implemented. The skill "${Z}" could not be executed.`,displayContent:"Skill system not available",error:{type:"execution_error",message:"Skill handler not configured"}}}})});import{z as F5}from"zod";var y8;var _5=R(()=>{k1();y0();y8=e({name:"SlashCommand",displayName:"Slash Command",kind:"execute",schema:F5.object({command:F5.string().describe('The slash command to execute with its arguments, e.g., "/review-pr 123"')}),description:{short:"Execute a slash command within the main conversation",long:`Execute a slash command within the main conversation
763
+ `},async execute($,Y){let{skill:Z}=$;return{success:!1,llmContent:`Skill system not yet implemented. The skill "${Z}" could not be executed.`,displayContent:"Skill system not available",error:{type:"execution_error",message:"Skill handler not configured"}}}})});import{z as D5}from"zod";var f8;var I5=D(()=>{j1();y0();f8=Y1({name:"SlashCommand",displayName:"Slash Command",kind:"execute",schema:D5.object({command:D5.string().describe('The slash command to execute with its arguments, e.g., "/review-pr 123"')}),description:{short:"Execute a slash command within the main conversation",long:`Execute a slash command within the main conversation
753
764
 
754
765
  How slash commands work:
755
766
  When you use this tool or when a user types a slash command, you will see <command-message>{name} is running...</command-message> followed by the expanded prompt. For example, if .claude/commands/foo.md contains "Print today's date", then /foo expands to that prompt in the next message.
@@ -767,9 +778,9 @@ Notes:
767
778
  - When a user requests multiple slash commands, execute each one sequentially and check for <command-message>{name} is running...</command-message> to verify each has been processed
768
779
  - Do not invoke a command that is already running. For example, if you see <command-message>foo is running...</command-message>, do NOT use this tool with "/foo" - process the expanded prompt in the following message
769
780
  - Only custom slash commands with descriptions are listed in Available Commands. If a user's command is not listed, ask them to check the slash command file and consult the docs.
770
- `},async execute($,Y){let{command:Z}=$;return{success:!1,llmContent:`Slash command system not yet implemented. The command "${Z}" could not be executed.`,displayContent:"Slash command system not available",error:{type:"execution_error",message:"Slash command handler not configured"}}}})});var B5=R(()=>{z5();_5()});class v8{config;constructor($){this.config=$}async execute($){let Y=Date.now();try{let Z=this.buildSystemPrompt($),X=await E1.create({systemPrompt:Z,toolWhitelist:this.config.tools}),Q=[{role:"user",content:$.prompt}],J="",q=0,K=0,G=await X.runAgenticLoop($.prompt,{messages:[],userId:"subagent",sessionId:$.parentSessionId||`subagent_${Date.now()}`,workspaceRoot:process.cwd(),permissionMode:$.permissionMode});if(G.success)J=G.finalMessage||"",q=G.metadata?.toolCallsCount||0,K=G.metadata?.tokensUsed||0;else throw Error(G.error?.message||"Subagent execution failed");let W=Date.now()-Y;return{success:!0,message:J,stats:{tokens:K,toolCalls:q,duration:W}}}catch(Z){let X=Date.now()-Y;return{success:!1,message:"",error:Z instanceof Error?Z.message:String(Z),stats:{duration:X}}}}buildSystemPrompt($){return this.config.systemPrompt||""}}var N5=R(()=>{J2()});import P8 from"node:fs";import Rq from"node:path";import bq from"yaml";class w5{subagents=new Map;register($){if(this.subagents.has($.name))throw Error(`Subagent '${$.name}' already registered`);this.subagents.set($.name,$)}getSubagent($){return this.subagents.get($)}getAllNames(){return Array.from(this.subagents.keys())}getAllSubagents(){return Array.from(this.subagents.values())}getDescriptionsForPrompt(){let $=this.getAllSubagents();if($.length===0)return"No subagents available.";return`Available subagent types and the tools they have access to:
781
+ `},async execute($,Y){let{command:Z}=$;return{success:!1,llmContent:`Slash command system not yet implemented. The command "${Z}" could not be executed.`,displayContent:"Slash command system not available",error:{type:"execution_error",message:"Slash command handler not configured"}}}})});var M5=D(()=>{V5();I5()});class h8{config;constructor($){this.config=$}async execute($){let Y=Date.now();try{let Z=this.buildSystemPrompt($),X=await v1.create({systemPrompt:Z,toolWhitelist:this.config.tools}),Q=[{role:"user",content:$.prompt}],J="",q=0,G=0,K=await X.runAgenticLoop($.prompt,{messages:[],userId:"subagent",sessionId:$.parentSessionId||`subagent_${Date.now()}`,workspaceRoot:process.cwd(),permissionMode:$.permissionMode});if(K.success)J=K.finalMessage||"",q=K.metadata?.toolCallsCount||0,G=K.metadata?.tokensUsed||0;else throw Error(K.error?.message||"Subagent execution failed");let W=Date.now()-Y;return{success:!0,message:J,stats:{tokens:G,toolCalls:q,duration:W}}}catch(Z){let X=Date.now()-Y;return{success:!1,message:"",error:Z instanceof Error?Z.message:String(Z),stats:{duration:X}}}}buildSystemPrompt($){return this.config.systemPrompt||""}}var k5=D(()=>{K2()});import x8 from"node:fs";import Cq from"node:path";import fq from"yaml";class j5{subagents=new Map;register($){if(this.subagents.has($.name))throw Error(`Subagent '${$.name}' already registered`);this.subagents.set($.name,$)}getSubagent($){return this.subagents.get($)}getAllNames(){return Array.from(this.subagents.keys())}getAllSubagents(){return Array.from(this.subagents.values())}getDescriptionsForPrompt(){let $=this.getAllSubagents();if($.length===0)return"No subagents available.";return`Available subagent types and the tools they have access to:
771
782
  ${$.map((Z)=>{let X=`- ${Z.name}: ${Z.description}`;if(Z.tools&&Z.tools.length>0)X+=` (Tools: ${Z.tools.join(", ")})`;return X}).join(`
772
- `)}`}loadFromDirectory($){if(!P8.existsSync($))return;let Y=P8.readdirSync($);for(let Z of Y){if(!Z.endsWith(".md"))continue;let X=Rq.join($,Z);try{let Q=this.parseConfigFile(X);this.register(Q)}catch(Q){Vq.warn(`Failed to load subagent config from ${X}:`,Q)}}}parseConfigFile($){let Z=P8.readFileSync($,"utf-8").match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!Z)throw Error(`No YAML frontmatter found in ${$}`);let[,X,Q]=Z,J=bq.parse(X);if(!J.name||!J.description)throw Error(`Missing required fields (name, description) in ${$}`);let q=Q.trim();return{name:J.name,description:J.description,systemPrompt:q,tools:J.tools,configPath:$}}loadFromStandardLocations(){let $=S1("node:os"),Y=S1("node:path"),Z=Y.join($.homedir(),".blade","agents");this.loadFromDirectory(Z);let X=Y.join(process.cwd(),".blade","agents");return this.loadFromDirectory(X),this.getAllNames().length}clear(){this.subagents.clear()}}var Vq,M1;var Z$=R(()=>{N1();Vq=u("Agent");M1=new w5});import{z as f6}from"zod";function Dq(){let $=M1.getAllNames();if($.length===0)return["Explore"];return $}var T8;var L5=R(()=>{N5();Z$();k1();h1();T8=e({name:"Task",displayName:"Subagent Scheduler",kind:"readonly",isReadOnly:!0,schema:f6.object({subagent_type:f6.enum(Dq()).describe('Subagent type to use (e.g., "Explore", "Plan")'),description:f6.string().min(3).max(100).describe("Short task description (3-5 words)"),prompt:f6.string().min(10).describe("Detailed task instructions")}),description:{short:"Launch a specialized agent to handle complex, multi-step tasks autonomously",long:`
783
+ `)}`}loadFromDirectory($){if(!x8.existsSync($))return;let Y=x8.readdirSync($);for(let Z of Y){if(!Z.endsWith(".md"))continue;let X=Cq.join($,Z);try{let Q=this.parseConfigFile(X);this.register(Q)}catch(Q){hq.warn(`Failed to load subagent config from ${X}:`,Q)}}}parseConfigFile($){let Z=x8.readFileSync($,"utf-8").match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!Z)throw Error(`No YAML frontmatter found in ${$}`);let[,X,Q]=Z,J=fq.parse(X);if(!J.name||!J.description)throw Error(`Missing required fields (name, description) in ${$}`);let q=Q.trim();return{name:J.name,description:J.description,systemPrompt:q,tools:J.tools,configPath:$}}loadFromStandardLocations(){let $=C1("node:os"),Y=C1("node:path"),Z=Y.join($.homedir(),".blade","agents");this.loadFromDirectory(Z);let X=Y.join(process.cwd(),".blade","agents");return this.loadFromDirectory(X),this.getAllNames().length}clear(){this.subagents.clear()}}var hq,M1;var Q$=D(()=>{B1();hq=l("Agent");M1=new j5});import{z as d6}from"zod";function xq(){let $=M1.getAllNames();if($.length===0)return["Explore"];return $}var p8;var E5=D(()=>{k5();Q$();j1();p1();p8=Y1({name:"Task",displayName:"Subagent Scheduler",kind:"readonly",isReadOnly:!0,schema:d6.object({subagent_type:d6.enum(xq()).describe('Subagent type to use (e.g., "Explore", "Plan")'),description:d6.string().min(3).max(100).describe("Short task description (3-5 words)"),prompt:d6.string().min(10).describe("Detailed task instructions")}),description:{short:"Launch a specialized agent to handle complex, multi-step tasks autonomously",long:`
773
784
  Launch a specialized agent to handle complex, multi-step tasks autonomously.
774
785
 
775
786
  The Task tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
@@ -795,9 +806,9 @@ ${M1.getDescriptionsForPrompt()}
795
806
  - Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent
796
807
  - If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.
797
808
  - If the user specifies that they want you to run agents "in parallel", you MUST send a single message with multiple Task tool use content blocks.
798
- `.trim(),usageNotes:["subagent_type is required - choose from available agent types",'description should be 3-5 words (e.g., "Explore error handling")',"prompt should contain a highly detailed task description and specify exactly what information to return","Launch multiple agents concurrently when possible for better performance"],examples:[{description:"Explore codebase for API endpoints",params:{subagent_type:"Explore",description:"Find API endpoints",prompt:"Search the codebase for all API endpoint definitions. Look for route handlers, REST endpoints, and GraphQL resolvers. Return a structured list with file paths, endpoint URLs, HTTP methods, and descriptions."}},{description:"Plan authentication feature",params:{subagent_type:"Plan",description:"Plan user auth",prompt:"Create a detailed implementation plan for adding user authentication to this project. Analyze the existing architecture, then provide step-by-step instructions including: 1) Database schema changes 2) API routes to create 3) Frontend components needed 4) Security considerations 5) Testing strategy. Be specific about file names and code locations."}}]},async execute($,Y){let{subagent_type:Z,description:X,prompt:Q}=$,{updateOutput:J}=Y;try{let q=M1.getAllNames();console.log(`[Task] subagentRegistry 状态: registered=${q.length}, names=[${q.join(", ")}], looking for="${Z}"`);let K=M1.getSubagent(Z);if(!K)return{success:!1,llmContent:`Unknown subagent type: ${Z}. Available types: ${q.join(", ")||"none"}`,displayContent:`❌ 未知的 subagent 类型: ${Z}
809
+ `.trim(),usageNotes:["subagent_type is required - choose from available agent types",'description should be 3-5 words (e.g., "Explore error handling")',"prompt should contain a highly detailed task description and specify exactly what information to return","Launch multiple agents concurrently when possible for better performance"],examples:[{description:"Explore codebase for API endpoints",params:{subagent_type:"Explore",description:"Find API endpoints",prompt:"Search the codebase for all API endpoint definitions. Look for route handlers, REST endpoints, and GraphQL resolvers. Return a structured list with file paths, endpoint URLs, HTTP methods, and descriptions."}},{description:"Plan authentication feature",params:{subagent_type:"Plan",description:"Plan user auth",prompt:"Create a detailed implementation plan for adding user authentication to this project. Analyze the existing architecture, then provide step-by-step instructions including: 1) Database schema changes 2) API routes to create 3) Frontend components needed 4) Security considerations 5) Testing strategy. Be specific about file names and code locations."}}]},async execute($,Y){let{subagent_type:Z,description:X,prompt:Q}=$,{updateOutput:J}=Y;try{let q=M1.getAllNames();console.log(`[Task] subagentRegistry 状态: registered=${q.length}, names=[${q.join(", ")}], looking for="${Z}"`);let G=M1.getSubagent(Z);if(!G)return{success:!1,llmContent:`Unknown subagent type: ${Z}. Available types: ${q.join(", ")||"none"}`,displayContent:`❌ 未知的 subagent 类型: ${Z}
799
810
 
800
- 可用类型: ${q.join(", ")||"无"}`,error:{type:"execution_error",message:`Unknown subagent type: ${Z}`}};J?.(`\uD83D\uDE80 启动 ${Z} subagent: ${X}`);let G=new v8(K),W={prompt:Q,parentSessionId:Y.sessionId,permissionMode:Y.permissionMode};J?.("⚙️ 执行任务中...");let U=Date.now(),H=await G.execute(W),O=Date.now()-U;if(H.success){let z=H.message.length>1000?H.message.slice(0,1000)+`
811
+ 可用类型: ${q.join(", ")||"无"}`,error:{type:"execution_error",message:`Unknown subagent type: ${Z}`}};J?.(`\uD83D\uDE80 启动 ${Z} subagent: ${X}`);let K=new h8(G),W={prompt:Q,parentSessionId:Y.sessionId,permissionMode:Y.permissionMode};J?.("⚙️ 执行任务中...");let U=Date.now(),H=await K.execute(W),O=Date.now()-U;if(H.success){let F=H.message.length>1000?H.message.slice(0,1000)+`
801
812
  ...(截断)`:H.message;return{success:!0,llmContent:H.message,displayContent:`✅ Subagent 任务完成
802
813
 
803
814
  `+`类型: ${Z}
@@ -807,16 +818,16 @@ ${M1.getDescriptionsForPrompt()}
807
818
  `+`Token: ${H.stats?.tokens||0}
808
819
 
809
820
  `+`结果:
810
- ${z}`,metadata:{subagent_type:Z,description:X,duration:O,stats:H.stats}}}else return{success:!1,llmContent:`Subagent execution failed: ${H.error}`,displayContent:`⚠️ Subagent 任务失败
821
+ ${F}`,metadata:{subagent_type:Z,description:X,duration:O,stats:H.stats}}}else return{success:!1,llmContent:`Subagent execution failed: ${H.error}`,displayContent:`⚠️ Subagent 任务失败
811
822
 
812
823
  `+`类型: ${Z}
813
824
  `+`任务: ${X}
814
825
  `+`耗时: ${O}ms
815
- `+`错误: ${H.error}`,error:{type:"execution_error",message:H.error||"Unknown error"}}}catch(q){let K=q;return{success:!1,llmContent:`Subagent execution error: ${K.message}`,displayContent:`❌ Subagent 执行异常
826
+ `+`错误: ${H.error}`,error:{type:"execution_error",message:H.error||"Unknown error"}}}catch(q){let G=q;return{success:!1,llmContent:`Subagent execution error: ${G.message}`,displayContent:`❌ Subagent 执行异常
816
827
 
817
- ${K.message}
828
+ ${G.message}
818
829
 
819
- ${K.stack||""}`,error:{type:"execution_error",message:K.message,details:q}}}},version:"4.0.0",category:"Subagent",tags:["task","subagent","delegation","explore","plan"],extractSignatureContent:($)=>`${$.subagent_type}:${$.description}`,abstractPermissionRule:()=>""})});var A5=R(()=>{L5()});import{randomUUID as Mq}from"crypto";import*as X$ from"fs/promises";import*as h6 from"path";var q2;var S8=R(()=>{q2=class q2{static instances=new Map;todos=[];filePath;loaded=!1;constructor($,Y){this.filePath=h6.join(Y,"todos",`${$}-agent-${$}.json`)}static getInstance($,Y){let Z=`${$}-${Y}`;if(!q2.instances.has(Z))q2.instances.set(Z,new q2($,Y));return q2.instances.get(Z)}validate($){if($.filter((Z)=>Z.status==="in_progress").length>1)return{valid:!1,error:"同时只能有一个任务处于 in_progress 状态"};return{valid:!0}}async updateTodos($){await this.ensureLoaded();let Y=new Date().toISOString(),Z=$.map((Q)=>{let J=Q,q=this.todos.find((K)=>K.id===J.id||K.content===Q.content);return{...Q,id:J.id||q?.id||Mq(),priority:Q.priority||q?.priority||"medium",createdAt:q?.createdAt||Y,startedAt:Q.status==="in_progress"&&!q?.startedAt?Y:q?.startedAt,completedAt:Q.status==="completed"&&!q?.completedAt?Y:q?.completedAt}}),X=this.validate(Z);if(!X.valid)throw Error(X.error);this.todos=Z,await this.saveTodos()}getSortedTodos(){let $={completed:0,in_progress:1,pending:2},Y={high:0,medium:1,low:2};return[...this.todos].sort((Z,X)=>{let Q=$[Z.status]-$[X.status];if(Q!==0)return Q;return Y[Z.priority]-Y[X.priority]})}getTodos(){return this.getSortedTodos()}async ensureLoaded(){if(!this.loaded)await this.loadTodos(),this.loaded=!0}async loadTodos(){try{let $=await X$.readFile(this.filePath,"utf-8");this.todos=JSON.parse($)}catch($){if($.code==="ENOENT")this.todos=[];else console.warn("加载 TODO 列表失败:",$),this.todos=[]}}async saveTodos(){try{await X$.mkdir(h6.dirname(this.filePath),{recursive:!0}),await X$.writeFile(this.filePath,JSON.stringify(this.todos,null,2),"utf-8")}catch($){throw console.error("保存 TODO 列表失败:",$),$}}}});import{z as Q$}from"zod";var R5;var b5=R(()=>{R5=Q$.object({id:Q$.string().optional(),content:Q$.string().min(1,"Content cannot be empty"),status:Q$.enum(["pending","in_progress","completed"]),activeForm:Q$.string().min(1,"ActiveForm cannot be empty"),priority:Q$.enum(["high","medium","low"]).default("medium")})});import{z as V5}from"zod";function C8($){let{sessionId:Y,configDir:Z}=$;return e({name:"TodoWrite",displayName:"Todo Write",kind:"readonly",schema:V5.object({todos:V5.array(R5).min(1,"At least one task is required")}),description:{short:"Use this tool to create and manage a structured task list for your current coding session",long:`Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
830
+ ${G.stack||""}`,error:{type:"execution_error",message:G.message,details:q}}}},version:"4.0.0",category:"Subagent",tags:["task","subagent","delegation","explore","plan"],extractSignatureContent:($)=>`${$.subagent_type}:${$.description}`,abstractPermissionRule:()=>""})});var v5=D(()=>{E5()});import{randomUUID as pq}from"crypto";import*as J$ from"fs/promises";import*as u6 from"path";var W2;var g8=D(()=>{W2=class W2{static instances=new Map;todos=[];filePath;loaded=!1;constructor($,Y){this.filePath=u6.join(Y,"todos",`${$}-agent-${$}.json`)}static getInstance($,Y){let Z=`${$}-${Y}`;if(!W2.instances.has(Z))W2.instances.set(Z,new W2($,Y));return W2.instances.get(Z)}validate($){if($.filter((Z)=>Z.status==="in_progress").length>1)return{valid:!1,error:"同时只能有一个任务处于 in_progress 状态"};return{valid:!0}}async updateTodos($){await this.ensureLoaded();let Y=new Date().toISOString(),Z=$.map((Q)=>{let J=Q,q=this.todos.find((G)=>G.id===J.id||G.content===Q.content);return{...Q,id:J.id||q?.id||pq(),priority:Q.priority||q?.priority||"medium",createdAt:q?.createdAt||Y,startedAt:Q.status==="in_progress"&&!q?.startedAt?Y:q?.startedAt,completedAt:Q.status==="completed"&&!q?.completedAt?Y:q?.completedAt}}),X=this.validate(Z);if(!X.valid)throw Error(X.error);this.todos=Z,await this.saveTodos()}getSortedTodos(){let $={completed:0,in_progress:1,pending:2},Y={high:0,medium:1,low:2};return[...this.todos].sort((Z,X)=>{let Q=$[Z.status]-$[X.status];if(Q!==0)return Q;return Y[Z.priority]-Y[X.priority]})}getTodos(){return this.getSortedTodos()}async ensureLoaded(){if(!this.loaded)await this.loadTodos(),this.loaded=!0}async loadTodos(){try{let $=await J$.readFile(this.filePath,"utf-8");this.todos=JSON.parse($)}catch($){if($.code==="ENOENT")this.todos=[];else console.warn("加载 TODO 列表失败:",$),this.todos=[]}}async saveTodos(){try{await J$.mkdir(u6.dirname(this.filePath),{recursive:!0}),await J$.writeFile(this.filePath,JSON.stringify(this.todos,null,2),"utf-8")}catch($){throw console.error("保存 TODO 列表失败:",$),$}}}});import{z as q$}from"zod";var y5;var P5=D(()=>{y5=q$.object({id:q$.string().optional(),content:q$.string().min(1,"Content cannot be empty"),status:q$.enum(["pending","in_progress","completed"]),activeForm:q$.string().min(1,"ActiveForm cannot be empty"),priority:q$.enum(["high","medium","low"]).default("medium")})});import{z as T5}from"zod";function m8($){let{sessionId:Y,configDir:Z}=$;return Y1({name:"TodoWrite",displayName:"Todo Write",kind:"readonly",schema:T5.object({todos:T5.array(y5).min(1,"At least one task is required")}),description:{short:"Use this tool to create and manage a structured task list for your current coding session",long:`Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
820
831
  It also helps the user understand the progress of the task and overall progress of their requests.
821
832
 
822
833
  ## When to Use This Tool
@@ -877,16 +888,16 @@ NOTE that you should not use this tool if there is only one trivial task to do.
877
888
  - activeForm: "Fixing authentication bug"
878
889
 
879
890
  When in doubt, use this tool. Being proactive with task management demonstrates attentiveness and ensures you complete all requirements successfully.
880
- `},async execute(X,Q){let{todos:J}=X,{updateOutput:q}=Q;try{let K=Q.sessionId||Y,G=q2.getInstance(K,Z);q?.("Updating TODO list..."),await G.updateTodos(J);let W=G.getTodos(),U=Iq(W),H=kq(W,U);return q?.(`✅ TODO list updated (${U.completed}/${U.total} completed)`),{success:!0,llmContent:{todos:W,stats:U},displayContent:H,metadata:{stats:U}}}catch(K){return{success:!1,llmContent:`Update failed: ${K.message}`,displayContent:`❌ 更新 TODO 列表失败: ${K.message}`,error:{type:"execution_error",message:K.message,details:K}}}},version:"1.0.0",category:"TODO tools",tags:["todo","task","management","planning"],extractSignatureContent:(X)=>`${X.todos.length} todos`,abstractPermissionRule:()=>"*"})}function Iq($){return{total:$.length,completed:$.filter((Y)=>Y.status==="completed").length,inProgress:$.filter((Y)=>Y.status==="in_progress").length,pending:$.filter((Y)=>Y.status==="pending").length}}function kq($,Y){let Z=[],X=Y.total>0?Math.round(Y.completed/Y.total*100):0;if(Z.push(`\uD83D\uDCCB TODO 列表 (${Y.completed}/${Y.total} 完成,${X}%)`),Z.push(""),$.length===0)return Z.push(" (暂无任务)"),Z.join(`
881
- `);for(let Q of $){let J=Q.status==="completed"?"☑":"☐",q=`(P${Q.priority==="high"?0:Q.priority==="medium"?1:2})`,K=Q.status==="in_progress"?" ⚡":"",G=Q.status==="completed"?"~~":"";Z.push(` ${J} ${q} ${G}${Q.content}${G}${K}`)}return Z.join(`
882
- `)}var D5=R(()=>{k1();h1();S8();b5()});var M5=R(()=>{S8();D5()});import{z as i0}from"zod";async function jq($){let{url:Y,method:Z,headers:X,body:Q,timeout:J,follow_redirects:q,max_redirects:K,signal:G}=$,W={"User-Agent":"Blade-AI/1.0",...X},U=Y,H=Z,O=Q,z=0,_=[];while(!0){let F={...W};if(O&&H!=="GET"&&H!=="HEAD"&&!Sq(F,"content-type"))F["Content-Type"]="application/json";let N=await vq(U,{method:H,headers:F,body:O&&H!=="GET"&&H!=="HEAD"?O:void 0,redirect:"manual"},J,G),w=N.headers.get("location"),B=N.status>=300&&N.status<400,A=q&&B&&w&&z<K;if(B&&q&&!w)throw Error(`收到状态码 ${N.status} 但响应缺少 Location 头`);if(B&&q&&z>=K)throw Error(`超过最大重定向次数 (${K})`);if(A&&w){z++;let b=Pq(w,U);if(_.push(`${N.status} → ${b}`),N.status===303||(N.status===301||N.status===302)&&H!=="GET"&&H!=="HEAD")H="GET",O=void 0;U=b;continue}let D=await N.text(),I=Tq(N.headers);return{status:N.status,status_text:N.statusText,headers:I,body:D,url:N.url||U,redirected:z>0,redirect_count:z,redirect_chain:_,content_type:I["content-type"],response_time:0}}}function I5($,Y,Z){let{url:X,method:Q,status:J,response_time:q,content_length:K}=Y,G=Z?`❌ ${Q} ${X} - ${J} ${$.status_text}`:`✅ ${Q} ${X} - ${J} ${$.status_text}`;if(G+=`
883
- 响应时间: ${q}ms`,G+=`
884
- 内容长度: ${K} 字节`,Y.content_type)G+=`
885
- Content-Type: ${Y.content_type}`;if($.redirected&&Y.final_url&&Y.final_url!==X){if(G+=`
886
- 最终URL: ${Y.final_url}`,Y.redirect_count)G+=`
887
- 重定向次数: ${Y.redirect_count}`}let W=Eq($.body,$.content_type);if(W)G+=`
891
+ `},async execute(X,Q){let{todos:J}=X,{updateOutput:q}=Q;try{let G=Q.sessionId||Y,K=W2.getInstance(G,Z);q?.("Updating TODO list..."),await K.updateTodos(J);let W=K.getTodos(),U=gq(W),H=mq(W,U);return q?.(`✅ TODO list updated (${U.completed}/${U.total} completed)`),{success:!0,llmContent:{todos:W,stats:U},displayContent:H,metadata:{stats:U}}}catch(G){return{success:!1,llmContent:`Update failed: ${G.message}`,displayContent:`❌ 更新 TODO 列表失败: ${G.message}`,error:{type:"execution_error",message:G.message,details:G}}}},version:"1.0.0",category:"TODO tools",tags:["todo","task","management","planning"],extractSignatureContent:(X)=>`${X.todos.length} todos`,abstractPermissionRule:()=>"*"})}function gq($){return{total:$.length,completed:$.filter((Y)=>Y.status==="completed").length,inProgress:$.filter((Y)=>Y.status==="in_progress").length,pending:$.filter((Y)=>Y.status==="pending").length}}function mq($,Y){let Z=[],X=Y.total>0?Math.round(Y.completed/Y.total*100):0;if(Z.push(`\uD83D\uDCCB TODO 列表 (${Y.completed}/${Y.total} 完成,${X}%)`),Z.push(""),$.length===0)return Z.push(" (暂无任务)"),Z.join(`
892
+ `);for(let Q of $){let J=Q.status==="completed"?"☑":"☐",q=`(P${Q.priority==="high"?0:Q.priority==="medium"?1:2})`,G=Q.status==="in_progress"?" ⚡":"",K=Q.status==="completed"?"~~":"";Z.push(` ${J} ${q} ${K}${Q.content}${K}${G}`)}return Z.join(`
893
+ `)}var S5=D(()=>{j1();p1();g8();P5()});var C5=D(()=>{g8();S5()});import{z as a0}from"zod";async function dq($){let{url:Y,method:Z,headers:X,body:Q,timeout:J,follow_redirects:q,max_redirects:G,signal:K}=$,W={"User-Agent":"Blade-AI/1.0",...X},U=Y,H=Z,O=Q,F=0,_=[];while(!0){let z={...W};if(O&&H!=="GET"&&H!=="HEAD"&&!aq(z,"content-type"))z["Content-Type"]="application/json";let w=await lq(U,{method:H,headers:z,body:O&&H!=="GET"&&H!=="HEAD"?O:void 0,redirect:"manual"},J,K),B=w.headers.get("location"),N=w.status>=300&&w.status<400,b=q&&N&&B&&F<G;if(N&&q&&!B)throw Error(`收到状态码 ${w.status} 但响应缺少 Location 头`);if(N&&q&&F>=G)throw Error(`超过最大重定向次数 (${G})`);if(b&&B){F++;let L=iq(B,U);if(_.push(`${w.status} → ${L}`),w.status===303||(w.status===301||w.status===302)&&H!=="GET"&&H!=="HEAD")H="GET",O=void 0;U=L;continue}let V=await w.text(),R=rq(w.headers);return{status:w.status,status_text:w.statusText,headers:R,body:V,url:w.url||U,redirected:F>0,redirect_count:F,redirect_chain:_,content_type:R["content-type"],response_time:0}}}function f5($,Y,Z){let{url:X,method:Q,status:J,response_time:q,content_length:G}=Y,K=Z?`❌ ${Q} ${X} - ${J} ${$.status_text}`:`✅ ${Q} ${X} - ${J} ${$.status_text}`;if(K+=`
894
+ 响应时间: ${q}ms`,K+=`
895
+ 内容长度: ${G} 字节`,Y.content_type)K+=`
896
+ Content-Type: ${Y.content_type}`;if($.redirected&&Y.final_url&&Y.final_url!==X){if(K+=`
897
+ 最终URL: ${Y.final_url}`,Y.redirect_count)K+=`
898
+ 重定向次数: ${Y.redirect_count}`}let W=uq($.body,$.content_type);if(W)K+=`
888
899
  响应内容:
889
- ${W}`;return G}function Eq($,Y){if(!$)return"(空响应)";if(yq(Y,$))return"[binary content omitted]";let Z=$.trim();if(!Z)return"(仅包含空白字符)";return Z.length>800?`${Z.slice(0,800)}...`:Z}function yq($,Y){if($){let Q=$.toLowerCase();if(["image/","audio/","video/","application/pdf","application/zip","application/octet-stream"].some((q)=>Q.startsWith(q)))return!0}if(!Y)return!1;let Z=0,X=Math.min(Y.length,200);for(let Q=0;Q<X;Q++){let J=Y.charCodeAt(Q);if(J===9||J===10||J===13)continue;if(J<32||J>126)Z++}return Z/(X||1)>0.3}async function vq($,Y,Z,X){let Q=new AbortController,J=setTimeout(()=>Q.abort(),Z),q=()=>Q.abort();X?.addEventListener("abort",q);try{return await fetch($,{...Y,signal:Q.signal})}catch(K){if(K.name==="AbortError")throw K.message="请求被中止或超时",K;throw K}finally{clearTimeout(J),X?.removeEventListener("abort",q)}}function Pq($,Y){try{return new URL($,Y).toString()}catch{return $}}function Tq($){let Y={};return $.forEach((Z,X)=>{Y[X.toLowerCase()]=Z}),Y}function Sq($,Y){let Z=Y.toLowerCase();return Object.keys($).some((X)=>X.toLowerCase()===Z)}var f8;var k5=R(()=>{k1();h1();Z2();f8=e({name:"WebFetch",displayName:"Web Fetch",kind:"readonly",schema:i0.object({url:i0.string().url().describe("URL to request"),method:i0.enum(["GET","POST","PUT","DELETE","HEAD"]).default("GET").describe("HTTP method"),headers:i0.record(i0.string()).optional().describe("Request headers (optional)"),body:i0.string().optional().describe("Request body (optional)"),timeout:H1.timeout(1000,120000,30000),follow_redirects:i0.boolean().default(!0).describe("Follow redirects"),max_redirects:i0.number().int().min(0).max(10).default(5).describe("Maximum redirect hops"),return_headers:i0.boolean().default(!1).describe("Return response headers")}),description:{short:"Fetches content from a specified URL and processes it using an AI model",long:`
900
+ ${W}`;return K}function uq($,Y){if(!$)return"(空响应)";if(cq(Y,$))return"[binary content omitted]";let Z=$.trim();if(!Z)return"(仅包含空白字符)";return Z.length>800?`${Z.slice(0,800)}...`:Z}function cq($,Y){if($){let Q=$.toLowerCase();if(["image/","audio/","video/","application/pdf","application/zip","application/octet-stream"].some((q)=>Q.startsWith(q)))return!0}if(!Y)return!1;let Z=0,X=Math.min(Y.length,200);for(let Q=0;Q<X;Q++){let J=Y.charCodeAt(Q);if(J===9||J===10||J===13)continue;if(J<32||J>126)Z++}return Z/(X||1)>0.3}async function lq($,Y,Z,X){let Q=new AbortController,J=setTimeout(()=>Q.abort(),Z),q=()=>Q.abort();X?.addEventListener("abort",q);try{return await fetch($,{...Y,signal:Q.signal})}catch(G){if(G.name==="AbortError")throw G.message="请求被中止或超时",G;throw G}finally{clearTimeout(J),X?.removeEventListener("abort",q)}}function iq($,Y){try{return new URL($,Y).toString()}catch{return $}}function rq($){let Y={};return $.forEach((Z,X)=>{Y[X.toLowerCase()]=Z}),Y}function aq($,Y){let Z=Y.toLowerCase();return Object.keys($).some((X)=>X.toLowerCase()===Z)}var d8;var h5=D(()=>{j1();p1();J2();d8=Y1({name:"WebFetch",displayName:"Web Fetch",kind:"readonly",schema:a0.object({url:a0.string().url().describe("URL to request"),method:a0.enum(["GET","POST","PUT","DELETE","HEAD"]).default("GET").describe("HTTP method"),headers:a0.record(a0.string()).optional().describe("Request headers (optional)"),body:a0.string().optional().describe("Request body (optional)"),timeout:O1.timeout(1000,120000,30000),follow_redirects:a0.boolean().default(!0).describe("Follow redirects"),max_redirects:a0.number().int().min(0).max(10).default(5).describe("Maximum redirect hops"),return_headers:a0.boolean().default(!1).describe("Return response headers")}),description:{short:"Fetches content from a specified URL and processes it using an AI model",long:`
890
901
  - Fetches content from a specified URL and processes it using an AI model
891
902
  - Takes a URL and a prompt as input
892
903
  - Fetches the URL content, converts HTML to markdown
@@ -903,12 +914,12 @@ Usage notes:
903
914
  - Results may be summarized if the content is very large
904
915
  - Includes a self-cleaning 15-minute cache for faster responses when repeatedly accessing the same URL
905
916
  - When a URL redirects to a different host, the tool will inform you and provide the redirect URL in a special format. You should then make a new WebFetch request with the redirect URL to fetch the content.
906
- `},async execute($,Y){let{url:Z,method:X="GET",headers:Q={},body:J,timeout:q=30000,follow_redirects:K=!0,max_redirects:G=5,return_headers:W=!1}=$,{updateOutput:U}=Y,H=Y.signal??new AbortController().signal;try{U?.(`发送 ${X} 请求到: ${Z}`);let O=Date.now(),z=await jq({url:Z,method:X,headers:Q,body:J,timeout:q,follow_redirects:K,max_redirects:G,signal:H}),_=Date.now()-O;if(z.response_time=_,!W)delete z.headers;let F={url:Z,method:X,status:z.status,response_time:_,content_length:Buffer.byteLength(z.body||"","utf8"),redirected:z.redirected||!1,redirect_count:z.redirect_count??0,final_url:z.url,content_type:z.content_type,redirect_chain:z.redirect_chain};if(z.status>=400)return{success:!1,llmContent:`HTTP error ${z.status}: ${z.status_text}`,displayContent:I5(z,F,!0),error:{type:"execution_error",message:`HTTP error ${z.status}: ${z.status_text}`,details:{...F,response_body:z.body}},metadata:F};return{success:!0,llmContent:z,displayContent:I5(z,F,!1),metadata:F}}catch(O){if(O.name==="AbortError")return{success:!1,llmContent:"Request aborted",displayContent:"⚠️ 请求被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Network request failed: ${O.message}`,displayContent:`❌ 网络请求失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"网络工具",tags:["web","http","fetch","request","api"],extractSignatureContent:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return $.url}},abstractPermissionRule:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return"*"}}})});function Cq($){return $.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'")}function j5($){let Y=Cq($).trim();if(!Y.includes(" - "))return{title:Y,snippet:Y};let[Z,...X]=Y.split(" - "),Q=Z.trim(),J=X.join(" - ").trim()||Y;return{title:Q,snippet:J}}function h8($){try{let Y=new URL($),Z=Y.pathname==="/"?"":Y.pathname;return`${Y.hostname}${Z}`}catch{return $}}function x8($){try{return new URL($).hostname.toLowerCase()}catch{return""}}function fq($){if(!$.FirstURL||!$.Text)return null;let{title:Y,snippet:Z}=j5($.Text);return{title:Y,snippet:Z,url:$.FirstURL,display_url:h8($.FirstURL),source:x8($.FirstURL)}}function E5($){let Y=[];for(let Z of $){if(Z.Topics&&Z.Topics.length>0){Y.push(...E5(Z.Topics));continue}if(Z.FirstURL&&Z.Text){let{title:X,snippet:Q}=j5(Z.Text);Y.push({title:X,snippet:Q,url:Z.FirstURL,display_url:h8(Z.FirstURL),source:x8(Z.FirstURL)})}}return Y}function hq($){let Y=$,Z=(Y.Results??[]).map((Q)=>fq(Q)).filter((Q)=>Q!==null),X=E5(Y.RelatedTopics??[]);return[...Z,...X]}function pq($){let Y=$,Z=[];for(let X of Y.results??[]){if(!X.url||!X.title)continue;Z.push({title:X.title,snippet:X.content||X.title,url:X.url,display_url:h8(X.url),source:x8(X.url)})}return Z}function gq($){return{name:`SearXNG(${(()=>{try{return new URL($).hostname}catch{return $}})()})`,endpoint:$,buildUrl:(Z)=>{let X=new URL(`${$}/search`);return X.searchParams.set("q",Z),X.searchParams.set("format","json"),X.searchParams.set("categories","general"),X.toString()},parseResponse:pq,getHeaders:()=>({Accept:"application/json","User-Agent":"Blade-AI-WebSearch/1.0"})}}function v5(){return[xq,...y5.map(gq)]}function P5(){return 1+y5.length}var xq,y5;var T5=R(()=>{xq={name:"DuckDuckGo",endpoint:"https://duckduckgo.com/",buildUrl:($)=>{let Y=new URL("https://duckduckgo.com/");return Y.searchParams.set("q",$),Y.searchParams.set("format","json"),Y.searchParams.set("no_html","1"),Y.searchParams.set("skip_disambig","1"),Y.searchParams.set("t","blade-code"),Y.searchParams.set("kl","us-en"),Y.toString()},parseResponse:hq,getHeaders:()=>({Accept:"application/json, text/plain;q=0.9","User-Agent":"Blade-AI-WebSearch/1.0"})};y5=["https://searx.be","https://search.ononoki.org","https://searx.tiekoetter.com","https://searx.work"]});import{ProxyAgent as mq,fetch as dq}from"undici";import{z as J$}from"zod";function lq(){let $=process.env.HTTPS_PROXY||process.env.HTTP_PROXY||process.env.https_proxy||process.env.http_proxy;if($)try{return new mq($)}catch(Y){console.warn(`Invalid proxy URL: ${$}`)}return}async function iq($,Y,Z,X,Q){let J=new AbortController,q=setTimeout(()=>J.abort(),Z),K=()=>J.abort();X?.addEventListener("abort",K);try{return await dq($,{...Y,signal:J.signal,dispatcher:Q})}catch(G){if(G.name==="AbortError")throw Error("搜索请求超时或被中止");throw G}finally{clearTimeout(q),X?.removeEventListener("abort",K)}}async function rq($,Y,Z,X,Q,J){let q=null;for(let K=0;K<m$.maxRetries;K++)try{return await iq($,Y,Z,X,Q)}catch(G){if(q=G,X?.aborted)throw G;if(K<m$.maxRetries-1){let W=Math.min(m$.baseDelay*Math.pow(2,K),m$.maxDelay);J?.(`⏳ 请求失败,${W/1000}s 后重试 (${K+1}/${m$.maxRetries})...`),await new Promise((U)=>setTimeout(U,W))}}throw q}async function aq($,Y,Z,X,Q,J){let q=$.buildUrl(Y),K=await rq(q,{headers:$.getHeaders()},Z,X,Q,J);if(!K.ok)throw Error(`HTTP ${K.status}`);let G=await K.text(),W;try{W=JSON.parse(G)}catch{throw Error("Failed to parse search result JSON")}return{results:$.parseResponse(W),providerName:$.name}}async function nq($,Y,Z,X){let Q=v5(),J=lq(),q=[];for(let K=0;K<Q.length;K++){let G=Q[K];if(Z?.aborted)throw Error("搜索被用户中止");try{return X?.(`\uD83D\uDD0E 使用 ${G.name} 搜索...`),await aq(G,$,Y,Z,J,X)}catch(W){let U=`${G.name}: ${W.message}`;if(q.push(U),X?.(`⚠️ ${U}`),K===Q.length-1)throw Error(`所有搜索提供商都失败了:
917
+ `},async execute($,Y){let{url:Z,method:X="GET",headers:Q={},body:J,timeout:q=30000,follow_redirects:G=!0,max_redirects:K=5,return_headers:W=!1}=$,{updateOutput:U}=Y,H=Y.signal??new AbortController().signal;try{U?.(`发送 ${X} 请求到: ${Z}`);let O=Date.now(),F=await dq({url:Z,method:X,headers:Q,body:J,timeout:q,follow_redirects:G,max_redirects:K,signal:H}),_=Date.now()-O;if(F.response_time=_,!W)delete F.headers;let z={url:Z,method:X,status:F.status,response_time:_,content_length:Buffer.byteLength(F.body||"","utf8"),redirected:F.redirected||!1,redirect_count:F.redirect_count??0,final_url:F.url,content_type:F.content_type,redirect_chain:F.redirect_chain};if(F.status>=400)return{success:!1,llmContent:`HTTP error ${F.status}: ${F.status_text}`,displayContent:f5(F,z,!0),error:{type:"execution_error",message:`HTTP error ${F.status}: ${F.status_text}`,details:{...z,response_body:F.body}},metadata:z};return{success:!0,llmContent:F,displayContent:f5(F,z,!1),metadata:z}}catch(O){if(O.name==="AbortError")return{success:!1,llmContent:"Request aborted",displayContent:"⚠️ 请求被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Network request failed: ${O.message}`,displayContent:`❌ 网络请求失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"网络工具",tags:["web","http","fetch","request","api"],extractSignatureContent:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return $.url}},abstractPermissionRule:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return"*"}}})});function nq($){return $.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'")}function x5($){let Y=nq($).trim();if(!Y.includes(" - "))return{title:Y,snippet:Y};let[Z,...X]=Y.split(" - "),Q=Z.trim(),J=X.join(" - ").trim()||Y;return{title:Q,snippet:J}}function u8($){try{let Y=new URL($),Z=Y.pathname==="/"?"":Y.pathname;return`${Y.hostname}${Z}`}catch{return $}}function c8($){try{return new URL($).hostname.toLowerCase()}catch{return""}}function oq($){if(!$.FirstURL||!$.Text)return null;let{title:Y,snippet:Z}=x5($.Text);return{title:Y,snippet:Z,url:$.FirstURL,display_url:u8($.FirstURL),source:c8($.FirstURL)}}function p5($){let Y=[];for(let Z of $){if(Z.Topics&&Z.Topics.length>0){Y.push(...p5(Z.Topics));continue}if(Z.FirstURL&&Z.Text){let{title:X,snippet:Q}=x5(Z.Text);Y.push({title:X,snippet:Q,url:Z.FirstURL,display_url:u8(Z.FirstURL),source:c8(Z.FirstURL)})}}return Y}function sq($){let Y=$,Z=(Y.Results??[]).map((Q)=>oq(Q)).filter((Q)=>Q!==null),X=p5(Y.RelatedTopics??[]);return[...Z,...X]}function eq($){let Y=$,Z=[];for(let X of Y.results??[]){if(!X.url||!X.title)continue;Z.push({title:X.title,snippet:X.content||X.title,url:X.url,display_url:u8(X.url),source:c8(X.url)})}return Z}function $G($){return{name:`SearXNG(${(()=>{try{return new URL($).hostname}catch{return $}})()})`,endpoint:$,buildUrl:(Z)=>{let X=new URL(`${$}/search`);return X.searchParams.set("q",Z),X.searchParams.set("format","json"),X.searchParams.set("categories","general"),X.toString()},parseResponse:eq,getHeaders:()=>({Accept:"application/json","User-Agent":"Blade-AI-WebSearch/1.0"})}}function m5(){return[tq,...g5.map($G)]}function d5(){return 1+g5.length}var tq,g5;var u5=D(()=>{tq={name:"DuckDuckGo",endpoint:"https://duckduckgo.com/",buildUrl:($)=>{let Y=new URL("https://duckduckgo.com/");return Y.searchParams.set("q",$),Y.searchParams.set("format","json"),Y.searchParams.set("no_html","1"),Y.searchParams.set("skip_disambig","1"),Y.searchParams.set("t","blade-code"),Y.searchParams.set("kl","us-en"),Y.toString()},parseResponse:sq,getHeaders:()=>({Accept:"application/json, text/plain;q=0.9","User-Agent":"Blade-AI-WebSearch/1.0"})};g5=["https://searx.be","https://search.ononoki.org","https://searx.tiekoetter.com","https://searx.work"]});import{ProxyAgent as YG,fetch as ZG}from"undici";import{z as G$}from"zod";function JG(){let $=process.env.HTTPS_PROXY||process.env.HTTP_PROXY||process.env.https_proxy||process.env.http_proxy;if($)try{return new YG($)}catch(Y){console.warn(`Invalid proxy URL: ${$}`)}return}async function qG($,Y,Z,X,Q){let J=new AbortController,q=setTimeout(()=>J.abort(),Z),G=()=>J.abort();X?.addEventListener("abort",G);try{return await ZG($,{...Y,signal:J.signal,dispatcher:Q})}catch(K){if(K.name==="AbortError")throw Error("搜索请求超时或被中止");throw K}finally{clearTimeout(q),X?.removeEventListener("abort",G)}}async function GG($,Y,Z,X,Q,J){let q=null;for(let G=0;G<i$.maxRetries;G++)try{return await qG($,Y,Z,X,Q)}catch(K){if(q=K,X?.aborted)throw K;if(G<i$.maxRetries-1){let W=Math.min(i$.baseDelay*Math.pow(2,G),i$.maxDelay);J?.(`⏳ 请求失败,${W/1000}s 后重试 (${G+1}/${i$.maxRetries})...`),await new Promise((U)=>setTimeout(U,W))}}throw q}async function KG($,Y,Z,X,Q,J){let q=$.buildUrl(Y),G=await GG(q,{headers:$.getHeaders()},Z,X,Q,J);if(!G.ok)throw Error(`HTTP ${G.status}`);let K=await G.text(),W;try{W=JSON.parse(K)}catch{throw Error("Failed to parse search result JSON")}return{results:$.parseResponse(W),providerName:$.name}}async function WG($,Y,Z,X){let Q=m5(),J=JG(),q=[];for(let G=0;G<Q.length;G++){let K=Q[G];if(Z?.aborted)throw Error("搜索被用户中止");try{return X?.(`\uD83D\uDD0E 使用 ${K.name} 搜索...`),await KG(K,$,Y,Z,J,X)}catch(W){let U=`${K.name}: ${W.message}`;if(q.push(U),X?.(`⚠️ ${U}`),G===Q.length-1)throw Error(`所有搜索提供商都失败了:
907
918
  ${q.join(`
908
- `)}`)}}throw Error("No search providers available")}function oq($){try{return new URL($).hostname.toLowerCase()}catch{return null}}function sq($){return $.trim().toLowerCase()}function S5($){if(!$||$.length===0)return[];return $.map(sq).filter(Boolean)}function C5($,Y){return $===Y||$.endsWith(`.${Y}`)}function tq($,Y,Z){return $.filter((X)=>{let Q=oq(X.url);if(!Q)return!1;if(Z.length>0&&Z.some((J)=>C5(Q,J)))return!1;if(Y.length>0&&!Y.some((J)=>C5(Q,J)))return!1;return!0})}function eq($,Y,Z,X){let Q=`\uD83D\uDD0E WebSearch("${$}") via ${X} - 返回 ${Y.length}/${Z} 条结果`,J=Y.map((q,K)=>`${K+1}. ${q.title}
919
+ `)}`)}}throw Error("No search providers available")}function UG($){try{return new URL($).hostname.toLowerCase()}catch{return null}}function HG($){return $.trim().toLowerCase()}function c5($){if(!$||$.length===0)return[];return $.map(HG).filter(Boolean)}function l5($,Y){return $===Y||$.endsWith(`.${Y}`)}function OG($,Y,Z){return $.filter((X)=>{let Q=UG(X.url);if(!Q)return!1;if(Z.length>0&&Z.some((J)=>l5(Q,J)))return!1;if(Y.length>0&&!Y.some((J)=>l5(Q,J)))return!1;return!0})}function FG($,Y,Z,X){let Q=`\uD83D\uDD0E WebSearch("${$}") via ${X} - 返回 ${Y.length}/${Z} 条结果`,J=Y.map((q,G)=>`${G+1}. ${q.title}
909
920
  ${q.display_url}
910
921
  ${q.snippet}`);return[Q,...J].join(`
911
- `)}function $K($){let Y=$.trim().toLowerCase();return Y.length>80?Y.slice(0,80):Y}var uq=15000,cq=8,m$,p8;var f5=R(()=>{k1();h1();T5();m$={maxRetries:3,baseDelay:1000,maxDelay:8000};p8=e({name:"WebSearch",displayName:"Web Search",kind:"readonly",schema:J$.object({query:J$.string().min(2,"Search query must be at least 2 characters").describe("Search query"),allowed_domains:J$.array(J$.string().min(1)).optional().describe("Return results only from these domains (optional)"),blocked_domains:J$.array(J$.string().min(1)).optional().describe("Exclude results from these domains (optional)")}),description:{short:"Search the web and use the results to inform responses",long:`
922
+ `)}function zG($){let Y=$.trim().toLowerCase();return Y.length>80?Y.slice(0,80):Y}var XG=15000,QG=8,i$,l8;var i5=D(()=>{j1();p1();u5();i$={maxRetries:3,baseDelay:1000,maxDelay:8000};l8=Y1({name:"WebSearch",displayName:"Web Search",kind:"readonly",schema:G$.object({query:G$.string().min(2,"Search query must be at least 2 characters").describe("Search query"),allowed_domains:G$.array(G$.string().min(1)).optional().describe("Return results only from these domains (optional)"),blocked_domains:G$.array(G$.string().min(1)).optional().describe("Exclude results from these domains (optional)")}),description:{short:"Search the web and use the results to inform responses",long:`
912
923
  - Search the web and use the results to inform responses
913
924
  - Provides up-to-date information for current events and recent data
914
925
  - Returns search result information formatted as search result blocks, including links as markdown hyperlinks
@@ -936,15 +947,15 @@ Usage notes:
936
947
  IMPORTANT - Use the correct year in search queries:
937
948
  - You MUST use the current year when searching for recent information, documentation, or current events.
938
949
  - Example: If the user asks for "latest React docs", search for "React documentation 2025", NOT "React documentation 2024"
939
- `},async execute($,Y){let{query:Z}=$,X=S5($.allowed_domains),Q=S5($.blocked_domains),{updateOutput:J}=Y,q=Y.signal??new AbortController().signal;J?.(`\uD83D\uDD0E Searching: "${Z}" (${P5()} providers available)`);try{let{results:K,providerName:G}=await nq(Z,uq,q,J),W=tq(K,X,Q),U=W.slice(0,cq),H={query:Z,results:U,provider:G,total_results:W.length,fetched_at:new Date().toISOString()},O={query:Z,provider:G,fetched_at:H.fetched_at,total_results:W.length,returned_results:U.length,allowed_domains:X,blocked_domains:Q};if(U.length===0)return{success:!0,llmContent:H,displayContent:`\uD83D\uDD0D WebSearch("${Z}") via ${G} - 未找到匹配结果`,metadata:O};return{success:!0,llmContent:H,displayContent:eq(Z,U,W.length,G),metadata:O}}catch(K){return{success:!1,llmContent:`WebSearch call failed: ${K.message}`,displayContent:`❌ WebSearch 调用失败: ${K.message}`,error:{type:"execution_error",message:K.message,details:{query:Z,allowedDomains:X,blockedDomains:Q}}}}},version:"2.0.0",category:"网络工具",tags:["web","search","internet","news"],extractSignatureContent:($)=>`search:${$K($.query)}`,abstractPermissionRule:()=>"search:*"})});var h5=R(()=>{k5();f5()});import*as x5 from"os";import*as p5 from"path";async function YK(){try{return await C1.getInstance().getAvailableTools()}catch($){return console.warn("MCP协议工具加载失败:",$),[]}}async function g5($){let Y=$?.sessionId||`session_${Date.now()}`,Z=$?.configDir||p5.join(x5.homedir(),".blade"),X=[H8,U8,z8,F8,A8,V8,M8,k8,j8,f8,p8,T8,C8({sessionId:Y,configDir:Z}),_8,N8,E8,y8],Q=await YK();return[...X,...Q]}var m5=R(()=>{u2();u3();l3();o3();Q5();H5();B5();A5();M5();h5()});var x6,g8,m8;var p6=R(()=>{((X)=>{X.PreToolUse="PreToolUse";X.PostToolUse="PostToolUse";X.Stop="Stop"})(x6||={});((X)=>{X.Approve="approve";X.Block="block";X.Async="async"})(g8||={});((X)=>{X.Allow="allow";X.Deny="deny";X.Ask="ask"})(m8||={})});function u8($,Y){return{...$,...Y,PreToolUse:Y.PreToolUse??$.PreToolUse,PostToolUse:Y.PostToolUse??$.PostToolUse,Stop:Y.Stop??$.Stop}}function d5(){let $={};if(process.env.BLADE_DISABLE_HOOKS==="true")$.enabled=!1;if(process.env.BLADE_HOOK_TIMEOUT){let Y=parseInt(process.env.BLADE_HOOK_TIMEOUT,10);if(!isNaN(Y)&&Y>0)$.defaultTimeout=Y}return $}var d8;var u5=R(()=>{d8={enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],Stop:[]}});import{spawn as ZK}from"child_process";class c8{content="";maxSize;constructor($){this.maxSize=$}append($){if(this.content.length<this.maxSize){let Y=this.maxSize-this.content.length;this.content+=$.substring(0,Y)}}getContent(){return this.content}isFull(){return this.content.length>=this.maxSize}}class l8{MAX_STDOUT_SIZE=1048576;MAX_STDERR_SIZE=1048576;MAX_INPUT_SIZE=102400;async execute($,Y,Z,X){let Q=JSON.stringify(Y);if(Q.length>this.MAX_INPUT_SIZE)throw Error(`Hook input too large: ${Q.length} bytes (max ${this.MAX_INPUT_SIZE})`);let J=this.createSafeEnv(Y),q=ZK($,[],{shell:!0,env:J,cwd:Z.projectDir,timeout:X}),K=new c8(this.MAX_STDOUT_SIZE),G=new c8(this.MAX_STDERR_SIZE);q.stdout.setEncoding("utf8"),q.stderr.setEncoding("utf8"),q.stdout.on("data",(W)=>{K.append(W)}),q.stderr.on("data",(W)=>{G.append(W)});try{q.stdin.write(Q),q.stdin.end()}catch(W){throw q.kill("SIGTERM"),Error(`Failed to write hook input: ${W}`)}return new Promise((W,U)=>{let H=!1,O=setTimeout(()=>{H=!0,q.kill("SIGKILL")},X);if(q.on("close",(z)=>{clearTimeout(O),W({stdout:K.getContent(),stderr:G.getContent(),exitCode:H?124:z??1,timedOut:H})}),q.on("error",(z)=>{clearTimeout(O),U(z)}),Z.abortSignal)Z.abortSignal.addEventListener("abort",()=>{clearTimeout(O),q.kill("SIGTERM"),W({stdout:K.getContent(),stderr:"Hook cancelled by abort signal",exitCode:1,timedOut:!1})})})}createSafeEnv($){return{BLADE_PROJECT_DIR:$.project_dir,BLADE_SESSION_ID:$.session_id,BLADE_HOOK_EVENT:$.hook_event_name,BLADE_TOOL_NAME:"tool_name"in $?$.tool_name:"",BLADE_TOOL_USE_ID:"tool_use_id"in $?$.tool_use_id:"",PATH:process.env.PATH||"",HOME:process.env.HOME||"",USER:process.env.USER||"",SHELL:process.env.SHELL||"/bin/sh"}}}var c5=()=>{};import{z as T}from"zod";function l5($){let Y=WK.safeParse($);if(Y.success)return{success:!0,data:Y.data};return{success:!1,error:Y.error}}var r8,QK,JK,qK,hw,KK,GK,WK,UK,HK,OK,zK,i8,xw;var i5=R(()=>{p6();r8=T.object({hook_event_name:T.nativeEnum(x6),hook_execution_id:T.string(),timestamp:T.string(),project_dir:T.string(),session_id:T.string(),permission_mode:T.enum(["default","autoEdit","yolo","plan"]),_metadata:T.object({blade_version:T.string(),hook_timeout_ms:T.number()}).optional()}),QK=r8.extend({hook_event_name:T.literal("PreToolUse"),tool_name:T.string(),tool_use_id:T.string(),tool_input:T.record(T.unknown())}),JK=r8.extend({hook_event_name:T.literal("PostToolUse"),tool_name:T.string(),tool_use_id:T.string(),tool_input:T.record(T.unknown()),tool_response:T.unknown()}),qK=r8.extend({hook_event_name:T.literal("Stop"),reason:T.string().optional()}),hw=T.discriminatedUnion("hook_event_name",[QK,JK,qK]),KK=T.object({hookEventName:T.literal("PreToolUse"),permissionDecision:T.nativeEnum(m8).optional(),permissionDecisionReason:T.string().optional(),updatedInput:T.record(T.unknown()).optional()}),GK=T.object({hookEventName:T.literal("PostToolUse"),additionalContext:T.string().optional(),updatedOutput:T.unknown().optional()}),WK=T.object({decision:T.object({behavior:T.nativeEnum(g8)}).optional(),systemMessage:T.string().optional(),hookSpecificOutput:T.discriminatedUnion("hookEventName",[KK,GK]).optional(),suppressOutput:T.boolean().optional()}),UK=T.object({type:T.literal("command"),command:T.string(),timeout:T.number().positive().optional(),statusMessage:T.string().optional()}),HK=T.object({type:T.literal("prompt"),prompt:T.string(),timeout:T.number().positive().optional()}),OK=T.discriminatedUnion("type",[UK,HK]),zK=T.object({tools:T.string().optional(),paths:T.string().optional(),commands:T.string().optional()}),i8=T.object({name:T.string().optional(),matcher:zK.optional(),hooks:T.array(OK)}),xw=T.object({enabled:T.boolean().optional(),defaultTimeout:T.number().positive().optional(),timeoutBehavior:T.enum(["ignore","deny","ask"]).optional(),failureBehavior:T.enum(["ignore","deny","ask"]).optional(),maxConcurrentHooks:T.number().positive().optional(),PreToolUse:T.array(i8).optional(),PostToolUse:T.array(i8).optional(),Stop:T.array(i8).optional()})});class a8{parse($,Y,Z){if($.timedOut){let Q=Z?.timeoutBehavior||"ignore",J="Hook timeout";if(Q==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y}}let X=this.tryParseJSON($.stdout);if(X){let Q=l5(X);if(!Q.success){let q="error"in Q?Q.error.message:"Unknown validation error",K=Z?.failureBehavior||"ignore",G=`Invalid hook output JSON: ${q}`;if(K==="deny")return{success:!1,blocking:!0,error:G,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};else if(K==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${G}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};else return{success:!1,blocking:!1,warning:G,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y}}let J=Q.data;if(J.decision?.behavior==="block")return{success:!1,blocking:!0,error:J.systemMessage||"Hook blocked execution",output:J,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};if(J.decision?.behavior==="async")return{success:!0,output:J,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};return{success:!0,output:J,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y}}return this.parseByExitCode($,Y,Z)}parseByExitCode($,Y,Z){let X=$.exitCode;switch(X){case 0:return{success:!0,stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};case 2:return{success:!1,blocking:!0,error:$.stderr||$.stdout||"Hook returned exit code 2",stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};case 124:{let Q=Z?.timeoutBehavior||"ignore",J="Hook timeout";if(Q==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y}}default:{let Q=Z?.failureBehavior||"ignore",J=$.stderr||$.stdout||`Hook failed with exit code ${X}`;if(Q==="deny")return{success:!1,blocking:!0,error:J,stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${J}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};else return{success:!1,blocking:!1,warning:J,stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y}}}}tryParseJSON($){try{let Y=$.trim();if(!Y)return null;let Z=Y.match(/^\s*(\{[\s\S]*\})\s*$/);if(!Z)return null;return JSON.parse(Z[1])}catch{return null}}}var r5=R(()=>{i5()});class n8{processExecutor=new l8;outputParser=new a8;async executePreToolHooks($,Y,Z){if($.length===0)return{decision:"allow"};let X="tool_input"in Y?Y.tool_input:{},Q=[];for(let J of $)try{let q={...Y,...X&&{tool_input:X}},K=await this.executeHook(J,q,Z);if(!K.success){if(K.blocking)return{decision:"deny",reason:K.error};if(K.needsConfirmation)return{decision:"ask",reason:K.warning||K.error};if(K.warning)Q.push(K.warning);continue}let G=K.output?.hookSpecificOutput;if(G&&"permissionDecision"in G){switch(G.permissionDecision){case"deny":return{decision:"deny",reason:G.permissionDecisionReason};case"ask":return{decision:"ask",reason:G.permissionDecisionReason};case"allow":break}if(G.updatedInput)X={...X,...G.updatedInput}}}catch(q){let K=q instanceof Error?q.message:String(q);if(Q.push(`Hook failed: ${K}`),Z.config.failureBehavior==="deny")return{decision:"deny",reason:K};else if(Z.config.failureBehavior==="ask")return{decision:"ask",reason:`Hook failed: ${K}. Continue?`}}return{decision:"allow",modifiedInput:X,warning:Q.length>0?Q.join(`
940
- `):void 0}}async executePostToolHooks($,Y,Z){if($.length===0)return{};let X=Z.config.maxConcurrentHooks||5,Q=await this.executeHooksConcurrently($,Y,Z,X),J=[],q=void 0,K=[];for(let G of Q){if(!G.success&&G.warning){K.push(G.warning);continue}let W=G.output?.hookSpecificOutput;if(W&&"additionalContext"in W){if(W.additionalContext)J.push(W.additionalContext);if(W.updatedOutput!==void 0)q=W.updatedOutput}}return{additionalContext:J.length>0?J.join(`
950
+ `},async execute($,Y){let{query:Z}=$,X=c5($.allowed_domains),Q=c5($.blocked_domains),{updateOutput:J}=Y,q=Y.signal??new AbortController().signal;J?.(`\uD83D\uDD0E Searching: "${Z}" (${d5()} providers available)`);try{let{results:G,providerName:K}=await WG(Z,XG,q,J),W=OG(G,X,Q),U=W.slice(0,QG),H={query:Z,results:U,provider:K,total_results:W.length,fetched_at:new Date().toISOString()},O={query:Z,provider:K,fetched_at:H.fetched_at,total_results:W.length,returned_results:U.length,allowed_domains:X,blocked_domains:Q};if(U.length===0)return{success:!0,llmContent:H,displayContent:`\uD83D\uDD0D WebSearch("${Z}") via ${K} - 未找到匹配结果`,metadata:O};return{success:!0,llmContent:H,displayContent:FG(Z,U,W.length,K),metadata:O}}catch(G){return{success:!1,llmContent:`WebSearch call failed: ${G.message}`,displayContent:`❌ WebSearch 调用失败: ${G.message}`,error:{type:"execution_error",message:G.message,details:{query:Z,allowedDomains:X,blockedDomains:Q}}}}},version:"2.0.0",category:"网络工具",tags:["web","search","internet","news"],extractSignatureContent:($)=>`search:${zG($.query)}`,abstractPermissionRule:()=>"search:*"})});var r5=D(()=>{h5();i5()});import*as a5 from"os";import*as n5 from"path";async function _G(){try{return await f1.getInstance().getAvailableTools()}catch($){return console.warn("MCP协议工具加载失败:",$),[]}}async function o5($){let Y=$?.sessionId||`session_${Date.now()}`,Z=$?.configDir||n5.join(a5.homedir(),".blade"),X=[B8,N8,L8,A8,M8,E8,y8,T8,S8,d8,l8,p8,m8({sessionId:Y,configDir:Z}),b8,V8,C8,f8],Q=await _G();return[...X,...Q]}var s5=D(()=>{l2();e3();Y5();q5();z5();b5();M5();v5();C5();r5()});var c6,i8,r8;var l6=D(()=>{((X)=>{X.PreToolUse="PreToolUse";X.PostToolUse="PostToolUse";X.Stop="Stop"})(c6||={});((X)=>{X.Approve="approve";X.Block="block";X.Async="async"})(i8||={});((X)=>{X.Allow="allow";X.Deny="deny";X.Ask="ask"})(r8||={})});function n8($,Y){return{...$,...Y,PreToolUse:Y.PreToolUse??$.PreToolUse,PostToolUse:Y.PostToolUse??$.PostToolUse,Stop:Y.Stop??$.Stop}}function t5(){let $={};if(process.env.BLADE_DISABLE_HOOKS==="true")$.enabled=!1;if(process.env.BLADE_HOOK_TIMEOUT){let Y=parseInt(process.env.BLADE_HOOK_TIMEOUT,10);if(!isNaN(Y)&&Y>0)$.defaultTimeout=Y}return $}var a8;var e5=D(()=>{a8={enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],Stop:[]}});import{spawn as NG}from"child_process";class o8{content="";maxSize;constructor($){this.maxSize=$}append($){if(this.content.length<this.maxSize){let Y=this.maxSize-this.content.length;this.content+=$.substring(0,Y)}}getContent(){return this.content}isFull(){return this.content.length>=this.maxSize}}class s8{MAX_STDOUT_SIZE=1048576;MAX_STDERR_SIZE=1048576;MAX_INPUT_SIZE=102400;async execute($,Y,Z,X){let Q=JSON.stringify(Y);if(Q.length>this.MAX_INPUT_SIZE)throw Error(`Hook input too large: ${Q.length} bytes (max ${this.MAX_INPUT_SIZE})`);let J=this.createSafeEnv(Y),q=NG($,[],{shell:!0,env:J,cwd:Z.projectDir,timeout:X}),G=new o8(this.MAX_STDOUT_SIZE),K=new o8(this.MAX_STDERR_SIZE);q.stdout.setEncoding("utf8"),q.stderr.setEncoding("utf8"),q.stdout.on("data",(W)=>{G.append(W)}),q.stderr.on("data",(W)=>{K.append(W)});try{q.stdin.write(Q),q.stdin.end()}catch(W){throw q.kill("SIGTERM"),Error(`Failed to write hook input: ${W}`)}return new Promise((W,U)=>{let H=!1,O=setTimeout(()=>{H=!0,q.kill("SIGKILL")},X);if(q.on("close",(F)=>{clearTimeout(O),W({stdout:G.getContent(),stderr:K.getContent(),exitCode:H?124:F??1,timedOut:H})}),q.on("error",(F)=>{clearTimeout(O),U(F)}),Z.abortSignal)Z.abortSignal.addEventListener("abort",()=>{clearTimeout(O),q.kill("SIGTERM"),W({stdout:G.getContent(),stderr:"Hook cancelled by abort signal",exitCode:1,timedOut:!1})})})}createSafeEnv($){return{BLADE_PROJECT_DIR:$.project_dir,BLADE_SESSION_ID:$.session_id,BLADE_HOOK_EVENT:$.hook_event_name,BLADE_TOOL_NAME:"tool_name"in $?$.tool_name:"",BLADE_TOOL_USE_ID:"tool_use_id"in $?$.tool_use_id:"",PATH:process.env.PATH||"",HOME:process.env.HOME||"",USER:process.env.USER||"",SHELL:process.env.SHELL||"/bin/sh"}}}var $Y=()=>{};import{z as S}from"zod";function YY($){let Y=VG.safeParse($);if(Y.success)return{success:!0,data:Y.data};return{success:!1,error:Y.error}}var e8,wG,LG,AG,rw,bG,RG,VG,DG,IG,MG,kG,t8,aw;var ZY=D(()=>{l6();e8=S.object({hook_event_name:S.nativeEnum(c6),hook_execution_id:S.string(),timestamp:S.string(),project_dir:S.string(),session_id:S.string(),permission_mode:S.enum(["default","autoEdit","yolo","plan"]),_metadata:S.object({blade_version:S.string(),hook_timeout_ms:S.number()}).optional()}),wG=e8.extend({hook_event_name:S.literal("PreToolUse"),tool_name:S.string(),tool_use_id:S.string(),tool_input:S.record(S.unknown())}),LG=e8.extend({hook_event_name:S.literal("PostToolUse"),tool_name:S.string(),tool_use_id:S.string(),tool_input:S.record(S.unknown()),tool_response:S.unknown()}),AG=e8.extend({hook_event_name:S.literal("Stop"),reason:S.string().optional()}),rw=S.discriminatedUnion("hook_event_name",[wG,LG,AG]),bG=S.object({hookEventName:S.literal("PreToolUse"),permissionDecision:S.nativeEnum(r8).optional(),permissionDecisionReason:S.string().optional(),updatedInput:S.record(S.unknown()).optional()}),RG=S.object({hookEventName:S.literal("PostToolUse"),additionalContext:S.string().optional(),updatedOutput:S.unknown().optional()}),VG=S.object({decision:S.object({behavior:S.nativeEnum(i8)}).optional(),systemMessage:S.string().optional(),hookSpecificOutput:S.discriminatedUnion("hookEventName",[bG,RG]).optional(),suppressOutput:S.boolean().optional()}),DG=S.object({type:S.literal("command"),command:S.string(),timeout:S.number().positive().optional(),statusMessage:S.string().optional()}),IG=S.object({type:S.literal("prompt"),prompt:S.string(),timeout:S.number().positive().optional()}),MG=S.discriminatedUnion("type",[DG,IG]),kG=S.object({tools:S.string().optional(),paths:S.string().optional(),commands:S.string().optional()}),t8=S.object({name:S.string().optional(),matcher:kG.optional(),hooks:S.array(MG)}),aw=S.object({enabled:S.boolean().optional(),defaultTimeout:S.number().positive().optional(),timeoutBehavior:S.enum(["ignore","deny","ask"]).optional(),failureBehavior:S.enum(["ignore","deny","ask"]).optional(),maxConcurrentHooks:S.number().positive().optional(),PreToolUse:S.array(t8).optional(),PostToolUse:S.array(t8).optional(),Stop:S.array(t8).optional()})});class $9{parse($,Y,Z){if($.timedOut){let Q=Z?.timeoutBehavior||"ignore",J="Hook timeout";if(Q==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y}}let X=this.tryParseJSON($.stdout);if(X){let Q=YY(X);if(!Q.success){let q="error"in Q?Q.error.message:"Unknown validation error",G=Z?.failureBehavior||"ignore",K=`Invalid hook output JSON: ${q}`;if(G==="deny")return{success:!1,blocking:!0,error:K,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};else if(G==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${K}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};else return{success:!1,blocking:!1,warning:K,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y}}let J=Q.data;if(J.decision?.behavior==="block")return{success:!1,blocking:!0,error:J.systemMessage||"Hook blocked execution",output:J,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};if(J.decision?.behavior==="async")return{success:!0,output:J,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y};return{success:!0,output:J,stdout:$.stdout,stderr:$.stderr,exitCode:$.exitCode,hook:Y}}return this.parseByExitCode($,Y,Z)}parseByExitCode($,Y,Z){let X=$.exitCode;switch(X){case 0:return{success:!0,stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};case 2:return{success:!1,blocking:!0,error:$.stderr||$.stdout||"Hook returned exit code 2",stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};case 124:{let Q=Z?.timeoutBehavior||"ignore",J="Hook timeout";if(Q==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y}}default:{let Q=Z?.failureBehavior||"ignore",J=$.stderr||$.stdout||`Hook failed with exit code ${X}`;if(Q==="deny")return{success:!1,blocking:!0,error:J,stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${J}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y};else return{success:!1,blocking:!1,warning:J,stdout:$.stdout,stderr:$.stderr,exitCode:X,hook:Y}}}}tryParseJSON($){try{let Y=$.trim();if(!Y)return null;let Z=Y.match(/^\s*(\{[\s\S]*\})\s*$/);if(!Z)return null;return JSON.parse(Z[1])}catch{return null}}}var XY=D(()=>{ZY()});class Y9{processExecutor=new s8;outputParser=new $9;async executePreToolHooks($,Y,Z){if($.length===0)return{decision:"allow"};let X="tool_input"in Y?Y.tool_input:{},Q=[];for(let J of $)try{let q={...Y,...X&&{tool_input:X}},G=await this.executeHook(J,q,Z);if(!G.success){if(G.blocking)return{decision:"deny",reason:G.error};if(G.needsConfirmation)return{decision:"ask",reason:G.warning||G.error};if(G.warning)Q.push(G.warning);continue}let K=G.output?.hookSpecificOutput;if(K&&"permissionDecision"in K){switch(K.permissionDecision){case"deny":return{decision:"deny",reason:K.permissionDecisionReason};case"ask":return{decision:"ask",reason:K.permissionDecisionReason};case"allow":break}if(K.updatedInput)X={...X,...K.updatedInput}}}catch(q){let G=q instanceof Error?q.message:String(q);if(Q.push(`Hook failed: ${G}`),Z.config.failureBehavior==="deny")return{decision:"deny",reason:G};else if(Z.config.failureBehavior==="ask")return{decision:"ask",reason:`Hook failed: ${G}. Continue?`}}return{decision:"allow",modifiedInput:X,warning:Q.length>0?Q.join(`
951
+ `):void 0}}async executePostToolHooks($,Y,Z){if($.length===0)return{};let X=Z.config.maxConcurrentHooks||5,Q=await this.executeHooksConcurrently($,Y,Z,X),J=[],q=void 0,G=[];for(let K of Q){if(!K.success&&K.warning){G.push(K.warning);continue}let W=K.output?.hookSpecificOutput;if(W&&"additionalContext"in W){if(W.additionalContext)J.push(W.additionalContext);if(W.updatedOutput!==void 0)q=W.updatedOutput}}return{additionalContext:J.length>0?J.join(`
941
952
 
942
- `):void 0,modifiedOutput:q,warning:K.length>0?K.join(`
943
- `):void 0}}async executeHook($,Y,Z){if($.type==="command")return this.executeCommandHook($,Y,Z);throw Error(`Hook type ${$.type} not yet implemented`)}async executeCommandHook($,Y,Z){let X=($.timeout??Z.config.defaultTimeout??60)*1000;try{let Q=await this.processExecutor.execute($.command,Y,Z,X);return this.outputParser.parse(Q,$,{timeoutBehavior:Z.config.timeoutBehavior,failureBehavior:Z.config.failureBehavior})}catch(Q){return{success:!1,blocking:!1,error:Q instanceof Error?Q.message:String(Q),hook:$}}}async executeHooksConcurrently($,Y,Z,X){let Q=[],J=new Set;for(let q of $){if(J.size>=X)await Promise.race(J);let K=this.executeHook(q,Y,Z).catch((W)=>({success:!1,blocking:!1,error:W instanceof Error?W.message:String(W),hook:q})),G=K.then(()=>{J.delete(G)}).catch(()=>{J.delete(G)});J.add(G),Q.push(K)}return Promise.all(Q)}}var a5=R(()=>{p6();c5();r5()});class o8{executedHooks=new Map;canExecute($,Y){if(!this.executedHooks.has($))this.executedHooks.set($,new Set);if(this.executedHooks.get($).has(Y))return console.warn(`[HookGuard] Hook ${Y} for tool ${$} already executed, skipping`),!1;return!0}markExecuted($,Y){let Z=this.executedHooks.get($);if(Z)Z.add(Y)}cleanup($){this.executedHooks.delete($)}cleanupAll(){this.executedHooks.clear()}}import FK from"picomatch";class s8{matches($,Y){if(!$)return!0;if($.tools&&Y.toolName){if(!this.matchPattern(Y.toolName,$.tools))return!1}if($.paths&&Y.filePath){if(!FK($.paths)(Y.filePath))return!1}if($.commands&&Y.command){if(!this.matchPattern(Y.command,$.commands))return!1}return!0}matchPattern($,Y){if(Y==="*")return!0;if(!Y.includes("|")&&!/[.*+?^${}()|[\]\\]/.test(Y))return $===Y;if(Y.includes("|"))return Y.split("|").map((X)=>X.trim()).includes($);try{return new RegExp(Y).test($)}catch{return $===Y}}}var n5=()=>{};import{nanoid as o5}from"nanoid";class J0{static instance=null;config=d8;executor=new n8;guard=new o8;matcher=new s8;sessionDisabled=!1;constructor(){}static getInstance(){if(!J0.instance)J0.instance=new J0;return J0.instance}loadConfig($){let Y=u8(d8,$),Z=d5();Y=u8(Y,Z),this.config=Y}isEnabled(){if(!this.config.enabled)return!1;if(this.sessionDisabled)return!1;return!0}disable(){this.sessionDisabled=!0,console.log("[HookManager] Hooks disabled for this session")}enable(){this.sessionDisabled=!1,console.log("[HookManager] Hooks enabled for this session")}async executePreToolHooks($,Y,Z,X){if(!this.isEnabled())return{decision:"allow"};if(X.permissionMode==="plan")return{decision:"allow"};if(!this.guard.canExecute(Y,"PreToolUse"))return{decision:"allow"};let Q={hook_event_name:"PreToolUse",hook_execution_id:o5(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:Y,tool_input:Z,project_dir:X.projectDir,session_id:X.sessionId,permission_mode:X.permissionMode},J=this.getMatchingHooks("PreToolUse",{toolName:$,filePath:this.extractFilePath(Z),command:this.extractCommand($,Z)});if(J.length===0)return{decision:"allow"};let q={projectDir:X.projectDir,sessionId:X.sessionId,permissionMode:X.permissionMode,config:this.config,abortSignal:X.abortSignal};try{let K=await this.executor.executePreToolHooks(J,Q,q);if(this.guard.markExecuted(Y,"PreToolUse"),X.permissionMode==="yolo"){if(K.decision==="deny")return K;return{decision:"allow",modifiedInput:K.modifiedInput,warning:K.warning,reason:K.reason}}return K}catch(K){return console.error("[HookManager] Error executing PreToolUse hooks:",K),{decision:"allow",warning:`Hook execution failed: ${K instanceof Error?K.message:String(K)}`}}}async executePostToolHooks($,Y,Z,X,Q){if(!this.isEnabled())return{};if(Q.permissionMode==="plan")return{};if(!this.guard.canExecute(Y,"PostToolUse"))return{};let J={hook_event_name:"PostToolUse",hook_execution_id:o5(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:Y,tool_input:Z,tool_response:X,project_dir:Q.projectDir,session_id:Q.sessionId,permission_mode:Q.permissionMode},q=this.getMatchingHooks("PostToolUse",{toolName:$,filePath:this.extractFilePath(Z),command:this.extractCommand($,Z)});if(q.length===0)return{};let K={projectDir:Q.projectDir,sessionId:Q.sessionId,permissionMode:Q.permissionMode,config:this.config,abortSignal:Q.abortSignal};try{let G=await this.executor.executePostToolHooks(q,J,K);return this.guard.markExecuted(Y,"PostToolUse"),G}catch(G){return console.error("[HookManager] Error executing PostToolUse hooks:",G),{warning:`Hook execution failed: ${G instanceof Error?G.message:String(G)}`}}finally{this.guard.cleanup(Y)}}getMatchingHooks($,Y){let Z=this.config[$]||[],X=[];for(let Q of Z)if(this.matcher.matches(Q.matcher,Y))X.push(...Q.hooks);return X}extractFilePath($){let Y=["file_path","path","filePath","source","target"];for(let Z of Y){let X=$[Z];if(typeof X==="string")return X}return}extractCommand($,Y){if($==="Bash"||$==="BashTool"){let Z=Y.command;if(typeof Z==="string")return Z}return}cleanup(){this.guard.cleanupAll()}}var g6=R(()=>{p6();u5();a5();n5()});import{nanoid as _K}from"nanoid";class t8{name="hook";hookManager;constructor(){this.hookManager=J0.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let Y=$._internal.tool;if(!Y)return;try{let Z=$.context.messageId||`tool_${_K()}`;$._internal.hookToolUseId=Z;let X=$.context.workspaceRoot||process.cwd(),Q=await this.hookManager.executePreToolHooks(Y.name,Z,$.params,{projectDir:X,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode||"default"});if(Q.decision==="deny"){$.abort(Q.reason||"Hook blocked execution");return}if(Q.decision==="ask"){$._internal.needsConfirmation=!0,$._internal.confirmationReason=Q.reason||"Hook requires confirmation";return}if(Q.modifiedInput){let J={...$.params,...Q.modifiedInput};if(Y.build)try{Y.build(J),$.params=J}catch(q){$.abort(`Hook modified parameters are invalid: ${q instanceof Error?q.message:String(q)}`);return}}if(Q.warning)console.warn(`[Hook Warning] ${Q.warning}`)}catch(Z){console.error("[HookStage] Error executing hooks:",Z)}}}var s5=R(()=>{g6()});import{nanoid as BK}from"nanoid";class e8{name="post-hook";hookManager;constructor(){this.hookManager=J0.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let Y=$._internal.tool;if(!Y)return;let Z=$.getResult();if(!Z)return;try{let X=$._internal.hookToolUseId||$.context.messageId||`tool_${BK()}`,Q=$.context.workspaceRoot||process.cwd(),J=await this.hookManager.executePostToolHooks(Y.name,X,$.params,Z,{projectDir:Q,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode||"default"});if(J.additionalContext){let q=Z.llmContent||Z.displayContent||"";Z.llmContent=`${q}
953
+ `):void 0,modifiedOutput:q,warning:G.length>0?G.join(`
954
+ `):void 0}}async executeHook($,Y,Z){if($.type==="command")return this.executeCommandHook($,Y,Z);throw Error(`Hook type ${$.type} not yet implemented`)}async executeCommandHook($,Y,Z){let X=($.timeout??Z.config.defaultTimeout??60)*1000;try{let Q=await this.processExecutor.execute($.command,Y,Z,X);return this.outputParser.parse(Q,$,{timeoutBehavior:Z.config.timeoutBehavior,failureBehavior:Z.config.failureBehavior})}catch(Q){return{success:!1,blocking:!1,error:Q instanceof Error?Q.message:String(Q),hook:$}}}async executeHooksConcurrently($,Y,Z,X){let Q=[],J=new Set;for(let q of $){if(J.size>=X)await Promise.race(J);let G=this.executeHook(q,Y,Z).catch((W)=>({success:!1,blocking:!1,error:W instanceof Error?W.message:String(W),hook:q})),K=G.then(()=>{J.delete(K)}).catch(()=>{J.delete(K)});J.add(K),Q.push(G)}return Promise.all(Q)}}var QY=D(()=>{l6();$Y();XY()});class Z9{executedHooks=new Map;canExecute($,Y){if(!this.executedHooks.has($))this.executedHooks.set($,new Set);if(this.executedHooks.get($).has(Y))return console.warn(`[HookGuard] Hook ${Y} for tool ${$} already executed, skipping`),!1;return!0}markExecuted($,Y){let Z=this.executedHooks.get($);if(Z)Z.add(Y)}cleanup($){this.executedHooks.delete($)}cleanupAll(){this.executedHooks.clear()}}import jG from"picomatch";class X9{matches($,Y){if(!$)return!0;if($.tools&&Y.toolName){if(!this.matchPattern(Y.toolName,$.tools))return!1}if($.paths&&Y.filePath){if(!jG($.paths)(Y.filePath))return!1}if($.commands&&Y.command){if(!this.matchPattern(Y.command,$.commands))return!1}return!0}matchPattern($,Y){if(Y==="*")return!0;if(!Y.includes("|")&&!/[.*+?^${}()|[\]\\]/.test(Y))return $===Y;if(Y.includes("|"))return Y.split("|").map((X)=>X.trim()).includes($);try{return new RegExp(Y).test($)}catch{return $===Y}}}var JY=()=>{};import{nanoid as qY}from"nanoid";class q0{static instance=null;config=a8;executor=new Y9;guard=new Z9;matcher=new X9;sessionDisabled=!1;constructor(){}static getInstance(){if(!q0.instance)q0.instance=new q0;return q0.instance}loadConfig($){let Y=n8(a8,$),Z=t5();Y=n8(Y,Z),this.config=Y}isEnabled(){if(!this.config.enabled)return!1;if(this.sessionDisabled)return!1;return!0}disable(){this.sessionDisabled=!0,console.log("[HookManager] Hooks disabled for this session")}enable(){this.sessionDisabled=!1,console.log("[HookManager] Hooks enabled for this session")}async executePreToolHooks($,Y,Z,X){if(!this.isEnabled())return{decision:"allow"};if(X.permissionMode==="plan")return{decision:"allow"};if(!this.guard.canExecute(Y,"PreToolUse"))return{decision:"allow"};let Q={hook_event_name:"PreToolUse",hook_execution_id:qY(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:Y,tool_input:Z,project_dir:X.projectDir,session_id:X.sessionId,permission_mode:X.permissionMode},J=this.getMatchingHooks("PreToolUse",{toolName:$,filePath:this.extractFilePath(Z),command:this.extractCommand($,Z)});if(J.length===0)return{decision:"allow"};let q={projectDir:X.projectDir,sessionId:X.sessionId,permissionMode:X.permissionMode,config:this.config,abortSignal:X.abortSignal};try{let G=await this.executor.executePreToolHooks(J,Q,q);if(this.guard.markExecuted(Y,"PreToolUse"),X.permissionMode==="yolo"){if(G.decision==="deny")return G;return{decision:"allow",modifiedInput:G.modifiedInput,warning:G.warning,reason:G.reason}}return G}catch(G){return console.error("[HookManager] Error executing PreToolUse hooks:",G),{decision:"allow",warning:`Hook execution failed: ${G instanceof Error?G.message:String(G)}`}}}async executePostToolHooks($,Y,Z,X,Q){if(!this.isEnabled())return{};if(Q.permissionMode==="plan")return{};if(!this.guard.canExecute(Y,"PostToolUse"))return{};let J={hook_event_name:"PostToolUse",hook_execution_id:qY(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:Y,tool_input:Z,tool_response:X,project_dir:Q.projectDir,session_id:Q.sessionId,permission_mode:Q.permissionMode},q=this.getMatchingHooks("PostToolUse",{toolName:$,filePath:this.extractFilePath(Z),command:this.extractCommand($,Z)});if(q.length===0)return{};let G={projectDir:Q.projectDir,sessionId:Q.sessionId,permissionMode:Q.permissionMode,config:this.config,abortSignal:Q.abortSignal};try{let K=await this.executor.executePostToolHooks(q,J,G);return this.guard.markExecuted(Y,"PostToolUse"),K}catch(K){return console.error("[HookManager] Error executing PostToolUse hooks:",K),{warning:`Hook execution failed: ${K instanceof Error?K.message:String(K)}`}}finally{this.guard.cleanup(Y)}}getMatchingHooks($,Y){let Z=this.config[$]||[],X=[];for(let Q of Z)if(this.matcher.matches(Q.matcher,Y))X.push(...Q.hooks);return X}extractFilePath($){let Y=["file_path","path","filePath","source","target"];for(let Z of Y){let X=$[Z];if(typeof X==="string")return X}return}extractCommand($,Y){if($==="Bash"||$==="BashTool"){let Z=Y.command;if(typeof Z==="string")return Z}return}cleanup(){this.guard.cleanupAll()}}var i6=D(()=>{l6();e5();QY();JY()});import{nanoid as EG}from"nanoid";class Q9{name="hook";hookManager;constructor(){this.hookManager=q0.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let Y=$._internal.tool;if(!Y)return;try{let Z=$.context.messageId||`tool_${EG()}`;$._internal.hookToolUseId=Z;let X=$.context.workspaceRoot||process.cwd(),Q=await this.hookManager.executePreToolHooks(Y.name,Z,$.params,{projectDir:X,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode||"default"});if(Q.decision==="deny"){$.abort(Q.reason||"Hook blocked execution");return}if(Q.decision==="ask"){$._internal.needsConfirmation=!0,$._internal.confirmationReason=Q.reason||"Hook requires confirmation";return}if(Q.modifiedInput){let J={...$.params,...Q.modifiedInput};if(Y.build)try{Y.build(J),$.params=J}catch(q){$.abort(`Hook modified parameters are invalid: ${q instanceof Error?q.message:String(q)}`);return}}if(Q.warning)console.warn(`[Hook Warning] ${Q.warning}`)}catch(Z){console.error("[HookStage] Error executing hooks:",Z)}}}var GY=D(()=>{i6()});import{nanoid as vG}from"nanoid";class J9{name="post-hook";hookManager;constructor(){this.hookManager=q0.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let Y=$._internal.tool;if(!Y)return;let Z=$.getResult();if(!Z)return;try{let X=$._internal.hookToolUseId||$.context.messageId||`tool_${vG()}`,Q=$.context.workspaceRoot||process.cwd(),J=await this.hookManager.executePostToolHooks(Y.name,X,$.params,Z,{projectDir:Q,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode||"default"});if(J.additionalContext){let q=Z.llmContent||Z.displayContent||"";Z.llmContent=`${q}
944
955
 
945
956
  ---
946
957
  **Hook Context:**
947
- ${J.additionalContext}`}if(J.modifiedOutput!==void 0){let q=J.modifiedOutput;if(typeof q==="object"&&q!==null)Object.assign(Z,q)}if(J.warning)console.warn(`[PostToolUseHook Warning] ${J.warning}`)}catch(X){console.error("[PostToolUseHookStage] Error executing post-tool hooks:",X)}}}var t5=R(()=>{g6()});class K2{static instance=null;locks=new Map;constructor(){}static getInstance(){if(!K2.instance)K2.instance=new K2;return K2.instance}async acquireLock($,Y){let Z=this.locks.get($);if(Z)try{await Z}catch{}let X=this.executeWithLock($,Y);return this.locks.set($,X.then(()=>{return})),X}async executeWithLock($,Y){$9.debug(`获取文件锁: ${$}`);try{let Z=await Y();return $9.debug(`释放文件锁: ${$}`),Z}catch(Z){throw $9.debug(`操作失败,释放文件锁: ${$}`),Z}}isLocked($){return this.locks.has($)}clearLock($){this.locks.delete($)}clearAll(){this.locks.clear()}getLockedFiles(){return Array.from(this.locks.keys())}getLockedFileCount(){return this.locks.size}static resetInstance(){K2.instance=null}}var $9;var e5=R(()=>{N1();$9=u("Execution")});import NK from"node:os";import Y9 from"node:path";var Z9;var $Y=R(()=>{Z9=class Z9{static SENSITIVE_PATTERNS=[{pattern:/^\.?id_rsa$/i,level:"high",description:"SSH 私钥"},{pattern:/^\.?id_ed25519$/i,level:"high",description:"SSH Ed25519 私钥"},{pattern:/^\.?id_ecdsa$/i,level:"high",description:"SSH ECDSA 私钥"},{pattern:/\.pem$/i,level:"high",description:"PEM 格式私钥"},{pattern:/\.key$/i,level:"high",description:"密钥文件"},{pattern:/\.p12$/i,level:"high",description:"PKCS#12 证书"},{pattern:/\.pfx$/i,level:"high",description:"PFX 证书"},{pattern:/^\.?keystore$/i,level:"high",description:"Java Keystore"},{pattern:/^\.?pgpass$/i,level:"high",description:"PostgreSQL 密码文件"},{pattern:/^\.?my\.cnf$/i,level:"high",description:"MySQL 配置文件(可能含密码)"},{pattern:/credentials\.json$/i,level:"high",description:"Google Cloud 凭证"},{pattern:/^\.?aws[\\/]credentials$/i,level:"high",description:"AWS 凭证"},{pattern:/^\.?gcp[\\/]credentials$/i,level:"high",description:"GCP 凭证"},{pattern:/^\.?azure[\\/]credentials$/i,level:"high",description:"Azure 凭证"},{pattern:/^service-account.*\.json$/i,level:"high",description:"服务账号密钥"},{pattern:/^\.env$/i,level:"medium",description:"环境变量文件"},{pattern:/^\.env\./i,level:"medium",description:"环境变量文件(带环境后缀)"},{pattern:/^\.?npmrc$/i,level:"medium",description:"npm 配置文件(可能含 token)"},{pattern:/^\.?pypirc$/i,level:"medium",description:"PyPI 配置文件(可能含密码)"},{pattern:/^\.?dockercfg$/i,level:"medium",description:"Docker 配置文件"},{pattern:/^\.?docker[\\/]config\.json$/i,level:"medium",description:"Docker 配置文件"},{pattern:/^\.?netrc$/i,level:"medium",description:"FTP/HTTP 认证文件"},{pattern:/^\.?git-credentials$/i,level:"medium",description:"Git 凭证文件"},{pattern:/^config\.toml$/i,level:"medium",description:"配置文件(可能含敏感信息)"},{pattern:/^secrets\./i,level:"medium",description:"密钥配置文件"},{pattern:/\.sqlite$/i,level:"low",description:"SQLite 数据库"},{pattern:/\.db$/i,level:"low",description:"数据库文件"},{pattern:/\.sql$/i,level:"low",description:"SQL 文件(可能含敏感数据)"}];static SENSITIVE_PATHS=[{path:/\.ssh[\\/]/i,level:"high",description:"SSH 配置目录"},{path:/\.aws[\\/]/i,level:"high",description:"AWS 配置目录"},{path:/\.config[\\/]gcloud[\\/]/i,level:"high",description:"Google Cloud 配置目录"},{path:/\.kube[\\/]/i,level:"high",description:"Kubernetes 配置目录"}];static check($){let Y=this.normalizePath($),Z=Y9.basename(Y);for(let X of this.SENSITIVE_PATTERNS)if(this.matchPattern(Z,X.pattern))return{isSensitive:!0,level:X.level,matchedPattern:X.pattern instanceof RegExp?X.pattern.source:X.pattern,reason:X.description};for(let X of this.SENSITIVE_PATHS)if(this.matchPattern(Y,X.path))return{isSensitive:!0,level:X.level,matchedPattern:X.path instanceof RegExp?X.path.source:X.path,reason:X.description};return{isSensitive:!1}}static checkMultiple($){let Y=new Map;for(let Z of $)Y.set(Z,this.check(Z));return Y}static filterSensitive($,Y="low"){let Z={["high"]:3,["medium"]:2,["low"]:1},X=Z[Y];return $.map((Q)=>({path:Q,result:this.check(Q)})).filter(({result:Q})=>Q.isSensitive&&Q.level&&Z[Q.level]>=X)}static normalizePath($){if($.startsWith("~/")||$==="~")return Y9.join(NK.homedir(),$.slice(1));return Y9.resolve($)}static matchPattern($,Y){if(Y instanceof RegExp)return Y.test($);let Z=Y.replace(/\*/g,".*");return new RegExp(`^${Z}$`,"i").test($)}static getSensitivePatterns(){return[...this.SENSITIVE_PATTERNS]}static getSensitivePaths(){return[...this.SENSITIVE_PATHS]}}});class X9{registry;name="discovery";constructor($){this.registry=$}async process($){let Y=this.registry.get($.toolName);if(!Y){$.abort(`Tool "${$.toolName}" not found`);return}$._internal.tool=Y}}class Q9{name="permission";permissionChecker;sessionApprovals;defaultPermissionMode;constructor($,Y,Z){this.permissionChecker=new A2($),this.sessionApprovals=Y,this.defaultPermissionMode=Z}getPermissionChecker(){return this.permissionChecker}async process($){let Y=$._internal.tool;if(!Y){$.abort("Discovery stage failed; cannot perform permission check");return}try{let Z=Y.build($.params),X=Z.getAffectedPaths(),Q={toolName:Y.name,params:$.params,affectedPaths:X,tool:Y},J=A2.buildSignature(Q);$._internal.permissionSignature=J;let q=this.permissionChecker.check(Q),K=$.context.permissionMode||this.defaultPermissionMode;switch(q=this.applyModeOverrides(Y.kind,q,K),q.result){case"deny":$.abort(q.reason||`Tool invocation "${Y.name}" was denied by permission rules: ${q.matchedRule}`);return;case"ask":if(this.sessionApprovals.has(J))q={result:"allow",matchedRule:"remembered:session",reason:"User already allowed this operation in this session"};else $._internal.needsConfirmation=!0,$._internal.confirmationReason=q.reason||"User confirmation required";break;case"allow":break}if(X.length>0){let G=["/etc/","/sys/","/proc/","/dev/","/boot/","/root/","C:\\Windows\\System32","C:\\Program Files","C:\\ProgramData"],W=X.filter((H)=>{if(H.includes(".."))return!0;return G.some((O)=>H.includes(O))});if(W.length>0){$.abort(`Access to dangerous system paths denied: ${W.join(", ")}`);return}let U=Z9.filterSensitive(X,"medium");if(U.length>0){let H=U.map(({path:z,result:_})=>`${z} (${_.level}: ${_.reason})`);if(U.filter(({result:z})=>z.level==="high").length>0&&q.result!=="allow"){$.abort(`Access to highly sensitive files denied:
958
+ ${J.additionalContext}`}if(J.modifiedOutput!==void 0){let q=J.modifiedOutput;if(typeof q==="object"&&q!==null)Object.assign(Z,q)}if(J.warning)console.warn(`[PostToolUseHook Warning] ${J.warning}`)}catch(X){console.error("[PostToolUseHookStage] Error executing post-tool hooks:",X)}}}var KY=D(()=>{i6()});class U2{static instance=null;locks=new Map;constructor(){}static getInstance(){if(!U2.instance)U2.instance=new U2;return U2.instance}async acquireLock($,Y){let Z=this.locks.get($);if(Z)try{await Z}catch{}let X=this.executeWithLock($,Y);return this.locks.set($,X.then(()=>{return})),X}async executeWithLock($,Y){q9.debug(`获取文件锁: ${$}`);try{let Z=await Y();return q9.debug(`释放文件锁: ${$}`),Z}catch(Z){throw q9.debug(`操作失败,释放文件锁: ${$}`),Z}}isLocked($){return this.locks.has($)}clearLock($){this.locks.delete($)}clearAll(){this.locks.clear()}getLockedFiles(){return Array.from(this.locks.keys())}getLockedFileCount(){return this.locks.size}static resetInstance(){U2.instance=null}}var q9;var WY=D(()=>{B1();q9=l("Execution")});import yG from"node:os";import G9 from"node:path";var K9;var UY=D(()=>{K9=class K9{static SENSITIVE_PATTERNS=[{pattern:/^\.?id_rsa$/i,level:"high",description:"SSH 私钥"},{pattern:/^\.?id_ed25519$/i,level:"high",description:"SSH Ed25519 私钥"},{pattern:/^\.?id_ecdsa$/i,level:"high",description:"SSH ECDSA 私钥"},{pattern:/\.pem$/i,level:"high",description:"PEM 格式私钥"},{pattern:/\.key$/i,level:"high",description:"密钥文件"},{pattern:/\.p12$/i,level:"high",description:"PKCS#12 证书"},{pattern:/\.pfx$/i,level:"high",description:"PFX 证书"},{pattern:/^\.?keystore$/i,level:"high",description:"Java Keystore"},{pattern:/^\.?pgpass$/i,level:"high",description:"PostgreSQL 密码文件"},{pattern:/^\.?my\.cnf$/i,level:"high",description:"MySQL 配置文件(可能含密码)"},{pattern:/credentials\.json$/i,level:"high",description:"Google Cloud 凭证"},{pattern:/^\.?aws[\\/]credentials$/i,level:"high",description:"AWS 凭证"},{pattern:/^\.?gcp[\\/]credentials$/i,level:"high",description:"GCP 凭证"},{pattern:/^\.?azure[\\/]credentials$/i,level:"high",description:"Azure 凭证"},{pattern:/^service-account.*\.json$/i,level:"high",description:"服务账号密钥"},{pattern:/^\.env$/i,level:"medium",description:"环境变量文件"},{pattern:/^\.env\./i,level:"medium",description:"环境变量文件(带环境后缀)"},{pattern:/^\.?npmrc$/i,level:"medium",description:"npm 配置文件(可能含 token)"},{pattern:/^\.?pypirc$/i,level:"medium",description:"PyPI 配置文件(可能含密码)"},{pattern:/^\.?dockercfg$/i,level:"medium",description:"Docker 配置文件"},{pattern:/^\.?docker[\\/]config\.json$/i,level:"medium",description:"Docker 配置文件"},{pattern:/^\.?netrc$/i,level:"medium",description:"FTP/HTTP 认证文件"},{pattern:/^\.?git-credentials$/i,level:"medium",description:"Git 凭证文件"},{pattern:/^config\.toml$/i,level:"medium",description:"配置文件(可能含敏感信息)"},{pattern:/^secrets\./i,level:"medium",description:"密钥配置文件"},{pattern:/\.sqlite$/i,level:"low",description:"SQLite 数据库"},{pattern:/\.db$/i,level:"low",description:"数据库文件"},{pattern:/\.sql$/i,level:"low",description:"SQL 文件(可能含敏感数据)"}];static SENSITIVE_PATHS=[{path:/\.ssh[\\/]/i,level:"high",description:"SSH 配置目录"},{path:/\.aws[\\/]/i,level:"high",description:"AWS 配置目录"},{path:/\.config[\\/]gcloud[\\/]/i,level:"high",description:"Google Cloud 配置目录"},{path:/\.kube[\\/]/i,level:"high",description:"Kubernetes 配置目录"}];static check($){let Y=this.normalizePath($),Z=G9.basename(Y);for(let X of this.SENSITIVE_PATTERNS)if(this.matchPattern(Z,X.pattern))return{isSensitive:!0,level:X.level,matchedPattern:X.pattern instanceof RegExp?X.pattern.source:X.pattern,reason:X.description};for(let X of this.SENSITIVE_PATHS)if(this.matchPattern(Y,X.path))return{isSensitive:!0,level:X.level,matchedPattern:X.path instanceof RegExp?X.path.source:X.path,reason:X.description};return{isSensitive:!1}}static checkMultiple($){let Y=new Map;for(let Z of $)Y.set(Z,this.check(Z));return Y}static filterSensitive($,Y="low"){let Z={["high"]:3,["medium"]:2,["low"]:1},X=Z[Y];return $.map((Q)=>({path:Q,result:this.check(Q)})).filter(({result:Q})=>Q.isSensitive&&Q.level&&Z[Q.level]>=X)}static normalizePath($){if($.startsWith("~/")||$==="~")return G9.join(yG.homedir(),$.slice(1));return G9.resolve($)}static matchPattern($,Y){if(Y instanceof RegExp)return Y.test($);let Z=Y.replace(/\*/g,".*");return new RegExp(`^${Z}$`,"i").test($)}static getSensitivePatterns(){return[...this.SENSITIVE_PATTERNS]}static getSensitivePaths(){return[...this.SENSITIVE_PATHS]}}});class W9{registry;name="discovery";constructor($){this.registry=$}async process($){let Y=this.registry.get($.toolName);if(!Y){$.abort(`Tool "${$.toolName}" not found`);return}$._internal.tool=Y}}class U9{name="permission";permissionChecker;sessionApprovals;defaultPermissionMode;constructor($,Y,Z){this.permissionChecker=new A2($),this.sessionApprovals=Y,this.defaultPermissionMode=Z}getPermissionChecker(){return this.permissionChecker}async process($){let Y=$._internal.tool;if(!Y){$.abort("Discovery stage failed; cannot perform permission check");return}try{let Z=Y.build($.params),X=Z.getAffectedPaths(),Q={toolName:Y.name,params:$.params,affectedPaths:X,tool:Y},J=A2.buildSignature(Q);$._internal.permissionSignature=J;let q=this.permissionChecker.check(Q),G=$.context.permissionMode||this.defaultPermissionMode;switch(q=this.applyModeOverrides(Y.kind,q,G),q.result){case"deny":$.abort(q.reason||`Tool invocation "${Y.name}" was denied by permission rules: ${q.matchedRule}`);return;case"ask":if(this.sessionApprovals.has(J))q={result:"allow",matchedRule:"remembered:session",reason:"User already allowed this operation in this session"};else $._internal.needsConfirmation=!0,$._internal.confirmationReason=q.reason||"User confirmation required";break;case"allow":break}if(X.length>0){let K=["/etc/","/sys/","/proc/","/dev/","/boot/","/root/","C:\\Windows\\System32","C:\\Program Files","C:\\ProgramData"],W=X.filter((H)=>{if(H.includes(".."))return!0;return K.some((O)=>H.includes(O))});if(W.length>0){$.abort(`Access to dangerous system paths denied: ${W.join(", ")}`);return}let U=K9.filterSensitive(X,"medium");if(U.length>0){let H=U.map(({path:F,result:_})=>`${F} (${_.level}: ${_.reason})`);if(U.filter(({result:F})=>F.level==="high").length>0&&q.result!=="allow"){$.abort(`Access to highly sensitive files denied:
948
959
  ${H.join(`
949
960
  `)}
950
961
 
@@ -952,10 +963,10 @@ If access is required, add an explicit allow rule in permissions.`);return}if(q.
952
963
  ${H.join(`
953
964
  `)}
954
965
 
955
- Confirm to proceed?`,$._internal.needsConfirmation=!0}}$._internal.invocation=Z,$._internal.permissionCheckResult=q}catch(Z){$.abort(`Permission check failed: ${Z.message}`)}}applyModeOverrides($,Y,Z){if(Z==="yolo")return{result:"allow",matchedRule:"mode:yolo",reason:"YOLO mode: automatically approve all tool invocations"};if(Z==="plan"){if(!S$($))return{result:"deny",matchedRule:"mode:plan",reason:"Plan mode: modification tools are blocked; only read-only tools are allowed (Read/Glob/Grep/WebFetch/WebSearch/Task)"}}if(Y.result==="deny")return Y;if(Y.result==="allow")return Y;if(S$($))return{result:"allow",matchedRule:`mode:${Z}:readonly`,reason:"Read-only tools do not require confirmation"};if(Z==="autoEdit"&&$==="write")return{result:"allow",matchedRule:"mode:autoEdit:write",reason:"AUTO_EDIT mode: automatically approve write tools"};return Y}}class J9{sessionApprovals;name="confirmation";permissionChecker;constructor($,Y){this.sessionApprovals=$;this.permissionChecker=Y}async process($){let{tool:Y,invocation:Z,needsConfirmation:X,confirmationReason:Q,permissionCheckResult:J}=$._internal;if(!Y||!Z){$.abort("Pre-confirmation stage failed; cannot request user approval");return}if(!X)return;try{let K={title:`权限确认: ${Y.extractSignatureContent?Y.extractSignatureContent($.params):Y.name}`,message:Q||"此操作需要用户确认",kind:Y.kind,details:this.generatePreviewForTool(Y.name,$.params),risks:this.extractRisksFromPermissionCheck(Y,$.params,J),affectedFiles:Z.getAffectedPaths()||[]};if(M2.warn(`工具 "${Y.name}" 需要用户确认: ${K.title}`),M2.warn(`详情: ${K.message}`),K.risks&&K.risks.length>0)M2.warn(`风险: ${K.risks.join(", ")}`);let G=$.context.confirmationHandler;if(G){let W=await G.requestConfirmation(K);if(!W.approved){$.abort(`User rejected execution: ${W.reason||"No reason provided"}`,{shouldExitLoop:!0});return}if((W.scope||"once")==="session"&&$._internal.permissionSignature){let H=$._internal.permissionSignature;this.sessionApprovals.add(H);let O={toolName:Y.name,params:$.params,affectedPaths:Z.getAffectedPaths()||[],tool:Y};await this.persistSessionApproval(H,O)}}else M2.warn("⚠️ No ConfirmationHandler; auto-approving tool execution (non-interactive environment only)")}catch(q){$.abort(`User confirmation failed: ${q.message}`)}}async persistSessionApproval($,Y){try{let Z=A2.abstractPattern(Y);M2.debug(`保存权限规则: "${Z}"`),await U1().appendLocalPermissionAllowRule(Z,{immediate:!0});let X=V1();if(X?.permissions)M2.debug("同步权限配置到 PermissionChecker:",X.permissions),this.permissionChecker.replaceConfig(X.permissions)}catch(Z){M2.warn(`Failed to persist permission rule "${$}": ${Z instanceof Error?Z.message:"Unknown error"}`)}}generatePreviewForTool($,Y){switch($){case"Edit":{let{old_string:Z,new_string:X}=Y;if(!Z&&!X)return;let Q=20,J=(q)=>{let K=q.split(`
956
- `);if(K.length<=Q)return q;return`${K.slice(0,Q).join(`
966
+ Confirm to proceed?`,$._internal.needsConfirmation=!0}}$._internal.invocation=Z,$._internal.permissionCheckResult=q}catch(Z){$.abort(`Permission check failed: ${Z.message}`)}}applyModeOverrides($,Y,Z){if(Z==="yolo")return{result:"allow",matchedRule:"mode:yolo",reason:"YOLO mode: automatically approve all tool invocations"};if(Z==="plan"){if(!x$($))return{result:"deny",matchedRule:"mode:plan",reason:"Plan mode: modification tools are blocked; only read-only tools are allowed (Read/Glob/Grep/WebFetch/WebSearch/Task)"}}if(Y.result==="deny")return Y;if(Y.result==="allow")return Y;if(x$($))return{result:"allow",matchedRule:`mode:${Z}:readonly`,reason:"Read-only tools do not require confirmation"};if(Z==="autoEdit"&&$==="write")return{result:"allow",matchedRule:"mode:autoEdit:write",reason:"AUTO_EDIT mode: automatically approve write tools"};return Y}}class H9{sessionApprovals;name="confirmation";permissionChecker;constructor($,Y){this.sessionApprovals=$;this.permissionChecker=Y}async process($){let{tool:Y,invocation:Z,needsConfirmation:X,confirmationReason:Q,permissionCheckResult:J}=$._internal;if(!Y||!Z){$.abort("Pre-confirmation stage failed; cannot request user approval");return}if(!X)return;try{let G={title:`权限确认: ${Y.extractSignatureContent?Y.extractSignatureContent($.params):Y.name}`,message:Q||"此操作需要用户确认",kind:Y.kind,details:this.generatePreviewForTool(Y.name,$.params),risks:this.extractRisksFromPermissionCheck(Y,$.params,J),affectedFiles:Z.getAffectedPaths()||[]};if(I2.warn(`工具 "${Y.name}" 需要用户确认: ${G.title}`),I2.warn(`详情: ${G.message}`),G.risks&&G.risks.length>0)I2.warn(`风险: ${G.risks.join(", ")}`);let K=$.context.confirmationHandler;if(K){let W=await K.requestConfirmation(G);if(!W.approved){$.abort(`User rejected execution: ${W.reason||"No reason provided"}`,{shouldExitLoop:!0});return}if((W.scope||"once")==="session"&&$._internal.permissionSignature){let H=$._internal.permissionSignature;this.sessionApprovals.add(H);let O={toolName:Y.name,params:$.params,affectedPaths:Z.getAffectedPaths()||[],tool:Y};await this.persistSessionApproval(H,O)}}else I2.warn("⚠️ No ConfirmationHandler; auto-approving tool execution (non-interactive environment only)")}catch(q){$.abort(`User confirmation failed: ${q.message}`)}}async persistSessionApproval($,Y){try{let Z=A2.abstractPattern(Y);I2.debug(`保存权限规则: "${Z}"`),await H1().appendLocalPermissionAllowRule(Z,{immediate:!0});let X=V1();if(X?.permissions)I2.debug("同步权限配置到 PermissionChecker:",X.permissions),this.permissionChecker.replaceConfig(X.permissions)}catch(Z){I2.warn(`Failed to persist permission rule "${$}": ${Z instanceof Error?Z.message:"Unknown error"}`)}}generatePreviewForTool($,Y){switch($){case"Edit":{let{old_string:Z,new_string:X}=Y;if(!Z&&!X)return;let Q=20,J=(q)=>{let G=q.split(`
967
+ `);if(G.length<=Q)return q;return`${G.slice(0,Q).join(`
957
968
  `)}
958
- ... (还有 ${K.length-Q} 行)`};return`**变更前:**
969
+ ... (还有 ${G.length-Q} 行)`};return`**变更前:**
959
970
  \`\`\`
960
971
  ${J(Z||"(空)")}
961
972
  \`\`\`
@@ -973,44 +984,58 @@ ${Z}
973
984
  ${q}
974
985
  \`\`\`
975
986
 
976
- ... (还有 ${J.length-Q} 行)`}case"Bash":case"Shell":return;default:return}}extractRisksFromPermissionCheck($,Y,Z){let X=[];if(Z?.reason)X.push(Z.reason);if($.name==="Bash"){let Q=Y.command||"",J=Q.trim().split(/\s+/)[0];if(J==="cat"||J==="head"||J==="tail")X.push(`\uD83D\uDCA1 建议使用 Read 工具代替 ${J} 命令(性能更好,支持大文件分页)`);else if(J==="grep"||J==="rg")X.push("\uD83D\uDCA1 建议使用 Grep 工具代替 grep/rg 命令(支持更强大的过滤和上下文)");else if(J==="find")X.push("\uD83D\uDCA1 建议使用 Glob 工具代替 find 命令(更快,支持 glob 模式)");else if(J==="sed"||J==="awk")X.push(`\uD83D\uDCA1 建议使用 Edit 工具代替 ${J} 命令(更安全,支持预览和回滚)`);if(Q.includes("rm"))X.push("⚠️ 此命令可能删除文件");if(Q.includes("sudo"))X.push("⚠️ 此命令需要管理员权限");if(Q.includes("git push"))X.push("⚠️ 此命令将推送代码到远程仓库")}else if($.name==="Write"||$.name==="Edit")X.push("此操作将修改文件内容");else if($.name==="Delete")X.push("此操作将永久删除文件");return X}}class q9{name="execution";async process($){let Y=$._internal.invocation;if(!Y){$.abort("Pre-execution stage failed; cannot run tool");return}try{let Z=await Y.execute($.context.signal,$.context.onProgress,$.context);$.setResult(Z)}catch(Z){$.abort(`Tool execution failed: ${Z.message}`)}}}class K9{name="formatting";async process($){try{let Y=$.getResult();if(!Y.llmContent)Y.llmContent="Execution completed";if(!Y.displayContent)Y.displayContent=Y.success?"执行成功":"执行失败";if(!Y.metadata)Y.metadata={};Y.metadata.executionId=$.context.sessionId,Y.metadata.toolName=$.toolName,Y.metadata.timestamp=Date.now(),$.setResult(Y)}catch(Y){$.abort(`Result formatting failed: ${Y.message}`)}}}var M2;var YY=R(()=>{E4();s1();N1();F1();h1();$Y();M2=u("Execution")});import{EventEmitter as wK}from"events";var G9;var ZY=R(()=>{s1();s5();t5();h4();y0();e5();YY();G9=class G9 extends wK{registry;stages;executionHistory=[];maxHistorySize;sessionApprovals=new Set;constructor($,Y={}){super();this.registry=$;this.maxHistorySize=Y.maxHistorySize||1000;let Z=Y.permissionConfig||{allow:[],ask:[],deny:[]},X=Y.permissionMode??"default",Q=new Q9(Z,this.sessionApprovals,X);this.stages=[new X9(this.registry),Q,new t8,new J9(this.sessionApprovals,Q.getPermissionChecker()),new q9,new e8,new K9]}async execute($,Y,Z){let X=Date.now(),Q=this.generateExecutionId(),J=new f4($,Y,{...Z,sessionId:Z.sessionId||Q});this.emit("executionStarted",{executionId:Q,toolName:$,params:Y,context:Z,timestamp:X});let q=this.registry.get($),K=q&&!q.isConcurrencySafe,G=K&&Y.file_path?String(Y.file_path):null;if(K&&G)return K2.getInstance().acquireLock(G,()=>this.executeWithPipeline(J,Q,X));return this.executeWithPipeline(J,Q,X)}async executeWithPipeline($,Y,Z){try{for(let J of this.stages){if($.context.signal?.aborted){$.abort("任务已被用户中止");break}if(this.emit("stageStarted",{executionId:Y,stageName:J.name,timestamp:Date.now()}),await J.process($),this.emit("stageCompleted",{executionId:Y,stageName:J.name,timestamp:Date.now()}),$.shouldAbort())break}let X=$.getResult(),Q=Date.now();return this.addToHistory({executionId:Y,toolName:$.toolName,params:$.params,result:X,startTime:Z,endTime:Q,context:$.context}),this.emit("executionCompleted",{executionId:Y,toolName:$.toolName,result:X,duration:Q-Z,timestamp:Q}),X}catch(X){let Q={success:!1,llmContent:`Tool execution failed: ${X.message}`,displayContent:`错误: ${X.message}`,error:{type:"execution_error",message:X.message}},J=Date.now();return this.addToHistory({executionId:Y,toolName:$.toolName,params:$.params,result:Q,startTime:Z,endTime:J,context:$.context}),this.emit("executionFailed",{executionId:Y,toolName:$.toolName,error:X,duration:J-Z,timestamp:J}),Q}}async executeAll($){let Y=$.map((Z)=>this.execute(Z.toolName,Z.params,Z.context));return Promise.all(Y)}async executeParallel($,Y=5){let Z=[],X=[];for(let Q=0;Q<$.length;Q++){let J=$[Q],q=this.execute(J.toolName,J.params,J.context);if(X.push(q),X.length>=Y||Q===$.length-1){let K=await Promise.all(X);Z.push(...K),X.length=0}}return Z}getExecutionHistory($){let Y=[...this.executionHistory];return $?Y.slice(-$):Y}clearHistory(){this.executionHistory=[],this.emit("historyClear",{timestamp:Date.now()})}getStats(){let $={totalExecutions:this.executionHistory.length,successfulExecutions:0,failedExecutions:0,averageDuration:0,toolUsage:new Map,recentExecutions:this.executionHistory.slice(-10)},Y=0;for(let Z of this.executionHistory){if(Z.result.success)$.successfulExecutions++;else $.failedExecutions++;let X=Z.endTime-Z.startTime;Y+=X;let Q=$.toolUsage.get(Z.toolName)||0;$.toolUsage.set(Z.toolName,Q+1)}return $.averageDuration=$.totalExecutions>0?Y/$.totalExecutions:0,$}addStage($,Y=-1){if(Y===-1){let Z=this.stages.findIndex((X)=>X.name==="execution");this.stages.splice(Z,0,$)}else this.stages.splice(Y,0,$);this.emit("stageAdded",{stageName:$.name,position:Y,timestamp:Date.now()})}removeStage($){let Y=this.stages.findIndex((Z)=>Z.name===$);if(Y===-1)return!1;return this.stages.splice(Y,1),this.emit("stageRemoved",{stageName:$,timestamp:Date.now()}),!0}getStages(){return[...this.stages]}getRegistry(){return this.registry}generateExecutionId(){return`exec_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}addToHistory($){if(this.executionHistory.push($),this.executionHistory.length>this.maxHistorySize)this.executionHistory=this.executionHistory.slice(-this.maxHistorySize)}}});import{EventEmitter as LK}from"events";var W9;var XY=R(()=>{s1();W9=class W9 extends LK{tools=new Map;mcpTools=new Map;categories=new Map;tags=new Map;constructor(){super()}register($){if(this.tools.has($.name))throw Error(`工具 '${$.name}' 已注册`);this.tools.set($.name,$),this.updateIndexes($),this.emit("toolRegistered",{type:"builtin",tool:$,timestamp:Date.now()})}registerAll($){let Y=[];for(let Z of $)try{this.register(Z)}catch(X){Y.push(`${Z.name}: ${X.message}`)}if(Y.length>0)throw Error(`批量注册失败: ${Y.join(", ")}`)}unregister($){let Y=this.tools.get($);if(!Y)return!1;return this.tools.delete($),this.removeFromIndexes(Y),this.emit("toolUnregistered",{type:"builtin",toolName:$,timestamp:Date.now()}),!0}get($){return this.tools.get($)||this.mcpTools.get($)}has($){return this.tools.has($)||this.mcpTools.has($)}getAll(){return[...Array.from(this.tools.values()),...Array.from(this.mcpTools.values())]}getBuiltinTools(){return Array.from(this.tools.values())}getMcpTools(){return Array.from(this.mcpTools.values())}getByCategory($){let Y=this.categories.get($);if(!Y)return[];return Array.from(Y).map((Z)=>this.get(Z)).filter((Z)=>Z!==void 0)}getByTag($){let Y=this.tags.get($);if(!Y)return[];return Array.from(Y).map((Z)=>this.get(Z)).filter((Z)=>Z!==void 0)}search($){let Y=$.toLowerCase();return this.getAll().filter((Z)=>{let X=typeof Z.description==="string"?Z.description:Z.description.short;return Z.name.toLowerCase().includes(Y)||X.toLowerCase().includes(Y)||Z.displayName.toLowerCase().includes(Y)||Z.category&&Z.category.toLowerCase().includes(Y)||Z.tags.some((Q)=>Q.toLowerCase().includes(Y))})}getFunctionDeclarations(){return this.getAll().map(($)=>$.getFunctionDeclaration())}getReadOnlyFunctionDeclarations(){return this.getAll().filter(($)=>$.isReadOnly).map(($)=>$.getFunctionDeclaration())}getFunctionDeclarationsByMode($){if($==="plan")return this.getReadOnlyFunctionDeclarations();return this.getFunctionDeclarations()}getReadOnlyTools(){return this.getAll().filter(($)=>$.isReadOnly)}getCategories(){return Array.from(this.categories.keys())}getTags(){return Array.from(this.tags.keys())}getStats(){return{totalTools:this.tools.size+this.mcpTools.size,builtinTools:this.tools.size,mcpTools:this.mcpTools.size,categories:this.categories.size,tags:this.tags.size,toolsByCategory:Object.fromEntries(Array.from(this.categories.entries()).map(([$,Y])=>[$,Y.size]))}}registerMcpTool($){if(this.mcpTools.has($.name))this.mcpTools.delete($.name);this.mcpTools.set($.name,$),this.updateIndexes($),this.emit("toolRegistered",{type:"mcp",tool:$,timestamp:Date.now()})}removeMcpTools($){let Y=0,Z=`mcp__${$}__`;for(let[X,Q]of this.mcpTools.entries())if(X.startsWith(Z))this.mcpTools.delete(X),this.removeFromIndexes(Q),Y++,this.emit("toolUnregistered",{type:"mcp",toolName:X,serverName:$,timestamp:Date.now()});return Y}updateIndexes($){if($.category){if(!this.categories.has($.category))this.categories.set($.category,new Set);this.categories.get($.category).add($.name)}for(let Y of $.tags){if(!this.tags.has(Y))this.tags.set(Y,new Set);this.tags.get(Y).add($.name)}}removeFromIndexes($){if($.category){let Y=this.categories.get($.category);if(Y){if(Y.delete($.name),Y.size===0)this.categories.delete($.category)}}for(let Y of $.tags){let Z=this.tags.get(Y);if(Z){if(Z.delete($.name),Z.size===0)this.tags.delete(Y)}}}}});function RK($){return AK.some((Y)=>Y.test($))}function bK($){if($.supportsThinking!==void 0)return{supportsThinking:$.supportsThinking,thinkingBudget:$.thinkingBudget};return{supportsThinking:RK($.model),thinkingBudget:void 0}}function q$($){return bK($).supportsThinking}var AK;var m6=R(()=>{AK=[/deepseek.*r1/i,/deepseek.*reasoner/i,/o1-preview/i,/o1-mini/i,/o1/i,/qwen.*qwq/i,/qwen.*think/i,/kimi.*k1/i,/moonshot.*think/i,/k1-32k/i,/doubao.*think/i,/doubao.*pro.*think/i,/claude.*opus.*4/i]});class U9{maxSummaryLength;keyPointsLimit;recentMessagesLimit;constructor($=500,Y=10,Z=20){this.maxSummaryLength=$,this.keyPointsLimit=Y,this.recentMessagesLimit=Z}async compress($){let Y=$.layers.conversation.messages,Z=$.layers.tool.recentCalls,X=Y.filter((H)=>H.role==="system"),Q=Y.filter((H)=>H.role!=="system"),J=this.getRecentMessages(Q),q=Q.slice(0,-this.recentMessagesLimit),K=await this.generateSummary(q),G=this.extractKeyPoints(q,Z),W=this.generateToolSummary(Z),U=this.estimateTokenCount(K,G,J,W);return{summary:K,keyPoints:G,recentMessages:[...X,...J],toolSummary:W,tokenCount:U}}getRecentMessages($){return $.slice(-this.recentMessagesLimit)}async generateSummary($){if($.length===0)return"";let Y=new Set,Z=new Set,X=new Set;for(let J of $){let q=J.content.toLowerCase();["关于","讨论","问题","项目","功能","需求"].forEach((U)=>{if(q.includes(U)){let H=this.extractContext(q,U,50);if(H)Y.add(H)}}),["创建","删除","修改","更新","实现","开发"].forEach((U)=>{if(q.includes(U)){let H=this.extractContext(q,U,30);if(H)Z.add(H)}}),["决定","选择","确定","采用","使用"].forEach((U)=>{if(q.includes(U)){let H=this.extractContext(q,U,40);if(H)X.add(H)}})}let Q=`对话涉及 ${$.length} 条消息。`;if(Y.size>0)Q+=` 主要讨论:${Array.from(Y).slice(0,3).join("、")}。`;if(Z.size>0)Q+=` 执行操作:${Array.from(Z).slice(0,3).join("、")}。`;if(X.size>0)Q+=` 关键决策:${Array.from(X).slice(0,2).join("、")}。`;return Q.length>this.maxSummaryLength?Q.substring(0,this.maxSummaryLength)+"...":Q}extractKeyPoints($,Y){let Z=new Set;for(let Q of $)if(Q.role==="user")this.extractQuestions(Q.content).forEach((K)=>Z.add(`用户问题:${K}`)),this.extractRequests(Q.content).forEach((K)=>Z.add(`用户请求:${K}`));else if(Q.role==="assistant")this.extractSolutions(Q.content).forEach((q)=>Z.add(`解决方案:${q}`));return this.summarizeToolUsage(Y).forEach((Q)=>Z.add(`工具使用:${Q}`)),Array.from(Z).slice(0,this.keyPointsLimit)}generateToolSummary($){if($.length===0)return"";let Y=new Map,Z=Date.now()-600000;for(let Q of $){let J=Y.get(Q.name)||{count:0,success:0,recent:0};if(J.count++,Q.status==="success")J.success++;if(Q.timestamp>Z)J.recent++;Y.set(Q.name,J)}let X=[];for(let[Q,J]of Array.from(Y.entries())){let q=Math.round(J.success/J.count*100);X.push(`${Q}(${J.count}次,成功率${q}%)`)}return`工具调用:${X.join("、")}`}estimateTokenCount($,Y,Z,X){let Q=$.length+Y.join(" ").length;if(X)Q+=X.length;for(let J of Z)Q+=J.content.length;return Math.ceil(Q/4)}extractContext($,Y,Z){let X=$.indexOf(Y);if(X===-1)return null;let Q=Math.max(0,X-Z/2),J=Math.min($.length,X+Z/2);return $.substring(Q,J).trim()}extractQuestions($){let Y=[],Z=["?","?","如何","怎么","什么","为什么"],X=$.split(/[。!.!]/);for(let Q of X)if(Z.some((J)=>Q.includes(J))){let J=Q.trim();if(J.length>5&&J.length<100)Y.push(J)}return Y.slice(0,3)}extractRequests($){let Y=[],Z=["请","帮我","需要","想要","希望","能否"],X=$.split(/[。!.!]/);for(let Q of X)if(Z.some((J)=>Q.includes(J))){let J=Q.trim();if(J.length>5&&J.length<100)Y.push(J)}return Y.slice(0,3)}extractSolutions($){let Y=[],Z=["可以","建议","推荐","应该","最好","解决方案"],X=$.split(/[。!.!]/);for(let Q of X)if(Z.some((J)=>Q.includes(J))){let J=Q.trim();if(J.length>10&&J.length<150)Y.push(J)}return Y.slice(0,3)}summarizeToolUsage($){let Y=[],Z=$.filter((X)=>Date.now()-X.timestamp<1800000);if(Z.length>0){let X=new Map;Z.forEach((Q)=>{let J=X.get(Q.name)||[];J.push(Q),X.set(Q.name,J)});for(let[Q,J]of Array.from(X.entries())){let q=J.filter((K)=>K.status==="success").length;Y.push(`${Q}(${J.length}次,${q}成功)`)}}return Y.slice(0,5)}shouldCompress($,Y){return this.estimateCurrentTokens($)>Y*0.8}estimateCurrentTokens($){let Z=$.layers.conversation.messages.reduce((X,Q)=>X+Q.content.length,0);return Math.ceil(Z/4)}}class I2{defaultOptions;constructor($){this.defaultOptions={maxTokens:32000,maxMessages:50,timeWindow:86400000,priority:1,includeTools:!0,includeWorkspace:!0,...$}}filter($,Y){let Z={...this.defaultOptions,...Y},X={layers:{system:$.layers.system,session:$.layers.session,conversation:this.filterConversation($.layers.conversation,Z),tool:Z.includeTools?this.filterTools($.layers.tool,Z):{recentCalls:[],toolStates:{},dependencies:{}},workspace:Z.includeWorkspace?$.layers.workspace:{currentFiles:[],recentFiles:[],environment:{}}},metadata:{...$.metadata,lastUpdated:Date.now()}};return X.metadata.totalTokens=this.estimateTokens(X),X}filterConversation($,Y){let Z=[...$.messages];if(Y.timeWindow>0){let X=Date.now()-Y.timeWindow;Z=Z.filter((Q)=>Q.timestamp>=X||Q.role==="system")}if(Y.priority>1)Z=this.filterByPriority(Z,Y.priority);if(Y.maxMessages>0)Z=this.limitMessages(Z,Y.maxMessages);if(Y.maxTokens>0)Z=this.limitByTokens(Z,Y.maxTokens);return{messages:Z,summary:$.summary,topics:this.updateTopics(Z,$.topics),lastActivity:$.lastActivity}}filterTools($,Y){let Z=[...$.recentCalls];if(Y.timeWindow>0){let G=Date.now()-Y.timeWindow;Z=Z.filter((W)=>W.timestamp>=G)}let X=Z.filter((G)=>G.status==="success"),Q=Z.filter((G)=>G.status==="error"),J=Math.min(20,X.length),q=Math.min(10,Q.length);return{recentCalls:[...X.slice(-J),...Q.slice(-q)].sort((G,W)=>G.timestamp-W.timestamp),toolStates:$.toolStates,dependencies:$.dependencies}}filterByPriority($,Y){return $.filter((Z)=>{if(Z.role==="system")return!0;return this.calculateMessagePriority(Z)>=Y})}calculateMessagePriority($){let Y=1;if($.role==="system")Y+=3;else if($.role==="assistant")Y+=1;let Z=$.content.toLowerCase();if(["错误","警告","重要","关键","问题","解决"].some((J)=>Z.includes(J)))Y+=2;if(Z.includes("```")||Z.includes("function")||Z.includes("class"))Y+=1;let Q=(Date.now()-$.timestamp)/3600000;if(Q<1)Y+=2;else if(Q<6)Y+=1;return Y}limitMessages($,Y){if($.length<=Y)return $;let Z=$.filter((q)=>q.role==="system"),X=$.filter((q)=>q.role!=="system"),Q=Y-Z.length,J=Q>0?X.slice(-Q):[];return[...Z,...J].sort((q,K)=>q.timestamp-K.timestamp)}limitByTokens($,Y){if(Y<=0)return $;let Z=0,X=[];for(let Q=$.length-1;Q>=0;Q--){let J=$[Q],q=this.estimateMessageTokens(J);if(J.role==="system")if(Z+q<=Y)X.unshift(J),Z+=q;else{let K=this.compressMessage(J,Y-Z);X.unshift(K),Z+=this.estimateMessageTokens(K)}else if(Z+q<=Y)X.unshift(J),Z+=q;else break}return X.sort((Q,J)=>Q.timestamp-J.timestamp)}estimateMessageTokens($){return Math.ceil($.content.length/4)}compressMessage($,Y){let Z=Y*4;if($.content.length<=Z)return $;let X=$.content.substring(0,Z-3)+"...";return{...$,content:X,metadata:{...$.metadata,compressed:!0,originalLength:$.content.length}}}updateTopics($,Y){let Z=new Set(Y);for(let X of $)this.extractTopicsFromMessage(X).forEach((J)=>Z.add(J));return Array.from(Z).slice(0,10)}extractTopicsFromMessage($){let Y=$.content.toLowerCase(),Z=[];return["项目","功能","模块","组件","服务","接口","数据库","前端","后端","算法","架构","设计"].forEach((Q)=>{if(Y.includes(Q))Z.push(Q)}),Z}estimateTokens($){let Y=0;for(let X of $.layers.conversation.messages)Y+=this.estimateMessageTokens(X);let Z=JSON.stringify($.layers.system);if(Y+=Math.ceil(Z.length/4),$.layers.tool.recentCalls.length>0){let X=JSON.stringify($.layers.tool);Y+=Math.ceil(X.length/8)}return Y}static createPresets(){return{lightweight:new I2({maxTokens:1000,maxMessages:10,timeWindow:7200000,includeTools:!1,includeWorkspace:!1}),standard:new I2({maxTokens:4000,maxMessages:30,timeWindow:43200000,includeTools:!0,includeWorkspace:!0}),comprehensive:new I2({maxTokens:8000,maxMessages:100,timeWindow:86400000,includeTools:!0,includeWorkspace:!0}),debug:new I2({maxTokens:2000,maxMessages:20,timeWindow:21600000,priority:2,includeTools:!0,includeWorkspace:!1})}}}class H9{cache=new Map;maxSize;defaultTTL;constructor($=100,Y=300000){this.maxSize=$,this.defaultTTL=Y}set($,Y,Z){let X=Date.now(),Q={data:Y,timestamp:X,accessCount:0,lastAccess:X,ttl:Z||this.defaultTTL};if(this.cache.size>=this.maxSize&&!this.cache.has($))this.evictLeastUsed();this.cache.set($,Q)}get($){let Y=this.cache.get($);if(!Y)return null;let Z=Date.now();if(Z-Y.timestamp>Y.ttl)return this.cache.delete($),null;return Y.accessCount++,Y.lastAccess=Z,Y.data}has($){let Y=this.cache.get($);if(!Y)return!1;if(Date.now()-Y.timestamp>Y.ttl)return this.cache.delete($),!1;return!0}delete($){return this.cache.delete($)}clear(){this.cache.clear()}size(){return this.cleanExpired(),this.cache.size}cacheMessageSummary($,Y,Z){let X=`summary:${$}:${Y.length}`;this.set(X,{summary:Z,messageCount:Y.length,lastMessage:Y[Y.length-1]?.timestamp||0},600000)}getMessageSummary($,Y){let Z=`summary:${$}:${Y}`;return this.get(Z)}cacheToolResult($,Y,Z){let X=this.hashInput(Y),Q=`tool:${$}:${X}`;this.set(Q,Z,1800000)}getToolResult($,Y){let Z=this.hashInput(Y),X=`tool:${$}:${Z}`;return this.get(X)}cacheCompressedContext($,Y){let Z=`compressed:${$}`;this.set(Z,Y,900000)}getCompressedContext($){let Y=`compressed:${$}`;return this.get(Y)}getStats(){this.cleanExpired();let $=0,Y=0,Z=[];for(let[X,Q]of Array.from(this.cache.entries()))$+=Q.accessCount,Y+=this.estimateItemSize(Q),Z.push({key:X,accessCount:Q.accessCount,lastAccess:Q.lastAccess});return Z.sort((X,Q)=>Q.accessCount-X.accessCount),{size:this.cache.size,maxSize:this.maxSize,hitRate:$>0?$/($+this.cache.size):0,memoryUsage:Y,topKeys:Z.slice(0,10)}}cleanExpired(){let $=Date.now(),Y=[];for(let[Z,X]of Array.from(this.cache.entries()))if($-X.timestamp>X.ttl)Y.push(Z);Y.forEach((Z)=>this.cache.delete(Z))}evictLeastUsed(){let $=null,Y=1/0,Z=Date.now();for(let[X,Q]of Array.from(this.cache.entries())){let J=1/(Z-Q.lastAccess+1),q=Q.accessCount,K=J*q;if(K<Y)Y=K,$=X}if($)this.cache.delete($)}hashInput($){let Y=JSON.stringify($),Z=0;for(let X=0;X<Y.length;X++){let Q=Y.charCodeAt(X);Z=(Z<<5)-Z+Q,Z=Z&Z}return Math.abs(Z).toString(36)}estimateItemSize($){try{return JSON.stringify($).length*2}catch{return 1000}}setTTL($,Y){let Z=this.cache.get($);if(Z)return Z.ttl=Y,Z.timestamp=Date.now(),!0;return!1}getRemainingTTL($){let Y=this.cache.get($);if(!Y)return-1;let Z=Y.ttl-(Date.now()-Y.timestamp);return Math.max(0,Z)}warmup($){$.forEach(({key:Y,value:Z,ttl:X})=>{this.set(Y,Z,X)})}}class O9{contextData=null;maxSize;accessLog=new Map;constructor($=1000){this.maxSize=$}setContext($){this.contextData={...$},this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("context")}getContext(){if(this.contextData)this.recordAccess("context");return this.contextData}addMessage($){if(!this.contextData)throw Error("上下文数据未初始化");this.contextData.layers.conversation.messages.push($),this.contextData.layers.conversation.lastActivity=Date.now(),this.contextData.metadata.lastUpdated=Date.now(),this.enforceMemoryLimit(),this.recordAccess("messages")}getRecentMessages($=10){if(!this.contextData)return[];let Y=this.contextData.layers.conversation.messages;return this.recordAccess("messages"),Y.slice(-$)}addToolCall($){if(!this.contextData)throw Error("上下文数据未初始化");if(this.contextData.layers.tool.recentCalls.push($),this.contextData.metadata.lastUpdated=Date.now(),this.contextData.layers.tool.recentCalls.length>50)this.contextData.layers.tool.recentCalls=this.contextData.layers.tool.recentCalls.slice(-25);this.recordAccess("tools")}updateToolState($,Y){if(!this.contextData)throw Error("上下文数据未初始化");this.contextData.layers.tool.toolStates[$]=Y,this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("tools")}getToolState($){if(!this.contextData)return null;return this.recordAccess("tools"),this.contextData.layers.tool.toolStates[$]}updateWorkspace($){if(!this.contextData)throw Error("上下文数据未初始化");Object.assign(this.contextData.layers.workspace,$),this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("workspace")}clear(){this.contextData=null,this.accessLog.clear()}getMemoryInfo(){if(!this.contextData)return{hasData:!1,messageCount:0,toolCallCount:0,lastUpdated:null};return{hasData:!0,messageCount:this.contextData.layers.conversation.messages.length,toolCallCount:this.contextData.layers.tool.recentCalls.length,lastUpdated:this.contextData.metadata.lastUpdated}}recordAccess($){this.accessLog.set($,Date.now())}enforceMemoryLimit(){if(!this.contextData)return;let $=this.contextData.layers.conversation.messages;if($.length>this.maxSize){let Y=Math.floor(this.maxSize*0.8);this.contextData.layers.conversation.messages=$.slice(-Y)}}getMemoryUsage(){if(!this.contextData)return 0;return JSON.stringify(this.contextData).length}}import*as d6 from"node:fs";import{createReadStream as VK}from"node:fs";import*as u1 from"node:fs/promises";import*as z9 from"node:path";import{createInterface as DK}from"node:readline";class b0{filePath;constructor($){this.filePath=$}async append($){try{await u1.mkdir(z9.dirname(this.filePath),{recursive:!0});let Y=JSON.stringify($)+`
977
- `;await u1.appendFile(this.filePath,Y,"utf-8")}catch(Y){throw console.error(`[JSONLStore] 追加写入失败: ${this.filePath}`,Y),Y}}async appendBatch($){try{await u1.mkdir(z9.dirname(this.filePath),{recursive:!0});let Y=$.map((Z)=>JSON.stringify(Z)).join(`
987
+ ... (还有 ${J.length-Q} 行)`}case"Bash":case"Shell":return;default:return}}extractRisksFromPermissionCheck($,Y,Z){let X=[];if(Z?.reason)X.push(Z.reason);if($.name==="Bash"){let Q=Y.command||"",J=Q.trim().split(/\s+/)[0];if(J==="cat"||J==="head"||J==="tail")X.push(`\uD83D\uDCA1 建议使用 Read 工具代替 ${J} 命令(性能更好,支持大文件分页)`);else if(J==="grep"||J==="rg")X.push("\uD83D\uDCA1 建议使用 Grep 工具代替 grep/rg 命令(支持更强大的过滤和上下文)");else if(J==="find")X.push("\uD83D\uDCA1 建议使用 Glob 工具代替 find 命令(更快,支持 glob 模式)");else if(J==="sed"||J==="awk")X.push(`\uD83D\uDCA1 建议使用 Edit 工具代替 ${J} 命令(更安全,支持预览和回滚)`);if(Q.includes("rm"))X.push("⚠️ 此命令可能删除文件");if(Q.includes("sudo"))X.push("⚠️ 此命令需要管理员权限");if(Q.includes("git push"))X.push("⚠️ 此命令将推送代码到远程仓库")}else if($.name==="Write"||$.name==="Edit")X.push("此操作将修改文件内容");else if($.name==="Delete")X.push("此操作将永久删除文件");return X}}class O9{name="execution";async process($){let Y=$._internal.invocation;if(!Y){$.abort("Pre-execution stage failed; cannot run tool");return}try{let Z=await Y.execute($.context.signal,$.context.onProgress,$.context);$.setResult(Z)}catch(Z){$.abort(`Tool execution failed: ${Z.message}`)}}}class F9{name="formatting";async process($){try{let Y=$.getResult();if(!Y.llmContent)Y.llmContent="Execution completed";if(!Y.displayContent)Y.displayContent=Y.success?"执行成功":"执行失败";if(!Y.metadata)Y.metadata={};Y.metadata.executionId=$.context.sessionId,Y.metadata.toolName=$.toolName,Y.metadata.timestamp=Date.now(),$.setResult(Y)}catch(Y){$.abort(`Result formatting failed: ${Y.message}`)}}}var I2;var HY=D(()=>{f4();s1();B1();z1();p1();UY();I2=l("Execution")});import{EventEmitter as PG}from"events";var z9;var OY=D(()=>{s1();GY();KY();c4();y0();WY();HY();z9=class z9 extends PG{registry;stages;executionHistory=[];maxHistorySize;sessionApprovals=new Set;constructor($,Y={}){super();this.registry=$;this.maxHistorySize=Y.maxHistorySize||1000;let Z=Y.permissionConfig||{allow:[],ask:[],deny:[]},X=Y.permissionMode??"default",Q=new U9(Z,this.sessionApprovals,X);this.stages=[new W9(this.registry),Q,new Q9,new H9(this.sessionApprovals,Q.getPermissionChecker()),new O9,new J9,new F9]}async execute($,Y,Z){let X=Date.now(),Q=this.generateExecutionId(),J=new u4($,Y,{...Z,sessionId:Z.sessionId||Q});this.emit("executionStarted",{executionId:Q,toolName:$,params:Y,context:Z,timestamp:X});let q=this.registry.get($),G=q&&!q.isConcurrencySafe,K=G&&Y.file_path?String(Y.file_path):null;if(G&&K)return U2.getInstance().acquireLock(K,()=>this.executeWithPipeline(J,Q,X));return this.executeWithPipeline(J,Q,X)}async executeWithPipeline($,Y,Z){try{for(let J of this.stages){if($.context.signal?.aborted){$.abort("任务已被用户中止");break}if(this.emit("stageStarted",{executionId:Y,stageName:J.name,timestamp:Date.now()}),await J.process($),this.emit("stageCompleted",{executionId:Y,stageName:J.name,timestamp:Date.now()}),$.shouldAbort())break}let X=$.getResult(),Q=Date.now();return this.addToHistory({executionId:Y,toolName:$.toolName,params:$.params,result:X,startTime:Z,endTime:Q,context:$.context}),this.emit("executionCompleted",{executionId:Y,toolName:$.toolName,result:X,duration:Q-Z,timestamp:Q}),X}catch(X){let Q={success:!1,llmContent:`Tool execution failed: ${X.message}`,displayContent:`错误: ${X.message}`,error:{type:"execution_error",message:X.message}},J=Date.now();return this.addToHistory({executionId:Y,toolName:$.toolName,params:$.params,result:Q,startTime:Z,endTime:J,context:$.context}),this.emit("executionFailed",{executionId:Y,toolName:$.toolName,error:X,duration:J-Z,timestamp:J}),Q}}async executeAll($){let Y=$.map((Z)=>this.execute(Z.toolName,Z.params,Z.context));return Promise.all(Y)}async executeParallel($,Y=5){let Z=[],X=[];for(let Q=0;Q<$.length;Q++){let J=$[Q],q=this.execute(J.toolName,J.params,J.context);if(X.push(q),X.length>=Y||Q===$.length-1){let G=await Promise.all(X);Z.push(...G),X.length=0}}return Z}getExecutionHistory($){let Y=[...this.executionHistory];return $?Y.slice(-$):Y}clearHistory(){this.executionHistory=[],this.emit("historyClear",{timestamp:Date.now()})}getStats(){let $={totalExecutions:this.executionHistory.length,successfulExecutions:0,failedExecutions:0,averageDuration:0,toolUsage:new Map,recentExecutions:this.executionHistory.slice(-10)},Y=0;for(let Z of this.executionHistory){if(Z.result.success)$.successfulExecutions++;else $.failedExecutions++;let X=Z.endTime-Z.startTime;Y+=X;let Q=$.toolUsage.get(Z.toolName)||0;$.toolUsage.set(Z.toolName,Q+1)}return $.averageDuration=$.totalExecutions>0?Y/$.totalExecutions:0,$}addStage($,Y=-1){if(Y===-1){let Z=this.stages.findIndex((X)=>X.name==="execution");this.stages.splice(Z,0,$)}else this.stages.splice(Y,0,$);this.emit("stageAdded",{stageName:$.name,position:Y,timestamp:Date.now()})}removeStage($){let Y=this.stages.findIndex((Z)=>Z.name===$);if(Y===-1)return!1;return this.stages.splice(Y,1),this.emit("stageRemoved",{stageName:$,timestamp:Date.now()}),!0}getStages(){return[...this.stages]}getRegistry(){return this.registry}generateExecutionId(){return`exec_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}addToHistory($){if(this.executionHistory.push($),this.executionHistory.length>this.maxHistorySize)this.executionHistory=this.executionHistory.slice(-this.maxHistorySize)}}});import{EventEmitter as TG}from"events";var _9;var FY=D(()=>{s1();_9=class _9 extends TG{tools=new Map;mcpTools=new Map;categories=new Map;tags=new Map;constructor(){super()}register($){if(this.tools.has($.name))throw Error(`工具 '${$.name}' 已注册`);this.tools.set($.name,$),this.updateIndexes($),this.emit("toolRegistered",{type:"builtin",tool:$,timestamp:Date.now()})}registerAll($){let Y=[];for(let Z of $)try{this.register(Z)}catch(X){Y.push(`${Z.name}: ${X.message}`)}if(Y.length>0)throw Error(`批量注册失败: ${Y.join(", ")}`)}unregister($){let Y=this.tools.get($);if(!Y)return!1;return this.tools.delete($),this.removeFromIndexes(Y),this.emit("toolUnregistered",{type:"builtin",toolName:$,timestamp:Date.now()}),!0}get($){return this.tools.get($)||this.mcpTools.get($)}has($){return this.tools.has($)||this.mcpTools.has($)}getAll(){return[...Array.from(this.tools.values()),...Array.from(this.mcpTools.values())]}getBuiltinTools(){return Array.from(this.tools.values())}getMcpTools(){return Array.from(this.mcpTools.values())}getByCategory($){let Y=this.categories.get($);if(!Y)return[];return Array.from(Y).map((Z)=>this.get(Z)).filter((Z)=>Z!==void 0)}getByTag($){let Y=this.tags.get($);if(!Y)return[];return Array.from(Y).map((Z)=>this.get(Z)).filter((Z)=>Z!==void 0)}search($){let Y=$.toLowerCase();return this.getAll().filter((Z)=>{let X=typeof Z.description==="string"?Z.description:Z.description.short;return Z.name.toLowerCase().includes(Y)||X.toLowerCase().includes(Y)||Z.displayName.toLowerCase().includes(Y)||Z.category&&Z.category.toLowerCase().includes(Y)||Z.tags.some((Q)=>Q.toLowerCase().includes(Y))})}getFunctionDeclarations(){return this.getAll().map(($)=>$.getFunctionDeclaration())}getReadOnlyFunctionDeclarations(){return this.getAll().filter(($)=>$.isReadOnly).map(($)=>$.getFunctionDeclaration())}getFunctionDeclarationsByMode($){if($==="plan")return this.getReadOnlyFunctionDeclarations();return this.getFunctionDeclarations()}getReadOnlyTools(){return this.getAll().filter(($)=>$.isReadOnly)}getCategories(){return Array.from(this.categories.keys())}getTags(){return Array.from(this.tags.keys())}getStats(){return{totalTools:this.tools.size+this.mcpTools.size,builtinTools:this.tools.size,mcpTools:this.mcpTools.size,categories:this.categories.size,tags:this.tags.size,toolsByCategory:Object.fromEntries(Array.from(this.categories.entries()).map(([$,Y])=>[$,Y.size]))}}registerMcpTool($){if(this.mcpTools.has($.name))this.mcpTools.delete($.name);this.mcpTools.set($.name,$),this.updateIndexes($),this.emit("toolRegistered",{type:"mcp",tool:$,timestamp:Date.now()})}removeMcpTools($){let Y=0,Z=`mcp__${$}__`;for(let[X,Q]of this.mcpTools.entries())if(X.startsWith(Z))this.mcpTools.delete(X),this.removeFromIndexes(Q),Y++,this.emit("toolUnregistered",{type:"mcp",toolName:X,serverName:$,timestamp:Date.now()});return Y}updateIndexes($){if($.category){if(!this.categories.has($.category))this.categories.set($.category,new Set);this.categories.get($.category).add($.name)}for(let Y of $.tags){if(!this.tags.has(Y))this.tags.set(Y,new Set);this.tags.get(Y).add($.name)}}removeFromIndexes($){if($.category){let Y=this.categories.get($.category);if(Y){if(Y.delete($.name),Y.size===0)this.categories.delete($.category)}}for(let Y of $.tags){let Z=this.tags.get(Y);if(Z){if(Z.delete($.name),Z.size===0)this.tags.delete(Y)}}}}});function CG($){return SG.some((Y)=>Y.test($))}function fG($){if($.supportsThinking!==void 0)return{supportsThinking:$.supportsThinking,thinkingBudget:$.thinkingBudget};return{supportsThinking:CG($.model),thinkingBudget:void 0}}function K$($){return fG($).supportsThinking}var SG;var r6=D(()=>{SG=[/deepseek.*r1/i,/deepseek.*reasoner/i,/o1-preview/i,/o1-mini/i,/o1/i,/qwen.*qwq/i,/qwen.*think/i,/kimi.*k1/i,/moonshot.*think/i,/k1-32k/i,/doubao.*think/i,/doubao.*pro.*think/i,/claude.*opus.*4/i]});class N9{maxSummaryLength;keyPointsLimit;recentMessagesLimit;constructor($=500,Y=10,Z=20){this.maxSummaryLength=$,this.keyPointsLimit=Y,this.recentMessagesLimit=Z}async compress($){let Y=$.layers.conversation.messages,Z=$.layers.tool.recentCalls,X=Y.filter((H)=>H.role==="system"),Q=Y.filter((H)=>H.role!=="system"),J=this.getRecentMessages(Q),q=Q.slice(0,-this.recentMessagesLimit),G=await this.generateSummary(q),K=this.extractKeyPoints(q,Z),W=this.generateToolSummary(Z),U=this.estimateTokenCount(G,K,J,W);return{summary:G,keyPoints:K,recentMessages:[...X,...J],toolSummary:W,tokenCount:U}}getRecentMessages($){return $.slice(-this.recentMessagesLimit)}async generateSummary($){if($.length===0)return"";let Y=new Set,Z=new Set,X=new Set;for(let J of $){let q=J.content.toLowerCase();["关于","讨论","问题","项目","功能","需求"].forEach((U)=>{if(q.includes(U)){let H=this.extractContext(q,U,50);if(H)Y.add(H)}}),["创建","删除","修改","更新","实现","开发"].forEach((U)=>{if(q.includes(U)){let H=this.extractContext(q,U,30);if(H)Z.add(H)}}),["决定","选择","确定","采用","使用"].forEach((U)=>{if(q.includes(U)){let H=this.extractContext(q,U,40);if(H)X.add(H)}})}let Q=`对话涉及 ${$.length} 条消息。`;if(Y.size>0)Q+=` 主要讨论:${Array.from(Y).slice(0,3).join("、")}。`;if(Z.size>0)Q+=` 执行操作:${Array.from(Z).slice(0,3).join("、")}。`;if(X.size>0)Q+=` 关键决策:${Array.from(X).slice(0,2).join("、")}。`;return Q.length>this.maxSummaryLength?Q.substring(0,this.maxSummaryLength)+"...":Q}extractKeyPoints($,Y){let Z=new Set;for(let Q of $)if(Q.role==="user")this.extractQuestions(Q.content).forEach((G)=>Z.add(`用户问题:${G}`)),this.extractRequests(Q.content).forEach((G)=>Z.add(`用户请求:${G}`));else if(Q.role==="assistant")this.extractSolutions(Q.content).forEach((q)=>Z.add(`解决方案:${q}`));return this.summarizeToolUsage(Y).forEach((Q)=>Z.add(`工具使用:${Q}`)),Array.from(Z).slice(0,this.keyPointsLimit)}generateToolSummary($){if($.length===0)return"";let Y=new Map,Z=Date.now()-600000;for(let Q of $){let J=Y.get(Q.name)||{count:0,success:0,recent:0};if(J.count++,Q.status==="success")J.success++;if(Q.timestamp>Z)J.recent++;Y.set(Q.name,J)}let X=[];for(let[Q,J]of Array.from(Y.entries())){let q=Math.round(J.success/J.count*100);X.push(`${Q}(${J.count}次,成功率${q}%)`)}return`工具调用:${X.join("、")}`}estimateTokenCount($,Y,Z,X){let Q=$.length+Y.join(" ").length;if(X)Q+=X.length;for(let J of Z)Q+=J.content.length;return Math.ceil(Q/4)}extractContext($,Y,Z){let X=$.indexOf(Y);if(X===-1)return null;let Q=Math.max(0,X-Z/2),J=Math.min($.length,X+Z/2);return $.substring(Q,J).trim()}extractQuestions($){let Y=[],Z=["?","?","如何","怎么","什么","为什么"],X=$.split(/[。!.!]/);for(let Q of X)if(Z.some((J)=>Q.includes(J))){let J=Q.trim();if(J.length>5&&J.length<100)Y.push(J)}return Y.slice(0,3)}extractRequests($){let Y=[],Z=["请","帮我","需要","想要","希望","能否"],X=$.split(/[。!.!]/);for(let Q of X)if(Z.some((J)=>Q.includes(J))){let J=Q.trim();if(J.length>5&&J.length<100)Y.push(J)}return Y.slice(0,3)}extractSolutions($){let Y=[],Z=["可以","建议","推荐","应该","最好","解决方案"],X=$.split(/[。!.!]/);for(let Q of X)if(Z.some((J)=>Q.includes(J))){let J=Q.trim();if(J.length>10&&J.length<150)Y.push(J)}return Y.slice(0,3)}summarizeToolUsage($){let Y=[],Z=$.filter((X)=>Date.now()-X.timestamp<1800000);if(Z.length>0){let X=new Map;Z.forEach((Q)=>{let J=X.get(Q.name)||[];J.push(Q),X.set(Q.name,J)});for(let[Q,J]of Array.from(X.entries())){let q=J.filter((G)=>G.status==="success").length;Y.push(`${Q}(${J.length}次,${q}成功)`)}}return Y.slice(0,5)}shouldCompress($,Y){return this.estimateCurrentTokens($)>Y*0.8}estimateCurrentTokens($){let Z=$.layers.conversation.messages.reduce((X,Q)=>X+Q.content.length,0);return Math.ceil(Z/4)}}class M2{defaultOptions;constructor($){this.defaultOptions={maxTokens:32000,maxMessages:50,timeWindow:86400000,priority:1,includeTools:!0,includeWorkspace:!0,...$}}filter($,Y){let Z={...this.defaultOptions,...Y},X={layers:{system:$.layers.system,session:$.layers.session,conversation:this.filterConversation($.layers.conversation,Z),tool:Z.includeTools?this.filterTools($.layers.tool,Z):{recentCalls:[],toolStates:{},dependencies:{}},workspace:Z.includeWorkspace?$.layers.workspace:{currentFiles:[],recentFiles:[],environment:{}}},metadata:{...$.metadata,lastUpdated:Date.now()}};return X.metadata.totalTokens=this.estimateTokens(X),X}filterConversation($,Y){let Z=[...$.messages];if(Y.timeWindow>0){let X=Date.now()-Y.timeWindow;Z=Z.filter((Q)=>Q.timestamp>=X||Q.role==="system")}if(Y.priority>1)Z=this.filterByPriority(Z,Y.priority);if(Y.maxMessages>0)Z=this.limitMessages(Z,Y.maxMessages);if(Y.maxTokens>0)Z=this.limitByTokens(Z,Y.maxTokens);return{messages:Z,summary:$.summary,topics:this.updateTopics(Z,$.topics),lastActivity:$.lastActivity}}filterTools($,Y){let Z=[...$.recentCalls];if(Y.timeWindow>0){let K=Date.now()-Y.timeWindow;Z=Z.filter((W)=>W.timestamp>=K)}let X=Z.filter((K)=>K.status==="success"),Q=Z.filter((K)=>K.status==="error"),J=Math.min(20,X.length),q=Math.min(10,Q.length);return{recentCalls:[...X.slice(-J),...Q.slice(-q)].sort((K,W)=>K.timestamp-W.timestamp),toolStates:$.toolStates,dependencies:$.dependencies}}filterByPriority($,Y){return $.filter((Z)=>{if(Z.role==="system")return!0;return this.calculateMessagePriority(Z)>=Y})}calculateMessagePriority($){let Y=1;if($.role==="system")Y+=3;else if($.role==="assistant")Y+=1;let Z=$.content.toLowerCase();if(["错误","警告","重要","关键","问题","解决"].some((J)=>Z.includes(J)))Y+=2;if(Z.includes("```")||Z.includes("function")||Z.includes("class"))Y+=1;let Q=(Date.now()-$.timestamp)/3600000;if(Q<1)Y+=2;else if(Q<6)Y+=1;return Y}limitMessages($,Y){if($.length<=Y)return $;let Z=$.filter((q)=>q.role==="system"),X=$.filter((q)=>q.role!=="system"),Q=Y-Z.length,J=Q>0?X.slice(-Q):[];return[...Z,...J].sort((q,G)=>q.timestamp-G.timestamp)}limitByTokens($,Y){if(Y<=0)return $;let Z=0,X=[];for(let Q=$.length-1;Q>=0;Q--){let J=$[Q],q=this.estimateMessageTokens(J);if(J.role==="system")if(Z+q<=Y)X.unshift(J),Z+=q;else{let G=this.compressMessage(J,Y-Z);X.unshift(G),Z+=this.estimateMessageTokens(G)}else if(Z+q<=Y)X.unshift(J),Z+=q;else break}return X.sort((Q,J)=>Q.timestamp-J.timestamp)}estimateMessageTokens($){return Math.ceil($.content.length/4)}compressMessage($,Y){let Z=Y*4;if($.content.length<=Z)return $;let X=$.content.substring(0,Z-3)+"...";return{...$,content:X,metadata:{...$.metadata,compressed:!0,originalLength:$.content.length}}}updateTopics($,Y){let Z=new Set(Y);for(let X of $)this.extractTopicsFromMessage(X).forEach((J)=>Z.add(J));return Array.from(Z).slice(0,10)}extractTopicsFromMessage($){let Y=$.content.toLowerCase(),Z=[];return["项目","功能","模块","组件","服务","接口","数据库","前端","后端","算法","架构","设计"].forEach((Q)=>{if(Y.includes(Q))Z.push(Q)}),Z}estimateTokens($){let Y=0;for(let X of $.layers.conversation.messages)Y+=this.estimateMessageTokens(X);let Z=JSON.stringify($.layers.system);if(Y+=Math.ceil(Z.length/4),$.layers.tool.recentCalls.length>0){let X=JSON.stringify($.layers.tool);Y+=Math.ceil(X.length/8)}return Y}static createPresets(){return{lightweight:new M2({maxTokens:1000,maxMessages:10,timeWindow:7200000,includeTools:!1,includeWorkspace:!1}),standard:new M2({maxTokens:4000,maxMessages:30,timeWindow:43200000,includeTools:!0,includeWorkspace:!0}),comprehensive:new M2({maxTokens:8000,maxMessages:100,timeWindow:86400000,includeTools:!0,includeWorkspace:!0}),debug:new M2({maxTokens:2000,maxMessages:20,timeWindow:21600000,priority:2,includeTools:!0,includeWorkspace:!1})}}}class B9{cache=new Map;maxSize;defaultTTL;constructor($=100,Y=300000){this.maxSize=$,this.defaultTTL=Y}set($,Y,Z){let X=Date.now(),Q={data:Y,timestamp:X,accessCount:0,lastAccess:X,ttl:Z||this.defaultTTL};if(this.cache.size>=this.maxSize&&!this.cache.has($))this.evictLeastUsed();this.cache.set($,Q)}get($){let Y=this.cache.get($);if(!Y)return null;let Z=Date.now();if(Z-Y.timestamp>Y.ttl)return this.cache.delete($),null;return Y.accessCount++,Y.lastAccess=Z,Y.data}has($){let Y=this.cache.get($);if(!Y)return!1;if(Date.now()-Y.timestamp>Y.ttl)return this.cache.delete($),!1;return!0}delete($){return this.cache.delete($)}clear(){this.cache.clear()}size(){return this.cleanExpired(),this.cache.size}cacheMessageSummary($,Y,Z){let X=`summary:${$}:${Y.length}`;this.set(X,{summary:Z,messageCount:Y.length,lastMessage:Y[Y.length-1]?.timestamp||0},600000)}getMessageSummary($,Y){let Z=`summary:${$}:${Y}`;return this.get(Z)}cacheToolResult($,Y,Z){let X=this.hashInput(Y),Q=`tool:${$}:${X}`;this.set(Q,Z,1800000)}getToolResult($,Y){let Z=this.hashInput(Y),X=`tool:${$}:${Z}`;return this.get(X)}cacheCompressedContext($,Y){let Z=`compressed:${$}`;this.set(Z,Y,900000)}getCompressedContext($){let Y=`compressed:${$}`;return this.get(Y)}getStats(){this.cleanExpired();let $=0,Y=0,Z=[];for(let[X,Q]of Array.from(this.cache.entries()))$+=Q.accessCount,Y+=this.estimateItemSize(Q),Z.push({key:X,accessCount:Q.accessCount,lastAccess:Q.lastAccess});return Z.sort((X,Q)=>Q.accessCount-X.accessCount),{size:this.cache.size,maxSize:this.maxSize,hitRate:$>0?$/($+this.cache.size):0,memoryUsage:Y,topKeys:Z.slice(0,10)}}cleanExpired(){let $=Date.now(),Y=[];for(let[Z,X]of Array.from(this.cache.entries()))if($-X.timestamp>X.ttl)Y.push(Z);Y.forEach((Z)=>this.cache.delete(Z))}evictLeastUsed(){let $=null,Y=1/0,Z=Date.now();for(let[X,Q]of Array.from(this.cache.entries())){let J=1/(Z-Q.lastAccess+1),q=Q.accessCount,G=J*q;if(G<Y)Y=G,$=X}if($)this.cache.delete($)}hashInput($){let Y=JSON.stringify($),Z=0;for(let X=0;X<Y.length;X++){let Q=Y.charCodeAt(X);Z=(Z<<5)-Z+Q,Z=Z&Z}return Math.abs(Z).toString(36)}estimateItemSize($){try{return JSON.stringify($).length*2}catch{return 1000}}setTTL($,Y){let Z=this.cache.get($);if(Z)return Z.ttl=Y,Z.timestamp=Date.now(),!0;return!1}getRemainingTTL($){let Y=this.cache.get($);if(!Y)return-1;let Z=Y.ttl-(Date.now()-Y.timestamp);return Math.max(0,Z)}warmup($){$.forEach(({key:Y,value:Z,ttl:X})=>{this.set(Y,Z,X)})}}class w9{contextData=null;maxSize;accessLog=new Map;constructor($=1000){this.maxSize=$}setContext($){this.contextData={...$},this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("context")}getContext(){if(this.contextData)this.recordAccess("context");return this.contextData}addMessage($){if(!this.contextData)throw Error("上下文数据未初始化");this.contextData.layers.conversation.messages.push($),this.contextData.layers.conversation.lastActivity=Date.now(),this.contextData.metadata.lastUpdated=Date.now(),this.enforceMemoryLimit(),this.recordAccess("messages")}getRecentMessages($=10){if(!this.contextData)return[];let Y=this.contextData.layers.conversation.messages;return this.recordAccess("messages"),Y.slice(-$)}addToolCall($){if(!this.contextData)throw Error("上下文数据未初始化");if(this.contextData.layers.tool.recentCalls.push($),this.contextData.metadata.lastUpdated=Date.now(),this.contextData.layers.tool.recentCalls.length>50)this.contextData.layers.tool.recentCalls=this.contextData.layers.tool.recentCalls.slice(-25);this.recordAccess("tools")}updateToolState($,Y){if(!this.contextData)throw Error("上下文数据未初始化");this.contextData.layers.tool.toolStates[$]=Y,this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("tools")}getToolState($){if(!this.contextData)return null;return this.recordAccess("tools"),this.contextData.layers.tool.toolStates[$]}updateWorkspace($){if(!this.contextData)throw Error("上下文数据未初始化");Object.assign(this.contextData.layers.workspace,$),this.contextData.metadata.lastUpdated=Date.now(),this.recordAccess("workspace")}clear(){this.contextData=null,this.accessLog.clear()}getMemoryInfo(){if(!this.contextData)return{hasData:!1,messageCount:0,toolCallCount:0,lastUpdated:null};return{hasData:!0,messageCount:this.contextData.layers.conversation.messages.length,toolCallCount:this.contextData.layers.tool.recentCalls.length,lastUpdated:this.contextData.metadata.lastUpdated}}recordAccess($){this.accessLog.set($,Date.now())}enforceMemoryLimit(){if(!this.contextData)return;let $=this.contextData.layers.conversation.messages;if($.length>this.maxSize){let Y=Math.floor(this.maxSize*0.8);this.contextData.layers.conversation.messages=$.slice(-Y)}}getMemoryUsage(){if(!this.contextData)return 0;return JSON.stringify(this.contextData).length}}import*as a6 from"node:fs";import{createReadStream as hG}from"node:fs";import*as l1 from"node:fs/promises";import*as L9 from"node:path";import{createInterface as xG}from"node:readline";class R0{filePath;constructor($){this.filePath=$}async append($){try{await l1.mkdir(L9.dirname(this.filePath),{recursive:!0});let Y=JSON.stringify($)+`
988
+ `;await l1.appendFile(this.filePath,Y,"utf-8")}catch(Y){throw console.error(`[JSONLStore] 追加写入失败: ${this.filePath}`,Y),Y}}async appendBatch($){try{await l1.mkdir(L9.dirname(this.filePath),{recursive:!0});let Y=$.map((Z)=>JSON.stringify(Z)).join(`
978
989
  `)+`
979
- `;await u1.appendFile(this.filePath,Y,"utf-8")}catch(Y){throw console.error(`[JSONLStore] 批量追加写入失败: ${this.filePath}`,Y),Y}}async readAll(){try{if(!d6.existsSync(this.filePath))return[];let Y=(await u1.readFile(this.filePath,"utf-8")).split(`
980
- `).filter((X)=>X.trim().length>0),Z=[];for(let X of Y)try{Z.push(JSON.parse(X))}catch(Q){console.warn(`[JSONLStore] 解析 JSON 行失败: ${X}`,Q)}return Z}catch($){return console.error(`[JSONLStore] 读取文件失败: ${this.filePath}`,$),[]}}async readStream($){return new Promise((Y,Z)=>{if(!d6.existsSync(this.filePath)){Y();return}let X=VK(this.filePath,"utf-8"),Q=DK({input:X,crlfDelay:Number.POSITIVE_INFINITY});Q.on("line",async(J)=>{let q=J.trim();if(q.length===0)return;try{let K=JSON.parse(q);await $(K)}catch(K){console.warn(`[JSONLStore] 解析 JSON 行失败: ${q}`,K)}}),Q.on("close",()=>Y()),Q.on("error",Z),X.on("error",Z)})}async filter($){let Y=[];return await this.readStream((Z)=>{if($(Z))Y.push(Z)}),Y}async readLast($){return(await this.readAll()).slice(-$)}async getStats(){try{if(!d6.existsSync(this.filePath))return{exists:!1,size:0,lineCount:0};let $=await u1.stat(this.filePath),Z=(await u1.readFile(this.filePath,"utf-8")).split(`
981
- `).filter((X)=>X.trim().length>0).length;return{exists:!0,size:$.size,lineCount:Z}}catch($){return console.error(`[JSONLStore] 获取统计信息失败: ${this.filePath}`,$),{exists:!1,size:0,lineCount:0}}}async exists(){try{return await u1.access(this.filePath),!0}catch{return!1}}async delete(){try{if(await this.exists())await u1.unlink(this.filePath)}catch($){throw console.error(`[JSONLStore] 删除文件失败: ${this.filePath}`,$),$}}getFilePath(){return this.filePath}}var QY=()=>{};import{nanoid as K$}from"nanoid";import*as r0 from"node:fs/promises";import*as JY from"node:path";class F9{projectPath;maxSessions;version;constructor($=process.cwd(),Y=100,Z="0.0.10"){this.projectPath=$,this.maxSessions=Y,this.version=Z}async initialize(){try{let $=t2(this.projectPath);await r0.mkdir($,{recursive:!0}),console.log(`[PersistentStore] 初始化存储目录: ${$}`)}catch($){console.warn("[PersistentStore] 无法创建持久化存储目录:",$)}}async saveMessage($,Y,Z,X=null,Q){try{let J=R0(this.projectPath,$),q=new b0(J),K={uuid:K$(),parentUuid:X,sessionId:$,timestamp:new Date().toISOString(),type:Y==="user"?"user":Y==="assistant"?"assistant":"system",cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:Y,content:Z,...Q||{}}};return await q.append(K),K.uuid}catch(J){throw console.error(`[PersistentStore] 保存消息失败 (session: ${$}):`,J),J}}async saveToolUse($,Y,Z,X=null){try{let Q=R0(this.projectPath,$),J=new b0(Q),q={uuid:K$(),parentUuid:X,sessionId:$,timestamp:new Date().toISOString(),type:"tool_use",cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:"assistant",content:""},tool:{id:K$(),name:Y,input:Z}};return await J.append(q),q.uuid}catch(Q){throw console.error(`[PersistentStore] 保存工具调用失败 (session: ${$}):`,Q),Q}}async saveToolResult($,Y,Z,X=null,Q){try{let J=R0(this.projectPath,$),q=new b0(J),K={uuid:K$(),parentUuid:X,sessionId:$,timestamp:new Date().toISOString(),type:"tool_result",cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:"assistant",content:""},toolResult:{id:Y,output:Z,error:Q}};return await q.append(K),K.uuid}catch(J){throw console.error(`[PersistentStore] 保存工具结果失败 (session: ${$}):`,J),J}}async saveCompaction($,Y,Z,X=null){try{let Q=R0(this.projectPath,$),J=new b0(Q),q={uuid:K$(),parentUuid:X,sessionId:$,timestamp:new Date().toISOString(),type:"system",subtype:"compact_boundary",cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:"system",content:"=== 上下文压缩边界 ==="},compactMetadata:Z};await J.append(q),console.log("[PersistentStore] 保存压缩边界标记");let K={uuid:K$(),parentUuid:q.uuid,logicalParentUuid:X??void 0,sessionId:$,timestamp:new Date().toISOString(),type:"user",isCompactSummary:!0,cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:"user",content:Y},compactMetadata:Z};return await J.append(K),console.log("[PersistentStore] 保存压缩总结消息"),K.uuid}catch(Q){throw console.error(`[PersistentStore] 保存压缩失败 (session: ${$}):`,Q),Q}}async saveContext($,Y){try{let{conversation:Z}=Y.layers;for(let X of Z.messages)await this.saveMessage($,X.role,X.content,null)}catch(Z){console.warn(`[PersistentStore] 保存上下文失败 (session: ${$}):`,Z)}}async saveSession($,Y){console.warn("[PersistentStore] saveSession 方法已废弃,请使用 saveMessage")}async saveConversation($,Y){console.warn("[PersistentStore] saveConversation 方法已废弃,请使用 saveMessage")}async loadSession($){try{let Y=R0(this.projectPath,$),X=await new b0(Y).readAll();if(X.length===0)return null;let Q=X[0];return{sessionId:$,userId:void 0,preferences:{},configuration:{},startTime:new Date(Q.timestamp).getTime()}}catch{return null}}async loadConversation($){try{let Y=R0(this.projectPath,$),X=await new b0(Y).readAll();if(X.length===0)return null;let Q=X.filter((K)=>["user","assistant","system"].includes(K.type)).map((K)=>({id:K.uuid,role:K.message.role,content:K.message.content,timestamp:new Date(K.timestamp).getTime()})),J=X[X.length-1],q=new Date(J.timestamp).getTime();return{messages:Q,topics:[],lastActivity:q}}catch{return null}}async listSessions(){try{let $=t2(this.projectPath);return(await r0.readdir($)).filter((Z)=>Z.endsWith(".jsonl")).map((Z)=>Z.replace(".jsonl","")).sort()}catch{return[]}}async getSessionSummary($){try{let Y=R0(this.projectPath,$),Z=new b0(Y);if(!(await Z.getStats()).exists)return null;let Q=await Z.readAll();if(Q.length===0)return null;let J=Q[Q.length-1];return{sessionId:$,lastActivity:new Date(J.timestamp).getTime(),messageCount:Q.filter((q)=>["user","assistant"].includes(q.type)).length,topics:[]}}catch{return null}}async deleteSession($){try{let Y=R0(this.projectPath,$);await new b0(Y).delete()}catch(Y){console.warn(`[PersistentStore] 删除会话失败 (session: ${$}):`,Y)}}async cleanupOldSessions(){try{let $=await this.listSessions();if($.length<=this.maxSessions)return;let X=(await Promise.all($.map((Q)=>this.getSessionSummary(Q)))).filter((Q)=>Q!==null).sort((Q,J)=>J.lastActivity-Q.lastActivity).slice(this.maxSessions).map((Q)=>Q.sessionId);await Promise.all(X.map((Q)=>this.deleteSession(Q))),console.log(`[PersistentStore] 已清理 ${X.length} 个旧会话`)}catch($){console.error("[PersistentStore] 清理旧会话失败:",$)}}async getStorageStats(){try{let $=await this.listSessions(),Y=0;for(let Z of $){let X=R0(this.projectPath,Z),J=await new b0(X).getStats();Y+=J.size}return{totalSessions:$.length,totalSize:Y,projectPath:this.projectPath}}catch{return{totalSessions:0,totalSize:0,projectPath:this.projectPath}}}async checkStorageHealth(){try{let $=t2(this.projectPath);await r0.mkdir($,{recursive:!0});let Y=JY.join($,".health-check");return await r0.writeFile(Y,"test","utf-8"),await r0.unlink(Y),{isAvailable:!0,canWrite:!0}}catch($){return{isAvailable:!1,canWrite:!1,error:$ instanceof Error?$.message:String($)}}}static async listAllProjects(){return G8()}}var qY=R(()=>{e2();QY()});import*as GY from"crypto";import{nanoid as KY}from"nanoid";class d${memory;persistent;cache;compressor;filter;options;currentSessionId=null;initialized=!1;constructor($={}){let Y=$.storage?.persistentPath||X2();this.options={storage:{maxMemorySize:1000,persistentPath:Y,cacheSize:100,compressionEnabled:!0,...$.storage},defaultFilter:{maxTokens:32000,maxMessages:50,timeWindow:86400000,...$.defaultFilter},compressionThreshold:$.compressionThreshold||6000,enableVectorSearch:$.enableVectorSearch||!1},this.memory=new O9(this.options.storage.maxMemorySize),this.persistent=new F9(process.cwd(),100),this.cache=new H9(this.options.storage.cacheSize,300000),this.compressor=new U9,this.filter=new I2(this.options.defaultFilter)}async initialize(){if(this.initialized)return;try{if(await this.persistent.initialize(),!(await this.persistent.checkStorageHealth()).isAvailable)console.warn("警告:持久化存储不可用,将仅使用内存存储");this.initialized=!0,console.log("上下文管理器初始化完成")}catch($){throw console.error("上下文管理器初始化失败:",$),$}}async createSession($,Y={},Z={}){let X=Z.sessionId||this.generateSessionId(),Q=Date.now(),J={layers:{system:await this.createSystemContext(),session:{sessionId:X,userId:$,preferences:Y,configuration:Z,startTime:Q},conversation:{messages:[],topics:[],lastActivity:Q},tool:{recentCalls:[],toolStates:{},dependencies:{}},workspace:await this.createWorkspaceContext()},metadata:{totalTokens:0,priority:1,lastUpdated:Q}};return this.memory.setContext(J),await this.persistent.saveContext(X,J),this.currentSessionId=X,console.log(`新会话已创建: ${X}`),X}async loadSession($){try{let Y=this.memory.getContext();if(!Y||Y.layers.session.sessionId!==$){let[Z,X]=await Promise.all([this.persistent.loadSession($),this.persistent.loadConversation($)]);if(!Z||!X)return!1;Y={layers:{system:await this.createSystemContext(),session:Z,conversation:X,tool:{recentCalls:[],toolStates:{},dependencies:{}},workspace:await this.createWorkspaceContext()},metadata:{totalTokens:0,priority:1,lastUpdated:Date.now()}},this.memory.setContext(Y)}return this.currentSessionId=$,console.log(`会话已加载: ${$}`),!0}catch(Y){return console.error("加载会话失败:",Y),!1}}async addMessage($,Y,Z){if(!this.currentSessionId)throw Error("没有活动会话");let X={id:this.generateMessageId(),role:$,content:Y,timestamp:Date.now(),metadata:Z};this.memory.addMessage(X);let Q=this.memory.getContext();if(Q&&this.shouldCompress(Q))await this.compressCurrentContext();this.saveCurrentSessionAsync()}async addToolCall($){if(!this.currentSessionId)throw Error("没有活动会话");if(this.memory.addToolCall($),$.status==="success"&&$.output)this.cache.cacheToolResult($.name,$.input,$.output);this.saveCurrentSessionAsync()}async saveMessage($,Y,Z,X=null,Q){return this.persistent.saveMessage($,Y,Z,X,Q)}async saveToolUse($,Y,Z,X=null){return this.persistent.saveToolUse($,Y,Z,X)}async saveToolResult($,Y,Z,X=null,Q){return this.persistent.saveToolResult($,Y,Z,X,Q)}async saveCompaction($,Y,Z,X=null){return this.persistent.saveCompaction($,Y,Z,X)}updateToolState($,Y){if(!this.currentSessionId)throw Error("没有活动会话");this.memory.updateToolState($,Y)}updateWorkspace($){if(!this.currentSessionId)throw Error("没有活动会话");this.memory.updateWorkspace($)}async getFormattedContext($){let Y=this.memory.getContext();if(!Y)throw Error("没有可用的上下文数据");let Z=this.filter.filter(Y,$),X=this.shouldCompress(Z),Q;if(X){let J=this.hashContext(Z);if(Q=this.cache.getCompressedContext(J),!Q)Q=await this.compressor.compress(Z),this.cache.cacheCompressedContext(J,Q)}return{context:Z,compressed:Q,tokenCount:Q?Q.tokenCount:Z.metadata.totalTokens}}async searchSessions($,Y=10){let Z=await this.persistent.listSessions(),X=[];for(let Q of Z){let J=await this.persistent.getSessionSummary(Q);if(J){let q=this.calculateRelevance($,J.topics);if(q>0)X.push({sessionId:Q,summary:`${J.messageCount}条消息,主题:${J.topics.join("、")}`,lastActivity:J.lastActivity,relevanceScore:q})}}return X.sort((Q,J)=>J.relevanceScore-Q.relevanceScore).slice(0,Y)}getCachedToolResult($,Y){return this.cache.getToolResult($,Y)}async getStats(){let[$,Y,Z]=await Promise.all([Promise.resolve(this.memory.getMemoryInfo()),Promise.resolve(this.cache.getStats()),this.persistent.getStorageStats()]);return{currentSession:this.currentSessionId,memory:$,cache:Y,storage:Z}}async cleanup(){if(this.currentSessionId)await this.saveCurrentSession();this.memory.clear(),this.cache.clear(),await this.persistent.cleanupOldSessions(),this.currentSessionId=null,console.log("上下文管理器资源清理完成")}generateSessionId(){return KY()}generateMessageId(){return KY()}async createSystemContext(){return{role:"AI助手",capabilities:["对话","工具调用","代码生成","文档分析"],tools:["文件操作","Git操作","代码分析"],version:"1.0.0"}}async createWorkspaceContext(){try{let $=process.cwd();return{projectPath:$,currentFiles:[],recentFiles:[],environment:{nodeVersion:process.version,platform:process.platform,cwd:$}}}catch($){return{currentFiles:[],recentFiles:[],environment:{}}}}shouldCompress($){return $.metadata.totalTokens>this.options.compressionThreshold}async compressCurrentContext(){let $=this.memory.getContext();if(!$)return;let Y=await this.compressor.compress($);$.layers.conversation.summary=Y.summary,this.memory.setContext($)}async saveCurrentSession(){if(!this.currentSessionId)return;let $=this.memory.getContext();if($)await this.persistent.saveContext(this.currentSessionId,$)}saveCurrentSessionAsync(){this.saveCurrentSession().catch(($)=>{console.warn("异步保存会话失败:",$)})}hashContext($){let Y=JSON.stringify({messageCount:$.layers.conversation.messages.length,lastMessage:$.layers.conversation.messages[$.layers.conversation.messages.length-1]?.id,toolCallCount:$.layers.tool.recentCalls.length});return GY.createHash("md5").update(Y).digest("hex")}calculateRelevance($,Y){let Z=$.toLowerCase(),X=0;for(let Q of Y)if(Z.includes(Q.toLowerCase())||Q.toLowerCase().includes(Z))X+=1;return X}}var _9=R(()=>{qY();e2()});class B9{chatService;contextManager;memoryAdapter;constructor($,Y){this.chatService=$,this.contextManager=Y||new d$,this.memoryAdapter=this.createMemoryAdapter()}createMemoryAdapter(){let $=[];return{getMessages:()=>[...$],addMessage:(Y)=>{$.push(Y)},clearContext:()=>{$.length=0},getContextSize:()=>$.length}}getContextManager(){return this.contextManager}getMemoryAdapter(){return this.memoryAdapter}async executeSimpleTask($){let Y=[{role:"user",content:$.prompt}],Z=await this.chatService.chat(Y);return{taskId:$.id,content:Z.content,metadata:{executionMode:"simple",taskType:$.type}}}async executeParallelTask($){let Y=this.decomposeTask($),Z=await Promise.all(Y.map(async(Q)=>{try{return{success:!0,result:await this.executeSimpleTask(Q)}}catch(J){return{success:!1,error:J instanceof Error?J.message:"执行失败",taskId:Q.id}}})),X=this.combineSubTaskResults(Z);return{taskId:$.id,content:X,metadata:{executionMode:"parallel",taskType:$.type,subTaskCount:Y.length,failedSubTasks:Z.filter((Q)=>!Q.success).length}}}async executeSteeringTask($){let Y=await this.generateExecutionSteps($),Z="",X={};for(let Q=0;Q<Y.length;Q++){let J=Y[Q];try{let q=await this.executeStep(J,$);Z+=q.content+`
990
+ `;await l1.appendFile(this.filePath,Y,"utf-8")}catch(Y){throw console.error(`[JSONLStore] 批量追加写入失败: ${this.filePath}`,Y),Y}}async readAll(){try{if(!a6.existsSync(this.filePath))return[];let Y=(await l1.readFile(this.filePath,"utf-8")).split(`
991
+ `).filter((X)=>X.trim().length>0),Z=[];for(let X of Y)try{Z.push(JSON.parse(X))}catch(Q){console.warn(`[JSONLStore] 解析 JSON 行失败: ${X}`,Q)}return Z}catch($){return console.error(`[JSONLStore] 读取文件失败: ${this.filePath}`,$),[]}}async readStream($){return new Promise((Y,Z)=>{if(!a6.existsSync(this.filePath)){Y();return}let X=hG(this.filePath,"utf-8"),Q=xG({input:X,crlfDelay:Number.POSITIVE_INFINITY});Q.on("line",async(J)=>{let q=J.trim();if(q.length===0)return;try{let G=JSON.parse(q);await $(G)}catch(G){console.warn(`[JSONLStore] 解析 JSON 行失败: ${q}`,G)}}),Q.on("close",()=>Y()),Q.on("error",Z),X.on("error",Z)})}async filter($){let Y=[];return await this.readStream((Z)=>{if($(Z))Y.push(Z)}),Y}async readLast($){return(await this.readAll()).slice(-$)}async getStats(){try{if(!a6.existsSync(this.filePath))return{exists:!1,size:0,lineCount:0};let $=await l1.stat(this.filePath),Z=(await l1.readFile(this.filePath,"utf-8")).split(`
992
+ `).filter((X)=>X.trim().length>0).length;return{exists:!0,size:$.size,lineCount:Z}}catch($){return console.error(`[JSONLStore] 获取统计信息失败: ${this.filePath}`,$),{exists:!1,size:0,lineCount:0}}}async exists(){try{return await l1.access(this.filePath),!0}catch{return!1}}async delete(){try{if(await this.exists())await l1.unlink(this.filePath)}catch($){throw console.error(`[JSONLStore] 删除文件失败: ${this.filePath}`,$),$}}getFilePath(){return this.filePath}}var zY=()=>{};import{nanoid as W$}from"nanoid";import*as n0 from"node:fs/promises";import*as _Y from"node:path";class A9{projectPath;maxSessions;version;constructor($=process.cwd(),Y=100,Z="0.0.10"){this.projectPath=$,this.maxSessions=Y,this.version=Z}async initialize(){try{let $=$$(this.projectPath);await n0.mkdir($,{recursive:!0}),console.log(`[PersistentStore] 初始化存储目录: ${$}`)}catch($){console.warn("[PersistentStore] 无法创建持久化存储目录:",$)}}async saveMessage($,Y,Z,X=null,Q){try{let J=b0(this.projectPath,$),q=new R0(J),G={uuid:W$(),parentUuid:X,sessionId:$,timestamp:new Date().toISOString(),type:Y==="user"?"user":Y==="assistant"?"assistant":"system",cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:Y,content:Z,...Q||{}}};return await q.append(G),G.uuid}catch(J){throw console.error(`[PersistentStore] 保存消息失败 (session: ${$}):`,J),J}}async saveToolUse($,Y,Z,X=null){try{let Q=b0(this.projectPath,$),J=new R0(Q),q={uuid:W$(),parentUuid:X,sessionId:$,timestamp:new Date().toISOString(),type:"tool_use",cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:"assistant",content:""},tool:{id:W$(),name:Y,input:Z}};return await J.append(q),q.uuid}catch(Q){throw console.error(`[PersistentStore] 保存工具调用失败 (session: ${$}):`,Q),Q}}async saveToolResult($,Y,Z,X=null,Q){try{let J=b0(this.projectPath,$),q=new R0(J),G={uuid:W$(),parentUuid:X,sessionId:$,timestamp:new Date().toISOString(),type:"tool_result",cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:"assistant",content:""},toolResult:{id:Y,output:Z,error:Q}};return await q.append(G),G.uuid}catch(J){throw console.error(`[PersistentStore] 保存工具结果失败 (session: ${$}):`,J),J}}async saveCompaction($,Y,Z,X=null){try{let Q=b0(this.projectPath,$),J=new R0(Q),q={uuid:W$(),parentUuid:X,sessionId:$,timestamp:new Date().toISOString(),type:"system",subtype:"compact_boundary",cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:"system",content:"=== 上下文压缩边界 ==="},compactMetadata:Z};await J.append(q),console.log("[PersistentStore] 保存压缩边界标记");let G={uuid:W$(),parentUuid:q.uuid,logicalParentUuid:X??void 0,sessionId:$,timestamp:new Date().toISOString(),type:"user",isCompactSummary:!0,cwd:this.projectPath,gitBranch:V2(this.projectPath),version:this.version,message:{role:"user",content:Y},compactMetadata:Z};return await J.append(G),console.log("[PersistentStore] 保存压缩总结消息"),G.uuid}catch(Q){throw console.error(`[PersistentStore] 保存压缩失败 (session: ${$}):`,Q),Q}}async saveContext($,Y){try{let{conversation:Z}=Y.layers;for(let X of Z.messages)await this.saveMessage($,X.role,X.content,null)}catch(Z){console.warn(`[PersistentStore] 保存上下文失败 (session: ${$}):`,Z)}}async saveSession($,Y){console.warn("[PersistentStore] saveSession 方法已废弃,请使用 saveMessage")}async saveConversation($,Y){console.warn("[PersistentStore] saveConversation 方法已废弃,请使用 saveMessage")}async loadSession($){try{let Y=b0(this.projectPath,$),X=await new R0(Y).readAll();if(X.length===0)return null;let Q=X[0];return{sessionId:$,userId:void 0,preferences:{},configuration:{},startTime:new Date(Q.timestamp).getTime()}}catch{return null}}async loadConversation($){try{let Y=b0(this.projectPath,$),X=await new R0(Y).readAll();if(X.length===0)return null;let Q=X.filter((G)=>["user","assistant","system"].includes(G.type)).map((G)=>({id:G.uuid,role:G.message.role,content:G.message.content,timestamp:new Date(G.timestamp).getTime()})),J=X[X.length-1],q=new Date(J.timestamp).getTime();return{messages:Q,topics:[],lastActivity:q}}catch{return null}}async listSessions(){try{let $=$$(this.projectPath);return(await n0.readdir($)).filter((Z)=>Z.endsWith(".jsonl")).map((Z)=>Z.replace(".jsonl","")).sort()}catch{return[]}}async getSessionSummary($){try{let Y=b0(this.projectPath,$),Z=new R0(Y);if(!(await Z.getStats()).exists)return null;let Q=await Z.readAll();if(Q.length===0)return null;let J=Q[Q.length-1];return{sessionId:$,lastActivity:new Date(J.timestamp).getTime(),messageCount:Q.filter((q)=>["user","assistant"].includes(q.type)).length,topics:[]}}catch{return null}}async deleteSession($){try{let Y=b0(this.projectPath,$);await new R0(Y).delete()}catch(Y){console.warn(`[PersistentStore] 删除会话失败 (session: ${$}):`,Y)}}async cleanupOldSessions(){try{let $=await this.listSessions();if($.length<=this.maxSessions)return;let X=(await Promise.all($.map((Q)=>this.getSessionSummary(Q)))).filter((Q)=>Q!==null).sort((Q,J)=>J.lastActivity-Q.lastActivity).slice(this.maxSessions).map((Q)=>Q.sessionId);await Promise.all(X.map((Q)=>this.deleteSession(Q))),console.log(`[PersistentStore] 已清理 ${X.length} 个旧会话`)}catch($){console.error("[PersistentStore] 清理旧会话失败:",$)}}async getStorageStats(){try{let $=await this.listSessions(),Y=0;for(let Z of $){let X=b0(this.projectPath,Z),J=await new R0(X).getStats();Y+=J.size}return{totalSessions:$.length,totalSize:Y,projectPath:this.projectPath}}catch{return{totalSessions:0,totalSize:0,projectPath:this.projectPath}}}async checkStorageHealth(){try{let $=$$(this.projectPath);await n0.mkdir($,{recursive:!0});let Y=_Y.join($,".health-check");return await n0.writeFile(Y,"test","utf-8"),await n0.unlink(Y),{isAvailable:!0,canWrite:!0}}catch($){return{isAvailable:!1,canWrite:!1,error:$ instanceof Error?$.message:String($)}}}static async listAllProjects(){return z8()}}var NY=D(()=>{Y$();zY()});import*as wY from"crypto";import{nanoid as BY}from"nanoid";class r${memory;persistent;cache;compressor;filter;options;currentSessionId=null;initialized=!1;constructor($={}){let Y=$.storage?.persistentPath||q2();this.options={storage:{maxMemorySize:1000,persistentPath:Y,cacheSize:100,compressionEnabled:!0,...$.storage},defaultFilter:{maxTokens:32000,maxMessages:50,timeWindow:86400000,...$.defaultFilter},compressionThreshold:$.compressionThreshold||6000,enableVectorSearch:$.enableVectorSearch||!1},this.memory=new w9(this.options.storage.maxMemorySize),this.persistent=new A9(process.cwd(),100),this.cache=new B9(this.options.storage.cacheSize,300000),this.compressor=new N9,this.filter=new M2(this.options.defaultFilter)}async initialize(){if(this.initialized)return;try{if(await this.persistent.initialize(),!(await this.persistent.checkStorageHealth()).isAvailable)console.warn("警告:持久化存储不可用,将仅使用内存存储");this.initialized=!0,console.log("上下文管理器初始化完成")}catch($){throw console.error("上下文管理器初始化失败:",$),$}}async createSession($,Y={},Z={}){let X=Z.sessionId||this.generateSessionId(),Q=Date.now(),J={layers:{system:await this.createSystemContext(),session:{sessionId:X,userId:$,preferences:Y,configuration:Z,startTime:Q},conversation:{messages:[],topics:[],lastActivity:Q},tool:{recentCalls:[],toolStates:{},dependencies:{}},workspace:await this.createWorkspaceContext()},metadata:{totalTokens:0,priority:1,lastUpdated:Q}};return this.memory.setContext(J),await this.persistent.saveContext(X,J),this.currentSessionId=X,console.log(`新会话已创建: ${X}`),X}async loadSession($){try{let Y=this.memory.getContext();if(!Y||Y.layers.session.sessionId!==$){let[Z,X]=await Promise.all([this.persistent.loadSession($),this.persistent.loadConversation($)]);if(!Z||!X)return!1;Y={layers:{system:await this.createSystemContext(),session:Z,conversation:X,tool:{recentCalls:[],toolStates:{},dependencies:{}},workspace:await this.createWorkspaceContext()},metadata:{totalTokens:0,priority:1,lastUpdated:Date.now()}},this.memory.setContext(Y)}return this.currentSessionId=$,console.log(`会话已加载: ${$}`),!0}catch(Y){return console.error("加载会话失败:",Y),!1}}async addMessage($,Y,Z){if(!this.currentSessionId)throw Error("没有活动会话");let X={id:this.generateMessageId(),role:$,content:Y,timestamp:Date.now(),metadata:Z};this.memory.addMessage(X);let Q=this.memory.getContext();if(Q&&this.shouldCompress(Q))await this.compressCurrentContext();this.saveCurrentSessionAsync()}async addToolCall($){if(!this.currentSessionId)throw Error("没有活动会话");if(this.memory.addToolCall($),$.status==="success"&&$.output)this.cache.cacheToolResult($.name,$.input,$.output);this.saveCurrentSessionAsync()}async saveMessage($,Y,Z,X=null,Q){return this.persistent.saveMessage($,Y,Z,X,Q)}async saveToolUse($,Y,Z,X=null){return this.persistent.saveToolUse($,Y,Z,X)}async saveToolResult($,Y,Z,X=null,Q){return this.persistent.saveToolResult($,Y,Z,X,Q)}async saveCompaction($,Y,Z,X=null){return this.persistent.saveCompaction($,Y,Z,X)}updateToolState($,Y){if(!this.currentSessionId)throw Error("没有活动会话");this.memory.updateToolState($,Y)}updateWorkspace($){if(!this.currentSessionId)throw Error("没有活动会话");this.memory.updateWorkspace($)}async getFormattedContext($){let Y=this.memory.getContext();if(!Y)throw Error("没有可用的上下文数据");let Z=this.filter.filter(Y,$),X=this.shouldCompress(Z),Q;if(X){let J=this.hashContext(Z);if(Q=this.cache.getCompressedContext(J),!Q)Q=await this.compressor.compress(Z),this.cache.cacheCompressedContext(J,Q)}return{context:Z,compressed:Q,tokenCount:Q?Q.tokenCount:Z.metadata.totalTokens}}async searchSessions($,Y=10){let Z=await this.persistent.listSessions(),X=[];for(let Q of Z){let J=await this.persistent.getSessionSummary(Q);if(J){let q=this.calculateRelevance($,J.topics);if(q>0)X.push({sessionId:Q,summary:`${J.messageCount}条消息,主题:${J.topics.join("、")}`,lastActivity:J.lastActivity,relevanceScore:q})}}return X.sort((Q,J)=>J.relevanceScore-Q.relevanceScore).slice(0,Y)}getCachedToolResult($,Y){return this.cache.getToolResult($,Y)}async getStats(){let[$,Y,Z]=await Promise.all([Promise.resolve(this.memory.getMemoryInfo()),Promise.resolve(this.cache.getStats()),this.persistent.getStorageStats()]);return{currentSession:this.currentSessionId,memory:$,cache:Y,storage:Z}}async cleanup(){if(this.currentSessionId)await this.saveCurrentSession();this.memory.clear(),this.cache.clear(),await this.persistent.cleanupOldSessions(),this.currentSessionId=null,console.log("上下文管理器资源清理完成")}generateSessionId(){return BY()}generateMessageId(){return BY()}async createSystemContext(){return{role:"AI助手",capabilities:["对话","工具调用","代码生成","文档分析"],tools:["文件操作","Git操作","代码分析"],version:"1.0.0"}}async createWorkspaceContext(){try{let $=process.cwd();return{projectPath:$,currentFiles:[],recentFiles:[],environment:{nodeVersion:process.version,platform:process.platform,cwd:$}}}catch($){return{currentFiles:[],recentFiles:[],environment:{}}}}shouldCompress($){return $.metadata.totalTokens>this.options.compressionThreshold}async compressCurrentContext(){let $=this.memory.getContext();if(!$)return;let Y=await this.compressor.compress($);$.layers.conversation.summary=Y.summary,this.memory.setContext($)}async saveCurrentSession(){if(!this.currentSessionId)return;let $=this.memory.getContext();if($)await this.persistent.saveContext(this.currentSessionId,$)}saveCurrentSessionAsync(){this.saveCurrentSession().catch(($)=>{console.warn("异步保存会话失败:",$)})}hashContext($){let Y=JSON.stringify({messageCount:$.layers.conversation.messages.length,lastMessage:$.layers.conversation.messages[$.layers.conversation.messages.length-1]?.id,toolCallCount:$.layers.tool.recentCalls.length});return wY.createHash("md5").update(Y).digest("hex")}calculateRelevance($,Y){let Z=$.toLowerCase(),X=0;for(let Q of Y)if(Z.includes(Q.toLowerCase())||Q.toLowerCase().includes(Z))X+=1;return X}}var b9=D(()=>{NY();Y$()});class R9{chatService;contextManager;memoryAdapter;constructor($,Y){this.chatService=$,this.contextManager=Y||new r$,this.memoryAdapter=this.createMemoryAdapter()}createMemoryAdapter(){let $=[];return{getMessages:()=>[...$],addMessage:(Y)=>{$.push(Y)},clearContext:()=>{$.length=0},getContextSize:()=>$.length}}getContextManager(){return this.contextManager}getMemoryAdapter(){return this.memoryAdapter}async executeSimpleTask($){let Y=[{role:"user",content:$.prompt}],Z=await this.chatService.chat(Y);return{taskId:$.id,content:Z.content,metadata:{executionMode:"simple",taskType:$.type}}}async executeParallelTask($){let Y=this.decomposeTask($),Z=await Promise.all(Y.map(async(Q)=>{try{return{success:!0,result:await this.executeSimpleTask(Q)}}catch(J){return{success:!1,error:J instanceof Error?J.message:"执行失败",taskId:Q.id}}})),X=this.combineSubTaskResults(Z);return{taskId:$.id,content:X,metadata:{executionMode:"parallel",taskType:$.type,subTaskCount:Y.length,failedSubTasks:Z.filter((Q)=>!Q.success).length}}}async executeSteeringTask($){let Y=await this.generateExecutionSteps($),Z="",X={};for(let Q=0;Q<Y.length;Q++){let J=Y[Q];try{let q=await this.executeStep(J,$);Z+=q.content+`
982
993
 
983
994
  `,X[`step_${Q}_type`]=J.type,X[`step_${Q}_result`]=q}catch(q){throw Error(`步骤 ${J.id} 执行失败: ${q instanceof Error?q.message:"未知错误"}`)}}return{taskId:$.id,content:Z.trim(),metadata:{executionMode:"steering",taskType:$.type,steps:Y.length,...X}}}decomposeTask($){return[{...$,id:`${$.id}_sub1`,prompt:`${$.prompt} (子任务1: 分析和规划)`},{...$,id:`${$.id}_sub2`,prompt:`${$.prompt} (子任务2: 执行和验证)`}]}async generateExecutionSteps($){return[{id:`${$.id}_step1`,type:"llm",description:"理解任务要求和约束",status:"pending"},{id:`${$.id}_step2`,type:"tool",description:"准备执行环境和工具",status:"pending"},{id:`${$.id}_step3`,type:"llm",description:"执行任务并生成结果",status:"pending"}]}async executeStep($,Y){switch($.type){case"llm":return this.executeLlmStep($,Y);case"tool":return this.executeToolStep($,Y);default:throw Error(`未知的步骤类型: ${$.type}`)}}async executeLlmStep($,Y){let Z=`Step: ${$.description}
984
995
  Task: ${Y.prompt}`;return{content:(await this.chatService.chat([{role:"user",content:Z}])).content,stepId:$.id}}async executeToolStep($,Y){return{content:`Tool step completed: ${$.description}`,stepId:$.id}}combineSubTaskResults($){return $.filter((Y)=>Y.success).map((Y)=>Y.result?.content||Y.content||"").join(`
985
996
 
986
- `)}}var WY=R(()=>{_9()});import*as UY from"os";import*as HY from"path";class E1{config;runtimeOptions;isInitialized=!1;activeTask;executionPipeline;systemPrompt;chatService;executionEngine;attachmentCollector;constructor($,Y={},Z){this.config=$,this.runtimeOptions=Y,this.executionPipeline=Z||this.createDefaultPipeline()}createDefaultPipeline(){let $=new W9,Y={...this.config.permissions,...this.runtimeOptions.permissions},Z=this.runtimeOptions.permissionMode??this.config.permissionMode??"default";return new G9($,{permissionConfig:Y,permissionMode:Z,maxHistorySize:1000})}static async create($={}){if(await H6(),T$().length===0)throw Error(`❌ 没有可用的模型配置
997
+ `)}}var LY=D(()=>{b9()});import*as AY from"os";import*as bY from"path";class v1{config;runtimeOptions;isInitialized=!1;activeTask;executionPipeline;systemPrompt;chatService;executionEngine;attachmentCollector;constructor($,Y={},Z){this.config=$,this.runtimeOptions=Y,this.executionPipeline=Z||this.createDefaultPipeline()}createDefaultPipeline(){let $=new _9,Y={...this.config.permissions,...this.runtimeOptions.permissions},Z=this.runtimeOptions.permissionMode??this.config.permissionMode??"default";return new z9($,{permissionConfig:Y,permissionMode:Z,maxHistorySize:1000})}static async create($={}){if(await B6(),h$().length===0)throw Error(`❌ 没有可用的模型配置
987
998
 
988
999
  `+`请先使用以下命令添加模型:
989
1000
  `+` /model add
990
1001
 
991
1002
  `+`或运行初始化向导:
992
- `+" /init");let Z=V1();if(!Z)throw Error("❌ 配置未初始化,请确保应用已正确启动");m1.getInstance().validateConfig(Z);let Q=new E1(Z,$);if(await Q.initialize(),$.toolWhitelist&&$.toolWhitelist.length>0)Q.applyToolWhitelist($.toolWhitelist);return Q}async initialize(){if(this.isInitialized)return;try{this.log("初始化Agent..."),await this.initializeSystemPrompt(),await this.registerBuiltinTools(),await this.loadSubagents();let $=m2();if(!$)throw Error("❌ 当前模型配置未找到");this.log(`\uD83D\uDE80 使用模型: ${$.name} (${$.model})`);let Y=q$($);if(Y)this.log("\uD83E\uDDE0 检测到 Thinking 模型,启用 reasoning_content 支持");this.chatService=L6({provider:$.provider,apiKey:$.apiKey,model:$.model,baseUrl:$.baseUrl,temperature:$.temperature??this.config.temperature,maxContextTokens:$.maxContextTokens??this.config.maxContextTokens,maxOutputTokens:$.maxOutputTokens??this.config.maxOutputTokens,timeout:this.config.timeout,supportsThinking:Y}),this.executionEngine=new B9(this.chatService),this.attachmentCollector=new $8({cwd:process.cwd(),maxFileSize:1048576,maxLines:2000,maxTokens:32000}),this.isInitialized=!0,this.log(`Agent初始化完成,已加载 ${this.executionPipeline.getRegistry().getAll().length} 个工具`)}catch($){throw this.error("Agent初始化失败",$),$}}async executeTask($){if(!this.isInitialized)throw Error("Agent未初始化");this.activeTask=$;try{this.log(`开始执行任务: ${$.id}`);let Y;if($.type==="parallel")Y=await this.executionEngine.executeParallelTask($);else if($.type==="steering")Y=await this.executionEngine.executeSteeringTask($);else Y=await this.executionEngine.executeSimpleTask($);return this.activeTask=void 0,this.log(`任务执行完成: ${$.id}`),Y}catch(Y){throw this.activeTask=void 0,this.error(`任务执行失败: ${$.id}`,Y),Y}}async chat($,Y,Z){if(!this.isInitialized)throw Error("Agent未初始化");let X=await this.processAtMentions($);if(Y){let q={signal:Y.signal,...Z},K=Y.permissionMode==="plan"?await this.runPlanLoop(X,Y,q):await this.runLoop(X,Y,q);if(!K.success){if(K.error?.type==="aborted"||K.metadata?.shouldExitLoop)return"";throw Error(K.error?.message||"执行失败")}if(K.metadata?.targetMode&&Y.permissionMode==="plan"){let G=K.metadata.targetMode,W=K.metadata.planContent;E.debug(`\uD83D\uDD04 Plan 模式已批准,切换到 ${G} 模式并重新执行`),await U1().setPermissionMode(G),E.debug(`✅ 权限模式已更新: ${G}`);let U={...Y,permissionMode:G},H=X;if(W)H=`${X}
1003
+ `+" /init");let Z=V1();if(!Z)throw Error("❌ 配置未初始化,请确保应用已正确启动");u1.getInstance().validateConfig(Z);let Q=new v1(Z,$);if(await Q.initialize(),$.toolWhitelist&&$.toolWhitelist.length>0)Q.applyToolWhitelist($.toolWhitelist);return Q}async initialize(){if(this.isInitialized)return;try{this.log("初始化Agent..."),await this.initializeSystemPrompt(),await this.registerBuiltinTools(),await this.loadSubagents();let $=u2();if(!$)throw Error("❌ 当前模型配置未找到");this.log(`\uD83D\uDE80 使用模型: ${$.name} (${$.model})`);let Y=K$($);if(Y)this.log("\uD83E\uDDE0 检测到 Thinking 模型,启用 reasoning_content 支持");this.chatService=I6({provider:$.provider,apiKey:$.apiKey,model:$.model,baseUrl:$.baseUrl,temperature:$.temperature??this.config.temperature,maxContextTokens:$.maxContextTokens??this.config.maxContextTokens,maxOutputTokens:$.maxOutputTokens??this.config.maxOutputTokens,timeout:this.config.timeout,supportsThinking:Y}),this.executionEngine=new R9(this.chatService),this.attachmentCollector=new q8({cwd:process.cwd(),maxFileSize:1048576,maxLines:2000,maxTokens:32000}),this.isInitialized=!0,this.log(`Agent初始化完成,已加载 ${this.executionPipeline.getRegistry().getAll().length} 个工具`)}catch($){throw this.error("Agent初始化失败",$),$}}async executeTask($){if(!this.isInitialized)throw Error("Agent未初始化");this.activeTask=$;try{this.log(`开始执行任务: ${$.id}`);let Y;if($.type==="parallel")Y=await this.executionEngine.executeParallelTask($);else if($.type==="steering")Y=await this.executionEngine.executeSteeringTask($);else Y=await this.executionEngine.executeSimpleTask($);return this.activeTask=void 0,this.log(`任务执行完成: ${$.id}`),Y}catch(Y){throw this.activeTask=void 0,this.error(`任务执行失败: ${$.id}`,Y),Y}}async chat($,Y,Z){if(!this.isInitialized)throw Error("Agent未初始化");let X=await this.processAtMentionsForContent($);if(Y){let G={signal:Y.signal,...Z},K=Y.permissionMode==="plan"?await this.runPlanLoop(X,Y,G):await this.runLoop(X,Y,G);if(!K.success){if(K.error?.type==="aborted"||K.metadata?.shouldExitLoop)return"";throw Error(K.error?.message||"执行失败")}if(K.metadata?.targetMode&&Y.permissionMode==="plan"){let W=K.metadata.targetMode,U=K.metadata.planContent;y.debug(`\uD83D\uDD04 Plan 模式已批准,切换到 ${W} 模式并重新执行`),await H1().setPermissionMode(W),y.debug(`✅ 权限模式已更新: ${W}`);let H={...Y,permissionMode:W},O=X;if(U){let F=`
993
1004
 
994
1005
  <approved-plan>
995
- ${W}
1006
+ ${U}
996
1007
  </approved-plan>
997
1008
 
998
- IMPORTANT: Execute according to the approved plan above. Follow the steps exactly as specified.`,E.debug(`\uD83D\uDCCB 已将 plan 内容注入到消息中 (${W.length} 字符)`);return this.runLoop(H,U,q).then((O)=>{if(!O.success)throw Error(O.error?.message||"执行失败");return O.finalMessage||""})}return K.finalMessage||""}let Q={id:this.generateTaskId(),type:"simple",prompt:X};return(await this.executeTask(Q)).content}async runPlanLoop($,Y,Z){E.debug("\uD83D\uDD35 Processing Plan mode message...");let{prompt:X}=await V6({projectPath:process.cwd(),mode:"plan",includeEnvironment:!0}),Q=t4($);return this.executeLoop(Q,Y,Z,X)}async runLoop($,Y,Z){E.debug("\uD83D\uDCAC Processing enhanced chat message...");let X=b6(),Q=this.systemPrompt?`${X}
1009
+ IMPORTANT: Execute according to the approved plan above. Follow the steps exactly as specified.`;if(typeof X==="string")O=X+F;else O=[...X,{type:"text",text:F}];y.debug(`\uD83D\uDCCB 已将 plan 内容注入到消息中 (${U.length} 字符)`)}return this.runLoop(O,H,G).then((F)=>{if(!F.success)throw Error(F.error?.message||"执行失败");return F.finalMessage||""})}return K.finalMessage||""}let Q=typeof X==="string"?X:X.filter((G)=>G.type==="text").map((G)=>G.text).join(`
1010
+ `),J={id:this.generateTaskId(),type:"simple",prompt:Q};return(await this.executeTask(J)).content}async runPlanLoop($,Y,Z){y.debug("\uD83D\uDD35 Processing Plan mode message...");let{prompt:X}=await E6({projectPath:process.cwd(),mode:"plan",includeEnvironment:!0}),Q;if(typeof $==="string")Q=d$($);else{let J=$.filter((q)=>q.type==="text");if(J.length>0){let q=J[0];Q=$.map((G)=>G===q?{type:"text",text:d$(q.text)}:G)}else Q=[{type:"text",text:d$("")},...$]}return this.executeLoop(Q,Y,Z,X)}async runLoop($,Y,Z){y.debug("\uD83D\uDCAC Processing enhanced chat message...");let X=j6(),Q=this.systemPrompt?`${X}
999
1011
 
1000
1012
  ---
1001
1013
 
1002
- ${this.systemPrompt}`:X;return this.executeLoop($,Y,Z,Q)}async executeLoop($,Y,Z,X){if(!this.isInitialized)throw Error("Agent未初始化");let Q=Date.now();try{let J=this.executionPipeline.getRegistry(),q=Y.permissionMode,K=J.getFunctionDeclarationsByMode(q);if(q==="plan"){let D=J.getReadOnlyTools();E.debug(`\uD83D\uDD12 Plan mode: 使用只读工具 (${D.length} 个): ${D.map((I)=>I.name).join(", ")}`)}let W=Y.messages.length===0||!Y.messages.some((D)=>D.role==="system"),U=[];if(W&&X)U.push({role:"system",content:X});U.push(...Y.messages,{role:"user",content:$});let H=null;try{let D=this.executionEngine?.getContextManager();if(D&&Y.sessionId&&$.trim()!=="")H=await D.saveMessage(Y.sessionId,"user",$);else if($.trim()==="")E.debug("[Agent] 跳过保存空用户消息")}catch(D){E.warn("[Agent] 保存用户消息失败:",D)}let O=100,z=Y.permissionMode==="yolo",_=this.runtimeOptions.maxTurns??Z?.maxTurns??this.config.maxTurns??-1;if(_===0)return{success:!1,error:{type:"chat_disabled",message:`对话功能已被禁用 (maxTurns=0)。如需启用,请调整配置:
1014
+ ${this.systemPrompt}`:X;return this.executeLoop($,Y,Z,Q)}async executeLoop($,Y,Z,X){if(!this.isInitialized)throw Error("Agent未初始化");let Q=Date.now();try{let J=this.executionPipeline.getRegistry(),q=Y.permissionMode,G=J.getFunctionDeclarationsByMode(q);if(q==="plan"){let V=J.getReadOnlyTools();y.debug(`\uD83D\uDD12 Plan mode: 使用只读工具 (${V.length} 个): ${V.map((R)=>R.name).join(", ")}`)}let W=Y.messages.length===0||!Y.messages.some((V)=>V.role==="system"),U=[];if(W&&X)U.push({role:"system",content:X});U.push(...Y.messages,{role:"user",content:$});let H=null;try{let V=this.executionEngine?.getContextManager(),R=typeof $==="string"?$:$.filter((L)=>L.type==="text").map((L)=>L.text).join(`
1015
+ `);if(V&&Y.sessionId&&R.trim()!=="")H=await V.saveMessage(Y.sessionId,"user",R);else if(R.trim()==="")y.debug("[Agent] 跳过保存空用户消息")}catch(V){y.warn("[Agent] 保存用户消息失败:",V)}let O=100,F=Y.permissionMode==="yolo",_=this.runtimeOptions.maxTurns??Z?.maxTurns??this.config.maxTurns??-1;if(_===0)return{success:!1,error:{type:"chat_disabled",message:`对话功能已被禁用 (maxTurns=0)。如需启用,请调整配置:
1003
1016
  `+` • CLI 参数: blade --max-turns -1
1004
1017
  `+` • 配置文件: ~/.blade/config.json 中设置 "maxTurns": -1
1005
- `+" • 环境变量: export BLADE_MAX_TURNS=-1"},metadata:{turnsCount:0,toolCallsCount:0,duration:0}};let F=_===-1?O:Math.min(_,O);if(this.config.debug)E.debug(`[MaxTurns] runtimeOptions: ${this.runtimeOptions.maxTurns}, options: ${Z?.maxTurns}, config: ${this.config.maxTurns}, 最终: ${_} → ${F}, YOLO: ${z}`);let N=0,w=[],B=0,A;while(!0){if(Z?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:N,toolCallsCount:w.length,duration:Date.now()-Q}};let D=Y.messages.length;if(await this.checkAndCompactInLoop(Y,N,A,Z?.onCompacting)){E.debug(`[Agent] [轮次 ${N}] 检测到压缩发生,重建 messages 数组 (${D} → ${Y.messages.length} 条历史消息)`);let L=W&&X?1:0,V=L+D,j=U.slice(0,L),m=U.slice(V);U.length=0,U.push(...j,...Y.messages,...m),E.debug(`[Agent] [轮次 ${N}] messages 重建完成: ${j.length} system + ${Y.messages.length} 历史 + ${m.length} 新增 = ${U.length} 总计`)}if(N++,E.debug(`\uD83D\uDD04 [轮次 ${N}/${F}] 调用 LLM...`),Z?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:N-1,toolCallsCount:w.length,duration:Date.now()-Q}};Z?.onTurnStart?.({turn:N,maxTurns:F}),E.debug(`
1006
- ========== 发送给 LLM ==========`),E.debug("轮次:",N+1),E.debug("消息数量:",U.length),E.debug("最后 3 条消息:"),U.slice(-3).forEach((L,V)=>{if(E.debug(` [${V}] ${L.role}:`,typeof L.content==="string"?L.content.substring(0,100)+(L.content.length>100?"...":""):JSON.stringify(L.content).substring(0,100)),L.tool_calls)E.debug(" tool_calls:",L.tool_calls.map((j)=>("function"in j)?j.function.name:j.type).join(", "))}),E.debug("可用工具数量:",K.length),E.debug(`================================
1007
- `);let b=await this.chatService.chat(U,K,Z?.signal);if(b.usage){if(b.usage.totalTokens)B+=b.usage.totalTokens;if(A=b.usage.promptTokens,E.debug(`[Agent] LLM usage: prompt=${A}, completion=${b.usage.completionTokens}, total=${b.usage.totalTokens}`),Z?.onTokenUsage)Z.onTokenUsage({inputTokens:b.usage.promptTokens??0,outputTokens:b.usage.completionTokens??0,totalTokens:B,maxContextTokens:this.config.maxContextTokens})}if(Z?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:N-1,toolCallsCount:w.length,duration:Date.now()-Q}};if(E.debug(`
1008
- ========== LLM 返回 ==========`),E.debug("Content:",b.content),E.debug("Tool Calls:",JSON.stringify(b.toolCalls,null,2)),E.debug("当前权限模式:",Y.permissionMode),E.debug(`================================
1009
- `),b.reasoningContent&&Z?.onThinking)Z.onThinking(b.reasoningContent);if(b.content&&b.content.trim()&&Z?.onContent)Z.onContent(b.content);if(!b.toolCalls||b.toolCalls.length===0){let L=[/:\s*$/,/:\s*$/,/\.\.\.\s*$/,/让我(先|来|开始|查看|检查|修复)/,/Let me (first|start|check|look|fix)/i],V=b.content||"",j=L.some((v)=>v.test(V)),m="请执行你提到的操作,不要只是描述。",P=U.slice(-10).filter((v)=>v.role==="user"&&v.content==="请执行你提到的操作,不要只是描述。").length;if(j&&P<2){E.debug(`⚠️ 检测到意图未完成(重试 ${P+1}/2): "${V.slice(-50)}"`),U.push({role:"user",content:"请执行你提到的操作,不要只是描述。"});continue}E.debug("✅ 任务完成 - LLM 未请求工具调用");try{let v=this.executionEngine?.getContextManager();if(v&&Y.sessionId&&b.content)if(b.content.trim()!=="")H=await v.saveMessage(Y.sessionId,"assistant",b.content,H);else E.debug("[Agent] 跳过保存空响应(任务完成时)")}catch(v){E.warn("[Agent] 保存助手消息失败:",v)}return{success:!0,finalMessage:b.content,metadata:{turnsCount:N,toolCallsCount:w.length,duration:Date.now()-Q,tokensUsed:B}}}U.push({role:"assistant",content:b.content||"",reasoningContent:b.reasoningContent,tool_calls:b.toolCalls});try{let L=this.executionEngine?.getContextManager();if(L&&Y.sessionId&&b.content)if(b.content.trim()!=="")H=await L.saveMessage(Y.sessionId,"assistant",b.content,H);else E.debug("[Agent] 跳过保存空响应(工具调用时)")}catch(L){E.warn("[Agent] 保存助手工具调用消息失败:",L)}for(let L of b.toolCalls){if(L.type!=="function")continue;if(Z?.signal?.aborted)return E.info(`[Agent] Aborting before tool ${L.function.name} due to signal.aborted=true`),{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:N,toolCallsCount:w.length,duration:Date.now()-Q}};try{if(Z?.onToolStart){let n1=this.executionPipeline.getRegistry().get(L.function.name)?.kind;Z.onToolStart(L,n1)}let V=JSON.parse(L.function.arguments);if(V.todos&&typeof V.todos==="string")try{V.todos=JSON.parse(V.todos),this.log("[Agent] 自动修复了字符串化的 todos 参数")}catch{this.error("[Agent] todos 参数格式异常,将由验证层处理")}let j=null;try{let X1=this.executionEngine?.getContextManager();if(X1&&Y.sessionId)j=await X1.saveToolUse(Y.sessionId,L.function.name,V,H)}catch(X1){E.warn("[Agent] 保存工具调用失败:",X1)}let m=Z?.signal;if(!m)E.error("[Agent] Missing signal in tool execution, this should not happen");E.debug("[Agent] Passing confirmationHandler to ExecutionPipeline.execute:",{toolName:L.function.name,hasHandler:!!Y.confirmationHandler,hasMethod:!!Y.confirmationHandler?.requestConfirmation,methodType:typeof Y.confirmationHandler?.requestConfirmation});let P=await this.executionPipeline.execute(L.function.name,V,{sessionId:Y.sessionId,userId:Y.userId||"default",workspaceRoot:Y.workspaceRoot||process.cwd(),signal:m,confirmationHandler:Y.confirmationHandler,permissionMode:Y.permissionMode});if(w.push(P),E.debug(`
1010
- ========== 工具执行结果 ==========`),E.debug("工具名称:",L.function.name),E.debug("成功:",P.success),E.debug("LLM Content:",P.llmContent),E.debug("Display Content:",P.displayContent),P.error)E.debug("错误:",P.error);if(E.debug(`==================================
1011
- `),P.metadata?.shouldExitLoop){E.debug("\uD83D\uDEAA 检测到退出循环标记,结束 Agent 循环");let X1=typeof P.llmContent==="string"?P.llmContent:"循环已退出";return{success:P.success,finalMessage:X1,metadata:{turnsCount:N,toolCallsCount:w.length,duration:Date.now()-Q,shouldExitLoop:!0,targetMode:P.metadata.targetMode}}}if(Z?.onToolResult){E.debug("[Agent] Calling onToolResult:",{toolName:L.function.name,hasCallback:!0,resultSuccess:P.success,resultKeys:Object.keys(P),hasMetadata:!!P.metadata,metadataKeys:P.metadata?Object.keys(P.metadata):[],hasSummary:!!P.metadata?.summary,summary:P.metadata?.summary});try{await Z.onToolResult(L,P),E.debug("[Agent] onToolResult callback completed successfully")}catch(X1){E.error("[Agent] onToolResult callback error:",X1)}}else E.debug("[Agent] No onToolResult callback provided");try{let X1=this.executionEngine?.getContextManager();if(X1&&Y.sessionId)H=await X1.saveToolResult(Y.sessionId,L.id,P.success?P.llmContent:void 0,j,P.success?void 0:P.error?.message)}catch(X1){E.warn("[Agent] 保存工具结果失败:",X1)}if(L.function.name==="TodoWrite"&&P.success&&P.llmContent){let X1=typeof P.llmContent==="object"?P.llmContent:{},n1=Array.isArray(X1)?X1:X1.todos||[];w0().setTodos(n1)}let v=P.success?P.llmContent||P.displayContent||"":P.error?.message||"执行失败";if(typeof v==="object"&&v!==null)v=JSON.stringify(v,null,2);let Z1=typeof v==="string"?v:JSON.stringify(v);U.push({role:"tool",tool_call_id:L.id,name:L.function.name,content:Z1})}catch(V){E.error(`Tool execution failed for ${L.function.name}:`,V),U.push({role:"tool",tool_call_id:L.id,name:L.function.name,content:`Execution failed: ${V instanceof Error?V.message:"Unknown error"}`})}}if(Z?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:N,toolCallsCount:w.length,duration:Date.now()-Q}};if(N>=F&&!z){if(E.info(`⚠️ 达到轮次上限 ${F} 轮,等待用户确认...`),Z?.onTurnLimitReached){let L=await Z.onTurnLimitReached({turnsCount:N});if(L?.continue){E.info("✅ 用户选择继续,压缩上下文...");try{let V=this.chatService.getConfig(),j=await l2.compact(Y.messages,{trigger:"auto",modelName:V.model,maxContextTokens:V.maxContextTokens??this.config.maxContextTokens,apiKey:V.apiKey,baseURL:V.baseUrl,actualPreTokens:A});Y.messages=j.compactedMessages;let m=U.find((v)=>v.role==="system");if(U.length=0,m)U.push(m);U.push(...Y.messages);let P={role:"user",content:`This session is being continued from a previous conversation. The conversation is summarized above.
1018
+ `+" • 环境变量: export BLADE_MAX_TURNS=-1"},metadata:{turnsCount:0,toolCallsCount:0,duration:0}};let z=_===-1?O:Math.min(_,O);if(this.config.debug)y.debug(`[MaxTurns] runtimeOptions: ${this.runtimeOptions.maxTurns}, options: ${Z?.maxTurns}, config: ${this.config.maxTurns}, 最终: ${_} → ${z}, YOLO: ${F}`);let w=0,B=[],N=0,b;while(!0){if(Z?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:w,toolCallsCount:B.length,duration:Date.now()-Q}};let V=Y.messages.length;if(await this.checkAndCompactInLoop(Y,w,b,Z?.onCompacting)){y.debug(`[Agent] [轮次 ${w}] 检测到压缩发生,重建 messages 数组 (${V} → ${Y.messages.length} 条历史消息)`);let A=W&&X?1:0,k=A+V,I=U.slice(0,A),T=U.slice(k);U.length=0,U.push(...I,...Y.messages,...T),y.debug(`[Agent] [轮次 ${w}] messages 重建完成: ${I.length} system + ${Y.messages.length} 历史 + ${T.length} 新增 = ${U.length} 总计`)}if(w++,y.debug(`\uD83D\uDD04 [轮次 ${w}/${z}] 调用 LLM...`),Z?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:w-1,toolCallsCount:B.length,duration:Date.now()-Q}};Z?.onTurnStart?.({turn:w,maxTurns:z}),y.debug(`
1019
+ ========== 发送给 LLM ==========`),y.debug("轮次:",w+1),y.debug("消息数量:",U.length),y.debug("最后 3 条消息:"),U.slice(-3).forEach((A,k)=>{if(y.debug(` [${k}] ${A.role}:`,typeof A.content==="string"?A.content.substring(0,100)+(A.content.length>100?"...":""):JSON.stringify(A.content).substring(0,100)),A.tool_calls)y.debug(" tool_calls:",A.tool_calls.map((I)=>("function"in I)?I.function.name:I.type).join(", "))}),y.debug("可用工具数量:",G.length),y.debug(`================================
1020
+ `);let L=await this.chatService.chat(U,G,Z?.signal);if(L.usage){if(L.usage.totalTokens)N+=L.usage.totalTokens;if(b=L.usage.promptTokens,y.debug(`[Agent] LLM usage: prompt=${b}, completion=${L.usage.completionTokens}, total=${L.usage.totalTokens}`),Z?.onTokenUsage)Z.onTokenUsage({inputTokens:L.usage.promptTokens??0,outputTokens:L.usage.completionTokens??0,totalTokens:N,maxContextTokens:this.config.maxContextTokens})}if(Z?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:w-1,toolCallsCount:B.length,duration:Date.now()-Q}};if(y.debug(`
1021
+ ========== LLM 返回 ==========`),y.debug("Content:",L.content),y.debug("Tool Calls:",JSON.stringify(L.toolCalls,null,2)),y.debug("当前权限模式:",Y.permissionMode),y.debug(`================================
1022
+ `),L.reasoningContent&&Z?.onThinking&&!Z.signal?.aborted)Z.onThinking(L.reasoningContent);if(L.content&&L.content.trim()&&Z?.onContent&&!Z.signal?.aborted)Z.onContent(L.content);if(!L.toolCalls||L.toolCalls.length===0){let A=[/:\s*$/,/:\s*$/,/\.\.\.\s*$/,/让我(先|来|开始|查看|检查|修复)/,/Let me (first|start|check|look|fix)/i],k=L.content||"",I=A.some((v)=>v.test(k)),T="请执行你提到的操作,不要只是描述。",E=U.slice(-10).filter((v)=>v.role==="user"&&v.content==="请执行你提到的操作,不要只是描述。").length;if(I&&E<2){y.debug(`⚠️ 检测到意图未完成(重试 ${E+1}/2): "${k.slice(-50)}"`),U.push({role:"user",content:"请执行你提到的操作,不要只是描述。"});continue}y.debug("✅ 任务完成 - LLM 未请求工具调用");try{let v=this.executionEngine?.getContextManager();if(v&&Y.sessionId&&L.content)if(L.content.trim()!=="")H=await v.saveMessage(Y.sessionId,"assistant",L.content,H);else y.debug("[Agent] 跳过保存空响应(任务完成时)")}catch(v){y.warn("[Agent] 保存助手消息失败:",v)}return{success:!0,finalMessage:L.content,metadata:{turnsCount:w,toolCallsCount:B.length,duration:Date.now()-Q,tokensUsed:N}}}U.push({role:"assistant",content:L.content||"",reasoningContent:L.reasoningContent,tool_calls:L.toolCalls});try{let A=this.executionEngine?.getContextManager();if(A&&Y.sessionId&&L.content)if(L.content.trim()!=="")H=await A.saveMessage(Y.sessionId,"assistant",L.content,H);else y.debug("[Agent] 跳过保存空响应(工具调用时)")}catch(A){y.warn("[Agent] 保存助手工具调用消息失败:",A)}for(let A of L.toolCalls){if(A.type!=="function")continue;if(Z?.signal?.aborted)return y.info(`[Agent] Aborting before tool ${A.function.name} due to signal.aborted=true`),{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:w,toolCallsCount:B.length,duration:Date.now()-Q}};try{if(Z?.onToolStart&&!Z.signal?.aborted){let D1=this.executionPipeline.getRegistry().get(A.function.name)?.kind;Z.onToolStart(A,D1)}let k=JSON.parse(A.function.arguments);if(k.todos&&typeof k.todos==="string")try{k.todos=JSON.parse(k.todos),this.log("[Agent] 自动修复了字符串化的 todos 参数")}catch{this.error("[Agent] todos 参数格式异常,将由验证层处理")}let I=null;try{let u=this.executionEngine?.getContextManager();if(u&&Y.sessionId)I=await u.saveToolUse(Y.sessionId,A.function.name,k,H)}catch(u){y.warn("[Agent] 保存工具调用失败:",u)}let T=Z?.signal;if(!T)y.error("[Agent] Missing signal in tool execution, this should not happen");y.debug("[Agent] Passing confirmationHandler to ExecutionPipeline.execute:",{toolName:A.function.name,hasHandler:!!Y.confirmationHandler,hasMethod:!!Y.confirmationHandler?.requestConfirmation,methodType:typeof Y.confirmationHandler?.requestConfirmation});let E=await this.executionPipeline.execute(A.function.name,k,{sessionId:Y.sessionId,userId:Y.userId||"default",workspaceRoot:Y.workspaceRoot||process.cwd(),signal:T,confirmationHandler:Y.confirmationHandler,permissionMode:Y.permissionMode});if(B.push(E),y.debug(`
1023
+ ========== 工具执行结果 ==========`),y.debug("工具名称:",A.function.name),y.debug("成功:",E.success),y.debug("LLM Content:",E.llmContent),y.debug("Display Content:",E.displayContent),E.error)y.debug("错误:",E.error);if(y.debug(`==================================
1024
+ `),E.metadata?.shouldExitLoop){y.debug("\uD83D\uDEAA 检测到退出循环标记,结束 Agent 循环");let u=typeof E.llmContent==="string"?E.llmContent:"循环已退出";return{success:E.success,finalMessage:u,metadata:{turnsCount:w,toolCallsCount:B.length,duration:Date.now()-Q,shouldExitLoop:!0,targetMode:E.metadata.targetMode}}}if(Z?.onToolResult&&!Z.signal?.aborted){y.debug("[Agent] Calling onToolResult:",{toolName:A.function.name,hasCallback:!0,resultSuccess:E.success,resultKeys:Object.keys(E),hasMetadata:!!E.metadata,metadataKeys:E.metadata?Object.keys(E.metadata):[],hasSummary:!!E.metadata?.summary,summary:E.metadata?.summary});try{await Z.onToolResult(A,E),y.debug("[Agent] onToolResult callback completed successfully")}catch(u){y.error("[Agent] onToolResult callback error:",u)}}else y.debug("[Agent] No onToolResult callback provided");try{let u=this.executionEngine?.getContextManager();if(u&&Y.sessionId)H=await u.saveToolResult(Y.sessionId,A.id,E.success?E.llmContent:void 0,I,E.success?void 0:E.error?.message)}catch(u){y.warn("[Agent] 保存工具结果失败:",u)}if(A.function.name==="TodoWrite"&&E.success&&E.llmContent){let u=typeof E.llmContent==="object"?E.llmContent:{},D1=Array.isArray(u)?u:u.todos||[];w0().setTodos(D1)}let v=E.success?E.llmContent||E.displayContent||"":E.error?.message||"执行失败";if(typeof v==="object"&&v!==null)v=JSON.stringify(v,null,2);let g=typeof v==="string"?v:JSON.stringify(v);U.push({role:"tool",tool_call_id:A.id,name:A.function.name,content:g})}catch(k){y.error(`Tool execution failed for ${A.function.name}:`,k),U.push({role:"tool",tool_call_id:A.id,name:A.function.name,content:`Execution failed: ${k instanceof Error?k.message:"Unknown error"}`})}}if(Z?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:w,toolCallsCount:B.length,duration:Date.now()-Q}};if(w>=z&&!F){if(y.info(`⚠️ 达到轮次上限 ${z} 轮,等待用户确认...`),Z?.onTurnLimitReached){let A=await Z.onTurnLimitReached({turnsCount:w});if(A?.continue){y.info("✅ 用户选择继续,压缩上下文...");try{let k=this.chatService.getConfig(),I=await r2.compact(Y.messages,{trigger:"auto",modelName:k.model,maxContextTokens:k.maxContextTokens??this.config.maxContextTokens,apiKey:k.apiKey,baseURL:k.baseUrl,actualPreTokens:b});Y.messages=I.compactedMessages;let T=U.find((v)=>v.role==="system");if(U.length=0,T)U.push(T);U.push(...Y.messages);let E={role:"user",content:`This session is being continued from a previous conversation. The conversation is summarized above.
1025
+
1026
+ Please continue the conversation from where we left it off without asking the user any further questions. Continue with the last task that you were asked to work on.`};U.push(E),Y.messages.push(E);try{let v=this.executionEngine?.getContextManager();if(v&&Y.sessionId)await v.saveCompaction(Y.sessionId,I.summary,{trigger:"auto",preTokens:I.preTokens,postTokens:I.postTokens,filesIncluded:I.filesIncluded},null)}catch(v){y.warn("[Agent] 保存压缩数据失败:",v)}y.info(`✅ 上下文已压缩 (${I.preTokens} → ${I.postTokens} tokens),重置轮次计数`)}catch(k){y.error("[Agent] 压缩失败,使用降级策略:",k);let I=U.find((E)=>E.role==="system"),T=U.slice(-80);if(U.length=0,I&&!T.some((E)=>E.role==="system"))U.push(I);U.push(...T),Y.messages=U.filter((E)=>E.role!=="system"),y.warn(`⚠️ 降级压缩完成,保留 ${U.length} 条消息`)}w=0;continue}return{success:!0,finalMessage:A?.reason||"已达到对话轮次上限,用户选择停止",metadata:{turnsCount:w,toolCallsCount:B.length,duration:Date.now()-Q,tokensUsed:N}}}return{success:!1,error:{type:"max_turns_exceeded",message:`已达到轮次上限 (${z} 轮)。使用 --permission-mode yolo 跳过此限制。`},metadata:{turnsCount:w,toolCallsCount:B.length,duration:Date.now()-Q,tokensUsed:N}}}}}catch(J){if(J instanceof Error&&(J.name==="AbortError"||J.message.includes("aborted")))return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:0,toolCallsCount:0,duration:Date.now()-Q}};return y.error("Enhanced chat processing error:",J),{success:!1,error:{type:"api_error",message:`处理消息时发生错误: ${J instanceof Error?J.message:"未知错误"}`,details:J},metadata:{turnsCount:0,toolCallsCount:0,duration:Date.now()-Q}}}}async runAgenticLoop($,Y,Z){if(!this.isInitialized)throw Error("Agent未初始化");let X={messages:Y.messages,userId:Y.userId||"subagent",sessionId:Y.sessionId||`subagent_${Date.now()}`,workspaceRoot:Y.workspaceRoot||process.cwd(),signal:Y.signal,confirmationHandler:Y.confirmationHandler};return await this.runLoop($,X,Z)}async chatWithSystem($,Y){if(!this.isInitialized)throw Error("Agent未初始化");let Z=[{role:"system",content:$},{role:"user",content:Y}];return(await this.chatService.chat(Z)).content}getActiveTask(){return this.activeTask}getChatService(){return this.chatService}getContextManager(){return this.executionEngine?.getContextManager()}getStats(){return{initialized:this.isInitialized,activeTask:this.activeTask?.id,components:{chatService:this.chatService?"ready":"not_loaded",executionEngine:this.executionEngine?"ready":"not_loaded"}}}getAvailableTools(){return this.executionPipeline?this.executionPipeline.getRegistry().getAll():[]}getToolRegistry(){return this.executionPipeline.getRegistry()}applyToolWhitelist($){let Y=this.executionPipeline.getRegistry(),X=Y.getAll().filter((Q)=>!$.includes(Q.name));for(let Q of X)Y.unregister(Q.name);y.debug(`\uD83D\uDD12 Applied tool whitelist: ${$.join(", ")} (removed ${X.length} tools)`)}getToolStats(){let $=this.getAvailableTools(),Y=new Map;return $.forEach((Z)=>{let X=Y.get(Z.kind)||0;Y.set(Z.kind,X+1)}),{totalTools:$.length,toolsByKind:Object.fromEntries(Y),toolNames:$.map((Z)=>Z.name)}}async destroy(){this.log("销毁Agent...");try{this.isInitialized=!1,this.log("Agent已销毁")}catch($){throw this.error("Agent销毁失败",$),$}}generateTaskId(){return`task_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}log($,Y){y.debug(`[MainAgent] ${$}`,Y||"")}error($,Y){y.error(`[MainAgent] ${$}`,Y||"")}async initializeSystemPrompt(){try{let $=this.runtimeOptions.systemPrompt,Y=this.runtimeOptions.appendSystemPrompt,Z=await E6({projectPath:process.cwd(),replaceDefault:$,append:Y,includeEnvironment:!1});if(this.systemPrompt=Z.prompt,this.systemPrompt)this.log("系统提示已加载"),y.debug(`[SystemPrompt] 加载来源: ${Z.sources.filter((X)=>X.loaded).map((X)=>X.name).join(", ")}`)}catch($){this.error("初始化系统提示失败",$)}}getSystemPrompt(){return this.systemPrompt}async checkAndCompactInLoop($,Y,Z,X){if(Z===void 0)return y.debug(`[Agent] [轮次 ${Y}] 压缩检查: 跳过(无历史 usage 数据)`),!1;let Q=this.chatService.getConfig(),J=Q.model,q=Q.maxContextTokens??this.config.maxContextTokens,G=Q.maxOutputTokens??this.config.maxOutputTokens,K=q-G,W=Math.floor(K*0.8);if(y.debug(`[Agent] [轮次 ${Y}] 压缩检查:`,{promptTokens:Z,maxContextTokens:q,maxOutputTokens:G,availableForInput:K,threshold:W,shouldCompact:Z>=W}),Z<W)return!1;let U=Y===0?"[Agent] 触发自动压缩":`[Agent] [轮次 ${Y}] 触发循环内自动压缩`;y.debug(U),X?.(!0);try{let H=await r2.compact($.messages,{trigger:"auto",modelName:J,maxContextTokens:q,apiKey:Q.apiKey,baseURL:Q.baseUrl,actualPreTokens:Z});if(H.success)$.messages=H.compactedMessages,y.debug(`[Agent] [轮次 ${Y}] 压缩完成: ${H.preTokens} → ${H.postTokens} tokens (-${((1-H.postTokens/H.preTokens)*100).toFixed(1)}%)`);else $.messages=H.compactedMessages,y.warn(`[Agent] [轮次 ${Y}] 压缩使用降级策略: ${H.preTokens} → ${H.postTokens} tokens`);try{let O=this.executionEngine?.getContextManager();if(O&&$.sessionId)await O.saveCompaction($.sessionId,H.summary,{trigger:"auto",preTokens:H.preTokens,postTokens:H.postTokens,filesIncluded:H.filesIncluded},null),y.debug(`[Agent] [轮次 ${Y}] 压缩数据已保存到 JSONL`)}catch(O){y.warn(`[Agent] [轮次 ${Y}] 保存压缩数据失败:`,O)}return X?.(!1),!0}catch(H){return X?.(!1),y.error(`[Agent] [轮次 ${Y}] 压缩失败,继续执行`,H),!1}}async registerBuiltinTools(){try{let $=await o5({sessionId:"default",configDir:bY.join(AY.homedir(),".blade")});y.debug(`\uD83D\uDCE6 Registering ${$.length} builtin tools...`),this.executionPipeline.getRegistry().registerAll($);let Y=this.executionPipeline.getRegistry().getAll().length;y.debug(`✅ Builtin tools registered: ${Y} tools`),y.debug(`[Tools] ${this.executionPipeline.getRegistry().getAll().map((Z)=>Z.name).join(", ")}`),await this.registerMcpTools()}catch($){throw y.error("Failed to register builtin tools:",$),$}}async registerMcpTools(){try{if(this.runtimeOptions.mcpConfig&&this.runtimeOptions.mcpConfig.length>0)await A3(this.runtimeOptions.mcpConfig);let $=Q0();if(Object.keys($).length===0){y.debug("\uD83D\uDCE6 No MCP servers configured");return}let Y=f1.getInstance();for(let[X,Q]of Object.entries($))try{y.debug(`\uD83D\uDD0C Connecting to MCP server: ${X}`),await Y.registerServer(X,Q),y.debug(`✅ MCP server "${X}" connected`)}catch(J){y.warn(`⚠️ MCP server "${X}" connection failed:`,J)}let Z=await Y.getAvailableTools();if(Z.length>0)this.executionPipeline.getRegistry().registerAll(Z),y.debug(`✅ Registered ${Z.length} MCP tools`),y.debug(`[MCP Tools] ${Z.map((X)=>X.name).join(", ")}`)}catch($){y.warn("Failed to register MCP tools:",$)}}async loadSubagents(){if(M1.getAllNames().length>0){y.debug(`\uD83D\uDCE6 Subagents already loaded: ${M1.getAllNames().join(", ")}`);return}try{let $=M1.loadFromStandardLocations();if($>0)y.debug(`✅ Loaded ${$} subagents: ${M1.getAllNames().join(", ")}`);else y.debug("\uD83D\uDCE6 No subagents configured")}catch($){y.warn("Failed to load subagents:",$)}}async processAtMentionsForContent($){if(!this.attachmentCollector)return $;if(typeof $==="string")return this.processAtMentions($);let Y=[];for(let X of $)if(X.type==="text")Y.push(X.text);if(Y.length===0)return $;let Z=Y.join(`
1027
+ `);try{let X=await this.attachmentCollector.collect(Z);if(X.length===0)return $;y.debug(`✅ Processed ${X.length} @ file mentions in multimodal message`);let Q=this.buildAttachmentText(X);if(!Q)return $;return[...$,{type:"text",text:Q}]}catch(X){return y.error("Failed to process @ mentions in multimodal message:",X),$}}buildAttachmentText($){let Y=[],Z=[];for(let Q of $)if(Q.type==="file"){let J=Q.metadata?.lineRange?` (lines ${Q.metadata.lineRange.start}${Q.metadata.lineRange.end?`-${Q.metadata.lineRange.end}`:""})`:"";Y.push(`<file path="${Q.path}"${J?` range="${J}"`:""}>`,Q.content,"</file>")}else if(Q.type==="directory")Y.push(`<directory path="${Q.path}">`,Q.content,"</directory>");else if(Q.type==="error")Z.push(`- @${Q.path}: ${Q.error}`);let X="";if(Y.length>0)X+=`
1028
+
1029
+ <system-reminder>
1030
+ `,X+=`The following files were mentioned with @ syntax:
1031
+
1032
+ `,X+=Y.join(`
1033
+ `),X+=`
1034
+ </system-reminder>`;if(Z.length>0)X+=`
1012
1035
 
1013
- Please continue the conversation from where we left it off without asking the user any further questions. Continue with the last task that you were asked to work on.`};U.push(P),Y.messages.push(P);try{let v=this.executionEngine?.getContextManager();if(v&&Y.sessionId)await v.saveCompaction(Y.sessionId,j.summary,{trigger:"auto",preTokens:j.preTokens,postTokens:j.postTokens,filesIncluded:j.filesIncluded},null)}catch(v){E.warn("[Agent] 保存压缩数据失败:",v)}E.info(`✅ 上下文已压缩 (${j.preTokens} → ${j.postTokens} tokens),重置轮次计数`)}catch(V){E.error("[Agent] 压缩失败,使用降级策略:",V);let j=U.find((P)=>P.role==="system"),m=U.slice(-80);if(U.length=0,j&&!m.some((P)=>P.role==="system"))U.push(j);U.push(...m),Y.messages=U.filter((P)=>P.role!=="system"),E.warn(`⚠️ 降级压缩完成,保留 ${U.length} 条消息`)}N=0;continue}return{success:!0,finalMessage:L?.reason||"已达到对话轮次上限,用户选择停止",metadata:{turnsCount:N,toolCallsCount:w.length,duration:Date.now()-Q,tokensUsed:B}}}return{success:!1,error:{type:"max_turns_exceeded",message:`已达到轮次上限 (${F} 轮)。使用 --permission-mode yolo 跳过此限制。`},metadata:{turnsCount:N,toolCallsCount:w.length,duration:Date.now()-Q,tokensUsed:B}}}}}catch(J){if(J instanceof Error&&(J.name==="AbortError"||J.message.includes("aborted")))return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:0,toolCallsCount:0,duration:Date.now()-Q}};return E.error("Enhanced chat processing error:",J),{success:!1,error:{type:"api_error",message:`处理消息时发生错误: ${J instanceof Error?J.message:"未知错误"}`,details:J},metadata:{turnsCount:0,toolCallsCount:0,duration:Date.now()-Q}}}}async runAgenticLoop($,Y,Z){if(!this.isInitialized)throw Error("Agent未初始化");let X={messages:Y.messages,userId:Y.userId||"subagent",sessionId:Y.sessionId||`subagent_${Date.now()}`,workspaceRoot:Y.workspaceRoot||process.cwd(),signal:Y.signal,confirmationHandler:Y.confirmationHandler};return await this.runLoop($,X,Z)}async chatWithSystem($,Y){if(!this.isInitialized)throw Error("Agent未初始化");let Z=[{role:"system",content:$},{role:"user",content:Y}];return(await this.chatService.chat(Z)).content}getActiveTask(){return this.activeTask}getChatService(){return this.chatService}getContextManager(){return this.executionEngine?.getContextManager()}getStats(){return{initialized:this.isInitialized,activeTask:this.activeTask?.id,components:{chatService:this.chatService?"ready":"not_loaded",executionEngine:this.executionEngine?"ready":"not_loaded"}}}getAvailableTools(){return this.executionPipeline?this.executionPipeline.getRegistry().getAll():[]}getToolRegistry(){return this.executionPipeline.getRegistry()}applyToolWhitelist($){let Y=this.executionPipeline.getRegistry(),X=Y.getAll().filter((Q)=>!$.includes(Q.name));for(let Q of X)Y.unregister(Q.name);E.debug(`\uD83D\uDD12 Applied tool whitelist: ${$.join(", ")} (removed ${X.length} tools)`)}getToolStats(){let $=this.getAvailableTools(),Y=new Map;return $.forEach((Z)=>{let X=Y.get(Z.kind)||0;Y.set(Z.kind,X+1)}),{totalTools:$.length,toolsByKind:Object.fromEntries(Y),toolNames:$.map((Z)=>Z.name)}}async destroy(){this.log("销毁Agent...");try{this.isInitialized=!1,this.log("Agent已销毁")}catch($){throw this.error("Agent销毁失败",$),$}}generateTaskId(){return`task_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}log($,Y){E.debug(`[MainAgent] ${$}`,Y||"")}error($,Y){E.error(`[MainAgent] ${$}`,Y||"")}async initializeSystemPrompt(){try{let $=this.runtimeOptions.systemPrompt,Y=this.runtimeOptions.appendSystemPrompt,Z=await V6({projectPath:process.cwd(),replaceDefault:$,append:Y,includeEnvironment:!1});if(this.systemPrompt=Z.prompt,this.systemPrompt)this.log("系统提示已加载"),E.debug(`[SystemPrompt] 加载来源: ${Z.sources.filter((X)=>X.loaded).map((X)=>X.name).join(", ")}`)}catch($){this.error("初始化系统提示失败",$)}}getSystemPrompt(){return this.systemPrompt}async checkAndCompactInLoop($,Y,Z,X){if(Z===void 0)return E.debug(`[Agent] [轮次 ${Y}] 压缩检查: 跳过(无历史 usage 数据)`),!1;let Q=this.chatService.getConfig(),J=Q.model,q=Q.maxContextTokens??this.config.maxContextTokens,K=Q.maxOutputTokens??this.config.maxOutputTokens,G=q-K,W=Math.floor(G*0.8);if(E.debug(`[Agent] [轮次 ${Y}] 压缩检查:`,{promptTokens:Z,maxContextTokens:q,maxOutputTokens:K,availableForInput:G,threshold:W,shouldCompact:Z>=W}),Z<W)return!1;let U=Y===0?"[Agent] 触发自动压缩":`[Agent] [轮次 ${Y}] 触发循环内自动压缩`;E.debug(U),X?.(!0);try{let H=await l2.compact($.messages,{trigger:"auto",modelName:J,maxContextTokens:q,apiKey:Q.apiKey,baseURL:Q.baseUrl,actualPreTokens:Z});if(H.success)$.messages=H.compactedMessages,E.debug(`[Agent] [轮次 ${Y}] 压缩完成: ${H.preTokens} → ${H.postTokens} tokens (-${((1-H.postTokens/H.preTokens)*100).toFixed(1)}%)`);else $.messages=H.compactedMessages,E.warn(`[Agent] [轮次 ${Y}] 压缩使用降级策略: ${H.preTokens} → ${H.postTokens} tokens`);try{let O=this.executionEngine?.getContextManager();if(O&&$.sessionId)await O.saveCompaction($.sessionId,H.summary,{trigger:"auto",preTokens:H.preTokens,postTokens:H.postTokens,filesIncluded:H.filesIncluded},null),E.debug(`[Agent] [轮次 ${Y}] 压缩数据已保存到 JSONL`)}catch(O){E.warn(`[Agent] [轮次 ${Y}] 保存压缩数据失败:`,O)}return X?.(!1),!0}catch(H){return X?.(!1),E.error(`[Agent] [轮次 ${Y}] 压缩失败,继续执行`,H),!1}}async registerBuiltinTools(){try{let $=await g5({sessionId:"default",configDir:HY.join(UY.homedir(),".blade")});E.debug(`\uD83D\uDCE6 Registering ${$.length} builtin tools...`),this.executionPipeline.getRegistry().registerAll($);let Y=this.executionPipeline.getRegistry().getAll().length;E.debug(`✅ Builtin tools registered: ${Y} tools`),E.debug(`[Tools] ${this.executionPipeline.getRegistry().getAll().map((Z)=>Z.name).join(", ")}`),await this.registerMcpTools()}catch($){throw E.error("Failed to register builtin tools:",$),$}}async registerMcpTools(){try{if(this.runtimeOptions.mcpConfig&&this.runtimeOptions.mcpConfig.length>0)await U3(this.runtimeOptions.mcpConfig);let $=X0();if(Object.keys($).length===0){E.debug("\uD83D\uDCE6 No MCP servers configured");return}let Y=C1.getInstance();for(let[X,Q]of Object.entries($))try{E.debug(`\uD83D\uDD0C Connecting to MCP server: ${X}`),await Y.registerServer(X,Q),E.debug(`✅ MCP server "${X}" connected`)}catch(J){E.warn(`⚠️ MCP server "${X}" connection failed:`,J)}let Z=await Y.getAvailableTools();if(Z.length>0)this.executionPipeline.getRegistry().registerAll(Z),E.debug(`✅ Registered ${Z.length} MCP tools`),E.debug(`[MCP Tools] ${Z.map((X)=>X.name).join(", ")}`)}catch($){E.warn("Failed to register MCP tools:",$)}}async loadSubagents(){if(M1.getAllNames().length>0){E.debug(`\uD83D\uDCE6 Subagents already loaded: ${M1.getAllNames().join(", ")}`);return}try{let $=M1.loadFromStandardLocations();if($>0)E.debug(`✅ Loaded ${$} subagents: ${M1.getAllNames().join(", ")}`);else E.debug("\uD83D\uDCE6 No subagents configured")}catch($){E.warn("Failed to load subagents:",$)}}async processAtMentions($){if(!this.attachmentCollector)return $;try{let Y=await this.attachmentCollector.collect($);if(Y.length===0)return $;return E.debug(`✅ Processed ${Y.length} @ file mentions`),this.appendAttachments($,Y)}catch(Y){return E.error("Failed to process @ mentions:",Y),$}}appendAttachments($,Y){let Z=[],X=[];for(let J of Y)if(J.type==="file"){let q=J.metadata?.lineRange?` (lines ${J.metadata.lineRange.start}${J.metadata.lineRange.end?`-${J.metadata.lineRange.end}`:""})`:"";Z.push(`<file path="${J.path}"${q?` range="${q}"`:""}>`,J.content,"</file>")}else if(J.type==="directory")Z.push(`<directory path="${J.path}">`,J.content,"</directory>");else if(J.type==="error")X.push(`- @${J.path}: ${J.error}`);let Q=$;if(Z.length>0)Q+=`
1036
+ ⚠️ Some files could not be loaded:
1037
+ `,X+=Z.join(`
1038
+ `);return X}async processAtMentions($){if(!this.attachmentCollector)return $;try{let Y=await this.attachmentCollector.collect($);if(Y.length===0)return $;return y.debug(`✅ Processed ${Y.length} @ file mentions`),this.appendAttachments($,Y)}catch(Y){return y.error("Failed to process @ mentions:",Y),$}}appendAttachments($,Y){let Z=[],X=[];for(let J of Y)if(J.type==="file"){let q=J.metadata?.lineRange?` (lines ${J.metadata.lineRange.start}${J.metadata.lineRange.end?`-${J.metadata.lineRange.end}`:""})`:"";Z.push(`<file path="${J.path}"${q?` range="${q}"`:""}>`,J.content,"</file>")}else if(J.type==="directory")Z.push(`<directory path="${J.path}">`,J.content,"</directory>");else if(J.type==="error")X.push(`- @${J.path}: ${J.error}`);let Q=$;if(Z.length>0)Q+=`
1014
1039
 
1015
1040
  <system-reminder>
1016
1041
  `,Q+=`The following files were mentioned with @ syntax:
@@ -1021,21 +1046,21 @@ Please continue the conversation from where we left it off without asking the us
1021
1046
 
1022
1047
  ⚠️ Some files could not be loaded:
1023
1048
  `,Q+=X.join(`
1024
- `);return Q}}var E;var J2=R(()=>{p2();a4();N1();H3();u2();_3();R3();r4();F1();m5();ZY();XY();n4();m6();WY();Z$();E=u("Agent")});import{readdir as DY,readFile as MY}from"node:fs/promises";import*as u6 from"node:path";class S0{static async listSessions(){let $=[],Y=u6.join(X2(),"projects");try{let Z=await DY(Y,{withFileTypes:!0});for(let X of Z){if(!X.isDirectory())continue;let Q=u6.join(Y,X.name),J=K8(X.name),K=(await DY(Q)).filter((G)=>G.endsWith(".jsonl"));for(let G of K){let W=u6.join(Q,G),U=G.replace(".jsonl","");try{let H=await this.extractMetadata(W,U,J);$.push(H)}catch(H){E2.warn(`[SessionService] 跳过损坏的会话文件: ${W}`,H)}}}return $.sort((X,Q)=>new Date(Q.lastMessageTime).getTime()-new Date(X.lastMessageTime).getTime()),$}catch(Z){return E2.error("[SessionService] 列出会话失败:",Z),[]}}static async extractMetadata($,Y,Z){let Q=(await MY($,"utf-8")).trim().split(`
1025
- `).filter((G)=>G.trim());if(Q.length===0)throw Error("空的 JSONL 文件");let J=JSON.parse(Q[0]),q=JSON.parse(Q[Q.length-1]),K=Q.some((G)=>{try{let W=JSON.parse(G);return W.type==="tool_result"&&W.toolResult?.error}catch{return!1}});return{sessionId:Y,projectPath:Z,gitBranch:J.gitBranch,messageCount:Q.length,firstMessageTime:J.timestamp,lastMessageTime:q.timestamp,hasErrors:K,filePath:$}}static async loadSession($,Y){try{if(Y){let Q=this.getSessionFilePath(Y,$);return await this.loadSessionFromFile(Q)}let X=(await this.listSessions()).find((Q)=>Q.sessionId===$);if(!X)throw Error(`未找到会话: ${$}`);return await this.loadSessionFromFile(X.filePath)}catch(Z){throw E2.error(`[SessionService] 加载会话失败 (${$}):`,Z),Z}}static async loadSessionFromFile($){let X=(await MY($,"utf-8")).trim().split(`
1026
- `).filter((Q)=>Q.trim()).map((Q)=>JSON.parse(Q));return this.convertJSONLToMessages(X)}static convertJSONLToMessages($){let Y=[],Z=-1;for(let Q=$.length-1;Q>=0;Q--)if($[Q].subtype==="compact_boundary"){Z=Q,E2.debug(`[SessionService] 检测到压缩边界 at index ${Q}`);break}let X=Z>=0?Z:0;for(let Q=X;Q<$.length;Q++){let J=$[Q];if(J.subtype==="compact_boundary"){E2.debug("[SessionService] 跳过 compact_boundary 消息");continue}switch(J.type){case"user":case"assistant":case"system":{let q={role:J.message.role,content:typeof J.message.content==="string"?J.message.content:JSON.stringify(J.message.content)};if(J.isCompactSummary)E2.debug("[SessionService] 加载压缩总结消息");Y.push(q);break}case"tool_result":if(J.toolResult){let q=J.toolResult.error?`Error: ${J.toolResult.error}`:typeof J.toolResult.output==="string"?J.toolResult.output:JSON.stringify(J.toolResult.output);Y.push({role:"tool",content:q,tool_call_id:J.toolResult.id,name:J.tool?.name})}break;case"tool_use":break;default:break}}if(Z>=0)E2.debug(`[SessionService] 会话已压缩,跳过前 ${Z} 条历史,加载 ${Y.length} 条消息`);return Y}static getSessionFilePath($,Y){let{getSessionFilePath:Z}=(e2(),zQ(T3));return Z($,Y)}}var E2;var c6=R(()=>{e2();N1();E2=u("Service")});function A1($){if($.acp)return{sendMessage:(Y)=>$.acp.sendMessage(`• ${Y}
1049
+ `);return Q}}var y;var K2=D(()=>{m2();Y8();B1();b3();l2();I3();y3();$8();z1();s5();OY();FY();Z8();r6();LY();Q$();y=l("Agent")});import{readdir as SY,readFile as CY}from"node:fs/promises";import*as n6 from"node:path";class C0{static async listSessions(){let $=[],Y=n6.join(q2(),"projects");try{let Z=await SY(Y,{withFileTypes:!0});for(let X of Z){if(!X.isDirectory())continue;let Q=n6.join(Y,X.name),J=F8(X.name),G=(await SY(Q)).filter((K)=>K.endsWith(".jsonl"));for(let K of G){let W=n6.join(Q,K),U=K.replace(".jsonl","");try{let H=await this.extractMetadata(W,U,J);$.push(H)}catch(H){E2.warn(`[SessionService] 跳过损坏的会话文件: ${W}`,H)}}}return $.sort((X,Q)=>new Date(Q.lastMessageTime).getTime()-new Date(X.lastMessageTime).getTime()),$}catch(Z){return E2.error("[SessionService] 列出会话失败:",Z),[]}}static async extractMetadata($,Y,Z){let Q=(await CY($,"utf-8")).trim().split(`
1050
+ `).filter((K)=>K.trim());if(Q.length===0)throw Error("空的 JSONL 文件");let J=JSON.parse(Q[0]),q=JSON.parse(Q[Q.length-1]),G=Q.some((K)=>{try{let W=JSON.parse(K);return W.type==="tool_result"&&W.toolResult?.error}catch{return!1}});return{sessionId:Y,projectPath:Z,gitBranch:J.gitBranch,messageCount:Q.length,firstMessageTime:J.timestamp,lastMessageTime:q.timestamp,hasErrors:G,filePath:$}}static async loadSession($,Y){try{if(Y){let Q=this.getSessionFilePath(Y,$);return await this.loadSessionFromFile(Q)}let X=(await this.listSessions()).find((Q)=>Q.sessionId===$);if(!X)throw Error(`未找到会话: ${$}`);return await this.loadSessionFromFile(X.filePath)}catch(Z){throw E2.error(`[SessionService] 加载会话失败 (${$}):`,Z),Z}}static async loadSessionFromFile($){let X=(await CY($,"utf-8")).trim().split(`
1051
+ `).filter((Q)=>Q.trim()).map((Q)=>JSON.parse(Q));return this.convertJSONLToMessages(X)}static convertJSONLToMessages($){let Y=[],Z=-1;for(let Q=$.length-1;Q>=0;Q--)if($[Q].subtype==="compact_boundary"){Z=Q,E2.debug(`[SessionService] 检测到压缩边界 at index ${Q}`);break}let X=Z>=0?Z:0;for(let Q=X;Q<$.length;Q++){let J=$[Q];if(J.subtype==="compact_boundary"){E2.debug("[SessionService] 跳过 compact_boundary 消息");continue}switch(J.type){case"user":case"assistant":case"system":{let q={role:J.message.role,content:typeof J.message.content==="string"?J.message.content:JSON.stringify(J.message.content)};if(J.isCompactSummary)E2.debug("[SessionService] 加载压缩总结消息");Y.push(q);break}case"tool_result":if(J.toolResult){let q=J.toolResult.error?`Error: ${J.toolResult.error}`:typeof J.toolResult.output==="string"?J.toolResult.output:JSON.stringify(J.toolResult.output);Y.push({role:"tool",content:q,tool_call_id:J.toolResult.id,name:J.tool?.name})}break;case"tool_use":break;default:break}}if(Z>=0)E2.debug(`[SessionService] 会话已压缩,跳过前 ${Z} 条历史,加载 ${Y.length} 条消息`);return Y}static getSessionFilePath($,Y){let{getSessionFilePath:Z}=(Y$(),kQ(u3));return Z($,Y)}}var E2;var o6=D(()=>{Y$();B1();E2=l("Service")});function A1($){if($.acp)return{sendMessage:(Y)=>$.acp.sendMessage(`• ${Y}
1027
1052
 
1028
- `),sendToolStart:$.acp.sendToolStart,sendToolResult:$.acp.sendToolResult};return{sendMessage:(Y)=>P$().addAssistantMessage(Y),sendToolStart:void 0,sendToolResult:void 0}}var H2=R(()=>{F1()});import CK from"node:os";import iY from"node:path";var rY;var aY=R(()=>{Z$();H2();rY={name:"agents",description:"Manage agent configurations",fullDescription:"Create, edit, or delete custom subagents. Subagents are specialized agents that Claude can delegate tasks to.",usage:"/agents [list|create|help]",category:"System",examples:["/agents","/agents list","/agents help"],async handler($,Y){let Z=$[0],X=A1(Y);if(!Z)return{success:!0,message:"show_agents_manager",data:{action:"show_agents_manager"}};if(Z==="list"){let J=M1.getAllNames().map((H)=>M1.getSubagent(H)).filter((H)=>H!==void 0);if(J.length===0){let H=`\uD83D\uDCCB **Agents 管理**
1053
+ `),sendToolStart:$.acp.sendToolStart,sendToolResult:$.acp.sendToolResult};return{sendMessage:(Y)=>f$().addAssistantMessage(Y),sendToolStart:void 0,sendToolResult:void 0}}var F2=D(()=>{z1()});import nG from"node:os";import XZ from"node:path";var QZ;var JZ=D(()=>{Q$();F2();QZ={name:"agents",description:"Manage agent configurations",fullDescription:"Create, edit, or delete custom subagents. Subagents are specialized agents that Claude can delegate tasks to.",usage:"/agents [list|create|help]",category:"System",examples:["/agents","/agents list","/agents help"],async handler($,Y){let Z=$[0],X=A1(Y);if(!Z)return{success:!0,message:"show_agents_manager",data:{action:"show_agents_manager"}};if(Z==="list"){let J=M1.getAllNames().map((H)=>M1.getSubagent(H)).filter((H)=>H!==void 0);if(J.length===0){let H=`\uD83D\uDCCB **Agents 管理**
1029
1054
 
1030
1055
  `+`❌ 没有找到任何 agent 配置
1031
1056
 
1032
1057
  `+`**配置文件位置:**
1033
- `+"- 项目级: `.blade/agents/`\n"+"- 用户级: `~/.blade/agents/`\n\n"+"\uD83D\uDCA1 使用 `/agents` 打开管理对话框";return X.sendMessage(H),{success:!0,message:"No agents found"}}let q=iY.join(process.cwd(),".blade","agents"),K=iY.join(CK.homedir(),".blade","agents"),G=J.filter((H)=>H.configPath?.startsWith(q)),W=J.filter((H)=>H.configPath?.startsWith(K)),U=`\uD83D\uDCCB **Agents 管理**
1058
+ `+"- 项目级: `.blade/agents/`\n"+"- 用户级: `~/.blade/agents/`\n\n"+"\uD83D\uDCA1 使用 `/agents` 打开管理对话框";return X.sendMessage(H),{success:!0,message:"No agents found"}}let q=XZ.join(process.cwd(),".blade","agents"),G=XZ.join(nG.homedir(),".blade","agents"),K=J.filter((H)=>H.configPath?.startsWith(q)),W=J.filter((H)=>H.configPath?.startsWith(G)),U=`\uD83D\uDCCB **Agents 管理**
1034
1059
 
1035
1060
  找到 **${J.length}** 个 agent:
1036
1061
 
1037
- `;if(G.length>0){U+=`**项目级** (.blade/agents/):
1038
- `;for(let H of G){if(U+=`
1062
+ `;if(K.length>0){U+=`**项目级** (.blade/agents/):
1063
+ `;for(let H of K){if(U+=`
1039
1064
  • **${H.name}**
1040
1065
  `,U+=` ${H.description}
1041
1066
  `,H.tools&&H.tools.length>0)U+=` 工具: ${H.tools.join(", ")}
@@ -1070,54 +1095,54 @@ Please continue the conversation from where we left it off without asking the us
1070
1095
  `+"- 项目级 (`.blade/agents/`) - 最高优先级\n"+"- 用户级 (`~/.blade/agents/`) - 较低优先级\n\n"+`**可用工具:**
1071
1096
  `+"- `Glob` - 文件搜索\n"+"- `Grep` - 内容搜索\n"+"- `Read` - 读取文件\n"+"- `Write` - 写入文件\n"+"- `Edit` - 编辑文件\n"+"- `Bash` - 执行命令\n"+"- 省略 `tools` 字段 = 继承所有工具\n\n"+"\uD83D\uDCA1 **提示:** 创建文件后,重启 Blade 使配置生效";return X.sendMessage(J),{success:!0,message:"Help displayed"}}if(Z==="create")return{success:!0,message:"show_agent_creation_wizard",data:{action:"show_agent_creation_wizard"}};let Q=`❌ 未知子命令: \`${Z}\`
1072
1097
 
1073
- `+"使用 `/agents help` 查看可用命令";return X.sendMessage(Q),{success:!1,error:`Unknown subcommand: ${Z}`}}}});async function fK($,Y){let Z=A1(Y);try{let X=V1(),Q=m2();if(!X||!Q)return{success:!1,error:"配置未初始化"};let J=n().session,q=J.messages,K=J.sessionId;if(!q||q.length===0)return Z.sendMessage("⚠️ 当前会话没有消息,无需压缩"),{success:!1,error:"没有消息需要压缩"};let G=q.map((z)=>({role:z.role,content:z.content})),W=l0.countTokens(G,Q.model),U=Q.maxContextTokens??X.maxContextTokens,H=(W/U*100).toFixed(1);if(Z.sendMessage(`\uD83D\uDCCA **当前上下文统计**
1074
- • 消息数量: ${G.length}
1098
+ `+"使用 `/agents help` 查看可用命令";return X.sendMessage(Q),{success:!1,error:`Unknown subcommand: ${Z}`}}}});async function oG($,Y){let Z=A1(Y);try{let X=V1(),Q=u2();if(!X||!Q)return{success:!1,error:"配置未初始化"};let J=s().session,q=J.messages,G=J.sessionId;if(!q||q.length===0)return Z.sendMessage("⚠️ 当前会话没有消息,无需压缩"),{success:!1,error:"没有消息需要压缩"};let K=q.map((F)=>({role:F.role,content:F.content})),W=r0.countTokens(K,Q.model),U=Q.maxContextTokens??X.maxContextTokens,H=(W/U*100).toFixed(1);if(Z.sendMessage(`\uD83D\uDCCA **当前上下文统计**
1099
+ • 消息数量: ${K.length}
1075
1100
  • Token 数量: ${W.toLocaleString()}
1076
1101
  • Token 限制: ${U.toLocaleString()}
1077
1102
  • 使用率: ${H}%`),W<U*0.5)return Z.sendMessage(`\uD83D\uDCA1 提示: 当前 token 使用率较低(${H}%),可以暂时不压缩。
1078
- 系统会在达到 80% 时自动触发压缩。`),{success:!0,message:"无需压缩"};Z.sendMessage("⏳ **正在压缩上下文...**");let O=await l2.compact(G,{trigger:"manual",modelName:Q.model,maxContextTokens:U,apiKey:Q.apiKey,baseURL:Q.baseUrl});if(O.success){try{if(K)await new d$().saveCompaction(K,O.summary,{trigger:"manual",preTokens:O.preTokens,postTokens:O.postTokens,filesIncluded:O.filesIncluded},null),console.log("[/compact] 压缩数据已保存到 JSONL")}catch(_){console.warn("[/compact] 保存压缩数据失败:",_)}let z=`✅ **压缩完成!**
1103
+ 系统会在达到 80% 时自动触发压缩。`),{success:!0,message:"无需压缩"};Z.sendMessage("⏳ **正在压缩上下文...**");let O=await r2.compact(K,{trigger:"manual",modelName:Q.model,maxContextTokens:U,apiKey:Q.apiKey,baseURL:Q.baseUrl});if(O.success){try{if(G)await new r$().saveCompaction(G,O.summary,{trigger:"manual",preTokens:O.preTokens,postTokens:O.postTokens,filesIncluded:O.filesIncluded},null),console.log("[/compact] 压缩数据已保存到 JSONL")}catch(_){console.warn("[/compact] 保存压缩数据失败:",_)}let F=`✅ **压缩完成!**
1079
1104
 
1080
1105
  \uD83D\uDCC9 **Token 变化**
1081
1106
  • 压缩前: ${O.preTokens.toLocaleString()} tokens
1082
1107
  • 压缩后: ${O.postTokens.toLocaleString()} tokens
1083
- • 压缩率: ${((1-O.postTokens/O.preTokens)*100).toFixed(1)}%`;if(O.filesIncluded.length>0)z+=`
1108
+ • 压缩率: ${((1-O.postTokens/O.preTokens)*100).toFixed(1)}%`;if(O.filesIncluded.length>0)F+=`
1084
1109
 
1085
- \uD83D\uDCC1 **包含文件** (${O.filesIncluded.length})`,O.filesIncluded.forEach((_,F)=>{z+=`
1086
- ${F+1}. ${_}`});return z+=`
1110
+ \uD83D\uDCC1 **包含文件** (${O.filesIncluded.length})`,O.filesIncluded.forEach((_,z)=>{F+=`
1111
+ ${z+1}. ${_}`});return F+=`
1087
1112
 
1088
- \uD83D\uDCA1 对话历史已压缩,但完整记录仍保存在会话文件中。`,Z.sendMessage(z),{success:!0,message:"compact_completed",data:{compactedMessages:O.compactedMessages,boundaryMessage:O.boundaryMessage,summaryMessage:O.summaryMessage,preTokens:O.preTokens,postTokens:O.postTokens,filesIncluded:O.filesIncluded}}}else return Z.sendMessage(`⚠️ **压缩使用降级策略**
1113
+ \uD83D\uDCA1 对话历史已压缩,但完整记录仍保存在会话文件中。`,Z.sendMessage(F),{success:!0,message:"compact_completed",data:{compactedMessages:O.compactedMessages,boundaryMessage:O.boundaryMessage,summaryMessage:O.summaryMessage,preTokens:O.preTokens,postTokens:O.postTokens,filesIncluded:O.filesIncluded}}}else return Z.sendMessage(`⚠️ **压缩使用降级策略**
1089
1114
 
1090
1115
  \uD83D\uDCC9 **Token 变化**
1091
1116
  • 压缩前: ${O.preTokens.toLocaleString()} tokens
1092
1117
  • 压缩后: ${O.postTokens.toLocaleString()} tokens
1093
1118
 
1094
1119
  \uD83D\uDCA1 由于压缩过程出现错误,已使用简单截断策略。
1095
- 错误信息: ${O.error}`),{success:!1,message:"compact_fallback",error:O.error,data:{compactedMessages:O.compactedMessages,boundaryMessage:O.boundaryMessage,summaryMessage:O.summaryMessage,preTokens:O.preTokens,postTokens:O.postTokens}}}catch(X){let Q=X instanceof Error?X.message:String(X);return Z.sendMessage(`❌ **压缩失败**: ${Q}`),{success:!1,error:Q}}}var hK,nY;var oY=R(()=>{a4();_9();R6();F1();H2();hK={name:"compact",description:"手动压缩当前会话的上下文",fullDescription:"压缩当前对话历史,生成详细的技术总结,保留最近的消息。压缩后的上下文可以节省 token 使用量,同时保留关键信息。",usage:"/compact",examples:["/compact"],category:"context",handler:fK},nY=hK});function tY($){let Y=Math.floor((Date.now()-$.getTime())/1000);if(Y<60)return`${Y}s ago`;let Z=Math.floor(Y/60);if(Z<60)return`${Z}m ago`;let X=Math.floor(Z/60);if(X<24)return`${X}h ago`;return`${Math.floor(X/24)}d ago`}async function xK($){let Y=C1.getInstance(),Z=X0();if(Object.keys(Z).length===0){$.sendMessage(`\uD83D\uDD0C **MCP 服务器状态**
1120
+ 错误信息: ${O.error}`),{success:!1,message:"compact_fallback",error:O.error,data:{compactedMessages:O.compactedMessages,boundaryMessage:O.boundaryMessage,summaryMessage:O.summaryMessage,preTokens:O.preTokens,postTokens:O.postTokens}}}catch(X){let Q=X instanceof Error?X.message:String(X);return Z.sendMessage(`❌ **压缩失败**: ${Q}`),{success:!1,error:Q}}}var sG,qZ;var GZ=D(()=>{Y8();b9();k6();z1();F2();sG={name:"compact",description:"手动压缩当前会话的上下文",fullDescription:"压缩当前对话历史,生成详细的技术总结,保留最近的消息。压缩后的上下文可以节省 token 使用量,同时保留关键信息。",usage:"/compact",examples:["/compact"],category:"context",handler:oG},qZ=sG});function WZ($){let Y=Math.floor((Date.now()-$.getTime())/1000);if(Y<60)return`${Y}s ago`;let Z=Math.floor(Y/60);if(Z<60)return`${Z}m ago`;let X=Math.floor(Z/60);if(X<24)return`${X}h ago`;return`${Math.floor(X/24)}d ago`}async function tG($){let Y=f1.getInstance(),Z=Q0();if(Object.keys(Z).length===0){$.sendMessage(`\uD83D\uDD0C **MCP 服务器状态**
1096
1121
 
1097
1122
  ⚠️ 暂无配置的 MCP 服务器
1098
1123
 
1099
- \uD83D\uDCA1 使用 \`blade mcp add\` 命令添加 MCP 服务器`);return}$.sendMessage("\uD83D\uDD0D 正在检查 MCP 服务器状态...");let X=Object.entries(Z).map(async([Q,J])=>{try{let q=Y.getServerStatus(Q);if(!q)await Y.registerServer(Q,J),q=Y.getServerStatus(Q);else if(q.status==="disconnected")await Y.connectServer(Q);return{name:Q,config:J,serverInfo:Y.getServerStatus(Q)}}catch(q){return{name:Q,config:J,serverInfo:null,error:q}}});await Promise.all(X),pK($,Y.getAllServers())}function pK($,Y){let Z=`\uD83D\uDD0C **MCP 服务器状态**
1124
+ \uD83D\uDCA1 使用 \`blade mcp add\` 命令添加 MCP 服务器`);return}$.sendMessage("\uD83D\uDD0D 正在检查 MCP 服务器状态...");let X=Object.entries(Z).map(async([Q,J])=>{try{let q=Y.getServerStatus(Q);if(!q)await Y.registerServer(Q,J),q=Y.getServerStatus(Q);else if(q.status==="disconnected")await Y.connectServer(Q);return{name:Q,config:J,serverInfo:Y.getServerStatus(Q)}}catch(q){return{name:Q,config:J,serverInfo:null,error:q}}});await Promise.all(X),eG($,Y.getAllServers())}function eG($,Y){let Z=`\uD83D\uDD0C **MCP 服务器状态**
1100
1125
 
1101
- `,X=0,Q=0,J=0;for(let[q,K]of Y){let{config:G,status:W,connectedAt:U,lastError:H,tools:O}=K,z=W==="connected"?"✓":"✗",_=W==="connected"?"Connected":"Disconnected";if(W==="connected")X++,J+=O.length;else Q++;if(Z+=`\uD83D\uDCE6 **${q}**
1102
- `,Z+=` 状态: ${z} ${_}
1103
- `,Z+=` 类型: ${G.type}
1104
- `,G.type==="stdio")Z+=` 命令: ${G.command}${G.args?.length?" "+G.args.join(" "):""}
1105
- `;else Z+=` URL: ${G.url}
1126
+ `,X=0,Q=0,J=0;for(let[q,G]of Y){let{config:K,status:W,connectedAt:U,lastError:H,tools:O}=G,F=W==="connected"?"✓":"✗",_=W==="connected"?"Connected":"Disconnected";if(W==="connected")X++,J+=O.length;else Q++;if(Z+=`\uD83D\uDCE6 **${q}**
1127
+ `,Z+=` 状态: ${F} ${_}
1128
+ `,Z+=` 类型: ${K.type}
1129
+ `,K.type==="stdio")Z+=` 命令: ${K.command}${K.args?.length?" "+K.args.join(" "):""}
1130
+ `;else Z+=` URL: ${K.url}
1106
1131
  `;if(Z+=` 工具: ${O.length} 个
1107
- `,U&&W==="connected")Z+=` 连接时间: ${tY(U)}
1132
+ `,U&&W==="connected")Z+=` 连接时间: ${WZ(U)}
1108
1133
  `;if(H&&W!=="connected")Z+=` 错误: ${H.message}
1109
1134
  `;Z+=`
1110
1135
  `}Z+=`**总计:**
1111
1136
  `,Z+=`- 服务器: ${Y.size} 个 (${X} 连接, ${Q} 断开)
1112
1137
  `,Z+=`- 可用工具: ${J} 个
1113
1138
 
1114
- `,Z+="\uD83D\uDCA1 使用 `/mcp <server-name>` 查看详细信息\n",Z+="\uD83D\uDCA1 使用 `/mcp tools` 查看所有工具",$.sendMessage(Z)}async function gK($,Y){let Z=C1.getInstance(),Q=X0()[Y];if(!Q){$.sendMessage(`❌ 服务器 "${Y}" 不存在
1139
+ `,Z+="\uD83D\uDCA1 使用 `/mcp <server-name>` 查看详细信息\n",Z+="\uD83D\uDCA1 使用 `/mcp tools` 查看所有工具",$.sendMessage(Z)}async function $K($,Y){let Z=f1.getInstance(),Q=Q0()[Y];if(!Q){$.sendMessage(`❌ 服务器 "${Y}" 不存在
1115
1140
 
1116
- \uD83D\uDCA1 使用 \`/mcp\` 查看所有可用服务器`);return}try{let J=Z.getServerStatus(Y);if(!J)$.sendMessage(`\uD83D\uDD0D 正在连接 ${Y}...`),await Z.registerServer(Y,Q),J=Z.getServerStatus(Y);else if(J.status==="disconnected")$.sendMessage(`\uD83D\uDD0D 正在重新连接 ${Y}...`),await Z.connectServer(Y),J=Z.getServerStatus(Y);if(J)mK($,Y,J);else sY($,Y,Q)}catch(J){sY($,Y,Q),$.sendMessage(`
1117
- ⚠️ 连接失败: ${J instanceof Error?J.message:"未知错误"}`)}}function mK($,Y,Z){let{config:X,status:Q,connectedAt:J,lastError:q,tools:K}=Z,G=Q==="connected"?"✓":"✗",W=Q==="connected"?"Connected":"Disconnected",U=`\uD83D\uDCE6 **${Y}**
1141
+ \uD83D\uDCA1 使用 \`/mcp\` 查看所有可用服务器`);return}try{let J=Z.getServerStatus(Y);if(!J)$.sendMessage(`\uD83D\uDD0D 正在连接 ${Y}...`),await Z.registerServer(Y,Q),J=Z.getServerStatus(Y);else if(J.status==="disconnected")$.sendMessage(`\uD83D\uDD0D 正在重新连接 ${Y}...`),await Z.connectServer(Y),J=Z.getServerStatus(Y);if(J)YK($,Y,J);else KZ($,Y,Q)}catch(J){KZ($,Y,Q),$.sendMessage(`
1142
+ ⚠️ 连接失败: ${J instanceof Error?J.message:"未知错误"}`)}}function YK($,Y,Z){let{config:X,status:Q,connectedAt:J,lastError:q,tools:G}=Z,K=Q==="connected"?"✓":"✗",W=Q==="connected"?"Connected":"Disconnected",U=`\uD83D\uDCE6 **${Y}**
1118
1143
 
1119
1144
  `;if(U+=`**连接状态:**
1120
- `,U+=` ${G} ${W}`,J&&Q==="connected")U+=` (连接于 ${tY(J)})`;if(U+=`
1145
+ `,U+=` ${K} ${W}`,J&&Q==="connected")U+=` (连接于 ${WZ(J)})`;if(U+=`
1121
1146
 
1122
1147
  `,U+=`**配置信息:**
1123
1148
  `,U+=` 类型: ${X.type}
@@ -1128,14 +1153,14 @@ Please continue the conversation from where we left it off without asking the us
1128
1153
  `,X.headers&&Object.keys(X.headers).length>0)U+=` Headers: ${Object.keys(X.headers).length} 个
1129
1154
  `;if(X.timeout)U+=` 超时: ${X.timeout}ms
1130
1155
  `;if(U+=`
1131
- `,Q==="connected")if(U+=`**可用工具 (${K.length}):**
1132
- `,K.length===0)U+=` (无)
1133
- `;else for(let H of K){if(U+=` • ${H.name}`,H.description)U+=` - ${H.description}`;U+=`
1156
+ `,Q==="connected")if(U+=`**可用工具 (${G.length}):**
1157
+ `,G.length===0)U+=` (无)
1158
+ `;else for(let H of G){if(U+=` • ${H.name}`,H.description)U+=` - ${H.description}`;U+=`
1134
1159
  `}else U+=`**工具:**
1135
1160
  ⚠️ 服务器未连接,无法获取工具列表
1136
1161
  `;if(q)U+=`
1137
1162
  **错误信息:**
1138
- `,U+=` ${q.message}`;$.sendMessage(U)}function sY($,Y,Z){let X=`\uD83D\uDCE6 **${Y}**
1163
+ `,U+=` ${q.message}`;$.sendMessage(U)}function KZ($,Y,Z){let X=`\uD83D\uDCE6 **${Y}**
1139
1164
 
1140
1165
  `;if(X+=`**连接状态:**
1141
1166
  `,X+=` ⏸️ 未启动 (等待 Agent 连接)
@@ -1149,22 +1174,22 @@ Please continue the conversation from where we left it off without asking the us
1149
1174
  `,Z.headers&&Object.keys(Z.headers).length>0)X+=` Headers: ${Object.keys(Z.headers).join(", ")}
1150
1175
  `;if(Z.timeout)X+=` 超时: ${Z.timeout}ms
1151
1176
  `;X+=`
1152
- \uD83D\uDCA1 服务器将在 Agent 启动时自动连接`,$.sendMessage(X)}async function dK($){let Y=C1.getInstance(),Z=X0();if(Object.keys(Z).length===0){$.sendMessage(`\uD83D\uDD27 **可用的 MCP 工具**
1177
+ \uD83D\uDCA1 服务器将在 Agent 启动时自动连接`,$.sendMessage(X)}async function ZK($){let Y=f1.getInstance(),Z=Q0();if(Object.keys(Z).length===0){$.sendMessage(`\uD83D\uDD27 **可用的 MCP 工具**
1153
1178
 
1154
1179
  ⚠️ 暂无配置的 MCP 服务器
1155
1180
 
1156
- \uD83D\uDCA1 使用 \`blade mcp add\` 命令添加 MCP 服务器`);return}$.sendMessage("\uD83D\uDD0D 正在检查 MCP 服务器并获取工具列表...");let X=Object.entries(Z).map(async([K,G])=>{try{let W=Y.getServerStatus(K);if(!W)await Y.registerServer(K,G),W=Y.getServerStatus(K);else if(W.status==="disconnected")await Y.connectServer(K);return{name:K,config:G,serverInfo:Y.getServerStatus(K)}}catch(W){return{name:K,config:G,serverInfo:null,error:W}}});await Promise.all(X);let Q=Y.getAllServers(),J=`\uD83D\uDD27 **可用的 MCP 工具**
1181
+ \uD83D\uDCA1 使用 \`blade mcp add\` 命令添加 MCP 服务器`);return}$.sendMessage("\uD83D\uDD0D 正在检查 MCP 服务器并获取工具列表...");let X=Object.entries(Z).map(async([G,K])=>{try{let W=Y.getServerStatus(G);if(!W)await Y.registerServer(G,K),W=Y.getServerStatus(G);else if(W.status==="disconnected")await Y.connectServer(G);return{name:G,config:K,serverInfo:Y.getServerStatus(G)}}catch(W){return{name:G,config:K,serverInfo:null,error:W}}});await Promise.all(X);let Q=Y.getAllServers(),J=`\uD83D\uDD27 **可用的 MCP 工具**
1157
1182
 
1158
- `,q=0;for(let[K,G]of Q){let{status:W,tools:U}=G;if(J+=`**${K} (${U.length} 个工具):**
1183
+ `,q=0;for(let[G,K]of Q){let{status:W,tools:U}=K;if(J+=`**${G} (${U.length} 个工具):**
1159
1184
  `,W!=="connected"){J+=` ⚠️ 服务器未连接
1160
1185
 
1161
1186
  `;continue}if(U.length===0){J+=` (无)
1162
1187
 
1163
1188
  `;continue}q+=U.length;for(let H of U){if(J+=` • ${H.name}`,H.description){let O=H.description.length>60?H.description.substring(0,57)+"...":H.description;J+=` - ${O}`}J+=`
1164
1189
  `}J+=`
1165
- `}J+=`**总计:** ${q} 个工具可用`,$.sendMessage(J)}var uK,eY;var $Z=R(()=>{u2();d2();F1();H2();uK={name:"mcp",description:"Display MCP server status and available tools",fullDescription:"显示 MCP 服务器状态、连接信息和可用工具列表",usage:"/mcp [server-name | tools]",category:"MCP",examples:["/mcp - 显示所有服务器概览","/mcp chrome-devtools - 显示特定服务器详情","/mcp tools - 显示所有可用工具"],async handler($,Y){let Z=A1(Y);try{if(console.log("[MCP Command] Received args:",$),$.length===0)return await xK(Z),{success:!0,message:"MCP 服务器概览已显示"};let X=$[0];if(console.log("[MCP Command] Subcommand:",X),X==="tools")return await dK(Z),{success:!0,message:"MCP 工具列表已显示"};return await gK(Z,X),{success:!0,message:`服务器 "${X}" 详情已显示`}}catch(X){return{success:!1,error:`显示 MCP 信息失败: ${X instanceof Error?X.message:"未知错误"}`}}}},eY=uK});async function cK($,Y){return{success:!0,message:"show_permissions_editor",data:{action:"show_permissions_editor"}}}var lK,n6;var A9=R(()=>{lK={name:"permissions",description:"管理项目的本地权限规则",fullDescription:"打开权限管理器,管理 .blade/settings.local.json 中的权限规则",usage:"/permissions",aliases:["perm"],category:"ui",handler:cK},n6=lK});var iK,YZ;var ZZ=R(()=>{c6();F1();H2();iK={name:"resume",description:"Resume a conversation",fullDescription:"恢复历史会话。可以指定 sessionId 直接恢复,或不带参数打开会话选择器",usage:"/resume [sessionId]",aliases:["r"],category:"Session",examples:["/resume - 打开会话选择器","/resume abc123xyz - 直接恢复指定的会话"],async handler($,Y){let Z=A1(Y),X=P$().restoreSession;if($.length>0){let Q=$[0];try{let J=await S0.loadSession(Q);if(J.length===0)return Z.sendMessage(`❌ 会话 \`${Q}\` 为空或无法加载`),{success:!1,error:"会话为空"};let q=J.filter((K)=>K.role!=="tool").map((K,G)=>({id:`restored-${Date.now()}-${G}`,role:K.role,content:typeof K.content==="string"?K.content:JSON.stringify(K.content),timestamp:Date.now()-(J.length-G)*1000}));return X(Q,q),Z.sendMessage(`✅ 已恢复会话 \`${Q}\`
1190
+ `}J+=`**总计:** ${q} 个工具可用`,$.sendMessage(J)}var XK,UZ;var HZ=D(()=>{l2();c2();z1();F2();XK={name:"mcp",description:"Display MCP server status and available tools",fullDescription:"显示 MCP 服务器状态、连接信息和可用工具列表",usage:"/mcp [server-name | tools]",category:"MCP",examples:["/mcp - 显示所有服务器概览","/mcp chrome-devtools - 显示特定服务器详情","/mcp tools - 显示所有可用工具"],async handler($,Y){let Z=A1(Y);try{if(console.log("[MCP Command] Received args:",$),$.length===0)return await tG(Z),{success:!0,message:"MCP 服务器概览已显示"};let X=$[0];if(console.log("[MCP Command] Subcommand:",X),X==="tools")return await ZK(Z),{success:!0,message:"MCP 工具列表已显示"};return await $K(Z,X),{success:!0,message:`服务器 "${X}" 详情已显示`}}catch(X){return{success:!1,error:`显示 MCP 信息失败: ${X instanceof Error?X.message:"未知错误"}`}}}},UZ=XK});async function QK($,Y){return{success:!0,message:"show_permissions_editor",data:{action:"show_permissions_editor"}}}var JK,Y4;var M9=D(()=>{JK={name:"permissions",description:"管理项目的本地权限规则",fullDescription:"打开权限管理器,管理 .blade/settings.local.json 中的权限规则",usage:"/permissions",aliases:["perm"],category:"ui",handler:QK},Y4=JK});var qK,OZ;var FZ=D(()=>{o6();z1();F2();qK={name:"resume",description:"Resume a conversation",fullDescription:"恢复历史会话。可以指定 sessionId 直接恢复,或不带参数打开会话选择器",usage:"/resume [sessionId]",aliases:["r"],category:"Session",examples:["/resume - 打开会话选择器","/resume abc123xyz - 直接恢复指定的会话"],async handler($,Y){let Z=A1(Y),X=f$().restoreSession;if($.length>0){let Q=$[0];try{let J=await C0.loadSession(Q);if(J.length===0)return Z.sendMessage(`❌ 会话 \`${Q}\` 为空或无法加载`),{success:!1,error:"会话为空"};let q=J.filter((G)=>G.role!=="tool").map((G,K)=>({id:`restored-${Date.now()}-${K}`,role:G.role,content:typeof G.content==="string"?G.content:JSON.stringify(G.content),timestamp:Date.now()-(J.length-K)*1000}));return X(Q,q),Z.sendMessage(`✅ 已恢复会话 \`${Q}\`
1166
1191
 
1167
- 共 ${q.length} 条消息已加载,可以继续对话`),{success:!0,message:"session_restored",data:{sessionId:Q,messageCount:q.length}}}catch(J){let q=J instanceof Error?J.message:"未知错误";return Z.sendMessage(`❌ 加载会话失败: ${q}`),{success:!1,error:`加载会话失败: ${q}`}}}try{let Q=await S0.listSessions();if(Q.length===0)return Z.sendMessage("\uD83D\uDCED **没有找到历史会话**\n\n开始一次对话后,会话历史将自动保存到 `~/.blade/projects/`"),{success:!0,message:"没有可用会话"};return{success:!0,message:"show_session_selector",data:{sessions:Q}}}catch(Q){let J=Q instanceof Error?Q.message:"未知错误";return Z.sendMessage(`❌ 获取会话列表失败: ${J}`),{success:!1,error:`获取会话列表失败: ${J}`}}}},YZ=iK});var rK,aK,nK,oK,sK,tK,XZ;var QZ=R(()=>{R6();F1();k$();aY();oY();$Z();A9();ZZ();H2();rK={name:"help",description:"Show all available slash commands",fullDescription:"显示所有可用的 slash commands 及其使用方法",usage:"/help",aliases:["h"],async handler($,Y){let Z=A1(Y),X=`\uD83D\uDD27 **可用的 Slash Commands:**
1192
+ 共 ${q.length} 条消息已加载,可以继续对话`),{success:!0,message:"session_restored",data:{sessionId:Q,messageCount:q.length}}}catch(J){let q=J instanceof Error?J.message:"未知错误";return Z.sendMessage(`❌ 加载会话失败: ${q}`),{success:!1,error:`加载会话失败: ${q}`}}}try{let Q=await C0.listSessions();if(Q.length===0)return Z.sendMessage("\uD83D\uDCED **没有找到历史会话**\n\n开始一次对话后,会话历史将自动保存到 `~/.blade/projects/`"),{success:!0,message:"没有可用会话"};return{success:!0,message:"show_session_selector",data:{sessions:Q}}}catch(Q){let J=Q instanceof Error?Q.message:"未知错误";return Z.sendMessage(`❌ 获取会话列表失败: ${J}`),{success:!1,error:`获取会话列表失败: ${J}`}}}},OZ=qK});var GK,KK,WK,UK,HK,OK,zZ;var _Z=D(()=>{k6();z1();y$();JZ();GZ();HZ();M9();FZ();F2();GK={name:"help",description:"Show all available slash commands",fullDescription:"显示所有可用的 slash commands 及其使用方法",usage:"/help",aliases:["h"],async handler($,Y){let Z=A1(Y),X=`\uD83D\uDD27 **可用的 Slash Commands:**
1168
1193
 
1169
1194
  **/init** - 分析当前项目并生成 BLADE.md 配置文件
1170
1195
  **/git** - Git 仓库查询和 AI 辅助 (status/log/diff/review/commit)
@@ -1200,7 +1225,7 @@ Please continue the conversation from where we left it off without asking the us
1200
1225
  - 在命令前加上 \`/\` 即可执行 slash command
1201
1226
  - 普通消息会发送给 AI 助手处理
1202
1227
  - 按 Ctrl+C 退出程序
1203
- - 按 Ctrl+L 快速清屏`),{success:!0,message:"帮助信息已显示"}}},aK={name:"clear",description:"Clear conversation history and free up context",fullDescription:"清除屏幕内容和对话历史",usage:"/clear",aliases:["cls"],async handler($,Y){return{success:!0,message:"clear_screen"}}},nK={name:"version",description:"Show Blade Code version information",fullDescription:"显示 Blade Code 版本信息和构建详情",usage:"/version",aliases:["v"],async handler($,Y){let Z=A1(Y),Q=`\uD83D\uDDE1️ **Blade Code v${f2()}**
1228
+ - 按 Ctrl+L 快速清屏`),{success:!0,message:"帮助信息已显示"}}},KK={name:"clear",description:"Clear conversation history and free up context",fullDescription:"清除屏幕内容和对话历史",usage:"/clear",aliases:["cls"],async handler($,Y){return{success:!0,message:"clear_screen"}}},WK={name:"version",description:"Show Blade Code version information",fullDescription:"显示 Blade Code 版本信息和构建详情",usage:"/version",aliases:["v"],async handler($,Y){let Z=A1(Y),Q=`\uD83D\uDDE1️ **Blade Code v${x2()}**
1204
1229
 
1205
1230
  **构建信息:**
1206
1231
  - Node.js: ${process.version}
@@ -1211,7 +1236,7 @@ Please continue the conversation from where we left it off without asking the us
1211
1236
  - \uD83E\uDD16 智能 AI 对话
1212
1237
  - \uD83D\uDD27 项目自动分析
1213
1238
  - \uD83D\uDCDD 自定义系统提示
1214
- - \uD83C\uDFAF 多工具集成支持`;return Z.sendMessage(Q),{success:!0,message:"版本信息已显示"}}},oK={name:"status",description:"Show current configuration status",fullDescription:"显示当前项目配置状态和环境信息",usage:"/status",async handler($,Y){let Z=A1(Y),{cwd:X}=Y,Q=S1("path"),J=S1("fs").promises;try{let q=Q.join(X,"BLADE.md"),K=await J.access(q).then(()=>!0).catch(()=>!1),G=Q.join(X,"package.json"),W="未知项目",U="未知类型";try{let O=await J.readFile(G,"utf-8"),z=JSON.parse(O);W=z.name||"未知项目";let _={...z.dependencies,...z.devDependencies};if(_.react)U="React 项目";else if(_.vue)U="Vue 项目";else if(_.next)U="Next.js 项目";else if(_.express)U="Express 项目";else U="Node.js 项目"}catch{}let H=`\uD83D\uDCCA **当前状态**
1239
+ - \uD83C\uDFAF 多工具集成支持`;return Z.sendMessage(Q),{success:!0,message:"版本信息已显示"}}},UK={name:"status",description:"Show current configuration status",fullDescription:"显示当前项目配置状态和环境信息",usage:"/status",async handler($,Y){let Z=A1(Y),{cwd:X}=Y,Q=C1("path"),J=C1("fs").promises;try{let q=Q.join(X,"BLADE.md"),G=await J.access(q).then(()=>!0).catch(()=>!1),K=Q.join(X,"package.json"),W="未知项目",U="未知类型";try{let O=await J.readFile(K,"utf-8"),F=JSON.parse(O);W=F.name||"未知项目";let _={...F.dependencies,...F.devDependencies};if(_.react)U="React 项目";else if(_.vue)U="Vue 项目";else if(_.next)U="Next.js 项目";else if(_.express)U="Express 项目";else U="Node.js 项目"}catch{}let H=`\uD83D\uDCCA **当前状态**
1215
1240
 
1216
1241
  **项目信息:**
1217
1242
  - 名称: ${W}
@@ -1219,13 +1244,13 @@ Please continue the conversation from where we left it off without asking the us
1219
1244
  - 路径: ${X}
1220
1245
 
1221
1246
  **配置状态:**
1222
- - BLADE.md: ${K?"✅ 已配置":"❌ 未配置 (使用 /init 创建)"}
1247
+ - BLADE.md: ${G?"✅ 已配置":"❌ 未配置 (使用 /init 创建)"}
1223
1248
 
1224
1249
  **环境信息:**
1225
1250
  - 工作目录: ${process.cwd()}
1226
1251
  - Node.js: ${process.version}
1227
1252
 
1228
- ${!K?"\n\uD83D\uDCA1 **建议:** 运行 `/init` 命令来创建项目配置文件":""}`;return Z.sendMessage(H),{success:!0,message:"状态信息已显示"}}catch(q){return{success:!1,error:`获取状态信息失败: ${q instanceof Error?q.message:"未知错误"}`}}}},sK={name:"exit",description:"Exit the REPL",fullDescription:"退出 Blade Code 命令行界面",usage:"/exit",aliases:["quit","q"],async handler($,Y){return{success:!0,message:"exit_application"}}},tK={name:"context",description:"Visualize current context usage as a colored grid",fullDescription:"可视化显示当前上下文使用情况",usage:"/context",async handler($,Y){let Z=A1(Y),X=V1(),Q=m2(),q=n().session.messages||[],K=q.map((N)=>({role:N.role,content:N.content})),G=Q?.model||"gpt-4",W=K.length>0?l0.countTokens(K,G):0,U=Q?.maxContextTokens??X?.maxContextTokens??128000,H=U>0?(W/U*100).toFixed(1):"0",O=(100-parseFloat(H)).toFixed(1),z=parseFloat(H),_;if(z<50)_="\uD83D\uDFE2 正常";else if(z<80)_="\uD83D\uDFE1 中等";else _="\uD83D\uDD34 高负载";let F=`\uD83D\uDCCA **上下文使用情况**
1253
+ ${!G?"\n\uD83D\uDCA1 **建议:** 运行 `/init` 命令来创建项目配置文件":""}`;return Z.sendMessage(H),{success:!0,message:"状态信息已显示"}}catch(q){return{success:!1,error:`获取状态信息失败: ${q instanceof Error?q.message:"未知错误"}`}}}},HK={name:"exit",description:"Exit the REPL",fullDescription:"退出 Blade Code 命令行界面",usage:"/exit",aliases:["quit","q"],async handler($,Y){return{success:!0,message:"exit_application"}}},OK={name:"context",description:"Visualize current context usage as a colored grid",fullDescription:"可视化显示当前上下文使用情况",usage:"/context",async handler($,Y){let Z=A1(Y),X=V1(),Q=u2(),q=s().session.messages||[],G=q.map((w)=>({role:w.role,content:w.content})),K=Q?.model||"gpt-4",W=G.length>0?r0.countTokens(G,K):0,U=Q?.maxContextTokens??X?.maxContextTokens??128000,H=U>0?(W/U*100).toFixed(1):"0",O=(100-parseFloat(H)).toFixed(1),F=parseFloat(H),_;if(F<50)_="\uD83D\uDFE2 正常";else if(F<80)_="\uD83D\uDFE1 中等";else _="\uD83D\uDD34 高负载";let z=`\uD83D\uDCCA **上下文使用情况**
1229
1254
 
1230
1255
  **当前会话:**
1231
1256
  - 消息数量: ${q.length}
@@ -1239,8 +1264,8 @@ ${!K?"\n\uD83D\uDCA1 **建议:** 运行 `/init` 命令来创建项目配置文
1239
1264
 
1240
1265
  **状态:** ${_}
1241
1266
 
1242
- \uD83D\uDCA1 使用 \`/compact\` 可手动压缩上下文`;return Z.sendMessage(F),{success:!0,message:"上下文信息已显示"}}},XZ={help:rK,clear:aK,version:nK,status:oK,exit:sK,context:tK,permissions:n6,resume:YZ,compact:nY,mcp:eY,agents:rY}});import{execFile as JZ,spawn as eK}from"child_process";import{promisify as $G}from"util";async function u$($,Y){return new Promise((Z)=>{JZ("git",Y,{cwd:$,maxBuffer:10485760},(X,Q,J)=>{Z({code:X?X.code||1:0,stdout:Q||"",stderr:J||""})})})}async function YG($,Y){let{code:Z}=await u$($,Y);return Z===0}async function C0($,Y){let{stdout:Z}=await u$($,Y);return Z.trim()}async function c$($){return YG($,["rev-parse","--is-inside-work-tree"])}async function o6($){return(await C0($,["status","--porcelain"])).length>0}async function qZ($){return C0($,["branch","--show-current"])}async function s6($,Y=10){return C0($,["log","-n",String(Y),"--pretty=format:%s"])}async function R9($){let{code:Y,stderr:Z}=await u$($,["add","."]);if(Y!==0){let X=Z||"Unknown error";if(X.includes("fatal: pathspec"))throw Error("Failed to stage files: Invalid file path or pattern");throw Error(`Failed to stage files: ${X}`)}}async function KZ($,Y,Z=!1,X){let Q=["commit","-m",Y];if(Z)Q.push("--no-verify");if(!X){let{code:J,stderr:q}=await u$($,Q);if(J!==0)throw Error(q||"Commit failed");return}return new Promise((J,q)=>{let K=eK("git",Q,{cwd:$}),G="",W=(O,z,_)=>{let N=(_+O.toString()).split(`
1243
- `),w=N.pop()||"";for(let B of N)if(B.trim())X(B,z);return w},U="",H="";K.stdout?.on("data",(O)=>{U=W(O,"stdout",U)}),K.stderr?.on("data",(O)=>{G+=O.toString(),H=W(O,"stderr",H)}),K.on("error",(O)=>{q(O)}),K.on("close",(O)=>{if(U.trim())X(U,"stdout");if(H.trim())X(H,"stderr");if(O===0)J();else q(Error(G||"Commit failed"))})})}async function GZ($){let{cwd:Y}=$;if(!await c$(Y))return null;let[Z,X,Q,J,q]=await Promise.all([C0(Y,["branch","--show-current"]),C0(Y,["rev-parse","--abbrev-ref","origin/HEAD"]).then((G)=>G.replace("origin/","")).catch(()=>"main"),C0(Y,["status","--short"]),C0(Y,["log","--oneline","-n","5"]),C0(Y,["config","user.email"])]),K=q?await C0(Y,["log","--author",q,"--oneline","-n","5"]):"";return{branch:Z,mainBranch:X,status:Q,log:J,author:q,authorLog:K}}function WZ($){if(!$)return null;return`
1267
+ \uD83D\uDCA1 使用 \`/compact\` 可手动压缩上下文`;return Z.sendMessage(z),{success:!0,message:"上下文信息已显示"}}},zZ={help:GK,clear:KK,version:WK,status:UK,exit:HK,context:OK,permissions:Y4,resume:OZ,compact:qZ,mcp:UZ,agents:QZ}});import{execFile as NZ,spawn as FK}from"child_process";import{promisify as zK}from"util";async function a$($,Y){return new Promise((Z)=>{NZ("git",Y,{cwd:$,maxBuffer:10485760},(X,Q,J)=>{Z({code:X?X.code||1:0,stdout:Q||"",stderr:J||""})})})}async function _K($,Y){let{code:Z}=await a$($,Y);return Z===0}async function h0($,Y){let{stdout:Z}=await a$($,Y);return Z.trim()}async function n$($){return _K($,["rev-parse","--is-inside-work-tree"])}async function Z4($){return(await h0($,["status","--porcelain"])).length>0}async function BZ($){return h0($,["branch","--show-current"])}async function X4($,Y=10){return h0($,["log","-n",String(Y),"--pretty=format:%s"])}async function k9($){let{code:Y,stderr:Z}=await a$($,["add","."]);if(Y!==0){let X=Z||"Unknown error";if(X.includes("fatal: pathspec"))throw Error("Failed to stage files: Invalid file path or pattern");throw Error(`Failed to stage files: ${X}`)}}async function wZ($,Y,Z=!1,X){let Q=["commit","-m",Y];if(Z)Q.push("--no-verify");if(!X){let{code:J,stderr:q}=await a$($,Q);if(J!==0)throw Error(q||"Commit failed");return}return new Promise((J,q)=>{let G=FK("git",Q,{cwd:$}),K="",W=(O,F,_)=>{let w=(_+O.toString()).split(`
1268
+ `),B=w.pop()||"";for(let N of w)if(N.trim())X(N,F);return B},U="",H="";G.stdout?.on("data",(O)=>{U=W(O,"stdout",U)}),G.stderr?.on("data",(O)=>{K+=O.toString(),H=W(O,"stderr",H)}),G.on("error",(O)=>{q(O)}),G.on("close",(O)=>{if(U.trim())X(U,"stdout");if(H.trim())X(H,"stderr");if(O===0)J();else q(Error(K||"Commit failed"))})})}async function LZ($){let{cwd:Y}=$;if(!await n$(Y))return null;let[Z,X,Q,J,q]=await Promise.all([h0(Y,["branch","--show-current"]),h0(Y,["rev-parse","--abbrev-ref","origin/HEAD"]).then((K)=>K.replace("origin/","")).catch(()=>"main"),h0(Y,["status","--short"]),h0(Y,["log","--oneline","-n","5"]),h0(Y,["config","user.email"])]),G=q?await h0(Y,["log","--author",q,"--oneline","-n","5"]):"";return{branch:Z,mainBranch:X,status:Q,log:J,author:q,authorLog:G}}function AZ($){if(!$)return null;return`
1244
1269
  Git repository status (snapshot at conversation start):
1245
1270
  Current branch: ${$.branch}
1246
1271
  Main branch (target for PRs): ${$.mainBranch}
@@ -1253,14 +1278,14 @@ ${$.log||"(no commits)"}
1253
1278
 
1254
1279
  Your recent commits:
1255
1280
  ${$.authorLog||"(no recent commits)"}
1256
- `.trim()}async function l$($){return C0($,["diff","--cached","--name-status"])}async function i$($){let Z=["diff","--cached","--",...[":!pnpm-lock.yaml",":!package-lock.json",":!yarn.lock",":!*.min.js",":!*.bundle.js",":!dist/**",":!build/**",":!*.gz",":!*.zip",":!*.tar",":!*.tgz",":!*.woff",":!*.woff2",":!*.ttf",":!*.png",":!*.jpg",":!*.jpeg",":!*.gif",":!*.ico",":!*.svg",":!*.pdf"]],{code:X,stdout:Q,stderr:J}=await u$($,Z);if(X!==0){let K=J||"Unknown error";if(K.includes("bad revision"))throw Error("Failed to get staged diff: Invalid Git revision or corrupt repository");if(K.includes("fatal: not a git repository"))throw Error("Not a Git repository");throw Error(`Failed to get staged diff: ${K}`)}let q=102400;if(Q.length>q)return Q.substring(0,q)+`
1281
+ `.trim()}async function o$($){return h0($,["diff","--cached","--name-status"])}async function s$($){let Z=["diff","--cached","--",...[":!pnpm-lock.yaml",":!package-lock.json",":!yarn.lock",":!*.min.js",":!*.bundle.js",":!dist/**",":!build/**",":!*.gz",":!*.zip",":!*.tar",":!*.tgz",":!*.woff",":!*.woff2",":!*.ttf",":!*.png",":!*.jpg",":!*.jpeg",":!*.gif",":!*.ico",":!*.svg",":!*.pdf"]],{code:X,stdout:Q,stderr:J}=await a$($,Z);if(X!==0){let G=J||"Unknown error";if(G.includes("bad revision"))throw Error("Failed to get staged diff: Invalid Git revision or corrupt repository");if(G.includes("fatal: not a git repository"))throw Error("Not a Git repository");throw Error(`Failed to get staged diff: ${G}`)}let q=102400;if(Q.length>q)return Q.substring(0,q)+`
1257
1282
 
1258
- [Diff truncated due to size. Total diff size: `+(Q.length/1024).toFixed(2)+"KB]";return Q}var jR;var b9=R(()=>{jR=$G(JZ)});async function UZ($){let Y=A1($),Z=await GZ({cwd:$.cwd});if(!Z)return{success:!1,error:"无法获取 Git 状态"};let X=WZ(Z);if(X)Y.sendMessage(`\`\`\`
1283
+ [Diff truncated due to size. Total diff size: `+(Q.length/1024).toFixed(2)+"KB]";return Q}var xb;var j9=D(()=>{xb=zK(NZ)});async function bZ($){let Y=A1($),Z=await LZ({cwd:$.cwd});if(!Z)return{success:!1,error:"无法获取 Git 状态"};let X=AZ(Z);if(X)Y.sendMessage(`\`\`\`
1259
1284
  ${X}
1260
- \`\`\``);else Y.sendMessage("\uD83D\uDCED 无法获取 Git 状态信息");return{success:!0}}async function XG($,Y){let Z=A1($),X=Math.min(Math.max(parseInt(Y||"5",10)||5,1),50),Q=await s6($.cwd,X);if(!Q)Z.sendMessage("\uD83D\uDCED 暂无提交记录");else Z.sendMessage(`**最近 ${X} 条提交:**
1285
+ \`\`\``);else Y.sendMessage("\uD83D\uDCED 无法获取 Git 状态信息");return{success:!0}}async function BK($,Y){let Z=A1($),X=Math.min(Math.max(parseInt(Y||"5",10)||5,1),50),Q=await X4($.cwd,X);if(!Q)Z.sendMessage("\uD83D\uDCED 暂无提交记录");else Z.sendMessage(`**最近 ${X} 条提交:**
1261
1286
  \`\`\`
1262
1287
  ${Q}
1263
- \`\`\``);return{success:!0}}async function QG($){let Y=A1($),{cwd:Z}=$,X=await l$(Z);if(!X)return Y.sendMessage("\uD83D\uDCED 暂存区为空,没有待提交的改动"),{success:!0};let Q=await i$(Z),J=`**暂存文件:**
1288
+ \`\`\``);return{success:!0}}async function wK($){let Y=A1($),{cwd:Z}=$,X=await o$(Z);if(!X)return Y.sendMessage("\uD83D\uDCED 暂存区为空,没有待提交的改动"),{success:!0};let Q=await s$(Z),J=`**暂存文件:**
1264
1289
  \`\`\`
1265
1290
  ${X}
1266
1291
  \`\`\`
@@ -1268,7 +1293,7 @@ ${X}
1268
1293
  **Diff:**
1269
1294
  \`\`\`diff
1270
1295
  ${Q||"(无差异)"}
1271
- \`\`\``;return Y.sendMessage(J),{success:!0}}async function JG($){let Y=A1($),{cwd:Z,signal:X}=$;if(!await o6(Z))return Y.sendMessage("\uD83D\uDCED 没有未提交的改动,无需 Review"),{success:!0};Y.sendMessage("\uD83D\uDD0D 正在分析代码改动...");let Q=await l$(Z),J=await i$(Z);if(!J&&!Q)return Y.sendMessage("\uD83D\uDCA1 请先使用 `git add` 暂存要 Review 的文件"),{success:!0};let q=await E1.create(),K=n().session.sessionId,G=`请对以下 Git 改动进行 Code Review。
1296
+ \`\`\``;return Y.sendMessage(J),{success:!0}}async function LK($){let Y=A1($),{cwd:Z,signal:X}=$;if(!await Z4(Z))return Y.sendMessage("\uD83D\uDCED 没有未提交的改动,无需 Review"),{success:!0};Y.sendMessage("\uD83D\uDD0D 正在分析代码改动...");let Q=await o$(Z),J=await s$(Z);if(!J&&!Q)return Y.sendMessage("\uD83D\uDCA1 请先使用 `git add` 暂存要 Review 的文件"),{success:!0};let q=await v1.create(),G=s().session.sessionId,K=`请对以下 Git 改动进行 Code Review。
1272
1297
 
1273
1298
  **暂存文件:**
1274
1299
  ${Q||"(无)"}
@@ -1284,7 +1309,7 @@ ${J||"(无差异)"}
1284
1309
  3. **潜在问题**:指出可能的 bug、安全问题或性能问题
1285
1310
  4. **改进建议**:具体的代码改进建议
1286
1311
 
1287
- 如果改动很好,也请说明优点。保持简洁专业。`,W=await q.chat(G,{messages:[],userId:"cli-user",sessionId:K||"git-review",workspaceRoot:Z,signal:X});return Y.sendMessage(W),{success:!0}}async function qG($){let Y=A1($),{cwd:Z,signal:X}=$;if(!await o6(Z))return Y.sendMessage("\uD83D\uDCED 没有未提交的改动"),{success:!0};Y.sendMessage("\uD83D\uDCE6 暂存所有改动..."),await R9(Z);let Q=await l$(Z),J=await i$(Z);if(!Q)return Y.sendMessage("\uD83D\uDCED 没有需要提交的改动"),{success:!0};Y.sendMessage("\uD83E\uDD16 正在生成 commit message...");let q=await s6(Z,5),K=await E1.create(),G=n().session.sessionId,W=HZ(Q,J,q),H=(await K.chat(W,{messages:[],userId:"cli-user",sessionId:G||"git-pre-commit",workspaceRoot:Z,signal:X})).replace(/^```\w*\n?/,"").replace(/\n?```$/,"").trim();return Y.sendMessage(`**生成的 Commit Message:**
1312
+ 如果改动很好,也请说明优点。保持简洁专业。`,W=await q.chat(K,{messages:[],userId:"cli-user",sessionId:G||"git-review",workspaceRoot:Z,signal:X});return Y.sendMessage(W),{success:!0}}async function AK($){let Y=A1($),{cwd:Z,signal:X}=$;if(!await Z4(Z))return Y.sendMessage("\uD83D\uDCED 没有未提交的改动"),{success:!0};Y.sendMessage("\uD83D\uDCE6 暂存所有改动..."),await k9(Z);let Q=await o$(Z),J=await s$(Z);if(!Q)return Y.sendMessage("\uD83D\uDCED 没有需要提交的改动"),{success:!0};Y.sendMessage("\uD83E\uDD16 正在生成 commit message...");let q=await X4(Z,5),G=await v1.create(),K=s().session.sessionId,W=RZ(Q,J,q),H=(await G.chat(W,{messages:[],userId:"cli-user",sessionId:K||"git-pre-commit",workspaceRoot:Z,signal:X})).replace(/^```\w*\n?/,"").replace(/\n?```$/,"").trim();return Y.sendMessage(`**生成的 Commit Message:**
1288
1313
  \`\`\`
1289
1314
  ${H}
1290
1315
  \`\`\`
@@ -1293,10 +1318,10 @@ ${H}
1293
1318
  \`\`\`bash
1294
1319
  git commit -m "${H.split(`
1295
1320
  `)[0]}"
1296
- \`\`\``),{success:!0}}async function KG($){let Y=A1($),{cwd:Z,signal:X}=$;if(!await o6(Z))return Y.sendMessage("\uD83D\uDCED 没有未提交的改动"),{success:!0};Y.sendMessage("\uD83D\uDCE6 暂存所有改动..."),await R9(Z);let Q=await l$(Z),J=await i$(Z);if(!Q)return Y.sendMessage("\uD83D\uDCED 没有需要提交的改动"),{success:!0};Y.sendMessage("\uD83E\uDD16 正在生成 commit message...");let q=await s6(Z,5),K=await E1.create(),G=n().session.sessionId,W=HZ(Q,J,q),H=(await K.chat(W,{messages:[],userId:"cli-user",sessionId:G||"git-commit",workspaceRoot:Z,signal:X})).replace(/^```\w*\n?/,"").replace(/\n?```$/,"").trim();Y.sendMessage(`**生成的 Commit Message:**
1321
+ \`\`\``),{success:!0}}async function bK($){let Y=A1($),{cwd:Z,signal:X}=$;if(!await Z4(Z))return Y.sendMessage("\uD83D\uDCED 没有未提交的改动"),{success:!0};Y.sendMessage("\uD83D\uDCE6 暂存所有改动..."),await k9(Z);let Q=await o$(Z),J=await s$(Z);if(!Q)return Y.sendMessage("\uD83D\uDCED 没有需要提交的改动"),{success:!0};Y.sendMessage("\uD83E\uDD16 正在生成 commit message...");let q=await X4(Z,5),G=await v1.create(),K=s().session.sessionId,W=RZ(Q,J,q),H=(await G.chat(W,{messages:[],userId:"cli-user",sessionId:K||"git-commit",workspaceRoot:Z,signal:X})).replace(/^```\w*\n?/,"").replace(/\n?```$/,"").trim();Y.sendMessage(`**生成的 Commit Message:**
1297
1322
  \`\`\`
1298
1323
  ${H}
1299
- \`\`\``);try{await KZ(Z,H),Y.sendMessage("✅ 提交成功!")}catch(O){let z=O instanceof Error?O.message:"未知错误";return Y.sendMessage(`❌ 提交失败: ${z}`),{success:!1,error:z}}return{success:!0}}function HZ($,Y,Z){let X=Z&&Z.trim().length>0;return`请根据以下 Git 改动生成一条 commit message。
1324
+ \`\`\``);try{await wZ(Z,H),Y.sendMessage("✅ 提交成功!")}catch(O){let F=O instanceof Error?O.message:"未知错误";return Y.sendMessage(`❌ 提交失败: ${F}`),{success:!1,error:F}}return{success:!0}}function RZ($,Y,Z){let X=Z&&Z.trim().length>0;return`请根据以下 Git 改动生成一条 commit message。
1300
1325
 
1301
1326
  **暂存文件:**
1302
1327
  ${$}
@@ -1317,13 +1342,13 @@ ${Z}
1317
1342
  1. ${X?"严格模仿历史提交的语言和格式风格":"使用英文,遵循 Conventional Commits 格式(feat:, fix:, docs:, refactor:, chore: 等)"}
1318
1343
  2. 第一行简明扼要,不超过 72 字符
1319
1344
  3. 如有必要,可添加空行后的详细说明
1320
- 4. 只输出 commit message 内容,不要其他解释或代码块标记`}var ZG,OZ;var zZ=R(()=>{J2();F1();b9();H2();ZG={name:"git",description:"Git 仓库查询和 AI 辅助",usage:"/git [status|log|diff|review|commit|pre-commit]",aliases:["g"],examples:["/git","/git status","/git log 10","/git review","/git commit","/git pre-commit"],async handler($,Y){let{cwd:Z}=Y,X=$[0]?.toLowerCase();if(!await c$(Z))return{success:!1,error:"❌ 当前目录不在 Git 仓库中"};try{switch(X){case"status":case"s":return UZ(Y);case"log":case"l":return XG(Y,$[1]);case"diff":case"d":return QG(Y);case"review":case"r":return JG(Y);case"commit":case"c":return KG(Y);case"pre-commit":case"pc":return qG(Y);default:return UZ(Y)}}catch(Q){return{success:!1,error:`Git 命令失败: ${Q instanceof Error?Q.message:"未知错误"}`}}}};OZ=ZG});import{exec as GG}from"child_process";import{promisify as WG}from"util";class V9{static async detectIde(){let $=process.env.TERM_PROGRAM,Y=process.env.VSCODE_INJECTION,Z=process.env.VSCODE_IPC_HOOK;if($==="vscode"||Y||Z)return await this.detectVsCode();let X=await this.detectVsCode();if(X)return X;return null}static async detectVsCode(){try{let{stdout:$}=await FZ("code --version"),Z=$.trim().split(`
1321
- `)[0]||"unknown",X=[];try{let{stdout:Q}=await FZ("code --list-extensions");X=Q.trim().split(`
1322
- `).filter(Boolean)}catch{}return{name:"VS Code",version:Z,extensions:X}}catch{return null}}static isRunningInIdeTerminal(){let $=process.env.TERM_PROGRAM,Y=process.env.VSCODE_INJECTION,Z=process.env.VSCODE_IPC_HOOK;return $==="vscode"||!!Y||!!Z}}var FZ;var _Z=R(()=>{FZ=WG(GG)});import{exec as UG}from"child_process";import{promisify as HG}from"util";class r${static async getInstalledIdes(){let $=[],Y=await this.checkVsCode();if(Y)$.push(Y);let Z=await this.checkVsCodeInsiders();if(Z)$.push(Z);let X=await this.checkCursor();if(X)$.push(X);return $}static async isIdeInstalled($){switch($){case"vscode":return await this.checkVsCode()!==null;case"vscode-insiders":return await this.checkVsCodeInsiders()!==null;case"cursor":return await this.checkCursor()!==null;default:return!1}}static async installExtension($){let Y;switch($){case"vscode":Y="code --install-extension blade-code.blade-code";break;case"vscode-insiders":Y="code-insiders --install-extension blade-code.blade-code";break;case"cursor":Y="cursor --install-extension blade-code.blade-code";break;default:return{success:!1,message:"不支持的 IDE: "+$}}try{return await t6(Y),{success:!0,message:"扩展安装成功"}}catch(Z){return{success:!1,message:"安装失败: "+(Z instanceof Error?Z.message:"未知错误")}}}static async checkVsCode(){try{let{stdout:$}=await t6("code --version");return{id:"vscode",name:"VS Code",version:$.trim().split(`
1323
- `)[0]||"unknown"}}catch{return null}}static async checkVsCodeInsiders(){try{let{stdout:$}=await t6("code-insiders --version");return{id:"vscode-insiders",name:"VS Code Insiders",version:$.trim().split(`
1324
- `)[0]||"unknown"}}catch{return null}}static async checkCursor(){try{let{stdout:$}=await t6("cursor --version");return{id:"cursor",name:"Cursor",version:$.trim().split(`
1325
- `)[0]||"unknown"}}catch{return null}}}var t6;var BZ=R(()=>{t6=HG(UG)});import{existsSync as OG,readFileSync as zG}from"fs";import{homedir as FG}from"os";import{join as _G}from"path";function BG(){switch(H$){case"connected":return{type:"info",content:`\uD83D\uDFE2 已连接到 ${D9||"IDE"} (端口: ${M9})`};case"connecting":return{type:"info",content:"\uD83D\uDFE1 正在连接..."};default:return{type:"error",content:"\uD83D\uDD34 未连接到 IDE"}}}function wZ(){try{if(OG(NZ)){let $=zG(NZ,"utf-8");return JSON.parse($)}}catch{}return null}function LZ(){let $=process.env.BLADE_IDE_PORT;if($)return parseInt($,10);let Y=wZ();if(Y)return Y.port;return null}async function NG(){let $=[],Y=BG();$.push(Y.content),$.push(""),$.push("\uD83D\uDCE6 已安装的 IDE:");let Z=await r$.getInstalledIdes();if(Z.length===0)$.push(" (未检测到支持的 IDE)");else for(let q of Z)$.push(` • ${q.name} ${q.version}`);$.push("");let X=await V9.detectIde();if(X){if($.push(`\uD83D\uDDA5️ 当前环境: ${X.name} ${X.version}`),X.extensions.length>0)$.push(` 已安装扩展: ${X.extensions.length} 个`)}let Q=LZ(),J=wZ();if(Q){if($.push(`\uD83D\uDD0C IDE 端口: ${Q}`),J&&J.workspaceFolders.length>0)$.push(` 工作区: ${J.workspaceFolders[0]}`)}else $.push(""),$.push("\uD83D\uDCA1 提示: 在 VS Code 中安装 Blade Code 插件后,运行 /ide connect 连接");return $.join(`
1326
- `)}async function wG(){let $=LZ();if(!$)return`❌ 未检测到 IDE 端口
1345
+ 4. 只输出 commit message 内容,不要其他解释或代码块标记`}var NK,VZ;var DZ=D(()=>{K2();z1();j9();F2();NK={name:"git",description:"Git 仓库查询和 AI 辅助",usage:"/git [status|log|diff|review|commit|pre-commit]",aliases:["g"],examples:["/git","/git status","/git log 10","/git review","/git commit","/git pre-commit"],async handler($,Y){let{cwd:Z}=Y,X=$[0]?.toLowerCase();if(!await n$(Z))return{success:!1,error:"❌ 当前目录不在 Git 仓库中"};try{switch(X){case"status":case"s":return bZ(Y);case"log":case"l":return BK(Y,$[1]);case"diff":case"d":return wK(Y);case"review":case"r":return LK(Y);case"commit":case"c":return bK(Y);case"pre-commit":case"pc":return AK(Y);default:return bZ(Y)}}catch(Q){return{success:!1,error:`Git 命令失败: ${Q instanceof Error?Q.message:"未知错误"}`}}}};VZ=NK});import{exec as RK}from"child_process";import{promisify as VK}from"util";class E9{static async detectIde(){let $=process.env.TERM_PROGRAM,Y=process.env.VSCODE_INJECTION,Z=process.env.VSCODE_IPC_HOOK;if($==="vscode"||Y||Z)return await this.detectVsCode();let X=await this.detectVsCode();if(X)return X;return null}static async detectVsCode(){try{let{stdout:$}=await IZ("code --version"),Z=$.trim().split(`
1346
+ `)[0]||"unknown",X=[];try{let{stdout:Q}=await IZ("code --list-extensions");X=Q.trim().split(`
1347
+ `).filter(Boolean)}catch{}return{name:"VS Code",version:Z,extensions:X}}catch{return null}}static isRunningInIdeTerminal(){let $=process.env.TERM_PROGRAM,Y=process.env.VSCODE_INJECTION,Z=process.env.VSCODE_IPC_HOOK;return $==="vscode"||!!Y||!!Z}}var IZ;var MZ=D(()=>{IZ=VK(RK)});import{exec as DK}from"child_process";import{promisify as IK}from"util";class t${static async getInstalledIdes(){let $=[],Y=await this.checkVsCode();if(Y)$.push(Y);let Z=await this.checkVsCodeInsiders();if(Z)$.push(Z);let X=await this.checkCursor();if(X)$.push(X);return $}static async isIdeInstalled($){switch($){case"vscode":return await this.checkVsCode()!==null;case"vscode-insiders":return await this.checkVsCodeInsiders()!==null;case"cursor":return await this.checkCursor()!==null;default:return!1}}static async installExtension($){let Y;switch($){case"vscode":Y="code --install-extension blade-code.blade-code";break;case"vscode-insiders":Y="code-insiders --install-extension blade-code.blade-code";break;case"cursor":Y="cursor --install-extension blade-code.blade-code";break;default:return{success:!1,message:"不支持的 IDE: "+$}}try{return await Q4(Y),{success:!0,message:"扩展安装成功"}}catch(Z){return{success:!1,message:"安装失败: "+(Z instanceof Error?Z.message:"未知错误")}}}static async checkVsCode(){try{let{stdout:$}=await Q4("code --version");return{id:"vscode",name:"VS Code",version:$.trim().split(`
1348
+ `)[0]||"unknown"}}catch{return null}}static async checkVsCodeInsiders(){try{let{stdout:$}=await Q4("code-insiders --version");return{id:"vscode-insiders",name:"VS Code Insiders",version:$.trim().split(`
1349
+ `)[0]||"unknown"}}catch{return null}}static async checkCursor(){try{let{stdout:$}=await Q4("cursor --version");return{id:"cursor",name:"Cursor",version:$.trim().split(`
1350
+ `)[0]||"unknown"}}catch{return null}}}var Q4;var kZ=D(()=>{Q4=IK(DK)});import{existsSync as MK,readFileSync as kK}from"fs";import{homedir as jK}from"os";import{join as EK}from"path";function vK(){switch(F$){case"connected":return{type:"info",content:`\uD83D\uDFE2 已连接到 ${v9||"IDE"} (端口: ${y9})`};case"connecting":return{type:"info",content:"\uD83D\uDFE1 正在连接..."};default:return{type:"error",content:"\uD83D\uDD34 未连接到 IDE"}}}function EZ(){try{if(MK(jZ)){let $=kK(jZ,"utf-8");return JSON.parse($)}}catch{}return null}function vZ(){let $=process.env.BLADE_IDE_PORT;if($)return parseInt($,10);let Y=EZ();if(Y)return Y.port;return null}async function yK(){let $=[],Y=vK();$.push(Y.content),$.push(""),$.push("\uD83D\uDCE6 已安装的 IDE:");let Z=await t$.getInstalledIdes();if(Z.length===0)$.push(" (未检测到支持的 IDE)");else for(let q of Z)$.push(` • ${q.name} ${q.version}`);$.push("");let X=await E9.detectIde();if(X){if($.push(`\uD83D\uDDA5️ 当前环境: ${X.name} ${X.version}`),X.extensions.length>0)$.push(` 已安装扩展: ${X.extensions.length} 个`)}let Q=vZ(),J=EZ();if(Q){if($.push(`\uD83D\uDD0C IDE 端口: ${Q}`),J&&J.workspaceFolders.length>0)$.push(` 工作区: ${J.workspaceFolders[0]}`)}else $.push(""),$.push("\uD83D\uDCA1 提示: 在 VS Code 中安装 Blade Code 插件后,运行 /ide connect 连接");return $.join(`
1351
+ `)}async function PK(){let $=vZ();if(!$)return`❌ 未检测到 IDE 端口
1327
1352
 
1328
1353
  请确保:
1329
1354
  1. 已在 VS Code 中安装 Blade Code 插件
@@ -1331,55 +1356,70 @@ ${Z}
1331
1356
  3. 在 VS Code 终端中运行 blade
1332
1357
 
1333
1358
  或手动设置端口:
1334
- export BLADE_IDE_PORT=9527`;H$="connecting";try{let Z=new(await import("ws")).default(`ws://127.0.0.1:${$}`);return await new Promise((X,Q)=>{let J=setTimeout(()=>{Z.close(),Q(Error("连接超时"))},5000);Z.on("open",()=>{clearTimeout(J),H$="connected",M9=$,D9="VS Code",Z.close(),X()}),Z.on("error",(q)=>{clearTimeout(J),Q(q)})}),`✅ 成功连接到 IDE (端口: ${$})
1359
+ export BLADE_IDE_PORT=9527`;F$="connecting";try{let Z=new(await import("ws")).default(`ws://127.0.0.1:${$}`);return await new Promise((X,Q)=>{let J=setTimeout(()=>{Z.close(),Q(Error("连接超时"))},5000);Z.on("open",()=>{clearTimeout(J),F$="connected",y9=$,v9="VS Code",Z.close(),X()}),Z.on("error",(q)=>{clearTimeout(J),Q(q)})}),`✅ 成功连接到 IDE (端口: ${$})
1335
1360
 
1336
1361
  现在可以使用以下功能:
1337
1362
  • 在 IDE 中打开文件
1338
1363
  • 获取当前选中的代码
1339
- • 查看打开的编辑器列表`}catch(Y){return H$="disconnected",`❌ 连接失败: ${Y instanceof Error?Y.message:"未知错误"}
1364
+ • 查看打开的编辑器列表`}catch(Y){return F$="disconnected",`❌ 连接失败: ${Y instanceof Error?Y.message:"未知错误"}
1340
1365
 
1341
1366
  请检查:
1342
1367
  1. VS Code 插件是否正在运行
1343
1368
  2. 端口 ${$} 是否正确
1344
- 3. 防火墙设置`}}async function LG(){let $=[];if($.push("\uD83D\uDCE6 安装 Blade Code VS Code 插件"),$.push(""),!await r$.isIdeInstalled("vscode"))return $.push("❌ 未检测到 VS Code"),$.push(""),$.push("请先安装 VS Code:"),$.push(" https://code.visualstudio.com/"),$.join(`
1369
+ 3. 防火墙设置`}}async function TK(){let $=[];if($.push("\uD83D\uDCE6 安装 Blade Code VS Code 插件"),$.push(""),!await t$.isIdeInstalled("vscode"))return $.push("❌ 未检测到 VS Code"),$.push(""),$.push("请先安装 VS Code:"),$.push(" https://code.visualstudio.com/"),$.join(`
1345
1370
  `);return $.push("✅ 检测到 VS Code"),$.push(""),$.push("安装方式:"),$.push(""),$.push("从 VSIX 文件安装:"),$.push(" 1. 下载插件: https://github.com/anthropics/blade-code/releases"),$.push(" 2. 运行: code --install-extension blade-code-x.x.x.vsix"),$.push(""),$.push("或从源码构建:"),$.push(" cd vscode-extension && pnpm install && pnpm run package"),$.push(" code --install-extension blade-code-0.0.1.vsix"),$.push(""),$.push("安装完成后,在 VS Code 终端中运行 blade 即可自动连接"),$.join(`
1346
- `)}async function AG(){if(H$==="disconnected")return"⚠️ 当前未连接到任何 IDE";return H$="disconnected",D9=null,M9=null,"✅ 已断开与 IDE 的连接"}var NZ,H$="disconnected",D9=null,M9=null,RG,AZ;var RZ=R(()=>{_Z();BZ();NZ=_G(FG(),".blade","ide-port");RG={name:"ide",aliases:[],description:"Manage IDE integrations and show status",usage:"/ide [status|connect|install|disconnect]",category:"system",async handler($,Y){let Z=($[0]||"").toLowerCase(),X;switch(Z){case"":case"status":X=await NG();break;case"connect":X=await wG();break;case"install":X=await LG();break;case"disconnect":X=await AG();break;default:X=`未知的子命令: ${Z}
1371
+ `)}async function SK(){if(F$==="disconnected")return"⚠️ 当前未连接到任何 IDE";return F$="disconnected",v9=null,y9=null,"✅ 已断开与 IDE 的连接"}var jZ,F$="disconnected",v9=null,y9=null,CK,yZ;var PZ=D(()=>{MZ();kZ();jZ=EK(jK(),".blade","ide-port");CK={name:"ide",aliases:[],description:"Manage IDE integrations and show status",usage:"/ide [status|connect|install|disconnect]",category:"system",async handler($,Y){let Z=($[0]||"").toLowerCase(),X;switch(Z){case"":case"status":X=await yK();break;case"connect":X=await PK();break;case"install":X=await TK();break;case"disconnect":X=await SK();break;default:X=`未知的子命令: ${Z}
1347
1372
 
1348
1373
  可用命令:
1349
1374
  /ide status - 显示连接状态
1350
1375
  /ide connect - 连接到 IDE
1351
1376
  /ide install - 安装 VS Code 插件
1352
- /ide disconnect - 断开连接`}return{success:!0,message:X}}},AZ=RG});function a$($,Y){switch($){case"Write":return`Write(${Y.file_path||"file"})`;case"Edit":return`Edit(${Y.file_path||"file"})`;case"Read":return`Read(${Y.file_path||"file"})`;case"Bash":{let Z=Y.command;return`Bash(${Z?Z.substring(0,50):"command"}${Z&&Z.length>50?"...":""})`}case"Glob":return`Glob(${Y.pattern||"*"})`;case"Grep":{let{pattern:Z,path:X}=Y;if(X)return`Grep("${Z}" in ${X})`;return`Grep("${Z}")`}case"WebFetch":{let Z=Y.url;if(Z)try{return`WebFetch(${new URL(Z).hostname})`}catch{return`WebFetch(${Z.substring(0,30)}${Z.length>30?"...":""})`}return"WebFetch(url)"}case"WebSearch":return`WebSearch("${Y.query||"query"}")`;case"TodoWrite":return`TodoWrite(${Y.todos?.length||0} items)`;case"UndoEdit":return`UndoEdit(${Y.file_path||"file"})`;default:return`${$}()`}}function bZ($,Y){if(!Y?.displayContent)return!1;switch($){case"Write":return(Y.metadata?.file_size||0)<1e4;case"Edit":return!0;case"Bash":return(Y.metadata?.stdout_length||0)<1000;case"Read":case"TodoWrite":return!1;default:return!1}}import{promises as n$}from"fs";import*as VZ from"path";var f0,bG,DZ;var MZ=R(()=>{J2();N1();F1();H2();f0=u("Agent"),bG={name:"init",description:"分析当前项目并生成 BLADE.md 配置文件",usage:"/init",async handler($,Y){try{let{cwd:Z,signal:X}=Y,Q=A1(Y),J=(z)=>{Q.sendMessage(`${z}`)},q=n().session.sessionId,K=VZ.join(Z,"BLADE.md"),G=!1,W=!1;try{if(G=(await n$.stat(K)).isFile(),G)W=(await n$.readFile(K,"utf-8")).trim().length===0}catch{G=!1}if(G&&!W){Q.sendMessage("⚠️ BLADE.md 已存在。"),Q.sendMessage("\uD83D\uDCA1 正在分析现有文件并提供改进建议...");let z=await E1.create(),_=`Please analyze the existing BLADE.md file and provide improvement suggestions.
1377
+ /ide disconnect - 断开连接`}return{success:!0,message:X}}},yZ=CK});function e$($,Y){switch($){case"Write":return`Write(${Y.file_path||"file"})`;case"Edit":return`Edit(${Y.file_path||"file"})`;case"Read":return`Read(${Y.file_path||"file"})`;case"Bash":{let Z=Y.command;return`Bash(${Z?Z.substring(0,50):"command"}${Z&&Z.length>50?"...":""})`}case"Glob":return`Glob(${Y.pattern||"*"})`;case"Grep":{let{pattern:Z,path:X}=Y;if(X)return`Grep("${Z}" in ${X})`;return`Grep("${Z}")`}case"WebFetch":{let Z=Y.url;if(Z)try{return`WebFetch(${new URL(Z).hostname})`}catch{return`WebFetch(${Z.substring(0,30)}${Z.length>30?"...":""})`}return"WebFetch(url)"}case"WebSearch":return`WebSearch("${Y.query||"query"}")`;case"TodoWrite":return`TodoWrite(${Y.todos?.length||0} items)`;case"UndoEdit":return`UndoEdit(${Y.file_path||"file"})`;default:return`${$}()`}}function TZ($,Y){if(!Y?.displayContent)return!1;switch($){case"Write":return(Y.metadata?.file_size||0)<1e4;case"Edit":return!0;case"Bash":return(Y.metadata?.stdout_length||0)<1000;case"Read":case"TodoWrite":return!1;default:return!1}}import{promises as $6}from"fs";import*as SZ from"path";var z$,fK,CZ;var fZ=D(()=>{K2();B1();z1();F2();z$=l("Agent"),fK={name:"init",description:"分析当前项目并生成 BLADE.md 配置文件",usage:"/init",async handler($,Y){try{let{cwd:Z,signal:X}=Y,Q=A1(Y),J=(F)=>{Q.sendMessage(`${F}`)},q=s().session.sessionId,G=SZ.join(Z,"BLADE.md"),K=!1,W=!1;try{if(K=(await $6.stat(G)).isFile(),K)W=(await $6.readFile(G,"utf-8")).trim().length===0}catch{K=!1}if(K&&!W){Q.sendMessage("⚠️ BLADE.md 已存在。"),Q.sendMessage("\uD83D\uDCA1 正在分析现有文件并提供改进建议...");let F=await v1.create(),_=`Please analyze the existing BLADE.md file and provide improvement suggestions.
1353
1378
 
1354
1379
  **Important**:
1355
1380
  - After each step, briefly describe what you found before proceeding
1356
1381
  - DO NOT create new files or modify the existing BLADE.md
1357
1382
  - Return only your analysis and suggestions as TEXT
1358
1383
 
1384
+ **Context**: BLADE.md is given to AI coding agents. Length should match project complexity - simple projects ~20 lines, complex projects can be longer but every section must provide value.
1385
+
1359
1386
  **Step-by-step process:**
1360
1387
 
1361
- 1. Read the current BLADE.md file at ${K} and summarize its current structure
1388
+ 1. Read the current BLADE.md file at ${G} and summarize its current structure
1362
1389
 
1363
1390
  2. Read package.json and note:
1364
1391
  - Any new scripts or commands not documented
1365
1392
  - New dependencies that might need explanation
1366
1393
  - Changes in project structure
1367
1394
 
1368
- 3. Explore the codebase (use Glob/Grep instead of find/grep commands) to identify:
1395
+ 3. Check for existing AI rule files and note any useful guidance:
1396
+ - .cursorrules or .cursor/rules/
1397
+ - .github/copilot-instructions.md
1398
+
1399
+ 4. Explore the codebase (use Glob/Grep tools) to identify:
1369
1400
  - Missing architectural information
1370
1401
  - Undocumented patterns or conventions
1371
1402
  - Important files or directories not mentioned
1403
+ - Key modules, design patterns, state management, data flow
1404
+
1405
+ **Evaluate against these criteria**:
1406
+ - Has essential commands (build, test, lint, especially single test execution)?
1407
+ - Has architecture overview proportional to project complexity?
1408
+ - Does it include project-specific knowledge that saves agent time?
1409
+ - Does it avoid LOW-VALUE content (generic best practices, exhaustive file listings)?
1372
1410
 
1373
- 4. Provide comprehensive feedback in Chinese:
1411
+ 5. Provide comprehensive feedback in Chinese:
1374
1412
  - 当前 BLADE.md 的优点
1375
1413
  - 缺失或过时的内容
1376
1414
  - 具体的改进建议(附带示例)
1377
1415
  - 如果需要重大修改,提供完整的改进版本内容
1378
1416
 
1379
- **Final output**: Return your analysis and suggestions as plain text. Do NOT use Write tool.`;f0.info(`[/init] Starting agent.chat, signal.aborted: ${X?.aborted}`);let F=await z.chat(_,{messages:[],userId:"cli-user",sessionId:q||"init-session",workspaceRoot:Z,signal:X},{onToolStart:(N)=>{if(N.type!=="function")return;if(X?.aborted){f0.info("[/init] onToolStart: signal already aborted, skipping");return}try{let w=JSON.parse(N.function.arguments),B=a$(N.function.name,w);J(B)}catch{}},onToolResult:async(N,w)=>{if(N.type!=="function")return;if(X?.aborted){f0.info("[/init] onToolResult: signal already aborted, skipping");return}if(w?.metadata?.summary)J(w.metadata.summary)}});if(f0.info(`[/init] agent.chat completed, signal.aborted: ${X?.aborted}`),X?.aborted)return f0.info("[/init] Returning cancelled after agent.chat"),{success:!1,message:"操作已取消"};return Q.sendMessage(F),{success:!0,message:"✅ 分析完成"}}if(W)Q.sendMessage("⚠️ 检测到空的 BLADE.md 文件,将重新生成...");Q.sendMessage("\uD83D\uDD0D 正在分析项目结构...");let U=await E1.create(),H=`Please analyze this codebase and generate BLADE.md content.
1417
+ **Final output**: Return your analysis and suggestions as plain text. Do NOT use Write tool.`;z$.info(`[/init] Starting agent.chat, signal.aborted: ${X?.aborted}`);let z=await F.chat(_,{messages:[],userId:"cli-user",sessionId:q||"init-session",workspaceRoot:Z,signal:X},{onToolStart:(w)=>{if(w.type!=="function")return;try{let B=JSON.parse(w.function.arguments),N=e$(w.function.name,B);J(N)}catch{}},onToolResult:async(w,B)=>{if(w.type!=="function")return;if(B?.metadata?.summary)J(B.metadata.summary)}});if(z$.info(`[/init] agent.chat completed, signal.aborted: ${X?.aborted}`),X?.aborted)return z$.info("[/init] Returning cancelled after agent.chat"),{success:!1,message:"操作已取消"};return Q.sendMessage(z),{success:!0,message:"✅ 分析完成"}}if(W)Q.sendMessage("⚠️ 检测到空的 BLADE.md 文件,将重新生成...");Q.sendMessage("\uD83D\uDD0D 正在分析项目结构...");let U=await v1.create(),H=`Please analyze this codebase and generate BLADE.md content.
1380
1418
 
1381
1419
  **Important**: After each step, briefly describe what you found before proceeding.
1382
1420
 
1421
+ **Context**: This file will be given to AI coding agents. Length should match project complexity - every section must provide value that saves agent time.
1422
+
1383
1423
  **Step-by-step process:**
1384
1424
 
1385
1425
  1. Read package.json and summarize:
@@ -1387,29 +1427,41 @@ ${Z}
1387
1427
  - Key dependencies and frameworks
1388
1428
  - Available scripts (build, test, lint, etc.)
1389
1429
 
1390
- 2. Explore the project structure and note:
1430
+ 2. Check for existing AI rule files and incorporate useful guidance:
1431
+ - .cursorrules or .cursor/rules/
1432
+ - .github/copilot-instructions.md
1433
+ - README.md (extract non-obvious insights only)
1434
+
1435
+ 3. Explore the project structure and note:
1391
1436
  - Main entry point
1392
1437
  - Key directories (src, tests, config, etc.)
1393
1438
  - Common patterns (React components, API routes, etc.)
1394
1439
 
1395
- 3. Analyze the architecture and identify:
1440
+ 4. Analyze the architecture and identify:
1396
1441
  - How the code is organized
1397
- - Main modules/components
1442
+ - Main modules/components and their responsibilities
1443
+ - Key design patterns (state management, data flow, etc.)
1398
1444
  - How different parts interact
1399
1445
 
1400
- 4. Generate the final BLADE.md content with:
1446
+ 5. Generate the final BLADE.md content with:
1401
1447
  - Project overview (type, languages, frameworks)
1402
- - Essential commands (from package.json scripts)
1448
+ - Essential commands (from package.json scripts, especially single test execution)
1403
1449
  - Architecture overview (structure, patterns, relationships)
1404
- - Development guidelines (testing, building, deploying)
1450
+ - Non-obvious conventions and gotchas
1451
+ - Key file locations for common tasks
1452
+
1453
+ **What to AVOID** (low-value content):
1454
+ - Generic best practices (error handling basics, security fundamentals)
1455
+ - Exhaustive file/directory listings without context
1456
+ - Information already obvious from README or file names
1405
1457
 
1406
1458
  **Format requirements:**
1407
- - Start with: "# BLADE.md\\n\\nalways respond in Chinese\\n\\n你是一个专门帮助 [项目类型] 开发者的助手。"
1459
+ - Start with: "# BLADE.md\\n\\nalways respond in Chinese"
1408
1460
  - Include actual working commands
1409
1461
  - Focus on non-obvious insights
1410
- - Be concise but comprehensive
1462
+ - Be concise but comprehensive for complex projects
1411
1463
 
1412
- **Final output**: Return ONLY the complete BLADE.md content (markdown format), ready to be written to the file.`;f0.info(`[/init] Starting agent.chat for new BLADE.md, signal.aborted: ${X?.aborted}`);let O=await U.chat(H,{messages:[],userId:"cli-user",sessionId:q||"init-session",workspaceRoot:Z,signal:X},{onToolStart:(z)=>{if(z.type!=="function")return;if(X?.aborted){f0.info("[/init] onToolStart: signal already aborted, skipping");return}try{let _=JSON.parse(z.function.arguments),F=a$(z.function.name,_);J(F)}catch{}},onToolResult:async(z,_)=>{if(z.type!=="function")return;if(X?.aborted){f0.info("[/init] onToolResult: signal already aborted, skipping");return}if(_?.metadata?.summary)J(_.metadata.summary)}});if(f0.info(`[/init] agent.chat completed for new BLADE.md, signal.aborted: ${X?.aborted}`),X?.aborted)return f0.info("[/init] Returning cancelled after agent.chat (new BLADE.md)"),{success:!1,message:"操作已取消"};if(!O||O.trim().length===0)throw Error("Agent 未能生成有效的 BLADE.md 内容");return Q.sendMessage("✨ 正在写入 BLADE.md..."),await n$.writeFile(K,O,"utf-8"),{success:!0,message:"✅ 已成功生成 BLADE.md 文件"}}catch(Z){return{success:!1,error:`初始化失败: ${Z instanceof Error?Z.message:"未知错误"}`}}}},DZ=bG});var VG,IZ;var kZ=R(()=>{F1();VG={name:"model",description:"管理和切换模型配置",usage:"/model [子命令] [参数]",fullDescription:`
1464
+ **Final output**: Return ONLY the complete BLADE.md content (markdown format), ready to be written to the file.`;z$.info(`[/init] Starting agent.chat for new BLADE.md, signal.aborted: ${X?.aborted}`);let O=await U.chat(H,{messages:[],userId:"cli-user",sessionId:q||"init-session",workspaceRoot:Z,signal:X},{onToolStart:(F)=>{if(F.type!=="function")return;try{let _=JSON.parse(F.function.arguments),z=e$(F.function.name,_);J(z)}catch{}},onToolResult:async(F,_)=>{if(F.type!=="function")return;if(_?.metadata?.summary)J(_.metadata.summary)}});if(z$.info(`[/init] agent.chat completed for new BLADE.md, signal.aborted: ${X?.aborted}`),X?.aborted)return z$.info("[/init] Returning cancelled after agent.chat (new BLADE.md)"),{success:!1,message:"操作已取消"};if(!O||O.trim().length===0)throw Error("Agent 未能生成有效的 BLADE.md 内容");return Q.sendMessage("✨ 正在写入 BLADE.md..."),await $6.writeFile(G,O,"utf-8"),{success:!0,message:"✅ 已成功生成 BLADE.md 文件"}}catch(Z){return{success:!1,error:`初始化失败: ${Z instanceof Error?Z.message:"未知错误"}`}}}},CZ=fK});var hK,hZ;var xZ=D(()=>{z1();hK={name:"model",description:"管理和切换模型配置",usage:"/model [子命令] [参数]",fullDescription:`
1413
1465
  管理和切换模型配置
1414
1466
 
1415
1467
  子命令:
@@ -1421,34 +1473,34 @@ ${Z}
1421
1473
  /model # 显示模型选择器
1422
1474
  /model add # 添加新模型
1423
1475
  /model remove 千问 # 删除名称包含"千问"的模型
1424
- `,async handler($,Y){let Z=$[0];if(!Z){if(T$().length===0)return{success:!1,message:`❌ 没有可用的模型配置
1476
+ `,async handler($,Y){let Z=$[0];if(!Z){if(h$().length===0)return{success:!1,message:`❌ 没有可用的模型配置
1425
1477
 
1426
1478
  使用 /model add 添加模型`};return{success:!0,message:"show_model_selector",data:{action:"show_model_selector"}}}switch(Z){case"add":return{success:!0,message:"show_model_add_wizard",data:{action:"show_model_add_wizard",mode:"add"}};case"remove":{let X=$.slice(1).join(" ");if(!X)return{success:!1,message:`❌ 请指定要删除的模型名称
1427
- 用法: /model remove <名称>`};let J=T$().find((q)=>q.name.toLowerCase().includes(X.toLowerCase()));if(!J)return{success:!1,message:`❌ 未找到匹配的模型配置: ${X}`};try{return await U1().removeModel(J.id),{success:!0,message:`✅ 已删除模型配置: ${J.name}`}}catch(q){return{success:!1,message:`❌ ${q.message}`}}}default:return{success:!1,message:`❌ 未知的子命令: ${Z}
1428
- 使用 /model 查看可用操作`}}}},IZ=VG});async function DG($,Y){return{success:!0,message:"show_theme_selector",data:{action:"show_theme_selector"}}}var MG,jZ;var EZ=R(()=>{MG={name:"theme",description:"打开交互式主题选择器",aliases:["themes","style"],usage:"/theme",examples:["/theme"],category:"ui",handler:DG},jZ=MG});import IG from"fuse.js";function e6($){return $.trim().startsWith("/")}function kG($){let Y=$.trim();if(!Y.startsWith("/"))throw Error("不是有效的 slash command");let Z=Y.slice(1).split(/\s+/),X=Z[0]||"",Q=Z.slice(1);return{command:X,args:Q}}function jG($){if(o$[$])return o$[$];for(let Y of Object.values(o$))if(Y.aliases?.includes($))return Y;return}async function $4($,Y){try{let{command:Z,args:X}=kG($),Q=jG(Z);if(!Q)return{success:!1,error:`未知命令: /${Z}\\n使用 /help 查看可用命令`};return await Q.handler(X,Y)}catch(Z){return{success:!1,error:`命令执行失败: ${Z instanceof Error?Z.message:"未知错误"}`}}}function yZ(){return Object.values(o$)}function vZ($){let Y=($.startsWith("/")?$.slice(1):$).trim(),Z=Object.values(o$).map((q)=>({name:q.name,description:q.description,aliases:q.aliases||[],command:q}));if(!Y)return Z.map((q)=>({command:`/${q.name}`,description:q.description,matchScore:50}));return new IG(Z,{keys:[{name:"name",weight:3},{name:"aliases",weight:2.5},{name:"description",weight:0.5}],threshold:0.4,includeScore:!0,ignoreLocation:!0,minMatchCharLength:1}).search(Y).map((q)=>{let K=q.score??1,G=Math.round((1-K)*100);return{command:`/${q.item.name}`,description:q.item.description,matchScore:G}}).filter((q)=>(q.matchScore||0)>=40)}var o$;var Y4=R(()=>{QZ();zZ();RZ();MZ();kZ();A9();EZ();o$={...XZ,init:DZ,theme:jZ,permissions:n6,model:IZ,git:OZ,ide:AZ}});import{nanoid as kH}from"nanoid";class X7{id;cwd;connection;clientCapabilities;agent=null;pendingPrompt=null;messages=[];mode="default";sessionApprovals=new Set;constructor($,Y,Z,X){this.id=$;this.cwd=Y;this.connection=Z;this.clientCapabilities=X}async initialize(){L1.debug(`[AcpSession ${this.id}] Initializing...`),l.initializeSession(this.connection,this.id,this.clientCapabilities,this.cwd),L1.debug(`[AcpSession ${this.id}] ACP service context initialized`),this.agent=await E1.create({}),L1.debug(`[AcpSession ${this.id}] Agent created successfully`)}sendAvailableCommandsDelayed(){L1.debug(`[AcpSession ${this.id}] Scheduling available commands update (500ms delay)`),setTimeout(()=>{this.sendAvailableCommands()},500)}async handleSlashCommand($,Y){try{L1.debug(`[AcpSession ${this.id}] Executing slash command: ${$}`);let Z={cwd:this.cwd,signal:Y,acp:{sendMessage:(J)=>{this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:J}})},sendToolStart:(J,q,K)=>{let G=`tool_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,W=this.mapToolKind(K);this.sendUpdate({sessionUpdate:"tool_call",toolCallId:G,status:"in_progress",title:`${J}`,content:[{type:"content",content:{type:"text",text:JSON.stringify(q,null,2)}}],kind:W})},sendToolResult:(J,q)=>{if(q.summary)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:q.summary}})}}},X=await $4($,Z),Q=X.content||X.message;if(Q)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:Q}});if(X.error)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`❌ ${X.error}`}});return{stopReason:X.success?"end_turn":"cancelled"}}catch(Z){return L1.error(`[AcpSession ${this.id}] Slash command error:`,Z),this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`❌ 命令执行失败: ${Z instanceof Error?Z.message:"未知错误"}`}}),{stopReason:"cancelled"}}}async sendAvailableCommands(){try{let $=yZ(),Y=["model","permissions","theme","config","exit","ide"],X=$.filter((Q)=>!Y.includes(Q.name)).map((Q)=>({name:Q.name,description:Q.description,input:Q.aliases?.length?{hint:`Aliases: ${Q.aliases.join(", ")}`}:void 0}));L1.info(`[AcpSession ${this.id}] Sending available commands: ${JSON.stringify(X.map((Q)=>Q.name))}`),this.sendUpdate({sessionUpdate:"available_commands_update",availableCommands:X}),L1.info(`[AcpSession ${this.id}] Sent ${X.length} available commands`)}catch($){L1.error(`[AcpSession ${this.id}] Failed to send available commands:`,$)}}async prompt($){l.setCurrentSession(this.id),this.pendingPrompt?.abort();let Y=new AbortController;if(this.pendingPrompt=Y,!this.agent)throw Error("Session not initialized");try{let Z=this.resolvePrompt($.prompt);if(L1.debug(`[AcpSession ${this.id}] Received prompt: ${Z.slice(0,100)}...`),e6(Z))return await this.handleSlashCommand(Z,Y.signal);let X={sessionId:this.id,userId:"acp-user",workspaceRoot:this.cwd,messages:[...this.messages],signal:Y.signal,permissionMode:this.mapModeToPermissionMode(),confirmationHandler:{requestConfirmation:async(q)=>{return this.requestPermission(q)}}},Q={signal:Y.signal,onContent:(q)=>{this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:q}})},onThinking:(q)=>{this.sendUpdate({sessionUpdate:"agent_thought_chunk",content:{type:"text",text:q}})},onToolStart:(q,K)=>{let G="function"in q?q.function.name:q.type,W=this.mapToolKind(K);this.sendUpdate({sessionUpdate:"tool_call",toolCallId:q.id,status:"in_progress",title:`Executing ${G}`,content:[],kind:W})},onToolResult:async(q,K)=>{let G=[],W=K.metadata;if(W?.kind==="edit"&&W?.file_path&&W?.oldContent!==void 0&&W?.newContent!==void 0)G.push({type:"diff",path:W.file_path,oldText:W.oldContent,newText:W.newContent});else if(K.displayContent){let O=typeof K.displayContent==="string"?K.displayContent:JSON.stringify(K.displayContent);G.push({type:"content",content:{type:"text",text:O}})}let U="function"in q?q.function.name:q.type,H=K.success?"completed":"failed";this.sendUpdate({sessionUpdate:"tool_call_update",toolCallId:q.id,status:H,content:G})}},J=await this.agent.chat(Z,X,Q);if(J)this.messages.push({role:"user",content:Z}),this.messages.push({role:"assistant",content:J});if(Y.signal.aborted)return{stopReason:"cancelled"};return{stopReason:"end_turn"}}catch(Z){if(Y.signal.aborted||Z instanceof Error&&Z.name==="AbortError")return{stopReason:"cancelled"};throw L1.error(`[AcpSession ${this.id}] Prompt error:`,Z),Z}finally{if(this.pendingPrompt===Y)this.pendingPrompt=null}}cancel(){if(L1.info(`[AcpSession ${this.id}] Cancel requested`),this.pendingPrompt)this.pendingPrompt.abort(),this.pendingPrompt=null,L1.info(`[AcpSession ${this.id}] Cancelled successfully`);else L1.warn(`[AcpSession ${this.id}] No pending prompt to cancel`)}async setMode($){let Y=["default","auto-edit","yolo","plan"];this.mode=Y.includes($)?$:"default",L1.info(`[AcpSession ${this.id}] Mode set to: ${this.mode}`),this.sendUpdate({sessionUpdate:"current_mode_update",currentModeId:this.mode})}mapModeToPermissionMode(){switch(this.mode){case"yolo":return"yolo";case"auto-edit":return"autoEdit";case"plan":return"plan";case"default":default:return"default"}}shouldAutoApprove($){switch(this.mode){case"yolo":return!0;case"auto-edit":return $==="readonly"||$==="write";case"plan":return $==="readonly";case"default":default:return!1}}async setModel($){if(L1.info(`[AcpSession ${this.id}] Model set to: ${$}`),this.agent)L1.warn(`[AcpSession ${this.id}] Runtime model switching not yet implemented`)}async destroy(){if(this.cancel(),this.agent)await this.agent.destroy(),this.agent=null;l.destroySession(this.id),L1.debug(`[AcpSession ${this.id}] Destroyed`)}resolvePrompt($){let Y=[];for(let Z of $)if(Z.type==="text")Y.push(Z.text);else if(Z.type==="image")Y.push(`[Image: ${Z.mimeType}]`);else if(Z.type==="resource"){let X=Z.resource;if("text"in X)Y.push(`<file path="${X.uri}">
1479
+ 用法: /model remove <名称>`};let J=h$().find((q)=>q.name.toLowerCase().includes(X.toLowerCase()));if(!J)return{success:!1,message:`❌ 未找到匹配的模型配置: ${X}`};try{return await H1().removeModel(J.id),{success:!0,message:`✅ 已删除模型配置: ${J.name}`}}catch(q){return{success:!1,message:`❌ ${q.message}`}}}default:return{success:!1,message:`❌ 未知的子命令: ${Z}
1480
+ 使用 /model 查看可用操作`}}}},hZ=hK});async function xK($,Y){return{success:!0,message:"show_theme_selector",data:{action:"show_theme_selector"}}}var pK,pZ;var gZ=D(()=>{pK={name:"theme",description:"打开交互式主题选择器",aliases:["themes","style"],usage:"/theme",examples:["/theme"],category:"ui",handler:xK},pZ=pK});import gK from"fuse.js";function J4($){return $.trim().startsWith("/")}function mK($){let Y=$.trim();if(!Y.startsWith("/"))throw Error("不是有效的 slash command");let Z=Y.slice(1).split(/\s+/),X=Z[0]||"",Q=Z.slice(1);return{command:X,args:Q}}function dK($){if(Y6[$])return Y6[$];for(let Y of Object.values(Y6))if(Y.aliases?.includes($))return Y;return}async function q4($,Y){try{let{command:Z,args:X}=mK($),Q=dK(Z);if(!Q)return{success:!1,error:`未知命令: /${Z}\\n使用 /help 查看可用命令`};return await Q.handler(X,Y)}catch(Z){return{success:!1,error:`命令执行失败: ${Z instanceof Error?Z.message:"未知错误"}`}}}function mZ(){return Object.values(Y6)}function dZ($){let Y=($.startsWith("/")?$.slice(1):$).trim(),Z=Object.values(Y6).map((q)=>({name:q.name,description:q.description,aliases:q.aliases||[],command:q}));if(!Y)return Z.map((q)=>({command:`/${q.name}`,description:q.description,matchScore:50}));return new gK(Z,{keys:[{name:"name",weight:3},{name:"aliases",weight:2.5},{name:"description",weight:0.5}],threshold:0.4,includeScore:!0,ignoreLocation:!0,minMatchCharLength:1}).search(Y).map((q)=>{let G=q.score??1,K=Math.round((1-G)*100);return{command:`/${q.item.name}`,description:q.item.description,matchScore:K}}).filter((q)=>(q.matchScore||0)>=40)}var Y6;var G4=D(()=>{_Z();DZ();PZ();fZ();xZ();M9();gZ();Y6={...zZ,init:CZ,theme:pZ,permissions:Y4,model:hZ,git:VZ,ide:yZ}});import{nanoid as hH}from"nanoid";class F7{id;cwd;connection;clientCapabilities;agent=null;pendingPrompt=null;messages=[];mode="default";sessionApprovals=new Set;constructor($,Y,Z,X){this.id=$;this.cwd=Y;this.connection=Z;this.clientCapabilities=X}async initialize(){L1.debug(`[AcpSession ${this.id}] Initializing...`),a.initializeSession(this.connection,this.id,this.clientCapabilities,this.cwd),L1.debug(`[AcpSession ${this.id}] ACP service context initialized`),this.agent=await v1.create({}),L1.debug(`[AcpSession ${this.id}] Agent created successfully`)}sendAvailableCommandsDelayed(){L1.debug(`[AcpSession ${this.id}] Scheduling available commands update (500ms delay)`),setTimeout(()=>{this.sendAvailableCommands()},500)}async handleSlashCommand($,Y){try{L1.debug(`[AcpSession ${this.id}] Executing slash command: ${$}`);let Z={cwd:this.cwd,signal:Y,acp:{sendMessage:(J)=>{this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:J}})},sendToolStart:(J,q,G)=>{let K=`tool_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,W=this.mapToolKind(G);this.sendUpdate({sessionUpdate:"tool_call",toolCallId:K,status:"in_progress",title:`${J}`,content:[{type:"content",content:{type:"text",text:JSON.stringify(q,null,2)}}],kind:W})},sendToolResult:(J,q)=>{if(q.summary)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:q.summary}})}}},X=await q4($,Z),Q=X.content||X.message;if(Q)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:Q}});if(X.error)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`❌ ${X.error}`}});return{stopReason:X.success?"end_turn":"cancelled"}}catch(Z){return L1.error(`[AcpSession ${this.id}] Slash command error:`,Z),this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`❌ 命令执行失败: ${Z instanceof Error?Z.message:"未知错误"}`}}),{stopReason:"cancelled"}}}async sendAvailableCommands(){try{let $=mZ(),Y=["model","permissions","theme","config","exit","ide"],X=$.filter((Q)=>!Y.includes(Q.name)).map((Q)=>({name:Q.name,description:Q.description,input:Q.aliases?.length?{hint:`Aliases: ${Q.aliases.join(", ")}`}:void 0}));L1.info(`[AcpSession ${this.id}] Sending available commands: ${JSON.stringify(X.map((Q)=>Q.name))}`),this.sendUpdate({sessionUpdate:"available_commands_update",availableCommands:X}),L1.info(`[AcpSession ${this.id}] Sent ${X.length} available commands`)}catch($){L1.error(`[AcpSession ${this.id}] Failed to send available commands:`,$)}}async prompt($){a.setCurrentSession(this.id),this.pendingPrompt?.abort();let Y=new AbortController;if(this.pendingPrompt=Y,!this.agent)throw Error("Session not initialized");try{let Z=this.resolvePrompt($.prompt);if(L1.debug(`[AcpSession ${this.id}] Received prompt: ${Z.slice(0,100)}...`),J4(Z))return await this.handleSlashCommand(Z,Y.signal);let X={sessionId:this.id,userId:"acp-user",workspaceRoot:this.cwd,messages:[...this.messages],signal:Y.signal,permissionMode:this.mapModeToPermissionMode(),confirmationHandler:{requestConfirmation:async(q)=>{return this.requestPermission(q)}}},Q={signal:Y.signal,onContent:(q)=>{this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:q}})},onThinking:(q)=>{this.sendUpdate({sessionUpdate:"agent_thought_chunk",content:{type:"text",text:q}})},onToolStart:(q,G)=>{let K="function"in q?q.function.name:q.type,W=this.mapToolKind(G);this.sendUpdate({sessionUpdate:"tool_call",toolCallId:q.id,status:"in_progress",title:`Executing ${K}`,content:[],kind:W})},onToolResult:async(q,G)=>{let K=[],W=G.metadata;if(W?.kind==="edit"&&W?.file_path&&W?.oldContent!==void 0&&W?.newContent!==void 0)K.push({type:"diff",path:W.file_path,oldText:W.oldContent,newText:W.newContent});else if(G.displayContent){let O=typeof G.displayContent==="string"?G.displayContent:JSON.stringify(G.displayContent);K.push({type:"content",content:{type:"text",text:O}})}let U="function"in q?q.function.name:q.type,H=G.success?"completed":"failed";this.sendUpdate({sessionUpdate:"tool_call_update",toolCallId:q.id,status:H,content:K})}},J=await this.agent.chat(Z,X,Q);if(J)this.messages.push({role:"user",content:Z}),this.messages.push({role:"assistant",content:J});if(Y.signal.aborted)return{stopReason:"cancelled"};return{stopReason:"end_turn"}}catch(Z){if(Y.signal.aborted||Z instanceof Error&&Z.name==="AbortError")return{stopReason:"cancelled"};throw L1.error(`[AcpSession ${this.id}] Prompt error:`,Z),Z}finally{if(this.pendingPrompt===Y)this.pendingPrompt=null}}cancel(){if(L1.info(`[AcpSession ${this.id}] Cancel requested`),this.pendingPrompt)this.pendingPrompt.abort(),this.pendingPrompt=null,L1.info(`[AcpSession ${this.id}] Cancelled successfully`);else L1.warn(`[AcpSession ${this.id}] No pending prompt to cancel`)}async setMode($){let Y=["default","auto-edit","yolo","plan"];this.mode=Y.includes($)?$:"default",L1.info(`[AcpSession ${this.id}] Mode set to: ${this.mode}`),this.sendUpdate({sessionUpdate:"current_mode_update",currentModeId:this.mode})}mapModeToPermissionMode(){switch(this.mode){case"yolo":return"yolo";case"auto-edit":return"autoEdit";case"plan":return"plan";case"default":default:return"default"}}shouldAutoApprove($){switch(this.mode){case"yolo":return!0;case"auto-edit":return $==="readonly"||$==="write";case"plan":return $==="readonly";case"default":default:return!1}}async setModel($){if(L1.info(`[AcpSession ${this.id}] Model set to: ${$}`),this.agent)L1.warn(`[AcpSession ${this.id}] Runtime model switching not yet implemented`)}async destroy(){if(this.cancel(),this.agent)await this.agent.destroy(),this.agent=null;a.destroySession(this.id),L1.debug(`[AcpSession ${this.id}] Destroyed`)}resolvePrompt($){let Y=[];for(let Z of $)if(Z.type==="text")Y.push(Z.text);else if(Z.type==="image")Y.push(`[Image: ${Z.mimeType}]`);else if(Z.type==="resource"){let X=Z.resource;if("text"in X)Y.push(`<file path="${X.uri}">
1429
1481
  ${X.text}
1430
1482
  </file>`)}else if(Z.type==="resource_link")Y.push(`[Resource: ${Z.uri}]`);return Y.join(`
1431
- `)}sendUpdate($){let Y={sessionId:this.id,update:$};this.connection.sessionUpdate(Y).catch((Z)=>{L1.warn(`[AcpSession ${this.id}] Failed to send update:`,Z)})}async requestPermission($){let Y=$.kind?.toLowerCase()||"execute";if(this.shouldAutoApprove(Y))return L1.debug(`[AcpSession ${this.id}] Auto-approving ${Y} in mode: ${this.mode}`),{approved:!0};if(this.mode==="plan"&&(Y==="write"||Y==="execute"))return L1.debug(`[AcpSession ${this.id}] Rejecting ${Y} in plan mode`),{approved:!1,reason:"Write and execute operations are not allowed in Plan mode"};let Z=`${Y}:${$.title||"unknown"}`;if(this.sessionApprovals.has(Z))return L1.debug(`[AcpSession ${this.id}] Using cached approval for: ${Z}`),{approved:!0};try{let X=kH(),Q=[];if($.message)Q.push({type:"content",content:{type:"text",text:$.message}});if($.risks&&$.risks.length>0)Q.push({type:"content",content:{type:"text",text:`Risks:
1483
+ `)}sendUpdate($){let Y={sessionId:this.id,update:$};this.connection.sessionUpdate(Y).catch((Z)=>{L1.warn(`[AcpSession ${this.id}] Failed to send update:`,Z)})}async requestPermission($){let Y=$.kind?.toLowerCase()||"execute";if(this.shouldAutoApprove(Y))return L1.debug(`[AcpSession ${this.id}] Auto-approving ${Y} in mode: ${this.mode}`),{approved:!0};if(this.mode==="plan"&&(Y==="write"||Y==="execute"))return L1.debug(`[AcpSession ${this.id}] Rejecting ${Y} in plan mode`),{approved:!1,reason:"Write and execute operations are not allowed in Plan mode"};let Z=`${Y}:${$.title||"unknown"}`;if(this.sessionApprovals.has(Z))return L1.debug(`[AcpSession ${this.id}] Using cached approval for: ${Z}`),{approved:!0};try{let X=hH(),Q=[];if($.message)Q.push({type:"content",content:{type:"text",text:$.message}});if($.risks&&$.risks.length>0)Q.push({type:"content",content:{type:"text",text:`Risks:
1432
1484
  - ${$.risks.join(`
1433
- - `)}`}});let J=this.mapToolKind(Y),q={sessionId:this.id,options:[{optionId:"allow_once",name:"Allow once",kind:"allow_once"},{optionId:"allow_always",name:"Always allow",kind:"allow_always"},{optionId:"reject_once",name:"Deny once",kind:"reject_once"},{optionId:"reject_always",name:"Always deny",kind:"reject_always"}],toolCall:{toolCallId:X,status:"pending",title:$.title||"Permission Required",content:Q,kind:J}},G=(await this.connection.requestPermission(q)).outcome;if(G.outcome==="cancelled")return{approved:!1,reason:"User cancelled the permission request"};let W=G.optionId,U=W==="allow_once"||W==="allow_always";if(W==="allow_always")this.sessionApprovals.add(Z),L1.debug(`[AcpSession ${this.id}] Cached approval for: ${Z}`);return{approved:U,reason:U?void 0:"User denied the operation"}}catch(X){return L1.warn(`[AcpSession ${this.id}] Permission request failed:`,X),{approved:!1,reason:"Permission request failed"}}}mapToolKind($){return{readonly:"read",write:"edit",execute:"execute",read:"read",edit:"edit",delete:"delete",move:"move",search:"search",think:"think",fetch:"fetch"}[$||""]||"other"}}var L1;var eX=R(()=>{J2();s1();N1();Y4();s2();L1=u("Agent")});import{PROTOCOL_VERSION as jH}from"@agentclientprotocol/sdk";import{nanoid as EH}from"nanoid";class Q7{connection;sessions=new Map;clientCapabilities;constructor($){this.connection=$}async initialize($){return g0.info("[BladeAgent] Initializing ACP connection"),g0.debug(`[BladeAgent] Client capabilities: ${JSON.stringify($.clientCapabilities)}`),this.clientCapabilities=$.clientCapabilities,{protocolVersion:jH,agentCapabilities:{loadSession:!1,promptCapabilities:{image:!0,audio:!1,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0}}}}async authenticate($){return}async newSession($){let Y=EH();g0.info(`[BladeAgent] Creating new session: ${Y}`),g0.debug(`[BladeAgent] Session cwd: ${$.cwd||process.cwd()}`);let Z=new X7(Y,$.cwd||process.cwd(),this.connection,this.clientCapabilities);await Z.initialize(),this.sessions.set(Y,Z),g0.info(`[BladeAgent] Session ${Y} created, scheduling available commands update`),Z.sendAvailableCommandsDelayed();let X=V1(),Q=X?.models||[],J=X?.currentModelId||Q[0]?.id,q=Q.map((G)=>({modelId:G.id,name:G.name||G.id,description:G.provider?`Provider: ${G.provider}`:void 0}));return{sessionId:Y,modes:{availableModes:[{id:"default",name:"Default",description:"Ask for confirmation before all file edits and commands"},{id:"auto-edit",name:"Auto Edit",description:"Auto-approve file edits, ask for shell commands"},{id:"yolo",name:"Full Auto",description:"Auto-approve everything without confirmation"},{id:"plan",name:"Plan Only",description:"Read-only mode, no file changes or commands"}],currentModeId:"default"},models:q.length>0?{availableModels:q,currentModelId:J}:void 0}}async prompt($){let Y=this.sessions.get($.sessionId);if(!Y)throw Error(`Session not found: ${$.sessionId}`);return Y.prompt($)}async cancel($){g0.info(`[BladeAgent] Cancel notification received for session: ${$.sessionId}`);let Y=this.sessions.get($.sessionId);if(Y)g0.info("[BladeAgent] Found session, calling session.cancel()"),Y.cancel();else g0.warn(`[BladeAgent] Session not found for cancel: ${$.sessionId}`)}async setSessionMode($){g0.info(`[BladeAgent] Setting session mode: ${$.modeId}`);let Y=this.sessions.get($.sessionId);if(Y)await Y.setMode($.modeId);return{}}async unstable_setSessionModel($){g0.info(`[BladeAgent] Setting session model: ${$.modelId}`);let Y=this.sessions.get($.sessionId);if(Y)await Y.setModel($.modelId);return{}}async destroy(){for(let $ of this.sessions.values())await $.destroy();this.sessions.clear()}}var g0;var $Q=R(()=>{N1();F1();eX();g0=u("Agent")});var YQ={};W7(YQ,{runAcpIntegration:()=>PH});import*as I4 from"@agentclientprotocol/sdk";import{Readable as yH,Writable as vH}from"node:stream";async function PH(){let $=vH.toWeb(process.stdout),Y=yH.toWeb(process.stdin),Z=I4.ndJsonStream($,Y);await new I4.AgentSideConnection((Q)=>new Q7(Q),Z).closed}var ZQ=R(()=>{$Q()});import{render as TH}from"ink";import SH from"react";import CH from"yargs";import{hideBin as QQ}from"yargs/helpers";k$();var F7={debug:{alias:"d",type:"string",describe:'Enable debug mode with optional category filtering (e.g., "agent,ui" or "!chat,!loop")',group:"Debug Options:"},print:{alias:"p",type:"boolean",describe:"Print response and exit (useful for pipes)",group:"Output Options:"},"output-format":{alias:["outputFormat"],type:"string",choices:["text","json","stream-json"],default:"text",describe:"Output format (only works with --print)",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},"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:"},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:($)=>{if($===void 0||$===!0||$==="")return"true";return String($)}},"fork-session":{alias:["forkSession"],type:"boolean",describe:"Create a new session ID when resuming",group:"Session Options:"},model:{type:"string",describe:"Model for the current session",group:"AI Options:"},"fallback-model":{alias:["fallbackModel"],type:"string",describe:"Enable automatic fallback to specified model",group:"AI 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:"}},L2={scriptName:"blade",usage:"$0 [command] [options]",description:O7(),version:f2(),locale:"en",showHelpOnFail:!0,demandCommand:!1,recommendCommands:!0,strict:!1};p2();N1();F1();var C4=u("General"),S7=($)=>{if($.yolo){if($.permissionMode&&$.permissionMode!=="yolo")throw Error("Cannot use both --yolo and --permission-mode with different values");$.permissionMode="yolo"}if(Array.isArray($.allowedTools)&&Array.isArray($.disallowedTools)){let Y=$.allowedTools.filter((Z)=>$.disallowedTools.includes(Z));if(Y.length>0)throw Error(`Tools cannot be both allowed and disallowed: ${Y.join(", ")}`)}},C7=async($)=>{try{let Z=await m1.getInstance().initialize();if(n().config.actions.setConfig(Z),$.debug)C4.info("[CLI] 配置已加载到 Store")}catch(Y){C4.error("[CLI] ❌ 配置初始化失败",Y instanceof Error?Y.message:Y),console.error(`
1485
+ - `)}`}});let J=this.mapToolKind(Y),q={sessionId:this.id,options:[{optionId:"allow_once",name:"Allow once",kind:"allow_once"},{optionId:"allow_always",name:"Always allow",kind:"allow_always"},{optionId:"reject_once",name:"Deny once",kind:"reject_once"},{optionId:"reject_always",name:"Always deny",kind:"reject_always"}],toolCall:{toolCallId:X,status:"pending",title:$.title||"Permission Required",content:Q,kind:J}},K=(await this.connection.requestPermission(q)).outcome;if(K.outcome==="cancelled")return{approved:!1,reason:"User cancelled the permission request"};let W=K.optionId,U=W==="allow_once"||W==="allow_always";if(W==="allow_always")this.sessionApprovals.add(Z),L1.debug(`[AcpSession ${this.id}] Cached approval for: ${Z}`);return{approved:U,reason:U?void 0:"User denied the operation"}}catch(X){return L1.warn(`[AcpSession ${this.id}] Permission request failed:`,X),{approved:!1,reason:"Permission request failed"}}}mapToolKind($){return{readonly:"read",write:"edit",execute:"execute",read:"read",edit:"edit",delete:"delete",move:"move",search:"search",think:"think",fetch:"fetch"}[$||""]||"other"}}var L1;var FQ=D(()=>{K2();s1();B1();G4();e2();L1=l("Agent")});import{PROTOCOL_VERSION as xH}from"@agentclientprotocol/sdk";import{nanoid as pH}from"nanoid";class z7{connection;sessions=new Map;clientCapabilities;constructor($){this.connection=$}async initialize($){return d0.info("[BladeAgent] Initializing ACP connection"),d0.debug(`[BladeAgent] Client capabilities: ${JSON.stringify($.clientCapabilities)}`),this.clientCapabilities=$.clientCapabilities,{protocolVersion:xH,agentCapabilities:{loadSession:!1,promptCapabilities:{image:!0,audio:!1,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0}}}}async authenticate($){return}async newSession($){let Y=pH();d0.info(`[BladeAgent] Creating new session: ${Y}`),d0.debug(`[BladeAgent] Session cwd: ${$.cwd||process.cwd()}`);let Z=new F7(Y,$.cwd||process.cwd(),this.connection,this.clientCapabilities);await Z.initialize(),this.sessions.set(Y,Z),d0.info(`[BladeAgent] Session ${Y} created, scheduling available commands update`),Z.sendAvailableCommandsDelayed();let X=V1(),Q=X?.models||[],J=X?.currentModelId||Q[0]?.id,q=Q.map((K)=>({modelId:K.id,name:K.name||K.id,description:K.provider?`Provider: ${K.provider}`:void 0}));return{sessionId:Y,modes:{availableModes:[{id:"default",name:"Default",description:"Ask for confirmation before all file edits and commands"},{id:"auto-edit",name:"Auto Edit",description:"Auto-approve file edits, ask for shell commands"},{id:"yolo",name:"Full Auto",description:"Auto-approve everything without confirmation"},{id:"plan",name:"Plan Only",description:"Read-only mode, no file changes or commands"}],currentModeId:"default"},models:q.length>0?{availableModels:q,currentModelId:J}:void 0}}async prompt($){let Y=this.sessions.get($.sessionId);if(!Y)throw Error(`Session not found: ${$.sessionId}`);return Y.prompt($)}async cancel($){d0.info(`[BladeAgent] Cancel notification received for session: ${$.sessionId}`);let Y=this.sessions.get($.sessionId);if(Y)d0.info("[BladeAgent] Found session, calling session.cancel()"),Y.cancel();else d0.warn(`[BladeAgent] Session not found for cancel: ${$.sessionId}`)}async setSessionMode($){d0.info(`[BladeAgent] Setting session mode: ${$.modeId}`);let Y=this.sessions.get($.sessionId);if(Y)await Y.setMode($.modeId);return{}}async unstable_setSessionModel($){d0.info(`[BladeAgent] Setting session model: ${$.modelId}`);let Y=this.sessions.get($.sessionId);if(Y)await Y.setModel($.modelId);return{}}async destroy(){for(let $ of this.sessions.values())await $.destroy();this.sessions.clear()}}var d0;var zQ=D(()=>{B1();z1();FQ();d0=l("Agent")});var _Q={};L7(_Q,{runAcpIntegration:()=>dH});import*as T4 from"@agentclientprotocol/sdk";import{Readable as gH,Writable as mH}from"node:stream";async function dH(){let $=mH.toWeb(process.stdout),Y=gH.toWeb(process.stdin),Z=T4.ndJsonStream($,Y);await new T4.AgentSideConnection((Q)=>new z7(Q),Z).closed}var NQ=D(()=>{zQ()});import{render as uH}from"ink";import cH from"react";import lH from"yargs";import{hideBin as wQ}from"yargs/helpers";y$();var D7={debug:{alias:"d",type:"string",describe:'Enable debug mode with optional category filtering (e.g., "agent,ui" or "!chat,!loop")',group:"Debug Options:"},print:{alias:"p",type:"boolean",describe:"Print response and exit (useful for pipes)",group:"Output Options:"},"output-format":{alias:["outputFormat"],type:"string",choices:["text","json","stream-json"],default:"text",describe:"Output format (only works with --print)",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},"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:"},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:($)=>{if($===void 0||$===!0||$==="")return"true";return String($)}},"fork-session":{alias:["forkSession"],type:"boolean",describe:"Create a new session ID when resuming",group:"Session Options:"},model:{type:"string",describe:"Model for the current session",group:"AI Options:"},"fallback-model":{alias:["fallbackModel"],type:"string",describe:"Enable automatic fallback to specified model",group:"AI 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:"}},L2={scriptName:"blade",usage:"$0 [command] [options]",description:R7(),version:x2(),locale:"en",showHelpOnFail:!0,demandCommand:!1,recommendCommands:!0,strict:!1};m2();B1();z1();var d4=l("General"),c7=($)=>{if($.yolo){if($.permissionMode&&$.permissionMode!=="yolo")throw Error("Cannot use both --yolo and --permission-mode with different values");$.permissionMode="yolo"}if(Array.isArray($.allowedTools)&&Array.isArray($.disallowedTools)){let Y=$.allowedTools.filter((Z)=>$.disallowedTools.includes(Z));if(Y.length>0)throw Error(`Tools cannot be both allowed and disallowed: ${Y.join(", ")}`)}},l7=async($)=>{try{let Z=await u1.getInstance().initialize();if(s().config.actions.setConfig(Z),$.debug)d4.info("[CLI] 配置已加载到 Store")}catch(Y){d4.error("[CLI] ❌ 配置初始化失败",Y instanceof Error?Y.message:Y),console.error(`
1434
1486
  ❌ 配置初始化失败
1435
1487
  `),console.error("原因:",Y instanceof Error?Y.message:"未知错误"),console.error(`
1436
1488
  请检查:`),console.error(" 1. 配置文件格式是否正确 (~/.blade/config.json)"),console.error(" 2. 是否需要运行 blade 进行首次配置"),console.error(` 3. 配置文件权限是否正确
1437
- `),process.exit(1)}if($.continue&&$.resume)throw Error("Cannot use both --continue and --resume flags simultaneously")},f7=($)=>{if($.outputFormat&&$.outputFormat!=="text"&&!$.print)throw Error("--output-format can only be used with --print flag");if($.inputFormat==="stream-json"&&$.print)C4.warn("⚠️ Warning: stream-json input format may not work as expected with --print")};p2();var h7={command:"doctor",describe:"Check the health of your Blade installation",handler:async()=>{console.log(`\uD83D\uDD0D Running Blade health check...
1438
- `);let $=0;try{await m1.getInstance().initialize(),console.log("✅ Configuration: OK")}catch(X){console.log("❌ Configuration: FAILED"),console.log(` Error: ${X instanceof Error?X.message:"未知错误"}`),$++}let Y=process.version;if(parseInt(Y.slice(1).split(".")[0])>=18)console.log(`✅ Node.js version: ${Y}`);else console.log(`⚠️ Node.js version: ${Y} (recommended: v18+)`),$++;try{let X=await import("fs/promises"),Q=process.cwd();await X.access(Q,(await import("fs")).constants.R_OK|(await import("fs")).constants.W_OK),console.log("✅ File system permissions: OK")}catch(X){console.log("❌ File system permissions: FAILED"),console.log(" Error: Cannot read/write in current directory"),$++}try{await import("ink"),console.log("✅ Dependencies: OK")}catch(X){console.log("❌ Dependencies: FAILED"),console.log(" Error: Missing required dependencies"),$++}if(console.log(`
1439
- \uD83D\uDCCA Health Check Summary:`),$===0)console.log("\uD83C\uDF89 All checks passed! Blade is ready to use.");else console.log(`⚠️ Found ${$} issue(s). Please resolve them for optimal performance.`),process.exit(1)}};var x7={command:"install [target]",describe:"Install Blade native build. Use [target] to specify version (stable, latest, or specific version)",builder:($)=>{return $.positional("target",{describe:"Version to install",type:"string",default:"stable",choices:["stable","latest"]}).option("force",{type:"boolean",describe:"Force reinstall",default:!1}).example([["$0 install","Install stable version"],["$0 install latest","Install latest version"],["$0 install --force","Force reinstall stable version"]])},handler:async($)=>{console.log(`\uD83D\uDCE6 Installing Blade ${$.target}...`);try{if($.force)console.log("\uD83D\uDD04 Force reinstall enabled");console.log("⬇️ Downloading..."),console.log("\uD83D\uDD27 Installing..."),console.log("✅ Installation completed successfully")}catch(Y){console.error(`❌ Installation failed: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}};u2();d2();F1();import t7 from"os";import B6 from"path";function iQ(){console.log(`
1489
+ `),process.exit(1)}if($.continue&&$.resume)throw Error("Cannot use both --continue and --resume flags simultaneously")},i7=($)=>{if($.outputFormat&&$.outputFormat!=="text"&&!$.print)throw Error("--output-format can only be used with --print flag");if($.inputFormat==="stream-json"&&$.print)d4.warn("⚠️ Warning: stream-json input format may not work as expected with --print")};m2();var r7={command:"doctor",describe:"Check the health of your Blade installation",handler:async()=>{console.log(`\uD83D\uDD0D Running Blade health check...
1490
+ `);let $=0;try{await u1.getInstance().initialize(),console.log("✅ Configuration: OK")}catch(X){console.log("❌ Configuration: FAILED"),console.log(` Error: ${X instanceof Error?X.message:"未知错误"}`),$++}let Y=process.version;if(parseInt(Y.slice(1).split(".")[0])>=18)console.log(`✅ Node.js version: ${Y}`);else console.log(`⚠️ Node.js version: ${Y} (recommended: v18+)`),$++;try{let X=await import("fs/promises"),Q=process.cwd();await X.access(Q,(await import("fs")).constants.R_OK|(await import("fs")).constants.W_OK),console.log("✅ File system permissions: OK")}catch(X){console.log("❌ File system permissions: FAILED"),console.log(" Error: Cannot read/write in current directory"),$++}try{await import("ink"),console.log("✅ Dependencies: OK")}catch(X){console.log("❌ Dependencies: FAILED"),console.log(" Error: Missing required dependencies"),$++}if(console.log(`
1491
+ \uD83D\uDCCA Health Check Summary:`),$===0)console.log("\uD83C\uDF89 All checks passed! Blade is ready to use.");else console.log(`⚠️ Found ${$} issue(s). Please resolve them for optimal performance.`),process.exit(1)}};var a7={command:"install [target]",describe:"Install Blade native build. Use [target] to specify version (stable, latest, or specific version)",builder:($)=>{return $.positional("target",{describe:"Version to install",type:"string",default:"stable",choices:["stable","latest"]}).option("force",{type:"boolean",describe:"Force reinstall",default:!1}).example([["$0 install","Install stable version"],["$0 install latest","Install latest version"],["$0 install --force","Force reinstall stable version"]])},handler:async($)=>{console.log(`\uD83D\uDCE6 Installing Blade ${$.target}...`);try{if($.force)console.log("\uD83D\uDD04 Force reinstall enabled");console.log("⬇️ Downloading..."),console.log("\uD83D\uDD27 Installing..."),console.log("✅ Installation completed successfully")}catch(Y){console.error(`❌ Installation failed: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}};l2();c2();z1();import K3 from"os";import R6 from"path";function qJ(){console.log(`
1440
1492
  blade mcp
1441
1493
  `),console.log(`管理 MCP 服务器
1442
1494
  `),console.log("Commands:"),console.log(" blade mcp add <name> <commandOrUrl> [args...] 添加 MCP 服务器"),console.log(" blade mcp remove <name> 删除 MCP 服务器 [aliases: rm]"),console.log(" blade mcp list 列出所有 MCP 服务器并检查健康状态 [aliases: ls]"),console.log(" blade mcp get <name> 获取服务器详情"),console.log(` blade mcp add-json <name> <json> 从 JSON 字符串添加服务器
1443
1495
  `),console.log("Options:"),console.log(` -h, --help 显示帮助信息 [boolean]
1444
1496
  `),console.log("Examples:"),console.log(" blade mcp list"),console.log(" blade mcp add github npx -y @modelcontextprotocol/server-github"),console.log(" blade mcp add api --transport http http://localhost:3000"),console.log(` blade mcp remove github
1445
1497
  `),console.log(`使用 blade mcp <command> --help 查看各子命令的详细帮助
1446
- `)}function rQ($){return $.reduce((Y,Z)=>{let[X,...Q]=Z.split("=");return Y[X]=Q.join("="),Y},{})}function aQ($){return $.reduce((Y,Z)=>{let[X,...Q]=Z.split(":");return Y[X.trim()]=Q.join(":").trim(),Y},{})}var nQ={command:"add <name> [commandOrUrl] [args...]",describe:"添加 MCP 服务器",builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).positional("commandOrUrl",{type:"string",describe:"stdio: 命令 | http/sse: URL"}).positional("args",{type:"string",array:!0,describe:"stdio 命令参数",default:[]}).option("transport",{alias:"t",choices:["stdio","sse","http"],default:"stdio",describe:"传输类型"}).option("env",{alias:"e",type:"array",describe:"环境变量 (KEY=value)"}).option("header",{alias:"H",type:"array",describe:"HTTP 头 (Key: Value)"}).option("timeout",{type:"number",describe:"超时时间(毫秒)"}).option("global",{alias:"g",type:"boolean",default:!1,describe:"存储到全局配置(~/.blade/config.json)"}).example([["$0 mcp add github -- npx -y @modelcontextprotocol/server-github","Add stdio server (recommended)"],["$0 mcp add github npx @modelcontextprotocol/server-github -e GITHUB_TOKEN=xxx","Add stdio server with env"],['$0 mcp add api --transport http http://localhost:3000 -H "Auth: Bearer token"',"Add HTTP server"]])},handler:async($)=>{try{let{name:Y,commandOrUrl:Z,args:X,transport:Q,env:J,header:q,timeout:K}=$,G=$.global===!0;if($["--"]&&$["--"].length>0)Z=$["--"][0],X=$["--"].slice(1);if(!Y||!Z)console.error("❌ 缺少必需参数: name 和 commandOrUrl"),console.log(`
1498
+ `)}function GJ($){return $.reduce((Y,Z)=>{let[X,...Q]=Z.split("=");return Y[X]=Q.join("="),Y},{})}function KJ($){return $.reduce((Y,Z)=>{let[X,...Q]=Z.split(":");return Y[X.trim()]=Q.join(":").trim(),Y},{})}var WJ={command:"add <name> [commandOrUrl] [args...]",describe:"添加 MCP 服务器",builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).positional("commandOrUrl",{type:"string",describe:"stdio: 命令 | http/sse: URL"}).positional("args",{type:"string",array:!0,describe:"stdio 命令参数",default:[]}).option("transport",{alias:"t",choices:["stdio","sse","http"],default:"stdio",describe:"传输类型"}).option("env",{alias:"e",type:"array",describe:"环境变量 (KEY=value)"}).option("header",{alias:"H",type:"array",describe:"HTTP 头 (Key: Value)"}).option("timeout",{type:"number",describe:"超时时间(毫秒)"}).option("global",{alias:"g",type:"boolean",default:!1,describe:"存储到全局配置(~/.blade/config.json)"}).example([["$0 mcp add github -- npx -y @modelcontextprotocol/server-github","Add stdio server (recommended)"],["$0 mcp add github npx @modelcontextprotocol/server-github -e GITHUB_TOKEN=xxx","Add stdio server with env"],['$0 mcp add api --transport http http://localhost:3000 -H "Auth: Bearer token"',"Add HTTP server"]])},handler:async($)=>{try{let{name:Y,commandOrUrl:Z,args:X,transport:Q,env:J,header:q,timeout:G}=$,K=$.global===!0;if($["--"]&&$["--"].length>0)Z=$["--"][0],X=$["--"].slice(1);if(!Y||!Z)console.error("❌ 缺少必需参数: name 和 commandOrUrl"),console.log(`
1447
1499
  \uD83D\uDCA1 用法:`),console.log(" blade mcp add <name> <command> [args...]"),console.log(" blade mcp add <name> -- <command> [args...]"),console.log(`
1448
- 示例:`),console.log(" blade mcp add github npx -y @modelcontextprotocol/server-github"),console.log(" blade mcp add github -- npx -y @modelcontextprotocol/server-github"),process.exit(1);let W={type:Q};if(Q==="stdio"){if(W.command=Z,W.args=X||[],J&&Array.isArray(J))W.env=rQ(J)}else if(W.url=Z,q&&Array.isArray(q))W.headers=aQ(q);if(K)W.timeout=K;await U1().addMcpServer(Y,W,{scope:G?"global":"project"});let U=G?B6.join(t7.homedir(),".blade","config.json"):B6.join(process.cwd(),".blade","config.json");console.log(`✅ MCP 服务器 "${Y}" 已添加`),console.log(` 配置文件: ${U}`)}catch(Y){console.error(`❌ 添加失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},oQ={command:"remove <name>",describe:"删除 MCP 服务器",aliases:["rm"],builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).option("global",{alias:"g",type:"boolean",default:!1,describe:"从全局配置删除(~/.blade/config.json)"}).example([["$0 mcp remove github","Remove the specified MCP server"]])},handler:async($)=>{try{let Y=X0(),Z=$.global===!0;if(!Y[$.name])console.error(`❌ 服务器 "${$.name}" 不存在`),process.exit(1);await U1().removeMcpServer($.name,{scope:Z?"global":"project"}),console.log(`✅ MCP 服务器 "${$.name}" 已删除`)}catch(Y){console.error(`❌ 删除失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},sQ={command:"list",describe:"列出所有 MCP 服务器并检查健康状态",aliases:["ls"],handler:async()=>{try{let $=X0();if(console.log(""),Object.keys($).length===0){console.log("暂无配置的 MCP 服务器");return}console.log(`检查 MCP 服务器健康状态...
1449
- `);let Y=C1.getInstance(),Z=Object.entries($).map(async([Q,J])=>{try{let q=Y.getServerStatus(Q);if(!q)await Y.registerServer(Q,J),q=Y.getServerStatus(Q);else if(q.status==="disconnected")await Y.connectServer(Q);return{name:Q,config:J,serverInfo:q}}catch(q){return{name:Q,config:J,serverInfo:null,error:q}}}),X=await Promise.all(Z);for(let{name:Q,config:J,serverInfo:q,error:K}of X){let G=q?.status||"disconnected",W=G==="connected"?"✓":"✗",U=G==="connected"?"Connected":"Failed";if(console.log(`${Q}: ${J.type==="stdio"?J.command:J.url} - ${W} ${U}`),K&&G!=="connected")console.log(` 错误: ${K instanceof Error?K.message:String(K)}`)}console.log("");for(let{name:Q}of X)try{await Y.unregisterServer(Q)}catch(J){}process.exit(0)}catch($){console.error(`❌ 列表获取失败: ${$ instanceof Error?$.message:"未知错误"}`),process.exit(1)}}},tQ={command:"get <name>",describe:"获取服务器详情",builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).example([["$0 mcp get github","Get details of the specified server"]])},handler:async($)=>{try{let Z=X0()[$.name];if(!Z)console.error(`❌ 服务器 "${$.name}" 不存在`),process.exit(1);console.log(`
1500
+ 示例:`),console.log(" blade mcp add github npx -y @modelcontextprotocol/server-github"),console.log(" blade mcp add github -- npx -y @modelcontextprotocol/server-github"),process.exit(1);let W={type:Q};if(Q==="stdio"){if(W.command=Z,W.args=X||[],J&&Array.isArray(J))W.env=GJ(J)}else if(W.url=Z,q&&Array.isArray(q))W.headers=KJ(q);if(G)W.timeout=G;await H1().addMcpServer(Y,W,{scope:K?"global":"project"});let U=K?R6.join(K3.homedir(),".blade","config.json"):R6.join(process.cwd(),".blade","config.json");console.log(`✅ MCP 服务器 "${Y}" 已添加`),console.log(` 配置文件: ${U}`)}catch(Y){console.error(`❌ 添加失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},UJ={command:"remove <name>",describe:"删除 MCP 服务器",aliases:["rm"],builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).option("global",{alias:"g",type:"boolean",default:!1,describe:"从全局配置删除(~/.blade/config.json)"}).example([["$0 mcp remove github","Remove the specified MCP server"]])},handler:async($)=>{try{let Y=Q0(),Z=$.global===!0;if(!Y[$.name])console.error(`❌ 服务器 "${$.name}" 不存在`),process.exit(1);await H1().removeMcpServer($.name,{scope:Z?"global":"project"}),console.log(`✅ MCP 服务器 "${$.name}" 已删除`)}catch(Y){console.error(`❌ 删除失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},HJ={command:"list",describe:"列出所有 MCP 服务器并检查健康状态",aliases:["ls"],handler:async()=>{try{let $=Q0();if(console.log(""),Object.keys($).length===0){console.log("暂无配置的 MCP 服务器");return}console.log(`检查 MCP 服务器健康状态...
1501
+ `);let Y=f1.getInstance(),Z=Object.entries($).map(async([Q,J])=>{try{let q=Y.getServerStatus(Q);if(!q)await Y.registerServer(Q,J),q=Y.getServerStatus(Q);else if(q.status==="disconnected")await Y.connectServer(Q);return{name:Q,config:J,serverInfo:q}}catch(q){return{name:Q,config:J,serverInfo:null,error:q}}}),X=await Promise.all(Z);for(let{name:Q,config:J,serverInfo:q,error:G}of X){let K=q?.status||"disconnected",W=K==="connected"?"✓":"✗",U=K==="connected"?"Connected":"Failed";if(console.log(`${Q}: ${J.type==="stdio"?J.command:J.url} - ${W} ${U}`),G&&K!=="connected")console.log(` 错误: ${G instanceof Error?G.message:String(G)}`)}console.log("");for(let{name:Q}of X)try{await Y.unregisterServer(Q)}catch(J){}process.exit(0)}catch($){console.error(`❌ 列表获取失败: ${$ instanceof Error?$.message:"未知错误"}`),process.exit(1)}}},OJ={command:"get <name>",describe:"获取服务器详情",builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).example([["$0 mcp get github","Get details of the specified server"]])},handler:async($)=>{try{let Z=Q0()[$.name];if(!Z)console.error(`❌ 服务器 "${$.name}" 不存在`),process.exit(1);console.log(`
1450
1502
  服务器: ${$.name}
1451
- `),console.log(JSON.stringify(Z,null,2))}catch(Y){console.error(`❌ 获取失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},eQ={command:"add-json <name> <json>",describe:"从 JSON 字符串添加服务器",builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).positional("json",{type:"string",describe:"JSON 配置字符串",demandOption:!0}).option("global",{alias:"g",type:"boolean",default:!1,describe:"存储到全局配置(~/.blade/config.json)"}).example([[`$0 mcp add-json my-server '{"type":"stdio","command":"npx","args":["-y","@example/server"]}'`,"Add server from JSON string"]])},handler:async($)=>{try{let Y=JSON.parse($.json),Z=$.global===!0;if(!Y.type)throw Error('配置必须包含 "type" 字段');await U1().addMcpServer($.name,Y,{scope:Z?"global":"project"});let X=Z?B6.join(t7.homedir(),".blade","config.json"):B6.join(process.cwd(),".blade","config.json");console.log(`✅ MCP 服务器 "${$.name}" 已添加`),console.log(` 配置文件: ${X}`)}catch(Y){console.error(`❌ 添加失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},e7={command:"mcp",describe:"管理 MCP 服务器",builder:($)=>{return $.command(nQ).command(oQ).command(sQ).command(tQ).command(eQ).demandCommand(0).help(!1).option("help",{alias:"h",type:"boolean",describe:"显示帮助信息"})},handler:($)=>{let Y=["add","remove","list","ls","get","add-json"];if(!$._.some((X)=>Y.includes(X))||$.help)iQ(),process.exit(0)}};J2();function MK($){return $.command("* [message]","Print response and exit (useful for pipes)",(Y)=>{return Y.positional("message",{describe:"Message to process",type:"string"}).option("p",{alias:"print",describe:"Print response and exit (useful for pipes)",type:"boolean"}).option("output-format",{describe:'Output format: "text", "json", "stream-json"',type:"string",default:"text"}).option("include-partial-messages",{describe:"Include partial message chunks as they arrive",type:"boolean"}).option("input-format",{describe:'Input format: "text", "stream-json"',type:"string",default:"text"}).option("model",{describe:"Model for the current session",type:"string"}).option("append-system-prompt",{describe:"Append a system prompt to the default system prompt",type:"string"}).option("system-prompt",{describe:"Replace the default system prompt",type:"string"}).option("max-turns",{alias:["maxTurns"],describe:"Maximum conversation turns (-1: unlimited, N>0: limit to N turns)",type:"number"})},async(Y)=>{if(!Y.print)return;try{let Z=await E1.create({systemPrompt:Y.systemPrompt,appendSystemPrompt:Y.appendSystemPrompt,maxTurns:Y.maxTurns}),X="",Q=Y._?.[0];if(Q&&typeof Q==="string")X=Q;else if(!process.stdin.isTTY){let q=[];for await(let K of process.stdin)q.push(K);X=Buffer.concat(q).toString("utf-8").trim()}else X="Hello";let J;if(Y.appendSystemPrompt)J=await Z.chatWithSystem(Y.appendSystemPrompt,X);else J=await Z.chat(X,{messages:[],userId:"cli-user",sessionId:`print-${Date.now()}`,workspaceRoot:process.cwd()});if(Y.outputFormat==="json")console.log(JSON.stringify({response:J,input:X,model:Y.model,timestamp:new Date().toISOString()},null,2));else if(Y.outputFormat==="stream-json")console.log(JSON.stringify({type:"response",content:J}));else console.log(J);process.exit(0)}catch(Z){console.error(`Error: ${Z instanceof Error?Z.message:"未知错误"}`),process.exit(1)}})}async function OY(){if(process.argv.slice(2).findIndex((Z)=>Z==="--print"||Z==="-p")===-1)return!1;try{let Z=(await import("yargs")).default,{hideBin:X}=await import("yargs/helpers"),Q=Z(X(process.argv)).scriptName("blade").strict(!1);return MK(Q),await Q.parse(),!0}catch(Z){console.error(`Print mode error: ${Z instanceof Error?Z.message:"未知错误"}`),process.exit(1)}}import{execSync as PK}from"child_process";import*as k2 from"fs/promises";import*as G2 from"path";import zY from"semver";import{fileURLToPath as IK}from"url";var N9="blade-code",kK="https://cdn.jsdelivr.net/npm/blade-code@latest/CHANGELOG.md",FY=G2.join(process.env.HOME||process.env.USERPROFILE||".",".blade"),_Y=G2.join(FY,"version-cache.json"),jK=3600000,EK=`https://registry.npmjs.org/${N9}/latest`;async function yK(){try{if(process.env.BLADE_VERSION)return process.env.BLADE_VERSION;let $=IK(import.meta.url),Y=G2.dirname($),Z=[G2.join(Y,"..","..","package.json"),G2.join(Y,"..","package.json"),G2.join(process.cwd(),"package.json")];for(let X of Z)try{let Q=await k2.readFile(X,"utf-8"),J=JSON.parse(Q);if(J.name===N9&&J.version)return J.version}catch{}return"unknown"}catch{return"unknown"}}async function BY(){try{let $=await k2.readFile(_Y,"utf-8"),Y=JSON.parse($);if(Date.now()-Y.checkedAt<jK)return Y;return{...Y,checkedAt:0}}catch{return null}}async function NY($){try{await k2.mkdir(FY,{recursive:!0}),await k2.writeFile(_Y,JSON.stringify($,null,2))}catch{}}async function vK(){try{let $=new AbortController,Y=setTimeout(()=>$.abort(),5000),Z=await fetch(EK,{signal:$.signal,headers:{Accept:"application/json"}});if(clearTimeout(Y),!Z.ok)return null;return(await Z.json()).version||null}catch{return null}}async function w9($=!1){let Y=await yK(),Z=kK;if(Y==="unknown")return{currentVersion:Y,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:Z,error:"Unable to determine current version"};let X=await BY(),Q=X?.skipUntilVersion,J=null;if(!$&&X&&X.checkedAt>0)J=X.latestVersion;else if(J=await vK(),J)await NY({latestVersion:J,checkedAt:Date.now(),skipUntilVersion:Q});if(!J)return{currentVersion:Y,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:Z,error:"Unable to check for updates"};let q=zY.gt(J,Y),K=q;if(q&&Q)K=zY.gt(J,Q);return{currentVersion:Y,latestVersion:J,hasUpdate:q,shouldPrompt:K,releaseNotesUrl:Z}}async function wY($){let Y=await BY();await NY({latestVersion:Y?.latestVersion||$,checkedAt:Y?.checkedAt||Date.now(),skipUntilVersion:$})}function L9(){return`npm install -g ${N9}@latest`}async function LY(){let{spawn:$}=await import("child_process");return new Promise((Y)=>{let Z=L9(),X=$(Z,{stdio:"inherit",shell:!0});X.on("close",(Q)=>{if(Q===0)Y({success:!0,message:"✅ 升级成功!请重新启动 blade。"});else Y({success:!1,message:`❌ 升级失败 (exit code: ${Q})`})}),X.on("error",(Q)=>{Y({success:!1,message:`❌ 升级失败: ${Q.message}`})})})}async function AY(){try{let $=await w9();return $.shouldPrompt?$:null}catch{return null}}var RY={command:"update",describe:"Check for updates and install if available",handler:async()=>{console.log("\uD83D\uDD0D Checking for updates...");try{let $=await w9(!0);if(console.log(`\uD83D\uDCE6 Current version: ${$.currentVersion}`),$.error){console.log(`⚠️ ${$.error}`);return}if($.latestVersion)console.log(`\uD83D\uDCE6 Latest version: ${$.latestVersion}`);if($.hasUpdate&&$.latestVersion){console.log(""),console.log(`\x1B[33m⚠️ Update available: ${$.currentVersion} → ${$.latestVersion}\x1B[0m`),console.log(""),console.log("\uD83D\uDE80 Updating...");try{PK("npm install -g blade-code@latest --registry https://registry.npmjs.org",{stdio:"inherit"}),console.log(""),console.log("✅ Update complete!")}catch(Y){console.error("❌ Update failed. Please run manually:"),console.error(" npm install -g blade-code@latest"),process.exit(1)}}else console.log("✅ You are running the latest version of Blade")}catch($){console.error(`❌ Failed to check for updates: ${$ instanceof Error?$.message:"未知错误"}`),process.exit(1)}}};N1();N1();var a0=u("Service");class G${static instance=null;cleanupHandlers=[];isShuttingDown=!1;initialized=!1;constructor(){}static getInstance(){if(!G$.instance)G$.instance=new G$;return G$.instance}initialize(){if(this.initialized){a0.debug("[GracefulShutdown] 已初始化,跳过重复初始化");return}if(process.on("uncaughtException",($)=>{this.handleFatalError("uncaughtException",$)}),process.on("unhandledRejection",($)=>{let Y=$ instanceof Error?$:Error(String($));this.handleFatalError("unhandledRejection",Y)}),process.on("SIGTERM",()=>{a0.info("[GracefulShutdown] 收到 SIGTERM 信号"),this.shutdown("SIGTERM",0)}),process.env.BLADE_NON_INTERACTIVE==="true")process.on("SIGINT",()=>{a0.info("[GracefulShutdown] 收到 SIGINT 信号(非交互模式)"),this.shutdown("SIGINT",0)});this.initialized=!0,a0.debug("[GracefulShutdown] 全局错误处理器已初始化")}registerCleanup($){return this.cleanupHandlers.push($),a0.debug(`[GracefulShutdown] 注册清理函数,当前共 ${this.cleanupHandlers.length} 个`),()=>{let Y=this.cleanupHandlers.indexOf($);if(Y!==-1)this.cleanupHandlers.splice(Y,1),a0.debug(`[GracefulShutdown] 取消注册清理函数,剩余 ${this.cleanupHandlers.length} 个`)}}handleFatalError($,Y){if(this.isShuttingDown){console.error(`[GracefulShutdown] 退出过程中发生额外错误 (${$}):`,Y);return}if(console.error(""),console.error("═".repeat(60)),console.error(`\uD83D\uDCA5 发生未捕获的错误 (${$})`),console.error("═".repeat(60)),console.error(""),console.error("错误信息:",Y.message),console.error(""),Y.stack)console.error("堆栈跟踪:"),console.error(Y.stack);console.error(""),console.error("═".repeat(60)),console.error(""),this.shutdown($,1)}async shutdown($,Y=0){if(this.isShuttingDown){a0.debug("[GracefulShutdown] 已在退出过程中,跳过重复退出");return}this.isShuttingDown=!0,a0.info(`[GracefulShutdown] 开始优雅退出 (原因: ${$})`);let Z=5000,X=new Promise((Q,J)=>{setTimeout(()=>{J(Error(`清理超时 (${Z}ms)`))},Z)});try{let Q=this.runCleanupHandlers();await Promise.race([Q,X]),a0.info("[GracefulShutdown] 所有清理函数执行完成")}catch(Q){console.error("[GracefulShutdown] 清理过程中发生错误:",Q)}finally{setTimeout(()=>{process.exit(Y)},100)}}async runCleanupHandlers(){let $=[...this.cleanupHandlers].reverse();for(let Y of $)try{let Z=Y();if(Z instanceof Promise)await Z}catch(Z){console.error("[GracefulShutdown] 清理函数执行失败:",Z)}}isExiting(){return this.isShuttingDown}reset(){this.isShuttingDown=!1,this.cleanupHandlers=[],this.initialized=!1}}var j2=()=>{return G$.getInstance()},bY=($)=>{return j2().registerCleanup($)},VY=()=>{j2().initialize()};Z$();p2();g6();u2();import{useMemoizedFn as sX}from"ahooks";import{useEffect as MH,useState as Z7}from"react";F1();Y$();s1();N1();c6();import{useMemoizedFn as a1}from"ahooks";import{Box as G6,useApp as AH}from"ink";import{useEffect as T2,useRef as b4}from"react";import{useShallow as dA}from"zustand/react/shallow";F1();F1();import{useStore as TK}from"zustand";function Q1($){return TK(v$,$)}s1();var SK=[],IY=()=>Q1(($)=>$.session.sessionId),l6=()=>Q1(($)=>$.session.messages),kY=()=>Q1(($)=>$.session.clearCount),W2=()=>Q1(($)=>$.session.isThinking),jY=()=>Q1(($)=>$.session.isCompacting);var W$=()=>Q1(($)=>$.session.actions);var EY=()=>Q1(($)=>{let{inputTokens:Y,maxContextTokens:Z}=$.session.tokenUsage;if(Z<=0)return 100;let X=Math.max(0,100-Y/Z*100);return Math.round(X)});var yY=()=>Q1(($)=>$.app.initializationStatus),vY=()=>Q1(($)=>$.app.initializationError),i6=()=>Q1(($)=>$.app.activeModal),PY=()=>Q1(($)=>$.app.todos),TY=()=>Q1(($)=>$.app.modelEditorTarget),SY=()=>Q1(($)=>$.app.sessionSelectorData),CY=()=>Q1(($)=>$.app.awaitingSecondCtrlC),U2=()=>Q1(($)=>$.app.actions),r6=()=>Q1(($)=>$.app.initializationStatus==="ready");var fY=()=>Q1(($)=>$.app.todos.length>0);var U$=()=>Q1(($)=>$.config.config?.permissionMode||"default"),hY=()=>Q1(($)=>$.config.config?.models??SK),a6=()=>Q1(($)=>{let Y=$.config.config;if(!Y)return;let Z=Y.currentModelId;return Y.models.find((Q)=>Q.id===Z)??Y.models[0]}),xY=()=>Q1(($)=>$.config.config?.currentModelId);var q0=()=>Q1(($)=>$.focus.currentFocus);var pY=()=>Q1(($)=>$.focus.actions);var gY=()=>Q1(($)=>$.command.isProcessing);var mY=()=>Q1(($)=>$.command.actions),dY=()=>Q1(($)=>$.command.pendingCommands);var uY=()=>Q1(($)=>$.app.thinkingModeEnabled),cY=()=>Q1(($)=>$.session.currentThinkingContent),lY=()=>Q1(($)=>$.session.thinkingExpanded);F1();N1();Y4();import{useMemoizedFn as I9}from"ahooks";import{useEffect as yG,useRef as vG}from"react";F1();J2();import{useMemoizedFn as PZ}from"ahooks";import{useRef as EG}from"react";function TZ($){let Y=EG(void 0),Z=PZ(async()=>{let Q=await E1.create({systemPrompt:$.systemPrompt,appendSystemPrompt:$.appendSystemPrompt,maxTurns:$.maxTurns});return Y.current=Q,Q}),X=PZ(()=>{if(Y.current)Y.current=void 0});return{agentRef:Y,createAgent:Z,cleanupAgent:X}}var PG=u("UI");function TG($,Y,Z,X){switch($){case"show_theme_selector":return Z.setActiveModal("themeSelector"),!0;case"show_model_selector":return Z.setActiveModal("modelSelector"),!0;case"show_model_add_wizard":return Z.setActiveModal("modelAddWizard"),!0;case"show_permissions_manager":return Z.setActiveModal("permissionsManager"),!0;case"show_agents_manager":return Z.setActiveModal("agentsManager"),!0;case"show_agent_creation_wizard":return Z.setActiveModal("agentCreationWizard"),!0;case"show_session_selector":{let Q=Y?.sessions;return Z.showSessionSelector(Q),!0}case"clear_screen":return X.clearMessages(),X.setError(null),X.resetTokenUsage(),Z.setTodos([]),!0;case"exit_application":return process.exit(0),!0;default:return!1}}var SZ=($,Y,Z,X)=>{let Q=gY(),J=l6(),q=IY(),K=U$(),G=W$(),W=U2(),U=mY(),H=vG(!1),{createAgent:O,cleanupAgent:z}=TZ({systemPrompt:$,appendSystemPrompt:Y,maxTurns:X});yG(()=>{return()=>{z()}},[z]);let _=I9(()=>{if(!Q)return;if(!H.current)G.addAssistantMessage("✋ 任务已停止"),H.current=!0;U.abort(),W.setTodos([])}),F=I9(async(w)=>{try{if(e6(w)){await H6();let L=U.createAbortController(),V={cwd:process.cwd(),signal:L.signal},j=await $4(w,V);if(j.message){if(TG(j.message,j.data,W,G))return{success:!0}}if(!j.success&&j.error)return G.addAssistantMessage(`❌ ${j.error}`),{success:j.success,output:j.message,error:j.error,metadata:j.data};let m=j.message;if(j.success&&typeof m==="string"&&m.trim()!=="")G.addAssistantMessage(m);return{success:j.success,output:j.message,error:j.error,metadata:j.data}}G.addUserMessage(w);let B=await O(),A=U.createAbortController(),D={messages:J.map((L)=>({role:L.role,content:L.content})),userId:"cli-user",sessionId:q,workspaceRoot:process.cwd(),signal:A.signal,confirmationHandler:Z,permissionMode:K},I={onThinking:(L)=>{G.setCurrentThinkingContent(L)},onContent:(L)=>{if(L.trim())G.addAssistantMessage(L),G.setCurrentThinkingContent(null)},onToolStart:(L)=>{if(L.type!=="function")return;if(L.function.name==="TodoWrite")return;try{let V=JSON.parse(L.function.arguments),j=a$(L.function.name,V);G.addToolMessage(j,{toolName:L.function.name,phase:"start",summary:j,params:V})}catch(V){PG.error("[useCommandHandler] onToolStart error:",V)}},onToolResult:async(L,V)=>{if(L.type!=="function")return;if(!V?.metadata?.summary)return;let j=bZ(L.function.name,V)?V.displayContent:void 0;G.addToolMessage(V.metadata.summary,{toolName:L.function.name,phase:"complete",summary:V.metadata.summary,detail:j})},onTokenUsage:(L)=>{G.updateTokenUsage(L)},onCompacting:(L)=>{G.setCompacting(L)},onTurnLimitReached:Z?async(L)=>{let V=await Z.requestConfirmation({type:"maxTurnsExceeded",title:"对话轮次上限",message:`已进行 ${L.turnsCount} 轮对话。是否继续?`,risks:["继续执行可能导致更长的等待时间","可能产生更多的 API 费用"]});return{continue:V.approved,reason:V.reason}}:void 0},b=await B.chat(w,D,I);if(!b||b.trim()==="")return G.addAssistantMessage("⏹ 已取消"),{success:!0,output:"已取消"};return{success:!0,output:b}}catch(B){let A=B instanceof Error?B.message:"未知错误",D={success:!1,error:A};return G.addAssistantMessage(`❌ ${A}`),D}}),N=I9(async(w)=>{if(!w.trim())return;let B=w.trim();if(Q){U.enqueueCommand(B);return}W.setTodos([]),H.current=!1,U.setProcessing(!0),G.setThinking(!0);try{let A=await F(B);if(!A.success&&A.error)G.setError(A.error)}catch(A){if(A instanceof Error&&(A.name==="AbortError"||A.message.includes("aborted")));else{let D=A instanceof Error?A.message:"未知错误";G.setError(`执行失败: ${D}`)}}finally{U.setProcessing(!1),G.setThinking(!1),U.clearAbortController(),G.setCurrentThinkingContent(null);let A=U.dequeueCommand();if(A)setTimeout(()=>N(A),100)}});return{executeCommand:N,handleAbort:_,isProcessing:Q}};import{useMemoizedFn as Z4}from"ahooks";import{useState as CZ}from"react";var fZ=()=>{let[$,Y]=CZ([]),[Z,X]=CZ(-1),Q=Z4((G)=>{Y((W)=>[...W,G]),X(-1)}),J=Z4(()=>{if($.length===0)return"";let G=Z===-1?$.length-1:Math.max(0,Z-1);return X(G),$[G]||""}),q=Z4(()=>{if(Z===-1)return"";let G=Z+1;if(G>=$.length)return X(-1),"";else return X(G),$[G]||""}),K=Z4(()=>{X(-1)});return{commandHistory:$,historyIndex:Z,addToHistory:Q,getPreviousCommand:J,getNextCommand:q,resetHistoryIndex:K}};import{useMemoizedFn as hZ}from"ahooks";import{useMemo as SG,useState as CG}from"react";var xZ=()=>{let[$,Y]=CG({isVisible:!1,details:null,resolver:null}),Z=hZ((J)=>{return new Promise((q)=>{Y({isVisible:!0,details:J,resolver:q})})}),X=hZ((J)=>{if($.resolver)$.resolver(J);Y({isVisible:!1,details:null,resolver:null})}),Q=SG(()=>({requestConfirmation:Z}),[Z]);return{confirmationState:$,confirmationHandler:Q,handleResponse:X}};import{useMemoizedFn as k9}from"ahooks";import{useState as fG}from"react";function pZ($="",Y=0){let[Z,X]=fG({value:$,cursorPosition:Y}),Q=k9((K)=>{X((G)=>({value:K,cursorPosition:G.cursorPosition}))}),J=k9((K)=>{X((G)=>({...G,cursorPosition:Math.max(0,Math.min(K,G.value.length))}))}),q=k9(()=>{X({value:"",cursorPosition:0})});return{value:Z.value,cursorPosition:Z.cursorPosition,setValue:Q,setCursorPosition:J,clear:q}}N1();Y4();import{useMemoizedFn as lZ}from"ahooks";import{useInput as uG}from"ink";import{useEffect as iZ,useRef as rZ,useState as v9}from"react";m6();T6();import{useMemoizedFn as fb}from"ahooks";import hG from"fast-glob";import xG from"fuse.js";import{useEffect as gZ,useMemo as j9,useState as E9}from"react";var O$=null,pG=5000;function gG($,Y){let Z=[...$.matchAll(/(?:^|\s)(@(?:"[^"]*"|(?:[^\\ ]|\\ )*))/g)];for(let X of Z){let Q=X[1],J=X.index+(X[0].length-Q.length),q=J+Q.length;if(Y>=J&&Y<=q){let K=Q.slice(1),G=!1;if(K.startsWith('"')){if(G=!0,K=K.slice(1),K.endsWith('"'))K=K.slice(0,-1)}return{hasQuery:!0,query:K,startIndex:J,endIndex:q,quoted:G}}}return{hasQuery:!1,query:"",startIndex:-1,endIndex:-1,quoted:!1}}var mG=[...T0.map(($)=>`${$}/**`),...T0,...w8.map(($)=>`**/${$}`)];function mZ($,Y,Z={}){let{cwd:X=process.cwd(),maxSuggestions:Q=15,ignorePatterns:J=mG,debounceDelay:q=300,fuzzyMatch:K=!0}=Z,[G,W]=E9([]),[U,H]=E9(!1),[O,z]=E9(0),_=j9(()=>JSON.stringify(J),[J]),F=j9(()=>{if(Y===void 0)return{hasQuery:!1,query:"",startIndex:-1,endIndex:-1,quoted:!1};return gG($,Y)},[$,Y]);gZ(()=>{if(!$.includes("@")){W([]),H(!1);return}let w=Date.now();if(O$&&O$.cwd===X&&O$.ignoreKey===_&&w-O$.timestamp<pG){W(O$.files),H(!1);return}let B=!1,D=setTimeout(async()=>{H(!0);try{let b=(await hG("**/*",{cwd:X,dot:!1,followSymbolicLinks:!1,onlyFiles:!1,markDirectories:!0,unique:!0,ignore:J})).map((L)=>L.replace(/\\/g,"/"));if(!B)W(b),O$={cwd:X,ignoreKey:_,files:b,timestamp:w}}catch(I){if(console.error("Failed to load files for @ completion:",I),!B)W([])}finally{if(!B)H(!1)}},q);return()=>{B=!0,clearTimeout(D)}},[$,X,q,_]);let N=j9(()=>{if(!F.hasQuery||G.length===0)return[];let w=F.query.toLowerCase();if(w==="")return G.slice(0,Q);if(K)return new xG(G,{threshold:0.4,ignoreLocation:!0,minMatchCharLength:1}).search(w).slice(0,Q).map((D)=>D.item);return G.filter((B)=>B.toLowerCase().includes(w)).slice(0,Q)},[F,G,Q,K]);return gZ(()=>{z(0)},[N]),{...F,suggestions:N,selectedIndex:O,loading:U}}function dG($,Y=!1){if($.includes(" ")||Y)return`@"${$}"`;return`@${$}`}function y9($,Y,Z){if(!Y.hasQuery)return{newInput:$,newCursorPos:$.length};let X=dG(Z,Y.quoted),Q=$.slice(0,Y.startIndex),J=$.slice(Y.endIndex),q=Q+X+" "+J,K=Y.startIndex+X.length+1;return{newInput:q,newCursorPos:K}}import{useMemoizedFn as dZ}from"ahooks";import{useEffect as uZ,useRef as cZ}from"react";F1();var P1=($,Y)=>{let Z=cZ(!1),X=cZ(null),Q=dZ(()=>{if(X.current)clearTimeout(X.current);X.current=setTimeout(()=>{w0().setAwaitingSecondCtrlC(!1),Z.current=!1,X.current=null},3000)}),J=()=>{j2().shutdown("SIGINT",0)},q=dZ(()=>{if(!Z.current){if(Z.current=!0,$&&Y)Y();w0().setAwaitingSecondCtrlC(!0),Q()}else{if(X.current)clearTimeout(X.current),X.current=null;w0().setAwaitingSecondCtrlC(!1),J()}});return uZ(()=>{if($){if(w0().setAwaitingSecondCtrlC(!1),Z.current=!1,X.current)clearTimeout(X.current),X.current=null}},[$]),uZ(()=>{return()=>{if(X.current)clearTimeout(X.current)}},[]),q};var X4=u("UI"),aZ=($,Y,Z,X,Q,J,q,K,G,W)=>{let H=q0()==="main-input",O=$.value,z=$.setValue,_=$.cursorPosition,F=W$(),N=U2(),w=a6(),B=w?q$(w):!1,[A,D]=v9(!1),[I,b]=v9([]),[L,V]=v9(0),j=mZ(O,_,{cwd:process.cwd(),maxSuggestions:10}),m=P1(q||!1,J),P=rZ(0),v=500,Z1=rZ(!1);iZ(()=>{if(q)Z1.current=!1},[q]),iZ(()=>{if(O.startsWith("/"))if(O.includes(" "))D(!1),b([]);else{let d=vZ(O);b(d),D(d.length>0),V(0)}else if(j.hasQuery&&j.suggestions.length>0){let z1=j.suggestions.map((d)=>({command:d,description:d.endsWith("/")?`Directory: ${d}`:`File: ${d}`,matchScore:1}));b(z1),D(!0),V(0)}else D(!1),b([])},[O,j.hasQuery,j.suggestions]);let X1=lZ(()=>{F.clearMessages(),F.setError(null)}),n1=lZ(()=>{X4.debug("[DIAG] handleSubmit called:",{input:O,showSuggestions:A});let z1=O.trim();if(z1)X4.debug("[DIAG] Submitting command:",z1),D(!1),b([]),Q(z1),$.clear(),Y(z1),X4.debug("[DIAG] Command submitted to onSubmit callback");else X4.debug("[DIAG] Empty command, not submitting")});return uG((z1,d)=>{if(z1==="?"&&!O){G?.(),setTimeout(()=>$.clear(),0);return}if(d.backspace||d.delete||d.leftArrow||d.rightArrow||d.pageUp||d.pageDown||!d.ctrl&&!d.meta&&!d.escape&&!d.tab&&!d.upArrow&&!d.downArrow&&!d.return&&!(z1==="?"&&!O))return;if(d.ctrl&&z1==="c"||d.meta&&z1==="c"||d.ctrl&&z1==="d"||d.meta&&z1==="d"){m();return}if(d.ctrl&&z1==="l"||d.meta&&z1==="l"){X1();return}if(d.ctrl&&z1==="t"||d.meta&&z1==="t"){F.toggleThinkingExpanded();return}if(d.escape){if(W)G?.();else if(q&&J){if(Z1.current)return;Z1.current=!0,J()}else if(A)D(!1),b([]);else if(O){let J1=Date.now();if(J1-P.current<500)$.clear(),P.current=0;else P.current=J1}return}if(d.tab&&d.shift){K?.();return}if(d.tab){if(A&&I.length>0){let J1=I[L].command;if(j.hasQuery&&j.suggestions.includes(J1)){let{newInput:R1,newCursorPos:m0}=y9(O,j,J1);z(R1),$.setCursorPosition(m0)}else{let R1=J1+" ";z(R1),$.setCursorPosition(R1.length)}D(!1),b([])}else if(B)N.toggleThinkingMode();return}if(d.return){if(A&&I.length>0){let J1=I[L].command;if(j.hasQuery&&j.suggestions.includes(J1)){let{newInput:R1,newCursorPos:m0}=y9(O,j,J1);z(R1),$.setCursorPosition(m0)}else{let R1=J1+" ";z(R1),$.setCursorPosition(R1.length)}D(!1),b([])}else n1();return}if(d.upArrow){if(A&&I.length>0){let J1=I.length-1;V((R1)=>R1>0?R1-1:J1)}else{let J1=Z();if(J1!=="")z(J1),$.setCursorPosition(J1.length)}return}if(d.downArrow){if(A&&I.length>0){let J1=I.length-1;V((R1)=>R1<J1?R1+1:0)}else{let J1=X();if(J1!=="")z(J1),$.setCursorPosition(J1.length)}return}},{isActive:H}),{handleSubmit:n1,showSuggestions:A,suggestions:I,selectedSuggestionIndex:L}};J2();import{MultiSelect as cG}from"@inkjs/ui";import{useMemoizedFn as Q4}from"ahooks";import{Box as g,Text as f,useFocus as lG,useFocusManager as iG,useInput as sZ}from"ink";import J4 from"ink-select-input";import rG from"ink-spinner";import s$ from"ink-text-input";import nZ from"node:fs";import aG from"node:os";import P9 from"node:path";import{useEffect as oZ,useState as F$}from"react";import{jsxDEV as M}from"react/jsx-dev-runtime";var nG=[{label:"\uD83D\uDD0D Glob - 文件搜索",value:"Glob"},{label:"\uD83D\uDD0E Grep - 内容搜索",value:"Grep"},{label:"\uD83D\uDCD6 Read - 读取文件",value:"Read"},{label:"✍️ Write - 写入文件",value:"Write"},{label:"✏️ Edit - 编辑文件",value:"Edit"},{label:"\uD83D\uDCBB Bash - 执行命令",value:"Bash"},{label:"✅ 所有工具 (不限制)",value:"all"}],oG=[{label:"\uD83D\uDD34 红色 (red)",value:"red"},{label:"\uD83D\uDD35 蓝色 (blue)",value:"blue"},{label:"\uD83D\uDFE2 绿色 (green)",value:"green"},{label:"\uD83D\uDFE1 黄色 (yellow)",value:"yellow"},{label:"\uD83D\uDFE3 紫色 (purple)",value:"purple"},{label:"\uD83D\uDFE0 橙色 (orange)",value:"orange"},{label:"\uD83E\uDE77 粉色 (pink)",value:"pink"},{label:"\uD83E\uDE75 青色 (cyan)",value:"cyan"},{label:"⚪ 不设置颜色",value:"none"}];function sG($){if(!$||$.trim()==="")return"名称不能为空";if(!/^[a-z0-9-]+$/.test($))return"名称只能包含小写字母、数字和连字符";if($.startsWith("-")||$.endsWith("-"))return"名称不能以连字符开头或结尾";return null}function t$({onComplete:$,onCancel:Y,initialConfig:Z}){let[X,Q]=F$(Z?"name":"mode"),[J,q]=F$({name:Z?.name||"",description:Z?.description||"",tools:Z?.tools||[],color:Z?.color,location:Z?.location||"project",systemPrompt:Z?.systemPrompt||""}),[K,G]=F$(""),[W,U]=F$(!1),[H,O]=F$(""),[z,_]=F$(Z?"edit":"manual"),{focus:F}=iG(),w={manual:["mode","name","description","tools","color","location","systemPrompt","confirm"],ai:["mode","aiPrompt","aiGenerating","confirm"],edit:["name","description","tools","color","location","systemPrompt","confirm"]}[z];oZ(()=>{if(X==="name"||X==="description"||X==="systemPrompt"||X==="aiPrompt")return;F(`step-${X}`)},[X,F]);let B=Q4(()=>{let L=w.indexOf(X);if(L<w.length-1)Q(w[L+1])}),A=Q4(()=>{if(H)O("");if(X==="confirm"&&z==="ai"){Q("aiPrompt");return}let L=w.indexOf(X);if(L>0)Q(w[L-1]);else Y()}),D=Q4(async()=>{U(!0),O("");try{let L=await E1.create(),V=`你是一个 Subagent 配置生成专家。用户会描述他们想要创建的 agent,你需要根据描述生成一个完整的 agent 配置。
1503
+ `),console.log(JSON.stringify(Z,null,2))}catch(Y){console.error(`❌ 获取失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},FJ={command:"add-json <name> <json>",describe:"从 JSON 字符串添加服务器",builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).positional("json",{type:"string",describe:"JSON 配置字符串",demandOption:!0}).option("global",{alias:"g",type:"boolean",default:!1,describe:"存储到全局配置(~/.blade/config.json)"}).example([[`$0 mcp add-json my-server '{"type":"stdio","command":"npx","args":["-y","@example/server"]}'`,"Add server from JSON string"]])},handler:async($)=>{try{let Y=JSON.parse($.json),Z=$.global===!0;if(!Y.type)throw Error('配置必须包含 "type" 字段');await H1().addMcpServer($.name,Y,{scope:Z?"global":"project"});let X=Z?R6.join(K3.homedir(),".blade","config.json"):R6.join(process.cwd(),".blade","config.json");console.log(`✅ MCP 服务器 "${$.name}" 已添加`),console.log(` 配置文件: ${X}`)}catch(Y){console.error(`❌ 添加失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},W3={command:"mcp",describe:"管理 MCP 服务器",builder:($)=>{return $.command(WJ).command(UJ).command(HJ).command(OJ).command(FJ).demandCommand(0).help(!1).option("help",{alias:"h",type:"boolean",describe:"显示帮助信息"})},handler:($)=>{let Y=["add","remove","list","ls","get","add-json"];if(!$._.some((X)=>Y.includes(X))||$.help)qJ(),process.exit(0)}};K2();function pG($){return $.command("* [message]","Print response and exit (useful for pipes)",(Y)=>{return Y.positional("message",{describe:"Message to process",type:"string"}).option("p",{alias:"print",describe:"Print response and exit (useful for pipes)",type:"boolean"}).option("output-format",{describe:'Output format: "text", "json", "stream-json"',type:"string",default:"text"}).option("include-partial-messages",{describe:"Include partial message chunks as they arrive",type:"boolean"}).option("input-format",{describe:'Input format: "text", "stream-json"',type:"string",default:"text"}).option("model",{describe:"Model for the current session",type:"string"}).option("append-system-prompt",{describe:"Append a system prompt to the default system prompt",type:"string"}).option("system-prompt",{describe:"Replace the default system prompt",type:"string"}).option("max-turns",{alias:["maxTurns"],describe:"Maximum conversation turns (-1: unlimited, N>0: limit to N turns)",type:"number"})},async(Y)=>{if(!Y.print)return;try{let Z=await v1.create({systemPrompt:Y.systemPrompt,appendSystemPrompt:Y.appendSystemPrompt,maxTurns:Y.maxTurns}),X="",Q=Y._?.[0];if(Q&&typeof Q==="string")X=Q;else if(!process.stdin.isTTY){let q=[];for await(let G of process.stdin)q.push(G);X=Buffer.concat(q).toString("utf-8").trim()}else X="Hello";let J;if(Y.appendSystemPrompt)J=await Z.chatWithSystem(Y.appendSystemPrompt,X);else J=await Z.chat(X,{messages:[],userId:"cli-user",sessionId:`print-${Date.now()}`,workspaceRoot:process.cwd()});if(Y.outputFormat==="json")console.log(JSON.stringify({response:J,input:X,model:Y.model,timestamp:new Date().toISOString()},null,2));else if(Y.outputFormat==="stream-json")console.log(JSON.stringify({type:"response",content:J}));else console.log(J);process.exit(0)}catch(Z){console.error(`Error: ${Z instanceof Error?Z.message:"未知错误"}`),process.exit(1)}})}async function RY(){if(process.argv.slice(2).findIndex((Z)=>Z==="--print"||Z==="-p")===-1)return!1;try{let Z=(await import("yargs")).default,{hideBin:X}=await import("yargs/helpers"),Q=Z(X(process.argv)).scriptName("blade").strict(!1);return pG(Q),await Q.parse(),!0}catch(Z){console.error(`Print mode error: ${Z instanceof Error?Z.message:"未知错误"}`),process.exit(1)}}import{execSync as iG}from"child_process";import*as k2 from"fs/promises";import*as H2 from"path";import VY from"semver";import{fileURLToPath as gG}from"url";var V9="blade-code",mG="https://cdn.jsdelivr.net/npm/blade-code@latest/CHANGELOG.md",DY=H2.join(process.env.HOME||process.env.USERPROFILE||".",".blade"),IY=H2.join(DY,"version-cache.json"),dG=3600000,uG=`https://registry.npmjs.org/${V9}/latest`;async function cG(){try{if(process.env.BLADE_VERSION)return process.env.BLADE_VERSION;let $=gG(import.meta.url),Y=H2.dirname($),Z=[H2.join(Y,"..","..","package.json"),H2.join(Y,"..","package.json"),H2.join(process.cwd(),"package.json")];for(let X of Z)try{let Q=await k2.readFile(X,"utf-8"),J=JSON.parse(Q);if(J.name===V9&&J.version)return J.version}catch{}return"unknown"}catch{return"unknown"}}async function MY(){try{let $=await k2.readFile(IY,"utf-8"),Y=JSON.parse($);if(Date.now()-Y.checkedAt<dG)return Y;return{...Y,checkedAt:0}}catch{return null}}async function kY($){try{await k2.mkdir(DY,{recursive:!0}),await k2.writeFile(IY,JSON.stringify($,null,2))}catch{}}async function lG(){try{let $=new AbortController,Y=setTimeout(()=>$.abort(),5000),Z=await fetch(uG,{signal:$.signal,headers:{Accept:"application/json"}});if(clearTimeout(Y),!Z.ok)return null;return(await Z.json()).version||null}catch{return null}}async function D9($=!1){let Y=await cG(),Z=mG;if(Y==="unknown")return{currentVersion:Y,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:Z,error:"Unable to determine current version"};let X=await MY(),Q=X?.skipUntilVersion,J=null;if(!$&&X&&X.checkedAt>0)J=X.latestVersion;else if(J=await lG(),J)await kY({latestVersion:J,checkedAt:Date.now(),skipUntilVersion:Q});if(!J)return{currentVersion:Y,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:Z,error:"Unable to check for updates"};let q=VY.gt(J,Y),G=q;if(q&&Q)G=VY.gt(J,Q);return{currentVersion:Y,latestVersion:J,hasUpdate:q,shouldPrompt:G,releaseNotesUrl:Z}}async function jY($){let Y=await MY();await kY({latestVersion:Y?.latestVersion||$,checkedAt:Y?.checkedAt||Date.now(),skipUntilVersion:$})}function I9(){return`npm install -g ${V9}@latest`}async function EY(){let{spawn:$}=await import("child_process");return new Promise((Y)=>{let Z=I9(),X=$(Z,{stdio:"inherit",shell:!0});X.on("close",(Q)=>{if(Q===0)Y({success:!0,message:"✅ 升级成功!请重新启动 blade。"});else Y({success:!1,message:`❌ 升级失败 (exit code: ${Q})`})}),X.on("error",(Q)=>{Y({success:!1,message:`❌ 升级失败: ${Q.message}`})})})}async function vY(){try{let $=await D9();return $.shouldPrompt?$:null}catch{return null}}var yY={command:"update",describe:"Check for updates and install if available",handler:async()=>{console.log("\uD83D\uDD0D Checking for updates...");try{let $=await D9(!0);if(console.log(`\uD83D\uDCE6 Current version: ${$.currentVersion}`),$.error){console.log(`⚠️ ${$.error}`);return}if($.latestVersion)console.log(`\uD83D\uDCE6 Latest version: ${$.latestVersion}`);if($.hasUpdate&&$.latestVersion){console.log(""),console.log(`\x1B[33m⚠️ Update available: ${$.currentVersion} → ${$.latestVersion}\x1B[0m`),console.log(""),console.log("\uD83D\uDE80 Updating...");try{iG("npm install -g blade-code@latest --registry https://registry.npmjs.org",{stdio:"inherit"}),console.log(""),console.log("✅ Update complete!")}catch(Y){console.error("❌ Update failed. Please run manually:"),console.error(" npm install -g blade-code@latest"),process.exit(1)}}else console.log("✅ You are running the latest version of Blade")}catch($){console.error(`❌ Failed to check for updates: ${$ instanceof Error?$.message:"未知错误"}`),process.exit(1)}}};B1();B1();var o0=l("Service");class U${static instance=null;cleanupHandlers=[];isShuttingDown=!1;initialized=!1;constructor(){}static getInstance(){if(!U$.instance)U$.instance=new U$;return U$.instance}initialize(){if(this.initialized){o0.debug("[GracefulShutdown] 已初始化,跳过重复初始化");return}if(process.on("uncaughtException",($)=>{this.handleFatalError("uncaughtException",$)}),process.on("unhandledRejection",($)=>{let Y=$ instanceof Error?$:Error(String($));this.handleFatalError("unhandledRejection",Y)}),process.on("SIGTERM",()=>{o0.info("[GracefulShutdown] 收到 SIGTERM 信号"),this.shutdown("SIGTERM",0)}),process.env.BLADE_NON_INTERACTIVE==="true")process.on("SIGINT",()=>{o0.info("[GracefulShutdown] 收到 SIGINT 信号(非交互模式)"),this.shutdown("SIGINT",0)});this.initialized=!0,o0.debug("[GracefulShutdown] 全局错误处理器已初始化")}registerCleanup($){return this.cleanupHandlers.push($),o0.debug(`[GracefulShutdown] 注册清理函数,当前共 ${this.cleanupHandlers.length} 个`),()=>{let Y=this.cleanupHandlers.indexOf($);if(Y!==-1)this.cleanupHandlers.splice(Y,1),o0.debug(`[GracefulShutdown] 取消注册清理函数,剩余 ${this.cleanupHandlers.length} 个`)}}handleFatalError($,Y){if(this.isShuttingDown){console.error(`[GracefulShutdown] 退出过程中发生额外错误 (${$}):`,Y);return}if(console.error(""),console.error("═".repeat(60)),console.error(`\uD83D\uDCA5 发生未捕获的错误 (${$})`),console.error("═".repeat(60)),console.error(""),console.error("错误信息:",Y.message),console.error(""),Y.stack)console.error("堆栈跟踪:"),console.error(Y.stack);console.error(""),console.error("═".repeat(60)),console.error(""),this.shutdown($,1)}async shutdown($,Y=0){if(this.isShuttingDown){o0.debug("[GracefulShutdown] 已在退出过程中,跳过重复退出");return}this.isShuttingDown=!0,o0.info(`[GracefulShutdown] 开始优雅退出 (原因: ${$})`);let Z=5000,X=new Promise((Q,J)=>{setTimeout(()=>{J(Error(`清理超时 (${Z}ms)`))},Z)});try{let Q=this.runCleanupHandlers();await Promise.race([Q,X]),o0.info("[GracefulShutdown] 所有清理函数执行完成")}catch(Q){console.error("[GracefulShutdown] 清理过程中发生错误:",Q)}finally{setTimeout(()=>{process.exit(Y)},100)}}async runCleanupHandlers(){let $=[...this.cleanupHandlers].reverse();for(let Y of $)try{let Z=Y();if(Z instanceof Promise)await Z}catch(Z){console.error("[GracefulShutdown] 清理函数执行失败:",Z)}}isExiting(){return this.isShuttingDown}reset(){this.isShuttingDown=!1,this.cleanupHandlers=[],this.initialized=!1}}var j2=()=>{return U$.getInstance()},PY=($)=>{return j2().registerCleanup($)},TY=()=>{j2().initialize()};Q$();m2();i6();l2();import{useMemoizedFn as HQ}from"ahooks";import{useEffect as CH,useState as O7}from"react";z1();X$();s1();B1();o6();import{useMemoizedFn as n1}from"ahooks";import{Box as z6,useApp as vH}from"ink";import{useEffect as f2,useRef as E4}from"react";import{useShallow as tA}from"zustand/react/shallow";z1();z1();import{useStore as rG}from"zustand";function q1($){return rG(C$,$)}s1();var aG=[],fY=()=>q1(($)=>$.session.sessionId),s6=()=>q1(($)=>$.session.messages),hY=()=>q1(($)=>$.session.clearCount),xY=()=>q1(($)=>$.session.isCompacting);var H$=()=>q1(($)=>$.session.actions);var pY=()=>q1(($)=>{let{inputTokens:Y,maxContextTokens:Z}=$.session.tokenUsage;if(Z<=0)return 100;let X=Math.max(0,100-Y/Z*100);return Math.round(X)});var gY=()=>q1(($)=>$.app.initializationStatus),mY=()=>q1(($)=>$.app.initializationError),t6=()=>q1(($)=>$.app.activeModal),dY=()=>q1(($)=>$.app.todos),uY=()=>q1(($)=>$.app.modelEditorTarget),cY=()=>q1(($)=>$.app.sessionSelectorData),lY=()=>q1(($)=>$.app.awaitingSecondCtrlC),O2=()=>q1(($)=>$.app.actions),e6=()=>q1(($)=>$.app.initializationStatus==="ready");var iY=()=>q1(($)=>$.app.todos.length>0);var O$=()=>q1(($)=>$.config.config?.permissionMode||"default"),rY=()=>q1(($)=>$.config.config?.models??aG),$4=()=>q1(($)=>{let Y=$.config.config;if(!Y)return;let Z=Y.currentModelId;return Y.models.find((Q)=>Q.id===Z)??Y.models[0]}),aY=()=>q1(($)=>$.config.config?.currentModelId);var G0=()=>q1(($)=>$.focus.currentFocus);var nY=()=>q1(($)=>$.focus.actions);var f0=()=>q1(($)=>$.command.isProcessing);var oY=()=>q1(($)=>$.command.actions),sY=()=>q1(($)=>$.command.pendingCommands);var tY=()=>q1(($)=>$.app.thinkingModeEnabled),eY=()=>q1(($)=>$.session.currentThinkingContent),$Z=()=>q1(($)=>$.session.thinkingExpanded),YZ=()=>q1(($)=>$.session.historyExpanded),ZZ=()=>q1(($)=>$.session.expandedMessageCount);z1();B1();G4();import{useMemoizedFn as P9}from"ahooks";import{useEffect as cK,useRef as lK}from"react";z1();K2();import{useMemoizedFn as uZ}from"ahooks";import{useRef as uK}from"react";function cZ($){let Y=uK(void 0),Z=uZ(async()=>{let Q=await v1.create({systemPrompt:$.systemPrompt,appendSystemPrompt:$.appendSystemPrompt,maxTurns:$.maxTurns});return Y.current=Q,Q}),X=uZ(()=>{if(Y.current)Y.current=void 0});return{agentRef:Y,createAgent:Z,cleanupAgent:X}}var iK=l("UI");function rK($,Y,Z,X){switch($){case"show_theme_selector":return Z.setActiveModal("themeSelector"),!0;case"show_model_selector":return Z.setActiveModal("modelSelector"),!0;case"show_model_add_wizard":return Z.setActiveModal("modelAddWizard"),!0;case"show_permissions_manager":return Z.setActiveModal("permissionsManager"),!0;case"show_agents_manager":return Z.setActiveModal("agentsManager"),!0;case"show_agent_creation_wizard":return Z.setActiveModal("agentCreationWizard"),!0;case"show_session_selector":{let Q=Y?.sessions;return Z.showSessionSelector(Q),!0}case"clear_screen":return X.clearMessages(),X.setError(null),X.resetTokenUsage(),Z.setTodos([]),!0;case"exit_application":return process.exit(0),!0;default:return!1}}function aK($){let{text:Y,images:Z,parts:X}=$;if(Z.length===0)return Y;let Q=[];for(let J of X)if(J.type==="text")Q.push({type:"text",text:J.text});else Q.push({type:"image_url",image_url:{url:`data:${J.mimeType};base64,${J.base64}`}});return Q}var lZ=($,Y,Z,X)=>{let Q=f0(),J=s6(),q=fY(),G=O$(),K=H$(),W=O2(),U=oY(),H=lK(!1),{createAgent:O,cleanupAgent:F}=cZ({systemPrompt:$,appendSystemPrompt:Y,maxTurns:X});cK(()=>{return()=>{F()}},[F]);let _=P9(()=>{if(!Q)return;if(!H.current)K.addAssistantMessage("✋ 任务已停止"),H.current=!0;U.abort(),W.setTodos([])}),z=P9(async(B)=>{let{text:N}=B;try{if(J4(N)){await B6();let I=U.createAbortController(),T={cwd:process.cwd(),signal:I.signal},E=await q4(N,T);if(E.message){if(rK(E.message,E.data,W,K))return{success:!0}}if(!E.success&&E.error)return K.addAssistantMessage(`❌ ${E.error}`),{success:E.success,output:E.message,error:E.error,metadata:E.data};let v=E.message;if(E.success&&typeof v==="string"&&v.trim()!=="")K.addAssistantMessage(v);return{success:E.success,output:E.message,error:E.error,metadata:E.data}}K.addUserMessage(B.displayText);let b=aK(B),V=await O(),R=U.createAbortController(),L={messages:J.map((I)=>({role:I.role,content:I.content})),userId:"cli-user",sessionId:q,workspaceRoot:process.cwd(),signal:R.signal,confirmationHandler:Z,permissionMode:G},A={onThinking:(I)=>{K.setCurrentThinkingContent(I)},onContent:(I)=>{if(I.trim())K.addAssistantMessage(I),K.setCurrentThinkingContent(null)},onToolStart:(I)=>{if(I.type!=="function")return;if(I.function.name==="TodoWrite")return;try{let T=JSON.parse(I.function.arguments),E=e$(I.function.name,T);K.addToolMessage(E,{toolName:I.function.name,phase:"start",summary:E,params:T})}catch(T){iK.error("[useCommandHandler] onToolStart error:",T)}},onToolResult:async(I,T)=>{if(I.type!=="function")return;if(!T?.metadata?.summary)return;let E=TZ(I.function.name,T)?T.displayContent:void 0;K.addToolMessage(T.metadata.summary,{toolName:I.function.name,phase:"complete",summary:T.metadata.summary,detail:E})},onTokenUsage:(I)=>{K.updateTokenUsage(I)},onCompacting:(I)=>{K.setCompacting(I)},onTurnLimitReached:Z?async(I)=>{let T=await Z.requestConfirmation({type:"maxTurnsExceeded",title:"对话轮次上限",message:`已进行 ${I.turnsCount} 轮对话。是否继续?`,risks:["继续执行可能导致更长的等待时间","可能产生更多的 API 费用"]});return{continue:T.approved,reason:T.reason}}:void 0},k=await V.chat(b,L,A);if(!k||k.trim()===""){if(!H.current)K.addAssistantMessage("⏹ 已取消");return{success:!0,output:"已取消"}}return{success:!0,output:k}}catch(b){if(H.current)return{success:!1,error:"aborted"};let V=b instanceof Error?b.message:"未知错误",R=V.includes("can only concatenate str")||V.includes("image_url")||V.includes("multimodal")||V.includes("vision")||V.includes("does not support images"),L=V;if(R)L="当前模型不支持图片理解功能。请切换到支持视觉能力的模型(如 Claude 4.5、GPT-5.2、Gemini 3 Pro、Qwen3-VL-Plus 等)后重试。";let A={success:!1,error:L};return K.addAssistantMessage(`❌ ${L}`),A}}),w=P9(async(B)=>{if(!B.text.trim()&&B.images.length===0)return;if(Q){U.enqueueCommand({displayText:B.displayText,text:B.text,images:B.images,parts:B.parts});return}W.setTodos([]),H.current=!1,U.setProcessing(!0);try{let N=await z(B);if(!N.success&&N.error&&N.error!=="aborted")K.setError(N.error)}catch(N){if(N instanceof Error&&(N.name==="AbortError"||N.message.includes("aborted")));else{let b=N instanceof Error?N.message:"未知错误";K.setError(`执行失败: ${b}`)}}finally{U.setProcessing(!1),U.clearAbortController(),K.setCurrentThinkingContent(null);let N=U.dequeueCommand();if(N)setTimeout(()=>w({displayText:N.displayText,text:N.text,images:N.images,parts:N.parts}),100)}});return{executeCommand:w,handleAbort:_,isProcessing:Q}};import{useMemoizedFn as K4}from"ahooks";import{useState as iZ}from"react";var rZ=()=>{let[$,Y]=iZ([]),[Z,X]=iZ(-1),Q=K4((K,W)=>{let U={display:K,pasteMappings:W?new Map(W):new Map};Y((H)=>[...H,U]),X(-1)}),J=K4(()=>{if($.length===0)return null;let K=Z===-1?$.length-1:Math.max(0,Z-1);return X(K),$[K]||null}),q=K4(()=>{if(Z===-1)return null;let K=Z+1;if(K>=$.length)return X(-1),null;else return X(K),$[K]||null}),G=K4(()=>{X(-1)});return{commandHistory:$,historyIndex:Z,addToHistory:Q,getPreviousCommand:J,getNextCommand:q,resetHistoryIndex:G}};import{useMemoizedFn as aZ}from"ahooks";import{useMemo as nK,useState as oK}from"react";var nZ=()=>{let[$,Y]=oK({isVisible:!1,details:null,resolver:null}),Z=aZ((J)=>{return new Promise((q)=>{Y({isVisible:!0,details:J,resolver:q})})}),X=aZ((J)=>{if($.resolver)$.resolver(J);Y({isVisible:!1,details:null,resolver:null})}),Q=nK(()=>({requestConfirmation:Z}),[Z]);return{confirmationState:$,confirmationHandler:Q,handleResponse:X}};import{useMemoizedFn as v2}from"ahooks";import{useRef as oZ,useState as sK}from"react";var W4="␞",U4="␟";function H4($){return`${W4}PASTE:${$}:`}function T9(){return U4}var cR=new RegExp(`${W4}PASTE:(\\d+):[\\s\\S]*?${U4}`,"g");function tK($){return $.includes(W4)&&$.includes(U4)}function sZ($="",Y=0){let[Z,X]=sK({value:$,cursorPosition:Y}),Q=oZ(0),J=oZ(new Map),q=v2((F)=>{X((_)=>({value:F,cursorPosition:_.cursorPosition}));for(let _ of J.current.keys()){let z=H4(_);if(!F.includes(z))J.current.delete(_)}}),G=v2((F)=>{X((_)=>({..._,cursorPosition:Math.max(0,Math.min(F,_.value.length))}))}),K=v2(()=>{X({value:"",cursorPosition:0}),J.current.clear()}),W=v2((F)=>{Q.current+=1;let _=Q.current;return J.current.set(_,{type:"text",data:F}),_}),U=v2((F,_)=>{Q.current+=1;let z=Q.current;return J.current.set(z,{type:"image",data:F,mimeType:_}),z}),H=v2((F)=>{for(let[_,z]of F)if(J.current.set(_,z),_>=Q.current)Q.current=_}),O=v2((F)=>{let _=[],z=[];if(!tK(F)){let I=F.trim();if(I)z.push({type:"text",text:I});return{displayText:F,text:F,images:_,parts:z}}let w=new RegExp(`${W4}PASTE:(\\d+):[\\s\\S]*?${U4}`,"g"),B=Array.from(F.matchAll(w)),N=0,b="",V="";for(let I of B){let T=I.index,E=T+I[0].length,v=parseInt(I[1],10),g=J.current.get(v);if(T>N){let u=F.slice(N,T);z.push({type:"text",text:u}),b+=u,V+=u}if(!g)b+=I[0],V+=I[0],z.push({type:"text",text:I[0]});else if(g.type==="text")b+=g.data,V+=g.data,z.push({type:"text",text:g.data});else{let u={id:v,base64:g.data,mimeType:g.mimeType};_.push(u),z.push({type:"image",...u}),V+=`[Image #${v}]`}N=E}if(N<F.length){let I=F.slice(N);z.push({type:"text",text:I}),b+=I,V+=I}let R=[];for(let I of z)if(I.type==="text"&&R.length>0&&R[R.length-1].type==="text")R[R.length-1].text+=I.text;else R.push(I);let L=0,A=R.length;while(L<R.length&&R[L].type==="text"&&R[L].text.trim()==="")L++;while(A>L&&R[A-1].type==="text"&&R[A-1].text.trim()==="")A--;let k=R.slice(L,A);return{displayText:V.trim(),text:b.trim(),images:_,parts:k}});return{value:Z.value,cursorPosition:Z.cursorPosition,setValue:q,setCursorPosition:G,clear:K,pasteMap:J.current,addPasteMapping:W,addImagePasteMapping:U,restorePasteMappings:H,resolveInput:O}}B1();G4();import{useMemoizedFn as XX}from"ahooks";import{useInput as JW}from"ink";import{useEffect as QX,useRef as JX,useState as h9}from"react";r6();p6();import{useMemoizedFn as rR}from"ahooks";import eK from"fast-glob";import $W from"fuse.js";import{useEffect as tZ,useMemo as S9,useState as C9}from"react";var _$=null,YW=5000;function ZW($,Y){let Z=[...$.matchAll(/(?:^|\s)(@(?:"[^"]*"|(?:[^\\ ]|\\ )*))/g)];for(let X of Z){let Q=X[1],J=X.index+(X[0].length-Q.length),q=J+Q.length;if(Y>=J&&Y<=q){let G=Q.slice(1),K=!1;if(G.startsWith('"')){if(K=!0,G=G.slice(1),G.endsWith('"'))G=G.slice(0,-1)}return{hasQuery:!0,query:G,startIndex:J,endIndex:q,quoted:K}}}return{hasQuery:!1,query:"",startIndex:-1,endIndex:-1,quoted:!1}}var XW=[...S0.map(($)=>`${$}/**`),...S0,...D8.map(($)=>`**/${$}`)];function eZ($,Y,Z={}){let{cwd:X=process.cwd(),maxSuggestions:Q=15,ignorePatterns:J=XW,debounceDelay:q=300,fuzzyMatch:G=!0}=Z,[K,W]=C9([]),[U,H]=C9(!1),[O,F]=C9(0),_=S9(()=>JSON.stringify(J),[J]),z=S9(()=>{if(Y===void 0)return{hasQuery:!1,query:"",startIndex:-1,endIndex:-1,quoted:!1};return ZW($,Y)},[$,Y]);tZ(()=>{if(!$.includes("@")){W([]),H(!1);return}let B=Date.now();if(_$&&_$.cwd===X&&_$.ignoreKey===_&&B-_$.timestamp<YW){W(_$.files),H(!1);return}let N=!1,V=setTimeout(async()=>{H(!0);try{let L=(await eK("**/*",{cwd:X,dot:!1,followSymbolicLinks:!1,onlyFiles:!1,markDirectories:!0,unique:!0,ignore:J})).map((A)=>A.replace(/\\/g,"/"));if(!N)W(L),_$={cwd:X,ignoreKey:_,files:L,timestamp:B}}catch(R){if(console.error("Failed to load files for @ completion:",R),!N)W([])}finally{if(!N)H(!1)}},q);return()=>{N=!0,clearTimeout(V)}},[$,X,q,_]);let w=S9(()=>{if(!z.hasQuery||K.length===0)return[];let B=z.query.toLowerCase();if(B==="")return K.slice(0,Q);if(G)return new $W(K,{threshold:0.4,ignoreLocation:!0,minMatchCharLength:1}).search(B).slice(0,Q).map((V)=>V.item);return K.filter((N)=>N.toLowerCase().includes(B)).slice(0,Q)},[z,K,Q,G]);return tZ(()=>{F(0)},[w]),{...z,suggestions:w,selectedIndex:O,loading:U}}function QW($,Y=!1){if($.includes(" ")||Y)return`@"${$}"`;return`@${$}`}function f9($,Y,Z){if(!Y.hasQuery)return{newInput:$,newCursorPos:$.length};let X=QW(Z,Y.quoted),Q=$.slice(0,Y.startIndex),J=$.slice(Y.endIndex),q=Q+X+" "+J,G=Y.startIndex+X.length+1;return{newInput:q,newCursorPos:G}}import{useMemoizedFn as $X}from"ahooks";import{useEffect as YX,useRef as ZX}from"react";z1();var T1=($,Y)=>{let Z=ZX(!1),X=ZX(null),Q=$X(()=>{if(X.current)clearTimeout(X.current);X.current=setTimeout(()=>{w0().setAwaitingSecondCtrlC(!1),Z.current=!1,X.current=null},3000)}),J=()=>{j2().shutdown("SIGINT",0)},q=$X(()=>{if(!Z.current){if(Z.current=!0,$&&Y)Y();w0().setAwaitingSecondCtrlC(!0),Q()}else{if(X.current)clearTimeout(X.current),X.current=null;w0().setAwaitingSecondCtrlC(!1),J()}});return YX(()=>{if($){if(w0().setAwaitingSecondCtrlC(!1),Z.current=!1,X.current)clearTimeout(X.current),X.current=null}},[$]),YX(()=>{return()=>{if(X.current)clearTimeout(X.current)}},[]),q};var O4=l("UI"),qX=($,Y,Z,X,Q,J,q,G,K,W)=>{let H=G0()==="main-input",O=$.value,F=$.setValue,_=$.cursorPosition,z=H$(),w=O2(),B=$4(),N=B?K$(B):!1,[b,V]=h9(!1),[R,L]=h9([]),[A,k]=h9(0),I=eZ(O,_,{cwd:process.cwd(),maxSuggestions:10}),T=T1(q||!1,J),E=JX(0),v=500,g=JX(!1);QX(()=>{if(q)g.current=!1},[q]),QX(()=>{if(O.startsWith("/"))if(O.includes(" "))V(!1),L([]);else{let x=dZ(O);L(x),V(x.length>0),k(0)}else if(I.hasQuery&&I.suggestions.length>0){let J1=I.suggestions.map((x)=>({command:x,description:x.endsWith("/")?`Directory: ${x}`:`File: ${x}`,matchScore:1}));L(J1),V(!0),k(0)}else V(!1),L([])},[O,I.hasQuery,I.suggestions]);let u=XX(()=>{z.clearMessages(),z.setError(null)}),D1=XX(()=>{O4.debug("[DIAG] handleSubmit called:",{input:O,showSuggestions:b});let J1=O.trim();if(J1){let x=$.resolveInput(J1);O4.debug("[DIAG] Submitting command:",{displayText:J1,textLength:x.text.length,imageCount:x.images.length}),V(!1),L([]);let j0=$.pasteMap.size>0?new Map($.pasteMap):new Map;Q(J1,j0),$.clear(),Y(x),O4.debug("[DIAG] Command submitted to onSubmit callback")}else O4.debug("[DIAG] Empty command, not submitting")});return JW((J1,x)=>{if(J1==="?"&&!O){K?.(),setTimeout(()=>$.clear(),0);return}if(x.backspace||x.delete||x.leftArrow||x.rightArrow||x.pageUp||x.pageDown||!x.ctrl&&!x.meta&&!x.escape&&!x.tab&&!x.upArrow&&!x.downArrow&&!x.return&&!(J1==="?"&&!O))return;if(x.ctrl&&J1==="c"||x.meta&&J1==="c"||x.ctrl&&J1==="d"||x.meta&&J1==="d"){T();return}if(x.ctrl&&J1==="l"||x.meta&&J1==="l"){u();return}if(x.ctrl&&J1==="t"||x.meta&&J1==="t"){z.toggleThinkingExpanded();return}if(x.ctrl&&J1==="o"||x.meta&&J1==="o"){z.toggleHistoryExpanded();return}if(x.escape){if(W)K?.();else if(q&&J){if(g.current)return;g.current=!0,J()}else if(b)V(!1),L([]);else if(O){let Q1=Date.now();if(Q1-E.current<500)$.clear(),E.current=0;else E.current=Q1}return}if(x.tab&&x.shift){G?.();return}if(x.tab){if(b&&R.length>0){let Q1=R[A].command;if(I.hasQuery&&I.suggestions.includes(Q1)){let{newInput:b1,newCursorPos:u0}=f9(O,I,Q1);F(b1),$.setCursorPosition(u0)}else{let b1=Q1+" ";F(b1),$.setCursorPosition(b1.length)}V(!1),L([])}else if(N)w.toggleThinkingMode();return}if(x.return){if(b&&R.length>0){let Q1=R[A].command;if(I.hasQuery&&I.suggestions.includes(Q1)){let{newInput:b1,newCursorPos:u0}=f9(O,I,Q1);F(b1),$.setCursorPosition(u0)}else{let b1=Q1+" ";F(b1),$.setCursorPosition(b1.length)}V(!1),L([])}else D1();return}if(x.upArrow){if(b&&R.length>0){let Q1=R.length-1;k((b1)=>b1>0?b1-1:Q1)}else{let Q1=Z();if(Q1){if(Q1.pasteMappings.size>0)$.restorePasteMappings(Q1.pasteMappings);F(Q1.display),$.setCursorPosition(Q1.display.length)}}return}if(x.downArrow){if(b&&R.length>0){let Q1=R.length-1;k((b1)=>b1<Q1?b1+1:0)}else{let Q1=X();if(Q1){if(Q1.pasteMappings.size>0)$.restorePasteMappings(Q1.pasteMappings);F(Q1.display),$.setCursorPosition(Q1.display.length)}}return}},{isActive:H}),{handleSubmit:D1,showSuggestions:b,suggestions:R,selectedSuggestionIndex:A}};K2();import{MultiSelect as qW}from"@inkjs/ui";import{useMemoizedFn as F4}from"ahooks";import{Box as c,Text as h,useFocus as GW,useFocusManager as KW,useInput as WX}from"ink";import z4 from"ink-select-input";import WW from"ink-spinner";import Z6 from"ink-text-input";import GX from"node:fs";import UW from"node:os";import x9 from"node:path";import{useEffect as KX,useState as B$}from"react";import{jsxDEV as M}from"react/jsx-dev-runtime";var HW=[{label:"\uD83D\uDD0D Glob - 文件搜索",value:"Glob"},{label:"\uD83D\uDD0E Grep - 内容搜索",value:"Grep"},{label:"\uD83D\uDCD6 Read - 读取文件",value:"Read"},{label:"✍️ Write - 写入文件",value:"Write"},{label:"✏️ Edit - 编辑文件",value:"Edit"},{label:"\uD83D\uDCBB Bash - 执行命令",value:"Bash"},{label:"✅ 所有工具 (不限制)",value:"all"}],OW=[{label:"\uD83D\uDD34 红色 (red)",value:"red"},{label:"\uD83D\uDD35 蓝色 (blue)",value:"blue"},{label:"\uD83D\uDFE2 绿色 (green)",value:"green"},{label:"\uD83D\uDFE1 黄色 (yellow)",value:"yellow"},{label:"\uD83D\uDFE3 紫色 (purple)",value:"purple"},{label:"\uD83D\uDFE0 橙色 (orange)",value:"orange"},{label:"\uD83E\uDE77 粉色 (pink)",value:"pink"},{label:"\uD83E\uDE75 青色 (cyan)",value:"cyan"},{label:"⚪ 不设置颜色",value:"none"}];function FW($){if(!$||$.trim()==="")return"名称不能为空";if(!/^[a-z0-9-]+$/.test($))return"名称只能包含小写字母、数字和连字符";if($.startsWith("-")||$.endsWith("-"))return"名称不能以连字符开头或结尾";return null}function X6({onComplete:$,onCancel:Y,initialConfig:Z}){let[X,Q]=B$(Z?"name":"mode"),[J,q]=B$({name:Z?.name||"",description:Z?.description||"",tools:Z?.tools||[],color:Z?.color,location:Z?.location||"project",systemPrompt:Z?.systemPrompt||""}),[G,K]=B$(""),[W,U]=B$(!1),[H,O]=B$(""),[F,_]=B$(Z?"edit":"manual"),{focus:z}=KW(),B={manual:["mode","name","description","tools","color","location","systemPrompt","confirm"],ai:["mode","aiPrompt","aiGenerating","confirm"],edit:["name","description","tools","color","location","systemPrompt","confirm"]}[F];KX(()=>{if(X==="name"||X==="description"||X==="systemPrompt"||X==="aiPrompt")return;z(`step-${X}`)},[X,z]);let N=F4(()=>{let A=B.indexOf(X);if(A<B.length-1)Q(B[A+1])}),b=F4(()=>{if(H)O("");if(X==="confirm"&&F==="ai"){Q("aiPrompt");return}let A=B.indexOf(X);if(A>0)Q(B[A-1]);else Y()}),V=F4(async()=>{U(!0),O("");try{let A=await v1.create(),k=`你是一个 Subagent 配置生成专家。用户会描述他们想要创建的 agent,你需要根据描述生成一个完整的 agent 配置。
1452
1504
 
1453
1505
  ## 可用工具列表
1454
1506
 
@@ -1485,7 +1537,7 @@ blade mcp
1485
1537
  4. **color**: 选择一个合适的颜色用于 UI 区分
1486
1538
  5. **systemPrompt**: 详细说明 agent 的职责、使用的工具、输出格式等,使用 Markdown 格式
1487
1539
 
1488
- **重要**:请直接返回 JSON,不要添加任何额外的解释或文字。`,m=(await L.chatWithSystem(`你是一个 Subagent 配置生成专家。用户会描述他们想要创建的 agent,你需要根据描述生成一个完整的 agent 配置。
1540
+ **重要**:请直接返回 JSON,不要添加任何额外的解释或文字。`,T=(await A.chatWithSystem(`你是一个 Subagent 配置生成专家。用户会描述他们想要创建的 agent,你需要根据描述生成一个完整的 agent 配置。
1489
1541
 
1490
1542
  ## 可用工具列表
1491
1543
 
@@ -1522,28 +1574,29 @@ blade mcp
1522
1574
  4. **color**: 选择一个合适的颜色用于 UI 区分
1523
1575
  5. **systemPrompt**: 详细说明 agent 的职责、使用的工具、输出格式等,使用 Markdown 格式
1524
1576
 
1525
- **重要**:请直接返回 JSON,不要添加任何额外的解释或文字。`,K)).trim(),P=m.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);if(P)m=P[1];let v=JSON.parse(m);if(!v.name||!v.description||!v.systemPrompt)throw Error("Missing required fields: name, description, or systemPrompt");if(!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(v.name))throw Error("Invalid name format. Must be kebab-case (lowercase, numbers, hyphens only)");q({name:v.name,description:v.description,tools:Array.isArray(v.tools)?v.tools:[],color:v.color||"blue",location:"project",systemPrompt:v.systemPrompt}),Q("confirm")}catch(L){O(L instanceof Error?L.message:String(L))}finally{U(!1)}});oZ(()=>{if(X==="aiGenerating"&&!W&&!H)D()},[X,W,H,D]);let I=Q4(async()=>{try{let L=J.location==="project"?P9.join(process.cwd(),".blade","agents"):P9.join(aG.homedir(),".blade","agents");await nZ.promises.mkdir(L,{recursive:!0});let V=["---",`name: ${J.name}`,`description: ${J.description}`];if(J.tools.length>0&&!J.tools.includes("all")){V.push("tools:");for(let P of J.tools)V.push(` - ${P}`)}if(J.color)V.push(`color: ${J.color}`);V.push("---");let j=[V.join(`
1577
+ **重要**:请直接返回 JSON,不要添加任何额外的解释或文字。`,G)).trim(),E=T.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);if(E)T=E[1];let v=JSON.parse(T);if(!v.name||!v.description||!v.systemPrompt)throw Error("Missing required fields: name, description, or systemPrompt");if(!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(v.name))throw Error("Invalid name format. Must be kebab-case (lowercase, numbers, hyphens only)");q({name:v.name,description:v.description,tools:Array.isArray(v.tools)?v.tools:[],color:v.color||"blue",location:"project",systemPrompt:v.systemPrompt}),Q("confirm")}catch(A){O(A instanceof Error?A.message:String(A))}finally{U(!1)}});KX(()=>{if(X==="aiGenerating"&&!W&&!H)V()},[X,W,H,V]);let R=F4(async()=>{try{let A=J.location==="project"?x9.join(process.cwd(),".blade","agents"):x9.join(UW.homedir(),".blade","agents");await GX.promises.mkdir(A,{recursive:!0});let k=["---",`name: ${J.name}`,`description: ${J.description}`];if(J.tools.length>0&&!J.tools.includes("all")){k.push("tools:");for(let E of J.tools)k.push(` - ${E}`)}if(J.color)k.push(`color: ${J.color}`);k.push("---");let I=[k.join(`
1526
1578
  `),"",`# ${J.name} Subagent`,"",J.systemPrompt||"你是一个专门的代理,负责执行特定任务。",""].join(`
1527
- `),m=P9.join(L,`${J.name}.md`);await nZ.promises.writeFile(m,j,"utf-8"),$()}catch(L){console.error("保存配置失败:",L)}}),b=P1(!1,Y);if(sZ((L,V)=>{if(V.escape)A();else if(V.ctrl&&L==="c"||V.meta&&L==="c")b()},{isActive:X!=="tools"}),X==="mode")return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"cyan",children:"\uD83C\uDFAF 选择创建方式"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:"你可以手动配置每个细节,或让 AI 根据你的描述自动生成配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(J4,{items:[{label:"\uD83E\uDD16 AI 智能生成 - 根据描述自动生成完整配置",value:"ai"},{label:"✍️ 手动配置 - 逐步配置每个选项",value:"manual"}],onSelect:(L)=>{if(L.value==="ai")_("ai"),Q("aiPrompt");else _("manual"),Q("name")}},void 0,!1,void 0,this),M(g,{marginTop:1,children:M(f,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 取消"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="aiPrompt")return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"cyan",children:"\uD83E\uDD16 AI 智能生成"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:'描述你想要创建的 Agent(例如:"一个专门用于代码审查的 agent,能够分析代码质量和潜在bug")'},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:[M(f,{color:"green",children:"描述: "},void 0,!1,void 0,this),M(s$,{value:K,onChange:G,onSubmit:(L)=>{if(!L.trim())return;Q("aiGenerating")}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(g,{children:M(f,{dimColor:!0,children:"按 Enter 开始生成 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="aiGenerating"){if(H)return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"red",children:"❌ AI 生成失败"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{color:"red",children:H},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:"按 ESC 返回修改描述"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"yellow",children:[M(rG,{type:"dots"},void 0,!1,void 0,this)," AI 正在生成配置..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:['根据你的描述:"',K,'"']},void 0,!0,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{color:"gray",children:"正在调用 LLM 生成 agent 配置,请稍候..."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}if(X==="name"){let L=z==="edit";return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"cyan",children:["\uD83D\uDCDD Step 1/7: ",L?"Agent 名称(不可修改)":"输入 Agent 名称"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:L?"编辑模式下名称不可修改(修改名称相当于创建新 Agent)":"名称只能包含小写字母、数字和连字符(例如:code-reviewer)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:[M(f,{color:"green",children:"名称: "},void 0,!1,void 0,this),L?M(f,{children:J.name},void 0,!1,void 0,this):M(s$,{value:J.name,onChange:(V)=>q({...J,name:V}),onSubmit:(V)=>{if(sG(V))return;B()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(g,{children:M(f,{dimColor:!0,children:L?"按 Enter 继续 | ESC 返回":"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this),L&&M(s$,{value:"",onChange:()=>{},onSubmit:B,showCursor:!1},"edit-mode-dummy-input",!1,void 0,this)]},void 0,!0,void 0,this)}if(X==="description")return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"cyan",children:"\uD83D\uDCDD Step 2/7: 输入描述信息"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:"简短描述这个 Agent 的用途和使用场景(这将帮助主 Agent 决定何时使用它)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:[M(f,{color:"green",children:"描述: "},void 0,!1,void 0,this),M(s$,{value:J.description,onChange:(L)=>q({...J,description:L}),onSubmit:(L)=>{if(!L.trim())return;B()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(g,{children:M(f,{dimColor:!0,children:"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="tools")return M(tG,{config:J,setConfig:q,onNext:B,onPrev:A},void 0,!1,void 0,this);if(X==="color")return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"cyan",children:"\uD83C\uDFA8 Step 4/7: 选择背景颜色"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:"为 Agent 选择一个颜色标识(用于在 UI 中区分不同的 Agents)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(J4,{items:oG,onSelect:(L)=>{let V=L.value==="none"?void 0:L.value;q({...J,color:V}),B()}},void 0,!1,void 0,this),M(g,{marginTop:1,children:M(f,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="location")return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"cyan",children:"\uD83D\uDCC2 Step 5/7: 选择保存位置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:"项目级配置仅在当前项目生效,用户级配置全局可用"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(J4,{items:[{label:"\uD83D\uDCC1 项目级 (.blade/agents/) - 仅当前项目",value:"project"},{label:"\uD83C\uDFE0 用户级 (~/.blade/agents/) - 全局可用",value:"user"}],onSelect:(L)=>{q({...J,location:L.value}),B()}},void 0,!1,void 0,this),M(g,{marginTop:1,children:M(f,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="systemPrompt")return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"cyan",children:"\uD83D\uDCAC Step 6/7: 输入系统提示词"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:"定义 Agent 的行为和职责(可选,留空将使用默认提示)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:[M(f,{color:"green",children:"提示词: "},void 0,!1,void 0,this),M(s$,{value:J.systemPrompt,onChange:(L)=>q({...J,systemPrompt:L}),onSubmit:()=>B()},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(g,{children:M(f,{dimColor:!0,children:"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="confirm")return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"cyan",children:"✅ Step 7/7: 确认配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{flexDirection:"column",paddingLeft:2,marginBottom:1,children:[M(f,{children:[M(f,{bold:!0,color:"green",children:["名称:"," "]},void 0,!0,void 0,this),M(f,{children:J.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(f,{children:[M(f,{bold:!0,color:"green",children:["描述:"," "]},void 0,!0,void 0,this),M(f,{children:J.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(f,{children:[M(f,{bold:!0,color:"green",children:["工具:"," "]},void 0,!0,void 0,this),M(f,{children:J.tools.includes("all")?"所有工具":J.tools.join(", ")||"所有工具"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(f,{children:[M(f,{bold:!0,color:"green",children:["颜色:"," "]},void 0,!0,void 0,this),M(f,{children:J.color||"默认"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(f,{children:[M(f,{bold:!0,color:"green",children:["位置:"," "]},void 0,!0,void 0,this),M(f,{children:J.location==="project"?"项目级":"用户级"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(f,{children:[M(f,{bold:!0,color:"green",children:["提示词:"," "]},void 0,!0,void 0,this),M(f,{children:J.systemPrompt||"(使用默认)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),M(J4,{items:[{label:"✅ 确认并保存",value:"save"},{label:"⬅️ 返回上一步",value:"back"},{label:"❌ 取消",value:"cancel"}],onSelect:(L)=>{if(L.value==="save")I();else if(L.value==="back")A();else Y()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null}function tG({config:$,setConfig:Y,onNext:Z,onPrev:X}){let{isFocused:Q}=lG({id:"step-tools"});sZ((q,K)=>{if(K.escape)X()},{isActive:Q});let J=(q)=>{if(q.includes("all"))Y({...$,tools:["all"]});else Y({...$,tools:q});Z()};return M(g,{flexDirection:"column",paddingY:1,children:[M(g,{marginBottom:1,children:M(f,{bold:!0,color:"cyan",children:"\uD83D\uDD27 Step 3/7: 选择可用工具"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(g,{marginBottom:1,children:M(f,{dimColor:!0,children:"方向键导航,空格切换勾选,Enter 确认进入下一步 | ESC 返回上一步"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(cG,{options:nG,defaultValue:$.tools,onSubmit:J},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}Z$();import{useMemoizedFn as e$}from"ahooks";import{Box as G1,Text as w1,useInput as eG}from"ink";import T9 from"ink-select-input";import $W from"node:fs";import{useMemo as YW,useState as S9}from"react";import{jsxDEV as C}from"react/jsx-dev-runtime";function tZ({initialMode:$="menu",onComplete:Y,onCancel:Z}){let[X,Q]=S9($),[J,q]=S9(null),[K,G]=S9(0),W=e$(()=>{M1.clear(),M1.loadFromStandardLocations(),G((B)=>B+1)}),U=YW(()=>{return M1.getAllSubagents()},[K]),H=[{key:"list",label:"\uD83D\uDCCB 查看所有 Agents",value:"list"},{key:"create",label:"➕ 创建新 Agent",value:"create"},{key:"edit",label:"✏️ 编辑 Agent",value:"edit"},{key:"delete",label:"\uD83D\uDDD1️ 删除 Agent",value:"delete"},{key:"cancel",label:"❌ 取消",value:"cancel"}],O=e$((B)=>{if(B.value==="cancel"){Z?.();return}Q(B.value)}),z=e$((B)=>{if(q(B.value),X==="edit")Q("editWizard");else if(X==="delete")Q("deleteConfirm")}),_=e$(async()=>{if(!J?.configPath)return;try{await $W.promises.unlink(J.configPath),W(),F()}catch(B){console.error("删除失败:",B)}}),F=e$(()=>{Q("menu"),q(null)}),N=P1(!1,Z);if(eG((B,A)=>{if(A.escape){if(X==="menu")Z?.();else if(X==="list"||X==="edit"||X==="delete")F();else if(X==="deleteConfirm")F()}else if(A.ctrl&&B==="c"||A.meta&&B==="c")N()},{isActive:X!=="create"&&X!=="editWizard"}),X==="menu")return C(G1,{flexDirection:"column",paddingY:1,children:[C(G1,{marginBottom:1,children:C(w1,{bold:!0,color:"cyan",children:"\uD83D\uDCCB Agents 管理"},void 0,!1,void 0,this)},void 0,!1,void 0,this),C(T9,{items:H,onSelect:O},void 0,!1,void 0,this),C(G1,{marginTop:1,children:C(w1,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 退出"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="list"){if(U.length===0)return C(G1,{flexDirection:"column",paddingY:1,children:[C(G1,{marginBottom:1,children:C(w1,{bold:!0,color:"cyan",children:"\uD83D\uDCCB 所有 Agents"},void 0,!1,void 0,this)},void 0,!1,void 0,this),C(G1,{paddingLeft:2,children:C(w1,{color:"gray",children:"❌ 没有找到任何 agent 配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),C(G1,{marginTop:1,paddingLeft:2,children:C(w1,{color:"gray",children:"\uD83D\uDCA1 配置文件位置: .blade/agents/ 或 ~/.blade/agents/"},void 0,!1,void 0,this)},void 0,!1,void 0,this),C(G1,{marginTop:1,paddingLeft:2,children:C(w1,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return C(G1,{flexDirection:"column",paddingY:1,children:[C(G1,{marginBottom:1,children:[C(w1,{bold:!0,color:"cyan",children:"\uD83D\uDCCB 所有 Agents"},void 0,!1,void 0,this),C(w1,{color:"gray",children:[" (找到 ",U.length," 个)"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),U.map((B)=>C(G1,{flexDirection:"column",paddingLeft:2,children:[C(G1,{children:C(w1,{children:[C(w1,{bold:!0,color:B.color||"white",children:["• ",B.name]},void 0,!0,void 0,this),C(w1,{color:"gray",children:[" - ",B.description]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),B.tools&&B.tools.length>0&&C(G1,{paddingLeft:2,children:C(w1,{color:"gray",children:["工具: ",B.tools.join(", ")]},void 0,!0,void 0,this)},void 0,!1,void 0,this),B.configPath&&C(G1,{paddingLeft:2,children:C(w1,{color:"gray",dimColor:!0,children:B.configPath},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},B.name,!0,void 0,this)),C(G1,{marginTop:1,paddingLeft:2,children:C(w1,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}let w=(B)=>{if(U.length===0)return C(G1,{flexDirection:"column",paddingY:1,children:[C(G1,{marginBottom:1,children:C(w1,{bold:!0,color:"cyan",children:B},void 0,!1,void 0,this)},void 0,!1,void 0,this),C(G1,{paddingLeft:2,children:C(w1,{color:"gray",children:"❌ 没有找到任何 agent 配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),C(G1,{marginTop:1,paddingLeft:2,children:C(w1,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);let A=U.map((D)=>({key:D.name,label:`${D.name} - ${D.description}`,value:D}));return C(G1,{flexDirection:"column",paddingY:1,children:[C(G1,{marginBottom:1,children:C(w1,{bold:!0,color:"cyan",children:B},void 0,!1,void 0,this)},void 0,!1,void 0,this),C(T9,{items:A,onSelect:z},void 0,!1,void 0,this),C(G1,{marginTop:1,children:C(w1,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};if(X==="create")return C(t$,{onComplete:()=>{W(),F()},onCancel:F},void 0,!1,void 0,this);if(X==="edit")return w("✏️ 编辑 Agent");if(X==="editWizard"&&J){let B={name:J.name,description:J.description,tools:J.tools||[],color:J.color,location:J.configPath?.includes(".blade/agents")?"project":"user",systemPrompt:J.systemPrompt||""};return C(t$,{initialConfig:B,onComplete:()=>{W(),F()},onCancel:F},void 0,!1,void 0,this)}if(X==="delete")return w("\uD83D\uDDD1️ 删除 Agent");if(X==="deleteConfirm"&&J)return C(G1,{flexDirection:"column",paddingY:1,children:[C(G1,{marginBottom:1,children:C(w1,{bold:!0,color:"red",children:"⚠️ 确认删除"},void 0,!1,void 0,this)},void 0,!1,void 0,this),C(G1,{marginBottom:1,paddingLeft:2,children:C(w1,{children:["你确定要删除 Agent"," ",C(w1,{bold:!0,color:"yellow",children:J.name},void 0,!1,void 0,this)," ","吗?"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),C(G1,{marginBottom:1,paddingLeft:2,children:C(w1,{dimColor:!0,children:["文件路径: ",J.configPath]},void 0,!0,void 0,this)},void 0,!1,void 0,this),C(G1,{marginBottom:1,paddingLeft:2,children:C(w1,{color:"red",children:"此操作无法撤销!"},void 0,!1,void 0,this)},void 0,!1,void 0,this),C(T9,{items:[{label:"\uD83D\uDDD1️ 确认删除",value:"confirm"},{label:"❌ 取消",value:"cancel"}],onSelect:(B)=>{if(B.value==="confirm")_();else F()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null}s1();import{Box as _$,Text as O1}from"ink";import XW from"react";m6();b9();import{useEffect as ZW,useState as eZ}from"react";function $X($=process.cwd(),Y=5000){let[Z,X]=eZ(null),[Q,J]=eZ(!0);return ZW(()=>{let q=!0,K=async()=>{try{let W=await c$($);if(!q)return;if(!W){X(null),J(!1);return}let U=await qZ($);if(!q)return;X(U)}catch{if(q)X(null)}finally{if(q)J(!1)}};K();let G=null;if(Y>0)G=setInterval(K,Y);return()=>{if(q=!1,G)clearInterval(G)}},[$,Y]),{branch:Z,loading:Q}}import{jsxDEV as s,Fragment as $6}from"react/jsx-dev-runtime";var YX=XW.memo(()=>{let $=r6(),Y=W2(),Z=U$(),Q=i6()==="shortcuts",J=CY(),{branch:q}=$X(),K=a6(),G=EY(),W=jY(),U=uY(),H=K?q$(K):!1,z=(()=>{if(Z==="default")return null;if(Z==="autoEdit")return s(O1,{color:"magenta",children:["▶▶ auto edit on ",s(O1,{color:"gray",children:"(shift+tab to cycle)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="plan")return s(O1,{color:"cyan",children:["‖ plan mode on ",s(O1,{color:"gray",children:"(shift+tab to cycle)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="yolo")return s(O1,{color:"red",children:["⚡ yolo mode on ",s(O1,{color:"gray",children:"(all tools auto-approved)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null})(),_=z!==null,F=[["Enter:发送","Shift+Enter:换行","Esc:中止"],["Shift+Tab:切换模式","↑/↓:历史","Tab:补全"],["Ctrl+A:行首","Ctrl+E:行尾","Ctrl+K:删到尾"],["Ctrl+U:删到首","Ctrl+W:删单词","Ctrl+C:退出"]];return s(_$,{flexDirection:"row",justifyContent:"space-between",paddingX:2,paddingY:0,children:[Q?s(_$,{flexDirection:"column",gap:0,children:F.map((N,w)=>s(_$,{flexDirection:"row",children:[N.map((B,A)=>{let[D,I]=B.split(":");return s(_$,{flexDirection:"row",width:20,children:[s(O1,{color:"yellow",children:D},void 0,!1,void 0,this),s(O1,{color:"gray",children:":"},void 0,!1,void 0,this),s(O1,{color:"white",children:I},void 0,!1,void 0,this)]},A,!0,void 0,this)}),w===F.length-1&&s(O1,{color:"cyan",children:" ? 关闭"},void 0,!1,void 0,this)]},w,!0,void 0,this))},void 0,!1,void 0,this):s(_$,{flexDirection:"row",gap:1,children:[q&&s($6,{children:[s(O1,{color:"gray",children:[" ",q]},void 0,!0,void 0,this),s(O1,{color:"gray",children:"·"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z,_&&s(O1,{color:"gray",children:"·"},void 0,!1,void 0,this),s(O1,{color:"gray",children:"? for shortcuts"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),s(_$,{flexDirection:"row",gap:1,children:!$?s(O1,{color:"red",children:"⚠ API 密钥未配置"},void 0,!1,void 0,this):s($6,{children:[H&&s($6,{children:[U?s(O1,{color:"cyan",children:"Thinking on"},void 0,!1,void 0,this):s(O1,{color:"gray",children:"Tab:Thinking"},void 0,!1,void 0,this),s(O1,{color:"gray",children:"·"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),K&&s(O1,{color:"gray",children:K.model},void 0,!1,void 0,this),s(O1,{color:"gray",children:"·"},void 0,!1,void 0,this),W?s(O1,{color:"yellow",children:"压缩中..."},void 0,!1,void 0,this):s(O1,{color:G<20?"red":G<50?"yellow":"gray",children:[G,"%"]},void 0,!0,void 0,this),Y&&s($6,{children:[s(O1,{color:"gray",children:"·"},void 0,!1,void 0,this),s(O1,{color:"yellow",children:"Processing..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),J&&s($6,{children:[s(O1,{color:"gray",children:"·"},void 0,!1,void 0,this),s(O1,{color:"yellow",children:"再按一次 Ctrl+C 退出"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{Box as C9,Text as f9}from"ink";import QW from"react";import{jsxDEV as B$}from"react/jsx-dev-runtime";var ZX=QW.memo(({suggestions:$,selectedIndex:Y,visible:Z,maxDisplay:X=8})=>{if(!Z||$.length===0)return null;let Q=0,J=Math.min(X,$.length),q=Y>=$.length;if(Y>=X&&!q)Q=Y-X+1,J=Y+1;let K=$.slice(Q,J),G=$.length>X;return B$(C9,{flexDirection:"column",paddingX:2,paddingY:0,children:[K.map((W,U)=>{let O=Q+U===Y;return B$(C9,{justifyContent:"space-between",paddingX:1,children:[B$(f9,{color:O?"cyan":"white",bold:O,children:W.command},void 0,!1,void 0,this),B$(f9,{color:O?"cyan":"gray",dimColor:!O,children:W.description},void 0,!1,void 0,this)]},W.command,!0,void 0,this)}),G&&B$(C9,{paddingX:1,children:B$(f9,{color:q?"cyan":"gray",bold:q,dimColor:!q,children:["... and ",$.length-X," more"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});s1();import{Box as H0,Text as M0,useInput as mW}from"ink";import dW from"ink-select-input";import{useMemo as uW}from"react";import{useEffect as JW,useState as qW}from"react";import{useStdout as KW}from"ink";import{debounce as GW}from"lodash-es";function N$($=200){let{stdout:Y}=KW(),[Z,X]=qW(Y.columns||80);return JW(()=>{let Q=GW(()=>{X(Y.columns||80)},$);return Q(),Y.on("resize",Q),()=>{Y.off("resize",Q),Q.cancel()}},[Y,$]),Z}import{Box as x1,Text as r1}from"ink";import W4 from"react";var WW={name:"ayu-dark",colors:{primary:"#ffcc66",secondary:"#bae67e",accent:"#73d0ff",success:"#bae67e",warning:"#ffcc66",error:"#ff3333",info:"#73d0ff",light:"#f0f0f0",dark:"#000000",muted:"#5c6773",highlight:"#2d323b",text:{primary:"#e6e1cf",secondary:"#bae67e",muted:"#5c6773",light:"#ffffff"},background:{primary:"#0f1419",secondary:"#14191f",dark:"#000000"},border:{light:"#2d323b",dark:"#000000"},syntax:{comment:"#5c6773",string:"#bae67e",number:"#ffcc66",keyword:"#ff8f40",function:"#73d0ff",variable:"#e6e1cf",operator:"#f29e74",type:"#73d0ff",tag:"#ff8f40",attr:"#ffd580",default:"#e6e1cf"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(0, 0, 0, 0.2)",base:"0 1px 3px 0 rgba(0, 0, 0, 0.3), 0 1px 2px 0 rgba(0, 0, 0, 0.2)",lg:"0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2)"}},UW={name:"dracula",colors:{primary:"#bd93f9",secondary:"#ffb86c",accent:"#ff79c6",success:"#50fa7b",warning:"#f1fa8c",error:"#ff5555",info:"#8be9fd",light:"#f8f8f2",dark:"#282a36",muted:"#6272a4",highlight:"#44475a",text:{primary:"#f8f8f2",secondary:"#f1fa8c",muted:"#6272a4",light:"#ffffff"},background:{primary:"#282a36",secondary:"#44475a",dark:"#21222c"},border:{light:"#44475a",dark:"#000000"},syntax:{comment:"#6272a4",string:"#f1fa8c",number:"#bd93f9",keyword:"#ff79c6",function:"#50fa7b",variable:"#f8f8f2",operator:"#ff79c6",type:"#8be9fd",tag:"#ff79c6",attr:"#50fa7b",default:"#f8f8f2"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(40, 42, 54, 0.2)",base:"0 1px 3px 0 rgba(40, 42, 54, 0.3), 0 1px 2px 0 rgba(40, 42, 54, 0.2)",lg:"0 10px 15px -3px rgba(40, 42, 54, 0.3), 0 4px 6px -2px rgba(40, 42, 54, 0.2)"}},HW={name:"monokai",colors:{primary:"#66d9ef",secondary:"#a6e22e",accent:"#f92672",success:"#a6e22e",warning:"#e6db74",error:"#f92672",info:"#66d9ef",light:"#f8f8f2",dark:"#272822",muted:"#75715e",highlight:"#3e3d32",text:{primary:"#f8f8f2",secondary:"#e6db74",muted:"#75715e",light:"#ffffff"},background:{primary:"#272822",secondary:"#3e3d32",dark:"#1e1f1c"},border:{light:"#3e3d32",dark:"#000000"},syntax:{comment:"#75715e",string:"#e6db74",number:"#ae81ff",keyword:"#f92672",function:"#a6e22e",variable:"#f8f8f2",operator:"#f92672",type:"#66d9ef",tag:"#f92672",attr:"#a6e22e",default:"#f8f8f2"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(39, 40, 34, 0.2)",base:"0 1px 3px 0 rgba(39, 40, 34, 0.3), 0 1px 2px 0 rgba(39, 40, 34, 0.2)",lg:"0 10px 15px -3px rgba(39, 40, 34, 0.3), 0 4px 6px -2px rgba(39, 40, 34, 0.2)"}},OW={name:"nord",colors:{primary:"#88c0d0",secondary:"#81a1c1",accent:"#b48ead",success:"#a3be8c",warning:"#ebcb8b",error:"#bf616a",info:"#88c0d0",light:"#eceff4",dark:"#2e3440",muted:"#4c566a",highlight:"#434c5e",text:{primary:"#eceff4",secondary:"#d8dee9",muted:"#4c566a",light:"#ffffff"},background:{primary:"#2e3440",secondary:"#3b4252",dark:"#242933"},border:{light:"#434c5e",dark:"#000000"},syntax:{comment:"#616e88",string:"#a3be8c",number:"#b48ead",keyword:"#81a1c1",function:"#88c0d0",variable:"#d8dee9",operator:"#81a1c1",type:"#8fbcbb",tag:"#81a1c1",attr:"#8fbcbb",default:"#eceff4"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(46, 52, 64, 0.2)",base:"0 1px 3px 0 rgba(46, 52, 64, 0.3), 0 1px 2px 0 rgba(46, 52, 64, 0.2)",lg:"0 10px 15px -3px rgba(46, 52, 64, 0.3), 0 4px 6px -2px rgba(46, 52, 64, 0.2)"}},zW={name:"solarized-light",colors:{primary:"#268bd2",secondary:"#2aa198",accent:"#d33682",success:"#859900",warning:"#b58900",error:"#dc322f",info:"#268bd2",light:"#fdf6e3",dark:"#073642",muted:"#93a1a1",highlight:"#eee8d5",text:{primary:"#586e75",secondary:"#657b83",muted:"#93a1a1",light:"#002b36"},background:{primary:"#fdf6e3",secondary:"#eee8d5",dark:"#073642"},border:{light:"#eee8d5",dark:"#073642"},syntax:{comment:"#93a1a1",string:"#2aa198",number:"#d33682",keyword:"#859900",function:"#268bd2",variable:"#657b83",operator:"#859900",type:"#b58900",tag:"#268bd2",attr:"#93a1a1",default:"#657b83"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(253, 246, 227, 0.2)",base:"0 1px 3px 0 rgba(253, 246, 227, 0.3), 0 1px 2px 0 rgba(253, 246, 227, 0.2)",lg:"0 10px 15px -3px rgba(253, 246, 227, 0.3), 0 4px 6px -2px rgba(253, 246, 227, 0.2)"}},FW={name:"solarized-dark",colors:{primary:"#268bd2",secondary:"#2aa198",accent:"#d33682",success:"#859900",warning:"#b58900",error:"#dc322f",info:"#268bd2",light:"#fdf6e3",dark:"#073642",muted:"#586e75",highlight:"#073642",text:{primary:"#839496",secondary:"#93a1a1",muted:"#586e75",light:"#fdf6e3"},background:{primary:"#002b36",secondary:"#073642",dark:"#001f29"},border:{light:"#073642",dark:"#000000"},syntax:{comment:"#586e75",string:"#2aa198",number:"#d33682",keyword:"#859900",function:"#268bd2",variable:"#839496",operator:"#859900",type:"#b58900",tag:"#268bd2",attr:"#93a1a1",default:"#839496"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(0, 43, 54, 0.2)",base:"0 1px 3px 0 rgba(0, 43, 54, 0.3), 0 1px 2px 0 rgba(0, 43, 54, 0.2)",lg:"0 10px 15px -3px rgba(0, 43, 54, 0.3), 0 4px 6px -2px rgba(0, 43, 54, 0.2)"}},_W={name:"tokyo-night",colors:{primary:"#7aa2f7",secondary:"#7dcfff",accent:"#bb9af7",success:"#9ece6a",warning:"#e0af68",error:"#f7768e",info:"#7aa2f7",light:"#c0caf5",dark:"#1a1b26",muted:"#565f89",highlight:"#292e42",text:{primary:"#a9b1d6",secondary:"#c0caf5",muted:"#565f89",light:"#ffffff"},background:{primary:"#1a1b26",secondary:"#292e42",dark:"#16161e"},border:{light:"#292e42",dark:"#000000"},syntax:{comment:"#565f89",string:"#9ece6a",number:"#ff9e64",keyword:"#bb9af7",function:"#7aa2f7",variable:"#c0caf5",operator:"#89ddff",type:"#7dcfff",tag:"#f7768e",attr:"#7aa2f7",default:"#a9b1d6"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(26, 27, 38, 0.2)",base:"0 1px 3px 0 rgba(26, 27, 38, 0.3), 0 1px 2px 0 rgba(26, 27, 38, 0.2)",lg:"0 10px 15px -3px rgba(26, 27, 38, 0.3), 0 4px 6px -2px rgba(26, 27, 38, 0.2)"}},BW={name:"github",colors:{primary:"#0969da",secondary:"#8250df",accent:"#bc4c00",success:"#1a7f37",warning:"#9a6700",error:"#d1242f",info:"#0969da",light:"#f6f8fa",dark:"#24292f",muted:"#6e7781",highlight:"#ddf4ff",text:{primary:"#24292f",secondary:"#57606a",muted:"#6e7781",light:"#ffffff"},background:{primary:"#ffffff",secondary:"#f6f8fa",dark:"#24292f"},border:{light:"#d0d7de",dark:"#24292f"},syntax:{comment:"#6e7781",string:"#0a3069",number:"#0550ae",keyword:"#cf222e",function:"#8250df",variable:"#24292f",operator:"#cf222e",type:"#0550ae",tag:"#116329",attr:"#0550ae",default:"#24292f"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(255, 255, 255, 0.2)",base:"0 1px 3px 0 rgba(255, 255, 255, 0.3), 0 1px 2px 0 rgba(255, 255, 255, 0.2)",lg:"0 10px 15px -3px rgba(255, 255, 255, 0.3), 0 4px 6px -2px rgba(255, 255, 255, 0.2)"}},NW={name:"gruvbox",colors:{primary:"#83a598",secondary:"#8ec07c",accent:"#d3869b",success:"#b8bb26",warning:"#fabd2f",error:"#fb4934",info:"#83a598",light:"#fbf1c7",dark:"#282828",muted:"#928374",highlight:"#3c3836",text:{primary:"#ebdbb2",secondary:"#d5c4a1",muted:"#928374",light:"#ffffff"},background:{primary:"#282828",secondary:"#3c3836",dark:"#1d2021"},border:{light:"#3c3836",dark:"#000000"},syntax:{comment:"#928374",string:"#b8bb26",number:"#d3869b",keyword:"#fb4934",function:"#8ec07c",variable:"#ebdbb2",operator:"#fe8019",type:"#fabd2f",tag:"#fb4934",attr:"#b8bb26",default:"#ebdbb2"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(40, 40, 40, 0.2)",base:"0 1px 3px 0 rgba(40, 40, 40, 0.3), 0 1px 2px 0 rgba(40, 40, 40, 0.2)",lg:"0 10px 15px -3px rgba(40, 40, 40, 0.3), 0 4px 6px -2px rgba(40, 40, 40, 0.2)"}},wW={name:"one-dark",colors:{primary:"#61afef",secondary:"#c678dd",accent:"#e5c07b",success:"#98c379",warning:"#e5c07b",error:"#e06c75",info:"#56b6c2",light:"#abb2bf",dark:"#282c34",muted:"#5c6370",highlight:"#3e4451",text:{primary:"#abb2bf",secondary:"#c6c8d0",muted:"#5c6370",light:"#ffffff"},background:{primary:"#282c34",secondary:"#3e4451",dark:"#21252b"},border:{light:"#3e4451",dark:"#000000"},syntax:{comment:"#5c6370",string:"#98c379",number:"#d19a66",keyword:"#c678dd",function:"#61afef",variable:"#e06c75",operator:"#56b6c2",type:"#e5c07b",tag:"#e06c75",attr:"#d19a66",default:"#abb2bf"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(40, 44, 52, 0.2)",base:"0 1px 3px 0 rgba(40, 44, 52, 0.3), 0 1px 2px 0 rgba(40, 44, 52, 0.2)",lg:"0 10px 15px -3px rgba(40, 44, 52, 0.3), 0 4px 6px -2px rgba(40, 44, 52, 0.2)"}},LW={name:"catppuccin",colors:{primary:"#89b4fa",secondary:"#cba6f7",accent:"#f5c2e7",success:"#a6e3a1",warning:"#f9e2af",error:"#f38ba8",info:"#89dceb",light:"#cdd6f4",dark:"#11111b",muted:"#6c7086",highlight:"#181825",text:{primary:"#cdd6f4",secondary:"#bac2de",muted:"#6c7086",light:"#ffffff"},background:{primary:"#1e1e2e",secondary:"#181825",dark:"#11111b"},border:{light:"#181825",dark:"#000000"},syntax:{comment:"#6c7086",string:"#a6e3a1",number:"#fab387",keyword:"#cba6f7",function:"#89b4fa",variable:"#cdd6f4",operator:"#89dceb",type:"#f5c2e7",tag:"#f38ba8",attr:"#89b4fa",default:"#cdd6f4"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(30, 30, 46, 0.2)",base:"0 1px 3px 0 rgba(30, 30, 46, 0.3), 0 1px 2px 0 rgba(30, 30, 46, 0.2)",lg:"0 10px 15px -3px rgba(30, 30, 46, 0.3), 0 4px 6px -2px rgba(30, 30, 46, 0.2)"}},AW={name:"rose-pine",colors:{primary:"#9ccfd8",secondary:"#c4a7e7",accent:"#f6c177",success:"#31748f",warning:"#f6c177",error:"#eb6f92",info:"#9ccfd8",light:"#e0def4",dark:"#191724",muted:"#6e6a86",highlight:"#1f1d2e",text:{primary:"#e0def4",secondary:"#cecacd",muted:"#6e6a86",light:"#ffffff"},background:{primary:"#191724",secondary:"#1f1d2e",dark:"#12101a"},border:{light:"#1f1d2e",dark:"#000000"},syntax:{comment:"#6e6a86",string:"#9ccfd8",number:"#ea9a97",keyword:"#c4a7e7",function:"#31748f",variable:"#e0def4",operator:"#f6c177",type:"#9ccfd8",tag:"#eb6f92",attr:"#f6c177",default:"#e0def4"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(25, 23, 36, 0.2)",base:"0 1px 3px 0 rgba(25, 23, 36, 0.3), 0 1px 2px 0 rgba(25, 23, 36, 0.2)",lg:"0 10px 15px -3px rgba(25, 23, 36, 0.3), 0 4px 6px -2px rgba(25, 23, 36, 0.2)"}},RW={name:"kanagawa",colors:{primary:"#8ba4b0",secondary:"#a292a3",accent:"#c47fd5",success:"#76946a",warning:"#c0a36e",error:"#c34043",info:"#7e9cd8",light:"#dcd7ba",dark:"#1f1f28",muted:"#727169",highlight:"#2a2a37",text:{primary:"#dcd7ba",secondary:"#c8c093",muted:"#727169",light:"#ffffff"},background:{primary:"#1f1f28",secondary:"#2a2a37",dark:"#16161d"},border:{light:"#2a2a37",dark:"#000000"},syntax:{comment:"#727169",string:"#98bb6c",number:"#d27e99",keyword:"#957fb8",function:"#7e9cd8",variable:"#dcd7ba",operator:"#c0a36e",type:"#7aa89f",tag:"#c34043",attr:"#7fb4ca",default:"#dcd7ba"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(31, 31, 40, 0.2)",base:"0 1px 3px 0 rgba(31, 31, 40, 0.3), 0 1px 2px 0 rgba(31, 31, 40, 0.2)",lg:"0 10px 15px -3px rgba(31, 31, 40, 0.3), 0 4px 6px -2px rgba(31, 31, 40, 0.2)"}},h0=[{id:"ayu-dark",label:"Ayu Dark",theme:WW,tags:["dark","popular"]},{id:"dracula",label:"Dracula",theme:UW,tags:["dark","popular"]},{id:"monokai",label:"Monokai",theme:HW,tags:["dark","classic"]},{id:"nord",label:"Nord",theme:OW,tags:["dark","minimal"]},{id:"solarized-light",label:"Solarized Light",theme:zW,tags:["light"]},{id:"solarized-dark",label:"Solarized Dark",theme:FW,tags:["dark"]},{id:"tokyo-night",label:"Tokyo Night",theme:_W,tags:["dark","popular"]},{id:"github",label:"GitHub",theme:BW,tags:["light","minimal"]},{id:"gruvbox",label:"Gruvbox",theme:NW,tags:["dark","warm"]},{id:"one-dark",label:"One Dark",theme:wW,tags:["dark","popular"]},{id:"catppuccin",label:"Catppuccin",theme:LW,tags:["dark","pastel"]},{id:"rose-pine",label:"Rose Pine",theme:AW,tags:["dark","elegant"]},{id:"kanagawa",label:"Kanagawa",theme:RW,tags:["dark","japanese"]}];function q4($){if(!$||typeof $!=="object")return!1;if(!$.name||typeof $.name!=="string")return!1;if(!$.colors||typeof $.colors!=="object")return!1;let Y=["primary","secondary","accent","success","warning","error","info","light","dark","muted","highlight"];for(let J of Y)if(!$.colors[J]||typeof $.colors[J]!=="string")return!1;if(!$.colors.text||typeof $.colors.text!=="object")return!1;if(!$.colors.background||typeof $.colors.background!=="object")return!1;if(!$.colors.border||typeof $.colors.border!=="object")return!1;let Z=["primary","secondary","muted","light"],X=["primary","secondary","dark"],Q=["light","dark"];for(let J of Z)if(!$.colors.text[J]||typeof $.colors.text[J]!=="string")return!1;for(let J of X)if(!$.colors.background[J]||typeof $.colors.background[J]!=="string")return!1;for(let J of Q)if(!$.colors.border[J]||typeof $.colors.border[J]!=="string")return!1;if(!$.spacing||typeof $.spacing!=="object")return!1;if(!$.typography||typeof $.typography!=="object")return!1;if(!$.borderRadius||typeof $.borderRadius!=="object")return!1;if(!$.boxShadow||typeof $.boxShadow!=="object")return!1;return!0}var XX={primary:"#0066cc",secondary:"#6c757d",accent:"#e83e8c",success:"#28a745",warning:"#ffc107",error:"#dc3545",info:"#17a2b8",light:"#f8f9fa",dark:"#343a40",muted:"#6c757d",highlight:"#fff3cd",text:{primary:"#212529",secondary:"#6c757d",muted:"#6c757d",light:"#ffffff"},background:{primary:"#ffffff",secondary:"#f8f9fa",dark:"#343a40"},border:{light:"#dee2e6",dark:"#495057"},syntax:{comment:"#6c757d",string:"#28a745",number:"#e83e8c",keyword:"#007bff",function:"#17a2b8",variable:"#495057",operator:"#ffc107",type:"#007bff",tag:"#dc3545",attr:"#ffc107",default:"#212529"}},K4={name:"default",colors:XX,spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(0, 0, 0, 0.05)",base:"0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)",lg:"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)"}},QX={...K4,name:"dark",colors:{...XX,text:{primary:"#ffffff",secondary:"#e2e8f0",muted:"#94a3b8",light:"#000000"},background:{primary:"#1e293b",secondary:"#334155",dark:"#0f172a"},border:{light:"#475569",dark:"#64748b"},syntax:{comment:"#94a3b8",string:"#34d399",number:"#f472b6",keyword:"#60a5fa",function:"#06b6d4",variable:"#e2e8f0",operator:"#fbbf24",type:"#60a5fa",tag:"#fb7185",attr:"#fbbf24",default:"#ffffff"}}};class h9{currentTheme=K4;themes=new Map;constructor(){this.themes.set("default",K4),this.themes.set("dark",QX);for(let $ of h0)this.themes.set($.id,$.theme)}setTheme($){let Y=this.themes.get($);if(Y)this.currentTheme=Y;else throw Error(`Theme '${$}' not found`)}getTheme(){return this.currentTheme}addTheme($,Y){if(!q4(Y))throw Error(`Invalid theme configuration for '${$}'`);this.themes.set($,Y)}getAvailableThemes(){return Array.from(this.themes.keys())}getCurrentThemeName(){return this.currentTheme.name}getThemeByName($){return this.themes.get($)}removeTheme($){if($==="default"||$==="dark"||h0.some((Z)=>Z.id===$))throw Error(`Cannot remove built-in theme '${$}'`);this.themes.delete($)}hasTheme($){return this.themes.has($)}validateTheme($){return q4($)}}var Y1=new h9;import{Box as w$,Text as O2}from"ink";import{common as bW,createLowlight as VW}from"lowlight";import DW from"react";import{jsxDEV as c1}from"react/jsx-dev-runtime";var x9=VW(bW);function G4($,Y,Z=0){if($.type==="text")return c1(O2,{children:$.value},Z,!1,void 0,this);if($.type==="element"){let X=$.properties?.className?.[0]||"",Q=Y.default;if(X.includes("comment"))Q=Y.comment;else if(X.includes("string"))Q=Y.string;else if(X.includes("number"))Q=Y.number;else if(X.includes("keyword"))Q=Y.keyword;else if(X.includes("function"))Q=Y.function;else if(X.includes("variable"))Q=Y.variable;else if(X.includes("operator"))Q=Y.operator;else if(X.includes("type"))Q=Y.type;else if(X.includes("tag"))Q=Y.tag;else if(X.includes("attr"))Q=Y.attr;let J=$.children?.map((q,K)=>G4(q,Y,K));return c1(O2,{color:Q,children:J},Z,!1,void 0,this)}if($.type==="root"&&$.children)return c1(DW.Fragment,{children:$.children.map((X,Q)=>G4(X,Y,Q))},Z,!1,void 0,this);return c1(O2,{},Z,!1,void 0,this)}function MW($,Y,Z,X){let Q=Z||Y1.getTheme().colors.syntax,J=$;if(X&&$.length>X)J=$.slice(0,X-3)+"...";try{if(!Y||!x9.registered(Y)){let K=x9.highlightAuto(J);return G4(K,Q)}let q=x9.highlight(Y,J);return G4(q,Q)}catch(q){return c1(O2,{color:Q.default,children:J},void 0,!1,void 0,this)}}var p9=({content:$,language:Y,showLineNumbers:Z=!0,terminalWidth:X,availableHeight:Q})=>{let J=Y1.getTheme(),q=$.split(`
1528
- `),K=0;if(Q&&q.length>Q){let H=Math.max(Q,5);if(q.length>H)K=q.length-H,q=q.slice(K)}let G=q.length+K,W=String(G).length+1;return c1(w$,{borderStyle:"round",borderColor:J.colors.border.light,paddingX:1,paddingY:0,marginY:1,flexDirection:"column",children:[Y&&c1(w$,{marginBottom:0,children:c1(O2,{color:J.colors.text.secondary,children:Y},void 0,!1,void 0,this)},void 0,!1,void 0,this),K>0&&c1(w$,{marginBottom:0,children:c1(O2,{color:J.colors.text.muted,dimColor:!0,children:["... ",K," lines hidden ..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this),q.map((U,H)=>{let O=H+K+1;return c1(w$,{flexDirection:"row",children:[Z&&c1(w$,{width:W,children:c1(O2,{color:J.colors.text.muted,dimColor:!0,children:String(O).padStart(W-1," ")},void 0,!1,void 0,this)},void 0,!1,void 0,this),c1(w$,{flexShrink:1,children:U.trim()===""?c1(O2,{children:" "},void 0,!1,void 0,this):MW(U,Y,J.colors.syntax)},void 0,!1,void 0,this)]},H,!0,void 0,this)})]},void 0,!0,void 0,this)};import{Box as JX,Text as x0}from"ink";import{jsxDEV as K0}from"react/jsx-dev-runtime";function IW($){let Y=$.split(`
1529
- `),Z=[],X=0,Q=0;for(let J of Y){if(J.startsWith("---")||J.startsWith("+++"))continue;if(J.startsWith("@@")){let q=J.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);if(q)X=parseInt(q[1],10),Q=parseInt(q[3],10);Z.push({type:"header",content:J});continue}if(J.startsWith("-")){Z.push({type:"remove",content:J.substring(1),lineNumber:X}),X++;continue}if(J.startsWith("+")){Z.push({type:"add",content:J.substring(1),lineNumber:Q}),Q++;continue}if(J.startsWith(" ")||J===""){Z.push({type:"context",content:J.substring(1),lineNumber:Q}),X++,Q++;continue}}return Z}var g9=({patch:$,startLine:Y,matchLine:Z,terminalWidth:X,maxLines:Q=20})=>{let J=Y1.getTheme(),q=IW($),G=Math.max(...q.map((z)=>z.lineNumber||0)).toString().length+1,W=q.length,U=W>Q,H=U?q.slice(0,Q):q,O=W-Q;return K0(JX,{flexDirection:"column",marginTop:1,marginBottom:1,children:[K0(x0,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,X)))},void 0,!1,void 0,this),U&&K0(x0,{color:J.colors.info,children:["\uD83D\uDCCA 显示前 ",Q," 行,共 ",W," 行 diff"]},void 0,!0,void 0,this),U&&K0(x0,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,X)))},void 0,!1,void 0,this),H.map((z,_)=>{if(z.type==="header")return K0(x0,{color:J.colors.muted,dimColor:!0,children:z.content},_,!1,void 0,this);let F=z.lineNumber?z.lineNumber.toString().padStart(G," "):" ".repeat(G),N=" ",w,B;if(z.type==="add")N="+",B=J.colors.success,w=void 0;else if(z.type==="remove")N="-",B=J.colors.error,w=void 0;else B=J.colors.text.primary;let A=Math.max(0,X-G-2),D=z.content;if(D.length>A)D=D.substring(0,A-3)+"...";return K0(x0,{color:B,backgroundColor:w,children:[K0(x0,{dimColor:!0,children:F},void 0,!1,void 0,this),K0(x0,{children:N},void 0,!1,void 0,this),K0(x0,{children:[" ",D]},void 0,!0,void 0,this)]},_,!0,void 0,this)}),U&&K0(JX,{marginTop:1,children:K0(x0,{color:J.colors.warning,dimColor:!0,children:["⚠️ 已隐藏剩余 ",O," 行 diff(总共 ",W," 行)"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),K0(x0,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,X)))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Text as V0}from"ink";import jW from"react";import kW from"string-width";var y2=($)=>{let Y=$.replace(/\*\*(.*?)\*\*/g,"$1").replace(/\*(.*?)\*/g,"$1").replace(/_(.*?)_/g,"$1").replace(/~~(.*?)~~/g,"$1").replace(/`(.*?)`/g,"$1").replace(/<u>(.*?)<\/u>/g,"$1").replace(/\[(.*?)\]\(.*?\)/g,"$1");return kW(Y)},qX=($,Y,Z="...")=>{if(y2($)<=Y)return $;if(Y<=Z.length)return Z.substring(0,Y);let Q=0,J=$.length,q="";while(Q<=J){let K=Math.floor((Q+J)/2),G=$.substring(0,K);if(y2(G)<=Y-Z.length)q=G,Q=K+1;else J=K-1}return q+Z},KX=($)=>{return/[*_~`<[\]https?:]/.test($)};import{jsxDEV as G0,Fragment as yW}from"react/jsx-dev-runtime";var m9=2,d9=1,u9=2;var EW=({text:$})=>{let Y=Y1.getTheme();if(!KX($))return G0(V0,{children:$},void 0,!1,void 0,this);let Z=[],X=0,Q=/(\*\*.*?\*\*|\*(?!\s).*?(?<!\s)\*|_(?!\s).*?(?<!\s)_|~~.*?~~|`+[^`]+`+|\[.*?\]\(.*?\)|https?:\/\/\S+)/g,J;while((J=Q.exec($))!==null){if(J.index>X)Z.push(G0(V0,{children:$.slice(X,J.index)},`t-${X}`,!1,void 0,this));let q=J[0],K=null,G=`m-${J.index}`;try{if(q.startsWith("**")&&q.endsWith("**")&&q.length>m9*2)K=G0(V0,{bold:!0,children:q.slice(m9,-m9)},G,!1,void 0,this);else if(q.length>d9*2&&(q.startsWith("*")&&q.endsWith("*")||q.startsWith("_")&&q.endsWith("_"))){let W=$.substring(J.index-1,J.index),U=$.substring(Q.lastIndex,Q.lastIndex+1);if(!(/\w/.test(W)||/\w/.test(U)||/[./\\]/.test(W+U)))K=G0(V0,{italic:!0,children:q.slice(d9,-d9)},G,!1,void 0,this)}else if(q.startsWith("~~")&&q.endsWith("~~")&&q.length>u9*2)K=G0(V0,{strikethrough:!0,children:q.slice(u9,-u9)},G,!1,void 0,this);else if(q.startsWith("`")&&q.endsWith("`")){let W=q.match(/^(`+)([^`]+)\1$/);if(W&&W[2])K=G0(V0,{color:Y.colors.syntax.keyword,backgroundColor:Y.colors.background.secondary,bold:!0,children:` ${W[2]} `},G,!1,void 0,this)}else if(q.startsWith("[")&&q.includes("](")&&q.endsWith(")")){let W=q.match(/\[(.*?)\]\((.*?)\)/);if(W){let U=W[1],H=W[2];K=G0(V0,{children:[U,G0(V0,{color:Y.colors.info,children:[" (",H,")"]},void 0,!0,void 0,this)]},G,!0,void 0,this)}}else if(q.match(/^https?:\/\//))K=G0(V0,{color:Y.colors.info,children:q},G,!1,void 0,this)}catch(W){console.error("InlineRenderer 解析错误:",q,W),K=null}Z.push(K??G0(V0,{children:q},G,!1,void 0,this)),X=Q.lastIndex}if(X<$.length)Z.push(G0(V0,{children:$.slice(X)},`t-${X}`,!1,void 0,this));return G0(yW,{children:Z.filter((q)=>q!==null)},void 0,!1,void 0,this)},W0=jW.memo(EW);import{Box as c9,Text as GX}from"ink";import vW from"react";import{jsxDEV as L$}from"react/jsx-dev-runtime";var PW=({itemText:$,type:Y,marker:Z,leadingWhitespace:X=""})=>{let Q=Y==="ol"?`${Z}. `:`${Z} `,J=Q.length,q=X.length;return L$(c9,{paddingLeft:q+1,flexDirection:"row",children:[L$(c9,{width:J,children:L$(GX,{children:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),L$(c9,{flexGrow:1,children:L$(GX,{wrap:"wrap",children:L$(W0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},WX=vW.memo(PW);import{Box as TW,Text as v2}from"ink";import UX from"react";import{jsxDEV as U0}from"react/jsx-dev-runtime";var HX=({headers:$,rows:Y,terminalWidth:Z})=>{let X=Y1.getTheme();if($.length===0||Y.length===0)return null;let Q=$.map((O,z)=>{let _=y2(O),F=Math.max(...Y.map((N)=>y2(N[z]||"")));return Math.max(_,F)+2}),J=$.length+1,q=Q.reduce((O,z)=>O+z,0)+J,K=q>Z?Z/q:1,G=Q.map((O)=>Math.floor(O*K)),W=(O,z,_=!1)=>{let F=Math.max(0,z-2),N=y2(O),w=O;if(N>F)w=qX(O,F);let B=y2(w),A=Math.max(0,F-B);return U0(v2,{children:[_?U0(v2,{bold:!0,color:X.colors.primary,children:U0(W0,{text:w},void 0,!1,void 0,this)},void 0,!1,void 0,this):U0(W0,{text:w},void 0,!1,void 0,this)," ".repeat(A)]},void 0,!0,void 0,this)},U=(O)=>{let _={top:{left:"┌",middle:"┬",right:"┐",horizontal:"─"},middle:{left:"├",middle:"┼",right:"┤",horizontal:"─"},bottom:{left:"└",middle:"┴",right:"┘",horizontal:"─"}}[O],F=G.map((w)=>_.horizontal.repeat(w)),N=_.left+F.join(_.middle)+_.right;return U0(v2,{color:X.colors.text.muted,dimColor:!0,children:N},void 0,!1,void 0,this)},H=(O,z=!1)=>{let _=O.map((F,N)=>{let w=G[N]||0;return W(F||"",w,z)});return U0(v2,{children:[U0(v2,{color:X.colors.text.muted,children:"│ "},void 0,!1,void 0,this),_.map((F,N)=>U0(UX.Fragment,{children:[F,N<_.length-1&&U0(v2,{color:X.colors.text.muted,children:" │ "},void 0,!1,void 0,this)]},N,!0,void 0,this)),U0(v2,{color:X.colors.text.muted,children:" │"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};return U0(TW,{flexDirection:"column",marginY:1,children:[U("top"),H($,!0),U("middle"),Y.map((O,z)=>U0(UX.Fragment,{children:H(O)},z,!1,void 0,this)),U("bottom")]},void 0,!0,void 0,this)};import{jsxDEV as p}from"react/jsx-dev-runtime";var SW=($,Y)=>{let X=Y1.getTheme().colors;switch($){case"user":return{color:X.info,prefix:"> "};case"assistant":return{color:X.success,prefix:"• "};case"system":return{color:X.warning,prefix:"⚙ "};case"tool":{let Q=Y&&"phase"in Y?Y.phase:void 0;return{color:X.text.secondary,prefix:Q==="start"?"• ":Q==="complete"?" └ ":" "}}default:return{color:X.text.primary,prefix:" "}}},D0={codeBlock:/^```(\w+)?\s*$/,heading:/^ *(#{1,4}) +(.+)/,ulItem:/^([ \t]*)([-*+]) +(.+)/,olItem:/^([ \t]*)(\d+)\. +(.+)/,hr:/^ *([-*_] *){3,} *$/,table:/^\|(.+)\|$/,tableSeparator:/^\|[\s]*:?-+:?[\s]*(\|[\s]*:?-+:?[\s]*)+\|?$/,diffStart:/^<<<DIFF>>>$/,diffEnd:/^<<<\/DIFF>>>$/};function CW($){let Y=[],Z=$.split(/\r?\n/),X=!1,Q=[],J=null,q=!1,K=[],G=[],W=!1,U=[],H=!0;for(let O=0;O<Z.length;O++){let z=Z[O];if(W){if(z.match(D0.diffEnd)){try{let I=JSON.parse(U.join(`
1530
- `));Y.push({type:"diff",content:"",diffData:{patch:I.patch,startLine:I.startLine,matchLine:I.matchLine}})}catch(I){Y.push({type:"text",content:U.join(`
1531
- `)})}W=!1,U=[],H=!1;continue}U.push(z);continue}if(z.match(D0.diffStart)){W=!0,U=[],H=!1;continue}if(X){if(z.match(D0.codeBlock))Y.push({type:"code",content:Q.join(`
1532
- `),language:J||void 0}),X=!1,Q=[],J=null,H=!1;else Q.push(z);continue}let _=z.match(D0.codeBlock);if(_){X=!0,J=_[1]||null,H=!1;continue}let F=z.match(D0.table),N=z.match(D0.tableSeparator);if(F&&!q){if(O+1<Z.length){if(Z[O+1].match(D0.tableSeparator)){q=!0,K=F[1].split("|").map((b)=>b.trim()).filter((b)=>b.length>0),G=[],H=!1;continue}}}if(q&&N)continue;if(q&&F){let I=F[1].split("|").map((b)=>b.trim()).filter((b)=>b.length>0);while(I.length<K.length)I.push("");if(I.length>K.length)I.length=K.length;G.push(I);continue}if(q&&!F){if(K.length>0&&G.length>0)Y.push({type:"table",content:"",tableData:{headers:K,rows:G}});q=!1,K=[],G=[]}let w=z.match(D0.heading);if(w){Y.push({type:"heading",content:w[2],level:w[1].length}),H=!1;continue}let B=z.match(D0.ulItem);if(B){Y.push({type:"list",content:B[3],listType:"ul",marker:B[2],indentation:B[1].length}),H=!1;continue}let A=z.match(D0.olItem);if(A){Y.push({type:"list",content:A[3],listType:"ol",marker:A[2],indentation:A[1].length}),H=!1;continue}if(z.match(D0.hr)){Y.push({type:"hr",content:""}),H=!1;continue}if(z.trim().length===0){if(!H)Y.push({type:"empty",content:""}),H=!0;continue}Y.push({type:"text",content:z}),H=!1}if(X)Y.push({type:"code",content:Q.join(`
1533
- `),language:J||void 0});if(q&&K.length>0&&G.length>0)Y.push({type:"table",content:"",tableData:{headers:K,rows:G}});return Y}var fW=({content:$,language:Y,terminalWidth:Z})=>{return p(p9,{content:$,language:Y,showLineNumbers:!0,terminalWidth:Z},void 0,!1,void 0,this)},hW=({content:$,level:Y})=>{let Z=Y1.getTheme();switch(Y){case 1:return p(r1,{bold:!0,color:Z.colors.primary,children:p(W0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 2:return p(r1,{bold:!0,color:Z.colors.primary,children:p(W0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 3:return p(r1,{bold:!0,color:Z.colors.text.primary,children:p(W0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 4:return p(r1,{italic:!0,color:Z.colors.text.muted,children:p(W0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);default:return p(r1,{children:p(W0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)}},xW=({terminalWidth:$})=>{let Y=Y1.getTheme(),Z=Math.max(0,Math.min($-4,80));return p(r1,{dimColor:!0,color:Y.colors.text.muted,children:"─".repeat(Z)},void 0,!1,void 0,this)},pW=({content:$})=>{return p(r1,{wrap:"wrap",children:p(W0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)},gW=W4.memo(({detail:$,terminalWidth:Y})=>{let Z=Y1.getTheme(),X=50,Q=$.split(`
1534
- `),J=Q.length>50,q=J?Q.slice(0,50):Q,K=q.join(`
1535
- `),G=K.includes("<<<DIFF>>>"),W=K.includes("```");if(G){let U=K.match(/<<<DIFF>>>\s*({[\s\S]*?})\s*<<<\/DIFF>>>/);if(U)try{let H=JSON.parse(U[1]);return p(x1,{flexDirection:"column",children:[p(g9,{patch:H.patch,startLine:H.startLine,matchLine:H.matchLine,terminalWidth:Y},void 0,!1,void 0,this),J&&p(x1,{marginTop:1,children:p(r1,{dimColor:!0,color:Z.colors.text.muted,children:["... 省略 ",Q.length-50," 行 ..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}catch{}}if(W){let U=K.match(/```(\w+)?\s*\n([\s\S]*?)\n```/);if(U){let H=U[1]||"text",O=U[2];return p(x1,{flexDirection:"column",children:[p(p9,{content:O,language:H,showLineNumbers:!1,terminalWidth:Y},void 0,!1,void 0,this),J&&p(x1,{marginTop:1,children:p(r1,{dimColor:!0,color:Z.colors.text.muted,children:["... 省略 ",Q.length-50," 行 ..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}}return p(x1,{flexDirection:"column",children:[q.map((U,H)=>p(r1,{color:Z.colors.text.primary,children:U},H,!1,void 0,this)),J&&p(x1,{marginTop:1,children:p(r1,{dimColor:!0,color:Z.colors.text.muted,children:["... 省略 ",Q.length-50," 行 ..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}),Y6=W4.memo(({content:$,role:Y,terminalWidth:Z,metadata:X,isPending:Q=!1})=>{let J=W4.useMemo(()=>SW(Y,X),[Y,X]),{color:q,prefix:K}=J;if(Y==="tool"&&X&&"detail"in X){let W=X;if(W.detail)return p(x1,{flexDirection:"column",marginBottom:1,children:[p(x1,{flexDirection:"row",children:[p(x1,{marginRight:1,children:p(r1,{color:q,bold:!0,children:K},void 0,!1,void 0,this)},void 0,!1,void 0,this),p(r1,{color:q,children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),p(x1,{marginLeft:K.length+1,marginTop:1,children:p(gW,{detail:W.detail,terminalWidth:Z-(K.length+1)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}let G=W4.useMemo(()=>CW($),[$]);return p(x1,{flexDirection:"column",marginBottom:1,children:G.map((W,U)=>{if(W.type==="empty")return p(x1,{height:1},U,!1,void 0,this);return p(x1,{flexDirection:"row",children:[U===0&&p(x1,{marginRight:1,children:p(r1,{color:q,bold:!0,children:K},void 0,!1,void 0,this)},void 0,!1,void 0,this),U>0&&p(x1,{width:K.length+1},void 0,!1,void 0,this),p(x1,{flexGrow:1,children:W.type==="code"?p(fW,{content:W.content,language:W.language,terminalWidth:Z-(K.length+1)},void 0,!1,void 0,this):W.type==="table"&&W.tableData?p(HX,{headers:W.tableData.headers,rows:W.tableData.rows,terminalWidth:Z-(K.length+1)},void 0,!1,void 0,this):W.type==="heading"?p(hW,{content:W.content,level:W.level||1},void 0,!1,void 0,this):W.type==="list"?p(WX,{type:W.listType||"ul",marker:W.marker||"-",itemText:W.content,leadingWhitespace:" ".repeat(W.indentation||0)},void 0,!1,void 0,this):W.type==="hr"?p(xW,{terminalWidth:Z-(K.length+1)},void 0,!1,void 0,this):W.type==="diff"&&W.diffData?p(g9,{patch:W.diffData.patch,startLine:W.diffData.startLine,matchLine:W.diffData.matchLine,terminalWidth:Z-(K.length+1)},void 0,!1,void 0,this):p(pW,{content:W.content},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},U,!0,void 0,this)})},void 0,!1,void 0,this)},($,Y)=>{return $.content===Y.content&&$.role===Y.role&&$.terminalWidth===Y.terminalWidth&&$.isPending===Y.isPending&&JSON.stringify($.metadata)===JSON.stringify(Y.metadata)});import{jsxDEV as _1}from"react/jsx-dev-runtime";var cW=({label:$,isSelected:Y})=>_1(M0,{color:Y?"yellow":void 0,children:$},void 0,!1,void 0,this),OX=({details:$,onResponse:Y})=>{let Z=N$(),Q=q0()==="confirmation-prompt",J=P1(!1),q=$.type==="exitPlanMode",K=$.type==="enterPlanMode",G=$.type==="maxTurnsExceeded";mW((O,z)=>{if(z.ctrl&&O==="c"||z.meta&&O==="c"){J();return}if(z.escape){Y({approved:!1,reason:"用户取消"});return}let _=O.toLowerCase();if(q){if(_==="y"){Y({approved:!0,targetMode:"autoEdit"});return}if(_==="s"){Y({approved:!0,targetMode:"default"});return}if(_==="n"){Y({approved:!1,reason:"方案需要改进"});return}}else if(K){if(_==="y"){Y({approved:!0});return}if(_==="n"){Y({approved:!1,reason:"用户拒绝进入 Plan 模式"});return}}else if(G){if(_==="y"){Y({approved:!0});return}if(_==="n"){Y({approved:!1,reason:"用户选择停止"});return}}else{if(_==="y"){Y({approved:!0,scope:"once"});return}if(_==="s"){Y({approved:!0,scope:"session"});return}if(_==="n"){Y({approved:!1,reason:"用户拒绝"});return}}},{isActive:Q});let W=uW(()=>{if(q)return[{key:"approve-auto",label:"[Y] Yes, execute with auto-edit mode",value:{approved:!0,targetMode:"autoEdit"}},{key:"approve-default",label:"[S] Yes, execute with default mode (ask for each operation)",value:{approved:!0,targetMode:"default"}},{key:"reject",label:"[N] No, keep planning",value:{approved:!1,reason:"方案需要改进"}}];if(K)return[{key:"approve",label:"[Y] Yes, enter Plan mode",value:{approved:!0}},{key:"reject",label:"[N] No, proceed directly",value:{approved:!1,reason:"用户拒绝进入 Plan 模式"}}];if(G)return[{key:"continue",label:"[Y] Yes, continue",value:{approved:!0}},{key:"stop",label:"[N] No, stop here",value:{approved:!1,reason:"用户选择停止"}}];return[{key:"approve-once",label:"[Y] Yes (once only)",value:{approved:!0,scope:"once"}},{key:"approve-session",label:"[S] Yes, remember for this project (Shift+Tab)",value:{approved:!0,scope:"session"}},{key:"reject",label:"[N] No",value:{approved:!1,reason:"用户拒绝"}}]},[q,K,G]),H=(()=>{if(q)return{color:"cyan",title:"\uD83D\uDD35 Plan Mode - Review Implementation Plan"};if(K)return{color:"magenta",title:"\uD83D\uDFE3 Enter Plan Mode?"};if(G)return{color:"yellow",title:"⚡ Max Turns Exceeded"};return{color:"yellow",title:"\uD83D\uDD14 Confirmation Required"}})();return _1(H0,{flexDirection:"column",borderStyle:"round",borderColor:Q?H.color:"gray",padding:1,children:[_1(H0,{marginBottom:1,children:_1(M0,{bold:!0,color:H.color,children:H.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),$.title&&_1(H0,{marginBottom:1,children:_1(M0,{bold:!0,children:$.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),_1(H0,{marginBottom:1,children:_1(M0,{children:$.message},void 0,!1,void 0,this)},void 0,!1,void 0,this),($.planContent||$.details)&&_1(H0,{flexDirection:"column",marginBottom:1,borderStyle:"single",borderColor:H.color,padding:1,children:[_1(M0,{bold:!0,color:H.color,children:q?"\uD83D\uDCCB Implementation Plan:":K?"\uD83D\uDCDD Details:":"\uD83D\uDCC4 Operation Details:"},void 0,!1,void 0,this),_1(H0,{marginTop:1,children:_1(Y6,{content:$.planContent||$.details||"",role:"assistant",terminalWidth:Z-4},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$.risks&&$.risks.length>0&&_1(H0,{flexDirection:"column",marginBottom:1,children:[_1(M0,{color:"red",bold:!0,children:"⚠️ 风险提示:"},void 0,!1,void 0,this),$.risks.map((O,z)=>_1(H0,{marginLeft:2,children:_1(M0,{color:"red",children:["• ",O]},void 0,!0,void 0,this)},z,!1,void 0,this))]},void 0,!0,void 0,this),$.affectedFiles&&$.affectedFiles.length>0&&_1(H0,{flexDirection:"column",marginBottom:1,children:[_1(M0,{color:"yellow",children:"\uD83D\uDCC1 影响的文件:"},void 0,!1,void 0,this),$.affectedFiles.slice(0,3).map((O,z)=>_1(H0,{marginLeft:2,children:_1(M0,{children:["• ",O]},void 0,!0,void 0,this)},z,!1,void 0,this)),$.affectedFiles.length>3&&_1(H0,{marginLeft:2,children:_1(M0,{color:"gray",children:["...还有 ",$.affectedFiles.length-3," 个文件"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_1(H0,{flexDirection:"column",children:[_1(M0,{color:"gray",children:"使用 ↑ ↓ 选择,回车确认(支持 Y/S/N 快捷键,ESC 取消)"},void 0,!1,void 0,this),_1(dW,{items:W,isFocused:Q,itemComponent:cW,onSelect:(O)=>{Y(O.value)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{useMemoizedFn as RX}from"ahooks";import{Box as UU,Text as HU}from"ink";import OU from"react";import{writeFileSync as lW}from"node:fs";import{join as iW}from"node:path";import{tmpdir as rW}from"node:os";import{nanoid as aW}from"nanoid";function zX($,Y,Z){let X=nW(Y),Q=Date.now(),J=aW(8),q=Z||`blade_image_${Q}_${J}.${X}`,K=rW(),G=iW(K,q),W=Buffer.from($,"base64");lW(G,W);let U=`[Image: ${q}]`;return console.log(`[ImageHandler] Saved image to: ${G}`),console.log(`[ImageHandler] Size: ${(W.length/1024).toFixed(2)} KB`),{filePath:G,filename:q,tag:U}}function nW($){return{"image/png":"png","image/jpeg":"jpg","image/jpg":"jpg","image/gif":"gif","image/webp":"webp","image/bmp":"bmp","image/svg+xml":"svg"}[$]||"png"}import{useMemoizedFn as XU}from"ahooks";import P2 from"chalk";import{Text as QU,useInput as JU}from"ink";import{useEffect as LX,useRef as qU}from"react";var z2={TIMEOUT_MS:100,RAPID_INPUT_THRESHOLD_MS:150,LARGE_INPUT_THRESHOLD:300,MEDIUM_SIZE_MULTI_CHUNK_THRESHOLD:200};import{execSync as oW}from"node:child_process";import{existsSync as QM,readFileSync as FX}from"node:fs";import{basename as _X,isAbsolute as sW}from"node:path";function tW(){let $=process.platform,Y={darwin:"No image found in clipboard. Use Cmd + Ctrl + Shift + 4 to copy a screenshot to clipboard.",win32:"No image found in clipboard. Use Print Screen to copy a screenshot to clipboard.",linux:"No image found in clipboard. Use appropriate screenshot tool to copy a screenshot to clipboard."};return Y[$]||Y.linux}var qM=tW();function eW($){try{let Y=Buffer.from($,"base64");if(Y.length<4)return"image/png";if(Y[0]===137&&Y[1]===80&&Y[2]===78&&Y[3]===71)return"image/png";if(Y[0]===255&&Y[1]===216&&Y[2]===255)return"image/jpeg";if(Y[0]===71&&Y[1]===73&&Y[2]===70)return"image/gif";if(Y[0]===82&&Y[1]===73&&Y[2]===70&&Y[3]===70){if(Y.length>=12&&Y[8]===87&&Y[9]===69&&Y[10]===66&&Y[11]===80)return"image/webp"}return"image/png"}catch{return"image/png"}}function $U(){let $=process.platform,Y={darwin:"/tmp/blade_cli_latest_screenshot.png",linux:"/tmp/blade_cli_latest_screenshot.png",win32:process.env.TEMP?`${process.env.TEMP}\\blade_cli_latest_screenshot.png`:"C:\\Temp\\blade_cli_latest_screenshot.png"},Z={darwin:{checkImage:"osascript -e 'the clipboard as «class PNGf»'",saveImage:(X)=>`osascript -e 'set png_data to (the clipboard as «class PNGf»)' -e 'set fp to open for access POSIX file "${X}" with write permission' -e 'write png_data to fp' -e 'close access fp'`,getPath:"osascript -e 'get POSIX path of (the clipboard as «class furl»)'",deleteFile:(X)=>`rm -f "${X}"`},linux:{checkImage:'xclip -selection clipboard -t TARGETS -o | grep -E "image/(png|jpeg|jpg|gif|webp)"',saveImage:(X)=>`xclip -selection clipboard -t image/png -o > "${X}" || wl-paste --type image/png > "${X}"`,getPath:"xclip -selection clipboard -t text/plain -o",deleteFile:(X)=>`rm -f "${X}"`},win32:{checkImage:'powershell -Command "(Get-Clipboard -Format Image) -ne $null"',saveImage:(X)=>`powershell -Command "$img = Get-Clipboard -Format Image; if ($img) { $img.Save('${X.replace(/\\/g,"\\\\")}', [System.Drawing.Imaging.ImageFormat]::Png) }"`,getPath:'powershell -Command "Get-Clipboard"',deleteFile:(X)=>`del /f "${X}"`}};return{commands:Z[$]||Z.linux,screenshotPath:Y[$]||Y.linux}}function YU(){let{commands:$}=$U();try{return oW($.getPath,{encoding:"utf-8"}).trim()}catch(Y){return console.error("Failed to get clipboard path:",Y),null}}function BX($){if($.startsWith('"')&&$.endsWith('"')||$.startsWith("'")&&$.endsWith("'"))return $.slice(1,-1);return $}function NX($){if(process.platform==="win32")return $;let Y="__DOUBLE_BACKSLASH__";return $.replace(/\\\\/g,Y).replace(/\\(.)/g,"$1").replace(new RegExp(Y,"g"),"\\")}function l9($){let Y=BX($.trim()),Z=NX(Y);return/\.(png|jpe?g|gif|webp)$/i.test(Z)}function ZU($){let Y=BX($.trim()),Z=NX(Y);if(l9(Z))return Z;return null}async function wX($){let Y=ZU($);if(!Y)return null;let Z;try{if(sW(Y))Z=FX(Y);else{let q=YU();if(q&&Y===_X(q))Z=FX(q);else return null}}catch(q){return console.error("Failed to read image file:",q),null}let X=Z.toString("base64"),Q=eW(X),J=_X(Y);return{path:Y,base64:X,mediaType:Q,filename:J}}import{jsxDEV as WU}from"react/jsx-dev-runtime";var KU=/\r\n/g,GU=/\r/g;function U4($){if(!$.includes("\r"))return $;return $.replace(KU,`
1536
- `).replace(GU,`
1537
- `)}function H4($,Y,Z){let X=Math.max(0,Math.min(Z,Y.length)),Q=Y.slice(0,X),J=Y.slice(X);return{newValue:Q+$+J,newCursorPosition:X+$.length}}function AX({value:$,placeholder:Y="",focus:Z=!0,onChange:X,cursorPosition:Q,onChangeCursorPosition:J,onPaste:q,onImagePaste:K,disabledKeys:G=[]}){let W=qU({chunks:[],timeoutId:null,firstInputTime:null,lastInputTime:null,totalLength:0});LX(()=>{return()=>{if(W.current.timeoutId)clearTimeout(W.current.timeoutId)}},[]),LX(()=>{if(Q>$.length)J($.length)},[$,Q,J]);let U=XU(()=>{let _=W.current;if(_.timeoutId)clearTimeout(_.timeoutId);let F=setTimeout(async()=>{let N=W.current.chunks,w=W.current.totalLength;if(N.length===0)return;let B=U4(N.join(""));if(W.current={chunks:[],timeoutId:null,firstInputTime:null,lastInputTime:null,totalLength:0},K&&l9(B))try{let V=await wX(B);if(V){let j=await K(V.base64,V.mediaType,V.filename);if(j?.prompt){let m=U4(j.prompt),{newValue:P,newCursorPosition:v}=H4(m,$,Q);X(P),J(v)}return}}catch(V){console.error("Failed to process image path:",V)}let A=B.includes(`
1538
- `),D=w>z2.MEDIUM_SIZE_MULTI_CHUNK_THRESHOLD&&N.length>3;if((w>z2.LARGE_INPUT_THRESHOLD||A||D)&&q){let V=await q(B);if(V?.prompt){let j=U4(V.prompt),{newValue:m,newCursorPosition:P}=H4(j,$,Q);X(m),J(P);return}}let{newValue:b,newCursorPosition:L}=H4(B,$,Q);X(b),J(L)},z2.TIMEOUT_MS);W.current.timeoutId=F});JU((_,F)=>{let N=U4(_);if(G.some((b)=>F[b])||F.ctrl&&_==="c"||F.shift&&F.tab||N==="?"&&$==="")return;let B=Date.now(),A=W.current,D=Q,I=$;if(F.leftArrow)D--;else if(F.rightArrow)D++;else if(F.backspace||F.delete){if(_===""){if(Q>0)I=$.slice(0,Q-1)+$.slice(Q,$.length),D--}else if(Q<$.length)I=$.slice(0,Q)+$.slice(Q+1,$.length)}else if(F.ctrl&&N==="a")D=0;else if(F.ctrl&&N==="e")D=$.length;else if(F.ctrl&&N==="k")I=$.slice(0,Q);else if(F.ctrl&&N==="u")I=$.slice(Q),D=0;else if(F.ctrl&&N==="w"){let L=$.slice(0,Q).match(/\s*\S+\s*$/);if(L){let V=L[0].length;I=$.slice(0,Q-V)+$.slice(Q),D-=V}}else if(F.pageUp)D=0;else if(F.pageDown)D=$.length;else if(N===`
1539
- `&&(F.shift||F.meta)){let{newValue:b,newCursorPosition:L}=H4(N,$,Q);X(b),J(L);return}else if(!F.ctrl&&!F.meta){if(!A.firstInputTime)A.firstInputTime=B;A.lastInputTime=B;let b=B-(A.firstInputTime||B),L=N.length>z2.LARGE_INPUT_THRESHOLD,V=N.includes(`
1540
- `)&&N.length>1,j=b<z2.RAPID_INPUT_THRESHOLD_MS&&A.chunks.length>0,m=b<z2.RAPID_INPUT_THRESHOLD_MS&&N.length>10,P=A.timeoutId!==null;if(q&&(L||V||j||m||P)){A.chunks.push(N),A.totalLength+=N.length,U();return}if(N.length===1&&!A.timeoutId)A.chunks=[],A.firstInputTime=null,A.lastInputTime=null,A.totalLength=0;I=$.slice(0,Q)+N+$.slice(Q,$.length),D+=N.length}if(D<0)D=0;if(D>I.length)D=I.length;if(I!==$)X(I);if(D!==Q)J(D)},{isActive:Z});let H=Z,O=$,z=Y?P2.grey(Y):void 0;if(H)if(z=Y.length>0?P2.inverse(Y[0])+P2.grey(Y.slice(1)):P2.inverse(" "),$.length===0)O=P2.inverse(" ");else{O="";for(let _=0;_<$.length;_++)if(_===Q&&Q<$.length)O+=P2.inverse($[_]);else O+=$[_];if(Q>=$.length)O+=P2.inverse(" ")}return WU(QU,{children:Y?$.length>0?O:z:O},void 0,!1,void 0,this)}import{jsxDEV as i9}from"react/jsx-dev-runtime";var bX=OU.memo(({input:$,cursorPosition:Y,onChange:Z,onChangeCursorPosition:X})=>{let J=q0()==="main-input",q=RX((G)=>{let W=G.split(`
1541
- `).length,U=G.length,H=500,O=10;if(U>500||W>10){let z=G.slice(0,30).replace(/\n/g," ");return{prompt:`[Pasted: ${U} chars, ${W} lines] ${z}...`}}return{}}),K=RX(async(G,W,U)=>{try{return{prompt:`[Image saved to ${zX(G,W,U).filePath}. Note: Image attachments not yet supported by @ mentions] `}}catch(H){return console.error("[Image Paste] Failed to process image:",H),{prompt:`[Image paste failed: ${H instanceof Error?H.message:"Unknown error"}] `}}});return i9(UU,{flexDirection:"row",paddingX:2,paddingY:0,borderStyle:"round",borderColor:"gray",children:[i9(HU,{color:"blue",bold:!0,children:"> "},void 0,!1,void 0,this),i9(AX,{value:$,cursorPosition:Y,onChange:Z,onChangeCursorPosition:X,onPaste:q,onImagePaste:K,placeholder:" 输入命令...",focus:J,disabledKeys:["upArrow","downArrow","tab","return","escape"]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{Box as O4,Text as I0}from"ink";import NU,{useEffect as wU,useState as LU}from"react";import{useEffect as BU,useState as IX}from"react";import{useEffect as zU,useState as FU}from"react";var _U=15000,VX=["炼化代码灵气...","参悟 AST 道法...","推演算法天机...","重铸代码根基...","破解逻辑封印...","凝练类型真元...","铸就函数金丹...","渡劫编译雷劫...","打通模块任督二脉...","修炼 Tree-shaking 神功...","压缩代码乾坤...","布下 Source Map 阵法...","推演 Token 灵数...","炼制 Prompt 仙丹...","调息温度参数...","参透困惑度玄机...","驱动 LLM 灵力...","施展向量搜索术...","构筑 RAG 法阵...","凝聚 Embedding 道果...","勾连向量宝库...","破译函数咒语...","验证 Schema 真意...","封印工具参数...","注入系统道韵...","串联历史因果...","炼化抽象语法树...","破境重构神功...","感悟类型天道...","筑基模块根基...","施展词法轻功...","破解语法阵法...","参悟语义心法...","凝练中间内力...","修炼优化神功...","调息寄存器真气...","运转指令招式...","消除死码杂念...","折叠常量真元...","内联函数身法...","逃逸分析密探...","垃圾回收扫地僧...","标记清除掌法...","分代回收心诀...","增量收功法门...","JIT 即时顿悟...","解读字节码暗器...","V8 引擎神功...","召唤 WASM 傀儡...","开辟虚拟洞府...","丹田分配内存...","掌控栈帧乾坤...","捕获异常剑气...","尾调优化身法...","动态链接飞剑...","建立 TCP 金桥...","三次握手结契...","传送 HTTP 飞书...","破译响应符文...","TLS 秘境握手...","验证 SSL 信物...","WebSocket 通灵...","流式传功大法...","gRPC 御剑飞行...","Protobuf 封印术...","GraphQL 问道...","DNS 测算域名...","负载均衡五行阵...","CDN 边缘瞬移...","HTTP/2 分身术...","QUIC 闪现神通...","gzip 缩地成寸...","Brotli 玄冰压缩...","断点续传接续术...","分片上传合璧功...","参研 SQL 真经...","推演查询路径...","索引扫描神识...","全表扫描暴力突破...","执行 JOIN 双修大法...","聚合数据炼丹...","事务提交天地誓...","ACID 四象护法...","乐观锁道心无畏...","悲观锁剑阵守护...","分布式锁万里封禁...","Redis 炼药鼎缓存...","LRU 新陈代谢...","WAL 预写因果簿...","B+ 树平衡阴阳...","LSM 树合璧压缩...","向量宝库搜寻...","余弦相似度测算...","KNN 近邻追踪...","倒排索引翻阅秘籍...","快速排序剑法...","归并排序双刀...","堆排优化内功...","二分查找闪现...","深度优先潜行...","广度优先横扫...","Dijkstra 寻路神算...","A* 天机推演...","动态规划填棋盘...","回溯剑法剪枝...","贪心策略奇谋...","分治递归化身术...","哈希表扩容开天...","红黑树旋转太极...","AVL 树平衡阴阳...","跳表纵身轻功...","Trie 树千头万绪...","布隆过滤天罗地网...","一致性哈希环定乾坤...","最小生成树扎根...","Docker 镜像炼制...","Kubernetes 调兵遣将...","容器结界布阵...","卷挂载空间挪移...","Helm 符箓展开...","CI/CD 流水线作业...","GitHub 门派行动...","代码品鉴术...","漏洞探查密探...","依赖追溯寻根...","蓝绿部署换防...","金丝雀试探...","回滚时光倒流...","健康探查望闻问切...","日志归档藏经阁...","监控预警千里眼...","告警通知飞鸽传书...","性能调优筋骨重塑...","扩容缩容易筋经...","灰度发布声东击西...","React 虚影对决...","组件树调和大法...","Hooks 勾魂术...","useEffect 副作用因果...","Redux 中枢天宫...","Zustand 灵台藏识...","CSS-in-JS 画地为牢...","Tailwind 疾风步...","Webpack 热更换血重生...","Vite 按需凝形...","ESBuild 极速神行...","SWC 闪电炼形...","SSR 天地初开...","Hydration 魂归肉身...","Ink 终端墨宝...","虚拟 DOM 镜花水月...","事件冒泡顺流而上...","状态提升登峰造极...","懒加载厚积薄发...","代码分割庖丁解牛...","SHA-256 炼心咒...","AES-256 玄冰封印...","RSA 阴阳双钥...","JWT 信物令牌...","OAuth 门派授权...","CSRF 防御结界...","XSS 祛邪过滤...","SQL 注入克星...","PBKDF2 淬炼秘钥...","零知识誓言验证...","HTTPS 金钟罩...","签名验证印玺鉴定...","盐值加密炼丹配方...","双因素认证双重认证...","权限控制天条律令...","拜见图灵祖师爷...","冯·诺依曼传道...","Linus 大侠坐镇...","参悟 Rust 生命轮回...","逃离回调地狱轮回...","await 静待天时...","捕获野生 Bug 妖兽...","喂养橡皮鸭灵兽 \uD83E\uDD86...","炼丹调参秘术...","0xDEADBEEF 死亡凝视...","递归无限轮回...","闭包封印记忆...","Promise 未来契约...","async 异步神功...","Generator 分身术...","Proxy 替身傀儡...","Reflect 返照镜...","Symbol 独一无二印记...","WeakMap 过眼云烟...","Iterator 周而复始...","GitHub 武林大会...","Star 点赞声望...","Fork 拜师学艺...","Pull Request 挑战切磋...","Code Review 武功点评...","Issue 悬赏令...","Merge 收徒入门...","Commit 闭关修炼记录...","Branch 分支独辟蹊径...","Tag 里程碑界碑...","Release 出关发布...","License 门规戒律...","README 入门心法...","Documentation 武学秘籍...","Open Source 广纳贤才..."],DX=["Esc - 立即停止当前任务","Shift+Tab - 切换权限模式 (default/auto_edit/plan)","Tab - 智能补全斜杠命令","↑↓ - 浏览输入历史记录","双击 Esc - 快速清空输入框","Ctrl+C - 强制终止程序","Ctrl+L - 清屏(保留历史)","Ctrl+R - 反向搜索历史","Ctrl+U - 清空当前行","/help - 查看完整帮助文档","/init - 生成 BLADE.md 项目配置","/resume - 恢复历史会话","/compact - 手动压缩上下文(节省 token)","/theme - 打开主题选择器","/config - 打开配置面板","/model - 管理与切换模型配置","/permissions - 管理工具权限规则","/mcp - 查看 MCP 服务器状态","/agents - 管理 Subagent 配置","/version - 显示版本信息","/clear - 清除屏幕内容","/status - 显示当前项目配置状态","/context - 可视化当前上下文使用情况","/cost - 显示会话成本统计","/exit - 退出 REPL","@ 文件路径 - 附加文件到上下文","@dir/ - 附加整个目录","@file.ts:10-20 - 附加指定行范围","Plan 模式 - 先规划后编码(/plan)","Auto Edit 模式 - 自动批准工具调用","MCP 协议 - 扩展外部工具集成","Subagents - 并行执行子任务","Hooks 系统 - 自定义工具执行流程","Context 压缩 - 自动总结历史对话","Loop 检测 - 防止无限循环","提示:使用 /init 让 AI 理解你的项目结构","提示:Plan 模式适合复杂多步骤任务","提示:Auto Edit 可加速重复性操作","提示:@ 引用可提供更精准的上下文","提示:定期 /compact 节省 token 成本","提示:使用 /permissions 控制工具权限","提示:Shift+Tab 快速切换模式","提示:Esc 可随时中断长时间任务","提示:/resume 继续未完成的对话","提示:/export 保存重要对话记录"];function MX($,Y){let[Z,X]=FU("");return zU(()=>{if(Y){X("等待用户确认...");return}if(!$){X("");return}let Q=()=>{if(Math.random()<0.16666666666666666){let G=Math.floor(Math.random()*DX.length);return DX[G]}let K=Math.floor(Math.random()*VX.length);return VX[K]};X(Q());let J=setInterval(()=>{X(Q())},_U);return()=>{clearInterval(J)}},[$,Y]),Z}function kX($,Y=!1){let[Z,X]=IX(0),[Q,J]=IX(null),q=MX($,Y);return BU(()=>{if(!$){X(0),J(null);return}if(Q===null)J(Date.now());let K=setInterval(()=>{if(Q!==null){let G=Math.floor((Date.now()-Q)/1000);X(G)}},1000);return()=>{clearInterval(K)}},[$,Q]),{currentPhrase:q,elapsedTime:Z}}import{jsxDEV as p1,Fragment as RU}from"react/jsx-dev-runtime";var r9=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],AU=80;function jX($){if($<60)return`${$}s`;let Y=Math.floor($/60),Z=$%60;return`${Y}m ${Z}s`}var EX=NU.memo(({message:$})=>{let Y=W2(),Z=r6(),X=Y||!Z,[Q,J]=LU(0),q=Y1.getTheme(),G=N$()>=AU,{currentPhrase:W,elapsedTime:U}=kX(X,!1);if(wU(()=>{if(!X){J(0);return}let O=setInterval(()=>{J((z)=>(z+1)%r9.length)},80);return()=>clearInterval(O)},[X]),!X)return null;let H=W||$||"正在思考中...";if(G)return p1(O4,{paddingX:2,paddingBottom:1,flexDirection:"row",gap:1,children:[p1(I0,{color:q.colors.warning,bold:!0,children:r9[Q]},void 0,!1,void 0,this),p1(I0,{color:q.colors.text.primary,children:H},void 0,!1,void 0,this),U>0&&p1(RU,{children:[p1(I0,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),p1(I0,{color:q.colors.info,children:["已用时: ",jX(U)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),p1(I0,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),p1(I0,{color:q.colors.secondary,children:"Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return p1(O4,{paddingX:2,paddingBottom:1,flexDirection:"column",children:[p1(O4,{flexDirection:"row",gap:1,children:[p1(I0,{color:q.colors.warning,bold:!0,children:r9[Q]},void 0,!1,void 0,this),p1(I0,{color:q.colors.text.primary,children:H},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U>0&&p1(O4,{marginLeft:2,flexDirection:"row",gap:1,children:[p1(I0,{color:q.colors.info,children:["已用时: ",jX(U)]},void 0,!0,void 0,this),p1(I0,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),p1(I0,{color:q.colors.secondary,children:"Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)});import{Box as R$,Static as yU}from"ink";import CX,{useEffect as vU,useMemo as s9}from"react";k$();import{Box as Z6,Text as X6}from"ink";import bU from"ink-big-text";import VU from"ink-gradient";import DU from"react";import{jsxDEV as O0}from"react/jsx-dev-runtime";var yX=DU.memo(()=>{return O0(Z6,{flexDirection:"column",paddingX:2,paddingTop:1,paddingBottom:1,children:[O0(Z6,{flexDirection:"column",children:O0(VU,{name:"pastel",children:O0(bU,{text:"BLADE",font:"block"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),O0(Z6,{marginBottom:1,children:O0(X6,{color:"white",dimColor:!0,children:z7()},void 0,!1,void 0,this)},void 0,!1,void 0,this),O0(Z6,{flexDirection:"column",marginBottom:1,children:[O0(Z6,{marginBottom:1,children:O0(X6,{color:"white",bold:!0,children:"使用指南:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),O0(X6,{color:"white",children:"1. 输入问题、编辑文件或运行命令"},void 0,!1,void 0,this),O0(X6,{color:"white",children:"2. 使用 /init 创建项目配置文件"},void 0,!1,void 0,this),O0(X6,{color:"white",children:"3. 输入 /help 查看所有 slash 命令"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)});import{Box as a9,Text as A$}from"ink";import MU,{useMemo as vX}from"react";import{jsxDEV as n0}from"react/jsx-dev-runtime";function IU($,Y=60){if(!$)return"";let Z=$.split(`
1542
- `)[0]||"";if(Z.length<=Y)return Z;return`${Z.slice(0,Y)}...`}function kU($){if(!$)return 0;return $.split(`
1543
- `).length}var n9=MU.memo(({content:$,isStreaming:Y=!1,isExpanded:Z})=>{let X=Y1.getTheme(),Q=vX(()=>kU($),[$]),J=vX(()=>IU($),[$]),q=X.colors.info,K=X.colors.muted;return n0(a9,{flexDirection:"column",marginBottom:1,children:[n0(a9,{flexDirection:"row",children:[n0(A$,{color:q,children:Z?"▼":"▶"},void 0,!1,void 0,this),n0(A$,{children:" "},void 0,!1,void 0,this),n0(A$,{color:K,children:["Thinking",Y?"...":` (${Q} lines)`]},void 0,!0,void 0,this),!Z&&!Y&&J&&n0(A$,{color:K,children:[" - ",J]},void 0,!0,void 0,this),n0(A$,{color:K,dimColor:!0,children:[" ","[Ctrl+T]"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Z&&$&&n0(a9,{marginLeft:2,marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,paddingY:0,children:n0(A$,{color:K,children:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});n9.displayName="ThinkingBlock";import{Box as z4,Text as o9}from"ink";import{useState as PX}from"react";function jU(){let[$,Y]=PX(Y1.getTheme()),[Z,X]=PX(Y1.getCurrentThemeName()),Q=(G)=>{try{Y1.setTheme(G),Y(Y1.getTheme()),X(G)}catch(W){console.error("Failed to change theme:",W)}},J=Y1.getAvailableThemes();return{theme:$,themeName:Z,changeTheme:Q,availableThemes:J,hasTheme:(G)=>Y1.hasTheme(G),getThemeByName:(G)=>Y1.getThemeByName(G),colors:$.colors,spacing:$.spacing,typography:$.typography}}function TX(){let{colors:$}=jU();return $}import{jsxDEV as F2}from"react/jsx-dev-runtime";var SX=({todos:$,visible:Y=!0,compact:Z=!1})=>{let X=TX();if(!Y||$.length===0)return null;let Q={total:$.length,completed:$.filter((J)=>J.status==="completed").length,inProgress:$.filter((J)=>J.status==="in_progress").length};return F2(z4,{flexDirection:"column",borderStyle:"single",borderColor:X.border.light,paddingX:1,paddingY:Z?0:1,marginBottom:1,children:[F2(z4,{marginBottom:Z?0:1,children:[F2(o9,{dimColor:!0,children:"Tasks "},void 0,!1,void 0,this),F2(o9,{color:X.text.muted,children:[Q.completed,"/",Q.total]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),F2(z4,{flexDirection:"column",children:$.map((J,q)=>F2(EU,{todo:J,compact:Z},J.id||q,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},EU=({todo:$,compact:Y})=>{let Z,X=!1,Q;switch($.status){case"completed":Z="✓",X=!0,Q=$.content;break;case"in_progress":Z="▶",X=!1,Q=$.activeForm;break;case"pending":default:Z="○",X=!0,Q=$.content;break}return F2(z4,{paddingY:Y?0:0,children:F2(o9,{dimColor:X,children:[Z," ",Q]},void 0,!0,void 0,this)},void 0,!1,void 0,this)};import{jsxDEV as z0}from"react/jsx-dev-runtime";var fX=CX.memo(()=>{let $=l6(),Y=W2(),Z=PY(),X=fY(),Q=dY(),J=cY(),q=lY(),K=kY(),G=N$(),W=CX.useRef(0);vU(()=>{W.current=0},[K]);let{completedMessages:U,streamingMessage:H}=s9(()=>{let F=Math.max(W.current,Y&&$.length>0?$.length-1:$.length);W.current=F;let N=$.slice(0,F),w=F<$.length?$[F]:null;return{completedMessages:N,streamingMessage:w}},[$,Y]),O=s9(()=>{return Z.some((F)=>F.status==="pending"||F.status==="in_progress")},[Z]),z=(F,N,w=!1)=>z0(R$,{flexDirection:"column",children:z0(Y6,{content:F.content,role:F.role,terminalWidth:G,metadata:F.metadata,isPending:w},void 0,!1,void 0,this)},F.id,!1,void 0,this),_=s9(()=>{let F=[];return F.push(z0(yX,{},"header",!1,void 0,this)),U.forEach((N,w)=>{F.push(z(N,w))}),F},[U,G]);return z0(R$,{flexDirection:"column",flexGrow:1,paddingX:2,children:z0(R$,{flexDirection:"column",flexGrow:1,children:[z0(yU,{items:_,children:(F)=>F},K,!1,void 0,this),J&&z0(R$,{marginBottom:1,children:z0(n9,{content:J,isStreaming:Y,isExpanded:q},void 0,!1,void 0,this)},void 0,!1,void 0,this),H&&z(H,U.length,!0),X&&O&&z0(R$,{marginTop:1,children:z0(SX,{todos:Z,visible:!0,compact:!1},void 0,!1,void 0,this)},void 0,!1,void 0,this),Q.map((F,N)=>z0(R$,{flexDirection:"column",children:z0(Y6,{content:F,role:"user",terminalWidth:G},void 0,!1,void 0,this)},`pending-${N}`,!1,void 0,this))]},void 0,!0,void 0,this)},void 0,!1,void 0,this)});F1();import{Box as o,Text as h,useFocus as hX,useFocusManager as PU,useInput as B4}from"ink";import TU from"ink-select-input";import SU from"ink-text-input";import{useEffect as CU,useState as Q6}from"react";import{jsxDEV as k,Fragment as _4}from"react/jsx-dev-runtime";var fU=({isSelected:$})=>k(o,{marginRight:1,children:k(h,{color:$?"yellow":"gray",children:$?"▶":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),hU=({isSelected:$,label:Y})=>k(h,{bold:$,color:$?"yellow":void 0,children:Y},void 0,!1,void 0,this);function xU($){switch($){case"openai-compatible":return"⚡ OpenAI Compatible";case"gpt-openai-platform":return"\uD83D\uDD37 GPT OpenAI Platform";case"anthropic":return"\uD83E\uDD16 Anthropic";default:return $}}var pU=({onSelect:$,onCancel:Y,initialProvider:Z})=>{let{isFocused:X}=hX({id:"provider-step"});B4((q,K)=>{if(K.escape)Y()},{isActive:X});let Q=[{label:"⚡ OpenAI Compatible - 兼容 OpenAI API 的服务 (千问/豆包/DeepSeek等)",value:"openai-compatible"},{label:"\uD83D\uDD37 GPT OpenAI Platform - 字节跳动 GPT 平台 (内部)",value:"gpt-openai-platform"},{label:"\uD83E\uDD16 Anthropic Claude API - Claude 官方 API",value:"anthropic"}],J=Z?Math.max(0,Q.findIndex((q)=>q.value===Z)):0;return k(o,{flexDirection:"column",marginBottom:1,children:[k(o,{marginBottom:1,children:k(h,{bold:!0,color:"blue",children:"\uD83D\uDCE1 Step 2: 选择 API 提供商"},void 0,!1,void 0,this)},void 0,!1,void 0,this),k(o,{marginBottom:1,children:k(h,{children:"根据您使用的 LLM 服务选择对应的 API 类型"},void 0,!1,void 0,this)},void 0,!1,void 0,this),k(o,{marginBottom:1,children:k(TU,{items:Q,onSelect:(q)=>$(q.value),indicatorComponent:fU,itemComponent:hU,initialIndex:J},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},F4=({stepNumber:$,icon:Y,title:Z,description:X,hint:Q,examples:J,value:q,placeholder:K,mask:G,previousValue:W,onChange:U,onSubmit:H,onCancel:O})=>{return B4((z,_)=>{if(_.escape)O()},{isActive:!0}),k(o,{flexDirection:"column",marginBottom:1,children:[k(o,{marginBottom:1,children:k(h,{bold:!0,color:"blue",children:[Y," Step ",$,": ",Z]},void 0,!0,void 0,this)},void 0,!1,void 0,this),k(o,{marginBottom:1,children:k(h,{children:X},void 0,!1,void 0,this)},void 0,!1,void 0,this),W&&k(o,{marginBottom:1,children:k(h,{color:"green",children:["✓ ",W]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Q&&k(o,{marginBottom:1,children:k(h,{dimColor:!0,children:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),J&&J.length>0&&k(_4,{children:[k(o,{marginBottom:1,children:k(h,{dimColor:!0,children:"常见示例:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),k(o,{marginBottom:1,paddingLeft:2,children:k(h,{dimColor:!0,children:J.join(`
1544
- `)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),k(o,{children:[k(h,{bold:!0,color:"cyan",children:["▶"," "]},void 0,!0,void 0,this),k(SU,{value:q,onChange:U,onSubmit:H,placeholder:K,mask:G},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},gU=({mode:$,config:Y,isSaving:Z,onConfirm:X,onBack:Q,onCancel:J})=>{let{isFocused:q}=hX({id:"confirm-step"});return B4((K,G)=>{if(Z)return;if(K==="y"||K==="Y")X();else if(K==="n"||K==="N")Q();else if(G.escape)J()},{isActive:q&&!Z}),k(o,{flexDirection:"column",marginBottom:1,children:[k(o,{marginBottom:1,children:k(h,{bold:!0,color:$==="edit"?"yellow":"blue",children:$==="edit"?"\uD83D\uDCBE 确认修改":"✅ Step 6: 确认配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),k(o,{marginBottom:1,children:k(h,{children:$==="edit"?"请确认修改内容,保存后将立即生效。":"请确认以下配置信息:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),k(o,{flexDirection:"column",marginBottom:1,paddingLeft:2,children:[k(o,{marginBottom:1,children:[k(h,{dimColor:!0,children:"名称: "},void 0,!1,void 0,this),k(h,{bold:!0,color:"cyan",children:Y.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),k(o,{marginBottom:1,children:[k(h,{dimColor:!0,children:"Provider: "},void 0,!1,void 0,this),k(h,{bold:!0,color:"cyan",children:xU(Y.provider)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),k(o,{marginBottom:1,children:[k(h,{dimColor:!0,children:"Base URL: "},void 0,!1,void 0,this),k(h,{bold:!0,color:"blue",children:Y.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),k(o,{marginBottom:1,children:[k(h,{dimColor:!0,children:"API Key: "},void 0,!1,void 0,this),k(h,{bold:!0,color:"yellow",children:[Y.apiKey?.slice(0,8),"*".repeat(Math.min(32,(Y.apiKey?.length||0)-8))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),k(o,{children:[k(h,{dimColor:!0,children:"Model: "},void 0,!1,void 0,this),k(h,{bold:!0,color:"cyan",children:Y.model},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),!Z&&k(o,{marginTop:1,children:k(h,{children:[$==="edit"?"保存修改? ":"确认保存配置? ","[",k(h,{bold:!0,color:"green",children:"Y"},void 0,!1,void 0,this),"/",k(h,{bold:!0,color:"red",children:"n"},void 0,!1,void 0,this),"]"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Z&&k(o,{children:k(h,{color:"yellow",children:"⏳ 正在保存配置到 ~/.blade/config.json..."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},t9=({mode:$,initialConfig:Y,modelId:Z,onComplete:X,onCancel:Q})=>{let J=$==="edit",[q,K]=Q6("name"),[G,W]=Q6(()=>J&&Y?{...Y}:{}),[U,H]=Q6(J&&Y?Y.name:""),[O,z]=Q6(!1),[_,F]=Q6(null),N=P1(!1);B4((v,Z1)=>{if(Z1.ctrl&&v==="c"||Z1.meta&&v==="c")if($==="setup")N();else Q()},{isActive:!0});let{focus:w}=PU();CU(()=>{if(q==="provider")w("provider-step");else if(q==="confirm")w("confirm-step")},[q,w]);let B=()=>{if(!U.trim()){F("配置名称不能为空");return}W({...G,name:U}),H(""),F(null),K("provider")},A=(v)=>{W({...G,provider:v});let Z1=J?G.baseUrl??Y?.baseUrl??"":"";H(Z1),K("baseUrl")},D=()=>{if(!U.trim()){F("Base URL 不能为空");return}try{new URL(U)}catch{F("请输入有效的 URL (例如: https://api.openai.com/v1)");return}W({...G,baseUrl:U});let v=J?G.apiKey??Y?.apiKey??"":"";H(v),F(null),K("apiKey")},I=()=>{if(!U.trim()){F("API Key 不能为空");return}W({...G,apiKey:U});let v=J?G.model??Y?.model??"":"";H(v),F(null),K("model")},b=()=>{if(!U.trim()){F("Model 不能为空");return}W({...G,model:U}),H(""),F(null),K("confirm")},L=async()=>{z(!0),F(null);try{let v={name:G.name,provider:G.provider,baseUrl:G.baseUrl,apiKey:G.apiKey,model:G.model};if($==="setup")X(v);else if($==="add"){let Z1=await U1().addModel(v);await U1().setCurrentModel(Z1.id),X(v)}else{if(!Z)throw Error("未提供模型 ID,无法编辑");await U1().updateModel(Z,v),X(v)}}catch(v){F(v instanceof Error?v.message:"配置失败"),z(!1)}},V=()=>{switch(F(null),H(""),q){case"provider":H(G.name||""),K("name");break;case"baseUrl":K("provider");break;case"apiKey":H(G.baseUrl||""),K("baseUrl");break;case"model":K("apiKey");break;case"confirm":H(G.model||""),K("model");break}},j=q==="name"?1:q==="provider"?2:q==="baseUrl"?3:q==="apiKey"?4:q==="model"?5:6,m=Math.floor((j-1)/5*40);return k(o,{...$==="setup"?{flexDirection:"column",padding:1}:$==="add"?{flexDirection:"column",borderStyle:"round",borderColor:"blue",padding:1}:{flexDirection:"column",borderStyle:"round",borderColor:"yellow",padding:1},children:[$==="setup"?k(_4,{children:[k(o,{marginBottom:1,children:k(h,{bold:!0,color:"blue",children:"\uD83D\uDE80 欢迎使用 Blade Code"},void 0,!1,void 0,this)},void 0,!1,void 0,this),k(o,{marginBottom:1,children:k(h,{children:"AI 驱动的代码助手 - 让我们开始配置您的助手"},void 0,!1,void 0,this)},void 0,!1,void 0,this),k(o,{marginBottom:1,children:[k(h,{bold:!0,color:"blue",children:"█".repeat(m)},void 0,!1,void 0,this),k(h,{dimColor:!0,children:"░".repeat(40-m)},void 0,!1,void 0,this),k(h,{children:" "},void 0,!1,void 0,this),k(h,{bold:!0,color:"cyan",children:[j,"/6"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),k(o,{marginBottom:1,children:k(h,{dimColor:!0,children:"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this):$==="add"?k(_4,{children:[k(o,{justifyContent:"center",marginBottom:1,children:k(h,{bold:!0,color:"blue",children:"添加新模型配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),k(o,{marginBottom:1,children:k(h,{children:["步骤: ",j,"/6"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this):k(_4,{children:[k(o,{justifyContent:"center",marginBottom:1,children:k(h,{bold:!0,color:"yellow",children:"编辑模型配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),k(o,{marginBottom:1,children:k(h,{children:["步骤: ",j,"/6"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q==="name"&&k(F4,{stepNumber:1,icon:"\uD83D\uDCDD",title:"配置名称",description:"给这个模型配置起一个易于识别的名称",value:U,placeholder:"例如: 千问工作账号",onChange:H,onSubmit:B,onCancel:Q},void 0,!1,void 0,this),q==="provider"&&k(pU,{onSelect:A,onCancel:Q,initialProvider:G.provider},void 0,!1,void 0,this),q==="baseUrl"&&k(F4,{stepNumber:3,icon:"\uD83C\uDF10",title:"配置 Base URL",description:"输入您的 API 端点地址(完整的 URL 包含协议)",examples:["• OpenAI: https://api.openai.com/v1","• 千问: https://dashscope.aliyuncs.com/compatible-mode/v1","• 豆包: https://ark.cn-beijing.volces.com/api/v3","• DeepSeek: https://api.deepseek.com/v1"],value:U,placeholder:"https://api.example.com/v1",onChange:H,onSubmit:D,onCancel:Q},void 0,!1,void 0,this),q==="apiKey"&&k(F4,{stepNumber:4,icon:"\uD83D\uDD11",title:"输入 API Key",description:"您的 API 密钥将被安全存储在 ~/.blade/config.json (权限 600)",hint:"\uD83D\uDCA1 提示: 输入时字符会被隐藏,支持粘贴 (Ctrl+V / Cmd+V)",previousValue:G.baseUrl?`✓ 当前 Base URL: ${G.baseUrl}`:void 0,value:U,placeholder:"sk-...",mask:"*",onChange:H,onSubmit:I,onCancel:Q},void 0,!1,void 0,this),q==="model"&&k(F4,{stepNumber:5,icon:"\uD83E\uDD16",title:"选择模型",description:"输入您想使用的模型名称(请参考您的 API 提供商文档)",examples:["• OpenAI: gpt-5, gpt-5-mini, gpt-5-nano","• Claude: claude-sonnet-4.5, claude-opus-4.1","• 千问: qwen3-max, qwen3-235b, qwen3-32b","• DeepSeek: deepseek-v3.1, deepseek-r1-0528","• 豆包: doubao-seed-1.6, doubao-seed-1.6-flash"],value:U,placeholder:"例如: gpt-5",onChange:H,onSubmit:b,onCancel:Q},void 0,!1,void 0,this),q==="confirm"&&k(gU,{mode:$,config:G,isSaving:O,onConfirm:L,onBack:V,onCancel:Q},void 0,!1,void 0,this),_&&k(o,{marginTop:1,borderStyle:"round",borderColor:"red",paddingX:1,children:k(h,{color:"red",children:["❌ ",_]},void 0,!0,void 0,this)},void 0,!1,void 0,this),k(o,{marginTop:1,children:k(h,{dimColor:!0,children:"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"},void 0,!1,void 0,this)},void 0,!1,void 0,this),!O&&q==="provider"&&k(o,{marginTop:1,children:k(h,{dimColor:!0,children:["\uD83D\uDCA1 使用 ",k(h,{bold:!0,children:"↑/↓"},void 0,!1,void 0,this)," 键选择,",k(h,{bold:!0,children:"Enter"},void 0,!1,void 0,this)," 确认,",k(h,{bold:!0,children:"Esc"},void 0,!1,void 0,this)," 取消"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),!O&&q!=="confirm"&&q!=="provider"&&k(o,{marginTop:1,children:k(h,{dimColor:!0,children:["\uD83D\uDCA1 输入完成后按 ",k(h,{bold:!0,children:"Enter"},void 0,!1,void 0,this),",",k(h,{bold:!0,children:"Ctrl+C"},void 0,!1,void 0,this)," 退出"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),!O&&q==="confirm"&&k(o,{marginTop:1,children:k(h,{dimColor:!0,children:["\uD83D\uDCA1 按"," ",k(h,{bold:!0,color:"green",children:"Y"},void 0,!1,void 0,this)," ","保存,",k(h,{bold:!0,color:"red",children:"N"},void 0,!1,void 0,this)," ","返回修改,",k(h,{bold:!0,children:"Esc"},void 0,!1,void 0,this)," 取消"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{useMemoizedFn as N4,useMount as mU}from"ahooks";import{Box as F0,Text as K1,useFocus as dU,useFocusManager as uU,useInput as cU}from"ink";import lU from"ink-select-input";import{memo as iU,useMemo as rU,useState as w4}from"react";F1();import{jsxDEV as i}from"react/jsx-dev-runtime";var aU=({isSelected:$})=>i(F0,{marginRight:1,children:i(K1,{color:$?"yellow":"gray",children:$?"▶":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),nU=({isSelected:$,label:Y})=>i(K1,{bold:$,color:$?"yellow":void 0,children:Y},void 0,!1,void 0,this),xX=iU(({onClose:$,onEdit:Y})=>{let Z=hY(),X=xY()??"",{isFocused:Q}=dU({id:"model-selector"}),J=uU(),[q,K]=w4(""),[G,W]=w4(!1),[U,H]=w4(null),O=P1(!1),[z]=w4(()=>{let b=process.stdout?.columns||80;return Math.max(20,b-8)});mU(()=>{if(J?.focus("model-selector"),Z.length>0)K(Z[0].id)}),cU((b,L)=>{if(G)return;if(L.ctrl&&b==="c"||L.meta&&b==="c"){O();return}if(L.escape){$();return}if(!Q)return;if(b==="d"||b==="D"){F();return}if((b==="e"||b==="E")&&Y)N()},{isActive:!0});let _=N4(async(b)=>{if(G)return;let L=b.value;if(L===X){$();return}W(!0),H(null);try{await U1().setCurrentModel(L),$()}catch(V){H(V.message),W(!1)}}),F=N4(async()=>{if(G||q===X)return;W(!0),H(null);try{if(await U1().removeModel(q),Z.length<=1)$()}catch(b){H(b.message)}finally{W(!1)}}),N=N4(()=>{if(G||!Y)return;let b=Z.find((L)=>L.id===q);if(!b)return;Y(b)}),w=N4((b)=>{K(b.value)}),B=rU(()=>{return Z.find((b)=>b.id===q)},[Z,q]),A=Z.map((b)=>({label:b.name+(b.id===X?" (当前)":""),value:b.id})),D=q===X;return i(F0,{flexDirection:"column",borderStyle:"round",borderColor:"gray",padding:1,width:"100%",children:[i(F0,{flexDirection:"row",justifyContent:"space-between",marginBottom:1,children:[i(K1,{bold:!0,color:"cyan",children:"模型管理"},void 0,!1,void 0,this),i(K1,{dimColor:!0,children:[G?"⏳ 处理中...":D?"Enter=关闭 • E=编辑 • Esc=取消":"Enter=切换 • D=删除 • E=编辑 • Esc=取消"," • Ctrl+C=退出"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),i(F0,{flexDirection:"row",children:[i(F0,{flexDirection:"column",flexGrow:2,marginRight:2,borderStyle:"single",borderColor:"gray",padding:1,children:[i(K1,{dimColor:!0,children:["已配置模型 (",Z.length,")"]},void 0,!0,void 0,this),i(F0,{marginTop:1,children:i(lU,{items:A,onSelect:_,onHighlight:w,indicatorComponent:aU,itemComponent:nU},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i(F0,{flexDirection:"column",flexGrow:3,borderStyle:"single",borderColor:"gray",padding:1,children:[i(K1,{dimColor:!0,children:"模型详情"},void 0,!1,void 0,this),i(F0,{marginY:1,children:i(K1,{color:D?"green":"yellow",children:D?"● 当前使用":"● 可切换"},void 0,!1,void 0,this)},void 0,!1,void 0,this),B?i(F0,{flexDirection:"column",children:[i(K1,{children:[i(K1,{dimColor:!0,children:"名称: "},void 0,!1,void 0,this),i(K1,{bold:!0,color:"cyan",children:B.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i(K1,{children:[i(K1,{dimColor:!0,children:"Provider: "},void 0,!1,void 0,this),i(K1,{bold:!0,children:B.provider},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i(K1,{children:[i(K1,{dimColor:!0,children:"Model: "},void 0,!1,void 0,this),i(K1,{bold:!0,children:B.model},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i(K1,{children:[i(K1,{dimColor:!0,children:"Base URL: "},void 0,!1,void 0,this),i(K1,{color:"blueBright",children:B.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.temperature!==void 0&&i(K1,{children:[i(K1,{dimColor:!0,children:"Temperature: "},void 0,!1,void 0,this),i(K1,{children:B.temperature},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.maxContextTokens!==void 0&&i(K1,{children:[i(K1,{dimColor:!0,children:"Context Window: "},void 0,!1,void 0,this),i(K1,{children:B.maxContextTokens},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):i(K1,{dimColor:!0,children:"请选择一个模型查看详情"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),U&&i(F0,{marginTop:1,children:i(K1,{color:"red",children:["❌ ",U]},void 0,!0,void 0,this)},void 0,!1,void 0,this),i(F0,{justifyContent:"center",marginTop:1,children:i(K1,{dimColor:!0,children:"─".repeat(z)},void 0,!1,void 0,this)},void 0,!1,void 0,this),i(F0,{justifyContent:"center",children:i(K1,{dimColor:!0,children:"提示:D=删除 • E=编辑 • ↑↓=移动 • Enter/ESC=确认"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{useMemoizedFn as J6}from"ahooks";import{promises as dX}from"fs";import{Box as Y0,Text as B1,useInput as oU}from"ink";import pX from"ink-select-input";import sU from"ink-text-input";import tU from"os";import L4 from"path";import{useEffect as eU,useMemo as A4,useRef as $H,useState as _2}from"react";F1();import{jsxDEV as r}from"react/jsx-dev-runtime";var q6=[{key:"allow",label:"Allow"},{key:"ask",label:"Ask"},{key:"deny",label:"Deny"},{key:"info",label:"Info"}],YH={allow:"Add a new rule...",ask:"Add a new rule...",deny:"Add a new rule..."},ZH={allow:"Allow permission rules",ask:"Ask permission rules",deny:"Deny permission rules"},gX={project:"[项目共享配置]",global:"[用户全局配置]",local:"[本地配置]"},XH=["project","global","local"],QH={allow:[],ask:[],deny:[]},JH={localExists:!1,projectExists:!1,globalExists:!1},mX={allow:[],ask:[],deny:[]};function qH($){let Y=(X)=>Array.isArray(X)?X.filter((Q)=>typeof Q==="string"):[],Z=$?.permissions??{};return{allow:Y(Z?.allow),ask:Y(Z?.ask),deny:Y(Z?.deny)}}async function KH($){try{let Y=await dX.readFile($,"utf-8"),Z=JSON.parse(Y);return{exists:!0,raw:Z,permissions:qH(Z)}}catch(Y){if(Y.code==="ENOENT")return{exists:!1,raw:{},permissions:{...mX}};return console.warn(`[PermissionsManager] Failed to read ${$}:`,Y),{exists:!0,raw:{},permissions:{...mX}}}}function GH($,Y){let Z=$.padEnd(32," "),X=Y==="local"?`${gX[Y]} ← 可删除`:gX[Y];return`${Z} ${X}`}var uX=({onClose:$})=>{let Z=q0()==="permissions-manager",X=P1(!1),[Q,J]=_2(0),q=q6[Q].key,[K,G]=_2(QH),[W,U]=_2(JH),[H,O]=_2(!0),[z,_]=_2("list"),[F,N]=_2(""),[w,B]=_2(null),[A,D]=_2(null),I=$H(!1),b=A4(()=>L4.join(process.cwd(),".blade","settings.local.json"),[]),L=A4(()=>L4.join(process.cwd(),".blade","settings.json"),[]),V=A4(()=>L4.join(tU.homedir(),".blade","settings.json"),[]),j=J6(async()=>{O(!0);let c=[{source:"local",path:b},{source:"project",path:L},{source:"global",path:V}],q1=await Promise.all(c.map(async({source:y1,path:d0})=>{let _0=await KH(d0);return{source:y1,path:d0,..._0}})),t={localExists:q1.find((y1)=>y1.source==="local")?.exists??!1,projectExists:q1.find((y1)=>y1.source==="project")?.exists??!1,globalExists:q1.find((y1)=>y1.source==="global")?.exists??!1};U(t);let o1={allow:[],ask:[],deny:[]},N2=Object.fromEntries(q1.map((y1)=>[y1.source,y1]));["allow","ask","deny"].forEach((y1)=>{XH.forEach((d0)=>{(N2[d0]?.permissions[y1]??[]).forEach((V$,j0)=>{let w2={key:`${d0}:${j0}:${V$}`,rule:V$,source:d0};o1[y1].push(w2)})})}),G(o1),O(!1)});eU(()=>{j()},[j]);let m=J6(async(c,q1)=>{try{let t=L4.join(process.cwd(),".blade","settings.local.json"),o1={allow:[],ask:[],deny:[]};try{let y1=await dX.readFile(t,"utf-8"),_0=JSON.parse(y1).permissions||{};o1={allow:Array.isArray(_0.allow)?_0.allow:[],ask:Array.isArray(_0.ask)?_0.ask:[],deny:Array.isArray(_0.deny)?_0.deny:[]}}catch(y1){}let N2=q1(o1);await U1().updateConfig({permissions:N2},{scope:"local",immediate:!0}),await j()}catch(t){throw console.error("[PermissionsManager] 修改权限规则失败:",t),t}});oU((c,q1)=>{if(q1.ctrl&&c==="c"||q1.meta&&c==="c"){X();return}if(z==="locked"){if(I.current){I.current=!1;return}_("list"),B(null),D(null);return}if(q1.escape){if(z==="list"||q==="info")$();else _("list"),N(""),B(null),D(null);return}if(z==="list"){if(q1.tab&&q1.shift)J((t)=>(t-1+q6.length)%q6.length);else if(q1.tab)J((t)=>(t+1)%q6.length);else if(c?.toLowerCase()==="q")$()}},{isActive:Z});let P=J6((c)=>{let q1=c.value;if(q==="info")return;if(q1.type==="add"){_("add"),N(""),D(null);return}if(q1.entry.source!=="local"){_("locked"),I.current=!0,B({tab:q,entry:q1.entry}),D({type:"error",text:q1.entry.source==="project"?"此规则定义在项目共享配置中,无法在此删除。":"此规则来自用户全局配置,无法在此删除。"});return}_("confirm-delete"),B({tab:q,entry:q1.entry}),D(null)}),v=J6(async()=>{if(q==="info")return;let c=F.trim();if(!c){D({type:"error",text:"Permission rule 不能为空"});return}if(K[q].map((t)=>t.rule).includes(c)){D({type:"error",text:"该规则已存在"});return}try{await m(q,(t)=>{let o1={allow:[...t.allow],ask:[...t.ask],deny:[...t.deny]};return o1[q]=[...new Set([...t[q],c])],o1}),_("list"),N(""),D({type:"success",text:"已添加本地权限规则"})}catch(t){D({type:"error",text:`保存失败: ${t instanceof Error?t.message:"未知错误"}`})}}),Z1=J6(async()=>{if(!w)return;let{tab:c,entry:q1}=w;try{await m(c,(t)=>{let o1={allow:[...t.allow],ask:[...t.ask],deny:[...t.deny]};return o1[c]=t[c].filter((N2)=>N2!==q1.rule),o1}),_("list"),B(null),D({type:"success",text:"已删除本地权限规则"})}catch(t){D({type:"error",text:`删除失败: ${t instanceof Error?t.message:"未知错误"}`})}}),X1=A4(()=>{if(q==="info")return[];let c=q;return[{label:`› ${YH[c]}`,value:{type:"add"}},...K[c].map((t)=>({label:GH(t.rule,t.source),value:{type:"rule",entry:t}}))]},[q,K]),n1=()=>r(Y0,{marginBottom:1,children:q6.map((c,q1)=>r(Y0,{marginRight:2,children:r(B1,{color:q1===Q?"yellow":"gray",children:["[",c.label,"]"]},void 0,!0,void 0,this)},c.key,!1,void 0,this))},void 0,!1,void 0,this),z1=()=>r(Y0,{flexDirection:"column",gap:1,children:[r(B1,{children:"配置文件优先级(从高到低):"},void 0,!1,void 0,this),r(Y0,{flexDirection:"column",marginLeft:2,children:[r(B1,{children:["1. .blade/settings.local.json (本地配置,不提交 Git)"," ",W.localExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this),r(B1,{children:["2. .blade/settings.json (项目配置,提交 Git)"," ",W.projectExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this),r(B1,{children:["3. ~/.blade/settings.json (用户全局配置)"," ",W.globalExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),r(B1,{children:"说明:"},void 0,!1,void 0,this),r(Y0,{flexDirection:"column",marginLeft:2,children:[r(B1,{children:"- /permissions 命令只管理本地配置 (.blade/settings.local.json)"},void 0,!1,void 0,this),r(B1,{children:"- 修改全局或项目配置请直接编辑对应文件"},void 0,!1,void 0,this),r(B1,{children:"- 本地配置不会提交到 Git"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),d=(c)=>r(Y0,{flexDirection:"column",gap:1,children:[r(B1,{bold:!0,children:ZH[c]},void 0,!1,void 0,this),r(B1,{children:"Permission rules are a tool name, optionally followed by a specifier in parentheses."},void 0,!1,void 0,this),r(B1,{color:"gray",children:"例如: WebFetch 或 Bash(ls:*)"},void 0,!1,void 0,this),r(Y0,{marginTop:1,children:r(sU,{value:F,onChange:N,onSubmit:v},void 0,!1,void 0,this)},void 0,!1,void 0,this),r(B1,{color:"gray",children:"Enter 提交 · Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C2=(c,q1)=>r(Y0,{flexDirection:"column",gap:1,children:[r(B1,{bold:!0,children:["Delete ",c," permission rule?"]},void 0,!0,void 0,this),r(B1,{children:q1.rule},void 0,!1,void 0,this),r(B1,{color:"gray",children:"From project local settings"},void 0,!1,void 0,this),r(B1,{children:"Are you sure you want to delete this permission rule?"},void 0,!1,void 0,this),r(pX,{items:[{label:"Yes",value:"yes"},{label:"No",value:"no"}],onSelect:(t)=>{if(t.value==="yes")Z1();else _("list"),B(null)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),J1=(c)=>r(Y0,{flexDirection:"column",gap:1,children:[r(B1,{bold:!0,children:"Cannot delete this rule"},void 0,!1,void 0,this),r(B1,{children:c.rule},void 0,!1,void 0,this),r(B1,{color:"gray",children:c.source==="project"?"This rule is defined in .blade/settings.json. 请手动编辑该文件以移除规则。":"This rule is defined in ~/.blade/settings.json. 请手动编辑该文件以移除规则。"},void 0,!1,void 0,this),r(B1,{color:"gray",children:"按任意键继续"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),R1=(c)=>r(pX,{items:X1,isFocused:z==="list",onSelect:P},void 0,!1,void 0,this),m0=()=>{if(H)return r(B1,{children:"加载中..."},void 0,!1,void 0,this);if(q==="info")return z1();if(z==="add")return d(q);if(z==="confirm-delete"&&w)return C2(w.tab,w.entry);if(z==="locked"&&w)return J1(w.entry);return R1(q)};return r(Y0,{flexDirection:"column",borderStyle:"round",borderColor:Z?"cyan":"gray",padding:1,width:80,children:[r(B1,{color:"cyan",bold:!0,children:"⚙️ 权限管理器"},void 0,!1,void 0,this),n1(),r(Y0,{flexDirection:"column",gap:1,children:m0()},void 0,!1,void 0,this),A&&r(Y0,{marginTop:1,children:r(B1,{color:A.type==="success"?"green":"red",children:A.text},void 0,!1,void 0,this)},void 0,!1,void 0,this),r(Y0,{marginTop:1,children:r(B1,{color:"gray",children:"Tab 切换视图 · Esc 关闭 · Q 退出"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};c6();import{Box as b$,Text as k0,useInput as WH}from"ink";import UH from"ink-select-input";import{useEffect as cX,useMemo as R4,useState as e9}from"react";import{jsxDEV as T1}from"react/jsx-dev-runtime";function HH($){let Y=new Date($),X=new Date().getTime()-Y.getTime(),Q=Math.floor(X/86400000);if(Q===0)return`今天 ${Y.getHours().toString().padStart(2,"0")}:${Y.getMinutes().toString().padStart(2,"0")}`;if(Q===1)return"昨天";if(Q<7)return`${Q}天前`;return`${Y.getMonth()+1}/${Y.getDate()}`}function OH($){let Y=$.split("/");return Y[Y.length-1]||$}var zH=({isSelected:$})=>T1(b$,{marginRight:1,children:T1(k0,{color:$?"cyan":"gray",children:$?"❯":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),FH=({isSelected:$,label:Y})=>T1(k0,{color:$?"cyan":"white",bold:$,children:Y},void 0,!1,void 0,this),K6=20,lX=({sessions:$,onSelect:Y,onCancel:Z})=>{let[X,Q]=e9([]),[J,q]=e9(!1),[K,G]=e9(0),U=q0()==="session-selector",H=P1(!1);WH((B,A)=>{if(A.ctrl&&B==="c"||A.meta&&B==="c"){H();return}if(A.escape&&Z){Z();return}if(A.leftArrow||B==="h"||B==="H"){if(K>0)G((D)=>D-1);return}if(A.rightArrow||B==="l"||B==="L"){if(K<_-1)G((D)=>D+1);return}},{isActive:U}),cX(()=>{if($){Q($);return}(async()=>{q(!0);try{let A=await S0.listSessions();Q(A)}catch(A){console.error("[SessionSelector] Failed to load sessions:",A),Q([])}finally{q(!1)}})()},[$]);let O=$||X,z=R4(()=>{return O.map((B)=>{let A=OH(B.projectPath),D=HH(B.lastMessageTime),I=B.gitBranch?` (${B.gitBranch})`:"",b=B.hasErrors?" ⚠️":"";return{label:`\uD83D\uDCC5 ${D} | ${A}${I} | ${B.messageCount} 条消息${b}`,value:B.sessionId}})},[O]),_=R4(()=>Math.max(1,Math.ceil(z.length/K6)),[z.length]),F=R4(()=>{let B=K*K6;return z.slice(B,B+K6)},[z,K]),N=R4(()=>({start:K*K6+1,end:Math.min((K+1)*K6,z.length)}),[K,z.length]);cX(()=>{G(0)},[O.length]);let w=(B)=>{Y(B.value)};if(J)return T1(b$,{flexDirection:"column",paddingX:2,paddingY:1,children:T1(k0,{children:"⏳ 正在加载会话列表..."},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(O.length===0)return T1(b$,{flexDirection:"column",paddingX:2,paddingY:1,children:[T1(k0,{color:"yellow",children:"⚠️ 没有找到历史会话"},void 0,!1,void 0,this),T1(k0,{dimColor:!0,children:[`
1545
- `,"提示: 开始一次对话后,会话历史将保存到 ~/.blade/projects/"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this);return T1(b$,{flexDirection:"column",paddingX:2,paddingY:1,children:[T1(k0,{bold:!0,color:"cyan",children:"\uD83D\uDCC2 选择要恢复的会话:"},void 0,!1,void 0,this),T1(k0,{dimColor:!0,children:[`
1579
+ `),T=x9.join(A,`${J.name}.md`);await GX.promises.writeFile(T,I,"utf-8"),$()}catch(A){console.error("保存配置失败:",A)}}),L=T1(!1,Y);if(WX((A,k)=>{if(k.escape)b();else if(k.ctrl&&A==="c"||k.meta&&A==="c")L()},{isActive:X!=="tools"}),X==="mode")return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"cyan",children:"\uD83C\uDFAF 选择创建方式"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:"你可以手动配置每个细节,或让 AI 根据你的描述自动生成配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(z4,{items:[{label:"\uD83E\uDD16 AI 智能生成 - 根据描述自动生成完整配置",value:"ai"},{label:"✍️ 手动配置 - 逐步配置每个选项",value:"manual"}],onSelect:(A)=>{if(A.value==="ai")_("ai"),Q("aiPrompt");else _("manual"),Q("name")}},void 0,!1,void 0,this),M(c,{marginTop:1,children:M(h,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 取消"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="aiPrompt")return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"cyan",children:"\uD83E\uDD16 AI 智能生成"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:'描述你想要创建的 Agent(例如:"一个专门用于代码审查的 agent,能够分析代码质量和潜在bug")'},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:[M(h,{color:"green",children:"描述: "},void 0,!1,void 0,this),M(Z6,{value:G,onChange:K,onSubmit:(A)=>{if(!A.trim())return;Q("aiGenerating")}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(c,{children:M(h,{dimColor:!0,children:"按 Enter 开始生成 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="aiGenerating"){if(H)return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"red",children:"❌ AI 生成失败"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{color:"red",children:H},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:"按 ESC 返回修改描述"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"yellow",children:[M(WW,{type:"dots"},void 0,!1,void 0,this)," AI 正在生成配置..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:['根据你的描述:"',G,'"']},void 0,!0,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{color:"gray",children:"正在调用 LLM 生成 agent 配置,请稍候..."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}if(X==="name"){let A=F==="edit";return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"cyan",children:["\uD83D\uDCDD Step 1/7: ",A?"Agent 名称(不可修改)":"输入 Agent 名称"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:A?"编辑模式下名称不可修改(修改名称相当于创建新 Agent)":"名称只能包含小写字母、数字和连字符(例如:code-reviewer)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:[M(h,{color:"green",children:"名称: "},void 0,!1,void 0,this),A?M(h,{children:J.name},void 0,!1,void 0,this):M(Z6,{value:J.name,onChange:(k)=>q({...J,name:k}),onSubmit:(k)=>{if(FW(k))return;N()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(c,{children:M(h,{dimColor:!0,children:A?"按 Enter 继续 | ESC 返回":"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this),A&&M(Z6,{value:"",onChange:()=>{},onSubmit:N,showCursor:!1},"edit-mode-dummy-input",!1,void 0,this)]},void 0,!0,void 0,this)}if(X==="description")return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"cyan",children:"\uD83D\uDCDD Step 2/7: 输入描述信息"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:"简短描述这个 Agent 的用途和使用场景(这将帮助主 Agent 决定何时使用它)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:[M(h,{color:"green",children:"描述: "},void 0,!1,void 0,this),M(Z6,{value:J.description,onChange:(A)=>q({...J,description:A}),onSubmit:(A)=>{if(!A.trim())return;N()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(c,{children:M(h,{dimColor:!0,children:"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="tools")return M(zW,{config:J,setConfig:q,onNext:N,onPrev:b},void 0,!1,void 0,this);if(X==="color")return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"cyan",children:"\uD83C\uDFA8 Step 4/7: 选择背景颜色"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:"为 Agent 选择一个颜色标识(用于在 UI 中区分不同的 Agents)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(z4,{items:OW,onSelect:(A)=>{let k=A.value==="none"?void 0:A.value;q({...J,color:k}),N()}},void 0,!1,void 0,this),M(c,{marginTop:1,children:M(h,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="location")return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"cyan",children:"\uD83D\uDCC2 Step 5/7: 选择保存位置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:"项目级配置仅在当前项目生效,用户级配置全局可用"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(z4,{items:[{label:"\uD83D\uDCC1 项目级 (.blade/agents/) - 仅当前项目",value:"project"},{label:"\uD83C\uDFE0 用户级 (~/.blade/agents/) - 全局可用",value:"user"}],onSelect:(A)=>{q({...J,location:A.value}),N()}},void 0,!1,void 0,this),M(c,{marginTop:1,children:M(h,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="systemPrompt")return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"cyan",children:"\uD83D\uDCAC Step 6/7: 输入系统提示词"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:"定义 Agent 的行为和职责(可选,留空将使用默认提示)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:[M(h,{color:"green",children:"提示词: "},void 0,!1,void 0,this),M(Z6,{value:J.systemPrompt,onChange:(A)=>q({...J,systemPrompt:A}),onSubmit:()=>N()},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(c,{children:M(h,{dimColor:!0,children:"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="confirm")return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"cyan",children:"✅ Step 7/7: 确认配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{flexDirection:"column",paddingLeft:2,marginBottom:1,children:[M(h,{children:[M(h,{bold:!0,color:"green",children:["名称:"," "]},void 0,!0,void 0,this),M(h,{children:J.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(h,{children:[M(h,{bold:!0,color:"green",children:["描述:"," "]},void 0,!0,void 0,this),M(h,{children:J.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(h,{children:[M(h,{bold:!0,color:"green",children:["工具:"," "]},void 0,!0,void 0,this),M(h,{children:J.tools.includes("all")?"所有工具":J.tools.join(", ")||"所有工具"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(h,{children:[M(h,{bold:!0,color:"green",children:["颜色:"," "]},void 0,!0,void 0,this),M(h,{children:J.color||"默认"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(h,{children:[M(h,{bold:!0,color:"green",children:["位置:"," "]},void 0,!0,void 0,this),M(h,{children:J.location==="project"?"项目级":"用户级"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M(h,{children:[M(h,{bold:!0,color:"green",children:["提示词:"," "]},void 0,!0,void 0,this),M(h,{children:J.systemPrompt||"(使用默认)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),M(z4,{items:[{label:"✅ 确认并保存",value:"save"},{label:"⬅️ 返回上一步",value:"back"},{label:"❌ 取消",value:"cancel"}],onSelect:(A)=>{if(A.value==="save")R();else if(A.value==="back")b();else Y()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null}function zW({config:$,setConfig:Y,onNext:Z,onPrev:X}){let{isFocused:Q}=GW({id:"step-tools"});WX((q,G)=>{if(G.escape)X()},{isActive:Q});let J=(q)=>{if(q.includes("all"))Y({...$,tools:["all"]});else Y({...$,tools:q});Z()};return M(c,{flexDirection:"column",paddingY:1,children:[M(c,{marginBottom:1,children:M(h,{bold:!0,color:"cyan",children:"\uD83D\uDD27 Step 3/7: 选择可用工具"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(c,{marginBottom:1,children:M(h,{dimColor:!0,children:"方向键导航,空格切换勾选,Enter 确认进入下一步 | ESC 返回上一步"},void 0,!1,void 0,this)},void 0,!1,void 0,this),M(qW,{options:HW,defaultValue:$.tools,onSubmit:J},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}Q$();import{useMemoizedFn as Q6}from"ahooks";import{Box as W1,Text as w1,useInput as _W}from"ink";import p9 from"ink-select-input";import NW from"node:fs";import{useMemo as BW,useState as g9}from"react";import{jsxDEV as f}from"react/jsx-dev-runtime";function UX({initialMode:$="menu",onComplete:Y,onCancel:Z}){let[X,Q]=g9($),[J,q]=g9(null),[G,K]=g9(0),W=Q6(()=>{M1.clear(),M1.loadFromStandardLocations(),K((N)=>N+1)}),U=BW(()=>{return M1.getAllSubagents()},[G]),H=[{key:"list",label:"\uD83D\uDCCB 查看所有 Agents",value:"list"},{key:"create",label:"➕ 创建新 Agent",value:"create"},{key:"edit",label:"✏️ 编辑 Agent",value:"edit"},{key:"delete",label:"\uD83D\uDDD1️ 删除 Agent",value:"delete"},{key:"cancel",label:"❌ 取消",value:"cancel"}],O=Q6((N)=>{if(N.value==="cancel"){Z?.();return}Q(N.value)}),F=Q6((N)=>{if(q(N.value),X==="edit")Q("editWizard");else if(X==="delete")Q("deleteConfirm")}),_=Q6(async()=>{if(!J?.configPath)return;try{await NW.promises.unlink(J.configPath),W(),z()}catch(N){console.error("删除失败:",N)}}),z=Q6(()=>{Q("menu"),q(null)}),w=T1(!1,Z);if(_W((N,b)=>{if(b.escape){if(X==="menu")Z?.();else if(X==="list"||X==="edit"||X==="delete")z();else if(X==="deleteConfirm")z()}else if(b.ctrl&&N==="c"||b.meta&&N==="c")w()},{isActive:X!=="create"&&X!=="editWizard"}),X==="menu")return f(W1,{flexDirection:"column",paddingY:1,children:[f(W1,{marginBottom:1,children:f(w1,{bold:!0,color:"cyan",children:"\uD83D\uDCCB Agents 管理"},void 0,!1,void 0,this)},void 0,!1,void 0,this),f(p9,{items:H,onSelect:O},void 0,!1,void 0,this),f(W1,{marginTop:1,children:f(w1,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 退出"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="list"){if(U.length===0)return f(W1,{flexDirection:"column",paddingY:1,children:[f(W1,{marginBottom:1,children:f(w1,{bold:!0,color:"cyan",children:"\uD83D\uDCCB 所有 Agents"},void 0,!1,void 0,this)},void 0,!1,void 0,this),f(W1,{paddingLeft:2,children:f(w1,{color:"gray",children:"❌ 没有找到任何 agent 配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),f(W1,{marginTop:1,paddingLeft:2,children:f(w1,{color:"gray",children:"\uD83D\uDCA1 配置文件位置: .blade/agents/ 或 ~/.blade/agents/"},void 0,!1,void 0,this)},void 0,!1,void 0,this),f(W1,{marginTop:1,paddingLeft:2,children:f(w1,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return f(W1,{flexDirection:"column",paddingY:1,children:[f(W1,{marginBottom:1,children:[f(w1,{bold:!0,color:"cyan",children:"\uD83D\uDCCB 所有 Agents"},void 0,!1,void 0,this),f(w1,{color:"gray",children:[" (找到 ",U.length," 个)"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),U.map((N)=>f(W1,{flexDirection:"column",paddingLeft:2,children:[f(W1,{children:f(w1,{children:[f(w1,{bold:!0,color:N.color||"white",children:["• ",N.name]},void 0,!0,void 0,this),f(w1,{color:"gray",children:[" - ",N.description]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),N.tools&&N.tools.length>0&&f(W1,{paddingLeft:2,children:f(w1,{color:"gray",children:["工具: ",N.tools.join(", ")]},void 0,!0,void 0,this)},void 0,!1,void 0,this),N.configPath&&f(W1,{paddingLeft:2,children:f(w1,{color:"gray",dimColor:!0,children:N.configPath},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},N.name,!0,void 0,this)),f(W1,{marginTop:1,paddingLeft:2,children:f(w1,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}let B=(N)=>{if(U.length===0)return f(W1,{flexDirection:"column",paddingY:1,children:[f(W1,{marginBottom:1,children:f(w1,{bold:!0,color:"cyan",children:N},void 0,!1,void 0,this)},void 0,!1,void 0,this),f(W1,{paddingLeft:2,children:f(w1,{color:"gray",children:"❌ 没有找到任何 agent 配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),f(W1,{marginTop:1,paddingLeft:2,children:f(w1,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);let b=U.map((V)=>({key:V.name,label:`${V.name} - ${V.description}`,value:V}));return f(W1,{flexDirection:"column",paddingY:1,children:[f(W1,{marginBottom:1,children:f(w1,{bold:!0,color:"cyan",children:N},void 0,!1,void 0,this)},void 0,!1,void 0,this),f(p9,{items:b,onSelect:F},void 0,!1,void 0,this),f(W1,{marginTop:1,children:f(w1,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};if(X==="create")return f(X6,{onComplete:()=>{W(),z()},onCancel:z},void 0,!1,void 0,this);if(X==="edit")return B("✏️ 编辑 Agent");if(X==="editWizard"&&J){let N={name:J.name,description:J.description,tools:J.tools||[],color:J.color,location:J.configPath?.includes(".blade/agents")?"project":"user",systemPrompt:J.systemPrompt||""};return f(X6,{initialConfig:N,onComplete:()=>{W(),z()},onCancel:z},void 0,!1,void 0,this)}if(X==="delete")return B("\uD83D\uDDD1️ 删除 Agent");if(X==="deleteConfirm"&&J)return f(W1,{flexDirection:"column",paddingY:1,children:[f(W1,{marginBottom:1,children:f(w1,{bold:!0,color:"red",children:"⚠️ 确认删除"},void 0,!1,void 0,this)},void 0,!1,void 0,this),f(W1,{marginBottom:1,paddingLeft:2,children:f(w1,{children:["你确定要删除 Agent"," ",f(w1,{bold:!0,color:"yellow",children:J.name},void 0,!1,void 0,this)," ","吗?"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),f(W1,{marginBottom:1,paddingLeft:2,children:f(w1,{dimColor:!0,children:["文件路径: ",J.configPath]},void 0,!0,void 0,this)},void 0,!1,void 0,this),f(W1,{marginBottom:1,paddingLeft:2,children:f(w1,{color:"red",children:"此操作无法撤销!"},void 0,!1,void 0,this)},void 0,!1,void 0,this),f(p9,{items:[{label:"\uD83D\uDDD1️ 确认删除",value:"confirm"},{label:"❌ 取消",value:"cancel"}],onSelect:(N)=>{if(N.value==="confirm")_();else z()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null}s1();import{Box as w$,Text as F1}from"ink";import LW from"react";r6();j9();import{useEffect as wW,useState as HX}from"react";function OX($=process.cwd(),Y=5000){let[Z,X]=HX(null),[Q,J]=HX(!0);return wW(()=>{let q=!0,G=async()=>{try{let W=await n$($);if(!q)return;if(!W){X(null),J(!1);return}let U=await BZ($);if(!q)return;X(U)}catch{if(q)X(null)}finally{if(q)J(!1)}};G();let K=null;if(Y>0)K=setInterval(G,Y);return()=>{if(q=!1,K)clearInterval(K)}},[$,Y]),{branch:Z,loading:Q}}import{jsxDEV as e,Fragment as J6}from"react/jsx-dev-runtime";var FX=LW.memo(()=>{let $=e6(),Y=f0(),Z=O$(),Q=t6()==="shortcuts",J=lY(),{branch:q}=OX(),G=$4(),K=pY(),W=xY(),U=tY(),H=G?K$(G):!1,F=(()=>{if(Z==="default")return null;if(Z==="autoEdit")return e(F1,{color:"magenta",children:["▶▶ auto edit on ",e(F1,{color:"gray",children:"(shift+tab to cycle)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="plan")return e(F1,{color:"cyan",children:["‖ plan mode on ",e(F1,{color:"gray",children:"(shift+tab to cycle)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="yolo")return e(F1,{color:"red",children:["⚡ yolo mode on ",e(F1,{color:"gray",children:"(all tools auto-approved)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null})(),_=F!==null,z=[["Enter:发送","Shift+Enter:换行","Esc:中止"],["Shift+Tab:切换模式","↑/↓:历史","Tab:补全"],["Ctrl+A:行首","Ctrl+E:行尾","Ctrl+K:删到尾"],["Ctrl+U:删到首","Ctrl+W:删单词","Ctrl+C:退出"]];return e(w$,{flexDirection:"row",justifyContent:"space-between",paddingX:2,paddingY:0,children:[Q?e(w$,{flexDirection:"column",gap:0,children:z.map((w,B)=>e(w$,{flexDirection:"row",children:[w.map((N,b)=>{let[V,R]=N.split(":");return e(w$,{flexDirection:"row",width:20,children:[e(F1,{color:"yellow",children:V},void 0,!1,void 0,this),e(F1,{color:"gray",children:":"},void 0,!1,void 0,this),e(F1,{color:"white",children:R},void 0,!1,void 0,this)]},b,!0,void 0,this)}),B===z.length-1&&e(F1,{color:"cyan",children:" ? 关闭"},void 0,!1,void 0,this)]},B,!0,void 0,this))},void 0,!1,void 0,this):e(w$,{flexDirection:"row",gap:1,children:[q&&e(J6,{children:[e(F1,{color:"gray",children:[" ",q]},void 0,!0,void 0,this),e(F1,{color:"gray",children:"·"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),F,_&&e(F1,{color:"gray",children:"·"},void 0,!1,void 0,this),e(F1,{color:"gray",children:"? for shortcuts"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),e(w$,{flexDirection:"row",gap:1,children:!$?e(F1,{color:"red",children:"⚠ API 密钥未配置"},void 0,!1,void 0,this):e(J6,{children:[H&&e(J6,{children:[U?e(F1,{color:"cyan",children:"Thinking on"},void 0,!1,void 0,this):e(F1,{color:"gray",children:"Tab:Thinking"},void 0,!1,void 0,this),e(F1,{color:"gray",children:"·"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),G&&e(F1,{color:"gray",children:G.model},void 0,!1,void 0,this),e(F1,{color:"gray",children:"·"},void 0,!1,void 0,this),W?e(F1,{color:"yellow",children:"压缩中..."},void 0,!1,void 0,this):e(F1,{color:K<20?"red":K<50?"yellow":"gray",children:[K,"%"]},void 0,!0,void 0,this),Y&&e(J6,{children:[e(F1,{color:"gray",children:"·"},void 0,!1,void 0,this),e(F1,{color:"yellow",children:"Processing..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),J&&e(J6,{children:[e(F1,{color:"gray",children:"·"},void 0,!1,void 0,this),e(F1,{color:"yellow",children:"再按一次 Ctrl+C 退出"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{Box as m9,Text as d9}from"ink";import AW from"react";import{jsxDEV as L$}from"react/jsx-dev-runtime";var zX=AW.memo(({suggestions:$,selectedIndex:Y,visible:Z,maxDisplay:X=8})=>{if(!Z||$.length===0)return null;let Q=0,J=Math.min(X,$.length),q=Y>=$.length;if(Y>=X&&!q)Q=Y-X+1,J=Y+1;let G=$.slice(Q,J),K=$.length>X;return L$(m9,{flexDirection:"column",paddingX:2,paddingY:0,children:[G.map((W,U)=>{let O=Q+U===Y;return L$(m9,{justifyContent:"space-between",paddingX:1,children:[L$(d9,{color:O?"cyan":"white",bold:O,children:W.command},void 0,!1,void 0,this),L$(d9,{color:O?"cyan":"gray",dimColor:!O,children:W.description},void 0,!1,void 0,this)]},W.command,!0,void 0,this)}),K&&L$(m9,{paddingX:1,children:L$(d9,{color:q?"cyan":"gray",bold:q,dimColor:!q,children:["... and ",$.length-X," more"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});s1();import{Box as O0,Text as I0,useInput as XU}from"ink";import QU from"ink-select-input";import{useMemo as JU}from"react";import{useEffect as bW,useState as RW}from"react";import{useStdout as VW}from"ink";import{debounce as DW}from"lodash-es";function A$($=200){let{stdout:Y}=VW(),[Z,X]=RW(Y.columns||80);return bW(()=>{let Q=DW(()=>{X(Y.columns||80)},$);return Q(),Y.on("resize",Q),()=>{Y.off("resize",Q),Q.cancel()}},[Y,$]),Z}import{Box as g1,Text as a1}from"ink";import w4 from"react";var IW={name:"ayu-dark",colors:{primary:"#ffcc66",secondary:"#bae67e",accent:"#73d0ff",success:"#bae67e",warning:"#ffcc66",error:"#ff3333",info:"#73d0ff",light:"#f0f0f0",dark:"#000000",muted:"#5c6773",highlight:"#2d323b",text:{primary:"#e6e1cf",secondary:"#bae67e",muted:"#5c6773",light:"#ffffff"},background:{primary:"#0f1419",secondary:"#14191f",dark:"#000000"},border:{light:"#2d323b",dark:"#000000"},syntax:{comment:"#5c6773",string:"#bae67e",number:"#ffcc66",keyword:"#ff8f40",function:"#73d0ff",variable:"#e6e1cf",operator:"#f29e74",type:"#73d0ff",tag:"#ff8f40",attr:"#ffd580",default:"#e6e1cf"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(0, 0, 0, 0.2)",base:"0 1px 3px 0 rgba(0, 0, 0, 0.3), 0 1px 2px 0 rgba(0, 0, 0, 0.2)",lg:"0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2)"}},MW={name:"dracula",colors:{primary:"#bd93f9",secondary:"#ffb86c",accent:"#ff79c6",success:"#50fa7b",warning:"#f1fa8c",error:"#ff5555",info:"#8be9fd",light:"#f8f8f2",dark:"#282a36",muted:"#6272a4",highlight:"#44475a",text:{primary:"#f8f8f2",secondary:"#f1fa8c",muted:"#6272a4",light:"#ffffff"},background:{primary:"#282a36",secondary:"#44475a",dark:"#21222c"},border:{light:"#44475a",dark:"#000000"},syntax:{comment:"#6272a4",string:"#f1fa8c",number:"#bd93f9",keyword:"#ff79c6",function:"#50fa7b",variable:"#f8f8f2",operator:"#ff79c6",type:"#8be9fd",tag:"#ff79c6",attr:"#50fa7b",default:"#f8f8f2"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(40, 42, 54, 0.2)",base:"0 1px 3px 0 rgba(40, 42, 54, 0.3), 0 1px 2px 0 rgba(40, 42, 54, 0.2)",lg:"0 10px 15px -3px rgba(40, 42, 54, 0.3), 0 4px 6px -2px rgba(40, 42, 54, 0.2)"}},kW={name:"monokai",colors:{primary:"#66d9ef",secondary:"#a6e22e",accent:"#f92672",success:"#a6e22e",warning:"#e6db74",error:"#f92672",info:"#66d9ef",light:"#f8f8f2",dark:"#272822",muted:"#75715e",highlight:"#3e3d32",text:{primary:"#f8f8f2",secondary:"#e6db74",muted:"#75715e",light:"#ffffff"},background:{primary:"#272822",secondary:"#3e3d32",dark:"#1e1f1c"},border:{light:"#3e3d32",dark:"#000000"},syntax:{comment:"#75715e",string:"#e6db74",number:"#ae81ff",keyword:"#f92672",function:"#a6e22e",variable:"#f8f8f2",operator:"#f92672",type:"#66d9ef",tag:"#f92672",attr:"#a6e22e",default:"#f8f8f2"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(39, 40, 34, 0.2)",base:"0 1px 3px 0 rgba(39, 40, 34, 0.3), 0 1px 2px 0 rgba(39, 40, 34, 0.2)",lg:"0 10px 15px -3px rgba(39, 40, 34, 0.3), 0 4px 6px -2px rgba(39, 40, 34, 0.2)"}},jW={name:"nord",colors:{primary:"#88c0d0",secondary:"#81a1c1",accent:"#b48ead",success:"#a3be8c",warning:"#ebcb8b",error:"#bf616a",info:"#88c0d0",light:"#eceff4",dark:"#2e3440",muted:"#4c566a",highlight:"#434c5e",text:{primary:"#eceff4",secondary:"#d8dee9",muted:"#4c566a",light:"#ffffff"},background:{primary:"#2e3440",secondary:"#3b4252",dark:"#242933"},border:{light:"#434c5e",dark:"#000000"},syntax:{comment:"#616e88",string:"#a3be8c",number:"#b48ead",keyword:"#81a1c1",function:"#88c0d0",variable:"#d8dee9",operator:"#81a1c1",type:"#8fbcbb",tag:"#81a1c1",attr:"#8fbcbb",default:"#eceff4"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(46, 52, 64, 0.2)",base:"0 1px 3px 0 rgba(46, 52, 64, 0.3), 0 1px 2px 0 rgba(46, 52, 64, 0.2)",lg:"0 10px 15px -3px rgba(46, 52, 64, 0.3), 0 4px 6px -2px rgba(46, 52, 64, 0.2)"}},EW={name:"solarized-light",colors:{primary:"#268bd2",secondary:"#2aa198",accent:"#d33682",success:"#859900",warning:"#b58900",error:"#dc322f",info:"#268bd2",light:"#fdf6e3",dark:"#073642",muted:"#93a1a1",highlight:"#eee8d5",text:{primary:"#586e75",secondary:"#657b83",muted:"#93a1a1",light:"#002b36"},background:{primary:"#fdf6e3",secondary:"#eee8d5",dark:"#073642"},border:{light:"#eee8d5",dark:"#073642"},syntax:{comment:"#93a1a1",string:"#2aa198",number:"#d33682",keyword:"#859900",function:"#268bd2",variable:"#657b83",operator:"#859900",type:"#b58900",tag:"#268bd2",attr:"#93a1a1",default:"#657b83"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(253, 246, 227, 0.2)",base:"0 1px 3px 0 rgba(253, 246, 227, 0.3), 0 1px 2px 0 rgba(253, 246, 227, 0.2)",lg:"0 10px 15px -3px rgba(253, 246, 227, 0.3), 0 4px 6px -2px rgba(253, 246, 227, 0.2)"}},vW={name:"solarized-dark",colors:{primary:"#268bd2",secondary:"#2aa198",accent:"#d33682",success:"#859900",warning:"#b58900",error:"#dc322f",info:"#268bd2",light:"#fdf6e3",dark:"#073642",muted:"#586e75",highlight:"#073642",text:{primary:"#839496",secondary:"#93a1a1",muted:"#586e75",light:"#fdf6e3"},background:{primary:"#002b36",secondary:"#073642",dark:"#001f29"},border:{light:"#073642",dark:"#000000"},syntax:{comment:"#586e75",string:"#2aa198",number:"#d33682",keyword:"#859900",function:"#268bd2",variable:"#839496",operator:"#859900",type:"#b58900",tag:"#268bd2",attr:"#93a1a1",default:"#839496"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(0, 43, 54, 0.2)",base:"0 1px 3px 0 rgba(0, 43, 54, 0.3), 0 1px 2px 0 rgba(0, 43, 54, 0.2)",lg:"0 10px 15px -3px rgba(0, 43, 54, 0.3), 0 4px 6px -2px rgba(0, 43, 54, 0.2)"}},yW={name:"tokyo-night",colors:{primary:"#7aa2f7",secondary:"#7dcfff",accent:"#bb9af7",success:"#9ece6a",warning:"#e0af68",error:"#f7768e",info:"#7aa2f7",light:"#c0caf5",dark:"#1a1b26",muted:"#565f89",highlight:"#292e42",text:{primary:"#a9b1d6",secondary:"#c0caf5",muted:"#565f89",light:"#ffffff"},background:{primary:"#1a1b26",secondary:"#292e42",dark:"#16161e"},border:{light:"#292e42",dark:"#000000"},syntax:{comment:"#565f89",string:"#9ece6a",number:"#ff9e64",keyword:"#bb9af7",function:"#7aa2f7",variable:"#c0caf5",operator:"#89ddff",type:"#7dcfff",tag:"#f7768e",attr:"#7aa2f7",default:"#a9b1d6"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(26, 27, 38, 0.2)",base:"0 1px 3px 0 rgba(26, 27, 38, 0.3), 0 1px 2px 0 rgba(26, 27, 38, 0.2)",lg:"0 10px 15px -3px rgba(26, 27, 38, 0.3), 0 4px 6px -2px rgba(26, 27, 38, 0.2)"}},PW={name:"github",colors:{primary:"#0969da",secondary:"#8250df",accent:"#bc4c00",success:"#1a7f37",warning:"#9a6700",error:"#d1242f",info:"#0969da",light:"#f6f8fa",dark:"#24292f",muted:"#6e7781",highlight:"#ddf4ff",text:{primary:"#24292f",secondary:"#57606a",muted:"#6e7781",light:"#ffffff"},background:{primary:"#ffffff",secondary:"#f6f8fa",dark:"#24292f"},border:{light:"#d0d7de",dark:"#24292f"},syntax:{comment:"#6e7781",string:"#0a3069",number:"#0550ae",keyword:"#cf222e",function:"#8250df",variable:"#24292f",operator:"#cf222e",type:"#0550ae",tag:"#116329",attr:"#0550ae",default:"#24292f"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(255, 255, 255, 0.2)",base:"0 1px 3px 0 rgba(255, 255, 255, 0.3), 0 1px 2px 0 rgba(255, 255, 255, 0.2)",lg:"0 10px 15px -3px rgba(255, 255, 255, 0.3), 0 4px 6px -2px rgba(255, 255, 255, 0.2)"}},TW={name:"gruvbox",colors:{primary:"#83a598",secondary:"#8ec07c",accent:"#d3869b",success:"#b8bb26",warning:"#fabd2f",error:"#fb4934",info:"#83a598",light:"#fbf1c7",dark:"#282828",muted:"#928374",highlight:"#3c3836",text:{primary:"#ebdbb2",secondary:"#d5c4a1",muted:"#928374",light:"#ffffff"},background:{primary:"#282828",secondary:"#3c3836",dark:"#1d2021"},border:{light:"#3c3836",dark:"#000000"},syntax:{comment:"#928374",string:"#b8bb26",number:"#d3869b",keyword:"#fb4934",function:"#8ec07c",variable:"#ebdbb2",operator:"#fe8019",type:"#fabd2f",tag:"#fb4934",attr:"#b8bb26",default:"#ebdbb2"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(40, 40, 40, 0.2)",base:"0 1px 3px 0 rgba(40, 40, 40, 0.3), 0 1px 2px 0 rgba(40, 40, 40, 0.2)",lg:"0 10px 15px -3px rgba(40, 40, 40, 0.3), 0 4px 6px -2px rgba(40, 40, 40, 0.2)"}},SW={name:"one-dark",colors:{primary:"#61afef",secondary:"#c678dd",accent:"#e5c07b",success:"#98c379",warning:"#e5c07b",error:"#e06c75",info:"#56b6c2",light:"#abb2bf",dark:"#282c34",muted:"#5c6370",highlight:"#3e4451",text:{primary:"#abb2bf",secondary:"#c6c8d0",muted:"#5c6370",light:"#ffffff"},background:{primary:"#282c34",secondary:"#3e4451",dark:"#21252b"},border:{light:"#3e4451",dark:"#000000"},syntax:{comment:"#5c6370",string:"#98c379",number:"#d19a66",keyword:"#c678dd",function:"#61afef",variable:"#e06c75",operator:"#56b6c2",type:"#e5c07b",tag:"#e06c75",attr:"#d19a66",default:"#abb2bf"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(40, 44, 52, 0.2)",base:"0 1px 3px 0 rgba(40, 44, 52, 0.3), 0 1px 2px 0 rgba(40, 44, 52, 0.2)",lg:"0 10px 15px -3px rgba(40, 44, 52, 0.3), 0 4px 6px -2px rgba(40, 44, 52, 0.2)"}},CW={name:"catppuccin",colors:{primary:"#89b4fa",secondary:"#cba6f7",accent:"#f5c2e7",success:"#a6e3a1",warning:"#f9e2af",error:"#f38ba8",info:"#89dceb",light:"#cdd6f4",dark:"#11111b",muted:"#6c7086",highlight:"#181825",text:{primary:"#cdd6f4",secondary:"#bac2de",muted:"#6c7086",light:"#ffffff"},background:{primary:"#1e1e2e",secondary:"#181825",dark:"#11111b"},border:{light:"#181825",dark:"#000000"},syntax:{comment:"#6c7086",string:"#a6e3a1",number:"#fab387",keyword:"#cba6f7",function:"#89b4fa",variable:"#cdd6f4",operator:"#89dceb",type:"#f5c2e7",tag:"#f38ba8",attr:"#89b4fa",default:"#cdd6f4"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(30, 30, 46, 0.2)",base:"0 1px 3px 0 rgba(30, 30, 46, 0.3), 0 1px 2px 0 rgba(30, 30, 46, 0.2)",lg:"0 10px 15px -3px rgba(30, 30, 46, 0.3), 0 4px 6px -2px rgba(30, 30, 46, 0.2)"}},fW={name:"rose-pine",colors:{primary:"#9ccfd8",secondary:"#c4a7e7",accent:"#f6c177",success:"#31748f",warning:"#f6c177",error:"#eb6f92",info:"#9ccfd8",light:"#e0def4",dark:"#191724",muted:"#6e6a86",highlight:"#1f1d2e",text:{primary:"#e0def4",secondary:"#cecacd",muted:"#6e6a86",light:"#ffffff"},background:{primary:"#191724",secondary:"#1f1d2e",dark:"#12101a"},border:{light:"#1f1d2e",dark:"#000000"},syntax:{comment:"#6e6a86",string:"#9ccfd8",number:"#ea9a97",keyword:"#c4a7e7",function:"#31748f",variable:"#e0def4",operator:"#f6c177",type:"#9ccfd8",tag:"#eb6f92",attr:"#f6c177",default:"#e0def4"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(25, 23, 36, 0.2)",base:"0 1px 3px 0 rgba(25, 23, 36, 0.3), 0 1px 2px 0 rgba(25, 23, 36, 0.2)",lg:"0 10px 15px -3px rgba(25, 23, 36, 0.3), 0 4px 6px -2px rgba(25, 23, 36, 0.2)"}},hW={name:"kanagawa",colors:{primary:"#8ba4b0",secondary:"#a292a3",accent:"#c47fd5",success:"#76946a",warning:"#c0a36e",error:"#c34043",info:"#7e9cd8",light:"#dcd7ba",dark:"#1f1f28",muted:"#727169",highlight:"#2a2a37",text:{primary:"#dcd7ba",secondary:"#c8c093",muted:"#727169",light:"#ffffff"},background:{primary:"#1f1f28",secondary:"#2a2a37",dark:"#16161d"},border:{light:"#2a2a37",dark:"#000000"},syntax:{comment:"#727169",string:"#98bb6c",number:"#d27e99",keyword:"#957fb8",function:"#7e9cd8",variable:"#dcd7ba",operator:"#c0a36e",type:"#7aa89f",tag:"#c34043",attr:"#7fb4ca",default:"#dcd7ba"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(31, 31, 40, 0.2)",base:"0 1px 3px 0 rgba(31, 31, 40, 0.3), 0 1px 2px 0 rgba(31, 31, 40, 0.2)",lg:"0 10px 15px -3px rgba(31, 31, 40, 0.3), 0 4px 6px -2px rgba(31, 31, 40, 0.2)"}},x0=[{id:"ayu-dark",label:"Ayu Dark",theme:IW,tags:["dark","popular"]},{id:"dracula",label:"Dracula",theme:MW,tags:["dark","popular"]},{id:"monokai",label:"Monokai",theme:kW,tags:["dark","classic"]},{id:"nord",label:"Nord",theme:jW,tags:["dark","minimal"]},{id:"solarized-light",label:"Solarized Light",theme:EW,tags:["light"]},{id:"solarized-dark",label:"Solarized Dark",theme:vW,tags:["dark"]},{id:"tokyo-night",label:"Tokyo Night",theme:yW,tags:["dark","popular"]},{id:"github",label:"GitHub",theme:PW,tags:["light","minimal"]},{id:"gruvbox",label:"Gruvbox",theme:TW,tags:["dark","warm"]},{id:"one-dark",label:"One Dark",theme:SW,tags:["dark","popular"]},{id:"catppuccin",label:"Catppuccin",theme:CW,tags:["dark","pastel"]},{id:"rose-pine",label:"Rose Pine",theme:fW,tags:["dark","elegant"]},{id:"kanagawa",label:"Kanagawa",theme:hW,tags:["dark","japanese"]}];function _4($){if(!$||typeof $!=="object")return!1;if(!$.name||typeof $.name!=="string")return!1;if(!$.colors||typeof $.colors!=="object")return!1;let Y=["primary","secondary","accent","success","warning","error","info","light","dark","muted","highlight"];for(let J of Y)if(!$.colors[J]||typeof $.colors[J]!=="string")return!1;if(!$.colors.text||typeof $.colors.text!=="object")return!1;if(!$.colors.background||typeof $.colors.background!=="object")return!1;if(!$.colors.border||typeof $.colors.border!=="object")return!1;let Z=["primary","secondary","muted","light"],X=["primary","secondary","dark"],Q=["light","dark"];for(let J of Z)if(!$.colors.text[J]||typeof $.colors.text[J]!=="string")return!1;for(let J of X)if(!$.colors.background[J]||typeof $.colors.background[J]!=="string")return!1;for(let J of Q)if(!$.colors.border[J]||typeof $.colors.border[J]!=="string")return!1;if(!$.spacing||typeof $.spacing!=="object")return!1;if(!$.typography||typeof $.typography!=="object")return!1;if(!$.borderRadius||typeof $.borderRadius!=="object")return!1;if(!$.boxShadow||typeof $.boxShadow!=="object")return!1;return!0}var _X={primary:"#0066cc",secondary:"#6c757d",accent:"#e83e8c",success:"#28a745",warning:"#ffc107",error:"#dc3545",info:"#17a2b8",light:"#f8f9fa",dark:"#343a40",muted:"#6c757d",highlight:"#fff3cd",text:{primary:"#212529",secondary:"#6c757d",muted:"#6c757d",light:"#ffffff"},background:{primary:"#ffffff",secondary:"#f8f9fa",dark:"#343a40"},border:{light:"#dee2e6",dark:"#495057"},syntax:{comment:"#6c757d",string:"#28a745",number:"#e83e8c",keyword:"#007bff",function:"#17a2b8",variable:"#495057",operator:"#ffc107",type:"#007bff",tag:"#dc3545",attr:"#ffc107",default:"#212529"}},N4={name:"default",colors:_X,spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(0, 0, 0, 0.05)",base:"0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)",lg:"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)"}},NX={...N4,name:"dark",colors:{..._X,text:{primary:"#ffffff",secondary:"#e2e8f0",muted:"#94a3b8",light:"#000000"},background:{primary:"#1e293b",secondary:"#334155",dark:"#0f172a"},border:{light:"#475569",dark:"#64748b"},syntax:{comment:"#94a3b8",string:"#34d399",number:"#f472b6",keyword:"#60a5fa",function:"#06b6d4",variable:"#e2e8f0",operator:"#fbbf24",type:"#60a5fa",tag:"#fb7185",attr:"#fbbf24",default:"#ffffff"}}};class u9{currentTheme=N4;themes=new Map;constructor(){this.themes.set("default",N4),this.themes.set("dark",NX);for(let $ of x0)this.themes.set($.id,$.theme)}setTheme($){let Y=this.themes.get($);if(Y)this.currentTheme=Y;else throw Error(`Theme '${$}' not found`)}getTheme(){return this.currentTheme}addTheme($,Y){if(!_4(Y))throw Error(`Invalid theme configuration for '${$}'`);this.themes.set($,Y)}getAvailableThemes(){return Array.from(this.themes.keys())}getCurrentThemeName(){return this.currentTheme.name}getThemeByName($){return this.themes.get($)}removeTheme($){if($==="default"||$==="dark"||x0.some((Z)=>Z.id===$))throw Error(`Cannot remove built-in theme '${$}'`);this.themes.delete($)}hasTheme($){return this.themes.has($)}validateTheme($){return _4($)}}var Z1=new u9;import{Box as b$,Text as p0}from"ink";import{common as xW,createLowlight as pW}from"lowlight";import gW from"react";import{jsxDEV as h1}from"react/jsx-dev-runtime";var c9=pW(xW);function B4($,Y,Z=0){if($.type==="text")return h1(p0,{children:$.value},Z,!1,void 0,this);if($.type==="element"){let X=$.properties?.className?.[0]||"",Q=Y.default;if(X.includes("comment"))Q=Y.comment;else if(X.includes("string"))Q=Y.string;else if(X.includes("number"))Q=Y.number;else if(X.includes("keyword"))Q=Y.keyword;else if(X.includes("function"))Q=Y.function;else if(X.includes("variable"))Q=Y.variable;else if(X.includes("operator"))Q=Y.operator;else if(X.includes("type"))Q=Y.type;else if(X.includes("tag"))Q=Y.tag;else if(X.includes("attr"))Q=Y.attr;let J=$.children?.map((q,G)=>B4(q,Y,G));return h1(p0,{color:Q,children:J},Z,!1,void 0,this)}if($.type==="root"&&$.children)return h1(gW.Fragment,{children:$.children.map((X,Q)=>B4(X,Y,Q))},Z,!1,void 0,this);return h1(p0,{},Z,!1,void 0,this)}function mW($,Y,Z,X){let Q=Z||Z1.getTheme().colors.syntax,J=$;if(X&&$.length>X)J=$.slice(0,X-3)+"...";try{if(!Y||!c9.registered(Y)){let G=c9.highlightAuto(J);if(!G.children||G.children.length===0)return h1(p0,{color:Q.default,children:J},void 0,!1,void 0,this);return B4(G,Q)}let q=c9.highlight(Y,J);if(!q.children||q.children.length===0)return h1(p0,{color:Q.default,children:J},void 0,!1,void 0,this);return B4(q,Q)}catch(q){return h1(p0,{color:Q.default,children:J},void 0,!1,void 0,this)}}var l9=({content:$,language:Y,showLineNumbers:Z=!0,terminalWidth:X,availableHeight:Q})=>{let J=Z1.getTheme(),q=$.split(`
1580
+ `),G=0;if(Q&&q.length>Q){let H=Math.max(Q,5);if(q.length>H)G=q.length-H,q=q.slice(G)}let K=q.length+G,W=String(K).length+1;return h1(b$,{borderStyle:"round",borderColor:J.colors.border.light,paddingX:1,paddingY:0,marginY:1,flexDirection:"column",children:[Y&&h1(b$,{marginBottom:0,children:h1(p0,{color:J.colors.text.secondary,children:Y},void 0,!1,void 0,this)},void 0,!1,void 0,this),G>0&&h1(b$,{marginBottom:0,children:h1(p0,{color:J.colors.text.muted,dimColor:!0,children:["... ",G," lines hidden ..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this),q.map((U,H)=>{let O=H+G+1;return h1(b$,{flexDirection:"row",children:[Z&&h1(b$,{width:W,children:h1(p0,{color:J.colors.text.muted,dimColor:!0,children:String(O).padStart(W-1," ")},void 0,!1,void 0,this)},void 0,!1,void 0,this),h1(b$,{flexShrink:1,children:U.trim()===""?h1(p0,{children:" "},void 0,!1,void 0,this):mW(U,Y,J.colors.syntax)},void 0,!1,void 0,this)]},H,!0,void 0,this)})]},void 0,!0,void 0,this)};import{Box as BX,Text as g0}from"ink";import{jsxDEV as K0}from"react/jsx-dev-runtime";function dW($){let Y=$.split(`
1581
+ `),Z=[],X=0,Q=0;for(let J of Y){if(J.startsWith("---")||J.startsWith("+++"))continue;if(J.startsWith("@@")){let q=J.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);if(q)X=parseInt(q[1],10),Q=parseInt(q[3],10);Z.push({type:"header",content:J});continue}if(J.startsWith("-")){Z.push({type:"remove",content:J.substring(1),lineNumber:X}),X++;continue}if(J.startsWith("+")){Z.push({type:"add",content:J.substring(1),lineNumber:Q}),Q++;continue}if(J.startsWith(" ")||J===""){Z.push({type:"context",content:J.substring(1),lineNumber:Q}),X++,Q++;continue}}return Z}var i9=({patch:$,startLine:Y,matchLine:Z,terminalWidth:X,maxLines:Q=20})=>{let J=Z1.getTheme(),q=dW($),K=Math.max(...q.map((F)=>F.lineNumber||0)).toString().length+1,W=q.length,U=W>Q,H=U?q.slice(0,Q):q,O=W-Q;return K0(BX,{flexDirection:"column",marginTop:1,marginBottom:1,children:[K0(g0,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,X)))},void 0,!1,void 0,this),U&&K0(g0,{color:J.colors.info,children:["\uD83D\uDCCA 显示前 ",Q," 行,共 ",W," 行 diff"]},void 0,!0,void 0,this),U&&K0(g0,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,X)))},void 0,!1,void 0,this),H.map((F,_)=>{if(F.type==="header")return K0(g0,{color:J.colors.muted,dimColor:!0,children:F.content},_,!1,void 0,this);let z=F.lineNumber?F.lineNumber.toString().padStart(K," "):" ".repeat(K),w=" ",B,N;if(F.type==="add")w="+",N=J.colors.success,B=void 0;else if(F.type==="remove")w="-",N=J.colors.error,B=void 0;else N=J.colors.text.primary;let b=Math.max(0,X-K-2),V=F.content;if(V.length>b)V=V.substring(0,b-3)+"...";return K0(g0,{color:N,backgroundColor:B,children:[K0(g0,{dimColor:!0,children:z},void 0,!1,void 0,this),K0(g0,{children:w},void 0,!1,void 0,this),K0(g0,{children:[" ",V]},void 0,!0,void 0,this)]},_,!0,void 0,this)}),U&&K0(BX,{marginTop:1,children:K0(g0,{color:J.colors.warning,dimColor:!0,children:["⚠️ 已隐藏剩余 ",O," 行 diff(总共 ",W," 行)"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),K0(g0,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,X)))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Text as V0}from"ink";import cW from"react";import uW from"string-width";var y2=($)=>{let Y=$.replace(/\*\*(.*?)\*\*/g,"$1").replace(/\*(.*?)\*/g,"$1").replace(/_(.*?)_/g,"$1").replace(/~~(.*?)~~/g,"$1").replace(/`(.*?)`/g,"$1").replace(/<u>(.*?)<\/u>/g,"$1").replace(/\[(.*?)\]\(.*?\)/g,"$1");return uW(Y)},wX=($,Y,Z="...")=>{if(y2($)<=Y)return $;if(Y<=Z.length)return Z.substring(0,Y);let Q=0,J=$.length,q="";while(Q<=J){let G=Math.floor((Q+J)/2),K=$.substring(0,G);if(y2(K)<=Y-Z.length)q=K,Q=G+1;else J=G-1}return q+Z},LX=($)=>{return/[*_~`<[\]https?:]/.test($)};import{jsxDEV as W0,Fragment as iW}from"react/jsx-dev-runtime";var r9=2,a9=1,n9=2;var lW=({text:$})=>{let Y=Z1.getTheme();if(!LX($))return W0(V0,{children:$},void 0,!1,void 0,this);let Z=[],X=0,Q=/(\*\*.*?\*\*|\*(?!\s).*?(?<!\s)\*|_(?!\s).*?(?<!\s)_|~~.*?~~|`+[^`]+`+|\[.*?\]\(.*?\)|https?:\/\/\S+)/g,J;while((J=Q.exec($))!==null){if(J.index>X)Z.push(W0(V0,{children:$.slice(X,J.index)},`t-${X}`,!1,void 0,this));let q=J[0],G=null,K=`m-${J.index}`;try{if(q.startsWith("**")&&q.endsWith("**")&&q.length>r9*2)G=W0(V0,{bold:!0,children:q.slice(r9,-r9)},K,!1,void 0,this);else if(q.length>a9*2&&(q.startsWith("*")&&q.endsWith("*")||q.startsWith("_")&&q.endsWith("_"))){let W=$.substring(J.index-1,J.index),U=$.substring(Q.lastIndex,Q.lastIndex+1);if(!(/\w/.test(W)||/\w/.test(U)||/[./\\]/.test(W+U)))G=W0(V0,{italic:!0,children:q.slice(a9,-a9)},K,!1,void 0,this)}else if(q.startsWith("~~")&&q.endsWith("~~")&&q.length>n9*2)G=W0(V0,{strikethrough:!0,children:q.slice(n9,-n9)},K,!1,void 0,this);else if(q.startsWith("`")&&q.endsWith("`")){let W=q.match(/^(`+)([^`]+)\1$/);if(W&&W[2])G=W0(V0,{color:Y.colors.syntax.keyword,backgroundColor:Y.colors.background.secondary,bold:!0,children:` ${W[2]} `},K,!1,void 0,this)}else if(q.startsWith("[")&&q.includes("](")&&q.endsWith(")")){let W=q.match(/\[(.*?)\]\((.*?)\)/);if(W){let U=W[1],H=W[2];G=W0(V0,{children:[U,W0(V0,{color:Y.colors.info,children:[" (",H,")"]},void 0,!0,void 0,this)]},K,!0,void 0,this)}}else if(q.match(/^https?:\/\//))G=W0(V0,{color:Y.colors.info,children:q},K,!1,void 0,this)}catch(W){console.error("InlineRenderer 解析错误:",q,W),G=null}Z.push(G??W0(V0,{children:q},K,!1,void 0,this)),X=Q.lastIndex}if(X<$.length)Z.push(W0(V0,{children:$.slice(X)},`t-${X}`,!1,void 0,this));return W0(iW,{children:Z.filter((q)=>q!==null)},void 0,!1,void 0,this)},U0=cW.memo(lW);import{Box as o9,Text as AX}from"ink";import rW from"react";import{jsxDEV as R$}from"react/jsx-dev-runtime";var aW=({itemText:$,type:Y,marker:Z,leadingWhitespace:X=""})=>{let Q=Y==="ol"?`${Z}. `:`${Z} `,J=Q.length,q=X.length;return R$(o9,{paddingLeft:q+1,flexDirection:"row",children:[R$(o9,{width:J,children:R$(AX,{children:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),R$(o9,{flexGrow:1,children:R$(AX,{wrap:"wrap",children:R$(U0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},bX=rW.memo(aW);import{Box as nW,Text as P2}from"ink";import RX from"react";import{jsxDEV as H0}from"react/jsx-dev-runtime";var VX=({headers:$,rows:Y,terminalWidth:Z})=>{let X=Z1.getTheme();if($.length===0||Y.length===0)return null;let Q=$.map((O,F)=>{let _=y2(O),z=Math.max(...Y.map((w)=>y2(w[F]||"")));return Math.max(_,z)+2}),J=$.length+1,q=Q.reduce((O,F)=>O+F,0)+J,G=q>Z?Z/q:1,K=Q.map((O)=>Math.floor(O*G)),W=(O,F,_=!1)=>{let z=Math.max(0,F-2),w=y2(O),B=O;if(w>z)B=wX(O,z);let N=y2(B),b=Math.max(0,z-N);return H0(P2,{children:[_?H0(P2,{bold:!0,color:X.colors.primary,children:H0(U0,{text:B},void 0,!1,void 0,this)},void 0,!1,void 0,this):H0(U0,{text:B},void 0,!1,void 0,this)," ".repeat(b)]},void 0,!0,void 0,this)},U=(O)=>{let _={top:{left:"┌",middle:"┬",right:"┐",horizontal:"─"},middle:{left:"├",middle:"┼",right:"┤",horizontal:"─"},bottom:{left:"└",middle:"┴",right:"┘",horizontal:"─"}}[O],z=K.map((B)=>_.horizontal.repeat(B)),w=_.left+z.join(_.middle)+_.right;return H0(P2,{color:X.colors.text.muted,dimColor:!0,children:w},void 0,!1,void 0,this)},H=(O,F=!1)=>{let _=O.map((z,w)=>{let B=K[w]||0;return W(z||"",B,F)});return H0(P2,{children:[H0(P2,{color:X.colors.text.muted,children:"│ "},void 0,!1,void 0,this),_.map((z,w)=>H0(RX.Fragment,{children:[z,w<_.length-1&&H0(P2,{color:X.colors.text.muted,children:" │ "},void 0,!1,void 0,this)]},w,!0,void 0,this)),H0(P2,{color:X.colors.text.muted,children:" │"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};return H0(nW,{flexDirection:"column",marginY:1,children:[U("top"),H($,!0),U("middle"),Y.map((O,F)=>H0(RX.Fragment,{children:H(O)},F,!1,void 0,this)),U("bottom")]},void 0,!0,void 0,this)};import{jsxDEV as d}from"react/jsx-dev-runtime";var oW=($,Y)=>{let X=Z1.getTheme().colors;switch($){case"user":return{color:X.info,prefix:"> "};case"assistant":return{color:X.success,prefix:"• "};case"system":return{color:X.warning,prefix:"⚙ "};case"tool":{let Q=Y&&"phase"in Y?Y.phase:void 0;return{color:X.text.secondary,prefix:Q==="start"?"• ":Q==="complete"?" └ ":" "}}default:return{color:X.text.primary,prefix:" "}}},D0={codeBlock:/^```(\w+)?\s*$/,heading:/^ *(#{1,4}) +(.+)/,ulItem:/^([ \t]*)([-*+]) +(.+)/,olItem:/^([ \t]*)(\d+)\. +(.+)/,hr:/^ *([-*_] *){3,} *$/,table:/^\|(.+)\|$/,tableSeparator:/^\|[\s]*:?-+:?[\s]*(\|[\s]*:?-+:?[\s]*)+\|?$/,diffStart:/^<<<DIFF>>>$/,diffEnd:/^<<<\/DIFF>>>$/};function sW($){let Y=[],Z=$.split(/\r?\n/),X=!1,Q=[],J=null,q=!1,G=[],K=[],W=!1,U=[],H=!0;for(let O=0;O<Z.length;O++){let F=Z[O];if(W){if(F.match(D0.diffEnd)){try{let R=JSON.parse(U.join(`
1582
+ `));Y.push({type:"diff",content:"",diffData:{patch:R.patch,startLine:R.startLine,matchLine:R.matchLine}})}catch(R){Y.push({type:"text",content:U.join(`
1583
+ `)})}W=!1,U=[],H=!1;continue}U.push(F);continue}if(F.match(D0.diffStart)){W=!0,U=[],H=!1;continue}if(X){if(F.match(D0.codeBlock))Y.push({type:"code",content:Q.join(`
1584
+ `),language:J||void 0}),X=!1,Q=[],J=null,H=!1;else Q.push(F);continue}let _=F.match(D0.codeBlock);if(_){X=!0,J=_[1]||null,H=!1;continue}let z=F.match(D0.table),w=F.match(D0.tableSeparator);if(z&&!q){if(O+1<Z.length){if(Z[O+1].match(D0.tableSeparator)){q=!0,G=z[1].split("|").map((L)=>L.trim()).filter((L)=>L.length>0),K=[],H=!1;continue}}}if(q&&w)continue;if(q&&z){let R=z[1].split("|").map((L)=>L.trim()).filter((L)=>L.length>0);while(R.length<G.length)R.push("");if(R.length>G.length)R.length=G.length;K.push(R);continue}if(q&&!z){if(G.length>0&&K.length>0)Y.push({type:"table",content:"",tableData:{headers:G,rows:K}});q=!1,G=[],K=[]}let B=F.match(D0.heading);if(B){Y.push({type:"heading",content:B[2],level:B[1].length}),H=!1;continue}let N=F.match(D0.ulItem);if(N){Y.push({type:"list",content:N[3],listType:"ul",marker:N[2],indentation:N[1].length}),H=!1;continue}let b=F.match(D0.olItem);if(b){Y.push({type:"list",content:b[3],listType:"ol",marker:b[2],indentation:b[1].length}),H=!1;continue}if(F.match(D0.hr)){Y.push({type:"hr",content:""}),H=!1;continue}if(F.trim().length===0){if(!H)Y.push({type:"empty",content:""}),H=!0;continue}Y.push({type:"text",content:F}),H=!1}if(X)Y.push({type:"code",content:Q.join(`
1585
+ `),language:J||void 0});if(q&&G.length>0&&K.length>0)Y.push({type:"table",content:"",tableData:{headers:G,rows:K}});return Y}var tW=({content:$,language:Y,terminalWidth:Z})=>{return d(l9,{content:$,language:Y,showLineNumbers:!0,terminalWidth:Z},void 0,!1,void 0,this)},eW=({content:$,level:Y})=>{let Z=Z1.getTheme();switch(Y){case 1:return d(a1,{bold:!0,color:Z.colors.primary,children:d(U0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 2:return d(a1,{bold:!0,color:Z.colors.primary,children:d(U0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 3:return d(a1,{bold:!0,color:Z.colors.text.primary,children:d(U0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 4:return d(a1,{italic:!0,color:Z.colors.text.muted,children:d(U0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);default:return d(a1,{children:d(U0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)}},$U=({terminalWidth:$})=>{let Y=Z1.getTheme(),Z=Math.max(0,Math.min($-4,80));return d(a1,{dimColor:!0,color:Y.colors.text.muted,children:"─".repeat(Z)},void 0,!1,void 0,this)},YU=({content:$})=>{return d(a1,{wrap:"wrap",children:d(U0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)},ZU=w4.memo(({detail:$,terminalWidth:Y})=>{let Z=Z1.getTheme(),X=50,Q=$.split(`
1586
+ `),J=Q.length>50,q=J?Q.slice(0,50):Q,G=q.join(`
1587
+ `),K=G.includes("<<<DIFF>>>"),W=G.includes("```");if(K){let U=G.match(/<<<DIFF>>>\s*({[\s\S]*?})\s*<<<\/DIFF>>>/);if(U)try{let H=JSON.parse(U[1]);return d(g1,{flexDirection:"column",children:[d(i9,{patch:H.patch,startLine:H.startLine,matchLine:H.matchLine,terminalWidth:Y},void 0,!1,void 0,this),J&&d(g1,{marginTop:1,children:d(a1,{dimColor:!0,color:Z.colors.text.muted,children:["... 省略 ",Q.length-50," 行 ..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}catch{}}if(W){let U=G.match(/```(\w+)?\s*\n([\s\S]*?)\n```/);if(U){let H=U[1]||"text",O=U[2];return d(g1,{flexDirection:"column",children:[d(l9,{content:O,language:H,showLineNumbers:!1,terminalWidth:Y},void 0,!1,void 0,this),J&&d(g1,{marginTop:1,children:d(a1,{dimColor:!0,color:Z.colors.text.muted,children:["... 省略 ",Q.length-50," 行 ..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}}return d(g1,{flexDirection:"column",children:[q.map((U,H)=>d(a1,{color:Z.colors.text.primary,children:U},H,!1,void 0,this)),J&&d(g1,{marginTop:1,children:d(a1,{dimColor:!0,color:Z.colors.text.muted,children:["... 省略 ",Q.length-50," 行 ..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}),q6=w4.memo(({content:$,role:Y,terminalWidth:Z,metadata:X,isPending:Q=!1})=>{let J=w4.useMemo(()=>oW(Y,X),[Y,X]),{color:q,prefix:G}=J;if(Y==="tool"&&X&&"detail"in X){let W=X;if(W.detail)return d(g1,{flexDirection:"column",marginBottom:1,children:[d(g1,{flexDirection:"row",children:[d(g1,{marginRight:1,children:d(a1,{color:q,bold:!0,children:G},void 0,!1,void 0,this)},void 0,!1,void 0,this),d(a1,{color:q,children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),d(g1,{marginLeft:G.length+1,marginTop:1,children:d(ZU,{detail:W.detail,terminalWidth:Z-(G.length+1)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}let K=w4.useMemo(()=>sW($),[$]);return d(g1,{flexDirection:"column",marginBottom:1,children:K.map((W,U)=>{if(W.type==="empty")return d(g1,{height:1},U,!1,void 0,this);return d(g1,{flexDirection:"row",children:[U===0&&d(g1,{marginRight:1,children:d(a1,{color:q,bold:!0,children:G},void 0,!1,void 0,this)},void 0,!1,void 0,this),U>0&&d(g1,{width:G.length+1},void 0,!1,void 0,this),d(g1,{flexGrow:1,children:W.type==="code"?d(tW,{content:W.content,language:W.language,terminalWidth:Z-(G.length+1)},void 0,!1,void 0,this):W.type==="table"&&W.tableData?d(VX,{headers:W.tableData.headers,rows:W.tableData.rows,terminalWidth:Z-(G.length+1)},void 0,!1,void 0,this):W.type==="heading"?d(eW,{content:W.content,level:W.level||1},void 0,!1,void 0,this):W.type==="list"?d(bX,{type:W.listType||"ul",marker:W.marker||"-",itemText:W.content,leadingWhitespace:" ".repeat(W.indentation||0)},void 0,!1,void 0,this):W.type==="hr"?d($U,{terminalWidth:Z-(G.length+1)},void 0,!1,void 0,this):W.type==="diff"&&W.diffData?d(i9,{patch:W.diffData.patch,startLine:W.diffData.startLine,matchLine:W.diffData.matchLine,terminalWidth:Z-(G.length+1)},void 0,!1,void 0,this):d(YU,{content:W.content},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},U,!0,void 0,this)})},void 0,!1,void 0,this)},($,Y)=>{return $.content===Y.content&&$.role===Y.role&&$.terminalWidth===Y.terminalWidth&&$.isPending===Y.isPending&&JSON.stringify($.metadata)===JSON.stringify(Y.metadata)});import{jsxDEV as _1}from"react/jsx-dev-runtime";var qU=({label:$,isSelected:Y})=>_1(I0,{color:Y?"yellow":void 0,children:$},void 0,!1,void 0,this),DX=({details:$,onResponse:Y})=>{let Z=A$(),Q=G0()==="confirmation-prompt",J=T1(!1),q=$.type==="exitPlanMode",G=$.type==="enterPlanMode",K=$.type==="maxTurnsExceeded";XU((O,F)=>{if(F.ctrl&&O==="c"||F.meta&&O==="c"){J();return}if(F.escape){Y({approved:!1,reason:"用户取消"});return}let _=O.toLowerCase();if(q){if(_==="y"){Y({approved:!0,targetMode:"autoEdit"});return}if(_==="s"){Y({approved:!0,targetMode:"default"});return}if(_==="n"){Y({approved:!1,reason:"方案需要改进"});return}}else if(G){if(_==="y"){Y({approved:!0});return}if(_==="n"){Y({approved:!1,reason:"用户拒绝进入 Plan 模式"});return}}else if(K){if(_==="y"){Y({approved:!0});return}if(_==="n"){Y({approved:!1,reason:"用户选择停止"});return}}else{if(_==="y"){Y({approved:!0,scope:"once"});return}if(_==="s"){Y({approved:!0,scope:"session"});return}if(_==="n"){Y({approved:!1,reason:"用户拒绝"});return}}},{isActive:Q});let W=JU(()=>{if(q)return[{key:"approve-auto",label:"[Y] Yes, execute with auto-edit mode",value:{approved:!0,targetMode:"autoEdit"}},{key:"approve-default",label:"[S] Yes, execute with default mode (ask for each operation)",value:{approved:!0,targetMode:"default"}},{key:"reject",label:"[N] No, keep planning",value:{approved:!1,reason:"方案需要改进"}}];if(G)return[{key:"approve",label:"[Y] Yes, enter Plan mode",value:{approved:!0}},{key:"reject",label:"[N] No, proceed directly",value:{approved:!1,reason:"用户拒绝进入 Plan 模式"}}];if(K)return[{key:"continue",label:"[Y] Yes, continue",value:{approved:!0}},{key:"stop",label:"[N] No, stop here",value:{approved:!1,reason:"用户选择停止"}}];return[{key:"approve-once",label:"[Y] Yes (once only)",value:{approved:!0,scope:"once"}},{key:"approve-session",label:"[S] Yes, remember for this project (Shift+Tab)",value:{approved:!0,scope:"session"}},{key:"reject",label:"[N] No",value:{approved:!1,reason:"用户拒绝"}}]},[q,G,K]),H=(()=>{if(q)return{color:"cyan",title:"\uD83D\uDD35 Plan Mode - Review Implementation Plan"};if(G)return{color:"magenta",title:"\uD83D\uDFE3 Enter Plan Mode?"};if(K)return{color:"yellow",title:"⚡ Max Turns Exceeded"};return{color:"yellow",title:"\uD83D\uDD14 Confirmation Required"}})();return _1(O0,{flexDirection:"column",borderStyle:"round",borderColor:Q?H.color:"gray",padding:1,children:[_1(O0,{marginBottom:1,children:_1(I0,{bold:!0,color:H.color,children:H.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),$.title&&_1(O0,{marginBottom:1,children:_1(I0,{bold:!0,children:$.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),_1(O0,{marginBottom:1,children:_1(I0,{children:$.message},void 0,!1,void 0,this)},void 0,!1,void 0,this),($.planContent||$.details)&&_1(O0,{flexDirection:"column",marginBottom:1,borderStyle:"single",borderColor:H.color,padding:1,children:[_1(I0,{bold:!0,color:H.color,children:q?"\uD83D\uDCCB Implementation Plan:":G?"\uD83D\uDCDD Details:":"\uD83D\uDCC4 Operation Details:"},void 0,!1,void 0,this),_1(O0,{marginTop:1,children:_1(q6,{content:$.planContent||$.details||"",role:"assistant",terminalWidth:Z-4},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$.risks&&$.risks.length>0&&_1(O0,{flexDirection:"column",marginBottom:1,children:[_1(I0,{color:"red",bold:!0,children:"⚠️ 风险提示:"},void 0,!1,void 0,this),$.risks.map((O,F)=>_1(O0,{marginLeft:2,children:_1(I0,{color:"red",children:["• ",O]},void 0,!0,void 0,this)},F,!1,void 0,this))]},void 0,!0,void 0,this),$.affectedFiles&&$.affectedFiles.length>0&&_1(O0,{flexDirection:"column",marginBottom:1,children:[_1(I0,{color:"yellow",children:"\uD83D\uDCC1 影响的文件:"},void 0,!1,void 0,this),$.affectedFiles.slice(0,3).map((O,F)=>_1(O0,{marginLeft:2,children:_1(I0,{children:["• ",O]},void 0,!0,void 0,this)},F,!1,void 0,this)),$.affectedFiles.length>3&&_1(O0,{marginLeft:2,children:_1(I0,{color:"gray",children:["...还有 ",$.affectedFiles.length-3," 个文件"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_1(O0,{flexDirection:"column",children:[_1(I0,{color:"gray",children:"使用 ↑ ↓ 选择,回车确认(支持 Y/S/N 快捷键,ESC 取消)"},void 0,!1,void 0,this),_1(QU,{items:W,isFocused:Q,itemComponent:qU,onSelect:(O)=>{Y(O.value)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{useMemoizedFn as SX}from"ahooks";import{Box as wU,Text as LU}from"ink";import AU from"react";import{useMemoizedFn as OU}from"ahooks";import T2 from"chalk";import{Text as FU,useInput as zU}from"ink";import{useEffect as e9,useRef as $7}from"react";var s0={TIMEOUT_MS:100,RAPID_INPUT_THRESHOLD_MS:150,LARGE_INPUT_THRESHOLD:300,MEDIUM_SIZE_MULTI_CHUNK_THRESHOLD:200};import{execSync as V$}from"node:child_process";import{existsSync as GU,readFileSync as s9}from"node:fs";import{basename as IX,isAbsolute as KU}from"node:path";function WU(){let $=process.platform,Y={darwin:"No image found in clipboard. Use Cmd + Ctrl + Shift + 4 to copy a screenshot to clipboard.",win32:"No image found in clipboard. Use Print Screen to copy a screenshot to clipboard.",linux:"No image found in clipboard. Use appropriate screenshot tool to copy a screenshot to clipboard."};return Y[$]||Y.linux}var HI=WU();function MX($){try{let Y=Buffer.from($,"base64");if(Y.length<4)return"image/png";if(Y[0]===137&&Y[1]===80&&Y[2]===78&&Y[3]===71)return"image/png";if(Y[0]===255&&Y[1]===216&&Y[2]===255)return"image/jpeg";if(Y[0]===71&&Y[1]===73&&Y[2]===70)return"image/gif";if(Y[0]===82&&Y[1]===73&&Y[2]===70&&Y[3]===70){if(Y.length>=12&&Y[8]===87&&Y[9]===69&&Y[10]===66&&Y[11]===80)return"image/webp"}return"image/png"}catch{return"image/png"}}function kX(){let $=process.platform,Y={darwin:"/tmp/blade_cli_latest_screenshot.png",linux:"/tmp/blade_cli_latest_screenshot.png",win32:process.env.TEMP?`${process.env.TEMP}\\blade_cli_latest_screenshot.png`:"C:\\Temp\\blade_cli_latest_screenshot.png"},Z={darwin:{checkImage:"osascript -e 'the clipboard as «class PNGf»'",saveImage:(X)=>`osascript -e 'set png_data to (the clipboard as «class PNGf»)' -e 'set fp to open for access POSIX file "${X}" with write permission' -e 'write png_data to fp' -e 'close access fp'`,getPath:"osascript -e 'get POSIX path of (the clipboard as «class furl»)'",deleteFile:(X)=>`rm -f "${X}"`},linux:{checkImage:'xclip -selection clipboard -t TARGETS -o | grep -E "image/(png|jpeg|jpg|gif|webp)"',saveImage:(X)=>`xclip -selection clipboard -t image/png -o > "${X}" || wl-paste --type image/png > "${X}"`,getPath:"xclip -selection clipboard -t text/plain -o",deleteFile:(X)=>`rm -f "${X}"`},win32:{checkImage:'powershell -Command "(Get-Clipboard -Format Image) -ne $null"',saveImage:(X)=>`powershell -Command "$img = Get-Clipboard -Format Image; if ($img) { $img.Save('${X.replace(/\\/g,"\\\\")}', [System.Drawing.Imaging.ImageFormat]::Png) }"`,getPath:'powershell -Command "Get-Clipboard"',deleteFile:(X)=>`del /f "${X}"`}};return{commands:Z[$]||Z.linux,screenshotPath:Y[$]||Y.linux}}function UU(){let{commands:$}=kX();try{return V$($.getPath,{encoding:"utf-8"}).trim()}catch(Y){return console.error("Failed to get clipboard path:",Y),null}}function jX($){if($.startsWith('"')&&$.endsWith('"')||$.startsWith("'")&&$.endsWith("'"))return $.slice(1,-1);return $}function EX($){if(process.platform==="win32")return $;let Y="__DOUBLE_BACKSLASH__";return $.replace(/\\\\/g,Y).replace(/\\(.)/g,"$1").replace(new RegExp(Y,"g"),"\\")}function t9($){let Y=jX($.trim()),Z=EX(Y);return/\.(png|jpe?g|gif|webp)$/i.test(Z)}function HU($){let Y=jX($.trim()),Z=EX(Y);if(t9(Z))return Z;return null}async function vX($){let Y=HU($);if(!Y)return null;let Z;try{if(KU(Y))Z=s9(Y);else{let q=UU();if(q&&Y===IX(q))Z=s9(q);else return null}}catch(q){return console.error("Failed to read image file:",q),null}let X=Z.toString("base64"),Q=MX(X),J=IX(Y);return{path:Y,base64:X,mediaType:Q,filename:J}}async function yX(){let $=process.platform,Y={darwin:"pbpaste",linux:"xclip -selection clipboard -o || wl-paste",win32:'powershell -Command "Get-Clipboard"'},Z=Y[$]||Y.linux;try{return V$(Z,{encoding:"utf-8"})||null}catch{return null}}async function PX(){let{commands:$,screenshotPath:Y}=kX();try{if(V$($.checkImage,{stdio:"ignore"}),V$($.saveImage(Y),{stdio:"ignore"}),!GU(Y))return null;let X=s9(Y).toString("base64"),Q=MX(X);return V$($.deleteFile(Y),{stdio:"ignore"}),{base64:X,mediaType:Q}}catch(Z){try{V$($.deleteFile(Y),{stdio:"ignore"})}catch{}return null}}import{jsxDEV as BU}from"react/jsx-dev-runtime";var _U=/\r\n/g,NU=/\r/g;function S2($){if(!$.includes("\r"))return $;return $.replace(_U,`
1588
+ `).replace(NU,`
1589
+ `)}function C2($,Y,Z){let X=Math.max(0,Math.min(Z,Y.length)),Q=Y.slice(0,X),J=Y.slice(X);return{newValue:Q+$+J,newCursorPosition:X+$.length}}function TX({value:$,placeholder:Y="",focus:Z=!0,onChange:X,cursorPosition:Q,onChangeCursorPosition:J,onPaste:q,onImagePaste:G,disabledKeys:K=[]}){let W=$7({chunks:[],timeoutId:null,firstInputTime:null,lastInputTime:null,totalLength:0}),U=$7($),H=$7(Q);e9(()=>{U.current=$,H.current=Q},[$,Q]),e9(()=>{return()=>{if(W.current.timeoutId)clearTimeout(W.current.timeoutId)}},[]),e9(()=>{if(Q>$.length)J($.length)},[$,Q,J]);let O=OU(()=>{let w=W.current;if(w.timeoutId)clearTimeout(w.timeoutId);let B=setTimeout(async()=>{let N=W.current.chunks,b=W.current.totalLength;if(N.length===0)return;let V=S2(N.join(""));W.current={chunks:[],timeoutId:null,firstInputTime:null,lastInputTime:null,totalLength:0};let R=U.current,L=H.current;if(G&&t9(V))try{let v=await vX(V);if(v){let g=await G(v.base64,v.mediaType,v.filename);if(g?.prompt){let u=S2(g.prompt),{newValue:D1,newCursorPosition:J1}=C2(u,R,L);X(D1),J(J1)}return}}catch(v){console.error("Failed to process image path:",v)}let A=V.includes(`
1590
+ `),k=b>s0.MEDIUM_SIZE_MULTI_CHUNK_THRESHOLD&&N.length>3;if((b>s0.LARGE_INPUT_THRESHOLD||A||k)&&q){let v=await q(V);if(v?.prompt){let g=S2(v.prompt),{newValue:u,newCursorPosition:D1}=C2(g,R,L);X(u),J(D1);return}}let{newValue:T,newCursorPosition:E}=C2(V,R,L);X(T),J(E)},s0.TIMEOUT_MS);W.current.timeoutId=B});zU((w,B)=>{let N=S2(w);if(K.some((k)=>B[k])||B.ctrl&&w==="c"||B.shift&&B.tab||N==="?"&&$==="")return;let V=Date.now(),R=W.current,L=Q,A=$;if(B.leftArrow)L--;else if(B.rightArrow)L++;else if(B.backspace||B.delete){if(w===""){if(Q>0)A=$.slice(0,Q-1)+$.slice(Q,$.length),L--}else if(Q<$.length)A=$.slice(0,Q)+$.slice(Q+1,$.length)}else if(B.ctrl&&N==="a")L=0;else if(B.ctrl&&N==="e")L=$.length;else if(B.ctrl&&N==="k")A=$.slice(0,Q);else if(B.ctrl&&N==="u")A=$.slice(Q),L=0;else if(B.ctrl&&N==="w"){let I=$.slice(0,Q).match(/\s*\S+\s*$/);if(I){let T=I[0].length;A=$.slice(0,Q-T)+$.slice(Q),L-=T}}else if(B.ctrl&&N==="v"){let k=process.platform==="darwin";(async()=>{if(G){let T=await PX();if(T){let E=await G(T.base64,T.mediaType,"clipboard.png");if(E?.prompt){let v=S2(E.prompt),{newValue:g,newCursorPosition:u}=C2(v,U.current,H.current);X(g),J(u)}return}}if(k)return;let I=await yX();if(I){let T=S2(I),E=T.includes(`
1591
+ `),v=T.length>s0.LARGE_INPUT_THRESHOLD;if((E||v)&&q){let D1=await q(T);if(D1?.prompt){let J1=S2(D1.prompt),{newValue:x,newCursorPosition:j0}=C2(J1,U.current,H.current);X(x),J(j0);return}}let{newValue:g,newCursorPosition:u}=C2(T,U.current,H.current);X(g),J(u)}})().catch(()=>{});return}else if(B.pageUp)L=0;else if(B.pageDown)L=$.length;else if(N===`
1592
+ `&&(B.shift||B.meta)){let{newValue:k,newCursorPosition:I}=C2(N,$,Q);X(k),J(I);return}else if(!B.ctrl&&!B.meta){if(!R.firstInputTime)R.firstInputTime=V;R.lastInputTime=V;let k=V-(R.firstInputTime||V),I=N.length>s0.LARGE_INPUT_THRESHOLD,T=N.includes(`
1593
+ `)&&N.length>1,E=k<s0.RAPID_INPUT_THRESHOLD_MS&&R.chunks.length>0,v=k<s0.RAPID_INPUT_THRESHOLD_MS&&N.length>10,g=R.timeoutId!==null;if(q&&(I||T||E||v||g)){R.chunks.push(N),R.totalLength+=N.length,O();return}if(N.length===1&&!R.timeoutId)R.chunks=[],R.firstInputTime=null,R.lastInputTime=null,R.totalLength=0;A=$.slice(0,Q)+N+$.slice(Q,$.length),L+=N.length}if(L<0)L=0;if(L>A.length)L=A.length;if(A!==$)X(A);if(L!==Q)J(L)},{isActive:Z});let F=Z,_=$,z=Y?T2.grey(Y):void 0;if(F)if(z=Y.length>0?T2.inverse(Y[0])+T2.grey(Y.slice(1)):T2.inverse(" "),$.length===0)_=T2.inverse(" ");else{_="";for(let w=0;w<$.length;w++)if(w===Q&&Q<$.length)_+=T2.inverse($[w]);else _+=$[w];if(Q>=$.length)_+=T2.inverse(" ")}return BU(FU,{children:Y?$.length>0?_:z:_},void 0,!1,void 0,this)}import{jsxDEV as Y7}from"react/jsx-dev-runtime";var CX=AU.memo(({input:$,cursorPosition:Y,onChange:Z,onChangeCursorPosition:X,onAddPasteMapping:Q,onAddImagePasteMapping:J})=>{let G=G0()==="main-input",K=SX((U)=>{let H=U.split(`
1594
+ `).length,O=U.length,F=500,_=10;if(O>500||H>10){let z=Q(U),w=U.slice(0,30).replace(/\n/g," "),B=`${O} chars, ${H} lines: ${w}...`;return{prompt:`${H4(z)}${B}${T9()}`}}return{}}),W=SX(async(U,H,O)=>{try{let F=J(U,H);return{prompt:`${H4(F)}[Image #${F}]${T9()}`}}catch(F){return console.error("[Image Paste] Failed to process image:",F),{prompt:`[Image paste failed: ${F instanceof Error?F.message:"Unknown error"}] `}}});return Y7(wU,{flexDirection:"row",width:"100%",paddingX:2,paddingY:0,flexShrink:0,flexGrow:0,overflow:"hidden",borderStyle:"round",borderColor:"gray",children:[Y7(LU,{color:"blue",bold:!0,children:"> "},void 0,!1,void 0,this),Y7(TX,{value:$,cursorPosition:Y,onChange:Z,onChangeCursorPosition:X,onPaste:K,onImagePaste:W,placeholder:" 输入命令...",focus:G,disabledKeys:["upArrow","downArrow","tab","return","escape"]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{Box as L4,Text as M0}from"ink";import IU,{useEffect as MU,useState as kU}from"react";import{useEffect as DU,useState as pX}from"react";import{useEffect as bU,useState as RU}from"react";var VU=15000,fX=["炼化代码灵气...","参悟 AST 道法...","推演算法天机...","重铸代码根基...","破解逻辑封印...","凝练类型真元...","铸就函数金丹...","渡劫编译雷劫...","打通模块任督二脉...","修炼 Tree-shaking 神功...","压缩代码乾坤...","布下 Source Map 阵法...","推演 Token 灵数...","炼制 Prompt 仙丹...","调息温度参数...","参透困惑度玄机...","驱动 LLM 灵力...","施展向量搜索术...","构筑 RAG 法阵...","凝聚 Embedding 道果...","勾连向量宝库...","破译函数咒语...","验证 Schema 真意...","封印工具参数...","注入系统道韵...","串联历史因果...","炼化抽象语法树...","破境重构神功...","感悟类型天道...","筑基模块根基...","施展词法轻功...","破解语法阵法...","参悟语义心法...","凝练中间内力...","修炼优化神功...","调息寄存器真气...","运转指令招式...","消除死码杂念...","折叠常量真元...","内联函数身法...","逃逸分析密探...","垃圾回收扫地僧...","标记清除掌法...","分代回收心诀...","增量收功法门...","JIT 即时顿悟...","解读字节码暗器...","V8 引擎神功...","召唤 WASM 傀儡...","开辟虚拟洞府...","丹田分配内存...","掌控栈帧乾坤...","捕获异常剑气...","尾调优化身法...","动态链接飞剑...","建立 TCP 金桥...","三次握手结契...","传送 HTTP 飞书...","破译响应符文...","TLS 秘境握手...","验证 SSL 信物...","WebSocket 通灵...","流式传功大法...","gRPC 御剑飞行...","Protobuf 封印术...","GraphQL 问道...","DNS 测算域名...","负载均衡五行阵...","CDN 边缘瞬移...","HTTP/2 分身术...","QUIC 闪现神通...","gzip 缩地成寸...","Brotli 玄冰压缩...","断点续传接续术...","分片上传合璧功...","参研 SQL 真经...","推演查询路径...","索引扫描神识...","全表扫描暴力突破...","执行 JOIN 双修大法...","聚合数据炼丹...","事务提交天地誓...","ACID 四象护法...","乐观锁道心无畏...","悲观锁剑阵守护...","分布式锁万里封禁...","Redis 炼药鼎缓存...","LRU 新陈代谢...","WAL 预写因果簿...","B+ 树平衡阴阳...","LSM 树合璧压缩...","向量宝库搜寻...","余弦相似度测算...","KNN 近邻追踪...","倒排索引翻阅秘籍...","快速排序剑法...","归并排序双刀...","堆排优化内功...","二分查找闪现...","深度优先潜行...","广度优先横扫...","Dijkstra 寻路神算...","A* 天机推演...","动态规划填棋盘...","回溯剑法剪枝...","贪心策略奇谋...","分治递归化身术...","哈希表扩容开天...","红黑树旋转太极...","AVL 树平衡阴阳...","跳表纵身轻功...","Trie 树千头万绪...","布隆过滤天罗地网...","一致性哈希环定乾坤...","最小生成树扎根...","Docker 镜像炼制...","Kubernetes 调兵遣将...","容器结界布阵...","卷挂载空间挪移...","Helm 符箓展开...","CI/CD 流水线作业...","GitHub 门派行动...","代码品鉴术...","漏洞探查密探...","依赖追溯寻根...","蓝绿部署换防...","金丝雀试探...","回滚时光倒流...","健康探查望闻问切...","日志归档藏经阁...","监控预警千里眼...","告警通知飞鸽传书...","性能调优筋骨重塑...","扩容缩容易筋经...","灰度发布声东击西...","React 虚影对决...","组件树调和大法...","Hooks 勾魂术...","useEffect 副作用因果...","Redux 中枢天宫...","Zustand 灵台藏识...","CSS-in-JS 画地为牢...","Tailwind 疾风步...","Webpack 热更换血重生...","Vite 按需凝形...","ESBuild 极速神行...","SWC 闪电炼形...","SSR 天地初开...","Hydration 魂归肉身...","Ink 终端墨宝...","虚拟 DOM 镜花水月...","事件冒泡顺流而上...","状态提升登峰造极...","懒加载厚积薄发...","代码分割庖丁解牛...","SHA-256 炼心咒...","AES-256 玄冰封印...","RSA 阴阳双钥...","JWT 信物令牌...","OAuth 门派授权...","CSRF 防御结界...","XSS 祛邪过滤...","SQL 注入克星...","PBKDF2 淬炼秘钥...","零知识誓言验证...","HTTPS 金钟罩...","签名验证印玺鉴定...","盐值加密炼丹配方...","双因素认证双重认证...","权限控制天条律令...","拜见图灵祖师爷...","冯·诺依曼传道...","Linus 大侠坐镇...","参悟 Rust 生命轮回...","逃离回调地狱轮回...","await 静待天时...","捕获野生 Bug 妖兽...","喂养橡皮鸭灵兽 \uD83E\uDD86...","炼丹调参秘术...","0xDEADBEEF 死亡凝视...","递归无限轮回...","闭包封印记忆...","Promise 未来契约...","async 异步神功...","Generator 分身术...","Proxy 替身傀儡...","Reflect 返照镜...","Symbol 独一无二印记...","WeakMap 过眼云烟...","Iterator 周而复始...","GitHub 武林大会...","Star 点赞声望...","Fork 拜师学艺...","Pull Request 挑战切磋...","Code Review 武功点评...","Issue 悬赏令...","Merge 收徒入门...","Commit 闭关修炼记录...","Branch 分支独辟蹊径...","Tag 里程碑界碑...","Release 出关发布...","License 门规戒律...","README 入门心法...","Documentation 武学秘籍...","Open Source 广纳贤才..."],hX=["Esc - 立即停止当前任务","Shift+Tab - 切换权限模式 (default/auto_edit/plan)","Tab - 智能补全斜杠命令","↑↓ - 浏览输入历史记录","双击 Esc - 快速清空输入框","Ctrl+C - 强制终止程序","Ctrl+L - 清屏(保留历史)","Ctrl+R - 反向搜索历史","Ctrl+U - 清空当前行","/help - 查看完整帮助文档","/init - 生成 BLADE.md 项目配置","/resume - 恢复历史会话","/compact - 手动压缩上下文(节省 token)","/theme - 打开主题选择器","/config - 打开配置面板","/model - 管理与切换模型配置","/permissions - 管理工具权限规则","/mcp - 查看 MCP 服务器状态","/agents - 管理 Subagent 配置","/version - 显示版本信息","/clear - 清除屏幕内容","/status - 显示当前项目配置状态","/context - 可视化当前上下文使用情况","/cost - 显示会话成本统计","/exit - 退出 REPL","@ 文件路径 - 附加文件到上下文","@dir/ - 附加整个目录","@file.ts:10-20 - 附加指定行范围","Plan 模式 - 先规划后编码(/plan)","Auto Edit 模式 - 自动批准工具调用","MCP 协议 - 扩展外部工具集成","Subagents - 并行执行子任务","Hooks 系统 - 自定义工具执行流程","Context 压缩 - 自动总结历史对话","Loop 检测 - 防止无限循环","提示:使用 /init 让 AI 理解你的项目结构","提示:Plan 模式适合复杂多步骤任务","提示:Auto Edit 可加速重复性操作","提示:@ 引用可提供更精准的上下文","提示:定期 /compact 节省 token 成本","提示:使用 /permissions 控制工具权限","提示:Shift+Tab 快速切换模式","提示:Esc 可随时中断长时间任务","提示:/resume 继续未完成的对话","提示:/export 保存重要对话记录"];function xX($,Y){let[Z,X]=RU("");return bU(()=>{if(Y){X("等待用户确认...");return}if(!$){X("");return}let Q=()=>{if(Math.random()<0.16666666666666666){let K=Math.floor(Math.random()*hX.length);return hX[K]}let G=Math.floor(Math.random()*fX.length);return fX[G]};X(Q());let J=setInterval(()=>{X(Q())},VU);return()=>{clearInterval(J)}},[$,Y]),Z}function gX($,Y=!1){let[Z,X]=pX(0),[Q,J]=pX(null),q=xX($,Y);return DU(()=>{if(!$){X(0),J(null);return}if(Q===null)J(Date.now());let G=setInterval(()=>{if(Q!==null){let K=Math.floor((Date.now()-Q)/1000);X(K)}},1000);return()=>{clearInterval(G)}},[$,Q]),{currentPhrase:q,elapsedTime:Z}}import{jsxDEV as m1,Fragment as EU}from"react/jsx-dev-runtime";var Z7=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],jU=80;function mX($){if($<60)return`${$}s`;let Y=Math.floor($/60),Z=$%60;return`${Y}m ${Z}s`}var dX=IU.memo(({message:$})=>{let Y=f0(),Z=e6(),X=Y||!Z,[Q,J]=kU(0),q=Z1.getTheme(),K=A$()>=jU,{currentPhrase:W,elapsedTime:U}=gX(X,!1);if(MU(()=>{if(!X){J(0);return}let O=setInterval(()=>{J((F)=>(F+1)%Z7.length)},80);return()=>clearInterval(O)},[X]),!X)return null;let H=W||$||"正在思考中...";if(K)return m1(L4,{paddingX:2,paddingBottom:1,flexDirection:"row",gap:1,children:[m1(M0,{color:q.colors.warning,bold:!0,children:Z7[Q]},void 0,!1,void 0,this),m1(M0,{color:q.colors.text.primary,children:H},void 0,!1,void 0,this),U>0&&m1(EU,{children:[m1(M0,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),m1(M0,{color:q.colors.info,children:["已用时: ",mX(U)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),m1(M0,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),m1(M0,{color:q.colors.secondary,children:"Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return m1(L4,{paddingX:2,paddingBottom:1,flexDirection:"column",children:[m1(L4,{flexDirection:"row",gap:1,children:[m1(M0,{color:q.colors.warning,bold:!0,children:Z7[Q]},void 0,!1,void 0,this),m1(M0,{color:q.colors.text.primary,children:H},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U>0&&m1(L4,{marginLeft:2,flexDirection:"row",gap:1,children:[m1(M0,{color:q.colors.info,children:["已用时: ",mX(U)]},void 0,!0,void 0,this),m1(M0,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),m1(M0,{color:q.colors.secondary,children:"Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)});import{Box as I$,Static as gU}from"ink";import nX,{useEffect as mU,useMemo as W6}from"react";import{Box as vU,Text as uX}from"ink";import yU from"react";import{jsxDEV as X7}from"react/jsx-dev-runtime";var Q7=yU.memo(({collapsedCount:$})=>{if($<=0)return null;let Z=Z1.getTheme().colors.text.muted;return X7(vU,{flexDirection:"row",marginBottom:1,children:[X7(uX,{color:Z,children:["▶ ",$," 条历史消息"]},void 0,!0,void 0,this),X7(uX,{color:Z,children:" [Ctrl+O 展开]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});Q7.displayName="CollapsedHistorySummary";y$();import{Box as G6,Text as K6}from"ink";import PU from"ink-big-text";import TU from"ink-gradient";import SU from"react";import{jsxDEV as F0}from"react/jsx-dev-runtime";var cX=SU.memo(()=>{return F0(G6,{flexDirection:"column",paddingX:2,paddingTop:1,paddingBottom:1,children:[F0(G6,{flexDirection:"column",children:F0(TU,{name:"pastel",children:F0(PU,{text:"BLADE",font:"block"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),F0(G6,{marginBottom:1,children:F0(K6,{color:"white",dimColor:!0,children:V7()},void 0,!1,void 0,this)},void 0,!1,void 0,this),F0(G6,{flexDirection:"column",marginBottom:1,children:[F0(G6,{marginBottom:1,children:F0(K6,{color:"white",bold:!0,children:"使用指南:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),F0(K6,{color:"white",children:"1. 输入问题、编辑文件或运行命令"},void 0,!1,void 0,this),F0(K6,{color:"white",children:"2. 使用 /init 创建项目配置文件"},void 0,!1,void 0,this),F0(K6,{color:"white",children:"3. 输入 /help 查看所有 slash 命令"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)});import{Box as J7,Text as D$}from"ink";import CU,{useMemo as lX}from"react";import{jsxDEV as t0}from"react/jsx-dev-runtime";function fU($,Y=60){if(!$)return"";let Z=$.split(`
1595
+ `)[0]||"";if(Z.length<=Y)return Z;return`${Z.slice(0,Y)}...`}function hU($){if(!$)return 0;return $.split(`
1596
+ `).length}var q7=CU.memo(({content:$,isStreaming:Y=!1,isExpanded:Z})=>{let X=Z1.getTheme(),Q=lX(()=>hU($),[$]),J=lX(()=>fU($),[$]),q=X.colors.info,G=X.colors.muted;return t0(J7,{flexDirection:"column",marginBottom:1,children:[t0(J7,{flexDirection:"row",children:[t0(D$,{color:q,children:Z?"▼":"▶"},void 0,!1,void 0,this),t0(D$,{children:" "},void 0,!1,void 0,this),t0(D$,{color:G,children:["Thinking",Y?"...":` (${Q} lines)`]},void 0,!0,void 0,this),!Z&&!Y&&J&&t0(D$,{color:G,children:[" - ",J]},void 0,!0,void 0,this),t0(D$,{color:G,dimColor:!0,children:[" ","[Ctrl+T]"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Z&&$&&t0(J7,{marginLeft:2,marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,paddingY:0,children:t0(D$,{color:G,children:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});q7.displayName="ThinkingBlock";import{Box as A4,Text as G7}from"ink";import{useState as iX}from"react";function xU(){let[$,Y]=iX(Z1.getTheme()),[Z,X]=iX(Z1.getCurrentThemeName()),Q=(K)=>{try{Z1.setTheme(K),Y(Z1.getTheme()),X(K)}catch(W){console.error("Failed to change theme:",W)}},J=Z1.getAvailableThemes();return{theme:$,themeName:Z,changeTheme:Q,availableThemes:J,hasTheme:(K)=>Z1.hasTheme(K),getThemeByName:(K)=>Z1.getThemeByName(K),colors:$.colors,spacing:$.spacing,typography:$.typography}}function rX(){let{colors:$}=xU();return $}import{jsxDEV as z2}from"react/jsx-dev-runtime";var aX=({todos:$,visible:Y=!0,compact:Z=!1})=>{let X=rX();if(!Y||$.length===0)return null;let Q={total:$.length,completed:$.filter((J)=>J.status==="completed").length,inProgress:$.filter((J)=>J.status==="in_progress").length};return z2(A4,{flexDirection:"column",borderStyle:"single",borderColor:X.border.light,paddingX:1,paddingY:Z?0:1,marginBottom:1,children:[z2(A4,{marginBottom:Z?0:1,children:[z2(G7,{dimColor:!0,children:"Tasks "},void 0,!1,void 0,this),z2(G7,{color:X.text.muted,children:[Q.completed,"/",Q.total]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),z2(A4,{flexDirection:"column",children:$.map((J,q)=>z2(pU,{todo:J,compact:Z},J.id||q,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},pU=({todo:$,compact:Y})=>{let Z,X=!1,Q;switch($.status){case"completed":Z="✓",X=!0,Q=$.content;break;case"in_progress":Z="▶",X=!1,Q=$.activeForm;break;case"pending":default:Z="○",X=!0,Q=$.content;break}return z2(A4,{paddingY:Y?0:0,children:z2(G7,{dimColor:X,children:[Z," ",Q]},void 0,!0,void 0,this)},void 0,!1,void 0,this)};import{jsxDEV as Y0}from"react/jsx-dev-runtime";var oX=nX.memo(()=>{let $=s6(),Y=f0(),Z=dY(),X=iY(),Q=sY(),J=eY(),q=$Z(),G=hY(),K=ZZ(),W=YZ(),U=A$(),H=nX.useRef(0);mU(()=>{H.current=0},[G]);let{completedMessages:O,streamingMessage:F}=W6(()=>{let b=Math.max(H.current,Y&&$.length>0?$.length-1:$.length);H.current=b;let V=$.slice(0,b),R=b<$.length?$[b]:null;return{completedMessages:V,streamingMessage:R}},[$,Y]),_=W6(()=>{return Z.some((b)=>b.status==="pending"||b.status==="in_progress")},[Z]),z=W6(()=>{if(W)return 0;return Math.max(0,$.length-K)},[$.length,K,W]),w=(b,V=!1)=>Y0(I$,{flexDirection:"column",children:Y0(q6,{content:b.content,role:b.role,terminalWidth:U,metadata:b.metadata,isPending:V},void 0,!1,void 0,this)},b.id,!1,void 0,this),B=W6(()=>{return Math.min(z,O.length)},[z,O.length]),N=W6(()=>{let b=[];if(b.push(Y0(cX,{},"header",!1,void 0,this)),B>0)b.push(Y0(Q7,{collapsedCount:B},"collapsed-summary",!1,void 0,this));return O.forEach((V,R)=>{if(R>=z)b.push(w(V))}),b},[O,U,z,B]);return Y0(I$,{flexDirection:"column",flexGrow:1,paddingX:2,children:Y0(I$,{flexDirection:"column",flexGrow:1,children:[Y0(gU,{items:N,children:(b)=>b},`${G}-${W}`,!1,void 0,this),J&&Y0(I$,{marginBottom:1,children:Y0(q7,{content:J,isStreaming:Y,isExpanded:q},void 0,!1,void 0,this)},void 0,!1,void 0,this),F&&w(F,!0),X&&_&&Y0(I$,{marginTop:1,children:Y0(aX,{todos:Z,visible:!0,compact:!1},void 0,!1,void 0,this)},void 0,!1,void 0,this),Q.map((b,V)=>Y0(I$,{flexDirection:"column",children:Y0(q6,{content:b.displayText,role:"user",terminalWidth:U},void 0,!1,void 0,this)},`pending-${V}`,!1,void 0,this))]},void 0,!0,void 0,this)},void 0,!1,void 0,this)});z1();import{Box as t,Text as p,useFocus as sX,useFocusManager as dU,useInput as V4}from"ink";import uU from"ink-select-input";import cU from"ink-text-input";import{useEffect as lU,useState as U6}from"react";import{jsxDEV as j,Fragment as R4}from"react/jsx-dev-runtime";var iU=({isSelected:$})=>j(t,{marginRight:1,children:j(p,{color:$?"yellow":"gray",children:$?"▶":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),rU=({isSelected:$,label:Y})=>j(p,{bold:$,color:$?"yellow":void 0,children:Y},void 0,!1,void 0,this);function aU($){switch($){case"openai-compatible":return"⚡ OpenAI Compatible";case"gpt-openai-platform":return"\uD83D\uDD37 GPT OpenAI Platform";case"anthropic":return"\uD83E\uDD16 Anthropic";default:return $}}var nU=({onSelect:$,onCancel:Y,initialProvider:Z})=>{let{isFocused:X}=sX({id:"provider-step"});V4((q,G)=>{if(G.escape)Y()},{isActive:X});let Q=[{label:"⚡ OpenAI Compatible - 兼容 OpenAI API 的服务 (千问/豆包/DeepSeek等)",value:"openai-compatible"},{label:"\uD83D\uDD37 GPT OpenAI Platform - 字节跳动 GPT 平台 (内部)",value:"gpt-openai-platform"},{label:"\uD83E\uDD16 Anthropic Claude API - Claude 官方 API",value:"anthropic"}],J=Z?Math.max(0,Q.findIndex((q)=>q.value===Z)):0;return j(t,{flexDirection:"column",marginBottom:1,children:[j(t,{marginBottom:1,children:j(p,{bold:!0,color:"blue",children:"\uD83D\uDCE1 Step 2: 选择 API 提供商"},void 0,!1,void 0,this)},void 0,!1,void 0,this),j(t,{marginBottom:1,children:j(p,{children:"根据您使用的 LLM 服务选择对应的 API 类型"},void 0,!1,void 0,this)},void 0,!1,void 0,this),j(t,{marginBottom:1,children:j(uU,{items:Q,onSelect:(q)=>$(q.value),indicatorComponent:iU,itemComponent:rU,initialIndex:J},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},b4=({stepNumber:$,icon:Y,title:Z,description:X,hint:Q,examples:J,value:q,placeholder:G,mask:K,previousValue:W,onChange:U,onSubmit:H,onCancel:O})=>{return V4((F,_)=>{if(_.escape)O()},{isActive:!0}),j(t,{flexDirection:"column",marginBottom:1,children:[j(t,{marginBottom:1,children:j(p,{bold:!0,color:"blue",children:[Y," Step ",$,": ",Z]},void 0,!0,void 0,this)},void 0,!1,void 0,this),j(t,{marginBottom:1,children:j(p,{children:X},void 0,!1,void 0,this)},void 0,!1,void 0,this),W&&j(t,{marginBottom:1,children:j(p,{color:"green",children:["✓ ",W]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Q&&j(t,{marginBottom:1,children:j(p,{dimColor:!0,children:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),J&&J.length>0&&j(R4,{children:[j(t,{marginBottom:1,children:j(p,{dimColor:!0,children:"常见示例:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),j(t,{marginBottom:1,paddingLeft:2,children:j(p,{dimColor:!0,children:J.join(`
1597
+ `)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j(t,{children:[j(p,{bold:!0,color:"cyan",children:["▶"," "]},void 0,!0,void 0,this),j(cU,{value:q,onChange:U,onSubmit:H,placeholder:G,mask:K},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},oU=({mode:$,config:Y,isSaving:Z,onConfirm:X,onBack:Q,onCancel:J})=>{let{isFocused:q}=sX({id:"confirm-step"});return V4((G,K)=>{if(Z)return;if(G==="y"||G==="Y")X();else if(G==="n"||G==="N")Q();else if(K.escape)J()},{isActive:q&&!Z}),j(t,{flexDirection:"column",marginBottom:1,children:[j(t,{marginBottom:1,children:j(p,{bold:!0,color:$==="edit"?"yellow":"blue",children:$==="edit"?"\uD83D\uDCBE 确认修改":"✅ Step 6: 确认配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),j(t,{marginBottom:1,children:j(p,{children:$==="edit"?"请确认修改内容,保存后将立即生效。":"请确认以下配置信息:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),j(t,{flexDirection:"column",marginBottom:1,paddingLeft:2,children:[j(t,{marginBottom:1,children:[j(p,{dimColor:!0,children:"名称: "},void 0,!1,void 0,this),j(p,{bold:!0,color:"cyan",children:Y.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j(t,{marginBottom:1,children:[j(p,{dimColor:!0,children:"Provider: "},void 0,!1,void 0,this),j(p,{bold:!0,color:"cyan",children:aU(Y.provider)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j(t,{marginBottom:1,children:[j(p,{dimColor:!0,children:"Base URL: "},void 0,!1,void 0,this),j(p,{bold:!0,color:"blue",children:Y.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j(t,{marginBottom:1,children:[j(p,{dimColor:!0,children:"API Key: "},void 0,!1,void 0,this),j(p,{bold:!0,color:"yellow",children:[Y.apiKey?.slice(0,8),"*".repeat(Math.min(32,(Y.apiKey?.length||0)-8))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j(t,{children:[j(p,{dimColor:!0,children:"Model: "},void 0,!1,void 0,this),j(p,{bold:!0,color:"cyan",children:Y.model},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),!Z&&j(t,{marginTop:1,children:j(p,{children:[$==="edit"?"保存修改? ":"确认保存配置? ","[",j(p,{bold:!0,color:"green",children:"Y"},void 0,!1,void 0,this),"/",j(p,{bold:!0,color:"red",children:"n"},void 0,!1,void 0,this),"]"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Z&&j(t,{children:j(p,{color:"yellow",children:"⏳ 正在保存配置到 ~/.blade/config.json..."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},K7=({mode:$,initialConfig:Y,modelId:Z,onComplete:X,onCancel:Q})=>{let J=$==="edit",[q,G]=U6("name"),[K,W]=U6(()=>J&&Y?{...Y}:{}),[U,H]=U6(J&&Y?Y.name:""),[O,F]=U6(!1),[_,z]=U6(null),w=T1(!1);V4((v,g)=>{if(g.ctrl&&v==="c"||g.meta&&v==="c")if($==="setup")w();else Q()},{isActive:!0});let{focus:B}=dU();lU(()=>{if(q==="provider")B("provider-step");else if(q==="confirm")B("confirm-step")},[q,B]);let N=()=>{if(!U.trim()){z("配置名称不能为空");return}W({...K,name:U}),H(""),z(null),G("provider")},b=(v)=>{W({...K,provider:v});let g=J?K.baseUrl??Y?.baseUrl??"":"";H(g),G("baseUrl")},V=()=>{if(!U.trim()){z("Base URL 不能为空");return}try{new URL(U)}catch{z("请输入有效的 URL (例如: https://api.openai.com/v1)");return}W({...K,baseUrl:U});let v=J?K.apiKey??Y?.apiKey??"":"";H(v),z(null),G("apiKey")},R=()=>{if(!U.trim()){z("API Key 不能为空");return}W({...K,apiKey:U});let v=J?K.model??Y?.model??"":"";H(v),z(null),G("model")},L=()=>{if(!U.trim()){z("Model 不能为空");return}W({...K,model:U}),H(""),z(null),G("confirm")},A=async()=>{F(!0),z(null);try{let v={name:K.name,provider:K.provider,baseUrl:K.baseUrl,apiKey:K.apiKey,model:K.model};if($==="setup")X(v);else if($==="add"){let g=await H1().addModel(v);await H1().setCurrentModel(g.id),X(v)}else{if(!Z)throw Error("未提供模型 ID,无法编辑");await H1().updateModel(Z,v),X(v)}}catch(v){z(v instanceof Error?v.message:"配置失败"),F(!1)}},k=()=>{switch(z(null),H(""),q){case"provider":H(K.name||""),G("name");break;case"baseUrl":G("provider");break;case"apiKey":H(K.baseUrl||""),G("baseUrl");break;case"model":G("apiKey");break;case"confirm":H(K.model||""),G("model");break}},I=q==="name"?1:q==="provider"?2:q==="baseUrl"?3:q==="apiKey"?4:q==="model"?5:6,T=Math.floor((I-1)/5*40);return j(t,{...$==="setup"?{flexDirection:"column",padding:1}:$==="add"?{flexDirection:"column",borderStyle:"round",borderColor:"blue",padding:1}:{flexDirection:"column",borderStyle:"round",borderColor:"yellow",padding:1},children:[$==="setup"?j(R4,{children:[j(t,{marginBottom:1,children:j(p,{bold:!0,color:"blue",children:"\uD83D\uDE80 欢迎使用 Blade Code"},void 0,!1,void 0,this)},void 0,!1,void 0,this),j(t,{marginBottom:1,children:j(p,{children:"AI 驱动的代码助手 - 让我们开始配置您的助手"},void 0,!1,void 0,this)},void 0,!1,void 0,this),j(t,{marginBottom:1,children:[j(p,{bold:!0,color:"blue",children:"█".repeat(T)},void 0,!1,void 0,this),j(p,{dimColor:!0,children:"░".repeat(40-T)},void 0,!1,void 0,this),j(p,{children:" "},void 0,!1,void 0,this),j(p,{bold:!0,color:"cyan",children:[I,"/6"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j(t,{marginBottom:1,children:j(p,{dimColor:!0,children:"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this):$==="add"?j(R4,{children:[j(t,{justifyContent:"center",marginBottom:1,children:j(p,{bold:!0,color:"blue",children:"添加新模型配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),j(t,{marginBottom:1,children:j(p,{children:["步骤: ",I,"/6"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this):j(R4,{children:[j(t,{justifyContent:"center",marginBottom:1,children:j(p,{bold:!0,color:"yellow",children:"编辑模型配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),j(t,{marginBottom:1,children:j(p,{children:["步骤: ",I,"/6"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q==="name"&&j(b4,{stepNumber:1,icon:"\uD83D\uDCDD",title:"配置名称",description:"给这个模型配置起一个易于识别的名称",value:U,placeholder:"例如: 千问工作账号",onChange:H,onSubmit:N,onCancel:Q},void 0,!1,void 0,this),q==="provider"&&j(nU,{onSelect:b,onCancel:Q,initialProvider:K.provider},void 0,!1,void 0,this),q==="baseUrl"&&j(b4,{stepNumber:3,icon:"\uD83C\uDF10",title:"配置 Base URL",description:"输入您的 API 端点地址(完整的 URL 包含协议)",examples:["• OpenAI: https://api.openai.com/v1","• 千问: https://dashscope.aliyuncs.com/compatible-mode/v1","• 豆包: https://ark.cn-beijing.volces.com/api/v3","• DeepSeek: https://api.deepseek.com/v1"],value:U,placeholder:"https://api.example.com/v1",onChange:H,onSubmit:V,onCancel:Q},void 0,!1,void 0,this),q==="apiKey"&&j(b4,{stepNumber:4,icon:"\uD83D\uDD11",title:"输入 API Key",description:"您的 API 密钥将被安全存储在 ~/.blade/config.json (权限 600)",hint:"\uD83D\uDCA1 提示: 输入时字符会被隐藏,支持粘贴 (Ctrl+V / Cmd+V)",previousValue:K.baseUrl?`✓ 当前 Base URL: ${K.baseUrl}`:void 0,value:U,placeholder:"sk-...",mask:"*",onChange:H,onSubmit:R,onCancel:Q},void 0,!1,void 0,this),q==="model"&&j(b4,{stepNumber:5,icon:"\uD83E\uDD16",title:"选择模型",description:"输入您想使用的模型名称(请参考您的 API 提供商文档)",examples:["• OpenAI: gpt-5, gpt-5-mini, gpt-5-nano","• Claude: claude-sonnet-4.5, claude-opus-4.1","• 千问: qwen3-max, qwen3-235b, qwen3-32b","• DeepSeek: deepseek-v3.1, deepseek-r1-0528","• 豆包: doubao-seed-1.6, doubao-seed-1.6-flash"],value:U,placeholder:"例如: gpt-5",onChange:H,onSubmit:L,onCancel:Q},void 0,!1,void 0,this),q==="confirm"&&j(oU,{mode:$,config:K,isSaving:O,onConfirm:A,onBack:k,onCancel:Q},void 0,!1,void 0,this),_&&j(t,{marginTop:1,borderStyle:"round",borderColor:"red",paddingX:1,children:j(p,{color:"red",children:["❌ ",_]},void 0,!0,void 0,this)},void 0,!1,void 0,this),j(t,{marginTop:1,children:j(p,{dimColor:!0,children:"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"},void 0,!1,void 0,this)},void 0,!1,void 0,this),!O&&q==="provider"&&j(t,{marginTop:1,children:j(p,{dimColor:!0,children:["\uD83D\uDCA1 使用 ",j(p,{bold:!0,children:"↑/↓"},void 0,!1,void 0,this)," 键选择,",j(p,{bold:!0,children:"Enter"},void 0,!1,void 0,this)," 确认,",j(p,{bold:!0,children:"Esc"},void 0,!1,void 0,this)," 取消"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),!O&&q!=="confirm"&&q!=="provider"&&j(t,{marginTop:1,children:j(p,{dimColor:!0,children:["\uD83D\uDCA1 输入完成后按 ",j(p,{bold:!0,children:"Enter"},void 0,!1,void 0,this),",",j(p,{bold:!0,children:"Ctrl+C"},void 0,!1,void 0,this)," 退出"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),!O&&q==="confirm"&&j(t,{marginTop:1,children:j(p,{dimColor:!0,children:["\uD83D\uDCA1 按"," ",j(p,{bold:!0,color:"green",children:"Y"},void 0,!1,void 0,this)," ","保存,",j(p,{bold:!0,color:"red",children:"N"},void 0,!1,void 0,this)," ","返回修改,",j(p,{bold:!0,children:"Esc"},void 0,!1,void 0,this)," 取消"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{useMemoizedFn as D4,useMount as sU}from"ahooks";import{Box as z0,Text as K1,useFocus as tU,useFocusManager as eU,useInput as $H}from"ink";import YH from"ink-select-input";import{memo as ZH,useMemo as XH,useState as I4}from"react";z1();import{jsxDEV as n}from"react/jsx-dev-runtime";var QH=({isSelected:$})=>n(z0,{marginRight:1,children:n(K1,{color:$?"yellow":"gray",children:$?"▶":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),JH=({isSelected:$,label:Y})=>n(K1,{bold:$,color:$?"yellow":void 0,children:Y},void 0,!1,void 0,this),tX=ZH(({onClose:$,onEdit:Y})=>{let Z=rY(),X=aY()??"",{isFocused:Q}=tU({id:"model-selector"}),J=eU(),[q,G]=I4(""),[K,W]=I4(!1),[U,H]=I4(null),O=T1(!1),[F]=I4(()=>{let L=process.stdout?.columns||80;return Math.max(20,L-8)});sU(()=>{if(J?.focus("model-selector"),Z.length>0)G(Z[0].id)}),$H((L,A)=>{if(K)return;if(A.ctrl&&L==="c"||A.meta&&L==="c"){O();return}if(A.escape){$();return}if(!Q)return;if(L==="d"||L==="D"){z();return}if((L==="e"||L==="E")&&Y)w()},{isActive:!0});let _=D4(async(L)=>{if(K)return;let A=L.value;if(A===X){$();return}W(!0),H(null);try{await H1().setCurrentModel(A),$()}catch(k){H(k.message),W(!1)}}),z=D4(async()=>{if(K||q===X)return;W(!0),H(null);try{if(await H1().removeModel(q),Z.length<=1)$()}catch(L){H(L.message)}finally{W(!1)}}),w=D4(()=>{if(K||!Y)return;let L=Z.find((A)=>A.id===q);if(!L)return;Y(L)}),B=D4((L)=>{G(L.value)}),N=XH(()=>{return Z.find((L)=>L.id===q)},[Z,q]),b=Z.map((L)=>({label:L.name+(L.id===X?" (当前)":""),value:L.id})),V=q===X;return n(z0,{flexDirection:"column",borderStyle:"round",borderColor:"gray",padding:1,width:"100%",children:[n(z0,{flexDirection:"row",justifyContent:"space-between",marginBottom:1,children:[n(K1,{bold:!0,color:"cyan",children:"模型管理"},void 0,!1,void 0,this),n(K1,{dimColor:!0,children:[K?"⏳ 处理中...":V?"Enter=关闭 • E=编辑 • Esc=取消":"Enter=切换 • D=删除 • E=编辑 • Esc=取消"," • Ctrl+C=退出"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),n(z0,{flexDirection:"row",children:[n(z0,{flexDirection:"column",flexGrow:2,marginRight:2,borderStyle:"single",borderColor:"gray",padding:1,children:[n(K1,{dimColor:!0,children:["已配置模型 (",Z.length,")"]},void 0,!0,void 0,this),n(z0,{marginTop:1,children:n(YH,{items:b,onSelect:_,onHighlight:B,indicatorComponent:QH,itemComponent:JH},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n(z0,{flexDirection:"column",flexGrow:3,borderStyle:"single",borderColor:"gray",padding:1,children:[n(K1,{dimColor:!0,children:"模型详情"},void 0,!1,void 0,this),n(z0,{marginY:1,children:n(K1,{color:V?"green":"yellow",children:V?"● 当前使用":"● 可切换"},void 0,!1,void 0,this)},void 0,!1,void 0,this),N?n(z0,{flexDirection:"column",children:[n(K1,{children:[n(K1,{dimColor:!0,children:"名称: "},void 0,!1,void 0,this),n(K1,{bold:!0,color:"cyan",children:N.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n(K1,{children:[n(K1,{dimColor:!0,children:"Provider: "},void 0,!1,void 0,this),n(K1,{bold:!0,children:N.provider},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n(K1,{children:[n(K1,{dimColor:!0,children:"Model: "},void 0,!1,void 0,this),n(K1,{bold:!0,children:N.model},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n(K1,{children:[n(K1,{dimColor:!0,children:"Base URL: "},void 0,!1,void 0,this),n(K1,{color:"blueBright",children:N.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),N.temperature!==void 0&&n(K1,{children:[n(K1,{dimColor:!0,children:"Temperature: "},void 0,!1,void 0,this),n(K1,{children:N.temperature},void 0,!1,void 0,this)]},void 0,!0,void 0,this),N.maxContextTokens!==void 0&&n(K1,{children:[n(K1,{dimColor:!0,children:"Context Window: "},void 0,!1,void 0,this),n(K1,{children:N.maxContextTokens},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):n(K1,{dimColor:!0,children:"请选择一个模型查看详情"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),U&&n(z0,{marginTop:1,children:n(K1,{color:"red",children:["❌ ",U]},void 0,!0,void 0,this)},void 0,!1,void 0,this),n(z0,{justifyContent:"center",marginTop:1,children:n(K1,{dimColor:!0,children:"─".repeat(F)},void 0,!1,void 0,this)},void 0,!1,void 0,this),n(z0,{justifyContent:"center",children:n(K1,{dimColor:!0,children:"提示:D=删除 • E=编辑 • ↑↓=移动 • Enter/ESC=确认"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{useMemoizedFn as H6}from"ahooks";import{promises as ZQ}from"fs";import{Box as Z0,Text as N1,useInput as qH}from"ink";import eX from"ink-select-input";import GH from"ink-text-input";import KH from"os";import M4 from"path";import{useEffect as WH,useMemo as k4,useRef as UH,useState as _2}from"react";z1();import{jsxDEV as o}from"react/jsx-dev-runtime";var O6=[{key:"allow",label:"Allow"},{key:"ask",label:"Ask"},{key:"deny",label:"Deny"},{key:"info",label:"Info"}],HH={allow:"Add a new rule...",ask:"Add a new rule...",deny:"Add a new rule..."},OH={allow:"Allow permission rules",ask:"Ask permission rules",deny:"Deny permission rules"},$Q={project:"[项目共享配置]",global:"[用户全局配置]",local:"[本地配置]"},FH=["project","global","local"],zH={allow:[],ask:[],deny:[]},_H={localExists:!1,projectExists:!1,globalExists:!1},YQ={allow:[],ask:[],deny:[]};function NH($){let Y=(X)=>Array.isArray(X)?X.filter((Q)=>typeof Q==="string"):[],Z=$?.permissions??{};return{allow:Y(Z?.allow),ask:Y(Z?.ask),deny:Y(Z?.deny)}}async function BH($){try{let Y=await ZQ.readFile($,"utf-8"),Z=JSON.parse(Y);return{exists:!0,raw:Z,permissions:NH(Z)}}catch(Y){if(Y.code==="ENOENT")return{exists:!1,raw:{},permissions:{...YQ}};return console.warn(`[PermissionsManager] Failed to read ${$}:`,Y),{exists:!0,raw:{},permissions:{...YQ}}}}function wH($,Y){let Z=$.padEnd(32," "),X=Y==="local"?`${$Q[Y]} ← 可删除`:$Q[Y];return`${Z} ${X}`}var XQ=({onClose:$})=>{let Z=G0()==="permissions-manager",X=T1(!1),[Q,J]=_2(0),q=O6[Q].key,[G,K]=_2(zH),[W,U]=_2(_H),[H,O]=_2(!0),[F,_]=_2("list"),[z,w]=_2(""),[B,N]=_2(null),[b,V]=_2(null),R=UH(!1),L=k4(()=>M4.join(process.cwd(),".blade","settings.local.json"),[]),A=k4(()=>M4.join(process.cwd(),".blade","settings.json"),[]),k=k4(()=>M4.join(KH.homedir(),".blade","settings.json"),[]),I=H6(async()=>{O(!0);let i=[{source:"local",path:L},{source:"project",path:A},{source:"global",path:k}],G1=await Promise.all(i.map(async({source:y1,path:c0})=>{let _0=await BH(c0);return{source:y1,path:c0,..._0}})),$1={localExists:G1.find((y1)=>y1.source==="local")?.exists??!1,projectExists:G1.find((y1)=>y1.source==="project")?.exists??!1,globalExists:G1.find((y1)=>y1.source==="global")?.exists??!1};U($1);let o1={allow:[],ask:[],deny:[]},B2=Object.fromEntries(G1.map((y1)=>[y1.source,y1]));["allow","ask","deny"].forEach((y1)=>{FH.forEach((c0)=>{(B2[c0]?.permissions[y1]??[]).forEach((k$,E0)=>{let w2={key:`${c0}:${E0}:${k$}`,rule:k$,source:c0};o1[y1].push(w2)})})}),K(o1),O(!1)});WH(()=>{I()},[I]);let T=H6(async(i,G1)=>{try{let $1=M4.join(process.cwd(),".blade","settings.local.json"),o1={allow:[],ask:[],deny:[]};try{let y1=await ZQ.readFile($1,"utf-8"),_0=JSON.parse(y1).permissions||{};o1={allow:Array.isArray(_0.allow)?_0.allow:[],ask:Array.isArray(_0.ask)?_0.ask:[],deny:Array.isArray(_0.deny)?_0.deny:[]}}catch(y1){}let B2=G1(o1);await H1().updateConfig({permissions:B2},{scope:"local",immediate:!0}),await I()}catch($1){throw console.error("[PermissionsManager] 修改权限规则失败:",$1),$1}});qH((i,G1)=>{if(G1.ctrl&&i==="c"||G1.meta&&i==="c"){X();return}if(F==="locked"){if(R.current){R.current=!1;return}_("list"),N(null),V(null);return}if(G1.escape){if(F==="list"||q==="info")$();else _("list"),w(""),N(null),V(null);return}if(F==="list"){if(G1.tab&&G1.shift)J(($1)=>($1-1+O6.length)%O6.length);else if(G1.tab)J(($1)=>($1+1)%O6.length);else if(i?.toLowerCase()==="q")$()}},{isActive:Z});let E=H6((i)=>{let G1=i.value;if(q==="info")return;if(G1.type==="add"){_("add"),w(""),V(null);return}if(G1.entry.source!=="local"){_("locked"),R.current=!0,N({tab:q,entry:G1.entry}),V({type:"error",text:G1.entry.source==="project"?"此规则定义在项目共享配置中,无法在此删除。":"此规则来自用户全局配置,无法在此删除。"});return}_("confirm-delete"),N({tab:q,entry:G1.entry}),V(null)}),v=H6(async()=>{if(q==="info")return;let i=z.trim();if(!i){V({type:"error",text:"Permission rule 不能为空"});return}if(G[q].map(($1)=>$1.rule).includes(i)){V({type:"error",text:"该规则已存在"});return}try{await T(q,($1)=>{let o1={allow:[...$1.allow],ask:[...$1.ask],deny:[...$1.deny]};return o1[q]=[...new Set([...$1[q],i])],o1}),_("list"),w(""),V({type:"success",text:"已添加本地权限规则"})}catch($1){V({type:"error",text:`保存失败: ${$1 instanceof Error?$1.message:"未知错误"}`})}}),g=H6(async()=>{if(!B)return;let{tab:i,entry:G1}=B;try{await T(i,($1)=>{let o1={allow:[...$1.allow],ask:[...$1.ask],deny:[...$1.deny]};return o1[i]=$1[i].filter((B2)=>B2!==G1.rule),o1}),_("list"),N(null),V({type:"success",text:"已删除本地权限规则"})}catch($1){V({type:"error",text:`删除失败: ${$1 instanceof Error?$1.message:"未知错误"}`})}}),u=k4(()=>{if(q==="info")return[];let i=q;return[{label:`› ${HH[i]}`,value:{type:"add"}},...G[i].map(($1)=>({label:wH($1.rule,$1.source),value:{type:"rule",entry:$1}}))]},[q,G]),D1=()=>o(Z0,{marginBottom:1,children:O6.map((i,G1)=>o(Z0,{marginRight:2,children:o(N1,{color:G1===Q?"yellow":"gray",children:["[",i.label,"]"]},void 0,!0,void 0,this)},i.key,!1,void 0,this))},void 0,!1,void 0,this),J1=()=>o(Z0,{flexDirection:"column",gap:1,children:[o(N1,{children:"配置文件优先级(从高到低):"},void 0,!1,void 0,this),o(Z0,{flexDirection:"column",marginLeft:2,children:[o(N1,{children:["1. .blade/settings.local.json (本地配置,不提交 Git)"," ",W.localExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this),o(N1,{children:["2. .blade/settings.json (项目配置,提交 Git)"," ",W.projectExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this),o(N1,{children:["3. ~/.blade/settings.json (用户全局配置)"," ",W.globalExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),o(N1,{children:"说明:"},void 0,!1,void 0,this),o(Z0,{flexDirection:"column",marginLeft:2,children:[o(N1,{children:"- /permissions 命令只管理本地配置 (.blade/settings.local.json)"},void 0,!1,void 0,this),o(N1,{children:"- 修改全局或项目配置请直接编辑对应文件"},void 0,!1,void 0,this),o(N1,{children:"- 本地配置不会提交到 Git"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),x=(i)=>o(Z0,{flexDirection:"column",gap:1,children:[o(N1,{bold:!0,children:OH[i]},void 0,!1,void 0,this),o(N1,{children:"Permission rules are a tool name, optionally followed by a specifier in parentheses."},void 0,!1,void 0,this),o(N1,{color:"gray",children:"例如: WebFetch 或 Bash(ls:*)"},void 0,!1,void 0,this),o(Z0,{marginTop:1,children:o(GH,{value:z,onChange:w,onSubmit:v},void 0,!1,void 0,this)},void 0,!1,void 0,this),o(N1,{color:"gray",children:"Enter 提交 · Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),j0=(i,G1)=>o(Z0,{flexDirection:"column",gap:1,children:[o(N1,{bold:!0,children:["Delete ",i," permission rule?"]},void 0,!0,void 0,this),o(N1,{children:G1.rule},void 0,!1,void 0,this),o(N1,{color:"gray",children:"From project local settings"},void 0,!1,void 0,this),o(N1,{children:"Are you sure you want to delete this permission rule?"},void 0,!1,void 0,this),o(eX,{items:[{label:"Yes",value:"yes"},{label:"No",value:"no"}],onSelect:($1)=>{if($1.value==="yes")g();else _("list"),N(null)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q1=(i)=>o(Z0,{flexDirection:"column",gap:1,children:[o(N1,{bold:!0,children:"Cannot delete this rule"},void 0,!1,void 0,this),o(N1,{children:i.rule},void 0,!1,void 0,this),o(N1,{color:"gray",children:i.source==="project"?"This rule is defined in .blade/settings.json. 请手动编辑该文件以移除规则。":"This rule is defined in ~/.blade/settings.json. 请手动编辑该文件以移除规则。"},void 0,!1,void 0,this),o(N1,{color:"gray",children:"按任意键继续"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1=(i)=>o(eX,{items:u,isFocused:F==="list",onSelect:E},void 0,!1,void 0,this),u0=()=>{if(H)return o(N1,{children:"加载中..."},void 0,!1,void 0,this);if(q==="info")return J1();if(F==="add")return x(q);if(F==="confirm-delete"&&B)return j0(B.tab,B.entry);if(F==="locked"&&B)return Q1(B.entry);return b1(q)};return o(Z0,{flexDirection:"column",borderStyle:"round",borderColor:Z?"cyan":"gray",padding:1,width:80,children:[o(N1,{color:"cyan",bold:!0,children:"⚙️ 权限管理器"},void 0,!1,void 0,this),D1(),o(Z0,{flexDirection:"column",gap:1,children:u0()},void 0,!1,void 0,this),b&&o(Z0,{marginTop:1,children:o(N1,{color:b.type==="success"?"green":"red",children:b.text},void 0,!1,void 0,this)},void 0,!1,void 0,this),o(Z0,{marginTop:1,children:o(N1,{color:"gray",children:"Tab 切换视图 · Esc 关闭 · Q 退出"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};o6();import{Box as M$,Text as k0,useInput as LH}from"ink";import AH from"ink-select-input";import{useEffect as QQ,useMemo as j4,useState as W7}from"react";import{jsxDEV as S1}from"react/jsx-dev-runtime";function bH($){let Y=new Date($),X=new Date().getTime()-Y.getTime(),Q=Math.floor(X/86400000);if(Q===0)return`今天 ${Y.getHours().toString().padStart(2,"0")}:${Y.getMinutes().toString().padStart(2,"0")}`;if(Q===1)return"昨天";if(Q<7)return`${Q}天前`;return`${Y.getMonth()+1}/${Y.getDate()}`}function RH($){let Y=$.split("/");return Y[Y.length-1]||$}var VH=({isSelected:$})=>S1(M$,{marginRight:1,children:S1(k0,{color:$?"cyan":"gray",children:$?"❯":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),DH=({isSelected:$,label:Y})=>S1(k0,{color:$?"cyan":"white",bold:$,children:Y},void 0,!1,void 0,this),F6=20,JQ=({sessions:$,onSelect:Y,onCancel:Z})=>{let[X,Q]=W7([]),[J,q]=W7(!1),[G,K]=W7(0),U=G0()==="session-selector",H=T1(!1);LH((N,b)=>{if(b.ctrl&&N==="c"||b.meta&&N==="c"){H();return}if(b.escape&&Z){Z();return}if(b.leftArrow||N==="h"||N==="H"){if(G>0)K((V)=>V-1);return}if(b.rightArrow||N==="l"||N==="L"){if(G<_-1)K((V)=>V+1);return}},{isActive:U}),QQ(()=>{if($){Q($);return}(async()=>{q(!0);try{let b=await C0.listSessions();Q(b)}catch(b){console.error("[SessionSelector] Failed to load sessions:",b),Q([])}finally{q(!1)}})()},[$]);let O=$||X,F=j4(()=>{return O.map((N)=>{let b=RH(N.projectPath),V=bH(N.lastMessageTime),R=N.gitBranch?` (${N.gitBranch})`:"",L=N.hasErrors?" ⚠️":"";return{label:`\uD83D\uDCC5 ${V} | ${b}${R} | ${N.messageCount} 条消息${L}`,value:N.sessionId}})},[O]),_=j4(()=>Math.max(1,Math.ceil(F.length/F6)),[F.length]),z=j4(()=>{let N=G*F6;return F.slice(N,N+F6)},[F,G]),w=j4(()=>({start:G*F6+1,end:Math.min((G+1)*F6,F.length)}),[G,F.length]);QQ(()=>{K(0)},[O.length]);let B=(N)=>{Y(N.value)};if(J)return S1(M$,{flexDirection:"column",paddingX:2,paddingY:1,children:S1(k0,{children:"⏳ 正在加载会话列表..."},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(O.length===0)return S1(M$,{flexDirection:"column",paddingX:2,paddingY:1,children:[S1(k0,{color:"yellow",children:"⚠️ 没有找到历史会话"},void 0,!1,void 0,this),S1(k0,{dimColor:!0,children:[`
1598
+ `,"提示: 开始一次对话后,会话历史将保存到 ~/.blade/projects/"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this);return S1(M$,{flexDirection:"column",paddingX:2,paddingY:1,children:[S1(k0,{bold:!0,color:"cyan",children:"\uD83D\uDCC2 选择要恢复的会话:"},void 0,!1,void 0,this),S1(k0,{dimColor:!0,children:[`
1546
1599
  `,"(←→ 翻页 | ↑↓ 选择 | Enter 确认 | Esc 取消)",`
1547
- `]},void 0,!0,void 0,this),T1(UH,{items:F,onSelect:w,indicatorComponent:zH,itemComponent:FH},void 0,!1,void 0,this),T1(b$,{marginTop:1,flexDirection:"column",children:[T1(k0,{dimColor:!0,children:["第 ",K+1,"/",_," 页 · 共 ",O.length," 个会话 · 显示"," ",N.start,"-",N.end]},void 0,!0,void 0,this),_>1&&T1(b$,{marginTop:1,children:[T1(k0,{color:K>0?"cyan":"gray",children:K>0?"◀ ← 上一页":" "},void 0,!1,void 0,this),T1(k0,{children:" "},void 0,!1,void 0,this),T1(k0,{color:K<_-1?"cyan":"gray",children:K<_-1?"下一页 → ▶":""},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{useMemoizedFn as _H}from"ahooks";import{Box as p0,Text as S,useInput as BH}from"ink";import NH from"ink-select-input";import{useState as iX}from"react";F1();import{jsxDEV as y}from"react/jsx-dev-runtime";var rX=h0.map(($)=>({label:$.label,value:$.id})),wH=({theme:$})=>{let{colors:Y}=$;return y(p0,{flexDirection:"column",paddingLeft:1,paddingTop:1,children:[y(S,{bold:!0,color:Y.text.primary,children:"代码预览"},void 0,!1,void 0,this),y(S,{children:" "},void 0,!1,void 0,this),y(S,{color:Y.syntax.comment,children:"# function"},void 0,!1,void 0,this),y(S,{children:[y(S,{color:Y.syntax.keyword,children:"def"},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.function,children:"fibonacci"},void 0,!1,void 0,this),y(S,{color:Y.text.primary,children:"("},void 0,!1,void 0,this),y(S,{color:Y.syntax.variable,children:"n"},void 0,!1,void 0,this),y(S,{color:Y.text.primary,children:"):"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(S,{children:[" ",y(S,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this),y(S,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.operator,children:"="},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.number,children:"0"},void 0,!1,void 0,this),y(S,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.number,children:"1"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(S,{children:[" ",y(S,{color:Y.syntax.keyword,children:"for"},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.variable,children:"_"},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.keyword,children:"in"},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.function,children:"range"},void 0,!1,void 0,this),y(S,{color:Y.text.primary,children:"("},void 0,!1,void 0,this),y(S,{color:Y.syntax.variable,children:"n"},void 0,!1,void 0,this),y(S,{color:Y.text.primary,children:"):"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(S,{children:[" ",y(S,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this),y(S,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.operator,children:"="},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this),y(S,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.operator,children:"+"},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(S,{children:[" ",y(S,{color:Y.syntax.keyword,children:"return"},void 0,!1,void 0,this)," ",y(S,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(S,{children:" "},void 0,!1,void 0,this),y(S,{color:Y.error,children:["- print(",y(S,{color:Y.syntax.string,children:'"Hello, "'},void 0,!1,void 0,this)," + name)"]},void 0,!0,void 0,this),y(S,{color:Y.success,children:["+ print(",y(S,{color:Y.syntax.string,children:['f"Hello, ',"{","name","}",'"']},void 0,!0,void 0,this),")"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},LH=({theme:$})=>{let{colors:Y}=$;return y(p0,{flexDirection:"column",paddingLeft:1,paddingTop:1,children:[y(S,{children:" "},void 0,!1,void 0,this),y(S,{bold:!0,color:Y.text.primary,children:"颜色配置"},void 0,!1,void 0,this),y(S,{children:" "},void 0,!1,void 0,this),y(S,{children:[y(S,{color:Y.text.muted,children:"Primary: "},void 0,!1,void 0,this),y(S,{color:Y.primary,children:Y.primary},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(S,{children:[y(S,{color:Y.text.muted,children:"Success: "},void 0,!1,void 0,this),y(S,{color:Y.success,children:Y.success},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(S,{children:[y(S,{color:Y.text.muted,children:"Error: "},void 0,!1,void 0,this),y(S,{color:Y.error,children:Y.error},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(S,{children:[y(S,{color:Y.text.muted,children:"Warning: "},void 0,!1,void 0,this),y(S,{color:Y.warning,children:Y.warning},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(S,{children:[y(S,{color:Y.text.muted,children:"Info: "},void 0,!1,void 0,this),y(S,{color:Y.info,children:Y.info},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},aX=()=>{let $=U2(),Y=Y1.getCurrentThemeName(),Z=h0.findIndex((_)=>_.label===Y),X=Z>=0?h0[Z].theme:h0[0].theme,[Q,J]=iX(X),[q,K]=iX(!1),G=_H(async(_)=>{if(q)return;K(!0);try{Y1.setTheme(_.value),await U1().setTheme(_.value),$.closeModal()}catch(F){console.error("❌ 主题切换失败:",F instanceof Error?F.message:F)}finally{K(!1)}}),W=(_)=>{let F=h0.find((N)=>N.id===_.value);if(F)J(F.theme)},H=q0()==="theme-selector",O=P1(!1);BH((_,F)=>{if(F.ctrl&&_==="c"||F.meta&&_==="c"){O();return}if(F.escape&&!q)$.closeModal()},{isActive:H});let z=(_)=>{let{isSelected:F,label:N}=_,B=N===Y?"✓":" ";return y(S,{color:F?Q.colors.primary:Q.colors.text.primary,children:[B," ",N]},void 0,!0,void 0,this)};return y(p0,{flexDirection:"column",height:"100%",children:[y(p0,{paddingX:2,paddingY:1,borderStyle:"single",borderColor:Q.colors.border.light,children:y(S,{bold:!0,color:Q.colors.primary,children:"\uD83C\uDFA8 主题选择器"},void 0,!1,void 0,this)},void 0,!1,void 0,this),y(p0,{flexDirection:"row",flexGrow:1,children:[y(p0,{width:"40%",borderStyle:"single",borderColor:Q.colors.border.light,paddingX:1,children:y(p0,{flexDirection:"column",children:[y(p0,{paddingTop:1,paddingBottom:1,children:y(S,{bold:!0,color:Q.colors.text.primary,children:["可用主题 (",rX.length,")"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),y(NH,{items:rX,initialIndex:Z>=0?Z:0,onSelect:G,onHighlight:W,itemComponent:z},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),y(p0,{width:"60%",flexDirection:"column",borderStyle:"single",borderColor:Q.colors.border.light,children:[y(wH,{theme:Q},void 0,!1,void 0,this),y(LH,{theme:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),y(p0,{paddingX:2,paddingY:1,borderStyle:"single",borderColor:Q.colors.border.light,children:y(S,{color:Q.colors.text.muted,children:q?"正在保存...":"Enter: 选择主题 | Esc: 取消"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as I1,Fragment as RH}from"react/jsx-dev-runtime";var Z0=u("UI"),nX=({debug:$,...Y})=>{if($)Z0.debug("[Debug] BladeInterface props:",{permissionMode:Y.permissionMode,yolo:Y.yolo,maxTurns:Y.maxTurns});let Z=b4(!1),X=b4(!1),Q=b4(!1),J=b4(null),q=yY(),K=vY(),G=i6(),W=SY(),U=TY(),H=U2(),O=W$(),z=pY(),_=U$(),F=W2(),{exit:N}=AH(),w=q==="ready",B=q==="needsSetup",A=q==="idle",{confirmationState:D,confirmationHandler:I,handleResponse:b}=xZ(),{executeCommand:L,handleAbort:V}=SZ(Y.systemPrompt,Y.appendSystemPrompt,I,Y.maxTurns),{getPreviousCommand:j,getNextCommand:m,addToHistory:P}=fZ(),v=pZ("",0),Z1=a1(async()=>{let a=_,W1;if(a==="default")W1="autoEdit";else if(a==="autoEdit")W1="plan";else W1="default";try{await U1().setPermissionMode(W1)}catch(B0){Z0.error("❌ 权限模式切换失败:",B0 instanceof Error?B0.message:B0)}}),X1=a1(async(a)=>{try{await U1().addModel({name:a.name,provider:a.provider,apiKey:a.apiKey,baseUrl:a.baseUrl,model:a.model}),H.setInitializationStatus("ready")}catch(W1){Z0.error("❌ 初始化配置保存失败:",W1 instanceof Error?W1.message:W1),H.setInitializationStatus("ready")}}),n1=a1(()=>{if(G==="shortcuts")H.closeModal();else H.setActiveModal("shortcuts")}),{showSuggestions:z1,suggestions:d,selectedSuggestionIndex:C2}=aZ(v,L,j,m,P,V,F,Z1,n1,G==="shortcuts");T2(()=>{if(v.value&&G==="shortcuts")H.closeModal()},[v.value,G,H]);let J1=a1(async()=>{try{if(typeof Y.resume==="string"&&Y.resume!=="true"){let W1=await S0.loadSession(Y.resume),B0=W1.map((u0,D$)=>({id:`restored-${Date.now()}-${D$}`,role:u0.role,content:typeof u0.content==="string"?u0.content:JSON.stringify(u0.content),timestamp:Date.now()-(W1.length-D$)*1000}));O.restoreSession(Y.resume,B0);return}let a=await S0.listSessions();if(a.length===0)Z0.error("没有找到历史会话"),process.exit(1);H.showSessionSelector(a)}catch(a){Z0.error("[BladeInterface] 加载会话失败:",a),process.exit(1)}});T2(()=>{if(Z.current)return;if(!Y.resume)return;Z.current=!0,J1()},[Y.resume,J1]);let R1=a1(async(a)=>{let W1=D.details?.type;if(W1==="enterPlanMode"&&a.approved)try{await U1().setPermissionMode("plan"),Z0.debug("[BladeInterface] Entered Plan mode")}catch(B0){Z0.error("[BladeInterface] Failed to enter Plan mode:",B0)}if(W1==="exitPlanMode"&&a.approved)Z0.debug("[BladeInterface] ExitPlanMode approved, Store auto-synced");b(a)}),m0=a1(()=>{O.addAssistantMessage("❌ 设置已取消"),O.addAssistantMessage("Blade 需要 API 配置才能正常工作。"),O.addAssistantMessage("您可以稍后运行 Blade 重新进入设置向导。"),process.exit(0)}),c=a1(()=>{H.closeModal()}),q1=a1(async(a)=>{try{let W1=await S0.loadSession(a),B0=W1.map((u0,D$)=>({id:`restored-${Date.now()}-${D$}`,role:u0.role,content:typeof u0.content==="string"?u0.content:JSON.stringify(u0.content),timestamp:Date.now()-(W1.length-D$)*1000}));O.restoreSession(a,B0),H.closeModal()}catch(W1){Z0.error("[BladeInterface] Failed to restore session:",W1),H.closeModal()}}),t=a1(()=>{if(Y.resume)N();else H.closeModal()}),o1=a1((a)=>{H.showModelEditWizard(a)}),N2=a1((a)=>{O.addAssistantMessage(`✅ 已添加模型配置: ${a.name},并已切换到该模型`),c()}),y1=a1((a)=>{O.addAssistantMessage(`✅ 已更新模型配置: ${a.name}`),c()});T2(()=>{if(B){z.setFocus("model-config-wizard");return}if(D.isVisible)z.setFocus("confirmation-prompt");else if(G==="sessionSelector")z.setFocus("session-selector");else if(G==="themeSelector")z.setFocus("theme-selector");else if(G==="modelSelector")z.setFocus("model-selector");else if(G==="modelAddWizard"||G==="modelEditWizard")z.setFocus("model-config-wizard");else if(G==="permissionsManager")z.setFocus("permissions-manager");else if(G==="agentsManager")z.setFocus("agents-manager");else if(G==="agentCreationWizard")z.setFocus("agent-creation-wizard");else if(G==="shortcuts")z.setFocus("main-input");else z.setFocus("main-input")},[B,D.isVisible,G,z.setFocus]),T2(()=>{if(!w||Q.current)return;if(T7().length>0){Q.current=!0;return}Q.current=!0,O.addAssistantMessage("请输入您的问题,我将为您提供帮助。")},[w]),T2(()=>{if(!K)return;if(J.current===K)return;if(J.current=K,q==="error")O.addAssistantMessage(`❌ 初始化失败: ${K}`);else O.addAssistantMessage(`❌ ${K}`),O.addAssistantMessage("请重新尝试设置,或检查文件权限")},[K,q,O.addAssistantMessage]);let d0=a1(async(a)=>{try{await L(a)}catch(W1){let B0=W1 instanceof Error?W1.message:"无法发送初始消息";O.addAssistantMessage(`❌ 初始消息发送失败:${B0}`)}});T2(()=>{let a=Y.initialMessage?.trim();if(!a||X.current||!w||B)return;X.current=!0,P(a),d0(a)},[Y.initialMessage,w,B,L,P]);let _0=a1(async(a)=>{try{await U1().setPermissionMode(a)}catch(W1){Z0.error("❌ 权限模式初始化失败:",W1 instanceof Error?W1.message:W1)}});if(T2(()=>{let a=Y.permissionMode;if($)Z0.debug("[Debug] permissionMode from CLI:",a),Z0.debug("[Debug] current permissionMode:",_);if(!a||a===_)return;_0(a)},[Y.permissionMode,_]),A)return null;if(B)return I1(t9,{mode:"setup",onComplete:X1,onCancel:m0},void 0,!1,void 0,this);if($)Z0.debug("[Debug] 渲染主界面,条件检查:",{confirmationVisible:D.isVisible,activeModal:G});let V$=G==="modelSelector",j0=U,w2=G==="modelAddWizard"?"add":G==="modelEditWizard"&&j0?"edit":null,JQ=V$||Boolean(w2),qQ=G==="agentsManager",KQ=G==="agentCreationWizard",GQ=j0?{name:j0.name,provider:j0.provider,baseUrl:j0.baseUrl,apiKey:j0.apiKey,model:j0.model}:void 0,WQ=D.isVisible&&D.details?I1(OX,{details:D.details,onResponse:R1},void 0,!1,void 0,this):G==="themeSelector"?I1(aX,{},void 0,!1,void 0,this):G==="permissionsManager"?I1(uX,{onClose:c},void 0,!1,void 0,this):G==="sessionSelector"?I1(lX,{sessions:W,onSelect:q1,onCancel:t},void 0,!1,void 0,this):null;return I1(G6,{flexDirection:"column",width:"100%",height:"100%",children:WQ??I1(RH,{children:[I1(fX,{},void 0,!1,void 0,this),I1(EX,{},void 0,!1,void 0,this),I1(bX,{input:v.value,cursorPosition:v.cursorPosition,onChange:v.setValue,onChangeCursorPosition:v.setCursorPosition},void 0,!1,void 0,this),V$&&I1(G6,{marginTop:1,paddingX:2,children:I1(xX,{onClose:c,onEdit:o1},void 0,!1,void 0,this)},void 0,!1,void 0,this),w2&&I1(G6,{marginTop:1,paddingX:2,children:I1(t9,{mode:w2,modelId:j0?.id,initialConfig:w2==="edit"?GQ:void 0,onComplete:w2==="edit"?y1:N2,onCancel:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),qQ&&I1(G6,{marginTop:1,paddingX:2,children:I1(tZ,{onComplete:c,onCancel:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),KQ&&I1(G6,{marginTop:1,paddingX:2,children:I1(t$,{onComplete:c,onCancel:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),I1(ZX,{suggestions:d,selectedIndex:C2,visible:z1&&!JQ},void 0,!1,void 0,this),I1(YX,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)};import{Box as bH,Text as B2}from"ink";import VH from"react";import{jsxDEV as o0}from"react/jsx-dev-runtime";class V4 extends VH.Component{constructor($){super($);this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError($){return{hasError:!0,error:$,errorInfo:null}}componentDidCatch($,Y){this.setState({error:$,errorInfo:Y}),console.error("未捕获的错误:",$,Y)}render(){if(this.state.hasError)return o0(bH,{flexDirection:"column",padding:1,borderStyle:"round",borderColor:"red",children:[o0(B2,{color:"red",children:"\uD83D\uDCA5 应用发生错误"},void 0,!1,void 0,this),o0(B2,{children:" "},void 0,!1,void 0,this),o0(B2,{color:"red",children:this.state.error?.message},void 0,!1,void 0,this),o0(B2,{children:" "},void 0,!1,void 0,this),o0(B2,{color:"gray",children:"错误详情:"},void 0,!1,void 0,this),o0(B2,{color:"gray",children:this.state.error?.stack},void 0,!1,void 0,this),o0(B2,{children:" "},void 0,!1,void 0,this),o0(B2,{color:"yellow",children:"请重启应用或联系开发者"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return this.props.children}}import{Box as S2,Text as s0,useInput as DH}from"ink";import{useState as $7}from"react";import{jsxDEV as g1}from"react/jsx-dev-runtime";var D4=[{key:"update",label:"Update now",description:`runs \`${L9()}\``},{key:"skip",label:"Skip",description:""},{key:"skip_until_next",label:"Skip until next version",description:""}],oX=({versionInfo:$,onComplete:Y})=>{let[Z,X]=$7(0),[Q,J]=$7(!1),[q,K]=$7(null);DH((W,U)=>{if(U.ctrl&&W==="c"){j2().shutdown("SIGINT",0);return}if(Q||q)return;if(U.upArrow||W==="k")X((H)=>H>0?H-1:D4.length-1);else if(U.downArrow||W==="j")X((H)=>H<D4.length-1?H+1:0);else if(U.return)G(D4[Z].key);else if(W==="1")G("update");else if(W==="2")G("skip");else if(W==="3")G("skip_until_next")});let G=async(W)=>{switch(W){case"update":{J(!0);let U=await LY();K(U.message),setTimeout(()=>{j2().shutdown("SIGINT",0)},1500);break}case"skip":Y();break;case"skip_until_next":if($.latestVersion)await wY($.latestVersion);Y();break}};if(q)return g1(S2,{flexDirection:"column",marginY:1,children:g1(s0,{children:q},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(Q)return g1(S2,{flexDirection:"column",marginY:1,children:g1(s0,{color:"cyan",children:"Updating..."},void 0,!1,void 0,this)},void 0,!1,void 0,this);return g1(S2,{flexDirection:"column",marginY:1,children:[g1(s0,{color:"yellow",bold:!0,children:["✨ Update available! ",g1(s0,{color:"gray",children:[$.currentVersion," ","→"," ",$.latestVersion]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),g1(S2,{marginTop:1,children:g1(s0,{color:"gray",children:["Release notes:"," ",g1(s0,{color:"cyan",underline:!0,children:$.releaseNotesUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),g1(S2,{flexDirection:"column",marginTop:1,children:D4.map((W,U)=>{let H=U===Z,O=H?"› ":" ",z=`${U+1}. `;return g1(S2,{children:g1(s0,{color:H?"cyan":void 0,children:[O,z,W.label,W.description&&g1(s0,{color:"gray",children:[" (",W.description,")"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},W.key,!1,void 0,this)})},void 0,!1,void 0,this),g1(S2,{marginTop:1,children:g1(s0,{color:"gray",children:"Press enter to continue"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};function Y7($){return($ instanceof Error?$.message:String($)).replace(/sk-[a-zA-Z0-9]{32,}/g,"sk-***").replace(/apiKey['":\s]+[a-zA-Z0-9-_]+/gi,"apiKey: ***").replace(/API_KEY['":\s=]+[a-zA-Z0-9-_]+/gi,"API_KEY=***")}import{jsxDEV as M4}from"react/jsx-dev-runtime";function IH($){if(n().config.actions.setConfig($),!$.models||$.models.length===0){if($.debug)console.log("[Debug] 未检测到模型配置,进入设置向导");w0().setInitializationStatus("needsSetup");return}if($.debug)console.log("[Debug] 模型配置检查通过,准备就绪");w0().setInitializationStatus("ready")}var tX=($)=>{let[Y,Z]=Z7(!1),[X,Q]=Z7(null),[J,q]=Z7(!1),K=sX(()=>{let W=n().config.config??h2,U=j4(W,$);if(IH(U),U.debug)console.error("[Debug] 运行时配置:",U);let H=U.theme;if(H&&Y1.hasTheme(H)){if(Y1.setTheme(H),$.debug)console.log(`✓ 已加载主题: ${H}`)}try{let O=M1.loadFromStandardLocations();if($.debug&&O>0)console.log(`✓ 已加载 ${O} 个 subagents: ${M1.getAllNames().join(", ")}`)}catch(O){if($.debug)console.warn("⚠️ Subagents 加载失败:",Y7(O))}try{if(J0.getInstance().loadConfig(U.hooks||{}),$.debug&&U.hooks?.enabled)console.log("✓ Hooks 系统已启用")}catch(O){if($.debug)console.warn("⚠️ Hooks 初始化失败:",Y7(O))}bY(async()=>{i1.getInstance().killAll(),await C1.getInstance().disconnectAll(),J0.getInstance().cleanup()}),Z(!0)}),G=sX(async()=>{if($.versionCheckPromise){let W=await $.versionCheckPromise;if(W){Q(W),q(!0);return}}K()});if(MH(()=>{G()},[]),J&&X)return M4(V4,{children:M4(oX,{versionInfo:X,onComplete:()=>{q(!1),K()}},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(!Y)return null;return M4(V4,{children:M4(nX,{...$},void 0,!1,void 0,this)},void 0,!1,void 0,this)};var J7=QQ(process.argv),XQ=J7.indexOf("--debug");if(XQ!==-1){let $=J7[XQ+1],Y=$&&!$.startsWith("-")?$:!0;N0.setGlobalDebug(Y)}async function fH(){VY();let $=AY();if(await OY())return;if(J7.includes("--acp")){let{runAcpIntegration:Z}=await Promise.resolve().then(() => (ZQ(),YQ));await Z();return}let Y=CH(QQ(process.argv)).scriptName(L2.scriptName).usage(L2.usage).version(L2.version).locale(L2.locale).showHelpOnFail(L2.showHelpOnFail).demandCommand(0,"").recommendCommands().strict(L2.strict).parserConfiguration({"populate--":!0}).options(F7).middleware([S7,C7,f7]).command(e7).command(h7).command(RY).command(x7).completion("completion",!1).help("help","Show help").alias("help","h").alias("version","V").fail((Z,X,Q)=>{if(X)console.error("\uD83D\uDCA5 An error occurred:"),console.error(X.message),console.error(`
1600
+ `]},void 0,!0,void 0,this),S1(AH,{items:z,onSelect:B,indicatorComponent:VH,itemComponent:DH},void 0,!1,void 0,this),S1(M$,{marginTop:1,flexDirection:"column",children:[S1(k0,{dimColor:!0,children:["第 ",G+1,"/",_," 页 · 共 ",O.length," 个会话 · 显示"," ",w.start,"-",w.end]},void 0,!0,void 0,this),_>1&&S1(M$,{marginTop:1,children:[S1(k0,{color:G>0?"cyan":"gray",children:G>0?"◀ ← 上一页":" "},void 0,!1,void 0,this),S1(k0,{children:" "},void 0,!1,void 0,this),S1(k0,{color:G<_-1?"cyan":"gray",children:G<_-1?"下一页 → ▶":""},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{useMemoizedFn as IH}from"ahooks";import{Box as m0,Text as C,useInput as MH}from"ink";import kH from"ink-select-input";import{useState as qQ}from"react";z1();import{jsxDEV as P}from"react/jsx-dev-runtime";var GQ=x0.map(($)=>({label:$.label,value:$.id})),jH=({theme:$})=>{let{colors:Y}=$;return P(m0,{flexDirection:"column",paddingLeft:1,paddingTop:1,children:[P(C,{bold:!0,color:Y.text.primary,children:"代码预览"},void 0,!1,void 0,this),P(C,{children:" "},void 0,!1,void 0,this),P(C,{color:Y.syntax.comment,children:"# function"},void 0,!1,void 0,this),P(C,{children:[P(C,{color:Y.syntax.keyword,children:"def"},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.function,children:"fibonacci"},void 0,!1,void 0,this),P(C,{color:Y.text.primary,children:"("},void 0,!1,void 0,this),P(C,{color:Y.syntax.variable,children:"n"},void 0,!1,void 0,this),P(C,{color:Y.text.primary,children:"):"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(C,{children:[" ",P(C,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this),P(C,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.operator,children:"="},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.number,children:"0"},void 0,!1,void 0,this),P(C,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.number,children:"1"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(C,{children:[" ",P(C,{color:Y.syntax.keyword,children:"for"},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.variable,children:"_"},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.keyword,children:"in"},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.function,children:"range"},void 0,!1,void 0,this),P(C,{color:Y.text.primary,children:"("},void 0,!1,void 0,this),P(C,{color:Y.syntax.variable,children:"n"},void 0,!1,void 0,this),P(C,{color:Y.text.primary,children:"):"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(C,{children:[" ",P(C,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this),P(C,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.operator,children:"="},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this),P(C,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.operator,children:"+"},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(C,{children:[" ",P(C,{color:Y.syntax.keyword,children:"return"},void 0,!1,void 0,this)," ",P(C,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(C,{children:" "},void 0,!1,void 0,this),P(C,{color:Y.error,children:["- print(",P(C,{color:Y.syntax.string,children:'"Hello, "'},void 0,!1,void 0,this)," + name)"]},void 0,!0,void 0,this),P(C,{color:Y.success,children:["+ print(",P(C,{color:Y.syntax.string,children:['f"Hello, ',"{","name","}",'"']},void 0,!0,void 0,this),")"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},EH=({theme:$})=>{let{colors:Y}=$;return P(m0,{flexDirection:"column",paddingLeft:1,paddingTop:1,children:[P(C,{children:" "},void 0,!1,void 0,this),P(C,{bold:!0,color:Y.text.primary,children:"颜色配置"},void 0,!1,void 0,this),P(C,{children:" "},void 0,!1,void 0,this),P(C,{children:[P(C,{color:Y.text.muted,children:"Primary: "},void 0,!1,void 0,this),P(C,{color:Y.primary,children:Y.primary},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(C,{children:[P(C,{color:Y.text.muted,children:"Success: "},void 0,!1,void 0,this),P(C,{color:Y.success,children:Y.success},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(C,{children:[P(C,{color:Y.text.muted,children:"Error: "},void 0,!1,void 0,this),P(C,{color:Y.error,children:Y.error},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(C,{children:[P(C,{color:Y.text.muted,children:"Warning: "},void 0,!1,void 0,this),P(C,{color:Y.warning,children:Y.warning},void 0,!1,void 0,this)]},void 0,!0,void 0,this),P(C,{children:[P(C,{color:Y.text.muted,children:"Info: "},void 0,!1,void 0,this),P(C,{color:Y.info,children:Y.info},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},KQ=()=>{let $=O2(),Y=Z1.getCurrentThemeName(),Z=x0.findIndex((_)=>_.label===Y),X=Z>=0?x0[Z].theme:x0[0].theme,[Q,J]=qQ(X),[q,G]=qQ(!1),K=IH(async(_)=>{if(q)return;G(!0);try{Z1.setTheme(_.value),await H1().setTheme(_.value),$.closeModal()}catch(z){console.error("❌ 主题切换失败:",z instanceof Error?z.message:z)}finally{G(!1)}}),W=(_)=>{let z=x0.find((w)=>w.id===_.value);if(z)J(z.theme)},H=G0()==="theme-selector",O=T1(!1);MH((_,z)=>{if(z.ctrl&&_==="c"||z.meta&&_==="c"){O();return}if(z.escape&&!q)$.closeModal()},{isActive:H});let F=(_)=>{let{isSelected:z,label:w}=_,N=w===Y?"✓":" ";return P(C,{color:z?Q.colors.primary:Q.colors.text.primary,children:[N," ",w]},void 0,!0,void 0,this)};return P(m0,{flexDirection:"column",height:"100%",children:[P(m0,{paddingX:2,paddingY:1,borderStyle:"single",borderColor:Q.colors.border.light,children:P(C,{bold:!0,color:Q.colors.primary,children:"\uD83C\uDFA8 主题选择器"},void 0,!1,void 0,this)},void 0,!1,void 0,this),P(m0,{flexDirection:"row",flexGrow:1,children:[P(m0,{width:"40%",borderStyle:"single",borderColor:Q.colors.border.light,paddingX:1,children:P(m0,{flexDirection:"column",children:[P(m0,{paddingTop:1,paddingBottom:1,children:P(C,{bold:!0,color:Q.colors.text.primary,children:["可用主题 (",GQ.length,")"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),P(kH,{items:GQ,initialIndex:Z>=0?Z:0,onSelect:K,onHighlight:W,itemComponent:F},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),P(m0,{width:"60%",flexDirection:"column",borderStyle:"single",borderColor:Q.colors.border.light,children:[P(jH,{theme:Q},void 0,!1,void 0,this),P(EH,{theme:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),P(m0,{paddingX:2,paddingY:1,borderStyle:"single",borderColor:Q.colors.border.light,children:P(C,{color:Q.colors.text.muted,children:q?"正在保存...":"Enter: 选择主题 | Esc: 取消"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as k1,Fragment as yH}from"react/jsx-dev-runtime";var X0=l("UI"),WQ=({debug:$,...Y})=>{if($)X0.debug("[Debug] BladeInterface props:",{permissionMode:Y.permissionMode,yolo:Y.yolo,maxTurns:Y.maxTurns});let Z=E4(!1),X=E4(!1),Q=E4(!1),J=E4(null),q=gY(),G=mY(),K=t6(),W=cY(),U=uY(),H=O2(),O=H$(),F=nY(),_=O$(),z=f0(),{exit:w}=vH(),B=q==="ready",N=q==="needsSetup",b=q==="idle",{confirmationState:V,confirmationHandler:R,handleResponse:L}=nZ(),{executeCommand:A,handleAbort:k}=lZ(Y.systemPrompt,Y.appendSystemPrompt,R,Y.maxTurns),{getPreviousCommand:I,getNextCommand:T,addToHistory:E}=rZ(),v=sZ("",0),g=n1(async()=>{let r=_,U1;if(r==="default")U1="autoEdit";else if(r==="autoEdit")U1="plan";else U1="default";try{await H1().setPermissionMode(U1)}catch(N0){X0.error("❌ 权限模式切换失败:",N0 instanceof Error?N0.message:N0)}}),u=n1(async(r)=>{try{await H1().addModel({name:r.name,provider:r.provider,apiKey:r.apiKey,baseUrl:r.baseUrl,model:r.model}),H.setInitializationStatus("ready")}catch(U1){X0.error("❌ 初始化配置保存失败:",U1 instanceof Error?U1.message:U1),H.setInitializationStatus("ready")}}),D1=n1(()=>{if(K==="shortcuts")H.closeModal();else H.setActiveModal("shortcuts")}),{showSuggestions:J1,suggestions:x,selectedSuggestionIndex:j0}=qX(v,A,I,T,E,k,z,g,D1,K==="shortcuts");f2(()=>{if(v.value&&K==="shortcuts")H.closeModal()},[v.value,K,H]);let Q1=n1(async()=>{try{if(typeof Y.resume==="string"&&Y.resume!=="true"){let U1=await C0.loadSession(Y.resume),N0=U1.map((l0,j$)=>({id:`restored-${Date.now()}-${j$}`,role:l0.role,content:typeof l0.content==="string"?l0.content:JSON.stringify(l0.content),timestamp:Date.now()-(U1.length-j$)*1000}));O.restoreSession(Y.resume,N0);return}let r=await C0.listSessions();if(r.length===0)X0.error("没有找到历史会话"),process.exit(1);H.showSessionSelector(r)}catch(r){X0.error("[BladeInterface] 加载会话失败:",r),process.exit(1)}});f2(()=>{if(Z.current)return;if(!Y.resume)return;Z.current=!0,Q1()},[Y.resume,Q1]);let b1=n1(async(r)=>{let U1=V.details?.type;if(U1==="enterPlanMode"&&r.approved)try{await H1().setPermissionMode("plan"),X0.debug("[BladeInterface] Entered Plan mode")}catch(N0){X0.error("[BladeInterface] Failed to enter Plan mode:",N0)}if(U1==="exitPlanMode"&&r.approved)X0.debug("[BladeInterface] ExitPlanMode approved, Store auto-synced");L(r)}),u0=n1(()=>{O.addAssistantMessage("❌ 设置已取消"),O.addAssistantMessage("Blade 需要 API 配置才能正常工作。"),O.addAssistantMessage("您可以稍后运行 Blade 重新进入设置向导。"),process.exit(0)}),i=n1(()=>{H.closeModal()}),G1=n1(async(r)=>{try{let U1=await C0.loadSession(r),N0=U1.map((l0,j$)=>({id:`restored-${Date.now()}-${j$}`,role:l0.role,content:typeof l0.content==="string"?l0.content:JSON.stringify(l0.content),timestamp:Date.now()-(U1.length-j$)*1000}));O.restoreSession(r,N0),H.closeModal()}catch(U1){X0.error("[BladeInterface] Failed to restore session:",U1),H.closeModal()}}),$1=n1(()=>{if(Y.resume)w();else H.closeModal()}),o1=n1((r)=>{H.showModelEditWizard(r)}),B2=n1((r)=>{O.addAssistantMessage(`✅ 已添加模型配置: ${r.name},并已切换到该模型`),i()}),y1=n1((r)=>{O.addAssistantMessage(`✅ 已更新模型配置: ${r.name}`),i()});f2(()=>{if(N){F.setFocus("model-config-wizard");return}if(V.isVisible)F.setFocus("confirmation-prompt");else if(K==="sessionSelector")F.setFocus("session-selector");else if(K==="themeSelector")F.setFocus("theme-selector");else if(K==="modelSelector")F.setFocus("model-selector");else if(K==="modelAddWizard"||K==="modelEditWizard")F.setFocus("model-config-wizard");else if(K==="permissionsManager")F.setFocus("permissions-manager");else if(K==="agentsManager")F.setFocus("agents-manager");else if(K==="agentCreationWizard")F.setFocus("agent-creation-wizard");else if(K==="shortcuts")F.setFocus("main-input");else F.setFocus("main-input")},[N,V.isVisible,K,F.setFocus]),f2(()=>{if(!B||Q.current)return;if(u7().length>0){Q.current=!0;return}Q.current=!0,O.addAssistantMessage("请输入您的问题,我将为您提供帮助。")},[B]),f2(()=>{if(!G)return;if(J.current===G)return;if(J.current=G,q==="error")O.addAssistantMessage(`❌ 初始化失败: ${G}`);else O.addAssistantMessage(`❌ ${G}`),O.addAssistantMessage("请重新尝试设置,或检查文件权限")},[G,q,O.addAssistantMessage]);let c0=n1(async(r)=>{try{await A({displayText:r,text:r,images:[],parts:[{type:"text",text:r}]})}catch(U1){let N0=U1 instanceof Error?U1.message:"无法发送初始消息";O.addAssistantMessage(`❌ 初始消息发送失败:${N0}`)}});f2(()=>{let r=Y.initialMessage?.trim();if(!r||X.current||!B||N)return;X.current=!0,E(r),c0(r)},[Y.initialMessage,B,N,A,E]);let _0=n1(async(r)=>{try{await H1().setPermissionMode(r)}catch(U1){X0.error("❌ 权限模式初始化失败:",U1 instanceof Error?U1.message:U1)}});if(f2(()=>{let r=Y.permissionMode;if($)X0.debug("[Debug] permissionMode from CLI:",r),X0.debug("[Debug] current permissionMode:",_);if(!r||r===_)return;_0(r)},[Y.permissionMode,_]),b)return null;if(N)return k1(K7,{mode:"setup",onComplete:u,onCancel:u0},void 0,!1,void 0,this);if($)X0.debug("[Debug] 渲染主界面,条件检查:",{confirmationVisible:V.isVisible,activeModal:K});let k$=K==="modelSelector",E0=U,w2=K==="modelAddWizard"?"add":K==="modelEditWizard"&&E0?"edit":null,LQ=k$||Boolean(w2),AQ=K==="agentsManager",bQ=K==="agentCreationWizard",RQ=E0?{name:E0.name,provider:E0.provider,baseUrl:E0.baseUrl,apiKey:E0.apiKey,model:E0.model}:void 0,VQ=V.isVisible&&V.details?k1(DX,{details:V.details,onResponse:b1},void 0,!1,void 0,this):K==="themeSelector"?k1(KQ,{},void 0,!1,void 0,this):K==="permissionsManager"?k1(XQ,{onClose:i},void 0,!1,void 0,this):K==="sessionSelector"?k1(JQ,{sessions:W,onSelect:G1,onCancel:$1},void 0,!1,void 0,this):null;return k1(z6,{flexDirection:"column",width:"100%",overflow:"hidden",children:VQ??k1(yH,{children:[k1(oX,{},void 0,!1,void 0,this),k1(dX,{},void 0,!1,void 0,this),k1(CX,{input:v.value,cursorPosition:v.cursorPosition,onChange:v.setValue,onChangeCursorPosition:v.setCursorPosition,onAddPasteMapping:v.addPasteMapping,onAddImagePasteMapping:v.addImagePasteMapping},void 0,!1,void 0,this),k$&&k1(z6,{marginTop:1,paddingX:2,children:k1(tX,{onClose:i,onEdit:o1},void 0,!1,void 0,this)},void 0,!1,void 0,this),w2&&k1(z6,{marginTop:1,paddingX:2,children:k1(K7,{mode:w2,modelId:E0?.id,initialConfig:w2==="edit"?RQ:void 0,onComplete:w2==="edit"?y1:B2,onCancel:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),AQ&&k1(z6,{marginTop:1,paddingX:2,children:k1(UX,{onComplete:i,onCancel:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),bQ&&k1(z6,{marginTop:1,paddingX:2,children:k1(X6,{onComplete:i,onCancel:i},void 0,!1,void 0,this)},void 0,!1,void 0,this),k1(zX,{suggestions:x,selectedIndex:j0,visible:J1&&!LQ},void 0,!1,void 0,this),k1(FX,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)};import{Box as PH,Text as N2}from"ink";import TH from"react";import{jsxDEV as e0}from"react/jsx-dev-runtime";class v4 extends TH.Component{constructor($){super($);this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError($){return{hasError:!0,error:$,errorInfo:null}}componentDidCatch($,Y){this.setState({error:$,errorInfo:Y}),console.error("未捕获的错误:",$,Y)}render(){if(this.state.hasError)return e0(PH,{flexDirection:"column",padding:1,borderStyle:"round",borderColor:"red",children:[e0(N2,{color:"red",children:"\uD83D\uDCA5 应用发生错误"},void 0,!1,void 0,this),e0(N2,{children:" "},void 0,!1,void 0,this),e0(N2,{color:"red",children:this.state.error?.message},void 0,!1,void 0,this),e0(N2,{children:" "},void 0,!1,void 0,this),e0(N2,{color:"gray",children:"错误详情:"},void 0,!1,void 0,this),e0(N2,{color:"gray",children:this.state.error?.stack},void 0,!1,void 0,this),e0(N2,{children:" "},void 0,!1,void 0,this),e0(N2,{color:"yellow",children:"请重启应用或联系开发者"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return this.props.children}}import{Box as h2,Text as $2,useInput as SH}from"ink";import{useState as U7}from"react";import{jsxDEV as d1}from"react/jsx-dev-runtime";var y4=[{key:"update",label:"Update now",description:`runs \`${I9()}\``},{key:"skip",label:"Skip",description:""},{key:"skip_until_next",label:"Skip until next version",description:""}],UQ=({versionInfo:$,onComplete:Y})=>{let[Z,X]=U7(0),[Q,J]=U7(!1),[q,G]=U7(null);SH((W,U)=>{if(U.ctrl&&W==="c"){j2().shutdown("SIGINT",0);return}if(Q||q)return;if(U.upArrow||W==="k")X((H)=>H>0?H-1:y4.length-1);else if(U.downArrow||W==="j")X((H)=>H<y4.length-1?H+1:0);else if(U.return)K(y4[Z].key);else if(W==="1")K("update");else if(W==="2")K("skip");else if(W==="3")K("skip_until_next")});let K=async(W)=>{switch(W){case"update":{J(!0);let U=await EY();G(U.message),setTimeout(()=>{j2().shutdown("SIGINT",0)},1500);break}case"skip":Y();break;case"skip_until_next":if($.latestVersion)await jY($.latestVersion);Y();break}};if(q)return d1(h2,{flexDirection:"column",marginY:1,children:d1($2,{children:q},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(Q)return d1(h2,{flexDirection:"column",marginY:1,children:d1($2,{color:"cyan",children:"Updating..."},void 0,!1,void 0,this)},void 0,!1,void 0,this);return d1(h2,{flexDirection:"column",marginY:1,children:[d1($2,{color:"yellow",bold:!0,children:["✨ Update available! ",d1($2,{color:"gray",children:[$.currentVersion," ","→"," ",$.latestVersion]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),d1(h2,{marginTop:1,children:d1($2,{color:"gray",children:["Release notes:"," ",d1($2,{color:"cyan",underline:!0,children:$.releaseNotesUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),d1(h2,{flexDirection:"column",marginTop:1,children:y4.map((W,U)=>{let H=U===Z,O=H?"› ":" ",F=`${U+1}. `;return d1(h2,{children:d1($2,{color:H?"cyan":void 0,children:[O,F,W.label,W.description&&d1($2,{color:"gray",children:[" (",W.description,")"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},W.key,!1,void 0,this)})},void 0,!1,void 0,this),d1(h2,{marginTop:1,children:d1($2,{color:"gray",children:"Press enter to continue"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};function H7($){return($ instanceof Error?$.message:String($)).replace(/sk-[a-zA-Z0-9]{32,}/g,"sk-***").replace(/apiKey['":\s]+[a-zA-Z0-9-_]+/gi,"apiKey: ***").replace(/API_KEY['":\s=]+[a-zA-Z0-9-_]+/gi,"API_KEY=***")}import{jsxDEV as P4}from"react/jsx-dev-runtime";function fH($){if(s().config.actions.setConfig($),!$.models||$.models.length===0){if($.debug)console.log("[Debug] 未检测到模型配置,进入设置向导");w0().setInitializationStatus("needsSetup");return}if($.debug)console.log("[Debug] 模型配置检查通过,准备就绪");w0().setInitializationStatus("ready")}var OQ=($)=>{let[Y,Z]=O7(!1),[X,Q]=O7(null),[J,q]=O7(!1),G=HQ(()=>{let W=s().config.config??p2,U=C4(W,$);if(fH(U),U.debug)console.error("[Debug] 运行时配置:",U);let H=U.theme;if(H&&Z1.hasTheme(H)){if(Z1.setTheme(H),$.debug)console.log(`✓ 已加载主题: ${H}`)}try{let O=M1.loadFromStandardLocations();if($.debug&&O>0)console.log(`✓ 已加载 ${O} 个 subagents: ${M1.getAllNames().join(", ")}`)}catch(O){if($.debug)console.warn("⚠️ Subagents 加载失败:",H7(O))}try{if(q0.getInstance().loadConfig(U.hooks||{}),$.debug&&U.hooks?.enabled)console.log("✓ Hooks 系统已启用")}catch(O){if($.debug)console.warn("⚠️ Hooks 初始化失败:",H7(O))}PY(async()=>{r1.getInstance().killAll(),await f1.getInstance().disconnectAll(),q0.getInstance().cleanup()}),Z(!0)}),K=HQ(async()=>{if($.versionCheckPromise){let W=await $.versionCheckPromise;if(W){Q(W),q(!0);return}}G()});if(CH(()=>{K()},[]),J&&X)return P4(v4,{children:P4(UQ,{versionInfo:X,onComplete:()=>{q(!1),G()}},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(!Y)return null;return P4(v4,{children:P4(WQ,{...$},void 0,!1,void 0,this)},void 0,!1,void 0,this)};var _7=wQ(process.argv),BQ=_7.indexOf("--debug");if(BQ!==-1){let $=_7[BQ+1],Y=$&&!$.startsWith("-")?$:!0;B0.setGlobalDebug(Y)}async function iH(){TY();let $=vY();if(await RY())return;if(_7.includes("--acp")){let{runAcpIntegration:Z}=await Promise.resolve().then(() => (NQ(),_Q));await Z();return}let Y=lH(wQ(process.argv)).scriptName(L2.scriptName).usage(L2.usage).version(L2.version).locale(L2.locale).showHelpOnFail(L2.showHelpOnFail).demandCommand(0,"").recommendCommands().strict(L2.strict).parserConfiguration({"populate--":!0}).options(D7).middleware([c7,l7,i7]).command(W3).command(r7).command(yY).command(a7).completion("completion",!1).help("help","Show help").alias("help","h").alias("version","V").fail((Z,X,Q)=>{if(X)console.error("\uD83D\uDCA5 An error occurred:"),console.error(X.message),console.error(`
1548
1601
  Stack trace:`),console.error(X.stack),process.exit(1);if(Z)console.error("❌ Invalid arguments:"),console.error(Z),console.error(`
1549
- \uD83D\uDCA1 Did you mean:`),Q.showHelp(),process.exit(1)}).command("$0",!1,()=>{},async(Z)=>{let X=Z._.slice(1),Q=X.length>0?X.join(" "):void 0,J={...Z,initialMessage:Q,debug:Z.debug,print:Boolean(Z.print),versionCheckPromise:$};delete J._,delete J.$0,delete J.message,TH(SH.createElement(tX,J),{patchConsole:!0,exitOnCtrlC:!1})});try{await Y.parse()}catch(Z){console.error("❌ Parse error:",Z),process.exit(1)}}if(S1.main==S1.module)fH().catch(console.error);export{fH as main};
1602
+ \uD83D\uDCA1 Did you mean:`),Q.showHelp(),process.exit(1)}).command("$0",!1,()=>{},async(Z)=>{let X=Z._.slice(1),Q=X.length>0?X.join(" "):void 0,J={...Z,initialMessage:Q,debug:Z.debug,print:Boolean(Z.print),versionCheckPromise:$};delete J._,delete J.$0,delete J.message,uH(cH.createElement(OQ,J),{patchConsole:!0,exitOnCtrlC:!1,alternateBuffer:!0})});try{await Y.parse()}catch(Z){console.error("❌ Parse error:",Z),process.exit(1)}}if(C1.main==C1.module)iH().catch(console.error);export{iH as main};